This commit was generated by cvs2svn to compensate for changes in r2,

which included commits to RCS files with non-trunk default branches.


git-svn-id: svn://svn.cc65.org/cc65/trunk@3 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2000-05-28 13:40:48 +00:00
parent 579491e8a4
commit 53dd513176
847 changed files with 91345 additions and 0 deletions

1
src/.cvsignore Normal file
View File

@@ -0,0 +1 @@
*.obj

3
src/ar65/.cvsignore Normal file
View File

@@ -0,0 +1,3 @@
.depend
ar65

83
src/ar65/add.c Normal file
View File

@@ -0,0 +1,83 @@
/*****************************************************************************/
/* */
/* add.c */
/* */
/* Object file adding for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include "error.h"
#include "objfile.h"
#include "library.h"
#include "add.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void AddObjFiles (int argc, char* argv [])
/* Add object files to a library */
{
int I;
/* Check the argument count */
if (argc <= 0) {
Error ("No library name given");
}
if (argc <= 1) {
Error ("No object files to add");
}
/* Open the library, read the index */
LibOpen (argv [0], 0, 1);
/* Add the object files */
I = 1;
while (I < argc) {
ObjAdd (argv [I]);
++I;
}
/* Create a new library file and close the old one */
LibClose ();
/* Successful end */
exit (EXIT_SUCCESS);
}

58
src/ar65/add.h Normal file
View File

@@ -0,0 +1,58 @@
/*****************************************************************************/
/* */
/* add.h */
/* */
/* Object file adding for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ADD_H
#define ADD_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void AddObjFiles (int argc, char* argv []);
/* Add object files to a library */
/* End of add.h */
#endif

84
src/ar65/del.c Normal file
View File

@@ -0,0 +1,84 @@
/*****************************************************************************/
/* */
/* del.h */
/* */
/* Object file deleting for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include "error.h"
#include "objdata.h"
#include "library.h"
#include "del.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void DelObjFiles (int argc, char* argv [])
/* Delete modules from a library */
{
int I;
/* Check the argument count */
if (argc <= 0) {
Error ("No library name given");
}
if (argc <= 1) {
Error ("No modules to delete");
}
/* Open the library, read the index */
LibOpen (argv [0], 1, 1);
/* Delete the modules */
I = 1;
while (I < argc) {
/* Delete the module from the list */
DelObjData (argv [I]);
++I;
}
/* Create a new library file and close the old one */
LibClose ();
/* Successful end */
exit (EXIT_SUCCESS);
}

58
src/ar65/del.h Normal file
View File

@@ -0,0 +1,58 @@
/*****************************************************************************/
/* */
/* del.h */
/* */
/* Object file deleting for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef DEL_H
#define DEL_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void DelObjFiles (int argc, char* argv []);
/* Delete modules from a library */
/* End of del.h */
#endif

106
src/ar65/error.c Normal file
View File

@@ -0,0 +1,106 @@
/*****************************************************************************/
/* */
/* global.c */
/* */
/* Error handling for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "error.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Messages for internal compiler errors */
const char _MsgCheckFailed [] =
"Check failed: `%s' (= %d), file `%s', line %u\n";
const char _MsgPrecondition [] =
"Precondition violated: `%s' (= %d), file `%s', line %u\n";
const char _MsgFail [] =
"%s, file `%s', line %u\n";
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Warning (const char* Format, ...)
/* Print a warning message */
{
va_list ap;
va_start (ap, Format);
fprintf (stderr, "Warning: ");
vfprintf (stderr, Format, ap);
putc ('\n', stderr);
va_end (ap);
}
void Error (const char* Format, ...)
/* Print an error message and die */
{
va_list ap;
va_start (ap, Format);
fprintf (stderr, "Error: ");
vfprintf (stderr, Format, ap);
putc ('\n', stderr);
va_end (ap);
exit (EXIT_FAILURE);
}
void Internal (const char* Format, ...)
/* Print an internal error message and die */
{
va_list ap;
va_start (ap, Format);
fprintf (stderr, "Internal error: ");
vfprintf (stderr, Format, ap);
putc ('\n', stderr);
va_end (ap);
exit (EXIT_FAILURE);
}

87
src/ar65/error.h Normal file
View File

@@ -0,0 +1,87 @@
/*****************************************************************************/
/* */
/* global.h */
/* */
/* Error handling for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ERROR_H
#define ERROR_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Messages for internal compiler errors */
extern const char _MsgCheckFailed [];
extern const char _MsgPrecondition [];
extern const char _MsgFail [];
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Warning (const char* Format, ...);
/* Print a warning message */
void Error (const char* Format, ...);
/* Print an error message and die */
void Internal (const char* Format, ...);
/* Print an internal error message and die */
#define CHECK(c) \
if (!(c)) \
Internal (_MsgCheckFailed, #c, c, __FILE__, __LINE__)
#define PRECONDITION(c) \
if (!(c)) \
Internal (_MsgPrecondition, #c, c, __FILE__, __LINE__)
#define FAIL(s) \
Internal (_MsgFail, s, __FILE__, __LINE__)
/* End of error.h */
#endif

149
src/ar65/exports.c Normal file
View File

@@ -0,0 +1,149 @@
/*****************************************************************************/
/* */
/* exports.c */
/* */
/* Duplicate export checking for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include "../common/hashstr.h"
#include "mem.h"
#include "error.h"
#include "objdata.h"
#include "exports.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* A hash table entry */
typedef struct HashEntry_ HashEntry;
struct HashEntry_ {
HashEntry* Next; /* Next in list */
unsigned Module; /* Module index */
char Name [1]; /* Name of identifier */
};
/* Hash table */
#define HASHTAB_SIZE 4783
static HashEntry* HashTab [HASHTAB_SIZE];
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static HashEntry* NewHashEntry (const char* Name, unsigned Module)
/* Create and return a new hash entry */
{
/* Get the length of the name */
unsigned Len = strlen (Name);
/* Get memory for the struct */
HashEntry* H = Xmalloc (sizeof (HashEntry) + Len);
/* Initialize the fields and return it */
H->Next = 0;
H->Module = Module;
memcpy (H->Name, Name, Len);
H->Name [Len] = '\0';
return H;
}
void ExpInsert (const char* Name, unsigned Module)
/* Insert an exported identifier and check if it's already in the list */
{
HashEntry* L;
/* Create a hash value for the given name */
unsigned HashVal = HashStr (Name) % HASHTAB_SIZE;
/* Create a new hash entry */
HashEntry* H = NewHashEntry (Name, Module);
/* Search through the list in that slot and print matching duplicates */
if (HashTab [HashVal] == 0) {
/* The slot is empty */
HashTab [HashVal] = H;
return;
}
L = HashTab [HashVal];
while (1) {
if (strcmp (L->Name, Name) == 0) {
/* Duplicate entry */
Warning ("External symbol `%s' in module `%s' is duplicated in "
"module `%s'",
Name, GetObjName (L->Module), GetObjName (Module));
}
if (L->Next == 0) {
break;
} else {
L = L->Next;
}
}
L->Next = H;
}
int ExpFind (const char* Name)
/* Check for an identifier in the list. Return -1 if not found, otherwise
* return the number of the module, that exports the identifer.
*/
{
/* Get a pointer to the list with the symbols hash value */
HashEntry* L = HashTab [HashStr (Name) % HASHTAB_SIZE];
while (L) {
/* Search through the list in that slot */
if (strcmp (L->Name, Name) == 0) {
/* Entry found */
return L->Module;
}
L = L->Next;
}
/* Not found */
return -1;
}

62
src/ar65/exports.h Normal file
View File

@@ -0,0 +1,62 @@
/*****************************************************************************/
/* */
/* exports.h */
/* */
/* Duplicate export checking for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef EXPORTS_H
#define EXPORTS_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ExpInsert (const char* Name, unsigned Module);
/* Insert an exported identifier and check if it's already in the list */
int ExpFind (const char* Name);
/* Check for an identifier in the list. Return -1 if not found, otherwise
* return the number of the module, that exports the identifer.
*/
/* End of exports.h */
#endif

83
src/ar65/extract.c Normal file
View File

@@ -0,0 +1,83 @@
/*****************************************************************************/
/* */
/* extract.c */
/* */
/* Object file extraction for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include "mem.h"
#include "error.h"
#include "objfile.h"
#include "library.h"
#include "extract.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ExtractObjFiles (int argc, char* argv [])
/* Extract object files from a library */
{
int I;
/* Check the argument count */
if (argc <= 0) {
Error ("No library name given");
}
if (argc <= 1) {
Error ("No object files to add");
}
/* Open the library, read the index */
LibOpen (argv [0], 1, 0);
/* Extract the object files */
I = 1;
while (I < argc) {
ObjExtract (argv [I]);
++I;
}
/* Create a new library file and close the old one */
LibClose ();
/* Successful end */
exit (EXIT_SUCCESS);
}

58
src/ar65/extract.h Normal file
View File

@@ -0,0 +1,58 @@
/*****************************************************************************/
/* */
/* extract.h */
/* */
/* Object file extraction for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef EXTRACT_H
#define EXTRACT_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ExtractObjFiles (int argc, char* argv []);
/* Extract object files from a library */
/* End of extract.h */
#endif

210
src/ar65/fileio.c Normal file
View File

@@ -0,0 +1,210 @@
/*****************************************************************************/
/* */
/* fileio.c */
/* */
/* File I/O for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include "error.h"
#include "mem.h"
#include "fileio.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Write8 (FILE* F, unsigned char Val)
/* Write an 8 bit value to the file */
{
if (putc (Val, F) == EOF) {
Error ("Write error (disk full?)");
}
}
void Write16 (FILE* F, unsigned Val)
/* Write a 16 bit value to the file */
{
Write8 (F, (unsigned char) Val);
Write8 (F, (unsigned char) (Val >> 8));
}
void Write32 (FILE* F, unsigned long Val)
/* Write a 32 bit value to the file */
{
Write8 (F, (unsigned char) Val);
Write8 (F, (unsigned char) (Val >> 8));
Write8 (F, (unsigned char) (Val >> 16));
Write8 (F, (unsigned char) (Val >> 24));
}
void WriteStr (FILE* F, const char* S)
/* Write a string to the file */
{
unsigned Len = strlen (S);
if (Len > 255) {
Internal ("String too long");
}
Write8 (F, (unsigned char) Len);
WriteData (F, S, Len);
}
void WriteData (FILE* F, const void* Data, unsigned Size)
/* Write data to the file */
{
if (fwrite (Data, 1, Size, F) != Size) {
Error ("Write error (disk full?)");
}
}
unsigned Read8 (FILE* F)
/* Read an 8 bit value from the file */
{
int C = getc (F);
if (C == EOF) {
Error ("Read error (file corrupt?)");
}
return C;
}
unsigned Read16 (FILE* F)
/* Read a 16 bit value from the file */
{
unsigned Lo = Read8 (F);
unsigned Hi = Read8 (F);
return (Hi << 8) | Lo;
}
unsigned long Read32 (FILE* F)
/* Read a 32 bit value from the file */
{
unsigned long Lo = Read16 (F);
unsigned long Hi = Read16 (F);
return (Hi << 16) | Lo;
}
char* ReadStr (FILE* F)
/* Read a string from the file (the memory will be malloc'ed) */
{
/* Read the length byte */
unsigned Len = Read8 (F);
/* Allocate memory and read the string itself */
char* S = Xmalloc (Len + 1);
ReadData (F, S, Len);
/* Terminate the string and return it */
S [Len] = '\0';
return S;
}
void* ReadData (FILE* F, void* Data, unsigned Size)
/* Read data from the file */
{
if (fread (Data, 1, Size, F) != Size) {
Error ("Read error (file corrupt?)");
}
return Data;
}

88
src/ar65/fileio.h Normal file
View File

@@ -0,0 +1,88 @@
/*****************************************************************************/
/* */
/* fileio.h */
/* */
/* File I/O for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef FILEIO_H
#define FILEIO_H
#include <stdio.h>
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Write8 (FILE* F, unsigned char Val);
/* Write an 8 bit value to the file */
void Write16 (FILE* F, unsigned Val);
/* Write a 16 bit value to the file */
void Write32 (FILE* F, unsigned long Val);
/* Write a 32 bit value to the file */
void WriteStr (FILE* F, const char* S);
/* Write a string to the file */
void WriteData (FILE* F, const void* Data, unsigned Size);
/* Write data to the file */
unsigned Read8 (FILE* F);
/* Read an 8 bit value from the file */
unsigned Read16 (FILE* F);
/* Read a 16 bit value from the file */
unsigned long Read32 (FILE* F);
/* Read a 32 bit value from the file */
char* ReadStr (FILE* F);
/* Read a string from the file (the memory will be malloc'ed) */
void* ReadData (FILE* F, void* Data, unsigned Size);
/* Read data from the file */
/* End of fileio.h */
#endif

51
src/ar65/global.c Normal file
View File

@@ -0,0 +1,51 @@
/*****************************************************************************/
/* */
/* global.c */
/* */
/* Global variables for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "global.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
const char* ProgName = "ar65"; /* Program name */
int Verbose = 0; /* Verbose operation flag */

58
src/ar65/global.h Normal file
View File

@@ -0,0 +1,58 @@
/*****************************************************************************/
/* */
/* global.h */
/* */
/* Global variables for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef GLOBAL_H
#define GLOBAL_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
extern const char* ProgName; /* Program name */
extern int Verbose; /* Verbose operation flag */
/* End of global.h */
#endif

470
src/ar65/library.c Normal file
View File

@@ -0,0 +1,470 @@
/*****************************************************************************/
/* */
/* library.c */
/* */
/* Library data structures and helpers for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "../common/libdefs.h"
#include "../common/symdefs.h"
#include "../common/exprdefs.h"
#include "../common/filepos.h"
#include "../common/bitops.h"
#include "mem.h"
#include "error.h"
#include "global.h"
#include "fileio.h"
#include "objdata.h"
#include "exports.h"
#include "library.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* File descriptor for the library file */
FILE* NewLib = 0;
static FILE* Lib = 0;
static const char* LibName = 0;
/* The library header */
static LibHeader Header = {
LIB_MAGIC,
LIB_VERSION
};
/*****************************************************************************/
/* Writing file data structures */
/*****************************************************************************/
static void ReadHeader (void)
/* Read the header of a library file */
{
/* Seek to position zero */
fseek (Lib, 0, SEEK_SET);
/* Read the header fields, checking magic and version */
Header.Magic = Read32 (Lib);
if (Header.Magic != LIB_MAGIC) {
Error ("`%s' is not a valid library file", LibName);
}
Header.Version = Read16 (Lib);
if (Header.Version != LIB_VERSION) {
Error ("Wrong data version in `%s'", LibName);
}
Header.Flags = Read16 (Lib);
Header.IndexOffs = Read32 (Lib);
}
static void ReadIndexEntry (void)
/* Read one entry in the index */
{
/* Create a new entry and insert it into the list */
ObjData* O = NewObjData ();
/* Module name/flags/MTime/Start/Size */
O->Name = ReadStr (Lib);
O->Flags = Read16 (Lib);
O->MTime = Read32 (Lib);
O->Start = Read32 (Lib);
O->Size = Read32 (Lib);
/* Exports */
O->ExportSize = Read16 (Lib);
O->Exports = Xmalloc (O->ExportSize);
ReadData (Lib, O->Exports, O->ExportSize);
/* Imports */
O->ImportSize = Read16 (Lib);
O->Imports = Xmalloc (O->ImportSize);
ReadData (Lib, O->Imports, O->ImportSize);
}
static void ReadIndex (void)
/* Read the index of a library file */
{
unsigned Count;
/* Seek to the start of the index */
fseek (Lib, Header.IndexOffs, SEEK_SET);
/* Read the object file count and calculate the cross ref size */
Count = Read16 (Lib);
/* Read all entries in the index */
while (Count--) {
ReadIndexEntry ();
}
}
/*****************************************************************************/
/* Writing file data structures */
/*****************************************************************************/
static void WriteHeader (void)
/* Write the header to the library file */
{
/* Seek to position zero */
fseek (NewLib, 0, SEEK_SET);
/* Write the header fields */
Write32 (NewLib, Header.Magic);
Write16 (NewLib, Header.Version);
Write16 (NewLib, Header.Flags);
Write32 (NewLib, Header.IndexOffs);
}
static void WriteIndexEntry (ObjData* O)
/* Write one index entry */
{
/* Module name/flags/MTime/start/size */
WriteStr (NewLib, O->Name);
Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA);
Write32 (NewLib, O->MTime);
Write32 (NewLib, O->Start);
Write32 (NewLib, O->Size);
/* Exports */
Write16 (NewLib, O->ExportSize);
WriteData (NewLib, O->Exports, O->ExportSize);
/* Imports */
Write16 (NewLib, O->ImportSize);
WriteData (NewLib, O->Imports, O->ImportSize);
}
static void WriteIndex (void)
/* Write the index of a library file */
{
ObjData* O;
/* Sync I/O in case the last operation was a read */
fseek (NewLib, 0, SEEK_CUR);
/* Remember the current offset in the header */
Header.IndexOffs = ftell (NewLib);
/* Write the object file count */
Write16 (NewLib, ObjCount);
/* Write the object files */
O = ObjRoot;
while (O) {
WriteIndexEntry (O);
O = O->Next;
}
}
/*****************************************************************************/
/* High level stuff */
/*****************************************************************************/
void LibOpen (const char* Name, int MustExist, int NeedTemp)
/* Open an existing library and a temporary copy. If MustExist is true, the
* old library is expected to exist. If NeedTemp is true, a temporary library
* is created.
*/
{
/* Remember the name */
LibName = StrDup (Name);
/* Open the existing library for reading */
Lib = fopen (Name, "rb");
if (Lib == 0) {
/* File does not exist */
if (MustExist) {
Error ("Library `%s' does not exist", Name);
} else {
Warning ("Library `%s' not found - will be created", Name);
}
} else {
/* We have an existing file: Read the header */
ReadHeader ();
/* Now read the existing index */
ReadIndex ();
}
if (NeedTemp) {
/* Create the temporary library */
NewLib = tmpfile ();
if (NewLib == 0) {
Error ("Cannot create temporary file: %s", strerror (errno));
}
/* Write a dummy header to the temp file */
WriteHeader ();
}
}
unsigned long LibCopyTo (FILE* F, unsigned long Bytes)
/* Copy data from F to the temp library file, return the start position in
* the temporary library file.
*/
{
unsigned char Buf [4096];
/* Remember the position */
unsigned long Pos = ftell (NewLib);
/* Copy loop */
while (Bytes) {
unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
ReadData (F, Buf, Count);
WriteData (NewLib, Buf, Count);
Bytes -= Count;
}
/* Return the start position */
return Pos;
}
void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F)
/* Copy data from the library file into another file */
{
unsigned char Buf [4096];
/* Seek to the correct position */
fseek (Lib, Pos, SEEK_SET);
/* Copy loop */
while (Bytes) {
unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
ReadData (Lib, Buf, Count);
WriteData (F, Buf, Count);
Bytes -= Count;
}
}
static void SkipExpr (unsigned char** Buf)
/* Skip an expression in Buf */
{
/* Get the operation and skip it */
unsigned char Op = **Buf;
++(*Buf);
/* Filter leaf nodes */
switch (Op) {
case EXPR_NULL:
return;
case EXPR_LITERAL:
/* 32 bit literal value */
*Buf += 4;
return;
case EXPR_SYMBOL:
/* 16 bit symbol index */
*Buf += 2;
return;
case EXPR_SEGMENT:
/* 8 bit segment number */
*Buf += 1;
return;
}
/* What's left are unary and binary nodes */
SkipExpr (Buf); /* Skip left */
SkipExpr (Buf); /* Skip right */
}
static void LibCheckExports (ObjData* O)
/* Insert all exports from the given object file into the global list
* checking for duplicates.
*/
{
char Name [256];
/* Get a pointer to the buffer */
unsigned char* Exports = O->Exports;
/* First two bytes are export count */
unsigned Lo = *Exports++;
unsigned Hi = *Exports++;
unsigned Count = (Hi << 8) + Lo;
/* Read the exports */
if (Verbose > 1) {
printf ("Module `%s' (%u exports):\n", O->Name, Count);
}
while (Count--) {
unsigned char Len;
/* Get the export tag */
unsigned char Tag = *Exports++;
/* Next thing is name of symbol */
Len = *Exports++;
memcpy (Name, Exports, Len);
Name [Len] = '\0';
Exports += Len;
/* Skip value of symbol */
if (Tag & EXP_EXPR) {
/* Expression tree */
SkipExpr (&Exports);
} else {
/* Constant 32 bit value */
Exports += 4;
}
/* Skip the position */
Exports += POS_SIZE;
/* Insert the name into the hash table */
if (Verbose > 1) {
printf (" %s\n", Name);
}
ExpInsert (Name, O->Index);
}
}
void LibClose (void)
/* Write remaining data, close both files and copy the temp file to the old
* filename
*/
{
/* Do we have a temporary library? */
if (NewLib) {
unsigned I;
unsigned char Buf [4096];
size_t Count;
/* Index the object files and make an array containing the objects */
MakeObjPool ();
/* Walk through the object file list, inserting exports into the
* export list checking for duplicates. Copy any data that is still
* in the old library into the new one.
*/
for (I = 0; I < ObjCount; ++I) {
/* Get a pointer to the object */
ObjData* O = ObjPool [I];
/* Check exports, make global export table */
LibCheckExports (O);
/* Copy data if needed */
if ((O->Flags & OBJ_HAVEDATA) == 0) {
/* Data is still in the old library */
fseek (Lib, O->Start, SEEK_SET);
O->Start = ftell (NewLib);
LibCopyTo (Lib, O->Size);
O->Flags |= OBJ_HAVEDATA;
}
}
/* Write the index */
WriteIndex ();
/* Write the updated header */
WriteHeader ();
/* Close the file */
if (Lib && fclose (Lib) != 0) {
Error ("Error closing library: %s", strerror (errno));
}
/* Reopen the library and truncate it */
Lib = fopen (LibName, "wb");
if (Lib == 0) {
Error ("Cannot open library `%s' for writing: %s",
LibName, strerror (errno));
}
/* Copy the new library to the new one */
fseek (NewLib, 0, SEEK_SET);
while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) {
if (fwrite (Buf, 1, Count, Lib) != Count) {
Error ("Cannot write to `%s': %s", LibName, strerror (errno));
}
}
}
/* Close both files */
if (Lib && fclose (Lib) != 0) {
Error ("Problem closing `%s': %s", LibName, strerror (errno));
}
if (NewLib && fclose (NewLib) != 0) {
Error ("Problem closing temporary library file: %s", strerror (errno));
}
}

88
src/ar65/library.h Normal file
View File

@@ -0,0 +1,88 @@
/*****************************************************************************/
/* */
/* library.h */
/* */
/* Library data structures and helpers for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef LIBRARY_H
#define LIBRARY_H
#include <stdio.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* File descriptor for the new library file */
extern FILE* NewLib;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void LibOpen (const char* Name, int MustExist, int NeedTemp);
/* Open an existing library and a temporary copy. If MustExist is true, the
* old library is expected to exist. If NeedTemp is true, a temporary library
* is created.
*/
unsigned long LibCopyTo (FILE* F, unsigned long Bytes);
/* Copy data from F to the temp library file, return the start position in
* the temporary library file.
*/
void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F);
/* Copy data from the library file into another file */
void LibClose (void);
/* Write remaining data, close both files and copy the temp file to the old
* filename
*/
/* End of library.h */
#endif

83
src/ar65/list.c Normal file
View File

@@ -0,0 +1,83 @@
/*****************************************************************************/
/* */
/* list.c */
/* */
/* Module listing for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "objdata.h"
#include "library.h"
#include "list.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ListObjFiles (int argc, char* argv [])
/* List modules in a library */
{
ObjData* O;
/* Check the argument count */
if (argc <= 0) {
Error ("No library name given");
}
if (argc > 2) {
Error ("Too many arguments");
}
/* Open the library, read the index */
LibOpen (argv [0], 1, 0);
/* List the modules */
O = ObjRoot;
while (O) {
printf ("%s\n", O->Name);
O = O->Next;
}
/* Create a new library file and close the old one */
LibClose ();
/* Successful end */
exit (EXIT_SUCCESS);
}

58
src/ar65/list.h Normal file
View File

@@ -0,0 +1,58 @@
/*****************************************************************************/
/* */
/* list.h */
/* */
/* Module listing for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef LIST_H
#define LIST_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ListObjFiles (int argc, char* argv []);
/* List modules in a library */
/* End of list.h */
#endif

140
src/ar65/main.c Normal file
View File

@@ -0,0 +1,140 @@
/*****************************************************************************/
/* */
/* main.c */
/* */
/* Main program for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../common/version.h"
#include "global.h"
#include "error.h"
#include "mem.h"
#include "add.h"
#include "del.h"
#include "list.h"
#include "extract.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static void Usage (void)
/* Print usage information and exit */
{
fprintf (stderr,
"Usage: %s <operation> lib file|module ...\n"
"Operation is one of:\n"
"\ta\tAdd modules\n"
"\td\tDelete modules\n"
"\tl\tList library contents\n"
"\tx\tExtract modules\n"
"\tV\tPrint the archiver version\n",
ProgName);
exit (EXIT_FAILURE);
}
int main (int argc, char* argv [])
/* Assembler main program */
{
int I;
/* We must have a file name */
if (argc < 2) {
Usage ();
}
/* Check the parameters */
I = 1;
while (I < argc) {
/* Get the argument */
const char* Arg = argv [I];
/* Check for an option */
if (strlen (Arg) != 1) {
Usage ();
}
switch (Arg [0]) {
case 'a':
AddObjFiles (argc - I - 1, &argv [I+1]);
break;
case 'd':
DelObjFiles (argc - I - 1, &argv [I+1]);
break;
case 'l':
ListObjFiles (argc - I - 1, &argv [I+1]);
break;
case 'v':
++Verbose;
break;
case 'x':
ExtractObjFiles (argc - I - 1, &argv [I+1]);
break;
case 'V':
fprintf (stderr,
"ar65 V%u.%u.%u - (C) Copyright 1998-1999 Ullrich von Bassewitz\n",
VER_MAJOR, VER_MINOR, VER_PATCH);
break;
default:
fprintf (stderr, "Unknown option: %s\n", Arg);
Usage ();
}
/* Next argument */
++I;
}
/* Return an apropriate exit code */
return EXIT_SUCCESS;
}

56
src/ar65/make/gcc.mak Normal file
View File

@@ -0,0 +1,56 @@
#
# gcc Makefile for ar65
#
CFLAGS = -g -O2 -Wall
CC = gcc
LDFLAGS =
OBJS = add.o \
del.o \
error.o \
exports.o \
extract.o \
fileio.o \
global.o \
library.o \
list.o \
main.o \
mem.o \
objdata.o \
objfile.o
LIBS = ../common/common.a
EXECS = ar65
.PHONY: all
ifeq (.depend,$(wildcard .depend))
all : $(EXECS)
include .depend
else
all: depend
@$(MAKE) -f make/gcc.mak all
endif
ar65: $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
clean:
rm -f *~ core
zap: clean
rm -f *.o $(EXECS) .depend
# ------------------------------------------------------------------------------
# Make the dependencies
.PHONY: depend dep
depend dep: $(OBJS:.o=.c)
@echo "Creating dependency information"
$(CC) -MM $^ > .depend

123
src/ar65/make/watcom.mak Normal file
View File

@@ -0,0 +1,123 @@
#
# ar65 Makefile for the Watcom compiler
#
# ------------------------------------------------------------------------------
# Generic stuff
.AUTODEPEND
.SUFFIXES .ASM .C .CC .CPP
.SWAP
AR = WLIB
LD = WLINK
!if !$d(TARGET)
!if $d(__OS2__)
TARGET = OS2
!else
TARGET = NT
!endif
!endif
# target specific macros.
!if $(TARGET)==OS2
# --------------------- OS2 ---------------------
SYSTEM = os2v2
CC = WCC386
CCCFG = -bt=$(TARGET) -d1 -onatx -zp4 -5 -zq -w2
!elif $(TARGET)==DOS32
# -------------------- DOS4G --------------------
SYSTEM = dos4g
CC = WCC386
CCCFG = -bt=$(TARGET) -d1 -onatx -zp4 -5 -zq -w2
!elif $(TARGET)==DOS
# --------------------- DOS ---------------------
SYSTEM = dos
CC = WCC
CCCFG = -bt=$(TARGET) -d1 -onatx -zp2 -2 -ml -zq -w2
!elif $(TARGET)==NT
# --------------------- NT ----------------------
SYSTEM = nt
CC = WCC386
CCCFG = -bt=$(TARGET) -d1 -onatx -zp4 -5 -zq -w2
!else
!error
!endif
# ------------------------------------------------------------------------------
# Implicit rules
.c.obj:
$(CC) $(CCCFG) $<
# ------------------------------------------------------------------------------
# All library OBJ files
OBJS = add.obj \
del.obj \
error.obj \
exports.obj \
extract.obj \
fileio.obj \
global.obj \
library.obj \
list.obj \
main.obj \
mem.obj \
objdata.obj \
objfile.obj
LIBS = ..\common\common.lib
# ------------------------------------------------------------------------------
# Main targets
all: ar65
ar65: ar65.exe
# ------------------------------------------------------------------------------
# Other targets
ar65.exe: $(OBJS) $(LIBS)
$(LD) system $(SYSTEM) @&&|
DEBUG ALL
OPTION QUIET
NAME $<
FILE add.obj
FILE del.obj
FILE error.obj
FILE exports.obj
FILE extract.obj
FILE fileio.obj
FILE global.obj
FILE library.obj
FILE list.obj
FILE main.obj
FILE mem.obj
FILE objdata.obj
FILE objfile.obj
LIBRARY ..\common\common.lib
|
clean:
@if exist *.obj del *.obj
@if exist ar65.exe del ar65.exe
strip:
@-wstrip ar65.exe

84
src/ar65/mem.c Normal file
View File

@@ -0,0 +1,84 @@
/*****************************************************************************/
/* */
/* mem.c */
/* */
/* Memory allocation for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "mem.h"
/*****************************************************************************/
/* code */
/*****************************************************************************/
void* Xmalloc (size_t size)
/* Allocate memory, check for out of memory condition. Do some debugging */
{
void* p;
p = malloc (size);
if (p == 0 && size != 0) {
Error ("Out of memory");
}
/* Return a pointer to the block */
return p;
}
void Xfree (const void* block)
/* Free the block, do some debugging */
{
free ((void*) block);
}
char* StrDup (const char* s)
/* Duplicate a string on the heap. The function checks for out of memory */
{
unsigned len;
len = strlen (s) + 1;
return memcpy (Xmalloc (len), s, len);
}

67
src/ar65/mem.h Normal file
View File

@@ -0,0 +1,67 @@
/*****************************************************************************/
/* */
/* mem.h */
/* */
/* Memory allocation for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef MEM_H
#define MEM_H
#include <stddef.h>
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void* Xmalloc (size_t size);
/* Allocate memory, check for out of memory condition. Do some debugging */
void Xfree (const void* block);
/* Free the block, do some debugging */
char* StrDup (const char* s);
/* Duplicate a string on the heap. The function checks for out of memory */
/* End of mem.h */
#endif

207
src/ar65/objdata.c Normal file
View File

@@ -0,0 +1,207 @@
/*****************************************************************************/
/* */
/* objdata.c */
/* */
/* Handling object file data for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include "mem.h"
#include "error.h"
#include "objdata.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Object data list management */
unsigned ObjCount = 0; /* Count of object files in the list */
ObjData* ObjRoot = 0; /* List of object files */
ObjData* ObjLast = 0; /* Last entry in list */
ObjData** ObjPool = 0; /* Object files as array */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
ObjData* NewObjData (void)
/* Allocate a new structure on the heap, insert it into the list, return it */
{
/* Allocate memory */
ObjData* O = Xmalloc (sizeof (ObjData));
/* Initialize the data */
O->Next = 0;
O->Name = 0;
O->Index = ~0;
O->Flags = 0;
O->MTime = 0;
O->Start = 0;
O->Size = 0;
O->ImportSize = 0;
O->Imports = 0;
O->ExportSize = 0;
O->Exports = 0;
/* Link it into the list */
if (ObjLast) {
ObjLast->Next = O;
ObjLast = O;
} else {
/* First entry */
ObjRoot = ObjLast = O;
}
/* One object file more now */
++ObjCount;
/* Return the new entry */
return O;
}
void FreeObjData (ObjData* O)
/* Free a complete struct */
{
Xfree (O->Name);
Xfree (O->Imports);
Xfree (O->Exports);
Xfree (O);
}
ObjData* FindObjData (const char* Module)
/* Search for the module with the given name and return it. Return NULL if the
* module is not in the list.
*/
{
/* Hmm. Maybe we should hash the module names? */
ObjData* O = ObjRoot;
while (O) {
if (strcmp (O->Name, Module) == 0) {
return O;
}
O = O->Next;
}
return 0;
}
void DelObjData (const char* Module)
/* Delete the object module from the list */
{
ObjData* O = ObjRoot;
ObjData* Last = 0;
while (O) {
if (strcmp (O->Name, Module) == 0) {
/* Found the module, remove it from the list */
if (Last == 0) {
/* This was the first entry in the list */
ObjRoot = O->Next;
} else {
Last->Next = O->Next;
}
if (ObjLast == O) {
/* O was the last object in the list */
ObjLast = Last;
}
--ObjCount;
/* Free the entry */
FreeObjData (O);
/* Done */
return;
}
Last = O;
O = O->Next;
}
/* Not found! */
Warning ("Module `%s' not found in library", Module);
}
void MakeObjPool (void)
/* Allocate memory, index the entries and make the ObjPool valid */
{
ObjData* O;
unsigned Index;
/* Allocate memory for the pool */
ObjPool = Xmalloc (ObjCount * sizeof (ObjData*));
/* Setup the pointers and index the objects */
Index = 0;
O = ObjRoot;
while (O) {
/* Safety */
CHECK (Index < ObjCount);
/* Set the Index */
O->Index = Index;
/* Set the pool pointer */
ObjPool [Index] = O;
/* Next object */
++Index;
O = O->Next;
}
}
const char* GetObjName (unsigned Index)
/* Get the name of a module by index */
{
PRECONDITION (ObjPool != 0 && Index < ObjCount && ObjPool [Index] != 0);
return ObjPool [Index]->Name;
}

111
src/ar65/objdata.h Normal file
View File

@@ -0,0 +1,111 @@
/*****************************************************************************/
/* */
/* objdata.h */
/* */
/* Handling object file data for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef OBJDATA_H
#define OBJDATA_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Values for the Flags field */
#define OBJ_HAVEDATA 0x0001 /* The object data is in the tmp file */
#define OBJ_MARKED 0x0002 /* Generic marker bit */
/* Internal structure holding object file data */
typedef struct ObjData_ ObjData;
struct ObjData_ {
ObjData* Next; /* Linked list of all objects */
char* Name; /* Module name */
unsigned Index; /* Module index */
unsigned Flags;
unsigned long MTime; /* Modifiation time of object file */
unsigned long Start; /* Start offset of data in library */
unsigned long Size; /* Size of data in library */
unsigned long ImportSize; /* Size of imports */
void* Imports; /* Imports as raw data */
unsigned long ExportSize; /* Size of exports */
void* Exports; /* Exports as raw data */
};
/* Object data list management */
extern unsigned ObjCount; /* Count of files in the list */
extern ObjData* ObjRoot; /* List of object files */
extern ObjData* ObjLast; /* Last entry in list */
extern ObjData** ObjPool; /* Object files as array */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
ObjData* NewObjData (void);
/* Allocate a new structure on the heap, insert it into the list, return it */
void FreeObjData (ObjData* O);
/* Free a complete struct */
ObjData* FindObjData (const char* Module);
/* Search for the module with the given name and return it. Return NULL if the
* module is not in the list.
*/
void DelObjData (const char* Module);
/* Delete the object module from the list */
void MakeObjPool (void);
/* Allocate memory, index the entries and make the ObjPool valid */
const char* GetObjName (unsigned Index);
/* Get the name of a module by index */
/* End of objdata.h */
#endif

288
src/ar65/objfile.c Normal file
View File

@@ -0,0 +1,288 @@
/*****************************************************************************/
/* */
/* objfile.c */
/* */
/* Object file handling for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include <errno.h>
#ifdef __WATCOMC__
/* Watcom has the file in the wrong directory */
# include <sys/utime.h>
#else
# include <sys/types.h> /* FreeBSD needs this */
# include <utime.h>
#endif
#include <time.h>
#include <sys/stat.h>
#include "error.h"
#include "mem.h"
#include "objdata.h"
#include "fileio.h"
#include "library.h"
#include "objfile.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static const char* GetModule (const char* Name)
/* Get a module name from the file name */
{
/* Make a module name from the file name */
const char* Module = Name + strlen (Name);
while (Module > Name) {
--Module;
if (*Module == '/' || *Module == '\\') {
++Module;
break;
}
}
if (*Module == 0) {
Error ("Cannot make module name from `%s'", Name);
}
return Module;
}
void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
/* Read the header of the object file checking the signature */
{
H->Magic = Read32 (Obj);
if (H->Magic != OBJ_MAGIC) {
Error ("`%s' is not an object file", Name);
}
H->Version = Read16 (Obj);
if (H->Version != OBJ_VERSION) {
Error ("Object file `%s' has wrong version", Name);
}
H->Flags = Read16 (Obj);
H->OptionOffs = Read32 (Obj);
H->OptionSize = Read32 (Obj);
H->FileOffs = Read32 (Obj);
H->FileSize = Read32 (Obj);
H->SegOffs = Read32 (Obj);
H->SegSize = Read32 (Obj);
H->ImportOffs = Read32 (Obj);
H->ImportSize = Read32 (Obj);
H->ExportOffs = Read32 (Obj);
H->ExportSize = Read32 (Obj);
H->DbgSymOffs = Read32 (Obj);
H->DbgSymSize = Read32 (Obj);
}
void ObjWriteHeader (FILE* Obj, ObjHeader* H)
/* Write the header of the object file */
{
Write32 (Obj, H->Magic);
Write16 (Obj, H->Version);
Write16 (Obj, H->Flags);
Write32 (Obj, H->OptionOffs);
Write32 (Obj, H->OptionSize);
Write32 (Obj, H->FileOffs);
Write32 (Obj, H->FileSize);
Write32 (Obj, H->SegOffs);
Write32 (Obj, H->SegSize);
Write32 (Obj, H->ImportOffs);
Write32 (Obj, H->ImportSize);
Write32 (Obj, H->ExportOffs);
Write32 (Obj, H->ExportSize);
Write32 (Obj, H->DbgSymOffs);
Write32 (Obj, H->DbgSymSize);
}
void ObjAdd (const char* Name)
/* Add an object file to the library */
{
struct stat StatBuf;
const char* Module;
ObjHeader H;
ObjData* O;
/* Open the object file */
FILE* Obj = fopen (Name, "rb");
if (Obj == 0) {
Error ("Could not open `%s': %s", Name, strerror (errno));
}
/* Get the modification time of the object file */
if (fstat (fileno (Obj), &StatBuf) != 0) {
Error ("Cannot stat object file `%s': %s", Name, strerror (errno));
}
/* Read and check the header */
ObjReadHeader (Obj, &H, Name);
/* Make a module name from the file name */
Module = GetModule (Name);
/* Check if we already have a module with this name */
O = FindObjData (Module);
if (O == 0) {
/* Not found, create a new entry */
O = NewObjData ();
} else {
/* Found - check the file modification times of the internal copy
* and the external one.
*/
if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) {
Warning ("Replacing module `%s' by older version", O->Name);
}
}
/* Initialize the object module data structure */
O->Name = StrDup (Module);
O->Flags = OBJ_HAVEDATA;
O->MTime = StatBuf.st_mtime;
O->ImportSize = H.ImportSize;
O->Imports = Xmalloc (O->ImportSize);
O->ExportSize = H.ExportSize;
O->Exports = Xmalloc (O->ExportSize);
/* Read imports and exports */
fseek (Obj, H.ImportOffs, SEEK_SET);
ReadData (Obj, O->Imports, O->ImportSize);
fseek (Obj, H.ExportOffs, SEEK_SET);
ReadData (Obj, O->Exports, O->ExportSize);
/* Skip the object file header */
O->Start = ftell (NewLib);
fseek (NewLib, OBJ_HDR_SIZE, SEEK_CUR);
/* Copy the remaining sections */
fseek (Obj, H.DbgSymOffs, SEEK_SET);
H.DbgSymOffs = LibCopyTo (Obj, H.DbgSymSize) - O->Start;
fseek (Obj, H.OptionOffs, SEEK_SET);
H.OptionOffs = LibCopyTo (Obj, H.OptionSize) - O->Start;
fseek (Obj, H.SegOffs, SEEK_SET);
H.SegOffs = LibCopyTo (Obj, H.SegSize) - O->Start;
fseek (Obj, H.FileOffs, SEEK_SET);
H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start;
/* Calculate the amount of data written */
O->Size = ftell (NewLib) - O->Start;
/* Clear the remaining header fields */
H.ImportOffs = H.ImportSize = 0;
H.ExportOffs = H.ExportSize = 0;
/* Seek back and write the updated header */
fseek (NewLib, O->Start, SEEK_SET);
ObjWriteHeader (NewLib, &H);
/* Now seek again to end of file */
fseek (NewLib, 0, SEEK_END);
/* Done, close the file (we read it only, so no error check) */
fclose (Obj);
}
void ObjExtract (const char* Name)
/* Extract a module from the library */
{
unsigned long ImportStart;
unsigned long ExportStart;
struct utimbuf U;
ObjHeader H;
FILE* Obj;
/* Make a module name from the file name */
const char* Module = GetModule (Name);
/* Try to find the module in the library */
ObjData* O = FindObjData (Module);
/* Bail out if the module does not exist */
if (O == 0) {
Error ("Module `%s' not found in library", Module);
}
/* Open the output file */
Obj = fopen (Name, "w+b");
if (Obj == 0) {
Error ("Cannot open target file `%s': %s", Name, strerror (errno));
}
/* Copy the first four segments including the header to the new file */
LibCopyFrom (O->Start, O->Size, Obj);
/* Write imports and exports */
ImportStart = ftell (Obj);
WriteData (Obj, O->Imports, O->ImportSize);
ExportStart = ftell (Obj);
WriteData (Obj, O->Exports, O->ExportSize);
/* Seek back and read the header */
fseek (Obj, 0, SEEK_SET);
ObjReadHeader (Obj, &H, Name);
/* Update the header fields */
H.ImportOffs = ImportStart;
H.ImportSize = O->ImportSize;
H.ExportOffs = ExportStart;
H.ExportSize = O->ExportSize;
/* Write the changed header */
fseek (Obj, 0, SEEK_SET);
ObjWriteHeader (Obj, &H);
/* Close the file */
if (fclose (Obj) != 0) {
Error ("Problem closing object file `%s': %s", Name, strerror (errno));
}
/* Set access and modification time */
U.actime = O->MTime;
U.modtime = O->MTime;
if (utime (Name, &U) != 0) {
Error ("Cannot set mod time on `%s': %s", Name, strerror (errno));
}
}

72
src/ar65/objfile.h Normal file
View File

@@ -0,0 +1,72 @@
/*****************************************************************************/
/* */
/* objfile.h */
/* */
/* Object file handling for the ar65 archiver */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef OBJFILE_H
#define OBJFILE_H
#include <stdio.h>
#include "../common/objdefs.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name);
/* Read the header of the object file checking the signature */
void ObjWriteHeader (FILE* Obj, ObjHeader* H);
/* Write the header of the object file */
void ObjAdd (const char* Name);
/* Add an object file to the library */
void ObjExtract (const char* Name);
/* Extract a module from the library */
/* End of objfile.h */
#endif

2
src/ca65/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
.depend
ca65

418
src/ca65/condasm.c Normal file
View File

@@ -0,0 +1,418 @@
/*****************************************************************************/
/* */
/* condasm.c */
/* */
/* Conditional assembly support for ca65 */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "error.h"
#include "expr.h"
#include "scanner.h"
#include "symtab.h"
#include "condasm.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Maximum count of nested .ifs */
#define MAX_IFS 32
/* Set of bitmapped flags for the if descriptor */
enum {
ifNone = 0x0000, /* No flag */
ifCond = 0x0001, /* IF condition was true */
ifElse = 0x0002, /* We had a .ELSE branch */
ifNeedTerm = 0x0004 /* Need .ENDIF termination */
};
/*****************************************************************************/
/* struct IfDesc */
/*****************************************************************************/
/* One .IF descriptor */
typedef struct IfDesc_ IfDesc;
struct IfDesc_ {
unsigned Flags; /* Bitmapped flags, see above */
FilePos Pos; /* File position of the .IF */
const char* Name; /* Name of the directive */
};
/* The .IF stack */
static IfDesc IfStack [MAX_IFS];
static unsigned IfCount = 0;
static IfDesc* AllocIf (const char* Directive, int NeedTerm)
/* Alloc a new element from the .IF stack */
{
IfDesc* ID;
/* Check for stack overflow */
if (IfCount >= MAX_IFS) {
Error (ERR_IF_NESTING);
}
/* Alloc one element */
ID = &IfStack [IfCount++];
/* Initialize elements */
ID->Flags = NeedTerm? ifNeedTerm : ifNone;
ID->Pos = CurPos;
ID->Name = Directive;
/* Return the result */
return ID;
}
static IfDesc* GetCurrentIf (void)
/* Return the current .IF descriptor */
{
if (IfCount == 0) {
return 0;
} else {
return &IfStack [IfCount-1];
}
}
static void FreeIf (void)
/* Free all .IF descriptors until we reach one with the NeedTerm bit set */
{
int Done = 0;
do {
IfDesc* D = GetCurrentIf();
if (D == 0) {
Error (ERR_UNEXPECTED, ".ENDIF");
} else {
Done = (D->Flags & ifNeedTerm) != 0;
--IfCount;
}
} while (!Done);
}
static int GetCurrentIfCond (void)
/* Return the current condition based on all conditions on the stack */
{
unsigned Count;
for (Count = 0; Count < IfCount; ++Count) {
if ((IfStack[Count].Flags & ifCond) == 0) {
return 0;
}
}
return 1;
}
static void SetIfCond (IfDesc* ID, int C)
/* Set the .IF condition */
{
if (C) {
ID->Flags |= ifCond;
} else {
ID->Flags &= ~ifCond;
}
}
static void InvertIfCond (IfDesc* ID)
/* Invert the current condition */
{
ID->Flags ^= ifCond;
}
static int GetElse (const IfDesc* ID)
/* Return true if we had a .ELSE */
{
return (ID->Flags & ifElse) != 0;
}
static void SetElse (IfDesc* ID, int E)
/* Set the .ELSE flag */
{
if (E) {
ID->Flags |= ifElse;
} else {
ID->Flags &= ~ifElse;
}
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void DoConditionals (void)
/* Catch all for conditional directives */
{
IfDesc* D;
int IfCond = GetCurrentIfCond ();
do {
switch (Tok) {
case TOK_ELSE:
D = GetCurrentIf ();
if (D == 0) {
Error (ERR_UNEXPECTED, ".ELSE");
} else if (GetElse(D)) {
/* We already had a .ELSE ! */
Error (ERR_DUPLICATE_ELSE);
} else {
/* Allow an .ELSE */
InvertIfCond (D);
SetElse (D, 1);
D->Pos = CurPos;
D->Name = ".ELSE";
IfCond = GetCurrentIfCond ();
}
NextTok ();
break;
case TOK_ELSEIF:
D = GetCurrentIf ();
if (D == 0) {
Error (ERR_UNEXPECTED, ".ELSEIF");
} else if (GetElse(D)) {
/* We already had a .ELSE */
Error (ERR_DUPLICATE_ELSE);
} else {
/* Handle as if there was an .ELSE first */
InvertIfCond (D);
SetElse (D, 1);
/* Allocate and prepare a new descriptor */
D = AllocIf (".ELSEIF", 0);
NextTok ();
/* Ignore the new condition if we are inside a false .ELSE
* branch. This way we won't get any errors about undefined
* symbols or similar...
*/
if (IfCond == 0) {
SetIfCond (D, ConstExpression ());
}
/* Get the new overall condition */
IfCond = GetCurrentIfCond ();
}
break;
case TOK_ENDIF:
/* We're done with this .IF.. - remove the descriptor(s) */
FreeIf ();
/* Be sure not to read the next token until the .IF stack
* has been cleanup up, since we may be at end of file.
*/
NextTok ();
/* Get the new overall condition */
IfCond = GetCurrentIfCond ();
break;
case TOK_IF:
D = AllocIf (".IF", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, ConstExpression ());
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFBLANK:
D = AllocIf (".IFBLANK", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, Tok == TOK_SEP);
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFCONST:
D = AllocIf (".IFCONST", 1);
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
SetIfCond (D, IsConstExpr (Expr));
FreeExpr (Expr);
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFDEF:
D = AllocIf (".IFDEF", 1);
NextTok ();
if (IfCond) {
if (Tok != TOK_IDENT) {
ErrorSkip (ERR_IDENT_EXPECTED);
} else {
SetIfCond (D, SymIsDef (SVal));
NextTok ();
}
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFNBLANK:
D = AllocIf (".IFNBLANK", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, Tok != TOK_SEP);
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFNCONST:
D = AllocIf (".IFNCONST", 1);
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
SetIfCond (D, !IsConstExpr (Expr));
FreeExpr (Expr);
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFNDEF:
D = AllocIf (".IFNDEF", 1);
NextTok ();
if (IfCond) {
if (Tok != TOK_IDENT) {
ErrorSkip (ERR_IDENT_EXPECTED);
} else {
SetIfCond (D, !SymIsDef (SVal));
NextTok ();
}
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFNREF:
D = AllocIf (".IFNREF", 1);
NextTok ();
if (IfCond) {
if (Tok != TOK_IDENT) {
ErrorSkip (ERR_IDENT_EXPECTED);
} else {
SetIfCond (D, !SymIsRef (SVal));
NextTok ();
}
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFP02:
break;
case TOK_IFP816:
break;
case TOK_IFPC02:
break;
case TOK_IFREF:
D = AllocIf (".IFREF", 1);
NextTok ();
if (IfCond) {
if (Tok != TOK_IDENT) {
ErrorSkip (ERR_IDENT_EXPECTED);
} else {
SetIfCond (D, SymIsRef (SVal));
NextTok ();
}
}
IfCond = GetCurrentIfCond ();
break;
default:
// Skip tokens
NextTok ();
}
} while (IfCond == 0 && Tok != TOK_EOF);
}
void CheckOpenIfs (void)
/* Called from the scanner before closing an input file. Will check for any
* open .ifs in this file.
*/
{
while (1) {
/* Get the current file number and check if the topmost entry on the
* .IF stack was inserted with this file number
*/
IfDesc* D = GetCurrentIf ();
if (D == 0) {
/* There are no open .IFs */
break;
}
if (D->Pos.Name != CurPos.Name) {
/* The .if is from another file, bail out */
break;
}
/* Start of .if is in the file we're about to leave */
PError (&D->Pos, ERR_OPEN_IF);
FreeIf ();
}
}

62
src/ca65/condasm.h Normal file
View File

@@ -0,0 +1,62 @@
/*****************************************************************************/
/* */
/* condasm.h */
/* */
/* Conditional assembly support for ca65 */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef CONDASM_H
#define CONDASM_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void DoConditionals (void);
/* Catch all for conditional directives */
void CheckOpenIfs (void);
/* Called from the scanner before closing an input file. Will check for any
* open .ifs in this file.
*/
/* End of condasm.h */
#endif

198
src/ca65/ea.c Normal file
View File

@@ -0,0 +1,198 @@
/*****************************************************************************/
/* */
/* ea.c */
/* */
/* Effective address parsing for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "error.h"
#include "expr.h"
#include "instr.h"
#include "scanner.h"
#include "ea.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void GetEA (unsigned long* AddrMode, ExprNode** Expr, ExprNode** Bank)
/* Parse an effective address, return the possible modes in AddrMode, and the
* expression involved (if any) in Expr.
*/
{
/* Clear the expressions */
*Bank = *Expr = 0;
if (Tok == TOK_SEP) {
*AddrMode = AM_IMPLICIT;
} else if (Tok == TOK_HASH) {
/* #val */
NextTok ();
*Expr = Expression ();
*AddrMode = AM_IMM;
} else if (Tok == TOK_A) {
NextTok ();
*AddrMode = AM_ACCU;
} else if (Tok == TOK_LBRACK) {
/* [dir] or [dir],y */
NextTok ();
*Expr = Expression ();
Consume (TOK_RBRACK, ERR_RBRACK_EXPECTED);
if (Tok == TOK_COMMA) {
/* [dir],y */
NextTok ();
Consume (TOK_Y, ERR_Y_EXPECTED);
*AddrMode = AM_DIR_IND_LONG_Y;
} else {
/* [dir] */
*AddrMode = AM_DIR_IND_LONG;
}
} else if (Tok == TOK_LPAREN) {
/* One of the indirect modes */
NextTok ();
*Expr = Expression ();
if (Tok == TOK_COMMA) {
/* (expr,X) or (rel,S),y */
NextTok ();
if (Tok == TOK_X) {
/* (adr,x) */
NextTok ();
*AddrMode = AM_ABS_X_IND | AM_DIR_X_IND;
ConsumeRParen ();
} else if (Tok == TOK_S) {
/* (rel,s),y */
NextTok ();
*AddrMode = AM_STACK_REL_IND_Y;
ConsumeRParen ();
ConsumeComma ();
Consume (TOK_Y, ERR_Y_EXPECTED);
} else {
Error (ERR_SYNTAX);
}
} else {
/* (adr) or (adr),y */
ConsumeRParen ();
if (Tok == TOK_COMMA) {
/* (adr),y */
NextTok ();
Consume (TOK_Y, ERR_Y_EXPECTED);
*AddrMode = AM_DIR_IND_Y;
} else {
/* (adr) */
*AddrMode = AM_ABS_IND | AM_DIR_IND;
}
}
} else {
/* Remaining stuff:
*
* adr
* bank.adr
* adr,x
* bank.adr,x
* adr,y
* adr,s
*/
*Expr = Expression ();
if (Tok == TOK_DOT) {
/* Expr was a bank specification: bank.adr or bank.adr,x */
*Bank = *Expr;
NextTok ();
*Expr = Expression ();
if (Tok == TOK_COMMA) {
/* bank.adr,x */
NextTok ();
Consume (TOK_X, ERR_X_EXPECTED);
*AddrMode = AM_ABS_LONG_X;
} else {
/* bank.adr */
*AddrMode = AM_ABS_LONG;
}
} else {
if (Tok == TOK_COMMA) {
NextTok ();
switch (Tok) {
case TOK_X:
*AddrMode = AM_ABS_X | AM_DIR_X;
NextTok ();
break;
case TOK_Y:
*AddrMode = AM_ABS_Y | AM_DIR_Y;
NextTok ();
break;
case TOK_S:
*AddrMode = AM_STACK_REL;
NextTok ();
break;
default:
Error (ERR_SYNTAX);
}
} else {
*AddrMode = AM_ABS | AM_DIR;
}
}
}
}

69
src/ca65/ea.h Normal file
View File

@@ -0,0 +1,69 @@
/*****************************************************************************/
/* */
/* ea.h */
/* */
/* Effective address parsing for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef EA_H
#define EA_H
#include "expr.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void GetEA (unsigned long* AddrMode, ExprNode** Expr, ExprNode** Bank);
/* Parse an effective address, return the possible modes in AddrMode, and the
* expression involved (if any) in Expr.
*/
/* End of ea.h */
#endif

291
src/ca65/error.c Normal file
View File

@@ -0,0 +1,291 @@
/*****************************************************************************/
/* */
/* error.c */
/* */
/* Error handling for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "scanner.h"
#include "error.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Warning level */
unsigned WarnLevel = 1;
/* Messages for internal compiler errors */
const char _MsgCheckFailed [] =
"Check failed: `%s' (= %d), file `%s', line %u\n";
const char _MsgPrecondition [] =
"Precondition violated: `%s' (= %d), file `%s', line %u\n";
const char _MsgFail [] =
"%s, file `%s', line %u\n";
/* Statistics */
unsigned ErrorCount = 0;
unsigned WarningCount = 0;
/*****************************************************************************/
/* Warnings */
/*****************************************************************************/
void WarningMsg (const FilePos* Pos, unsigned WarnNum, va_list ap)
/* Print warning message. */
{
static const struct {
unsigned char Level;
const char* Msg;
} Warnings [WARN_COUNT-1] = {
{ 1, "Mask error" },
{ 2, "Symbol `%s' is defined but never used" },
{ 2, "Symbol `%s' is imported but never used" },
{ 1, "Cannot track processor status byte" },
};
if (Warnings [WarnNum-1].Level <= WarnLevel) {
fprintf (stderr, "%s(%lu): Warning #%u: ",
GetFileName (Pos->Name), Pos->Line, WarnNum);
vfprintf (stderr, Warnings [WarnNum-1].Msg, ap);
fprintf (stderr, "\n");
++WarningCount;
}
}
void Warning (unsigned WarnNum, ...)
/* Print warning message. */
{
va_list ap;
va_start (ap, WarnNum);
WarningMsg (&CurPos, WarnNum, ap);
va_end (ap);
}
void PWarning (const FilePos* Pos, unsigned WarnNum, ...)
/* Print warning message giving an explicit file and position. */
{
va_list ap;
va_start (ap, WarnNum);
WarningMsg (Pos, WarnNum, ap);
va_end (ap);
}
/*****************************************************************************/
/* Errors */
/*****************************************************************************/
void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap)
/* Print an error message */
{
static const char* Msgs [ERR_COUNT-1] = {
"Command/operation not implemented",
"Cannot open include file `%s': %s",
"Include nesting too deep",
"Invalid input character: %02X",
"Hex digit expected",
"Digit expected",
"`0' or `1' expected",
"Numerical overflow",
"Control statement expected",
"Too many characters",
"`:' expected",
"`(' expected",
"`)' expected",
"`]' expected",
"`,' expected",
"Boolean switch value expected (on/off/+/-)",
"`Y' expected",
"`X' expected",
"Integer constant expected",
"String constant expected",
"Character constant expected",
"Constant expression expected",
"Identifier expected",
"`.endmacro' expected",
"Option key expected",
"Command is only valid in 65816 mode",
"User error: %s",
"String constant too long",
"Newline in string constant",
"Illegal character constant",
"Illegal addressing mode",
"Illegal character to start local symbols",
"Illegal use of local symbol",
"Illegal segment name: `%s'",
"Illegal segment attribute",
"Illegal macro package name",
"Illegal emulation feature",
"Syntax error",
"Symbol `%s' is already defined",
"Undefined symbol `%s'",
"Symbol `%s' is marked as import",
"Symbol `%s' is marked as export",
"Exported symbol `%s' is undefined",
"Exported values must be constant",
".IF nesting too deep",
"Unexpected end of line",
"Unexpected `%s'",
"Division by zero",
"Modulo operation with zero",
"Range error",
"Too many macro parameters",
"Macro parameter expected",
"Circular reference in symbol definition",
"Symbol redeclaration mismatch",
"Alignment value must be a power of 2",
"Duplicate `.ELSE'",
"Conditional assembly branch was never closed",
"Lexical level was not terminated correctly",
"Segment attribute mismatch",
"CPU not supported",
"Counter underflow",
"Undefined label",
};
fprintf (stderr, "%s(%lu): Error #%u: ",
GetFileName (Pos->Name), Pos->Line, ErrNum);
vfprintf (stderr, Msgs [ErrNum-1], ap);
fprintf (stderr, "\n");
++ErrorCount;
}
void Error (unsigned ErrNum, ...)
/* Print an error message */
{
va_list ap;
va_start (ap, ErrNum);
ErrorMsg (&CurPos, ErrNum, ap);
va_end (ap);
}
void PError (const FilePos* Pos, unsigned ErrNum, ...)
/* Print an error message giving an explicit file and position. */
{
va_list ap;
va_start (ap, ErrNum);
ErrorMsg (Pos, ErrNum, ap);
va_end (ap);
}
void ErrorSkip (unsigned ErrNum, ...)
/* Print an error message and skip the rest of the line */
{
va_list ap;
va_start (ap, ErrNum);
ErrorMsg (&CurPos, ErrNum, ap);
va_end (ap);
SkipUntilSep ();
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Fatal (unsigned FatNum, ...)
/* Print a message about a fatal error and die */
{
static const char* Msgs [FAT_COUNT-1] = {
"Maximum number of input files reached",
"Out of memory",
"Too many segments",
"String too long",
"Cannot open input file `%s': %s",
"Cannot stat input file `%s': %s",
"Cannot open output file `%s': %s",
"Cannot write to output file `%s': %s",
"Cannot open listing file: %s",
"Cannot write to listing file: %s",
"Cannot read from listing file: %s",
"Macro nesting too deep",
"Too many symbols",
};
va_list ap;
va_start (ap, FatNum);
fprintf (stderr, "Fatal #%u: ", FatNum);
vfprintf (stderr, Msgs [FatNum-1], ap);
fprintf (stderr, "\n");
va_end (ap);
/* And die... */
exit (EXIT_FAILURE);
}
void Internal (const char* Format, ...)
/* Print a message about an internal compiler error and die. */
{
va_list ap;
va_start (ap, Format);
fprintf (stderr, "Internal assembler error\n");
vfprintf (stderr, Format, ap);
va_end (ap);
fprintf (stderr, "\n");
exit (EXIT_FAILURE);
}

210
src/ca65/error.h Normal file
View File

@@ -0,0 +1,210 @@
/*****************************************************************************/
/* */
/* error.h */
/* */
/* Error handling for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ERROR_H
#define ERROR_H
#include "scanner.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Warning numbers */
enum Warnings {
WARN_NONE, /* No warning */
WARN_MASK_ERROR,
WARN_SYM_NOT_REFERENCED,
WARN_IMPORT_NOT_REFERENCED,
WARN_CANNOT_TRACK_STATUS,
WARN_COUNT /* Warning count */
};
/* Error numbers */
enum Errors {
ERR_NONE, /* No error */
ERR_NOT_IMPLEMENTED, /* Command/operation not implemented */
ERR_CANNOT_OPEN_INCLUDE,
ERR_INCLUDE_NESTING,
ERR_INVALID_CHAR,
ERR_HEX_DIGIT_EXPECTED,
ERR_DIGIT_EXPECTED,
ERR_01_EXPECTED,
ERR_NUM_OVERFLOW,
ERR_PSEUDO_EXPECTED,
ERR_TOO_MANY_CHARS,
ERR_COLON_EXPECTED,
ERR_LPAREN_EXPECTED,
ERR_RPAREN_EXPECTED,
ERR_RBRACK_EXPECTED,
ERR_COMMA_EXPECTED,
ERR_ONOFF_EXPECTED,
ERR_Y_EXPECTED,
ERR_X_EXPECTED,
ERR_INTCON_EXPECTED,
ERR_STRCON_EXPECTED,
ERR_CHARCON_EXPECTED,
ERR_CONSTEXPR_EXPECTED,
ERR_IDENT_EXPECTED,
ERR_ENDMACRO_EXPECTED,
ERR_OPTION_KEY_EXPECTED,
ERR_816_MODE_ONLY,
ERR_USER,
ERR_STRING_TOO_LONG,
ERR_NEWLINE_IN_STRING,
ERR_ILLEGAL_CHARCON,
ERR_ILLEGAL_ADDR_MODE,
ERR_ILLEGAL_LOCALSTART,
ERR_ILLEGAL_LOCAL_USE,
ERR_ILLEGAL_SEGMENT,
ERR_ILLEGAL_SEG_ATTR,
ERR_ILLEGAL_MACPACK,
ERR_ILLEGAL_FEATURE,
ERR_SYNTAX,
ERR_SYM_ALREADY_DEFINED,
ERR_SYM_UNDEFINED,
ERR_SYM_ALREADY_IMPORT,
ERR_SYM_ALREADY_EXPORT,
ERR_EXPORT_UNDEFINED,
ERR_EXPORT_MUST_BE_CONST,
ERR_IF_NESTING,
ERR_UNEXPECTED_EOL,
ERR_UNEXPECTED,
ERR_DIV_BY_ZERO,
ERR_MOD_BY_ZERO,
ERR_RANGE,
ERR_TOO_MANY_PARAMS,
ERR_MACRO_PARAM_EXPECTED,
ERR_CIRCULAR_REFERENCE,
ERR_SYM_REDECL_MISMATCH,
ERR_ALIGN,
ERR_DUPLICATE_ELSE,
ERR_OPEN_IF,
ERR_OPEN_PROC,
ERR_SEG_ATTR_MISMATCH,
ERR_CPU_NOT_SUPPORTED,
ERR_COUNTER_UNDERFLOW,
ERR_UNDEFINED_LABEL,
ERR_COUNT /* Error count */
};
/* Fatal errors */
enum Fatals {
FAT_NONE,
FAT_MAX_INPUT_FILES,
FAT_OUT_OF_MEMORY,
FAT_TOO_MANY_SEGMENTS,
FAT_STRING_TOO_LONG,
FAT_CANNOT_OPEN_INPUT,
FAT_CANNOT_STAT_INPUT,
FAT_CANNOT_OPEN_OUTPUT,
FAT_CANNOT_WRITE_OUTPUT,
FAT_CANNOT_OPEN_LISTING,
FAT_CANNOT_WRITE_LISTING,
FAT_CANNOT_READ_LISTING,
FAT_MACRO_NESTING,
FAT_TOO_MANY_SYMBOLS,
FAT_COUNT /* Fatal error count */
};
/* Warning levels */
extern unsigned WarnLevel;
/* Messages for internal compiler errors */
extern const char _MsgCheckFailed [];
extern const char _MsgPrecondition [];
extern const char _MsgFail [];
/* Statistics */
extern unsigned ErrorCount;
extern unsigned WarningCount;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Warning (unsigned WarnNum, ...);
/* Print warning message. */
void PWarning (const FilePos* Pos, unsigned WarnNum, ...);
/* Print warning message giving an explicit file and position. */
void Error (unsigned ErrNum, ...);
/* Print an error message */
void PError (const FilePos* Pos, unsigned ErrNum, ...);
/* Print an error message giving an explicit file and position. */
void ErrorSkip (unsigned ErrNum, ...);
/* Print an error message and skip the rest of the line */
void Fatal (unsigned FatNum, ...);
/* Print a message about a fatal error and die */
void Internal (const char* Format, ...);
/* Print a message about an internal compiler error and die. */
#define CHECK(c) \
if (!(c)) \
Internal (_MsgCheckFailed, #c, c, __FILE__, __LINE__)
#define PRECONDITION(c) \
if (!(c)) \
Internal (_MsgPrecondition, #c, c, __FILE__, __LINE__)
#define FAIL(s) \
Internal (_MsgFail, s, __FILE__, __LINE__)
/* End of error.h */
#endif

1566
src/ca65/expr.c Normal file

File diff suppressed because it is too large Load Diff

127
src/ca65/expr.h Normal file
View File

@@ -0,0 +1,127 @@
/*****************************************************************************/
/* */
/* expr.h */
/* */
/* Expression evaluation for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef EXPR_H
#define EXPR_H
#include "../common/exprdefs.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
ExprNode* Expression (void);
/* Evaluate an expression, build the expression tree on the heap and return
* a pointer to the root of the tree.
*/
long ConstExpression (void);
/* Parse an expression. Check if the expression is const, and print an error
* message if not. Return the value of the expression, or a dummy, if it is
* not constant.
*/
void FreeExpr (ExprNode* Root);
/* Free the expression tree, Root is pointing to. */
ExprNode* LiteralExpr (long Val);
/* Return an expression tree that encodes the given literal value */
ExprNode* CurrentPC (void);
/* Return the current program counter as expression */
ExprNode* SwapExpr (ExprNode* Expr);
/* Return an extended expression with lo and hi bytes swapped */
ExprNode* BranchExpr (unsigned Offs);
/* Return an expression that encodes the difference between current PC plus
* offset and the target expression (that is, Expression() - (*+Offs) ).
*/
ExprNode* ULabelExpr (unsigned Num);
/* Return an expression for an unnamed label with the given index */
ExprNode* ForceWordExpr (ExprNode* Expr);
/* Force the given expression into a word and return the result. */
int IsConstExpr (ExprNode* Root);
/* Return true if the given expression is a constant expression, that is, one
* with no references to external symbols.
*/
int IsByteExpr (ExprNode* Root);
/* Return true if this is a byte expression */
long GetExprVal (ExprNode* Expr);
/* Get the value of a constant expression */
int IsByteRange (long Val);
/* Return true if this is a byte value */
int IsWordRange (long Val);
/* Return true if this is a word value */
void DumpExpr (ExprNode* Expr);
/* Dump an expression tree to stdout */
ExprNode* FinalizeExpr (ExprNode* Expr);
/* Resolve any symbols by cloning the symbol expression tree instead of the
* symbol reference, then try to simplify the expression as much as possible.
* This function must only be called if all symbols are resolved (no undefined
* symbol errors).
*/
ExprNode* CloneExpr (ExprNode* Expr);
/* Clone the given expression tree. The function will simply clone symbol
* nodes, it will not resolve them.
*/
void WriteExpr (ExprNode* Expr);
/* Write the given expression to the object file */
/* End of expr.h */
#endif

74
src/ca65/fname.c Normal file
View File

@@ -0,0 +1,74 @@
/*****************************************************************************/
/* */
/* fname.c */
/* */
/* File name handling utilities */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include "mem.h"
#include "fname.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* MakeFilename (const char* Origin, const char* Ext)
/* Make a new file name from Origin and Ext. If Origin has an extension, it
* is removed and Ext is appended. If Origin has no extension, Ext is simply
* appended. The result is placed in a malloc'ed buffer and returned.
* The function may be used to create "foo.o" from "foo.s".
*/
{
/* Construct the name */
char* Result;
const char* P = strrchr (Origin, '.');
if (P == 0) {
/* No dot, add the extension */
Result = Xmalloc (strlen (Origin) + strlen (Ext) + 1);
strcpy (Result, Origin);
strcat (Result, Ext);
} else {
Result = Xmalloc (P - Origin + strlen (Ext) + 1);
memcpy (Result, Origin, P - Origin);
strcpy (Result + (P - Origin), Ext);
}
return Result;
}

61
src/ca65/fname.h Normal file
View File

@@ -0,0 +1,61 @@
/*****************************************************************************/
/* */
/* fname.h */
/* */
/* File name handling utilities */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef FNAME_H
#define FNAME_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* MakeFilename (const char* Origin, const char* Ext);
/* Make a new file name from Origin and Ext. If Origin has an extension, it
* is removed and Ext is appended. If Origin has no extension, Ext is simply
* appended. The result is placed in a malloc'ed buffer and returned.
* The function may be used to create "foo.o" from "foo.s".
*/
/* End of fname.h */
#endif

51
src/ca65/fragment.c Normal file
View File

@@ -0,0 +1,51 @@
/*****************************************************************************/
/* */
/* fragment.c */
/* */
/* Data fragments for the ca65 crossassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "fragment.h"
/*****************************************************************************/
/* struct Fragment */
/*****************************************************************************/
/* List of all fragments */
Fragment* FragList = 0;
Fragment* FragLast = 0;

78
src/ca65/fragment.h Normal file
View File

@@ -0,0 +1,78 @@
/*****************************************************************************/
/* */
/* fragment.h */
/* */
/* Data fragments for the ca65 crossassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef FRAGMENT_H
#define FRAGMENT_H
#include "../common/exprdefs.h"
#include "../common/filepos.h"
/*****************************************************************************/
/* struct Fragment */
/*****************************************************************************/
typedef struct Fragment_ Fragment;
struct Fragment_ {
Fragment* List; /* List of all fragments */
Fragment* Next; /* Fragment list in one segment */
Fragment* LineList; /* List of fragments for one src line */
FilePos Pos; /* File position for this fragment */
unsigned short Len; /* Length for this fragment */
unsigned char Type; /* Fragment type */
union {
unsigned char Data [4]; /* Literal values */
ExprNode* Expr; /* Expression */
} V;
};
/* List of all fragments */
extern Fragment* FragList;
extern Fragment* FragLast;
/* End of fragment.h */
#endif

76
src/ca65/global.c Normal file
View File

@@ -0,0 +1,76 @@
/*****************************************************************************/
/* */
/* global.c */
/* */
/* Global variables for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "global.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
const char* ProgName = "ca65"; /* Program name */
/* File names */
const char* InFile = 0; /* Name of input file */
const char* OutFile = 0; /* Name of output file */
const char* ListFile = 0; /* Name of listing file */
/* Default extensions */
const char ObjExt[] = ".o"; /* Default object extension */
const char ListExt[] = ".lst"; /* Default listing extension */
char LocalStart = '@'; /* This char starts local symbols */
unsigned char IgnoreCase = 0; /* Ignore case on identifiers? */
unsigned char AutoImport = 0; /* Mark unresolveds as import */
unsigned char Verbose = 0; /* Verbose operation flag */
unsigned char SmartMode = 0; /* Smart mode */
unsigned char DbgSyms = 0; /* Add debug symbols */
unsigned char Listing = 0; /* Create listing file */
unsigned char LineCont = 0; /* Allow line continuation */
/* Emulation features */
unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */
unsigned char NoColonLabels = 0; /* Allow labels without a colon */
unsigned char LooseStringTerm = 0; /* Allow ' as string terminator */
unsigned char AtInIdents = 0; /* Allow '@' in identifiers */
unsigned char DollarInIdents = 0; /* Allow '$' in identifiers */

82
src/ca65/global.h Normal file
View File

@@ -0,0 +1,82 @@
/*****************************************************************************/
/* */
/* global.h */
/* */
/* Global variables for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef GLOBAL_H
#define GLOBAL_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
extern const char* ProgName; /* Program name */
/* File names */
extern const char* InFile; /* Name of input file */
extern const char* OutFile; /* Name of output file */
extern const char* ListFile; /* Name of listing file */
/* Default extensions */
extern const char ObjExt[]; /* Default object extension */
extern const char ListExt[]; /* Default listing extension */
extern char LocalStart; /* This char starts local symbols */
extern unsigned char IgnoreCase; /* Ignore case on identifiers? */
extern unsigned char AutoImport; /* Mark unresolveds as import */
extern unsigned char Verbose; /* Verbose operation flag */
extern unsigned char SmartMode; /* Smart mode */
extern unsigned char DbgSyms; /* Add debug symbols */
extern unsigned char Listing; /* Create listing file */
extern unsigned char LineCont; /* Allow line continuation */
/* Emulation features */
extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */
extern unsigned char NoColonLabels; /* Allow labels without a colon */
extern unsigned char LooseStringTerm;/* Allow ' as string terminator */
extern unsigned char AtInIdents; /* Allow '@' in identifiers */
extern unsigned char DollarInIdents; /* Allow '$' in identifiers */
/* End of global.h */
#endif

748
src/ca65/instr.c Normal file
View File

@@ -0,0 +1,748 @@
/*****************************************************************************/
/* */
/* instr.c */
/* */
/* Instruction encoding for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "../common/bitops.h"
#include "ea.h"
#include "error.h"
#include "expr.h"
#include "global.h"
#include "objcode.h"
#include "scanner.h"
#include "instr.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Forwards for handler functions */
static void PutPCRel8 (const InsDesc* Ins);
static void PutPCRel16 (const InsDesc* Ins);
static void PutBlockMove (const InsDesc* Ins);
static void PutREP (const InsDesc* Ins);
static void PutSEP (const InsDesc* Ins);
static void PutAll (const InsDesc* Ins);
/* Instruction table for the 6502 */
#define INS_COUNT_6502 56
static const struct {
unsigned Count;
InsDesc Ins[INS_COUNT_6502];
} InsTab6502 = {
INS_COUNT_6502,
{
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
{ "AND", 0x080A26C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
{ "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
{ "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
{ "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
{ "BIT", 0x000000C, 0x00, 2, PutAll },
{ "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
{ "CLD", 0x0000001, 0xd8, 0, PutAll },
{ "CLI", 0x0000001, 0x58, 0, PutAll },
{ "CLV", 0x0000001, 0xb8, 0, PutAll },
{ "CMP", 0x080A26C, 0xc0, 0, PutAll },
{ "CPX", 0x080000C, 0xe0, 1, PutAll },
{ "CPY", 0x080000C, 0xc0, 1, PutAll },
{ "DEC", 0x000006C, 0x00, 3, PutAll },
{ "DEX", 0x0000001, 0xca, 0, PutAll },
{ "DEY", 0x0000001, 0x88, 0, PutAll },
{ "EOR", 0x080A26C, 0x40, 0, PutAll },
{ "INC", 0x000006c, 0x00, 4, PutAll },
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JMP", 0x0000808, 0x4c, 6, PutAll },
{ "JSR", 0x0000008, 0x20, 7, PutAll },
{ "LDA", 0x080A26C, 0xa0, 0, PutAll },
{ "LDX", 0x080030C, 0xa2, 1, PutAll },
{ "LDY", 0x080006C, 0xa0, 1, PutAll },
{ "LSR", 0x000006F, 0x42, 1, PutAll },
{ "NOP", 0x0000001, 0xea, 0, PutAll },
{ "ORA", 0x080A26C, 0x00, 0, PutAll },
{ "PHA", 0x0000001, 0x48, 0, PutAll },
{ "PHP", 0x0000001, 0x08, 0, PutAll },
{ "PLA", 0x0000001, 0x68, 0, PutAll },
{ "PLP", 0x0000001, 0x28, 0, PutAll },
{ "ROL", 0x000006F, 0x22, 1, PutAll },
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTS", 0x0000001, 0x60, 0, PutAll },
{ "SBC", 0x080A26C, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
{ "SEI", 0x0000001, 0x78, 0, PutAll },
{ "STA", 0x000A26C, 0x80, 0, PutAll },
{ "STX", 0x000010c, 0x82, 1, PutAll },
{ "STY", 0x000002c, 0x80, 1, PutAll },
{ "TAX", 0x0000001, 0xaa, 0, PutAll },
{ "TAY", 0x0000001, 0xa8, 0, PutAll },
{ "TSX", 0x0000001, 0xba, 0, PutAll },
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
}
};
/* Instruction table for the 65SC02 */
#define INS_COUNT_65SC02 66
static const struct {
unsigned Count;
InsDesc Ins[INS_COUNT_65SC02];
} InsTab65SC02 = {
INS_COUNT_65SC02,
{
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
{ "AND", 0x080A66C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
{ "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
{ "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
{ "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
{ "BIT", 0x080006C, 0x00, 2, PutAll },
{ "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
{ "CLD", 0x0000001, 0xd8, 0, PutAll },
{ "CLI", 0x0000001, 0x58, 0, PutAll },
{ "CLV", 0x0000001, 0xb8, 0, PutAll },
{ "CMP", 0x080A66C, 0xc0, 0, PutAll },
{ "CPX", 0x080000C, 0xe0, 1, PutAll },
{ "CPY", 0x080000C, 0xc0, 1, PutAll },
{ "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
{ "DEC", 0x000006F, 0x00, 3, PutAll },
{ "DEX", 0x0000001, 0xca, 0, PutAll },
{ "DEY", 0x0000001, 0x88, 0, PutAll },
{ "EOR", 0x080A66C, 0x40, 0, PutAll },
{ "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
{ "INC", 0x000006f, 0x00, 4, PutAll },
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JMP", 0x0010808, 0x4c, 6, PutAll },
{ "JSR", 0x0000008, 0x20, 7, PutAll },
{ "LDA", 0x080A66C, 0xa0, 0, PutAll },
{ "LDX", 0x080030C, 0xa2, 1, PutAll },
{ "LDY", 0x080006C, 0xa0, 1, PutAll },
{ "LSR", 0x000006F, 0x42, 1, PutAll },
{ "NOP", 0x0000001, 0xea, 0, PutAll },
{ "ORA", 0x080A66C, 0x00, 0, PutAll },
{ "PHA", 0x0000001, 0x48, 0, PutAll },
{ "PHP", 0x0000001, 0x08, 0, PutAll },
{ "PHX", 0x0000001, 0xda, 0, PutAll },
{ "PHY", 0x0000001, 0x5a, 0, PutAll },
{ "PLA", 0x0000001, 0x68, 0, PutAll },
{ "PLP", 0x0000001, 0x28, 0, PutAll },
{ "PLX", 0x0000001, 0xfa, 0, PutAll },
{ "PLY", 0x0000001, 0x7a, 0, PutAll },
{ "ROL", 0x000006F, 0x22, 1, PutAll },
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTS", 0x0000001, 0x60, 0, PutAll },
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
{ "SEI", 0x0000001, 0x78, 0, PutAll },
{ "STA", 0x000A66C, 0x80, 0, PutAll },
{ "STX", 0x000010c, 0x82, 1, PutAll },
{ "STY", 0x000002c, 0x80, 1, PutAll },
{ "STZ", 0x000006c, 0x04, 5, PutAll },
{ "TAX", 0x0000001, 0xaa, 0, PutAll },
{ "TAY", 0x0000001, 0xa8, 0, PutAll },
{ "TRB", 0x000000c, 0x10, 1, PutAll },
{ "TSB", 0x000000c, 0x00, 1, PutAll },
{ "TSX", 0x0000001, 0xba, 0, PutAll },
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
}
};
/* Instruction table for the 65816 */
#define INS_COUNT_65816 101
static const struct {
unsigned Count;
InsDesc Ins[INS_COUNT_65816];
} InsTab65816 = {
INS_COUNT_65816,
{
{ "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
{ "AND", 0x0b8f6fc, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
{ "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
{ "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
{ "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
{ "BGE", 0x0020000, 0xb0, 0, PutPCRel8 }, /* == BCS */
{ "BIT", 0x0a0006c, 0x00, 2, PutAll },
{ "BLT", 0x0020000, 0x90, 0, PutPCRel8 }, /* == BCC */
{ "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
{ "CLD", 0x0000001, 0xd8, 0, PutAll },
{ "CLI", 0x0000001, 0x58, 0, PutAll },
{ "CLV", 0x0000001, 0xb8, 0, PutAll },
{ "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
{ "COP", 0x0000004, 0x02, 6, PutAll },
{ "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
{ "CPX", 0x0c0000c, 0xe0, 1, PutAll },
{ "CPY", 0x0c0000c, 0xc0, 1, PutAll },
{ "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
{ "DEC", 0x000006F, 0x00, 3, PutAll },
{ "DEX", 0x0000001, 0xca, 0, PutAll },
{ "DEY", 0x0000001, 0x88, 0, PutAll },
{ "EOR", 0x0b8f6fc, 0x40, 0, PutAll },
{ "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
{ "INC", 0x000006F, 0x00, 4, PutAll },
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JML", 0x0000810, 0x5c, 1, PutAll },
{ "JMP", 0x0010818, 0x4c, 6, PutAll },
{ "JSL", 0x0000010, 0x20, 7, PutAll },
{ "JSR", 0x0010018, 0x20, 7, PutAll },
{ "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
{ "LDX", 0x0c0030c, 0xa2, 1, PutAll },
{ "LDY", 0x0c0006c, 0xa0, 1, PutAll },
{ "LSR", 0x000006F, 0x42, 1, PutAll },
{ "MVN", 0x1000000, 0x54, 0, PutBlockMove },
{ "MVP", 0x1000000, 0x44, 0, PutBlockMove },
{ "NOP", 0x0000001, 0xea, 0, PutAll },
{ "ORA", 0x0b8f6fc, 0x00, 0, PutAll },
{ "PEA", 0x0000008, 0xf4, 6, PutAll },
{ "PEI", 0x0800000, 0xd4, 0, PutAll },
{ "PER", 0x0040000, 0x62, 0, PutPCRel16 },
{ "PHA", 0x0000001, 0x48, 0, PutAll },
{ "PHB", 0x0000001, 0x8b, 0, PutAll },
{ "PHD", 0x0000001, 0x0b, 0, PutAll },
{ "PHK", 0x0000001, 0x4b, 0, PutAll },
{ "PHP", 0x0000001, 0x08, 0, PutAll },
{ "PHX", 0x0000001, 0xda, 0, PutAll },
{ "PHY", 0x0000001, 0x5a, 0, PutAll },
{ "PLA", 0x0000001, 0x68, 0, PutAll },
{ "PLB", 0x0000001, 0xab, 0, PutAll },
{ "PLD", 0x0000001, 0x2b, 0, PutAll },
{ "PLP", 0x0000001, 0x28, 0, PutAll },
{ "PLX", 0x0000001, 0xfa, 0, PutAll },
{ "PLY", 0x0000001, 0x7a, 0, PutAll },
{ "REP", 0x0800000, 0xc2, 1, PutREP },
{ "ROL", 0x000006F, 0x22, 1, PutAll },
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTL", 0x0000001, 0x6b, 0, PutAll },
{ "RTS", 0x0000001, 0x60, 0, PutAll },
{ "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
{ "SEI", 0x0000001, 0x78, 0, PutAll },
{ "SEP", 0x0800000, 0xe2, 1, PutSEP },
{ "STA", 0x018f6fc, 0x80, 0, PutAll },
{ "STP", 0x0000001, 0xdb, 0, PutAll },
{ "STX", 0x000010c, 0x82, 1, PutAll },
{ "STY", 0x000002c, 0x80, 1, PutAll },
{ "STZ", 0x000006c, 0x04, 5, PutAll },
{ "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */
{ "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */
{ "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */
{ "TAX", 0x0000001, 0xaa, 0, PutAll },
{ "TAY", 0x0000001, 0xa8, 0, PutAll },
{ "TCD", 0x0000001, 0x5b, 0, PutAll },
{ "TCS", 0x0000001, 0x1b, 0, PutAll },
{ "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */
{ "TDC", 0x0000001, 0x7b, 0, PutAll },
{ "TRB", 0x000000c, 0x10, 1, PutAll },
{ "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */
{ "TSB", 0x000000c, 0x00, 1, PutAll },
{ "TSC", 0x0000001, 0x3b, 0, PutAll },
{ "TSX", 0x0000001, 0xba, 0, PutAll },
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TXY", 0x0000001, 0x9b, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll },
{ "TYX", 0x0000001, 0xbb, 0, PutAll },
{ "WAI", 0x0000001, 0xcb, 0, PutAll },
{ "XBA", 0x0000001, 0xeb, 0, PutAll },
{ "XCE", 0x0000001, 0xfb, 0, PutAll }
}
};
#ifdef SUNPLUS
/* Table for the SUNPLUS CPU */
#include "sunplus.inc"
#endif
/* The current CPU and an array with instruction tables */
static enum CPUType CPU = CPU_6502;
static const InsTable* InsTabs[CPU_COUNT] = {
(const InsTable*) &InsTab6502,
(const InsTable*) &InsTab65SC02,
(const InsTable*) &InsTab65816,
#ifdef SUNPLUS
(const InsTable*) &InsTabSunPlus,
#else
NULL,
#endif
};
const InsTable* InsTab = (const InsTable*) &InsTab6502;
/* Table to build the effective opcode from a base opcode and an addressing
* mode.
*/
unsigned char EATab [9][AMI_COUNT] = {
{ /* Table 0 */
0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
0x00
},
{ /* Table 1 */
0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
0x14, 0x1C, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
},
{ /* Table 2 */
0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
0x00
},
{ /* Table 3 */
0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
},
{ /* Table 4 */
0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
},
{ /* Table 5 */
0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
},
{ /* Table 6 */
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
},
{ /* Table 7 */
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
},
{ /* Table 8 */
0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00
},
};
/* Table that encodes the additional bytes for each instruction */
unsigned char ExtBytes [AMI_COUNT] = {
0, /* Implicit */
0, /* Accu */
1, /* Direct */
2, /* Absolute */
3, /* Absolute long */
1, /* Direct,X */
2, /* Absolute,X */
3, /* Absolute long,X */
1, /* Direct,Y */
2, /* Absolute,Y */
1, /* (Direct) */
2, /* (Absolute) */
1, /* [Direct] */
1, /* (Direct),Y */
1, /* [Direct],Y */
1, /* (Direct,X) */
2, /* (Absolute,X) */
1, /* Relative short */
2, /* Relative long */
1, /* r,s */
1, /* (r,s),y */
1, /* Immidiate accu */
1, /* Immidiate index */
1, /* Immidiate byte */
2 /* Blockmove */
};
/*****************************************************************************/
/* Handler functions */
/*****************************************************************************/
static long PutImmed8 (const InsDesc* Ins)
/* Parse and emit an immediate 8 bit instruction. Return the value of the
* operand if it's available and const.
*/
{
ExprNode* Expr;
ExprNode* Bank;
unsigned long AddrMode;
unsigned char OpCode;
long Val = -1;
/* Get the addressing mode used */
GetEA (&AddrMode, &Expr, &Bank);
/* From the possible addressing modes, remove the ones that are invalid
* for this instruction or CPU.
*/
AddrMode &= Ins->AddrMode;
/* If we have possible zero page addressing modes, and the expression
* involved (if any) is not in byte range, remove the zero page addressing
* modes.
*/
if (Expr && (AddrMode & AM_ZP) && !IsByteExpr (Expr)) {
AddrMode &= ~AM_ZP;
}
/* Check if we have any adressing modes left */
if (AddrMode == 0) {
Error (ERR_ILLEGAL_ADDR_MODE);
return -1;
}
AddrMode = BitFind (AddrMode);
/* Build the opcode */
OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
/* If we have an expression and it's const, get it's value */
if (Expr && IsConstExpr (Expr)) {
Val = GetExprVal (Expr);
}
/* Check how many extension bytes are needed and output the instruction */
switch (ExtBytes [AddrMode]) {
case 1:
Emit1 (OpCode, Expr);
break;
default:
Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
}
/* Return the expression value */
return Val;
}
static void PutPCRel8 (const InsDesc* Ins)
/* Handle branches with a 8 bit distance */
{
EmitPCRel (Ins->BaseCode, BranchExpr (2), 1);
}
static void PutPCRel16 (const InsDesc* Ins)
/* Handle branches with an 16 bit distance and PER */
{
EmitPCRel (Ins->BaseCode, BranchExpr (3), 2);
}
static void PutBlockMove (const InsDesc* Ins)
/* Handle the blockmove instructions */
{
Emit0 (Ins->BaseCode);
EmitByte (Expression ());
ConsumeComma ();
EmitByte (Expression ());
}
static void PutREP (const InsDesc* Ins)
/* Emit a REP instruction, track register sizes */
{
/* Use the generic handler */
long Val = PutImmed8 (Ins);
/* We track the status only for the 816 CPU and in smart mode */
if (CPU == CPU_65816 && SmartMode) {
/* Check the range for Val. */
if (Val < 0) {
/* We had an error */
Warning (WARN_CANNOT_TRACK_STATUS);
} else {
if (Val & 0x10) {
/* Index registers to 16 bit */
ExtBytes [AMI_IMM_INDEX] = 2;
}
if (Val & 0x20) {
/* Accu to 16 bit */
ExtBytes [AMI_IMM_ACCU] = 2;
}
}
}
}
static void PutSEP (const InsDesc* Ins)
/* Emit a SEP instruction, track register sizes */
{
/* Use the generic handler */
long Val = PutImmed8 (Ins);
/* We track the status only for the 816 CPU and in smart mode */
if (CPU == CPU_65816 && SmartMode) {
/* Check the range for Val. */
if (Val < 0) {
/* We had an error */
Warning (WARN_CANNOT_TRACK_STATUS);
} else {
if (Val & 0x10) {
/* Index registers to 8 bit */
ExtBytes [AMI_IMM_INDEX] = 1;
}
if (Val & 0x20) {
/* Accu to 8 bit */
ExtBytes [AMI_IMM_ACCU] = 1;
}
}
}
}
static void PutAll (const InsDesc* Ins)
/* Handle all other instructions */
{
ExprNode* Expr;
ExprNode* Bank;
unsigned long AddrModeSet;
unsigned char OpCode;
unsigned AddrMode;
unsigned long AddrModeBit;
/* Get the addressing mode used */
GetEA (&AddrModeSet, &Expr, &Bank);
/* From the possible addressing modes, remove the ones that are invalid
* for this instruction or CPU.
*/
AddrModeSet &= Ins->AddrMode;
/* If we have possible zero page addressing modes, and the expression
* involved (if any) is not in byte range, remove the zero page addressing
* modes.
*/
if (Expr && (AddrModeSet & AM_ZP) && !IsByteExpr (Expr)) {
AddrModeSet &= ~AM_ZP;
}
/* Check if we have any adressing modes left */
if (AddrModeSet == 0) {
Error (ERR_ILLEGAL_ADDR_MODE);
return;
}
AddrMode = BitFind (AddrModeSet);
/* Build the opcode */
OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
/* Check how many extension bytes are needed and output the instruction */
switch (ExtBytes [AddrMode]) {
case 0:
Emit0 (OpCode);
break;
case 1:
Emit1 (OpCode, Expr);
break;
case 2:
AddrModeBit = (1L << AddrMode);
if (CPU == CPU_65816 && (AddrModeBit & (AM_ABS | AM_ABS_X | AM_ABS_Y))) {
/* This is a 16 bit mode that uses an address. If in 65816,
* mode, force this address into 16 bit range to allow
* addressing inside a 64K segment.
*/
Emit2 (OpCode, ForceWordExpr (Expr));
} else {
Emit2 (OpCode, Expr);
}
break;
case 3:
if (Bank) {
/* Separate bank given */
Emit3b (OpCode, Expr, Bank);
} else {
/* One far argument */
Emit3 (OpCode, Expr);
}
break;
default:
Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
}
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static int CmpName (const void* Key, const void* Instr)
/* Compare function for bsearch */
{
return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
}
void SetCPU (enum CPUType NewCPU)
/* Set a new CPU */
{
/* Make sure the parameter is correct */
CHECK (NewCPU < CPU_COUNT);
/* Check if we have support for the new CPU, if so, use it */
if (InsTabs[NewCPU]) {
CPU = NewCPU;
InsTab = InsTabs[CPU];
} else {
Error (ERR_CPU_NOT_SUPPORTED);
}
}
enum CPUType GetCPU (void)
/* Return the current CPU */
{
return CPU;
}
int FindInstruction (const char* Ident)
/* Check if Ident is a valid mnemonic. If so, return the index in the
* instruction table. If not, return -1.
*/
{
const InsDesc* I;
char Key [sizeof (I->Mnemonic)];
/* Accept only strings with the right length */
if (strlen (Ident) != sizeof (I->Mnemonic)-1) {
/* Wrong length */
return -1;
}
/* Make a copy, and uppercase that copy */
Key [0] = toupper (Ident [0]);
Key [1] = toupper (Ident [1]);
Key [2] = toupper (Ident [2]);
Key [3] = '\0';
/* Search for the key */
I = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
if (I == 0) {
/* Not found */
return -1;
} else {
/* Found, return the entry */
return I - InsTab->Ins;
}
}
void HandleInstruction (unsigned Index)
/* Handle the mnemonic with the given index */
{
/* Safety check */
PRECONDITION (Index < InsTab->Count);
/* Skip the mnemonic token */
NextTok ();
/* Call the handler */
InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
}

156
src/ca65/instr.h Normal file
View File

@@ -0,0 +1,156 @@
/*****************************************************************************/
/* */
/* instr.h */
/* */
/* Instruction encoding for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef INSTR_H
#define INSTR_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Supported CPUs */
enum CPUType {
CPU_6502,
CPU_65C02,
CPU_65816,
CPU_SUNPLUS, /* Not in the freeware version - sorry */
CPU_COUNT /* Count of different CPUs */
};
/* Constants for the addressing mode. If an opcode is available in zero page
* and absolut adressing mode, both bits are set. When checking for valid
* modes, the zeropage bit is checked first. Similar, the implicit bit is set
* on accu adressing modes, so the 'A' for accu adressing is not needed (but
* may be specified).
* When assembling for the 6502 or 65C02, all addressing modes that are not
* available on these CPUs are removed before doing any checks.
*/
#define AM_IMPLICIT 0x00000003UL
#define AM_ACCU 0x00000002UL
#define AM_DIR 0x00000004UL
#define AM_ABS 0x00000008UL
#define AM_ABS_LONG 0x00000010UL
#define AM_DIR_X 0x00000020UL
#define AM_ABS_X 0x00000040UL
#define AM_ABS_LONG_X 0x00000080UL
#define AM_DIR_Y 0x00000100UL
#define AM_ABS_Y 0x00000200UL
#define AM_DIR_IND 0x00000400UL
#define AM_ABS_IND 0x00000800UL
#define AM_DIR_IND_LONG 0x00001000UL
#define AM_DIR_IND_Y 0x00002000UL
#define AM_DIR_IND_LONG_Y 0x00004000UL
#define AM_DIR_X_IND 0x00008000UL
#define AM_ABS_X_IND 0x00010000UL
#define AM_REL 0x00020000UL
#define AM_REL_LONG 0x00040000UL
#define AM_STACK_REL 0x00080000UL
#define AM_STACK_REL_IND_Y 0x00100000UL
#define AM_IMM 0x00E00000UL
#define AM_BLOCKMOVE 0x01000000UL
/* Bitmask for all ZP operations that have correspondent ABS ops */
#define AM_ZP (AM_DIR | AM_DIR_X | AM_DIR_Y | AM_DIR_IND | AM_DIR_X_IND)
/* Bit numbers and count */
#define AMI_IMM_ACCU 21
#define AMI_IMM_INDEX 22
#define AMI_COUNT 25
/* Description for one instruction */
typedef struct InsDesc_ InsDesc;
struct InsDesc_ {
char Mnemonic [4];
unsigned long AddrMode; /* Valid adressing modes */
unsigned char BaseCode; /* Base opcode */
unsigned char ExtCode; /* Number of ext code table */
void (*Emit) (const InsDesc*);/* Handler function */
};
/* An instruction table */
typedef struct InsTable_ InsTable;
struct InsTable_ {
unsigned Count; /* Number of intstructions */
InsDesc Ins[1]; /* Varying length */
};
/* The instruction table for the currently active CPU */
extern const InsTable* InsTab;
/* Table to build the effective opcode from a base opcode and an addressing
* mode.
*/
extern unsigned char EATab [9][AMI_COUNT];
/* Table that encodes the additional bytes for each instruction */
extern unsigned char ExtBytes [AMI_COUNT];
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void SetCPU (enum CPUType NewCPU);
/* Set a new CPU */
enum CPUType GetCPU (void);
/* Return the current CPU */
int FindInstruction (const char* Ident);
/* Check if Ident is a valid mnemonic. If so, return the index in the
* instruction table. If not, return -1.
*/
void HandleInstruction (unsigned Index);
/* Handle the mnemonic with the given index */
/* End of instr.h */
#endif

437
src/ca65/listing.c Normal file
View File

@@ -0,0 +1,437 @@
/*****************************************************************************/
/* */
/* listing.c */
/* */
/* Listing support for the ca65 crossassembler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "../common/segdefs.h"
#include "../common/version.h"
#include "error.h"
#include "fname.h"
#include "global.h"
#include "mem.h"
#include "objcode.h"
#include "listing.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Single linked list of lines */
ListLine* LineList = 0; /* List of listing lines */
ListLine* LineCur = 0; /* Current listing line */
ListLine* LineLast = 0; /* Last (current) listing line */
/* Page and other formatting */
int PageLength = -1; /* Length of a listing page */
static unsigned PageNumber = 1; /* Current listing page number */
static unsigned PageLines = 0; /* Current line on page */
static unsigned ListBytes = 12; /* Number of bytes to list for one line */
/* Switch the listing on/off */
static int ListingEnabled = 1; /* Enabled if > 0 */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void NewListingLine (const char* Line, unsigned char File, unsigned char Depth)
/* Create a new ListLine struct and insert it */
{
/* Store only if listing is enabled */
if (Listing) {
ListLine* L;
/* Get the length of the line */
unsigned Len = strlen (Line);
/* Ignore trailing newlines */
while (Len > 0 && Line[Len-1] == '\n') {
--Len;
}
/* Allocate memory */
L = Xmalloc (sizeof (ListLine) + Len);
/* Initialize the fields. */
L->Next = 0;
L->FragList = 0;
L->FragLast = 0;
L->PC = GetPC ();
L->Reloc = RelocMode;
L->File = File;
L->Depth = Depth;
L->Output = (ListingEnabled > 0);
L->ListBytes = (unsigned char) ListBytes;
memcpy (L->Line, Line, Len);
L->Line [Len] = '\0';
/* Insert the line into the list of lines */
if (LineList == 0) {
LineList = L;
} else {
LineLast->Next = L;
}
LineLast = L;
}
}
void EnableListing (void)
/* Enable output of lines to the listing */
{
if (Listing) {
/* If we're about to enable the listing, do this for the current line
* also, so we will see the source line that did this.
*/
if (ListingEnabled++ == 0) {
LineCur->Output = 1;
}
}
}
void DisableListing (void)
/* Disable output of lines to the listing */
{
if (Listing) {
if (ListingEnabled == 0) {
/* Cannot switch the listing off once more */
Error (ERR_COUNTER_UNDERFLOW);
} else {
--ListingEnabled;
}
}
}
void SetListBytes (int Bytes)
/* Set the maximum number of bytes listed for one line */
{
if (Bytes < 0) {
Bytes = 0; /* Encode "unlimited" as zero */
}
ListBytes = Bytes;
}
void InitListingLine (void)
/* Initialize the current listing line */
{
if (Listing) {
/* Make the last loaded line the current line */
LineCur = LineLast;
/* Set the values for this line */
CHECK (LineCur != 0);
LineCur->PC = GetPC ();
LineCur->Reloc = RelocMode;
LineCur->Output = (ListingEnabled > 0);
LineCur->ListBytes = (unsigned char) ListBytes;
}
}
static char* AddHex (char* S, unsigned Val)
/* Add a hex byte in ASCII to the given string and return the new pointer */
{
static const char HexTab [16] = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
*S++ = HexTab [(Val >> 4) & 0x0F];
*S++ = HexTab [Val & 0x0F];
return S;
}
static void PrintPageHeader (FILE* F, const ListLine* L)
/* Print the header for a new page. It is assumed that the given line is the
* last line of the previous page.
*/
{
/* Print the header on the new page */
fprintf (F,
"ca65 V%u.%u.%u - (C) Copyright 1998-2000 Ullrich von Bassewitz\n"
"Main file : %s\n"
"Current file: %s\n"
"\n",
VER_MAJOR, VER_MINOR, VER_PATCH,
InFile,
GetFileName (L->File));
/* Count pages, reset lines */
++PageNumber;
PageLines = 4;
}
static void PrintLine (FILE* F, const char* Header, const char* Line, const ListLine* L)
/* Print one line to the listing file, adding a newline and counting lines */
{
/* Print the given line */
fprintf (F, "%s%s\n", Header, Line);
/* Increment the current line */
++PageLines;
/* Switch to a new page if needed. Do not switch, if the current line is
* the last one, to avoid pages that consist of just the header.
*/
if (PageLength > 0 && PageLines >= PageLength && L->Next != 0) {
/* Do a formfeed */
putc ('\f', F);
/* Print the header on the new page */
PrintPageHeader (F, L);
}
}
static char* AddMult (char* S, char C, unsigned Count)
/* Add multiple instances of character C to S, return updated S. */
{
memset (S, C, Count);
return S + Count;
}
static char* MakeLineHeader (char* H, const ListLine* L)
/* Prepare the line header */
{
char Mode;
char Depth;
/* Setup the PC mode */
Mode = (L->Reloc)? 'r' : ' ';
/* Set up the include depth */
Depth = (L->Depth < 10)? L->Depth + '0' : '+';
/* Format the line */
sprintf (H, "%06lX%c %c", L->PC, Mode, Depth);
memset (H+9, ' ', LINE_HEADER_LEN-9);
/* Return the buffer */
return H;
}
void CreateListing (void)
/* Create the listing */
{
FILE* F;
Fragment* Frag;
ListLine* L;
char HeaderBuf [LINE_HEADER_LEN+1];
/* Create the name of the listing file if needed */
if (ListFile == 0) {
ListFile = MakeFilename (InFile, ListExt);
}
/* Open the real listing file */
F = fopen (ListFile, "w");
if (F == 0) {
Fatal (FAT_CANNOT_OPEN_LISTING, strerror (errno));
}
/* Reset variables, print the header for the first page */
PageNumber = 0;
PrintPageHeader (F, LineList);
/* Terminate the header buffer. The last byte will never get overwritten */
HeaderBuf [LINE_HEADER_LEN] = '\0';
/* Walk through all listing lines */
L = LineList;
while (L) {
char* Buf;
char* B;
unsigned Count;
unsigned I;
char* Line;
/* If we should not output this line, go to the next */
if (L->Output == 0) {
L = L->Next;
continue;
}
/* If we don't have a fragment list for this line, things are easy */
if (L->FragList == 0) {
PrintLine (F, MakeLineHeader (HeaderBuf, L), L->Line, L);
L = L->Next;
continue;
}
/* Count the number of bytes in the complete fragment list */
Count = 0;
Frag = L->FragList;
while (Frag) {
Count += Frag->Len;
Frag = Frag->LineList;
}
/* Allocate memory for the given number of bytes */
Buf = Xmalloc (Count*2+1);
/* Copy an ASCII representation of the bytes into the buffer */
B = Buf;
Frag = L->FragList;
while (Frag) {
/* Write data depending on the type */
switch (Frag->Type) {
case FRAG_LITERAL:
for (I = 0; I < Frag->Len; ++I) {
B = AddHex (B, Frag->V.Data[I]);
}
break;
case FRAG_EXPR:
case FRAG_SEXPR:
B = AddMult (B, 'r', Frag->Len*2);
break;
case FRAG_FILL:
B = AddMult (B, 'x', Frag->Len*2);
break;
default:
Internal ("Invalid fragment type: %u", Frag->Type);
}
/* Next fragment */
Frag = Frag->LineList;
}
/* Limit the number of bytes actually printed */
if (L->ListBytes != 0) {
/* Not unlimited */
if (Count > L->ListBytes) {
Count = L->ListBytes;
}
}
/* Output the data. The format of a listing line is:
*
* PPPPPPm I 11 22 33 44
*
* where
*
* PPPPPP is the PC
* m is the mode ('r' or empty)
* I is the include level
* 11 .. are code or data bytes
*/
Line = L->Line;
B = Buf;
while (Count) {
unsigned Chunk;
char* P;
/* Prepare the line header */
MakeLineHeader (HeaderBuf, L);
/* Get the number of bytes for the next line */
Chunk = Count;
if (Chunk > 4) {
Chunk = 4;
}
Count -= Chunk;
/* Increment the program counter. Since we don't need the PC stored
* in the LineList object for anything else, just increment this
* variable.
*/
L->PC += Chunk;
/* Copy the bytes into the line */
P = HeaderBuf + 11;
for (I = 0; I < Chunk; ++I) {
*P++ = *B++;
*P++ = *B++;
*P++ = ' ';
}
/* Output this line */
PrintLine (F, HeaderBuf, Line, L);
/* Don't output a line twice */
Line = "";
}
/* Delete the temporary buffer */
Xfree (Buf);
/* Next line */
L = L->Next;
}
/* Close the listing file */
(void) fclose (F);
}

116
src/ca65/listing.h Normal file
View File

@@ -0,0 +1,116 @@
/*****************************************************************************/
/* */
/* listing.h */
/* */
/* Listing support for the ca65 crossassembler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef LISTING_H
#define LISTING_H
#include "fragment.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Length of the header of a listing line */
#define LINE_HEADER_LEN 24
/* One listing line as it is stored in memory */
typedef struct ListLine_ ListLine;
struct ListLine_ {
ListLine* Next; /* Pointer to next line */
Fragment* FragList; /* List of fragments for this line */
Fragment* FragLast; /* Last entry in fragment list */
unsigned long PC; /* Program counter for this line */
unsigned char Reloc; /* Relocatable mode? */
unsigned char File; /* From which file is the line? */
unsigned char Depth; /* Include depth */
unsigned char Output; /* Should we output this line? */
unsigned char ListBytes; /* How many bytes at max? */
char Line[1]; /* Line with dynamic length */
};
/* Single linked list of lines */
extern ListLine* LineList; /* List of listing lines */
extern ListLine* LineCur; /* Current listing line */
extern ListLine* LineLast; /* Last listing line */
/* Page formatting */
#define MIN_PAGE_LEN 32
#define MAX_PAGE_LEN 127
extern int PageLength; /* Length of a listing page */
/* Byte for one listing line */
#define MIN_LIST_BYTES 4
#define MAX_LIST_BYTES 255
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void NewListingLine (const char* Line, unsigned char File, unsigned char Depth);
/* Create a new ListLine struct */
void EnableListing (void);
/* Enable output of lines to the listing */
void DisableListing (void);
/* Disable output of lines to the listing */
void SetListBytes (int Bytes);
/* Set the maximum number of bytes listed for one line */
void InitListingLine (void);
/* Initialize the current listing line */
void CreateListing (void);
/* Create the listing */
/* End of listing.h */
#endif

154
src/ca65/macpack.c Normal file
View File

@@ -0,0 +1,154 @@
/*****************************************************************************/
/* */
/* macpack.c */
/* */
/* Predefined macro packages for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "error.h"
#include "scanner.h"
#include "macpack.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Predefined packages */
static const char MacGeneric [] = /* Generic macros */
".macro add Arg\n"
" clc\n"
" adc Arg\n"
".endmacro\n\n"
".macro sub Arg\n"
" sec\n"
" sbc Arg\n"
".endmacro\n\n";
static const char MacLongBranch [] = /* Long branch macros */
".macro jeq Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" beq Target\n"
" .else\n"
" bne *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jne Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bne Target\n"
" .else\n"
" beq *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jmi Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bmi Target\n"
" .else\n"
" bpl *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jpl Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bpl Target\n"
" .else\n"
" bmi *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jcs Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bcs Target\n"
" .else\n"
" bcc *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jcc Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bcc Target\n"
" .else\n"
" bcs *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jvs Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bvs Target\n"
" .else\n"
" bvc *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n"
".macro jvc Target\n"
" .if .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bvc Target\n"
" .else\n"
" bvs *+5\n"
" jmp Target\n"
" .endif\n"
".endmacro\n\n";
/* Table with pointers to the different packages */
static const char* MacPackages [] = {
MacGeneric,
MacLongBranch,
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void InsertMacPack (unsigned Id)
/* Insert the macro package with the given id in the input stream */
{
/* Check the parameter */
CHECK (Id < sizeof (MacPackages) / sizeof (MacPackages [0]));
/* Insert the package */
NewInputData (MacPackages [Id], 0);
}

69
src/ca65/macpack.h Normal file
View File

@@ -0,0 +1,69 @@
/*****************************************************************************/
/* */
/* macpack.h */
/* */
/* Predefined macro packages for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef MACPACK_H
#define MACPACK_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Constants for the predefined packages */
#define MAC_GENERIC 0
#define MAC_LONGBRANCH 1
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void InsertMacPack (unsigned Id);
/* Insert the macro package with the given id in the input stream */
/* End of macpack.h */
#endif

769
src/ca65/macro.c Normal file
View File

@@ -0,0 +1,769 @@
/*****************************************************************************/
/* */
/* macro.c */
/* */
/* Macros for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "../common/hashstr.h"
#include "mem.h"
#include "error.h"
#include "scanner.h"
#include "toknode.h"
#include "pseudo.h"
#include "macro.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Struct that describes an identifer (macro param, local list) */
typedef struct IdDesc_ IdDesc;
struct IdDesc_ {
IdDesc* Next; /* Linked list */
char Id [1]; /* Identifier, dynamically allocated */
};
/* Struct that describes a macro definition */
typedef struct Macro_ Macro;
struct Macro_ {
Macro* Next; /* Next macro with same hash */
Macro* List; /* List of all macros */
unsigned LocalCount; /* Count of local symbols */
IdDesc* Locals; /* List of local symbols */
unsigned ParamCount; /* Parameter count of macro */
IdDesc* Params; /* Identifiers of macro parameters */
unsigned TokCount; /* Number of tokens for this macro */
TokNode* TokRoot; /* Root of token list */
TokNode* TokLast; /* Pointer to last token in list */
unsigned char Style; /* Macro style */
char Name [1]; /* Macro name, dynamically allocated */
};
/* Macro hash table */
#define HASHTAB_SIZE 117
static Macro* MacroTab [HASHTAB_SIZE];
/* Global macro data */
static Macro* MacroRoot = 0; /* List of all macros */
/* Structs that holds data for a macro expansion */
typedef struct MacExp_ MacExp;
struct MacExp_ {
MacExp* Next; /* Pointer to next expansion */
Macro* M; /* Which macro do we expand? */
TokNode* Exp; /* Pointer to current token */
TokNode* Final; /* Pointer to final token */
unsigned LocalStart; /* Start of counter for local symbol names */
unsigned ParamCount; /* Number of actual parameters */
TokNode** Params; /* List of actual parameters */
TokNode* ParamExp; /* Node for expanding parameters */
};
/* Data for macro expansions */
#define MAX_MACRO_EXPANSIONS 255
static unsigned MacroNesting = 0;
static MacExp* CurMac = 0;
static unsigned LocalName = 0;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static IdDesc* NewIdDesc (const char* Id)
/* Create a new IdDesc, initialize and return it */
{
/* Allocate memory */
unsigned Len = strlen (Id);
IdDesc* I = Xmalloc (sizeof (IdDesc) + Len);
/* Initialize the struct */
I->Next = 0;
memcpy (I->Id, Id, Len);
I->Id [Len] = '\0';
/* Return the new struct */
return I;
}
static Macro* NewMacro (const char* Name, unsigned HashVal, unsigned char Style)
/* Generate a new macro entry, initialize and return it */
{
/* Allocate memory */
unsigned Len = strlen (Name);
Macro* M = Xmalloc (sizeof (Macro) + Len);
/* Initialize the macro struct */
M->LocalCount = 0;
M->ParamCount = 0;
M->Params = 0;
M->TokCount = 0;
M->TokRoot = 0;
M->TokLast = 0;
M->Style = Style;
memcpy (M->Name, Name, Len);
M->Name [Len] = '\0';
/* Insert the macro into the global macro list */
M->List = MacroRoot;
MacroRoot = M;
/* Insert the macro into the hash table */
M->Next = MacroTab [HashVal];
MacroTab [HashVal] = M;
/* Return the new macro struct */
return M;
}
static MacExp* NewMacExp (Macro* M)
/* Create a new expansion structure for the given macro */
{
unsigned I;
/* Allocate memory */
MacExp* E = Xmalloc (sizeof (MacExp));
/* Initialize the data */
E->M = M;
E->Exp = M->TokRoot;
E->Final = 0;
E->LocalStart = LocalName;
LocalName += M->LocalCount;
E->ParamCount = 0;
E->Params = Xmalloc (M->ParamCount * sizeof (TokNode*));
E->ParamExp = 0;
for (I = 0; I < M->ParamCount; ++I) {
E->Params [I] = 0;
}
/* And return it... */
return E;
}
static void MacInsertExp (MacExp* E)
/* Insert a macro expansion into the list */
{
E->Next = CurMac;
CurMac = E;
++MacroNesting;
}
static void FreeMacExp (void)
/* Remove and free the current macro expansion */
{
unsigned I;
MacExp* E;
/* Free the parameter list */
for (I = 0; I < CurMac->ParamCount; ++I) {
Xfree (CurMac->Params [I]);
}
Xfree (CurMac->Params);
/* Free the final token if we have one */
if (CurMac->Final) {
FreeTokNode (CurMac->Final);
}
/* Reset the list pointer */
E = CurMac;
CurMac = E->Next;
--MacroNesting;
/* Free the structure itself */
Xfree (E);
}
static void MacSkipDef (unsigned Style)
/* Skip a macro definition */
{
if (Style == MAC_STYLE_CLASSIC) {
/* Skip tokens until we reach the final .endmacro */
while (Tok != TOK_ENDMACRO && Tok != TOK_EOF) {
NextTok ();
}
if (Tok != TOK_EOF) {
SkipUntilSep ();
} else {
Error (ERR_ENDMACRO_EXPECTED);
}
} else {
/* Skip until end of line */
SkipUntilSep ();
}
}
static Macro* MacFind (const char* Name, unsigned HashVal)
/* Search for a macro in the hash table */
{
/* Search for the identifier */
Macro* M = MacroTab [HashVal];
while (M) {
if (strcmp (Name, M->Name) == 0) {
return M;
}
M = M->Next;
}
return 0;
}
void MacDef (unsigned Style)
/* Parse a macro definition */
{
Macro* M;
TokNode* T;
unsigned HashVal;
int HaveParams;
/* We expect a macro name here */
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
MacSkipDef (Style);
return;
}
/* Generate the hash value */
HashVal = HashStr (SVal) % HASHTAB_SIZE;
/* Did we already define that macro? */
if (MacFind (SVal, HashVal) != 0) {
/* Macro is already defined */
Error (ERR_SYM_ALREADY_DEFINED, SVal);
/* Skip tokens until we reach the final .endmacro */
MacSkipDef (Style);
return;
}
/* Define the macro */
M = NewMacro (SVal, HashVal, Style);
NextTok ();
/* If we have a DEFINE style macro, we may have parameters in braces,
* otherwise we may have parameters without braces.
*/
if (Style == MAC_STYLE_CLASSIC) {
HaveParams = 1;
} else {
if (Tok == TOK_LPAREN) {
HaveParams = 1;
NextTok ();
} else {
HaveParams = 0;
}
}
/* Parse the parameter list */
if (HaveParams) {
while (Tok == TOK_IDENT) {
/* Create a struct holding the identifier */
IdDesc* I = NewIdDesc (SVal);
/* Insert the struct into the list, checking for duplicate idents */
if (M->ParamCount == 0) {
M->Params = I;
} else {
IdDesc* List = M->Params;
while (1) {
if (strcmp (List->Id, SVal) == 0) {
Error (ERR_SYM_ALREADY_DEFINED, SVal);
}
if (List->Next == 0) {
break;
} else {
List = List->Next;
}
}
List->Next = I;
}
++M->ParamCount;
/* Skip the name */
NextTok ();
/* Maybe there are more params... */
if (Tok == TOK_COMMA) {
NextTok ();
} else {
break;
}
}
}
/* For class macros, we expect a separator token, for define style macros,
* we expect the closing paren.
*/
if (Style == MAC_STYLE_CLASSIC) {
ConsumeSep ();
} else if (HaveParams) {
ConsumeRParen ();
}
/* Preparse the macro body. We will read the tokens until we reach end of
* file, or a .endmacro (or end of line for DEFINE style macros) and store
* them into an token list internal to the macro. For classic macros, there
* the .LOCAL command is detected and removed at this time.
*/
while (1) {
/* Check for end of macro */
if (Style == MAC_STYLE_CLASSIC) {
/* In classic macros, only .endmacro is allowed */
if (Tok == TOK_ENDMACRO) {
/* Done */
break;
}
/* May not have end of file in a macro definition */
if (Tok == TOK_EOF) {
Error (ERR_ENDMACRO_EXPECTED);
return;
}
} else {
/* Accept a newline or end of file for new style macros */
if (Tok == TOK_SEP || Tok == TOK_EOF) {
break;
}
}
/* Check for a .LOCAL declaration */
if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
while (1) {
IdDesc* I;
/* Skip .local or comma */
NextTok ();
/* Need an identifer */
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
SkipUntilSep ();
break;
}
/* Put the identifier into the locals list and skip it */
I = NewIdDesc (SVal);
I->Next = M->Locals;
M->Locals = I;
++M->LocalCount;
NextTok ();
/* Check for end of list */
if (Tok != TOK_COMMA) {
break;
}
}
/* We need end of line after the locals */
ConsumeSep ();
continue;
}
/* Create a token node for the current token */
T = NewTokNode ();
/* If the token is an ident, check if it is a local parameter */
if (Tok == TOK_IDENT) {
unsigned Count = 0;
IdDesc* I = M->Params;
while (I) {
if (strcmp (I->Id, SVal) == 0) {
/* Local param name, replace it */
T->Tok = TOK_MACPARAM;
T->IVal = Count;
break;
}
++Count;
I = I->Next;
}
}
/* Insert the new token in the list */
if (M->TokCount == 0) {
/* First token */
M->TokRoot = M->TokLast = T;
} else {
/* We have already tokens */
M->TokLast->Next = T;
M->TokLast = T;
}
++M->TokCount;
/* Read the next token */
NextTok ();
}
/* Skip the .endmacro for a classic macro */
if (Style == MAC_STYLE_CLASSIC) {
NextTok ();
}
}
static void StartExpClassic (Macro* M)
/* Start expanding the classic macro M */
{
MacExp* E;
/* Skip the macro name */
NextTok ();
/* Create a structure holding expansion data */
E = NewMacExp (M);
/* Read the actual parameters */
while (Tok != TOK_SEP && Tok != TOK_EOF) {
TokNode* Last;
/* Check for maximum parameter count */
if (E->ParamCount >= M->ParamCount) {
Error (ERR_TOO_MANY_PARAMS);
SkipUntilSep ();
break;
}
/* Read tokens for one parameter, accept empty params */
Last = 0;
while (Tok != TOK_COMMA && Tok != TOK_SEP) {
TokNode* T;
/* Check for end of file */
if (Tok == TOK_EOF) {
Error (ERR_SYNTAX);
return;
}
/* Get the next token in a node */
T = NewTokNode ();
/* Insert it into the list */
if (Last == 0) {
E->Params [E->ParamCount] = T;
} else {
Last->Next = T;
}
Last = T;
/* And skip it... */
NextTok ();
}
/* One parameter more */
++E->ParamCount;
/* Check for a comma */
if (Tok == TOK_COMMA) {
NextTok ();
} else {
break;
}
}
/* Insert the newly created structure into the expansion list */
MacInsertExp (E);
}
static void StartExpDefine (Macro* M)
/* Start expanding a DEFINE style macro */
{
/* Create a structure holding expansion data */
MacExp* E = NewMacExp (M);
/* A define style macro must be called with as many actual parameters
* as there are formal ones. Get the parameter count.
*/
unsigned Count = M->ParamCount;
/* Skip the current token */
NextTok ();
/* Read the actual parameters */
while (Count--) {
TokNode* Last;
/* Check if there is really a parameter */
if (Tok == TOK_SEP || Tok == TOK_EOF || Tok == TOK_COMMA) {
Error (ERR_MACRO_PARAM_EXPECTED);
SkipUntilSep ();
return;
}
/* Read tokens for one parameter */
Last = 0;
do {
TokNode* T;
/* Get the next token in a node */
T = NewTokNode ();
/* Insert it into the list */
if (Last == 0) {
E->Params [E->ParamCount] = T;
} else {
Last->Next = T;
}
Last = T;
/* And skip it... */
NextTok ();
} while (Tok != TOK_COMMA && Tok != TOK_SEP && Tok != TOK_EOF);
/* One parameter more */
++E->ParamCount;
/* Check for a comma */
if (Count > 0) {
if (Tok == TOK_COMMA) {
NextTok ();
} else {
Error (ERR_COMMA_EXPECTED);
}
}
}
/* Macro expansion will overwrite the current token. This is a problem
* for define style macros since these are called from the scanner level.
* To avoid it, remember the current token and re-insert it if macro
* expansion is done.
*/
E->Final = NewTokNode ();
/* Insert the newly created structure into the expansion list */
MacInsertExp (E);
}
void MacExpandStart (void)
/* Start expanding the macro in SVal */
{
Macro* M;
/* Beware of runoff macros */
if (MacroNesting == MAX_MACRO_EXPANSIONS) {
Fatal (FAT_MACRO_NESTING);
}
/* Search for the macro */
M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
CHECK (M != 0);
/* Call the apropriate subroutine */
switch (M->Style) {
case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
case MAC_STYLE_DEFINE: StartExpDefine (M); break;
default: Internal ("Invalid macro style: %d", M->Style);
}
}
int MacExpand (void)
/* If we're currently expanding a macro, set the the scanner token and
* attribute to the next value and return true. If we are not expanding
* a macro, return false.
*/
{
if (MacroNesting == 0) {
/* Not expanding a macro */
return 0;
}
/* We're expanding a macro. Check if we are expanding one of the
* macro parameters.
*/
if (CurMac->ParamExp) {
/* Ok, use token from parameter list */
TokSet (CurMac->ParamExp);
/* Set pointer to next token */
CurMac->ParamExp = CurMac->ParamExp->Next;
/* Done */
return 1;
} else if (CurMac->Exp) {
/* We're not expanding a parameter, use next macro token */
TokSet (CurMac->Exp);
/* Set pointer to next token */
CurMac->Exp = CurMac->Exp->Next;
/* Is it a request for actual parameter count? */
if (Tok == TOK_PARAMCOUNT) {
Tok = TOK_INTCON;
IVal = CurMac->ParamCount;
return 1;
}
/* Is it an .exitmacro command? */
if (Tok == TOK_EXITMACRO) {
/* Forced exit from macro expansion */
FreeMacExp ();
return MacExpand ();
}
/* Is it the name of a macro parameter? */
if (Tok == TOK_MACPARAM) {
/* Start to expand the parameter token list */
CurMac->ParamExp = CurMac->Params [IVal];
/* Recursive call to expand the parameter */
return MacExpand ();
}
/* If it's an identifier, it may in fact be a local symbol */
if (Tok == TOK_IDENT && CurMac->M->LocalCount) {
/* Search for the local symbol in the list */
unsigned Index = 0;
IdDesc* I = CurMac->M->Locals;
while (I) {
if (strcmp (SVal, I->Id) == 0) {
/* This is in fact a local symbol, change the name */
sprintf (SVal, "___%04X__", CurMac->LocalStart + Index);
break;
}
/* Next symbol */
++Index;
I = I->Next;
}
/* Done */
return 1;
}
/* The token was successfully set */
return 1;
} else if (CurMac->Final) {
/* Set the final token and remove it */
TokSet (CurMac->Final);
FreeTokNode (CurMac->Final);
CurMac->Final = 0;
/* The token was successfully set */
return 1;
} else {
/* End of macro expansion */
FreeMacExp ();
return MacExpand ();
}
}
void MacAbort (void)
/* Abort the current macro expansion */
{
/* Must have an expansion */
CHECK (CurMac != 0);
/* Free current structure */
FreeMacExp ();
}
int IsMacro (const char* Name)
/* Return true if the given name is the name of a macro */
{
return MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE) != 0;
}
int IsDefine (const char* Name)
/* Return true if the given name is the name of a define style macro */
{
Macro* M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
return (M != 0 && M->Style == MAC_STYLE_DEFINE);
}
int InMacExpansion (void)
/* Return true if we're currently expanding a macro */
{
return MacroNesting != 0;
}

90
src/ca65/macro.h Normal file
View File

@@ -0,0 +1,90 @@
/*****************************************************************************/
/* */
/* macro.h */
/* */
/* Macros for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef MACRO_H
#define MACRO_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Macro styles */
#define MAC_STYLE_CLASSIC 0
#define MAC_STYLE_DEFINE 1
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void MacDef (unsigned Style);
/* Parse a macro definition */
void MacExpandStart (void);
/* Start expanding the macro in SVal */
int MacExpand (void);
/* If we're currently expanding a macro, set the the scanner token and
* attribute to the next value and return true. If we are not expanding
* a macro, return false.
*/
void MacAbort (void);
/* Abort the current macro expansion */
int IsMacro (const char* Name);
/* Return true if the given name is the name of a macro */
int IsDefine (const char* Name);
/* Return true if the given name is the name of a define style macro */
int InMacExpansion (void);
/* Return true if we're currently expanding a macro */
/* End of macro.h */
#endif

564
src/ca65/main.c Normal file
View File

@@ -0,0 +1,564 @@
/*****************************************************************************/
/* */
/* main.c */
/* */
/* Main program for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "../common/version.h"
#include "error.h"
#include "expr.h"
#include "global.h"
#include "instr.h"
#include "listing.h"
#include "macro.h"
#include "mem.h"
#include "objcode.h"
#include "objfile.h"
#include "options.h"
#include "pseudo.h"
#include "scanner.h"
#include "symtab.h"
#include "ulabel.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static void Usage (void)
/* Print usage information and exit */
{
fprintf (stderr,
"Usage: %s [options] file\n"
"Options:\n"
"\t-g\t\tAdd debug info to object file\n"
"\t-i\t\tIgnore case of symbols\n"
"\t-l\t\tCreate a listing if assembly was ok\n"
"\t-o name\t\tName the output file\n"
"\t-s\t\tEnable smart mode\n"
"\t-v\t\tIncrease verbosity\n"
"\t-D name[=value]\tDefine a symbol\n"
"\t-U\t\tMark unresolved symbols as import\n"
"\t-V\t\tPrint the assembler version\n"
"\t-W n\t\tSet warning level n\n"
"\t--cpu type\tSet cpu type\n"
"\t--pagelength n\tSet the page length for the listing\n"
"\t--smart\t\tEnable smart mode\n",
ProgName);
exit (EXIT_FAILURE);
}
static void UnknownOption (const char* Arg)
/* Print an error about an unknown option. Print usage information and exit */
{
fprintf (stderr, "Unknown option: %s\n", Arg);
Usage ();
}
static void NeedArg (const char* Arg)
/* Print an error about a missing option argument and exit. */
{
fprintf (stderr, "Option requires an argument: %s\n", Arg);
exit (EXIT_FAILURE);
}
static void InvSym (const char* Def)
/* Print an error about an invalid symbol definition and die */
{
fprintf (stderr, "Invalid symbol definition: `%s'\n", Def);
exit (EXIT_FAILURE);
}
static const char* GetArg (int* ArgNum, char* argv [], unsigned Len)
/* Get an option argument */
{
const char* Arg = argv [*ArgNum];
if (Arg [Len] != '\0') {
/* Argument appended */
return Arg + Len;
} else {
/* Separate argument */
Arg = argv [*ArgNum + 1];
if (Arg == 0) {
/* End of arguments */
NeedArg (argv [*ArgNum]);
}
++(*ArgNum);
return Arg;
}
}
static void SetOptions (void)
/* Set the option for the translator */
{
char Buf [256];
/* Set the translator */
sprintf (Buf, "ca65 V%u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH);
OptTranslator (Buf);
/* Set date and time */
OptDateTime ((unsigned long) time(0));
}
static void DefineSymbol (const char* Def)
/* Define a symbol from the command line */
{
const char* P;
unsigned I;
long Val;
char SymName [MAX_STR_LEN+1];
/* The symbol must start with a character or underline */
if (Def [0] != '_' && !isalpha (Def [0])) {
InvSym (Def);
}
P = Def;
/* Copy the symbol, checking the rest */
I = 0;
while (isalnum (*P) || *P == '_') {
if (I <= MAX_STR_LEN) {
SymName [I++] = *P;
}
++P;
}
SymName [I] = '\0';
/* Do we have a value given? */
if (*P != '=') {
if (*P != '\0') {
InvSym (Def);
}
Val = 0;
} else {
/* We have a value */
++P;
if (*P == '$') {
++P;
if (sscanf (P, "%lx", &Val) != 1) {
InvSym (Def);
}
} else {
if (sscanf (P, "%li", &Val) != 1) {
InvSym (Def);
}
}
}
/* Check if have already a symbol with this name */
if (SymIsDef (SymName)) {
fprintf (stderr, "`%s' is already defined\n", SymName);
exit (EXIT_FAILURE);
}
/* Define the symbol */
SymDef (SymName, LiteralExpr (Val), 0);
}
static void OptCPU (const char* Opt, const char* Arg)
/* Handle the --cpu option */
{
if (Arg == 0) {
NeedArg (Opt);
}
if (strcmp (Arg, "6502") == 0) {
SetCPU (CPU_6502);
} else if (strcmp (Arg, "65C02") == 0) {
SetCPU (CPU_65C02);
} else if (strcmp (Arg, "65816") == 0) {
SetCPU (CPU_65816);
#ifdef SUNPLUS
} else if (strcmp (Arg, "sunplus") == 0) {
SetCPU (CPU_SUNPLUS);
#endif
} else {
fprintf (stderr, "Invalid CPU: `%s'\n", Arg);
exit (EXIT_FAILURE);
}
}
static void OptPageLength (const char* Opt, const char* Arg)
/* Handle the --pagelength option */
{
int Len;
if (Arg == 0) {
NeedArg (Opt);
}
Len = atoi (Arg);
if (Len != -1 && (Len < MIN_PAGE_LEN || Len > MAX_PAGE_LEN)) {
fprintf (stderr, "Invalid page length: %d\n", Len);
exit (EXIT_FAILURE);
}
PageLength = Len;
}
static void OptSmart (const char* Opt)
/* Handle the -s/--smart options */
{
SmartMode = 1;
}
static void LongOption (int* ArgNum, char* argv [])
/* Handle a long command line option */
{
const char* Opt = argv [*ArgNum];
const char* Arg = argv [*ArgNum+1];
if (strcmp (Opt, "--cpu") == 0) {
OptCPU (Opt, Arg);
++(*ArgNum);
} else if (strcmp (Opt, "--pagelength") == 0) {
OptPageLength (Opt, Arg);
++(*ArgNum);
} else if (strcmp (Opt, "--smart") == 0) {
OptSmart (Opt);
} else {
UnknownOption (Opt);
}
}
static void OneLine (void)
/* Assemble one line */
{
char Ident [MAX_STR_LEN+1];
int Done = 0;
/* Initialize the listing line */
InitListingLine ();
if (Tok == TOK_COLON) {
/* An unnamed label */
ULabDef ();
NextTok ();
}
/* Assemble the line */
if (Tok == TOK_IDENT) {
/* Is it a macro? */
if (IsMacro (SVal)) {
/* Yes, start a macro expansion */
MacExpandStart ();
Done = 1;
} else {
/* No, label. Remember the identifier, then skip it */
int HadWS = WS; /* Did we have whitespace before the ident? */
strcpy (Ident, SVal);
NextTok ();
/* If a colon follows, this is a label definition. If there
* is no colon, it's an assignment.
*/
if (Tok == TOK_EQ) {
/* Skip the '=' */
NextTok ();
/* Define the symbol with the expression following the
* '='
*/
SymDef (Ident, Expression (), 0);
/* Don't allow anything after a symbol definition */
Done = 1;
} else {
/* Define a label */
SymDef (Ident, CurrentPC (), IsZPSeg ());
/* Skip the colon. If NoColonLabels is enabled, allow labels
* without a colon if there is no whitespace before the
* identifier.
*/
if (Tok != TOK_COLON) {
if (HadWS || !NoColonLabels) {
Error (ERR_COLON_EXPECTED);
}
if (Tok == TOK_NAMESPACE) {
/* Smart :: handling */
NextTok ();
}
} else {
/* Skip the colon */
NextTok ();
}
}
}
}
if (!Done) {
if (TokIsPseudo (Tok)) {
/* A control command, IVal is index into table */
HandlePseudo ();
} else if (Tok == TOK_MNEMO) {
/* A mnemonic - assemble one instruction */
HandleInstruction (IVal);
} else if (Tok == TOK_IDENT && IsMacro (SVal)) {
/* A macro expansion */
MacExpandStart ();
}
}
/* Calling InitListingLine again here is part of a hack that introduces
* enough magic to make the PC output in the listing work.
*/
InitListingLine ();
/* Line separator must come here */
ConsumeSep ();
}
static void Assemble (void)
/* Start the ball rolling ... */
{
/* Prime the pump */
NextTok ();
/* Assemble lines until end of file */
while (Tok != TOK_EOF) {
OneLine ();
}
}
static void CreateObjFile (void)
/* Create the object file */
{
/* Open the object, write the header */
ObjOpen ();
/* Write the object file options */
WriteOptions ();
/* Write the list of input files */
WriteFiles ();
/* Write the segment data to the file */
WriteSegments ();
/* Write the import list */
WriteImports ();
/* Write the export list */
WriteExports ();
/* Write debug symbols if requested */
WriteDbgSyms ();
/* Write an updated header and close the file */
ObjClose ();
}
int main (int argc, char* argv [])
/* Assembler main program */
{
int I;
/* Set the program name */
ProgName = argv [0];
/* We must have a file name */
if (argc < 2) {
Usage ();
}
/* Enter the base lexical level. We must do that here, since we may
* define symbols using -D.
*/
SymEnterLevel ();
/* Check the parameters */
I = 1;
while (I < argc) {
/* Get the argument */
const char* Arg = argv [I];
/* Check for an option */
if (Arg [0] == '-') {
switch (Arg [1]) {
case '-':
LongOption (&I, argv);
break;
case 'g':
DbgSyms = 1;
break;
case 'i':
IgnoreCase = 1;
break;
case 'l':
Listing = 1;
break;
case 'o':
OutFile = GetArg (&I, argv, 2);
break;
case 's':
OptSmart (Arg);
break;
case 'v':
++Verbose;
break;
case 'D':
DefineSymbol (GetArg (&I, argv, 2));
break;
case 'U':
AutoImport = 1;
break;
case 'V':
fprintf (stderr,
"ca65 V%u.%u.%u - (C) Copyright 1998-2000 Ullrich von Bassewitz\n",
VER_MAJOR, VER_MINOR, VER_PATCH);
break;
case 'W':
WarnLevel = atoi (GetArg (&I, argv, 2));
break;
default:
UnknownOption (Arg);
break;
}
} else {
/* Filename. Check if we already had one */
if (InFile) {
fprintf (stderr, "Don't know what to do with `%s'\n", Arg);
Usage ();
} else {
InFile = Arg;
}
}
/* Next argument */
++I;
}
/* Do we have an input file? */
if (InFile == 0) {
fprintf (stderr, "No input file\n");
exit (EXIT_FAILURE);
}
/* Initialize the scanner, open the input file */
InitScanner (InFile);
/* Define the default options */
SetOptions ();
/* Assemble the input */
Assemble ();
/* If we didn't have any errors, check the unnamed labels */
if (ErrorCount == 0) {
ULabCheck ();
}
/* If we didn't have any errors, check the symbol table */
if (ErrorCount == 0) {
SymCheck ();
}
/* If we didn't have any errors, check and resolve the segment data */
if (ErrorCount == 0) {
SegCheck ();
}
/* Dump the data */
if (Verbose >= 2) {
SymDump (stdout);
SegDump ();
}
/* If we didn't have any errors, create the object and listing files */
if (ErrorCount == 0) {
CreateObjFile ();
if (Listing) {
CreateListing ();
}
}
/* Close the input file */
DoneScanner ();
/* Return an apropriate exit code */
return (ErrorCount == 0)? EXIT_SUCCESS : EXIT_FAILURE;
}

63
src/ca65/make/gcc.mak Normal file
View File

@@ -0,0 +1,63 @@
#
# gcc Makefile for a65, link65 & libr65
#
CFLAGS = -g -O2 -Wall
CC = gcc
LDFLAGS =
OBJS = condasm.o \
ea.o \
error.o \
expr.o \
fname.o \
fragment.o \
global.o \
instr.o \
listing.o \
macpack.o \
macro.o \
main.o \
mem.o \
objcode.o \
objfile.o \
options.o \
pseudo.o \
scanner.o \
strexpr.o \
symtab.o \
toknode.o \
ulabel.o
LIBS = ../common/common.a
EXECS = ca65
.PHONY: all
ifeq (.depend,$(wildcard .depend))
all : $(EXECS)
include .depend
else
all: depend
@$(MAKE) -f make/gcc.mak all
endif
ca65: $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
clean:
rm -f *~ core *.lst
zap: clean
rm -f *.o $(EXECS) .depend
# ------------------------------------------------------------------------------
# Make the dependencies
.PHONY: depend dep
depend dep: $(OBJS:.o=.c)
@echo "Creating dependency information"
$(CC) -MM $^ > .depend

140
src/ca65/make/watcom.mak Normal file
View File

@@ -0,0 +1,140 @@
#
# CA65 Makefile for the Watcom compiler
#
# ------------------------------------------------------------------------------
# Generic stuff
.AUTODEPEND
.SUFFIXES .ASM .C .CC .CPP
.SWAP
AR = WLIB
LD = WLINK
!if !$d(TARGET)
!if $d(__OS2__)
TARGET = OS2
!else
TARGET = NT
!endif
!endif
# target specific macros.
!if $(TARGET)==OS2
# --------------------- OS2 ---------------------
SYSTEM = os2v2
CC = WCC386
CCCFG = -bt=$(TARGET) -d1 -onatx -zp4 -5 -zq -w2
!elif $(TARGET)==DOS32
# -------------------- DOS4G --------------------
SYSTEM = dos4g
CC = WCC386
CCCFG = -bt=$(TARGET) -d1 -onatx -zp4 -5 -zq -w2
!elif $(TARGET)==DOS
# --------------------- DOS ---------------------
SYSTEM = dos
CC = WCC
CCCFG = -bt=$(TARGET) -d1 -onatx -zp2 -2 -ml -zq -w2
!elif $(TARGET)==NT
# --------------------- NT ----------------------
SYSTEM = nt
CC = WCC386
CCCFG = -bt=$(TARGET) -d1 -onatx -zp4 -5 -zq -w2
!else
!error
!endif
# ------------------------------------------------------------------------------
# Implicit rules
.c.obj:
$(CC) $(CCCFG) $<
# ------------------------------------------------------------------------------
# All library OBJ files
OBJS = condasm.obj \
ea.obj \
error.obj \
expr.obj \
fname.obj \
fragment.obj \
global.obj \
instr.obj \
listing.obj \
macpack.obj \
macro.obj \
main.obj \
mem.obj \
objcode.obj \
objfile.obj \
options.obj \
pseudo.obj \
scanner.obj \
strexpr.obj \
symtab.obj \
toknode.obj \
ulabel.obj
LIBS = ..\common\common.lib
# ------------------------------------------------------------------------------
# Main targets
all: ca65
ca65: ca65.exe
# ------------------------------------------------------------------------------
# Other targets
ca65.exe: $(OBJS) $(LIBS)
$(LD) system $(SYSTEM) @&&|
DEBUG ALL
OPTION QUIET
NAME $<
FILE condasm.obj
FILE ea.obj
FILE error.obj
FILE expr.obj
FILE fname.obj
FILE fragment.obj
FILE global.obj
FILE instr.obj
FILE listing.obj
FILE macpack.obj
FILE macro.obj
FILE main.obj
FILE mem.obj
FILE objcode.obj
FILE objfile.obj
FILE options.obj
FILE pseudo.obj
FILE scanner.obj
FILE strexpr.obj
FILE symtab.obj
FILE toknode.obj
FILE ulabel.obj
LIBRARY ..\common\common.lib
|
clean:
@if exist *.obj del *.obj
@if exist ca65.exe del ca65.exe
strip:
@-wstrip ca65.exe

84
src/ca65/mem.c Normal file
View File

@@ -0,0 +1,84 @@
/*****************************************************************************/
/* */
/* mem.c */
/* */
/* Memory allocation for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "mem.h"
/*****************************************************************************/
/* code */
/*****************************************************************************/
void* Xmalloc (size_t size)
/* Allocate memory, check for out of memory condition. Do some debugging */
{
void* p;
p = malloc (size);
if (p == 0 && size != 0) {
Fatal (FAT_OUT_OF_MEMORY);
}
/* Return a pointer to the block */
return p;
}
void Xfree (const void* block)
/* Free the block, do some debugging */
{
free ((void*) block);
}
char* StrDup (const char* s)
/* Duplicate a string on the heap. The function checks for out of memory */
{
unsigned len;
len = strlen (s) + 1;
return memcpy (Xmalloc (len), s, len);
}

67
src/ca65/mem.h Normal file
View File

@@ -0,0 +1,67 @@
/*****************************************************************************/
/* */
/* mem.h */
/* */
/* Memory allocation for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef MEM_H
#define MEM_H
#include <stddef.h>
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void* Xmalloc (size_t size);
/* Allocate memory, check for out of memory condition. Do some debugging */
void Xfree (const void* block);
/* Free the block, do some debugging */
char* StrDup (const char* s);
/* Duplicate a string on the heap. The function checks for out of memory */
/* End of mem.h */
#endif

842
src/ca65/objcode.c Normal file
View File

@@ -0,0 +1,842 @@
/*****************************************************************************/
/* */
/* objcode.c */
/* */
/* Objectcode management for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "../common/segdefs.h"
#include "error.h"
#include "fragment.h"
#include "global.h"
#include "listing.h"
#include "mem.h"
#include "objfile.h"
#include "scanner.h"
#include "symtab.h"
#include "objcode.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Are we in absolute mode or in relocatable mode? */
int RelocMode = 1;
unsigned long AbsPC = 0; /* PC if in absolute mode */
typedef struct Segment_ Segment;
struct Segment_ {
Segment* List; /* List of all segments */
Fragment* Root; /* Root of fragment list */
Fragment* Last; /* Pointer to last fragment */
unsigned char Align; /* Segment alignment */
unsigned char SegType; /* True if zero page segment */
unsigned long PC;
unsigned Num; /* Segment number */
char* Name; /* Segment name */
};
/* Predefined segments */
static Segment NullSeg = {
0, 0, 0, 0, SEGTYPE_ABS, 0, 5, "NULL"
};
static Segment ZeropageSeg = {
&NullSeg, 0, 0, 0, SEGTYPE_ZP, 0, 4, "ZEROPAGE"
};
static Segment DataSeg = {
&ZeropageSeg, 0, 0, 0, SEGTYPE_ABS, 0, 3, "DATA"
};
static Segment BssSeg = {
&DataSeg, 0, 0, 0, SEGTYPE_ABS, 0, 2, "BSS"
};
static Segment RODataSeg = {
&BssSeg, 0, 0, 0, SEGTYPE_ABS, 0, 1, "RODATA"
};
static Segment CodeSeg = {
&RODataSeg, 0, 0, 0, SEGTYPE_ABS, 0, 0, "CODE"
};
/* Number of segments */
static unsigned SegmentCount = 6;
/* List of all segments */
static Segment* SegmentList = &CodeSeg;
static Segment* SegmentLast = &NullSeg;
/* Currently active segment */
static Segment* ActiveSeg = &CodeSeg;
/*****************************************************************************/
/* Segment management */
/*****************************************************************************/
static Segment* NewSegment (const char* Name, unsigned SegType)
/* Create a new segment, insert it into the global list and return it */
{
Segment* S;
const char* N;
/* Check for too many segments */
if (SegmentCount >= 256) {
Fatal (FAT_TOO_MANY_SEGMENTS);
}
/* Check the segment name for invalid names */
N = Name;
if ((*N != '_' && !isalpha (*N)) || strlen (Name) > 80) {
Error (ERR_ILLEGAL_SEGMENT, Name);
}
do {
if (*N != '_' && !isalnum (*N)) {
Error (ERR_ILLEGAL_SEGMENT, Name);
break;
}
++N;
} while (*N);
/* Create a new segment */
S = Xmalloc (sizeof (*S));
/* Initialize it */
S->List = 0;
S->Root = 0;
S->Last = 0;
S->Align = 0;
S->SegType = SegType;
S->PC = 0;
S->Num = SegmentCount++;
S->Name = StrDup (Name);
/* Insert it into the segment list */
SegmentLast->List = S;
SegmentLast = S;
/* And return it... */
return S;
}
void UseCodeSeg (void)
/* Use the code segment */
{
ActiveSeg = &CodeSeg;
}
void UseRODataSeg (void)
/* Use the r/o data segment */
{
ActiveSeg = &RODataSeg;
}
void UseDataSeg (void)
/* Use the data segment */
{
ActiveSeg = &DataSeg;
}
void UseBssSeg (void)
/* Use the BSS segment */
{
ActiveSeg = &BssSeg;
}
void UseZeropageSeg (void)
/* Use the zero page segment */
{
ActiveSeg = &ZeropageSeg;
}
void UseNullSeg (void)
/* Use the null segment */
{
ActiveSeg = &NullSeg;
}
void UseSeg (const char* Name, unsigned SegType)
/* Use the segment with the given name */
{
Segment* Seg = SegmentList;
while (Seg) {
if (strcmp (Seg->Name, Name) == 0) {
/* We found this segment. Check if the type is identical */
if (SegType != SEGTYPE_DEFAULT && Seg->SegType != SegType) {
Error (ERR_SEG_ATTR_MISMATCH);
/* Use the new attribute to avoid errors */
Seg->SegType = SegType;
}
ActiveSeg = Seg;
return;
}
/* Check next segment */
Seg = Seg->List;
}
/* Segment is not in list, create a new one */
if (SegType == SEGTYPE_DEFAULT) {
SegType = SEGTYPE_ABS;
}
Seg = NewSegment (Name, SegType);
ActiveSeg = Seg;
}
unsigned long GetPC (void)
/* Get the program counter of the current segment */
{
return RelocMode? ActiveSeg->PC : AbsPC;
}
void SetAbsPC (unsigned long PC)
/* Set the program counter in absolute mode */
{
RelocMode = 0;
AbsPC = PC;
}
unsigned GetSegNum (void)
/* Get the number of the current segment */
{
return ActiveSeg->Num;
}
void SegAlign (unsigned Power, int Val)
/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
* actual fill value will be determined by the linker), otherwise use the
* given value.
*/
{
unsigned char Data [4];
unsigned long Align = (1UL << Power) - 1;
unsigned long NewPC = (ActiveSeg->PC + Align) & ~Align;
unsigned long Count = NewPC - ActiveSeg->PC;
if (Val != -1) {
/* User defined fill value */
memset (Data, Val, sizeof (Data));
while (Count) {
if (Count > sizeof (Data)) {
EmitData (Data, sizeof (Data));
Count -= sizeof (Data);
} else {
EmitData (Data, Count);
Count = 0;
}
}
} else {
/* Linker defined fill value */
EmitFill (Count);
}
/* Remember the alignment in the header */
if (ActiveSeg->Align < Power) {
ActiveSeg->Align = Power;
}
}
int IsZPSeg (void)
/* Return true if the current segment is a zeropage segment */
{
return (ActiveSeg->SegType == SEGTYPE_ZP);
}
int IsFarSeg (void)
/* Return true if the current segment is a far segment */
{
return (ActiveSeg->SegType == SEGTYPE_FAR);
}
unsigned GetSegType (unsigned SegNum)
/* Return the type of the segment with the given number */
{
/* Search for the segment */
Segment* S = SegmentList;
while (S && SegNum) {
--SegNum;
S = S->List;
}
/* Did we find it? */
if (S == 0) {
FAIL ("Invalid segment number");
}
/* Return the segment type */
return S->SegType;
}
void SegCheck (void)
/* Check the segments for range and other errors */
{
Segment* S = SegmentList;
while (S) {
Fragment* F = S->Root;
while (F) {
if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
F->V.Expr = FinalizeExpr (F->V.Expr);
if (IsConstExpr (F->V.Expr)) {
/* We are able to evaluate the expression. Get the value
* and check for range errors.
*/
unsigned I;
long Val = GetExprVal (F->V.Expr);
int Abs = (F->Type != FRAG_SEXPR);
if (F->Len == 1) {
if (Abs) {
/* Absolute value */
if (Val > 255) {
PError (&F->Pos, ERR_RANGE);
}
} else {
/* PC relative value */
if (Val < -128 || Val > 127) {
PError (&F->Pos, ERR_RANGE);
}
}
} else if (F->Len == 2) {
if (Abs) {
/* Absolute value */
if (Val > 65535) {
PError (&F->Pos, ERR_RANGE);
}
} else {
/* PC relative value */
if (Val < -32768 || Val > 32767) {
PError (&F->Pos, ERR_RANGE);
}
}
}
/* Convert the fragment into a literal fragment */
for (I = 0; I < F->Len; ++I) {
F->V.Data [I] = Val & 0xFF;
Val >>= 8;
}
F->Type = FRAG_LITERAL;
} else {
/* We cannot evaluate the expression now, leave the job for
* the linker. However, we are able to check for explicit
* byte expressions and we will do so.
*/
if (F->Type == FRAG_EXPR && F->Len == 1 && !IsByteExpr (F->V.Expr)) {
PError (&F->Pos, ERR_RANGE);
}
}
}
F = F->Next;
}
S = S->List;
}
}
void SegDump (void)
/* Dump the contents of all segments */
{
unsigned X = 0;
Segment* S = SegmentList;
printf ("\n");
while (S) {
unsigned I;
Fragment* F;
int State = -1;
printf ("New segment: %s", S->Name);
F = S->Root;
while (F) {
if (F->Type == FRAG_LITERAL) {
if (State != 0) {
printf ("\n Literal:");
X = 15;
State = 0;
}
for (I = 0; I < F->Len; ++I) {
printf (" %02X", F->V.Data [I]);
X += 3;
}
} else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
State = 1;
printf ("\n Expression (%u): ", F->Len);
DumpExpr (F->V.Expr);
} else if (F->Type == FRAG_FILL) {
State = 1;
printf ("\n Fill bytes (%u)", F->Len);
} else {
Internal ("Unknown fragment type: %u", F->Type);
}
if (X > 65) {
State = -1;
}
F = F->Next;
}
printf ("\n End PC = $%04X\n", (unsigned)(S->PC & 0xFFFF));
S = S->List;
}
printf ("\n");
}
static void WriteOneSeg (Segment* Seg)
/* Write one segment to the object file */
{
Fragment* Frag;
Fragment* F;
unsigned long Size;
/* Write the segment name followed by the byte count in this segment */
ObjWriteStr (Seg->Name);
ObjWrite32 (Seg->PC);
ObjWrite8 (Seg->Align);
ObjWrite8 (Seg->SegType);
/* Now walk through the fragment list for this segment and write the
* fragments.
*/
Frag = Seg->Root;
while (Frag) {
/* Write data depending on the type */
switch (Frag->Type) {
case FRAG_LITERAL:
/* To make the object file somewhat smaller, write all literal
* data of this and the following fragments preceeded by the
* length.
*/
F = Frag;
Size = 0;
while (F && F->Type == FRAG_LITERAL) {
Size += F->Len;
F = F->Next;
}
if (Size < 0x100) {
ObjWrite8 (FRAG_LITERAL8);
ObjWrite8 (Size);
} else if (Size < 0x10000) {
ObjWrite8 (FRAG_LITERAL16);
ObjWrite16 (Size);
} else if (Size < 0x1000000) {
ObjWrite8 (FRAG_LITERAL24);
ObjWrite24 (Size);
} else {
ObjWrite8 (FRAG_LITERAL32);
ObjWrite32 (Size);
}
/* Now write the literal data */
F = Frag;
while (F && F->Type == FRAG_LITERAL) {
ObjWriteData (F->V.Data, F->Len);
Frag = F;
F = F->Next;
}
break;
case FRAG_EXPR:
switch (Frag->Len) {
case 1: ObjWrite8 (FRAG_EXPR8); break;
case 2: ObjWrite8 (FRAG_EXPR16); break;
case 3: ObjWrite8 (FRAG_EXPR24); break;
case 4: ObjWrite8 (FRAG_EXPR32); break;
default: Internal ("Invalid fragment size: %u", Frag->Len);
}
WriteExpr (Frag->V.Expr);
break;
case FRAG_SEXPR:
switch (Frag->Len) {
case 1: ObjWrite8 (FRAG_SEXPR8); break;
case 2: ObjWrite8 (FRAG_SEXPR16); break;
case 3: ObjWrite8 (FRAG_SEXPR24); break;
case 4: ObjWrite8 (FRAG_SEXPR32); break;
default: Internal ("Invalid fragment size: %u", Frag->Len);
}
WriteExpr (Frag->V.Expr);
break;
case FRAG_FILL:
ObjWrite8 (FRAG_FILL);
ObjWrite16 (Frag->Len);
break;
default:
Internal ("Invalid fragment type: %u", Frag->Type);
}
/* Write the file position of this fragment */
ObjWritePos (&Frag->Pos);
/* Next fragment */
Frag = Frag->Next;
}
}
void WriteSegments (void)
/* Write the segment data to the object file */
{
Segment* Seg;
/* Tell the object file module that we're about to start the seg list */
ObjStartSegments ();
/* First thing is segment count */
ObjWrite8 (SegmentCount);
/* Now walk through all segments and write them to the object file */
Seg = SegmentList;
while (Seg) {
/* Write one segment */
WriteOneSeg (Seg);
/* Next segment */
Seg = Seg->List;
}
/* Done writing segments */
ObjEndSegments ();
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static void IncPC (unsigned Value)
/* Increment the PC counter */
{
ActiveSeg->PC += Value;
if (!RelocMode) {
AbsPC += Value;
}
}
static Fragment* NewFragment (unsigned char Type, unsigned short Len)
/* Create, initialize and return a new fragment. The fragment will be inserted
* into the current segment.
*/
{
Fragment* F;
/* Create a new fragment */
F = Xmalloc (sizeof (*F));
/* Initialize it */
F->List = 0;
F->Next = 0;
F->LineList = 0;
F->Pos = CurPos;
F->Len = Len;
F->Type = Type;
/* Insert it into the list of all segments */
if (FragList == 0) {
FragList = F;
} else {
FragLast->List = F;
}
FragLast = F;
/* Insert it into the current segment */
if (ActiveSeg->Root) {
ActiveSeg->Last->Next = F;
ActiveSeg->Last = F;
} else {
ActiveSeg->Root = ActiveSeg->Last = F;
}
/* Add this fragment to the current listing line */
if (LineCur) {
if (LineCur->FragList == 0) {
LineCur->FragList = F;
/* First fragment - set the PC
LineCur->PC = GetPC ();
LineCur->Reloc = RelocMode;
*/
} else {
LineCur->FragLast->LineList = F;
}
LineCur->FragLast = F;
}
/* Increment the program counter */
IncPC (Len);
/* And return it */
return F;
}
void Emit0 (unsigned char OPC)
/* Emit an instruction with a zero sized operand */
{
/* First fragment, wrong type or out of space, create new one */
Fragment* F = NewFragment (FRAG_LITERAL, 1);
F->V.Data [0] = OPC;
}
void Emit1 (unsigned char OPC, ExprNode* Value)
/* Emit an instruction with an one byte argument */
{
Emit0 (OPC);
EmitByte (Value);
}
void Emit2 (unsigned char OPC, ExprNode* Value)
/* Emit an instruction with a two byte argument */
{
Emit0 (OPC);
EmitWord (Value);
}
void Emit3 (unsigned char OPC, ExprNode* Expr)
/* Emit an instruction with a three byte argument */
{
Emit0 (OPC);
EmitFarAddr (Expr);
}
void Emit3b (unsigned char OPC, ExprNode* Expr, ExprNode* Bank)
/* Emit an instruction with a three byte argument and separate bank */
{
Emit0 (OPC);
EmitWord (Expr);
EmitByte (Bank);
}
void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size)
/* Emit an opcode with a PC relative argument of one or two bytes */
{
Fragment* F;
Emit0 (OPC);
F = NewFragment (FRAG_SEXPR, Size);
F->V.Expr = Expr;
}
void EmitData (const unsigned char* Data, unsigned Size)
/* Emit data into the current segment */
{
/* Create lots of fragments for the data */
while (Size) {
Fragment* F;
/* Determine the length of the next fragment */
unsigned Len = Size;
if (Len > sizeof (F->V.Data)) {
Len = sizeof (F->V.Data);
}
/* Create a new fragment */
F = NewFragment (FRAG_LITERAL, Len);
/* Copy the data */
memcpy (F->V.Data, Data, Len);
/* Next chunk */
Data += Len;
Size -= Len;
}
}
void EmitByte (ExprNode* Expr)
/* Emit one byte */
{
if (IsConstExpr (Expr)) {
/* Constant expression, emit literal byte */
long Val = GetExprVal (Expr);
FreeExpr (Expr);
if ((Val & ~0xFF) != 0) {
Error (ERR_RANGE);
}
Emit0 (Val & 0xFF);
} else {
/* Create a new fragment */
Fragment* F = NewFragment (FRAG_EXPR, 1);
/* Set the data */
F->V.Expr = Expr;
}
}
void EmitWord (ExprNode* Expr)
/* Emit one word */
{
if (IsConstExpr (Expr)) {
/* Constant expression, emit literal byte */
long Val = GetExprVal (Expr);
FreeExpr (Expr);
if ((Val & ~0xFFFF) != 0) {
Error (ERR_RANGE);
}
Emit0 (Val & 0xFF);
Emit0 ((Val >> 8) & 0xFF);
} else {
/* Create a new fragment */
Fragment* F = NewFragment (FRAG_EXPR, 2);
/* Set the data */
F->V.Expr = Expr;
}
}
void EmitFarAddr (ExprNode* Expr)
/* Emit a 24 bit expression */
{
if (IsConstExpr (Expr)) {
/* Constant expression, emit literal byte */
long Val = GetExprVal (Expr);
FreeExpr (Expr);
if ((Val & ~0xFFFFFF) != 0) {
Error (ERR_RANGE);
}
Emit0 (Val & 0xFF);
Emit0 ((Val >> 8) & 0xFF);
Emit0 ((Val >> 16) & 0xFF);
} else {
/* Create a new fragment */
Fragment* F = NewFragment (FRAG_EXPR, 3);
/* Set the data */
F->V.Expr = Expr;
}
}
void EmitDWord (ExprNode* Expr)
/* Emit one dword */
{
if (IsConstExpr (Expr)) {
/* Constant expression, emit literal byte */
long Val = GetExprVal (Expr);
FreeExpr (Expr);
Emit0 (Val & 0xFF);
Emit0 ((Val >> 8) & 0xFF);
Emit0 ((Val >> 16) & 0xFF);
Emit0 ((Val >> 24) & 0xFF);
} else {
/* Create a new fragment */
Fragment* F = NewFragment (FRAG_EXPR, 4);
/* Set the data */
F->V.Expr = Expr;
}
}
void EmitFill (unsigned long Count)
/* Emit Count fill bytes */
{
while (Count) {
/* Calculate the size of the next chunk */
unsigned Chunk = (Count > 0xFFFF)? 0xFFFF : (unsigned) Count;
Count -= Chunk;
/* Emit one chunk */
NewFragment (FRAG_FILL, Chunk);
}
}

168
src/ca65/objcode.h Normal file
View File

@@ -0,0 +1,168 @@
/*****************************************************************************/
/* */
/* objcode.h */
/* */
/* Objectcode management for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef OBJCODE_H
#define OBJCODE_H
#include "../common/segdefs.h"
#include "expr.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Are we in absolute mode or in relocatable mode? */
extern int RelocMode;
/*****************************************************************************/
/* Segment management */
/*****************************************************************************/
void UseCodeSeg (void);
/* Use the code segment */
void UseRODataSeg (void);
/* Use the r/o data segment */
void UseDataSeg (void);
/* Use the data segment */
void UseBssSeg (void);
/* Use the BSS segment */
void UseZeropageSeg (void);
/* Use the zero page segment */
void UseNullSeg (void);
/* Use the null segment */
void UseSeg (const char* Name, unsigned SegType);
/* Use the segment with the given name */
unsigned GetSegNum (void);
/* Get the number of the current segment */
void SegAlign (unsigned Power, int Val);
/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
* actual fill value will be determined by the linker), otherwise use the
* given value.
*/
int IsZPSeg (void);
/* Return true if the current segment is a zeropage segment */
int IsFarSeg (void);
/* Return true if the current segment is a far segment */
unsigned GetSegType (unsigned SegNum);
/* Return the type of the segment with the given number */
unsigned long GetPC (void);
/* Get the program counter of the current segment */
void SetAbsPC (unsigned long AbsPC);
/* Set the program counter in absolute mode */
void SegCheck (void);
/* Check the segments for range and other errors */
void SegDump (void);
/* Dump the contents of all segments */
void WriteSegments (void);
/* Write the segment data to the object file */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Emit0 (unsigned char OPC);
/* Emit an instruction with a zero sized operand */
void Emit1 (unsigned char OPC, ExprNode* Value);
/* Emit an instruction with an one byte argument */
void Emit2 (unsigned char OPC, ExprNode* Value);
/* Emit an instruction with a two byte argument */
void Emit3 (unsigned char OPC, ExprNode* Expr);
/* Emit an instruction with a three byte argument */
void Emit3b (unsigned char OPC, ExprNode* Expr, ExprNode* Bank);
/* Emit an instruction with a three byte argument and separate bank */
void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size);
/* Emit an opcode with a PC relative argument of one or two bytes */
void EmitData (const unsigned char* Data, unsigned Size);
/* Emit data into the current segment */
void EmitByte (ExprNode* Expr);
/* Emit one byte */
void EmitWord (ExprNode* Expr);
/* Emit one word */
void EmitFarAddr (ExprNode* Expr);
/* Emit a 24 bit expression */
void EmitDWord (ExprNode* Expr);
/* Emit one dword */
void EmitFill (unsigned long Count);
/* Emit Count fill bytes */
/* End of objcode.h */
#endif

351
src/ca65/objfile.c Normal file
View File

@@ -0,0 +1,351 @@
/*****************************************************************************/
/* */
/* objfile.c */
/* */
/* Object file writing routines for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "../common/objdefs.h"
#include "global.h"
#include "error.h"
#include "fname.h"
#include "mem.h"
#include "objfile.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* File descriptor */
static FILE* F = 0;
/* Default extension */
#define OBJ_EXT ".o"
/* Header structure */
static ObjHeader Header = {
OBJ_MAGIC,
OBJ_VERSION
};
/*****************************************************************************/
/* Internally used functions */
/*****************************************************************************/
static void ObjWriteError (void)
/* Called on a write error. Will try to close and remove the file, then
* print a fatal error.
*/
{
/* Remember the error */
int Error = errno;
/* Force a close of the file, ignoring errors */
fclose (F);
/* Try to remove the file, also ignoring errors */
remove (OutFile);
/* Now abort with a fatal error */
Fatal (FAT_CANNOT_WRITE_OUTPUT, OutFile, strerror (Error));
}
static void ObjWriteHeader (void)
/* Write the object file header to the current file position */
{
ObjWrite32 (Header.Magic);
ObjWrite16 (Header.Version);
ObjWrite16 (Header.Flags);
ObjWrite32 (Header.OptionOffs);
ObjWrite32 (Header.OptionSize);
ObjWrite32 (Header.FileOffs);
ObjWrite32 (Header.FileSize);
ObjWrite32 (Header.SegOffs);
ObjWrite32 (Header.SegSize);
ObjWrite32 (Header.ImportOffs);
ObjWrite32 (Header.ImportSize);
ObjWrite32 (Header.ExportOffs);
ObjWrite32 (Header.ExportSize);
ObjWrite32 (Header.DbgSymOffs);
ObjWrite32 (Header.DbgSymSize);
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ObjOpen (void)
/* Open the object file for writing, write a dummy header */
{
/* Do we have a name for the output file? */
if (OutFile == 0) {
/* We don't have an output name explicitly given, construct one from
* the name of the input file.
*/
OutFile = MakeFilename (InFile, OBJ_EXT);
}
/* Create the output file */
F = fopen (OutFile, "w+b");
if (F == 0) {
Fatal (FAT_CANNOT_OPEN_OUTPUT, OutFile, strerror (errno));
}
/* Write a dummy header */
ObjWriteHeader ();
}
void ObjClose (void)
/* Write an update header and close the object file. */
{
/* Go back to the beginning */
if (fseek (F, 0, SEEK_SET) != 0) {
ObjWriteError ();
}
/* If we have debug infos, set the flag in the header */
if (DbgSyms) {
Header.Flags |= OBJ_FLAGS_DBGINFO;
}
/* Write the updated header */
ObjWriteHeader ();
/* Close the file */
if (fclose (F) != 0) {
ObjWriteError ();
}
}
void ObjWrite8 (unsigned char V)
/* Write an 8 bit value to the file */
{
if (putc (V, F) == EOF) {
ObjWriteError ();
}
}
void ObjWrite16 (unsigned V)
/* Write a 16 bit value to the file */
{
ObjWrite8 (V);
ObjWrite8 (V >> 8);
}
void ObjWrite24 (unsigned long V)
/* Write a 24 bit value to the file */
{
ObjWrite8 (V);
ObjWrite8 (V >> 8);
ObjWrite8 (V >> 16);
}
void ObjWrite32 (unsigned long V)
/* Write a 32 bit value to the file */
{
ObjWrite8 (V);
ObjWrite8 (V >> 8);
ObjWrite8 (V >> 16);
ObjWrite8 (V >> 24);
}
void ObjWriteStr (const char* S)
/* Write a string to the object file */
{
unsigned Len = strlen (S);
if (Len > 255) {
Internal ("String too long in ObjWriteStr");
}
/* Write the string with a length byte preceeded (this is easier for
* the reading routine than the C format since the length is known in
* advance).
*/
ObjWrite8 ((unsigned char) Len);
ObjWriteData (S, Len);
}
void ObjWriteData (const void* Data, unsigned Size)
/* Write literal data to the file */
{
if (fwrite (Data, 1, Size, F) != Size) {
ObjWriteError ();
}
}
void ObjWritePos (const FilePos* Pos)
/* Write a file position to the object file */
{
/* Write the line number as 24 bit value to save one byte */
ObjWrite24 (Pos->Line);
ObjWrite8 (Pos->Col);
if (Pos->Name == 0) {
/* Position is outside file scope, use the main file instead */
ObjWrite8 (0);
} else {
ObjWrite8 (Pos->Name - 1);
}
}
void ObjStartOptions (void)
/* Mark the start of the option section */
{
Header.OptionOffs = ftell (F);
}
void ObjEndOptions (void)
/* Mark the end of the option section */
{
Header.OptionSize = ftell (F) - Header.OptionOffs;
}
void ObjStartFiles (void)
/* Mark the start of the files section */
{
Header.FileOffs = ftell (F);
}
void ObjEndFiles (void)
/* Mark the end of the files section */
{
Header.FileSize = ftell (F) - Header.FileOffs;
}
void ObjStartSegments (void)
/* Mark the start of the segment section */
{
Header.SegOffs = ftell (F);
}
void ObjEndSegments (void)
/* Mark the end of the segment section */
{
Header.SegSize = ftell (F) - Header.SegOffs;
}
void ObjStartImports (void)
/* Mark the start of the import section */
{
Header.ImportOffs = ftell (F);
}
void ObjEndImports (void)
/* Mark the end of the import section */
{
Header.ImportSize = ftell (F) - Header.ImportOffs;
}
void ObjStartExports (void)
/* Mark the start of the export section */
{
Header.ExportOffs = ftell (F);
}
void ObjEndExports (void)
/* Mark the end of the export section */
{
Header.ExportSize = ftell (F) - Header.ExportOffs;
}
void ObjStartDbgSyms (void)
/* Mark the start of the debug symbol section */
{
Header.DbgSymOffs = ftell (F);
}
void ObjEndDbgSyms (void)
/* Mark the end of the debug symbol section */
{
Header.DbgSymSize = ftell (F) - Header.DbgSymOffs;
}

121
src/ca65/objfile.h Normal file
View File

@@ -0,0 +1,121 @@
/*****************************************************************************/
/* */
/* objfile.h */
/* */
/* Object file writing routines for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef OBJFILE_H
#define OBJFILE_H
#include "../common/filepos.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ObjOpen (void);
/* Open the object file for writing, write a dummy header */
void ObjClose (void);
/* Write an update header and close the object file. */
void ObjWrite8 (unsigned char V);
/* Write an 8 bit value to the file */
void ObjWrite16 (unsigned V);
/* Write a 16 bit value to the file */
void ObjWrite24 (unsigned long V);
/* Write a 24 bit value to the file */
void ObjWrite32 (unsigned long V);
/* Write a 32 bit value to the file */
void ObjWriteStr (const char* S);
/* Write a string to the object file */
void ObjWriteData (const void* Data, unsigned Size);
/* Write literal data to the file */
void ObjWritePos (const FilePos* Pos);
/* Write a file position to the object file */
void ObjStartOptions (void);
/* Mark the start of the option section */
void ObjEndOptions (void);
/* Mark the end of the option section */
void ObjStartFiles (void);
/* Mark the start of the files section */
void ObjEndFiles (void);
/* Mark the end of the files section */
void ObjStartSegments (void);
/* Mark the start of the segment section */
void ObjEndSegments (void);
/* Mark the end of the segment section */
void ObjStartImports (void);
/* Mark the start of the import section */
void ObjEndImports (void);
/* Mark the end of the import section */
void ObjStartExports (void);
/* Mark the start of the export section */
void ObjEndExports (void);
/* Mark the end of the export section */
void ObjStartDbgSyms (void);
/* Mark the start of the debug symbol section */
void ObjEndDbgSyms (void);
/* Mark the end of the debug symbol section */
/* End of objfile.h */
#endif

202
src/ca65/options.c Normal file
View File

@@ -0,0 +1,202 @@
/*****************************************************************************/
/* */
/* options.c */
/* */
/* Object file options for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "../common/optdefs.h"
#include "mem.h"
#include "error.h"
#include "objfile.h"
#include "options.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Option list */
static Option* OptRoot = 0;
static Option* OptLast = 0;
static unsigned OptCount = 0;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static Option* NewOption (unsigned char Type)
/* Create a new option, insert it into the list and return it */
{
Option* Opt;
/* Allocate memory */
Opt = Xmalloc (sizeof (*Opt));
/* Initialize fields */
Opt->Next = 0;
Opt->Type = Type;
Opt->V.Str = 0;
/* Insert it into the list */
if (OptRoot == 0) {
OptRoot = Opt;
} else {
OptLast->Next = Opt;
}
OptLast = Opt;
/* One more option now */
++OptCount;
/* Return the new struct */
return Opt;
}
void OptStr (unsigned char Type, const char* Text)
/* Add a string option */
{
Option* O;
/* String must have less than 255 bytes */
if (strlen (Text) > 255) {
Fatal (FAT_STRING_TOO_LONG);
}
O = NewOption (Type);
O->V.Str = StrDup (Text);
}
void OptComment (const char* Comment)
/* Add a comment */
{
OptStr (OPT_COMMENT, Comment);
}
void OptAuthor (const char* Author)
/* Add an author statement */
{
OptStr (OPT_AUTHOR, Author);
}
void OptTranslator (const char* Translator)
/* Add a translator option */
{
OptStr (OPT_TRANSLATOR, Translator);
}
void OptCompiler (const char* Compiler)
/* Add a compiler option */
{
OptStr (OPT_COMPILER, Compiler);
}
void OptOS (const char* OS)
/* Add an operating system option */
{
OptStr (OPT_OS, OS);
}
void OptDateTime (unsigned long DateTime)
/* Add a date/time option */
{
Option* O = NewOption (OPT_DATETIME);
O->V.Val = DateTime;
}
void WriteOptions (void)
/* Write the options to the object file */
{
Option* O;
/* Tell the object file module that we're about to start the options */
ObjStartOptions ();
/* Write the option count */
ObjWrite16 (OptCount);
/* Walk through the list and write the options */
O = OptRoot;
while (O) {
/* Write the type of the option */
ObjWrite8 (O->Type);
/* Write the argument */
switch (O->Type & OPT_ARGMASK) {
case OPT_ARGSTR:
ObjWriteStr (O->V.Str);
break;
case OPT_ARGNUM:
ObjWrite32 (O->V.Val);
break;
default:
Internal ("Invalid option type: $%02X", O->Type & 0xFF);
}
/* Next option */
O = O->Next;
}
/* Done writing options */
ObjEndOptions ();
}

78
src/ca65/options.h Normal file
View File

@@ -0,0 +1,78 @@
/*****************************************************************************/
/* */
/* options.h */
/* */
/* Object file options for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef OPTIONS_H
#define OPTIONS_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void OptStr (unsigned char Type, const char* Text);
/* Add a string option */
void OptComment (const char* Comment);
/* Add a comment */
void OptAuthor (const char* Author);
/* Add an author statement */
void OptTranslator (const char* Translator);
/* Add a translator option */
void OptCompiler (const char* Compiler);
/* Add a compiler option */
void OptOS (const char* OS);
/* Add an operating system option */
void OptDateTime (unsigned long DateTime);
/* Add a date/time option */
void WriteOptions (void);
/* Write the options to the object file */
/* End of options.h */
#endif

1190
src/ca65/pseudo.c Normal file

File diff suppressed because it is too large Load Diff

74
src/ca65/pseudo.h Normal file
View File

@@ -0,0 +1,74 @@
/*****************************************************************************/
/* */
/* pseudo.h */
/* */
/* Pseudo instructions for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef PSEUDO_H
#define PSEUDO_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Are we inside a .IF condition that has been evaluated to TRUE? */
extern unsigned char IfCond;
/* How many .IFs are currently open? */
extern unsigned OpenIfs;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
int TokIsPseudo (unsigned Tok);
/* Return true if the given token is a pseudo instruction token */
void HandlePseudo (void);
/* Handle a pseudo instruction */
/* End of pseudo.h */
#endif

1202
src/ca65/scanner.c Normal file

File diff suppressed because it is too large Load Diff

283
src/ca65/scanner.h Normal file
View File

@@ -0,0 +1,283 @@
/*****************************************************************************/
/* */
/* scanner.h */
/* */
/* The scanner for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef SCANNER_H
#define SCANNER_H
#include "../common/filepos.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Tokens */
enum Token {
TOK_NONE, /* Start value, invalid */
TOK_EOF, /* End of input file */
TOK_SEP, /* Separator (usually newline) */
TOK_IDENT, /* An identifier */
TOK_MNEMO, /* A mnemonic */
TOK_INTCON, /* Integer constant */
TOK_CHARCON, /* Character constant */
TOK_STRCON, /* String constant */
TOK_A, /* A)ccu */
TOK_X, /* X register */
TOK_Y, /* Y register */
TOK_S, /* S register */
TOK_ULABEL, /* :++ or :-- */
TOK_EQ, /* = */
TOK_NE, /* <> */
TOK_LT, /* < */
TOK_GT, /* > */
TOK_LE, /* <= */
TOK_GE, /* >= */
TOK_BAND, /* .and */
TOK_BOR, /* .or */
TOK_BXOR, /* .xor */
TOK_BNOT, /* .not */
TOK_PLUS, /* + */
TOK_MINUS, /* - */
TOK_MUL, /* * */
TOK_STAR = TOK_MUL, /* Alias */
TOK_DIV, /* / */
TOK_MOD, /* ! */
TOK_OR, /* | */
TOK_XOR, /* ^ */
TOK_AND, /* & */
TOK_SHL, /* << */
TOK_SHR, /* >> */
TOK_NOT, /* ~ */
TOK_PC, /* $ if enabled */
TOK_NAMESPACE, /* :: */
TOK_DOT, /* . */
TOK_COMMA, /* , */
TOK_HASH, /* # */
TOK_COLON, /* : */
TOK_LPAREN, /* ( */
TOK_RPAREN, /* ) */
TOK_LBRACK, /* [ */
TOK_RBRACK, /* ] */
TOK_MACPARAM, /* Macro parameter, not generated by scanner */
/* The next ones are tokens for the pseudo instructions. Keep together! */
TOK_FIRSTPSEUDO,
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A8,
TOK_ADDR,
TOK_ALIGN,
TOK_ASCIIZ,
TOK_AUTOIMPORT,
TOK_BLANK,
TOK_BSS,
TOK_BYTE,
TOK_CASE,
TOK_CODE,
TOK_CONST,
TOK_CPU,
TOK_DATA,
TOK_DBYT,
TOK_DEBUGINFO,
TOK_DEFINE,
TOK_DEFINED,
TOK_DWORD,
TOK_ELSE,
TOK_ELSEIF,
TOK_END,
TOK_ENDIF,
TOK_ENDMACRO,
TOK_ENDPROC,
TOK_ENDREP,
TOK_ERROR,
TOK_EXITMACRO,
TOK_EXPORT,
TOK_EXPORTZP,
TOK_FARADDR,
TOK_FEATURE,
TOK_FILEOPT,
TOK_GLOBAL,
TOK_GLOBALZP,
TOK_I16,
TOK_I8,
TOK_IF,
TOK_IFBLANK,
TOK_IFCONST,
TOK_IFDEF,
TOK_IFNBLANK,
TOK_IFNCONST,
TOK_IFNDEF,
TOK_IFNREF,
TOK_IFP02,
TOK_IFP816,
TOK_IFPC02,
TOK_IFREF,
TOK_IMPORT,
TOK_IMPORTZP,
TOK_INCBIN,
TOK_INCLUDE,
TOK_LINECONT,
TOK_LIST,
TOK_LISTBYTES,
TOK_LOCAL,
TOK_LOCALCHAR,
TOK_MACPACK,
TOK_MACRO,
TOK_MATCH,
TOK_NULL,
TOK_ORG,
TOK_OUT,
TOK_P02,
TOK_P816,
TOK_PAGELENGTH,
TOK_PARAMCOUNT,
TOK_PC02,
TOK_PROC,
TOK_REFERENCED,
TOK_RELOC,
TOK_REPEAT,
TOK_RES,
TOK_RODATA,
TOK_SEGMENT,
TOK_SMART,
TOK_STRING,
TOK_SUNPLUS,
TOK_WORD,
TOK_XMATCH,
TOK_ZEROPAGE,
TOK_LASTPSEUDO = TOK_ZEROPAGE,
TOK_COUNT /* Count of tokens */
};
/* Scanner variables */
#define MAX_INPUT_FILES 254 /* No more than this files total */
#define MAX_STR_LEN 255 /* Maximum length of any string */
extern enum Token Tok; /* Current token */
extern int WS; /* Flag: Whitespace before token */
extern long IVal; /* Integer token attribute */
extern char SVal [MAX_STR_LEN+1]; /* String token attribute */
extern FilePos CurPos; /* Name and position in file */
extern int ForcedEnd; /* Force end of assembly */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
const char* GetFileName (unsigned char Name);
/* Get the name of a file where the name index is known */
void NewInputFile (const char* Name);
/* Open a new input file */
void DoneInputFile (void);
/* Close the current input file */
void NewInputData (const char* Data, int Malloced);
/* Add a chunk of input data to the input stream */
void UpcaseSVal (void);
/* Make SVal upper case */
void NextTok (void);
/* Read the next token from the input stream */
void Consume (enum Token Expected, unsigned ErrMsg);
/* Consume Token, print an error if we don't find it */
void ConsumeSep (void);
/* Consume a separator token */
void ConsumeLParen (void);
/* Consume a left paren */
void ConsumeRParen (void);
/* Consume a right paren */
void ConsumeComma (void);
/* Consume a comma */
void SkipUntilSep (void);
/* Skip tokens until we reach a line separator */
int TokHasSVal (enum Token Tok);
/* Return true if the given token has an attached SVal */
int TokHasIVal (enum Token Tok);
/* Return true if the given token has an attached IVal */
int GetSubKey (const char** Keys, unsigned Count);
/* Search for a subkey in a table of keywords. The current token must be an
* identifier and all keys must be in upper case. The identifier will be
* uppercased in the process. The function returns the index of the keyword,
* or -1 if the keyword was not found.
*/
void WriteFiles (void);
/* Write the list of input files to the object file */
void InitScanner (const char* InFile);
/* Initialize the scanner, open the given input file */
void DoneScanner (void);
/* Release scanner resources */
/* End of scanner.h */
#endif

97
src/ca65/strexpr.c Normal file
View File

@@ -0,0 +1,97 @@
/*****************************************************************************/
/* */
/* strexpr.c */
/* */
/* String expressions for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include "error.h"
#include "expr.h"
#include "scanner.h"
#include "strexpr.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
const char* StringExpression (void)
/* Evaluate a string expression. If there are no errors, the function will
* place the string into the token attribute buffer SVal and the token will
* be TOK_STRCON. A pointer to the buffer is returned.
* If there was an error, a NULL pointer is returned.
*/
{
char Buf [sizeof (SVal)];
/* Check for a string constant or a function that returns a string */
switch (Tok) {
case TOK_STRING:
NextTok ();
ConsumeLParen ();
if (Tok == TOK_IDENT) {
/* Save the identifier, then skip it */
strcpy (Buf, SVal);
NextTok ();
} else {
/* Numeric expression */
long Val = ConstExpression ();
sprintf (Buf, "%ld", Val);
}
if (Tok != TOK_RPAREN) {
Error (ERR_RPAREN_EXPECTED);
}
/* Overwrite the token, do not skip it! */
strcpy (SVal, Buf);
Tok = TOK_STRCON;
break;
case TOK_STRCON:
/* We already have a string */
break;
default:
/* Error - no string constant */
return 0;
}
/* Return a pointer to the buffer */
return SVal;
}

61
src/ca65/strexpr.h Normal file
View File

@@ -0,0 +1,61 @@
/*****************************************************************************/
/* */
/* strexpr.h */
/* */
/* String expressions for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef STREXPR_H
#define STREXPR_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
const char* StringExpression (void);
/* Evaluate a string expression. If there are no errors, the function will
* place the string into the token attribute buffer SVal and the token will
* be TOK_STRCON. A pointer to the buffer is returned.
* If there was an error, a NULL pointer is returned.
*/
/* End of strexpr.h */
#endif

57
src/ca65/symentry.h Normal file
View File

@@ -0,0 +1,57 @@
/*****************************************************************************/
/* */
/* symentry.h */
/* */
/* Symbol table entry forward for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef SYMENTRY_H
#define SYMENTRY_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Forward declaration for struct SymEntry */
typedef struct SymEntry_ SymEntry;
/* End of symentry.h */
#endif

1127
src/ca65/symtab.c Normal file

File diff suppressed because it is too large Load Diff

145
src/ca65/symtab.h Normal file
View File

@@ -0,0 +1,145 @@
/*****************************************************************************/
/* */
/* symtab.h */
/* */
/* Symbol table for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef SYMTAB_H
#define SYMTAB_H
#include <stdio.h>
#include "../common/exprdefs.h"
#include "symentry.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void SymEnterLevel (void);
/* Enter a new lexical level */
void SymLeaveLevel (void);
/* Leave the current lexical level */
void SymDef (const char* Name, ExprNode* Expr, int ZP);
/* Define a new symbol */
SymEntry* SymRef (const char* Name);
/* Search for the symbol and return it */
SymEntry* SymRefGlobal (const char* Name);
/* Search for the symbol in the global namespace and return it */
int SymIsDef (const char* Name);
/* Return true if the given symbol is already defined */
int SymIsRef (const char* Name);
/* Return true if the given symbol has been referenced */
void SymImport (const char* Name, int ZP);
/* Mark the given symbol as an imported symbol */
void SymExport (const char* Name, int ZP);
/* Mark the given symbol as an exported symbol */
void SymGlobal (const char* Name, int ZP);
/* Mark the given symbol as a global symbol, that is, as a symbol that is
* either imported or exported.
*/
int SymIsConst (SymEntry* Sym);
/* Return true if the given symbol has a constant value */
int SymIsZP (SymEntry* Sym);
/* Return true if the symbol is explicitly marked as zeropage symbol */
int SymIsImport (SymEntry* Sym);
/* Return true if the given symbol is marked as import */
int SymHasExpr (SymEntry* Sym);
/* Return true if the given symbol has an associated expression */
void SymMarkUser (SymEntry* Sym);
/* Set a user mark on the specified symbol */
void SymUnmarkUser (SymEntry* Sym);
/* Remove a user mark from the specified symbol */
int SymHasUserMark (SymEntry* Sym);
/* Return the state of the user mark for the specified symbol */
long GetSymVal (SymEntry* Sym);
/* Return the symbol value */
ExprNode* GetSymExpr (SymEntry* Sym);
/* Get the expression for a non-const symbol */
const char* GetSymName (SymEntry* Sym);
/* Return the name of the symbol */
unsigned GetSymIndex (SymEntry* Sym);
/* Return the symbol index for the given symbol */
const FilePos* GetSymPos (SymEntry* Sym);
/* Return the position of first occurence in the source for the given symbol */
void SymCheck (void);
/* Run through all symbols and check for anomalies and errors */
void SymDump (FILE* F);
/* Dump the symbol table */
void WriteImports (void);
/* Write the imports list to the object file */
void WriteExports (void);
/* Write the exports list to the object file */
void WriteDbgSyms (void);
/* Write a list of all symbols to the object file */
/* End of symtab.h */
#endif

117
src/ca65/toknode.c Normal file
View File

@@ -0,0 +1,117 @@
/*****************************************************************************/
/* */
/* toknode.c */
/* */
/* Token list node for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include "mem.h"
#include "scanner.h"
#include "toknode.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
TokNode* NewTokNode (void)
/* Create and return a token node with the current token value */
{
TokNode* T;
/* Allocate memory */
unsigned Len = TokHasSVal (Tok)? strlen (SVal) : 0;
T = Xmalloc (sizeof (TokNode) + Len);
/* Initialize the token contents */
T->Next = 0;
T->Tok = Tok;
T->WS = WS;
T->IVal = IVal;
memcpy (T->SVal, SVal, Len);
T->SVal [Len] = '\0';
/* Return the node */
return T;
}
void FreeTokNode (TokNode* T)
/* Free the given token node */
{
Xfree (T);
}
void TokSet (TokNode* T)
/* Set the scanner token from the given token node */
{
/* Set the values */
Tok = T->Tok;
WS = T->WS;
IVal = T->IVal;
strcpy (SVal, T->SVal);
}
enum TC TokCmp (const TokNode* T)
/* Compare the token given as parameter against the current token */
{
if (T->Tok != Tok) {
/* Different token */
return tcDifferent;
}
/* If the token has string attribute, check it */
if (TokHasSVal (T->Tok)) {
if (strcmp (T->SVal, SVal) != 0) {
return tcSameToken;
}
} else if (TokHasIVal (T->Tok)) {
if (T->IVal != IVal) {
return tcSameToken;
}
}
/* Tokens are identical */
return tcIdentical;
}

94
src/ca65/toknode.h Normal file
View File

@@ -0,0 +1,94 @@
/*****************************************************************************/
/* */
/* toknode.h */
/* */
/* Token list node for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef TOKNODE_H
#define TOKNODE_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Struct holding a token */
typedef struct TokNode_ TokNode;
struct TokNode_ {
TokNode* Next; /* For single linked list */
enum Token Tok; /* Token value */
int WS; /* Whitespace before token? */
long IVal; /* Integer token attribute */
char SVal [1]; /* String attribute, dyn. allocated */
};
/* Return codes for TokCmp - higher numeric code means better match */
enum TC {
tcDifferent, /* Different tokents */
tcSameToken, /* Same token, different attribute */
tcIdentical /* Identical (token + attribute) */
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
TokNode* NewTokNode (void);
/* Create and return a token node with the current token value */
void FreeTokNode (TokNode* T);
/* Free the given token node */
void TokSet (TokNode* T);
/* Set the scanner token from the given token node */
enum TC TokCmp (const TokNode* T);
/* Compare the token given as parameter against the current token */
/* End of toknode.h */
#endif

242
src/ca65/ulabel.c Normal file
View File

@@ -0,0 +1,242 @@
/*****************************************************************************/
/* */
/* ulabel.c */
/* */
/* Unnamed labels for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "../common/filepos.h"
#include "error.h"
#include "expr.h"
#include "mem.h"
#include "scanner.h"
#include "ulabel.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Struct that describes an unnamed label */
typedef struct ULabel_ ULabel;
struct ULabel_ {
ULabel* Prev; /* Pointer to previous node in list */
ULabel* Next; /* Pointer to next node in list */
FilePos Pos; /* Position of the label in the source */
ExprNode* Val; /* The label value - may be NULL */
};
/* List management */
static ULabel* ULabRoot = 0; /* Root of the list */
static ULabel* ULabLast = 0; /* Last ULabel */
static ULabel* ULabLastDef = 0; /* Last defined ULabel */
static unsigned ULabCount = 0; /* Number of labels */
static unsigned ULabDefCount = 0; /* Number of defined labels */
static ULabel** ULabList = 0; /* Array with pointers to all labels */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static ULabel* NewULabel (ExprNode* Val)
/* Create a new ULabel and insert it into the list. The function will move
* ULabelLast, but not ULabelLastDef. The created label structure is returned.
*/
{
/* Allocate memory for the ULabel structure */
ULabel* L = Xmalloc (sizeof (ULabel));
/* Initialize the fields */
L->Pos = CurPos;
L->Val = Val;
/* Insert the label into the list */
L->Next = 0;
if (ULabRoot == 0) {
/* First label */
L->Prev = 0;
ULabRoot = L;
} else {
ULabLast->Next = L;
L->Prev = ULabLast;
}
ULabLast = L;
/* One label more */
++ULabCount;
/* Return the created label */
return L;
}
ExprNode* ULabRef (int Which)
/* Get an unnamed label. If Which is negative, it is a backreference (a
* reference to an already defined label), and the function will return a
* segment relative expression. If Which is positive, it is a forward ref,
* and the function will return a expression node for an unnamed label that
* must be resolved later.
*/
{
ULabel* L;
/* Which can never be 0 */
PRECONDITION (Which != 0);
/* Which is never really big (usually -3..+3), so a linear search is
* the best we can do here.
*/
L = ULabLastDef;
if (Which < 0) {
/* Backward reference */
while (Which < -1 && L != 0) {
L = L->Prev;
++Which;
}
if (L == 0) {
/* Label does not exist */
Error (ERR_UNDEFINED_LABEL);
/* We must return something valid */
return CurrentPC();
} else {
/* Return a copy of the label value */
return CloneExpr (L->Val);
}
} else {
/* Forward reference. Create labels as needed */
unsigned LabelNum = ULabDefCount + Which - 1;
while (Which > 0) {
if (L->Next == 0) {
NewULabel (0);
}
L = L->Next;
--Which;
}
/* Return an unnamed label expression */
return ULabelExpr (LabelNum);
}
}
void ULabDef (void)
/* Define an unnamed label at the current PC */
{
/* Create a new label if needed, or use an existing one */
if (ULabLastDef == 0 || ULabLastDef->Next == 0) {
/* The last label is also the last defined label, we need a new one */
ULabLastDef = NewULabel (CurrentPC ());
} else {
/* We do already have the label, but it's undefined until now */
ULabLastDef = ULabLastDef->Next;
ULabLastDef->Val = CurrentPC ();
ULabLastDef->Pos = CurPos;
}
++ULabDefCount;
}
int ULabCanResolve (void)
/* Return true if we can resolve arbitrary ULabels. */
{
/* We can resolve labels if we have built the necessary access array */
return (ULabList != 0);
}
ExprNode* ULabResolve (unsigned Index)
/* Return a valid expression for the unnamed label with the given index. This
* is used to resolve unnamed labels when assembly is done, so it is an error
* if a label is still undefined in this phase.
*/
{
ULabel* L;
/* Must be in resolve phase and the index must be valid */
CHECK (ULabList != 0 && Index < ULabCount);
/* Get the label */
L = ULabList [Index];
/* If the label is open (not defined), return some valid value */
if (L->Val == 0) {
return LiteralExpr (0);
} else {
return CloneExpr (L->Val);
}
}
void ULabCheck (void)
/* Run through all unnamed labels and check for anomalies and errors */
{
ULabel* L;
/* Check if there are undefined labels */
if (ULabLastDef) {
L = ULabLastDef->Next;
while (L) {
PError (&L->Pos, ERR_UNDEFINED_LABEL);
L = L->Next;
}
}
/* Create an array that holds pointers to all labels. This allows us to
* access the labels quickly by index in the resolver phase at the end of
* the assembly.
*/
if (ULabCount) {
unsigned I = 0;
ULabList = Xmalloc (ULabCount * sizeof (ULabel*));
L = ULabRoot;
while (L) {
ULabList[I] = L;
++I;
L = L->Next;
}
CHECK (I == ULabCount);
}
}

77
src/ca65/ulabel.h Normal file
View File

@@ -0,0 +1,77 @@
/*****************************************************************************/
/* */
/* ulabel.h */
/* */
/* Unnamed labels for the ca65 macroassembler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ULABEL_H
#define ULABEL_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
ExprNode* ULabRef (int Which);
/* Get an unnamed label. If Which is negative, it is a backreference (a
* reference to an already defined label), and the function will return a
* segment relative expression. If Which is positive, it is a forward ref,
* and the function will return a expression node for an unnamed label that
* must be resolved later.
*/
void ULabDef (void);
/* Define an unnamed label at the current PC */
int ULabCanResolve (void);
/* Return true if we can resolve arbitrary ULabels. */
ExprNode* ULabResolve (unsigned Index);
/* Return a valid expression for the unnamed label with the given index. This
* is used to resolve unnamed labels when assembly is done, so it is an error
* if a label is still undefined in this phase.
*/
void ULabCheck (void);
/* Run through all unnamed labels and check for anomalies and errors */
/* End of ulabel.h */
#endif

29
src/cc65/.cvsignore Normal file
View File

@@ -0,0 +1,29 @@
.depend
.kdbgrc.cc65
cc65
*.com
*.map
xopt
predent
postdent
code-gen.m65
glb.m65
cc64
error.m65
expr1.m65
expr2.m65
save
expr3.m65
function.m65
globlvar.m65
io.m65
lexer.m65
main.m65
optab1.m65
optab2.m65
optimize.m65
preproc.m65
rwords.m65
stmt1.m65
stmt2.m65
symtab.m65

59
src/cc65/anonname.c Normal file
View File

@@ -0,0 +1,59 @@
/*****************************************************************************/
/* */
/* anonname.c */
/* */
/* Create names for anonymous variables/types */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include "anonname.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* AnonName (char* Buf, const char* Spec)
/* Get a name for an anonymous variable or type. The given buffer is expected
* to be IDENTSIZE characters long. A pointer to the buffer is returned.
*/
{
static unsigned ACount = 0;
sprintf (Buf, "$anon-%s-%04X", Spec, ++ACount);
return Buf;
}

58
src/cc65/anonname.h Normal file
View File

@@ -0,0 +1,58 @@
/*****************************************************************************/
/* */
/* anonname.h */
/* */
/* Create names for anonymous variables/types */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ANONNAME_H
#define ANONNAME_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* AnonName (char* Buf, const char* Spec);
/* Get a name for an anonymous variable or type. The given buffer is expected
* to be IDENTSIZE characters long. A pointer to the buffer is returned.
*/
/* End of anonname.h */
#endif

115
src/cc65/asmcode.c Normal file
View File

@@ -0,0 +1,115 @@
/*****************************************************************************/
/* */
/* asmcode.c */
/* */
/* Assembler output code handling for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "asmline.h"
#include "check.h"
#include "global.h"
#include "asmcode.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void AddCodeLine (const char* Format, ...)
/* Add a new line of code to the output */
{
va_list ap;
va_start (ap, Format);
NewCodeLine (Format, ap);
va_end (ap);
}
void AddCodeHint (const char* Hint)
/* Add an optimizer hint */
{
AddCodeLine ("+%s", Hint);
}
void AddEmptyLine (void)
/* Add an empty line for formatting purposes */
{
AddCodeLine ("");
}
CodeMark GetCodePos (void)
/* Get a marker pointing to the current output position */
{
/* This function should never be called without any code output */
CHECK (LastLine != 0);
return LastLine;
}
void RemoveCode (CodeMark M)
/* Remove all code after the given code marker */
{
while (LastLine != M) {
FreeCodeLine (LastLine);
}
}
void WriteOutput (FILE* F)
/* Write the final output to a file */
{
Line* L = FirstLine;
while (L) {
/* Don't write optimizer hints if not requested to do so */
if (L->Line[0] == '+') {
if (Debug) {
fprintf (F, ";%s\n", L->Line);
}
} else {
fprintf (F, "%s\n", L->Line);
}
L = L->Next;
}
}

86
src/cc65/asmcode.h Normal file
View File

@@ -0,0 +1,86 @@
/*****************************************************************************/
/* */
/* asmcode.h */
/* */
/* Assembler output code handling for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ASMCODE_H
#define ASMCODE_H
#include <stdio.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Marker for an assembler code position */
typedef struct Line_* CodeMark;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void AddCodeLine (const char* Format, ...);
/* Add a new line of code to the output */
void AddCodeHint (const char* Hint);
/* Add an optimizer hint */
void AddEmptyLine (void);
/* Add an empty line for formatting purposes */
CodeMark GetCodePos (void);
/* Get a marker pointing to the current output position */
void RemoveCode (CodeMark M);
/* Remove all code after the given code marker */
void WriteOutput (FILE* F);
/* Write the final output to a file */
/* End of asmcode.h */
#endif

55
src/cc65/asmlabel.c Normal file
View File

@@ -0,0 +1,55 @@
/*****************************************************************************/
/* */
/* asmlabel.c */
/* */
/* Generate assembler code labels */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "asmlabel.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned GetLabel (void)
/* Get an unused label. Will never return zero. */
{
/* Number to generate unique labels */
static unsigned NextLabel = 0;
return ++NextLabel;
}

56
src/cc65/asmlabel.h Normal file
View File

@@ -0,0 +1,56 @@
/*****************************************************************************/
/* */
/* asmlabel.h */
/* */
/* Generate assembler code labels */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ASMLABEL_H
#define ASMLABEL_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned GetLabel (void);
/* Get an unused assembler label. Will never return zero. */
/* End of asmlabel.h */
#endif

184
src/cc65/asmline.c Normal file
View File

@@ -0,0 +1,184 @@
/*****************************************************************************/
/* */
/* asmline.h */
/* */
/* Internal assembler line structure */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include "error.h"
#include "mem.h"
#include "asmline.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Number used to index lines */
static unsigned long LineIndex = 0;
/* The line list */
Line* FirstLine = 0; /* Pointer to first line */
Line* LastLine = 0; /* Pointer to last line */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static Line* NewLine (const char* Format, va_list ap)
/* Interal routine to create a new line from the given text */
{
char Buf [8192];
int OVF;
unsigned Len;
Line* L;
/* Make a string from the given format and arguments */
#if defined(__WATCOMC__)
OVF = (_vbprintf (Buf, sizeof (Buf), Format, ap) >= sizeof (S));
#else
/* Assume gcc running on a Unix OS */
OVF = (vsnprintf (Buf, sizeof (Buf), Format, ap) < 0);
#endif
if (OVF) {
Internal ("String size overflow");
}
/* Get the length of the line */
Len = strlen (Buf);
/* Allocate memory */
L = xmalloc (sizeof (Line) + Len);
/* Partially initialize the struct (the remaining fields are initialized
* by the caller).
*/
L->Flags = 0;
L->Size = 0;
L->Len = Len;
memcpy (L->Line, Buf, Len+1);
/* Return the new line */
return L;
}
Line* NewCodeLine (const char* Format, va_list ap)
/* Create a new code line and return it */
{
/* Create a new line struct */
Line* L = NewLine (Format, ap);
/* Initialize struct fields */
L->Index = LineIndex++;
/* Insert the line into the list */
if (FirstLine == 0) {
/* The list is empty */
L->Next = L->Prev = 0;
FirstLine = LastLine = L;
} else {
/* There are entries in the list, add the new one at the end */
LastLine->Next = L;
L->Prev = LastLine;
L->Next = 0;
LastLine = L;
}
/* Return the new line */
return L;
}
Line* NewCodeLineAfter (Line* LineBefore, const char* Format, va_list ap)
/* Create a new line, insert it after L and return it. */
{
/* Create a new line struct */
Line* L = NewLine (Format, ap);
/* Initialize struct fields. We use the same index for the inserted line
* as for its predecessor, since we cannot create new numbers on the
* fly and the index is only used to determine sort order.
*/
L->Index = LineBefore->Index;
/* Insert the line after its predecessor */
L->Next = LineBefore->Next;
LineBefore->Next = L;
L->Prev = LineBefore;
if (L->Next) {
L->Next->Prev = L;
} else {
/* This is the last line */
LastLine = L;
}
/* Return the new line */
return L;
}
void FreeCodeLine (Line* L)
/* Remove a line from the list and free it */
{
/* Unlink the line */
if (L->Prev == 0) {
/* No line before this one */
FirstLine = L->Next;
} else {
L->Prev->Next = L->Next;
}
if (L->Next == 0) {
/* No line after this one */
LastLine = L->Prev;
} else {
L->Next->Prev = L->Prev;
}
/* Free the struct */
xfree (L);
}

90
src/cc65/asmline.h Normal file
View File

@@ -0,0 +1,90 @@
/*****************************************************************************/
/* */
/* asmline.h */
/* */
/* Internal assembler line structure */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ASMLINE_H
#define ASMLINE_H
#include <stdarg.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Structure that contains one line */
typedef struct Line_ Line;
struct Line_ {
Line* Next; /* Next line on double linked list */
Line* Prev; /* Revious line in list */
unsigned Flags; /* Flags for this line */
unsigned long Index; /* Index of this line */
unsigned Size; /* Size of this code */
unsigned Len; /* Length of the line */
char Line [1]; /* The line itself */
};
/* The line list */
extern Line* FirstLine; /* Pointer to first line */
extern Line* LastLine; /* Pointer to last line */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
Line* NewCodeLine (const char* Format, va_list ap);
/* Create a new code line and return it */
Line* NewCodeLineAfter (Line* LineBefore, const char* Format, va_list ap);
/* Create a new line, insert it after L and return it. */
void FreeCodeLine (Line* L);
/* Remove a line from the list and free it */
/* End of asmline.h */
#endif

102
src/cc65/check.c Normal file
View File

@@ -0,0 +1,102 @@
/*****************************************************************************/
/* */
/* check.c */
/* */
/* Assert macros for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include "error.h"
#include "check.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Predefined messages */
const char* _MsgInternalError = "Internal error: ";
const char* _MsgAbstractCall = "Call to abstract method";
const char* _MsgPrecondition = "Precondition violated: ";
const char* _MsgCheckFailed = "Check failed: ";
const char* _MsgProgramAborted = "Program aborted: ";
static void _CheckFailed (const char* msg, const char* cond,
int code, const char* file, unsigned line);
void (*CheckFailed) (const char* Msg, const char* Cond, int Code,
const char* File, unsigned Line) = _CheckFailed;
/* Function pointer that is called from check if the condition code is true. */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static void _CheckFailed (const char* Msg, const char* Cond,
int Code, const char* File, unsigned Line)
{
/* Log the error */
if (Code) {
Internal ("%s%s (= %d), file `%s', line %u", Msg, Cond, Code, File, Line);
} else {
Internal ("%s%s, file `%s', line %u", Msg, Cond, File, Line);
}
/* Use abort() to create a core for debugging */
abort ();
}
void Check (const char* Msg, const char* Cond, int Code,
const char* File, unsigned Line)
/* This function is called from all check macros (see below). It checks,
* wether the given Code is true (!= 0). If so, it calls the CheckFailed
* vector with the given strings. If not, it simply returns.
*/
{
if (Code != 0) {
CheckFailed (Msg, Cond, Code, File, Line);
}
}

96
src/cc65/check.h Normal file
View File

@@ -0,0 +1,96 @@
/*****************************************************************************/
/* */
/* check.h */
/* */
/* Assert macros for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef CHECK_H
#define CHECK_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
extern const char* _MsgInternalError; /* "Internal error: " */
extern const char* _MsgPrecondition; /* "Precondition violated: " */
extern const char* _MsgCheckFailed; /* "Check failed: " */
extern const char* _MsgProgramAborted; /* "Program aborted: " */
extern void (*CheckFailed) (const char* Msg, const char* Cond,
int Code, const char* File, unsigned Line);
/* Function pointer that is called from check if the condition code is true. */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Check (const char* Msg, const char* Cond, int Code,
const char* File, unsigned Line);
/* This function is called from all check macros (see below). It checks,
* wether the given Code is true (!= 0). If so, it calls the CheckFailed
* vector with the given strings. If not, it simply returns.
*/
#define FAIL(s) CheckFailed (_MsgInternalError, s, 0, __FILE__, __LINE__)
/* Fail macro. Is used if something evil happens, calls checkfailed directly. */
#define ABORT(s) CheckFailed (_MsgProgramAborted, s, 0, __FILE__, __LINE__)
/* Use this one instead of FAIL if there is no internal program error but an
* error condition that is caused by the user or operating system (FAIL and
* ABORT are essentially the same but the message differs).
*/
#define PRECONDITION(c) Check (_MsgPrecondition, #c, !(c), __FILE__, __LINE__)
#define CHECK(c) Check (_MsgCheckFailed, #c, !(c), __FILE__, __LINE__)
#define ZCHECK(c) Check (_MsgCheckFailed, #c, c, __FILE__, __LINE__)
/* End of check.h */
#endif

3712
src/cc65/codegen.c Normal file

File diff suppressed because it is too large Load Diff

395
src/cc65/codegen.h Normal file
View File

@@ -0,0 +1,395 @@
/*
* codegen.h
*
* Ullrich von Bassewitz, 04.06.1998
*/
#ifndef CODEGEN_H
#define CODEGEN_H
/*****************************************************************************/
/* data */
/*****************************************************************************/
/* Code generator flags.
* Note: The type flags are designed so that a smaller type may override a
* larger one by or'ing it into the existing one.
*/
#define CF_NONE 0x0000 /* No special flags */
#define CF_TYPE 0x000F /* Mask for operand type */
#define CF_CHAR 0x0003 /* Operation on characters */
#define CF_INT 0x0001 /* Operation on ints */
#define CF_PTR CF_INT /* Alias for readability */
#define CF_LONG 0x0000 /* Operation on longs */
#define CF_UNSIGNED 0x0010 /* Value is unsigned */
#define CF_CONST 0x0020 /* Constant value available */
#define CF_CONSTADDR 0x0040 /* Constant address value available */
#define CF_TEST 0x0080 /* Test value */
#define CF_FIXARGC 0x0100 /* Function has fixed arg count */
#define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */
#define CF_SHORT 0x0400 /* Use short addressing */
#define CF_REG 0x0800 /* Value is in primary register */
/* Type of static address */
#define CF_ADDRMASK 0xF000 /* Type of address */
#define CF_STATIC 0x0000 /* Static local */
#define CF_EXTERNAL 0x1000 /* Static external */
#define CF_ABSOLUTE 0x2000 /* Numeric absolute address */
#define CF_LOCAL 0x4000 /* Auto variable */
#define CF_REGVAR 0x8000 /* Register variable */
/* Compiler relative stackpointer */
extern int oursp;
/*****************************************************************************/
/* Pre- and postamble */
/*****************************************************************************/
void g_preamble (void);
/* Generate the assembler code preamble */
void g_postamble (void);
/* Generate assembler code postamble */
/*****************************************************************************/
/* Segment support */
/*****************************************************************************/
void g_usecode (void);
/* Switch to the code segment */
void g_userodata (void);
/* Switch to the read only data segment */
void g_usedata (void);
/* Switch to the data segment */
void g_usebss (void);
/* Switch to the bss segment */
void g_codename (const char* Name);
/* Set the name of the CODE segment */
void g_rodataname (const char* Name);
/* Set the name of the RODATA segment */
void g_dataname (const char* Name);
/* Set the name of the DATA segment */
void g_bssname (const char* Name);
/* Set the name of the BSS segment */
/*****************************************************************************/
/* Functions handling local labels */
/*****************************************************************************/
void g_defloclabel (unsigned label);
/* Define a local label */
/*****************************************************************************/
/* Functions handling global labels */
/*****************************************************************************/
void g_defgloblabel (const char* Name);
/* Define a global label with the given name */
void g_defexport (const char* Name, int ZP);
/* Export the given label */
void g_defimport (const char* Name, int ZP);
/* Import the given label */
/*****************************************************************************/
/* stack */
/*****************************************************************************/
int pop (unsigned flags);
/* Pop an argument of the given size */
int push (unsigned flags);
/* Push an argument of the given size */
unsigned sizeofarg (unsigned flags);
/* Return the size of a function argument type that is encoded in flags */
/*****************************************************************************/
/* type conversion and similiar stuff */
/*****************************************************************************/
void g_toslong (unsigned flags);
/* Make sure, the value on TOS is a long. Convert if necessary */
void g_tosint (unsigned flags);
/* Make sure, the value on TOS is an int. Convert if necessary */
void g_reglong (unsigned flags);
/* Make sure, the value in the primary register a long. Convert if necessary */
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
/* Adjust the integer operands before doing a binary operation. lhs is a flags
* value, that corresponds to the value on TOS, rhs corresponds to the value
* in (e)ax. The return value is the the flags value for the resulting type.
*/
unsigned g_typecast (unsigned lhs, unsigned rhs);
/* Cast the value in the primary register to the operand size that is flagged
* by the lhs value. Return the result value.
*/
void g_scale (unsigned flags, long val);
/* Scale the value in the primary register by the given value. If val is positive,
* scale up, is val is negative, scale down. This function is used to scale
* the operands or results of pointer arithmetic by the size of the type, the
* pointer points to.
*/
/*****************************************************************************/
/* Function entry and exit */
/*****************************************************************************/
void g_enter (unsigned flags, const char* Name, unsigned argsize);
/* Function prologue */
void g_leave (int flags, int val);
/* Function epilogue */
/*****************************************************************************/
/* Register variables */
/*****************************************************************************/
void g_save_regvars (int RegOffs, unsigned Bytes);
/* Save register variables */
void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes);
/* Restore register variables */
/*****************************************************************************/
/* Fetching memory cells */
/*****************************************************************************/
void g_getimmed (unsigned flags, unsigned long val, unsigned offs);
void g_getstatic (unsigned flags, unsigned long label, unsigned offs);
void g_getlocal (unsigned flags, int offs);
void g_getind (unsigned flags, unsigned offs);
void g_leasp (int offs);
/*****************************************************************************/
/* Store into memory */
/*****************************************************************************/
void g_putstatic (unsigned flags, unsigned long label, unsigned offs);
/* Store the primary register into the specified static memory cell */
void g_putlocal (unsigned flags, int offs);
/* Put data into local object. */
void g_putind (unsigned flags, unsigned offs);
/* Store the specified object type in the primary register at the address
* on the top of the stack
*/
/*****************************************************************************/
/* Adds and subs of variables fix a fixed address */
/*****************************************************************************/
void g_addlocal (unsigned flags, int offs);
/* Add a local variable to ax */
void g_addstatic (unsigned flags, unsigned long label, unsigned offs);
/* Add a static variable to ax */
/*****************************************************************************/
/* Compares of ax with a variable with fixed address */
/*****************************************************************************/
void g_cmplocal (unsigned flags, int offs);
/* Compare a local variable to ax */
void g_cmpstatic (unsigned flags, unsigned label, unsigned offs);
/* Compare a static variable to ax */
/*****************************************************************************/
/* Special op= functions */
/*****************************************************************************/
void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs,
unsigned long val);
/* Emit += for a static variable */
void g_addeqlocal (unsigned flags, int offs, unsigned long val);
/* Emit += for a local variable */
void g_addeqind (unsigned flags, unsigned offs, unsigned long val);
/* Emit += for the location with address in ax */
void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
unsigned long val);
/* Emit -= for a static variable */
void g_subeqlocal (unsigned flags, int offs, unsigned long val);
/* Emit -= for a local variable */
void g_subeqind (unsigned flags, unsigned offs, unsigned long val);
/* Emit -= for the location with address in ax */
/*****************************************************************************/
/* Add a variable address to the value in ax */
/*****************************************************************************/
void g_addaddr_local (unsigned flags, int offs);
/* Add the address of a local variable to ax */
void g_addaddr_static (unsigned flags, unsigned long label, unsigned offs);
/* Add the address of a static variable to ax */
/*****************************************************************************/
/* */
/*****************************************************************************/
void g_save (unsigned flags);
void g_restore (unsigned flags);
void g_cmp (unsigned flags, unsigned long val);
/* Immidiate compare. The primary register will not be changed, Z flag
* will be set.
*/
void g_test (unsigned flags);
void g_push (unsigned flags, unsigned long val);
void g_swap (unsigned flags);
void g_call (unsigned flags, char *lbl, unsigned argsize);
void g_callind (unsigned flags, unsigned argsize);
void g_jump (unsigned label);
void g_switch (unsigned flags);
void g_case (unsigned flags, unsigned label, unsigned long val);
/* Create table code for one case selector */
void g_truejump (unsigned flags, unsigned label);
/* Jump to label if zero flag clear */
void g_falsejump (unsigned flags, unsigned label);
/* Jump to label if zero flag set */
void g_space (int space);
/* Create or drop space on the stack */
void g_add (unsigned flags, unsigned long val);
void g_sub (unsigned flags, unsigned long val);
void g_rsub (unsigned flags, unsigned long val);
void g_mul (unsigned flags, unsigned long val);
void g_div (unsigned flags, unsigned long val);
void g_mod (unsigned flags, unsigned long val);
void g_or (unsigned flags, unsigned long val);
void g_xor (unsigned flags, unsigned long val);
void g_and (unsigned flags, unsigned long val);
void g_asr (unsigned flags, unsigned long val);
void g_asl (unsigned flags, unsigned long val);
void g_neg (unsigned flags);
void g_bneg (unsigned flags);
void g_com (unsigned flags);
void g_inc (unsigned flags, unsigned long n);
void g_dec (unsigned flags, unsigned long n);
void g_eq (unsigned flags, unsigned long val);
void g_ne (unsigned flags, unsigned long val);
void g_lt (unsigned flags, unsigned long val);
void g_le (unsigned flags, unsigned long val);
void g_gt (unsigned flags, unsigned long val);
void g_ge (unsigned flags, unsigned long val);
void g_makebool (unsigned flags);
void outdat (int n);
void g_res (unsigned n);
void g_defdata (unsigned flags, unsigned long val, unsigned offs);
/* Define data with the size given in flags */
void g_defbytes (const unsigned char *bytes, unsigned count);
void g_zerobytes (unsigned n);
/*****************************************************************************/
/* Inlined known functions */
/*****************************************************************************/
void g_strlen (unsigned flags, unsigned long val, unsigned offs);
/* Inline the strlen() function */
/* End of codegen.h */
#endif

32
src/cc65/copyleft.jrd Normal file
View File

@@ -0,0 +1,32 @@
-*- Mode: Text -*-
This is the copyright notice for RA65, LINK65, LIBR65, and other
Atari 8-bit programs. Said programs are Copyright 1989, by John R.
Dunning. All rights reserved, with the following exceptions:
Anyone may copy or redistribute these programs, provided that:
1: You don't charge anything for the copy. It is permissable to
charge a nominal fee for media, etc.
2: All source code and documentation for the programs is made
available as part of the distribution.
3: This copyright notice is preserved verbatim, and included in
the distribution.
You are allowed to modify these programs, and redistribute the
modified versions, provided that the modifications are clearly noted.
There is NO WARRANTY with this software, it comes as is, and is
distributed in the hope that it may be useful.
This copyright notice applies to any program which contains
this text, or the refers to this file.
This copyright notice is based on the one published by the Free
Software Foundation, sometimes known as the GNU project. The idea
is the same as theirs, ie the software is free, and is intended to
stay that way. Everybody has the right to copy, modify, and re-
distribute this software. Nobody has the right to prevent anyone
else from copying, modifying or redistributing it.

137
src/cc65/ctrans.c Normal file
View File

@@ -0,0 +1,137 @@
/*****************************************************************************/
/* */
/* ctrans.c */
/* */
/* Character set translation for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "global.h"
#include "ctrans.h"
/*****************************************************************************/
/* data */
/*****************************************************************************/
static unsigned char CTNone [256] = {
/* No system - no translation */
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
static unsigned char CTAtari [256] = {
/* ASCII -> ATASCII */
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x7E,0x08,0x7F,0x9B,0x0B,0x7D,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
static unsigned char CTPET [256] = {
/* ASCII -> PETSCII */
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0x5B,0x5C,0x5D,0x5E,0x5F,
0xC0,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xDB,0xDC,0xDD,0xDE,0xDF,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x0C,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
static unsigned char* CTab [TGT_COUNT] = {
CTNone, /* No system */
CTAtari, /* Atari */
CTPET, /* C64 */
CTPET, /* C128 */
CTPET, /* ACE */
CTPET, /* Plus/4 */
CTPET, /* CBM610 */
CTPET, /* PET */
CTNone, /* NES */
CTNone, /* Apple2 */
CTPET, /* GEOS */
};
/*****************************************************************************/
/* code */
/*****************************************************************************/
int ctrans (unsigned char C)
/* Translate a character from source charset into target charset */
{
/* Translate for the given system */
return CTab [Target][C];
}

57
src/cc65/ctrans.h Normal file
View File

@@ -0,0 +1,57 @@
/*****************************************************************************/
/* */
/* ctrans.h */
/* */
/* Character set translation for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef CTRANS_H
#define CTRANS_H
/*****************************************************************************/
/* code */
/*****************************************************************************/
int ctrans (unsigned char c);
/* Translate a character from source charset into target charset */
/* End of ctrans.h */
#endif

568
src/cc65/datatype.c Normal file
View File

@@ -0,0 +1,568 @@
/*****************************************************************************/
/* */
/* datatype.c */
/* */
/* Type string handling for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include "check.h"
#include "codegen.h"
#include "datatype.h"
#include "error.h"
#include "funcdesc.h"
#include "global.h"
#include "mem.h"
#include "util.h"
#include "symtab.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Predefined type strings */
type type_int [] = { T_INT, T_END };
type type_uint [] = { T_UINT, T_END };
type type_long [] = { T_LONG, T_END };
type type_ulong [] = { T_ULONG, T_END };
type type_void [] = { T_VOID, T_END };
type type_pschar [] = { T_PTR, T_CHAR, T_END };
type type_puchar [] = { T_PTR, T_UCHAR, T_END };
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned TypeLen (const type* T)
/* Return the length of the type string */
{
const type* Start = T;
while (*T) {
++T;
}
return T - Start;
}
int TypeCmp (const type* T1, const type* T2)
/* Compare two type strings */
{
int A, B, D;
do {
A = *T1++;
B = *T2++;
D = A - B;
} while (D == 0 && A != 0);
return D;
}
type* TypeCpy (type* Dest, const type* Src)
/* Copy a type string */
{
type T;
type* Orig = Dest;
do {
T = *Src++;
*Dest++ = T;
} while (T);
return Orig;
}
type* TypeCat (type* Dest, const type* Src)
/* Append Src */
{
TypeCpy (Dest + TypeLen (Dest), Src);
return Dest;
}
type* TypeDup (const type* T)
/* Create a copy of the given type on the heap */
{
unsigned Len = (TypeLen (T) + 1) * sizeof (type);
return memcpy (xmalloc (Len), T, Len);
}
type* TypeAlloc (unsigned Len)
/* Allocate memory for a type string of length Len. Len *must* include the
* trailing T_END.
*/
{
return xmalloc (Len * sizeof (type));
}
void TypeFree (type* T)
/* Free a type string */
{
xfree (T);
}
type GetDefaultChar (void)
/* Return the default char type (signed/unsigned) depending on the settings */
{
return SignedChars? T_CHAR : T_UCHAR;
}
type* GetCharArrayType (unsigned Len)
/* Return the type for a char array of the given length */
{
/* Allocate memory for the type string */
type* T = TypeAlloc (1 + DECODE_SIZE + 2);
/* Fill the type string */
T [0] = T_ARRAY;
T [DECODE_SIZE+1] = GetDefaultChar();
T [DECODE_SIZE+2] = T_END;
/* Encode the length in the type string */
Encode (T+1, Len);
/* Return the new type */
return T;
}
type* GetImplicitFuncType (void)
/* Return a type string for an inplicitly declared function */
{
/* Get a new function descriptor */
FuncDesc* F = NewFuncDesc ();
/* Allocate memory for the type string */
type* T = TypeAlloc (1 + DECODE_SIZE + 2);
/* Prepare the function descriptor */
F->Flags = FD_IMPLICIT | FD_ELLIPSIS;
F->SymTab = &EmptySymTab;
F->StructTab = &EmptySymTab;
F->EnumTab = &EmptySymTab;
/* Fill the type string */
T [0] = T_FUNC;
T [DECODE_SIZE+1] = T_INT;
T [DECODE_SIZE+2] = T_END;
/* Encode the function descriptor into the type string */
EncodePtr (T+1, F);
/* Return the new type */
return T;
}
void PrintType (FILE* F, const type* tarray)
/* Output translation of type array. */
{
const type* p;
for (p = tarray; *p != T_END; ++p) {
if (*p & T_UNSIGNED) {
fprintf (F, "unsigned ");
}
switch (*p) {
case T_VOID:
fprintf (F, "void\n");
break;
case T_CHAR:
case T_UCHAR:
fprintf (F, "char\n");
break;
case T_INT:
case T_UINT:
fprintf (F, "int\n");
break;
case T_SHORT:
case T_USHORT:
fprintf (F, "short\n");
break;
case T_LONG:
case T_ULONG:
fprintf (F, "long\n");
break;
case T_FLOAT:
fprintf (F, "float\n");
break;
case T_DOUBLE:
fprintf (F, "double\n");
break;
case T_PTR:
fprintf (F, "pointer to ");
break;
case T_ARRAY:
fprintf (F, "array[%lu] of ", Decode (p + 1));
p += DECODE_SIZE;
break;
case T_STRUCT:
fprintf (F, "struct %s\n", ((SymEntry*) Decode (p + 1))->Name);
p += DECODE_SIZE;
break;
case T_UNION:
fprintf (F, "union %s\n", ((SymEntry*) Decode (p + 1))->Name);
p += DECODE_SIZE;
break;
case T_FUNC:
fprintf (F, "function returning ");
p += DECODE_SIZE;
break;
default:
fprintf (F, "unknown type: %04X\n", *p);
}
}
}
void PrintRawType (FILE* F, const type* Type)
/* Print a type string in raw format (for debugging) */
{
while (*Type != T_END) {
fprintf (F, "%04X ", *Type++);
}
fprintf (F, "\n");
}
void Encode (type* Type, unsigned long Val)
/* Encode p[0] and p[1] so that neither p[0] nore p[1] is zero */
{
int I;
for (I = 0; I < DECODE_SIZE; ++I) {
*Type++ = ((type) Val) | 0x8000;
Val >>= 15;
}
}
void EncodePtr (type* Type, void* P)
/* Encode a pointer into a type array */
{
Encode (Type, (unsigned long) P);
}
unsigned long Decode (const type* Type)
/* Decode */
{
int I;
unsigned long Val = 0;
for (I = DECODE_SIZE-1; I >= 0; I--) {
Val <<= 15;
Val |= (Type[I] & 0x7FFF);
}
return Val;
}
void* DecodePtr (const type* Type)
/* Decode a pointer from a type array */
{
return (void*) Decode (Type);
}
int HasEncode (const type* Type)
/* Return true if the given type has encoded data */
{
return IsStruct (Type) || IsArray (Type) || IsFunc (Type);
}
void CopyEncode (const type* Source, type* Target)
/* Copy encoded data from Source to Target */
{
memcpy (Target, Source, DECODE_SIZE * sizeof (type));
}
unsigned SizeOf (const type* tarray)
/* Compute size of object represented by type array. */
{
SymEntry* Entry;
switch (*tarray) {
case T_VOID:
return 0;
case T_CHAR:
case T_UCHAR:
return 1;
case T_INT:
case T_UINT:
case T_SHORT:
case T_USHORT:
case T_PTR:
case T_ENUM:
return 2;
case T_LONG:
case T_ULONG:
return 4;
case T_ARRAY:
return (Decode (tarray + 1) * SizeOf (tarray + DECODE_SIZE + 1));
case T_STRUCT:
case T_UNION:
Entry = DecodePtr (tarray+1);
return Entry->V.S.Size;
default:
Internal ("Unknown type: %04X", *tarray);
return 0;
}
}
unsigned PSizeOf (const type* tptr)
/* Compute size of pointer object. */
{
/* We are expecting a pointer expression */
CHECK (*tptr & T_POINTER);
/* Skip the pointer or array token itself */
if (*tptr == T_ARRAY) {
return SizeOf (tptr + DECODE_SIZE + 1);
} else {
return SizeOf (tptr + 1);
}
}
unsigned TypeOf (const type* Type)
/* Get the code generator base type of the object */
{
FuncDesc* F;
switch (*Type) {
case T_CHAR:
return CF_CHAR;
case T_UCHAR:
return CF_CHAR | CF_UNSIGNED;
case T_SHORT:
case T_INT:
case T_ENUM:
return CF_INT;
case T_USHORT:
case T_UINT:
case T_PTR:
case T_ARRAY:
return CF_INT | CF_UNSIGNED;
case T_LONG:
return CF_LONG;
case T_ULONG:
return CF_LONG | CF_UNSIGNED;
case T_FUNC:
F = DecodePtr (Type+1);
return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC;
case T_STRUCT:
case T_UNION:
/* Address of ... */
return CF_INT | CF_UNSIGNED;
default:
Error (ERR_ILLEGAL_TYPE);
return CF_INT;
}
}
type* Indirect (type* Type)
/* Do one indirection for the given type, that is, return the type where the
* given type points to.
*/
{
/* We are expecting a pointer expression */
CHECK (Type[0] & T_POINTER);
/* Skip the pointer or array token itself */
if (Type[0] == T_ARRAY) {
return Type + DECODE_SIZE + 1;
} else {
return Type + 1;
}
}
int IsVoid (const type* Type)
/* Return true if this is a void type */
{
return (Type[0] == T_VOID && Type[1] == T_END);
}
int IsPtr (const type* Type)
/* Return true if this is a pointer type */
{
return (Type[0] & T_POINTER) != 0;
}
int IsChar (const type* Type)
/* Return true if this is a character type */
{
return (Type[0] == T_CHAR || Type[0] == T_UCHAR) && Type[1] == T_END;
}
int IsInt (const type* Type)
/* Return true if this is an integer type */
{
return (Type[0] & T_INTEGER) != 0;
}
int IsLong (const type* Type)
/* Return true if this is a long type (signed or unsigned) */
{
return (Type[0] & T_LONG) == T_LONG;
}
int IsUnsigned (const type* Type)
/* Return true if this is an unsigned type */
{
return (Type[0] & T_UNSIGNED) != 0;
}
int IsStruct (const type* Type)
/* Return true if this is a struct type */
{
return (Type[0] == T_STRUCT || Type[0] == T_UNION);
}
int IsFunc (const type* Type)
/* Return true if this is a function type */
{
return (Type[0] == T_FUNC);
}
int IsFastCallFunc (const type* Type)
/* Return true if this is a function type with __fastcall__ calling conventions */
{
FuncDesc* F;
CHECK (*Type == T_FUNC);
F = DecodePtr (Type+1);
return (F->Flags & FD_FASTCALL) != 0;
}
int IsFuncPtr (const type* Type)
/* Return true if this is a function pointer */
{
return (Type[0] == T_PTR && Type[1] == T_FUNC);
}
int IsArray (const type* Type)
/* Return true if this is an array type */
{
return (Type[0] == T_ARRAY);
}
struct FuncDesc* GetFuncDesc (const type* Type)
/* Get the FuncDesc pointer from a function or pointer-to-function type */
{
if (Type[0] == T_PTR) {
/* Pointer to function */
++Type;
}
/* Be sure it's a function type */
CHECK (Type[0] == T_FUNC);
/* Decode the function descriptor and return it */
return DecodePtr (Type+1);
}

223
src/cc65/datatype.h Normal file
View File

@@ -0,0 +1,223 @@
/*****************************************************************************/
/* */
/* datatype.h */
/* */
/* Type string handling for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef DATATYPE_H
#define DATATYPE_H
#include <stdio.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Data types */
#define T_END 0x0000
#define T_CHAR 0x0011
#define T_INT 0x0012
#define T_SHORT 0x0013
#define T_LONG 0x0014
#define T_ENUM 0x0015
#define T_UCHAR 0x0019
#define T_UINT 0x001A
#define T_USHORT 0x001B
#define T_ULONG 0x001C
#define T_FLOAT 0x0025
#define T_DOUBLE 0x0026
#define T_VOID 0x0001 /* void parameter list */
#define T_FUNC 0x0002 /* Function */
#define T_UNSIGNED 0x0008 /* Class */
#define T_INTEGER 0x0010 /* Class */
#define T_REAL 0x0020 /* Class */
#define T_POINTER 0x0040 /* Class */
#define T_PTR 0x0049
#define T_ARRAY 0x004A
#define T_STRUCT 0x0080
#define T_UNION 0x0081
#define T_SMASK 0x003F
/* Forward for a symbol entry */
struct SymEntry;
/* Type entry */
typedef unsigned short type;
/* Maximum length of a type string */
#define MAXTYPELEN 30
/* type elements needed for Encode/Decode */
#define DECODE_SIZE 5
/* Predefined type strings */
extern type type_int [];
extern type type_uint [];
extern type type_long [];
extern type type_ulong [];
extern type type_void [];
extern type type_pschar [];
extern type type_puchar [];
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned TypeLen (const type* Type);
/* Return the length of the type string */
int TypeCmp (const type* T1, const type* T2);
/* Compare two type strings */
type* TypeCpy (type* Dest, const type* Src);
/* Copy a type string */
type* TypeCat (type* Dest, const type* Src);
/* Append Src */
type* TypeDup (const type* Type);
/* Create a copy of the given type on the heap */
type* TypeAlloc (unsigned Len);
/* Allocate memory for a type string of length Len. Len *must* include the
* trailing T_END.
*/
void TypeFree (type* Type);
/* Free a type string */
type GetDefaultChar (void);
/* Return the default char type (signed/unsigned) depending on the settings */
type* GetCharArrayType (unsigned Len);
/* Return the type for a char array of the given length */
type* GetImplicitFuncType (void);
/* Return a type string for an inplicitly declared function */
void PrintType (FILE* F, const type* Type);
/* Output translation of type array. */
void PrintRawType (FILE* F, const type* Type);
/* Print a type string in raw format (for debugging) */
void Encode (type* Type, unsigned long Val);
/* Encode an unsigned long into a type array */
void EncodePtr (type* Type, void* P);
/* Encode a pointer into a type array */
unsigned long Decode (const type* Type);
/* Decode an unsigned long from a type array */
void* DecodePtr (const type* Type);
/* Decode a pointer from a type array */
int HasEncode (const type* Type);
/* Return true if the given type has encoded data */
void CopyEncode (const type* Source, type* Target);
/* Copy encoded data from Source to Target */
unsigned SizeOf (const type* Type);
/* Compute size of object represented by type array. */
unsigned PSizeOf (const type* Type);
/* Compute size of pointer object. */
unsigned TypeOf (const type* Type);
/* Get the code generator base type of the object */
type* Indirect (type* Type);
/* Do one indirection for the given type, that is, return the type where the
* given type points to.
*/
int IsVoid (const type* Type);
/* Return true if this is a void type */
int IsPtr (const type* Type);
/* Return true if this is a pointer type */
int IsChar (const type* Type);
/* Return true if this is a character type */
int IsInt (const type* Type);
/* Return true if this is an integer type */
int IsLong (const type* Type);
/* Return true if this is a long type (signed or unsigned) */
int IsUnsigned (const type* Type);
/* Return true if this is an unsigned type */
int IsStruct (const type* Type);
/* Return true if this is a struct type */
int IsFunc (const type* Type);
/* Return true if this is a function type */
int IsFastCallFunc (const type* Type);
/* Return true if this is a function type with __fastcall__ calling conventions */
int IsFuncPtr (const type* Type);
/* Return true if this is a function pointer */
int IsArray (const type* Type);
/* Return true if this is an array type */
struct FuncDesc* GetFuncDesc (const type* Type);
/* Get the FuncDesc pointer from a function or pointer-to-function type */
/* End of datatype.h */
#endif

938
src/cc65/declare.c Normal file
View File

@@ -0,0 +1,938 @@
/*
* declare.c
*
* Ullrich von Bassewitz, 20.06.1998
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "anonname.h"
#include "codegen.h"
#include "datatype.h"
#include "error.h"
#include "expr.h"
#include "funcdesc.h"
#include "function.h"
#include "global.h"
#include "litpool.h"
#include "mem.h"
#include "pragma.h"
#include "scanner.h"
#include "symtab.h"
#include "declare.h"
/*****************************************************************************/
/* Forwards */
/*****************************************************************************/
static void ParseTypeSpec (DeclSpec* D, int Default);
/* Parse a type specificier */
/*****************************************************************************/
/* internal functions */
/*****************************************************************************/
static void optional_modifiers (void)
/* Eat optional "const" or "volatile" tokens */
{
while (curtok == CONST || curtok == VOLATILE) {
/* Skip it */
gettok ();
}
}
static void optionalint (void)
/* Eat an optional "int" token */
{
if (curtok == INT) {
/* Skip it */
gettok ();
}
}
static void optionalsigned (void)
/* Eat an optional "signed" token */
{
if (curtok == SIGNED) {
/* Skip it */
gettok ();
}
}
static void InitDeclSpec (DeclSpec* D)
/* Initialize the DeclSpec struct for use */
{
D->StorageClass = 0;
D->Type[0] = T_END;
D->Flags = 0;
}
static void InitDeclaration (Declaration* D)
/* Initialize the Declaration struct for use */
{
D->Ident[0] = '\0';
D->Type[0] = T_END;
D->T = D->Type;
}
static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
/* Parse a storage class */
{
/* Assume we're using an explicit storage class */
D->Flags &= ~DS_DEF_STORAGE;
/* Check the storage class given */
switch (curtok) {
case EXTERN:
D->StorageClass = SC_EXTERN | SC_STATIC;
gettok ();
break;
case STATIC:
D->StorageClass = SC_STATIC;
gettok ();
break;
case REGISTER:
D->StorageClass = SC_REGISTER | SC_STATIC;
gettok ();
break;
case AUTO:
D->StorageClass = SC_AUTO;
gettok ();
break;
case TYPEDEF:
D->StorageClass = SC_TYPEDEF;
gettok ();
break;
default:
/* No storage class given, use default */
D->Flags |= DS_DEF_STORAGE;
D->StorageClass = DefStorage;
break;
}
}
static void ParseEnumDecl (void)
/* Process an enum declaration . */
{
int EnumVal;
ident Ident;
/* Accept forward definitions */
if (curtok != LCURLY) {
return;
}
/* Skip the opening curly brace */
gettok ();
/* Read the enum tags */
EnumVal = 0;
while (curtok != RCURLY) {
/* We expect an identifier */
if (curtok != IDENT) {
Error (ERR_IDENT_EXPECTED);
continue;
}
/* Remember the identifier and skip it */
strcpy (Ident, CurTok.Ident);
gettok ();
/* Check for an assigned value */
if (curtok == ASGN) {
struct expent lval;
gettok ();
constexpr (&lval);
EnumVal = lval.e_const;
}
/* Add an entry to the symbol table */
AddEnumSym (Ident, EnumVal++);
/* Check for end of definition */
if (curtok != COMMA)
break;
gettok ();
}
ConsumeRCurly ();
}
static SymEntry* ParseStructDecl (const char* Name, type StructType)
/* Parse a struct/union declaration. */
{
unsigned Size;
unsigned Offs;
SymTable* FieldTab;
SymEntry* Entry;
if (curtok != LCURLY) {
/* Just a forward declaration. Try to find a struct with the given
* name. If there is none, insert a forward declaration into the
* current lexical level.
*/
Entry = FindStructSym (Name);
if (Entry == 0 || Entry->Flags != SC_STRUCT) {
Entry = AddStructSym (Name, 0, 0);
}
return Entry;
}
/* Add a forward declaration for the struct in the current lexical level */
Entry = AddStructSym (Name, 0, 0);
/* Skip the curly brace */
gettok ();
/* Enter a new lexical level for the struct */
EnterStructLevel ();
/* Parse struct fields */
Size = 0;
while (curtok != RCURLY) {
/* Get the type of the entry */
DeclSpec Spec;
InitDeclSpec (&Spec);
ParseTypeSpec (&Spec, -1);
/* Read fields with this type */
while (1) {
/* Get type and name of the struct field */
Declaration Decl;
ParseDecl (&Spec, &Decl, 0);
/* Add a field entry to the table */
AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
/* Calculate offset of next field/size of the union */
Offs = SizeOf (Decl.Type);
if (StructType == T_STRUCT) {
Size += Offs;
} else {
if (Offs > Size) {
Size = Offs;
}
}
if (curtok != COMMA)
break;
gettok ();
}
ConsumeSemi ();
}
/* Skip the closing brace */
gettok ();
/* Remember the symbol table and leave the struct level */
FieldTab = GetSymTab ();
LeaveStructLevel ();
/* Make a real entry from the forward decl and return it */
return AddStructSym (Name, Size, FieldTab);
}
static void ParseTypeSpec (DeclSpec* D, int Default)
/* Parse a type specificier */
{
ident Ident;
SymEntry* Entry;
type StructType;
/* Assume have an explicit type */
D->Flags &= ~DS_DEF_TYPE;
/* Skip const or volatile modifiers if needed */
optional_modifiers ();
/* Look at the data type */
switch (curtok) {
case VOID:
gettok ();
D->Type[0] = T_VOID;
D->Type[1] = T_END;
break;
case CHAR:
gettok ();
D->Type[0] = GetDefaultChar();
D->Type[1] = T_END;
break;
case LONG:
gettok ();
if (curtok == UNSIGNED) {
gettok ();
optionalint ();
D->Type[0] = T_ULONG;
D->Type[1] = T_END;
} else {
optionalsigned ();
optionalint ();
D->Type[0] = T_LONG;
D->Type[1] = T_END;
}
break;
case SHORT:
gettok ();
if (curtok == UNSIGNED) {
gettok ();
optionalint ();
D->Type[0] = T_USHORT;
D->Type[1] = T_END;
} else {
optionalsigned ();
optionalint ();
D->Type[0] = T_SHORT;
D->Type[1] = T_END;
}
break;
case INT:
gettok ();
D->Type[0] = T_INT;
D->Type[1] = T_END;
break;
case SIGNED:
gettok ();
switch (curtok) {
case CHAR:
gettok ();
D->Type[0] = T_CHAR;
D->Type[1] = T_END;
break;
case SHORT:
gettok ();
optionalint ();
D->Type[0] = T_SHORT;
D->Type[1] = T_END;
break;
case LONG:
gettok ();
optionalint ();
D->Type[0] = T_LONG;
D->Type[1] = T_END;
break;
case INT:
gettok ();
/* FALL THROUGH */
default:
D->Type[0] = T_INT;
D->Type[1] = T_END;
break;
}
break;
case UNSIGNED:
gettok ();
switch (curtok) {
case CHAR:
gettok ();
D->Type[0] = T_UCHAR;
D->Type[1] = T_END;
break;
case SHORT:
gettok ();
optionalint ();
D->Type[0] = T_USHORT;
D->Type[1] = T_END;
break;
case LONG:
gettok ();
optionalint ();
D->Type[0] = T_ULONG;
D->Type[1] = T_END;
break;
case INT:
gettok ();
/* FALL THROUGH */
default:
D->Type[0] = T_UINT;
D->Type[1] = T_END;
break;
}
break;
case STRUCT:
case UNION:
StructType = (curtok == STRUCT)? T_STRUCT : T_UNION;
gettok ();
if (curtok == IDENT) {
strcpy (Ident, CurTok.Ident);
gettok ();
} else {
AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
}
/* Declare the struct in the current scope */
Entry = ParseStructDecl (Ident, StructType);
/* Encode the struct entry into the type */
D->Type[0] = StructType;
EncodePtr (D->Type+1, Entry);
D->Type[DECODE_SIZE+1] = T_END;
break;
case ENUM:
gettok ();
if (curtok != LCURLY) {
/* Named enum */
Consume (IDENT, ERR_IDENT_EXPECTED);
}
ParseEnumDecl ();
D->Type[0] = T_INT;
D->Type[1] = T_END;
break;
case IDENT:
Entry = FindSym (CurTok.Ident);
if (Entry && IsTypeDef (Entry)) {
/* It's a typedef */
gettok ();
TypeCpy (D->Type, Entry->Type);
break;
}
/* FALL THROUGH */
default:
if (Default < 0) {
Error (ERR_TYPE_EXPECTED);
D->Type[0] = T_INT;
D->Type[1] = T_END;
} else {
D->Flags |= DS_DEF_TYPE;
D->Type[0] = (type) Default;
D->Type[1] = T_END;
}
break;
}
}
static FuncDesc* ParseFuncDecl (void)
/* Parse the argument list of a function. */
{
unsigned UnnamedCount = 0;
unsigned Offs;
SymEntry* Sym;
type* Type;
/* Create a new function descriptor */
FuncDesc* F = NewFuncDesc ();
/* Enter a new lexical level */
EnterFunctionLevel ();
/* Check for an empty or void parameter list */
if (curtok == RPAREN) {
/* Parameter list is empty */
F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
} else if (curtok == VOID && nxttok == RPAREN) {
/* Parameter list declared as void */
gettok ();
F->Flags |= FD_VOID_PARAM;
}
/* Parse params */
while (curtok != RPAREN) {
DeclSpec Spec;
Declaration Decl;
/* Allow an ellipsis as last parameter */
if (curtok == ELLIPSIS) {
gettok ();
F->Flags |= FD_ELLIPSIS;
break;
}
/* Read the declaration specifier */
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
/* We accept only auto and register as storage class specifiers, but
* we ignore all this and use auto.
*/
if ((Spec.StorageClass & SC_AUTO) == 0 &&
(Spec.StorageClass & SC_REGISTER) == 0) {
Error (ERR_ILLEGAL_STORAGE_CLASS);
}
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
/* Allow parameters without a name, but remember if we had some to
* eventually print an error message later.
*/
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
if (Decl.Ident[0] == '\0') {
/* Unnamed symbol. Generate a name that is not user accessible,
* then handle the symbol normal.
*/
AnonName (Decl.Ident, "param");
++UnnamedCount;
/* Clear defined bit on nonames */
Spec.StorageClass &= ~SC_DEF;
}
/* If the parameter is an array, convert it to a pointer */
Type = Decl.Type;
if (IsArray (Type)) {
Type += DECODE_SIZE;
Type[0] = T_PTR;
}
/* Create a symbol table entry */
AddLocalSym (Decl.Ident, Type, Spec.StorageClass, 0);
/* Count arguments */
++F->ParamCount;
F->ParamSize += SizeOf (Type);
/* Check for more parameters */
if (curtok == COMMA) {
gettok ();
} else {
break;
}
}
/* Skip right paren. We must explicitly check for one here, since some of
* the breaks above bail out without checking.
*/
ConsumeRParen ();
/* Assign offsets. If the function has a variable parameter list,
* there's one additional byte (the arg size).
*/
Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
Sym = GetSymTab()->SymTail;
while (Sym) {
Sym->V.Offs = Offs;
Offs += SizeOf (Sym->Type);
Sym = Sym->PrevSym;
}
/* Check if this is a function definition */
if (curtok == LCURLY) {
/* Print an error if in strict ANSI mode and we have unnamed
* parameters.
*/
if (ANSI && UnnamedCount > 0) {
Error (ERR_MISSING_PARAM_NAME);
}
}
/* Leave the lexical level remembering the symbol tables */
RememberFunctionLevel (F);
/* Return the function descriptor */
return F;
}
static void Decl (Declaration* D, unsigned Mode)
/* Recursively process declarators. Build a type array in reverse order. */
{
if (curtok == STAR) {
gettok ();
/* Allow optional const or volatile modifiers */
optional_modifiers ();
Decl (D, Mode);
*D->T++ = T_PTR;
return;
} else if (curtok == LPAREN) {
gettok ();
Decl (D, Mode);
ConsumeRParen ();
} else if (curtok == FASTCALL) {
/* Remember the current type pointer */
type* T = D->T;
/* Skip the fastcall token */
gettok ();
/* Parse the function */
Decl (D, Mode);
/* Set the fastcall flag */
if (!IsFunc (T)) {
Error (ERR_ILLEGAL_MODIFIER);
} else {
FuncDesc* F = DecodePtr (T+1);
F->Flags |= FD_FASTCALL;
}
return;
} else {
/* Things depend on Mode now:
* - Mode == DM_NEED_IDENT means:
* we *must* have a type and a variable identifer.
* - Mode == DM_NO_IDENT means:
* we must have a type but no variable identifer
* (if there is one, it's not read).
* - Mode == DM_ACCEPT_IDENT means:
* we *may* have an identifier. If there is an identifier,
* it is read, but it is no error, if there is none.
*/
if (Mode == DM_NO_IDENT) {
D->Ident[0] = '\0';
} else if (curtok == IDENT) {
strcpy (D->Ident, CurTok.Ident);
gettok ();
} else {
if (Mode == DM_NEED_IDENT) {
Error (ERR_IDENT_EXPECTED);
}
D->Ident[0] = '\0';
return;
}
}
while (curtok == LBRACK || curtok == LPAREN) {
if (curtok == LPAREN) {
/* Function declaration */
FuncDesc* F;
gettok ();
/* Parse the function declaration */
F = ParseFuncDecl ();
*D->T++ = T_FUNC;
EncodePtr (D->T, F);
D->T += DECODE_SIZE;
} else {
/* Array declaration */
unsigned long Size = 0;
gettok ();
/* Read the size if it is given */
if (curtok != RBRACK) {
struct expent lval;
constexpr (&lval);
Size = lval.e_const;
}
ConsumeRBrack ();
*D->T++ = T_ARRAY;
Encode (D->T, Size);
D->T += DECODE_SIZE;
}
}
}
/*****************************************************************************/
/* code */
/*****************************************************************************/
type* ParseType (type* Type)
/* Parse a complete type specification */
{
DeclSpec Spec;
Declaration Decl;
/* Get a type without a default */
InitDeclSpec (&Spec);
ParseTypeSpec (&Spec, -1);
/* Parse additional declarators */
InitDeclaration (&Decl);
ParseDecl (&Spec, &Decl, DM_NO_IDENT);
/* Copy the type to the target buffer */
TypeCpy (Type, Decl.Type);
/* Return a pointer to the target buffer */
return Type;
}
void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
/* Parse a variable, type or function declaration */
{
/* Initialize the Declaration struct */
InitDeclaration (D);
/* Get additional declarators and the identifier */
Decl (D, Mode);
/* Add the base type. */
TypeCpy (D->T, Spec->Type);
/* Check the size of the generated type */
if (!IsFunc (D->Type) && SizeOf (D->Type) >= 0x10000) {
Error (ERR_ILLEGAL_SIZE);
}
}
void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
/* Parse a declaration specification */
{
/* Initialize the DeclSpec struct */
InitDeclSpec (D);
/* First, get the storage class specifier for this declaration */
ParseStorageClass (D, DefStorage);
/* Parse the type specifiers */
ParseTypeSpec (D, DefType);
}
static void ParseVoidInit (void)
/* Parse an initialization of a void variable (special cc65 extension) */
{
struct expent lval;
/* Allow an arbitrary list of values */
ConsumeLCurly ();
do {
constexpr (&lval);
switch (lval.e_tptr[0]) {
case T_CHAR:
case T_UCHAR:
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
/* Make it byte sized */
lval.e_const &= 0xFF;
}
DefineData (&lval);
break;
case T_SHORT:
case T_USHORT:
case T_INT:
case T_UINT:
case T_PTR:
case T_ARRAY:
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
/* Make it word sized */
lval.e_const &= 0xFFFF;
}
DefineData (&lval);
break;
case T_LONG:
case T_ULONG:
DefineData (&lval);
break;
default:
Error (ERR_ILLEGAL_TYPE);
break;
}
if (curtok != COMMA) {
break;
}
gettok ();
} while (curtok != RCURLY);
ConsumeRCurly ();
}
static void ParseStructInit (type* Type)
/* Parse initialization of a struct or union */
{
SymEntry* Entry;
SymTable* Tab;
/* Consume the opening curly brace */
ConsumeLCurly ();
/* Get a pointer to the struct entry from the type */
Entry = (SymEntry*) Decode (Type + 1);
/* Check if this struct definition has a field table. If it doesn't, it
* is an incomplete definition.
*/
Tab = Entry->V.S.SymTab;
if (Tab == 0) {
Error (ERR_INIT_INCOMPLETE_TYPE);
/* Returning here will cause lots of errors, but recovery is difficult */
return;
}
/* Get a pointer to the list of symbols */
Entry = Tab->SymHead;
while (curtok != RCURLY) {
if (Entry == NULL) {
Error (ERR_TOO_MANY_INITIALIZERS);
return;
}
ParseInit (Entry->Type);
Entry = Entry->NextSym;
if (curtok != COMMA)
break;
gettok ();
}
/* Consume the closing curly brace */
ConsumeRCurly ();
/* If there are struct fields left, reserve additional storage */
while (Entry) {
g_zerobytes (SizeOf (Entry->Type));
Entry = Entry->NextSym;
}
}
void ParseInit (type *tptr)
/* Parse initialization of variables */
{
int count;
struct expent lval;
type* t;
const char* str;
int sz;
switch (*tptr) {
case T_CHAR:
case T_UCHAR:
constexpr (&lval);
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
/* Make it byte sized */
lval.e_const &= 0xFF;
}
assignadjust (tptr, &lval);
DefineData (&lval);
break;
case T_SHORT:
case T_USHORT:
case T_INT:
case T_UINT:
case T_PTR:
constexpr (&lval);
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
/* Make it word sized */
lval.e_const &= 0xFFFF;
}
assignadjust (tptr, &lval);
DefineData (&lval);
break;
case T_LONG:
case T_ULONG:
constexpr (&lval);
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
/* Make it long sized */
lval.e_const &= 0xFFFFFFFF;
}
assignadjust (tptr, &lval);
DefineData (&lval);
break;
case T_ARRAY:
sz = Decode (tptr + 1);
t = tptr + DECODE_SIZE + 1;
if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == SCONST) {
str = GetLiteral (curval);
count = strlen (str) + 1;
TranslateLiteralPool (curval); /* Translate into target charset */
g_defbytes (str, count);
ResetLiteralOffs (curval); /* Remove string from pool */
gettok ();
} else {
ConsumeLCurly ();
count = 0;
while (curtok != RCURLY) {
ParseInit (tptr + DECODE_SIZE + 1);
++count;
if (curtok != COMMA)
break;
gettok ();
}
ConsumeRCurly ();
}
if (sz == 0) {
Encode (tptr + 1, count);
} else if (count < sz) {
g_zerobytes ((sz - count) * SizeOf (tptr + DECODE_SIZE + 1));
} else if (count > sz) {
Error (ERR_TOO_MANY_INITIALIZERS);
}
break;
case T_STRUCT:
case T_UNION:
ParseStructInit (tptr);
break;
case T_VOID:
if (!ANSI) {
/* Special cc65 extension in non ANSI mode */
ParseVoidInit ();
break;
}
/* FALLTHROUGH */
default:
Error (ERR_ILLEGAL_TYPE);
break;
}
}

79
src/cc65/declare.h Normal file
View File

@@ -0,0 +1,79 @@
/*
* declare.h
*
* Ullrich von Bassewitz, 20.06.1998
*/
#ifndef DECLARE_H
#define DECLARE_H
#include "scanner.h"
#include "symtab.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Masks for the Flags field in DeclSpec */
#define DS_DEF_STORAGE 0x0001U /* Default storage class used */
#define DS_DEF_TYPE 0x0002U /* Default type used */
/* Result of ParseDeclSpec */
typedef struct DeclSpec DeclSpec;
struct DeclSpec {
unsigned StorageClass; /* One of the SC_xxx flags */
type Type [MAXTYPELEN]; /* Type of the declaration spec */
unsigned Flags; /* Bitmapped flags */
};
/* Result of ParseDecl */
typedef struct Declaration Declaration;
struct Declaration {
ident Ident; /* The identifier if any, else empty */
type Type [MAXTYPELEN]; /* The type */
/* Working variables */
type* T; /* Used to build Type */
};
/* Modes for ParseDecl */
#define DM_NEED_IDENT 0U /* We must have an identifier */
#define DM_NO_IDENT 1U /* We won't read an identifier */
#define DM_ACCEPT_IDENT 2U /* We will accept an id if there is one */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
type* ParseType (type* Type);
/* Parse a complete type specification */
void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode);
/* Parse a variable, type or function declaration */
void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType);
/* Parse a declaration specification */
void ParseInit (type* tptr);
/* Parse initialization of variables */
/* End of declare.h */
#endif

310
src/cc65/error.c Normal file
View File

@@ -0,0 +1,310 @@
/*****************************************************************************/
/* */
/* error.c */
/* */
/* Error handling for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "global.h"
#include "io.h"
#include "scanner.h"
#include "stmt.h"
#include "error.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static char* WarnMsg [WARN_COUNT-1] = {
"Unreachable code",
"Condition is never true",
"Condition is always true",
"Converting pointer to integer without a cast",
"Converting integer to pointer without a cast",
"Function call without a prototype",
"Unknown #pragma",
"No case labels",
"Function must be extern",
"Parameter `%s' is never used",
"`%s' is defined but never used",
"Constant is long",
"`/*' found inside a comment",
};
/* Error messages sorted by ErrTypes */
static char* ErrMsg [ERR_COUNT-1] = {
"Invalid character (%u)",
"Unexpected newline",
"End-of-file reached in comment starting at line %u",
"Syntax error",
"`\"' expected",
"`:' expected",
"`;' expected",
"`(' expected",
"`)' expected",
"`[' expected",
"`]' expected",
"`{' expected",
"`}' expected",
"Identifier expected",
"Type expected",
"Incompatible types",
"Incompatible pointer types",
"Too many arguments in function call",
"Too few arguments in function call",
"Macro argument count mismatch",
"Duplicate macro parameter: %s",
"Variable identifier expected",
"Integer expression expected",
"Constant expression expected",
"No active loop",
"`\"' or `<' expected",
"Missing terminator or name too long",
"Include file `%s' not found",
"Open failure on include file `%s'",
"Invalid #error directive",
"#error: %s",
"Unexpected `#endif'",
"Unexpected `#else'",
"`#endif' expected",
"Compiler directive expected",
"Symbol `%s' defined more than once",
"String literal expected",
"`while' expected",
"Function must return a value",
"Function cannot return a value",
"Unexpected `continue'",
"Undefined symbol: `%s'",
"Undefined label: `%s'",
"Include nesting too deep",
"Too many local variables",
"Too many initializers",
"Cannot initialize incomplete type",
"Cannot subscript",
"Operation not allowed on these types",
"Struct expected",
"Struct/union has no field named `%s'",
"Struct pointer expected",
"lvalue expected",
"Expression expected",
"Preprocessor expression expected",
"Illegal type",
"Illegal function call",
"Illegal indirection",
"Illegal address",
"Illegal macro call",
"Illegal hex digit",
"Illegal character constant",
"Illegal modifier",
"Illegal storage class",
"Division by zero",
"Modulo operation with zero",
"Range error",
"Symbol is already different kind",
"Too many lexical levels",
"Parameter name omitted",
"Old style function decl used as prototype",
"Declaration for parameter `%s' but no such parameter",
"Cannot take address of a register variable",
"Illegal size of data type",
"__fastcall__ is not allowed for C functions",
"Variable has unknown size",
};
static char* FatMsg [FAT_COUNT-1] = {
"Too many errors",
"Cannot open output file: %s",
"Cannot write to output file (disk full?)",
"Cannot open input file: %s",
"Out of memory",
"Stack overflow",
"Stack empty",
"Out of string space",
"Too many case labels",
};
/* Count of errors/warnings */
unsigned ErrorCount = 0;
unsigned WarningCount = 0;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void Warning (unsigned WarnNum, ...)
/* Print warning message. */
{
va_list ap;
if (!NoWarn) {
fprintf (stderr, "%s(%u): Warning #%u: ", fin, curpos, WarnNum);
va_start (ap, WarnNum);
vfprintf (stderr, WarnMsg [WarnNum-1], ap);
va_end (ap);
fprintf (stderr, "\n");
if (Verbose) {
fprintf (stderr, "Line: %s\n", line);
}
}
++ WarningCount;
}
void PPWarning (unsigned WarnNum, ...)
/* Print warning message. For use within the preprocessor. */
{
va_list ap;
if (!NoWarn) {
fprintf (stderr, "%s(%u): Warning #%u: ", fin, ln, WarnNum);
va_start (ap, WarnNum);
vfprintf (stderr, WarnMsg [WarnNum-1], ap);
va_end (ap);
fprintf (stderr, "\n");
}
++WarningCount;
}
void Error (unsigned ErrNum, ...)
/* Print an error message */
{
va_list ap;
fprintf (stderr, "%s(%u): Error #%u: ", fin, curpos, ErrNum);
va_start (ap, ErrNum);
vfprintf (stderr, ErrMsg [ErrNum-1], ap);
va_end (ap);
fprintf (stderr, "\n");
if (Verbose) {
fprintf (stderr, "Line: %s\n", line);
}
++ErrorCount;
if (ErrorCount > 10) {
Fatal (FAT_TOO_MANY_ERRORS);
}
}
void PPError (unsigned ErrNum, ...)
/* Print an error message. For use within the preprocessor. */
{
va_list ap;
fprintf (stderr, "%s(%u): Error #%u: ", fin, ln, ErrNum);
va_start (ap, ErrNum);
vfprintf (stderr, ErrMsg [ErrNum-1], ap);
va_end (ap);
fprintf (stderr, "\n");
++ErrorCount;
if (ErrorCount > 10) {
Fatal (FAT_TOO_MANY_ERRORS);
}
}
void Fatal (unsigned FatNum, ...)
/* Print a message about a fatal error and die */
{
va_list ap;
fprintf (stderr, "%s(%u): Fatal #%u: ", fin, curpos, FatNum);
va_start (ap, FatNum);
vfprintf (stderr, FatMsg [FatNum-1], ap);
va_end (ap);
fprintf (stderr, "\n");
if (Verbose) {
fprintf (stderr, "Line: %s\n", line);
}
exit (EXIT_FAILURE);
}
void Internal (char* Format, ...)
/* Print a message about an internal compiler error and die. */
{
va_list ap;
fprintf (stderr, "%s(%u): Internal compiler error:\n", fin, curpos);
va_start (ap, Format);
vfprintf (stderr, Format, ap);
va_end (ap);
fprintf (stderr, "\nLine: %s\n", line);
/* Use abort to create a core dump */
abort ();
}
void ErrorReport (void)
/* Report errors (called at end of compile) */
{
if (ErrorCount == 0 && Verbose) {
printf ("No errors.\n");
}
}

206
src/cc65/error.h Normal file
View File

@@ -0,0 +1,206 @@
/*****************************************************************************/
/* */
/* error.h */
/* */
/* Error handling for the cc65 C compiler */
/* */
/* */
/* */
/* (C) 1998 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ERROR_H
#define ERROR_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Warning numbers */
enum Warnings {
WARN_NONE, /* No warning */
WARN_UNREACHABLE_CODE,
WARN_COND_NEVER_TRUE,
WARN_COND_ALWAYS_TRUE,
WARN_PTR_TO_INT_CONV,
WARN_INT_TO_PTR_CONV,
WARN_FUNC_WITHOUT_PROTO,
WARN_UNKNOWN_PRAGMA,
WARN_NO_CASE_LABELS,
WARN_FUNC_MUST_BE_EXTERN,
WARN_UNUSED_PARM,
WARN_UNUSED_ITEM,
WARN_CONSTANT_IS_LONG,
WARN_NESTED_COMMENT,
WARN_COUNT /* Warning count */
};
/* Error numbers */
enum Errors {
ERR_NONE, /* No error */
ERR_INVALID_CHAR,
ERR_UNEXPECTED_NEWLINE,
ERR_EOF_IN_COMMENT,
ERR_SYNTAX,
ERR_QUOTE_EXPECTED,
ERR_COLON_EXPECTED,
ERR_SEMICOLON_EXPECTED,
ERR_LPAREN_EXPECTED,
ERR_RPAREN_EXPECTED,
ERR_LBRACK_EXPECTED,
ERR_RBRACK_EXPECTED,
ERR_LCURLY_EXPECTED,
ERR_RCURLY_EXPECTED,
ERR_IDENT_EXPECTED,
ERR_TYPE_EXPECTED,
ERR_INCOMPATIBLE_TYPES,
ERR_INCOMPATIBLE_POINTERS,
ERR_TOO_MANY_FUNC_ARGS,
ERR_TOO_FEW_FUNC_ARGS,
ERR_MACRO_ARGCOUNT,
ERR_DUPLICATE_MACRO_ARG,
ERR_VAR_IDENT_EXPECTED,
ERR_INT_EXPR_EXPECTED,
ERR_CONST_EXPR_EXPECTED,
ERR_NO_ACTIVE_LOOP,
ERR_INCLUDE_LTERM_EXPECTED,
ERR_INCLUDE_RTERM_EXPECTED,
ERR_INCLUDE_NOT_FOUND,
ERR_INCLUDE_OPEN_FAILURE,
ERR_INVALID_USER_ERROR,
ERR_USER_ERROR,
ERR_UNEXPECTED_CPP_ENDIF,
ERR_UNEXPECTED_CPP_ELSE,
ERR_CPP_ENDIF_EXPECTED,
ERR_CPP_DIRECTIVE_EXPECTED,
ERR_MULTIPLE_DEFINITION,
ERR_STRLIT_EXPECTED,
ERR_WHILE_EXPECTED,
ERR_MUST_RETURN_VALUE,
ERR_CANNOT_RETURN_VALUE,
ERR_UNEXPECTED_CONTINUE,
ERR_UNDEFINED_SYMBOL,
ERR_UNDEFINED_LABEL,
ERR_INCLUDE_NESTING,
ERR_TOO_MANY_LOCALS,
ERR_TOO_MANY_INITIALIZERS,
ERR_INIT_INCOMPLETE_TYPE,
ERR_CANNOT_SUBSCRIPT,
ERR_OP_NOT_ALLOWED,
ERR_STRUCT_EXPECTED,
ERR_STRUCT_FIELD_MISMATCH,
ERR_STRUCT_PTR_EXPECTED,
ERR_LVALUE_EXPECTED,
ERR_EXPR_EXPECTED,
ERR_CPP_EXPR_EXPECTED,
ERR_ILLEGAL_TYPE,
ERR_ILLEGAL_FUNC_CALL,
ERR_ILLEGAL_INDIRECT,
ERR_ILLEGAL_ADDRESS,
ERR_ILLEGAL_MACRO_CALL,
ERR_ILLEGAL_HEX_DIGIT,
ERR_ILLEGAL_CHARCONST,
ERR_ILLEGAL_MODIFIER,
ERR_ILLEGAL_STORAGE_CLASS,
ERR_DIV_BY_ZERO,
ERR_MOD_BY_ZERO,
ERR_RANGE,
ERR_SYMBOL_KIND,
ERR_LEVEL_NESTING,
ERR_MISSING_PARAM_NAME,
ERR_OLD_STYLE_PROTO,
ERR_PARAM_DECL,
ERR_CANNOT_TAKE_ADDR_OF_REG,
ERR_ILLEGAL_SIZE,
ERR_FASTCALL,
ERR_UNKNOWN_SIZE,
ERR_COUNT /* Error count */
};
/* Fatal errors */
enum Fatals {
FAT_NONE,
FAT_TOO_MANY_ERRORS,
FAT_CANNOT_OPEN_OUTPUT,
FAT_CANNOT_WRITE_OUTPUT,
FAT_CANNOT_OPEN_INPUT,
FAT_OUT_OF_MEMORY,
FAT_STACK_OVERFLOW,
FAT_STACK_EMPTY,
FAT_OUT_OF_STRSPACE,
FAT_TOO_MANY_CASE_LABELS,
FAT_COUNT /* Fatal error count */
};
/* Count of errors/warnings */
extern unsigned ErrorCount;
extern unsigned WarningCount;
/*****************************************************************************/
/* code */
/*****************************************************************************/
void Warning (unsigned WarnNum, ...);
/* Print warning message. */
void PPWarning (unsigned WarnNum, ...);
/* Print warning message. For use within the preprocessor. */
void Error (unsigned ErrNum, ...);
/* Print an error message */
void PPError (unsigned ErrNum, ...);
/* Print an error message. For use within the preprocessor. */
void Fatal (unsigned FatNum, ...);
/* Print a message about a fatal error and die */
void Internal (char* Format, ...);
/* Print a message about an internal compiler error and die. */
void ErrorReport (void);
/* Report errors (called at end of compile) */
/* End of error.h */
#endif

2980
src/cc65/expr.c Normal file

File diff suppressed because it is too large Load Diff

125
src/cc65/expr.h Normal file
View File

@@ -0,0 +1,125 @@
/*
* expr.h
*
* Ullrich von Bassewitz, 21.06.1998
*/
#ifndef EXPR_H
#define EXPR_H
#include "datatype.h"
/*****************************************************************************/
/* data */
/*****************************************************************************/
/* Defines for the flags field of the expression descriptor */
#define E_MREG 0x0110 /* Special: Expression is primary register */
#define E_MGLOBAL 0x0080 /* Reference to static variable */
#define E_MLOCAL 0x0040 /* Reference to local variable (stack offset) */
#define E_MCONST 0x0020 /* Constant value */
#define E_MEXPR 0x0010 /* Result is in primary register */
#define E_MEOFFS 0x0011 /* Offset is in primary register, base on stack */
#define E_MCTYPE 0x0007 /* Type of a constant */
#define E_TCONST 0x0000 /* Constant */
#define E_TGLAB 0x0001 /* Global label */
#define E_TLIT 0x0002 /* Literal of some kind */
#define E_TLOFFS 0x0003 /* Constant stack offset */
#define E_TLLAB 0x0004 /* Local label */
#define E_TREGISTER 0x0005 /* Register variable */
/* Defines for the test field of the expression descriptor */
#define E_CC 0x0001 /* expr has set cond codes apropos result value */
#define E_FORCETEST 0x0002 /* if expr has NOT set CC, force a test */
#define E_LOGL 0x0004 /* expr has left a logical value (1 or 0) in AX */
#define E_XINV 0x0008 /* flip this bit to invert sense of test */
#define E_TEST 0x0010 /* We're evaluating a test */
/* Describe the result of an expression */
struct expent {
struct SymEntry* Sym; /* Symbol table entry if known */
type* e_tptr; /* Type array of expression */
long e_const; /* Value if expression constant */
unsigned e_flags;
unsigned e_test; /* */
unsigned long e_name; /* Name or label number */
};
/*****************************************************************************/
/* code */
/*****************************************************************************/
void doasm (void);
/* This function parses ASM statements. The syntax of the ASM directive
* looks like the one defined for C++ (C has no ASM directive), that is,
* a string literal in parenthesis.
*/
unsigned assignadjust (type* lhst, struct expent* rhs);
/* Adjust the type of the right hand expression so that it can be assigned to
* the type on the left hand side. This function is used for assignment and
* for converting parameters in a function call. It returns the code generator
* flags for the operation.
*/
void exprhs (unsigned flags, int k, struct expent *lval);
/* Put the result of an expression into the primary register */
void expression1 (struct expent* lval);
/* Evaluate an expression on level 1 (no comma operator) and put it into
* the primary register
*/
void expression (struct expent* lval);
/* Evaluate an expression and put it into the primary register */
int evalexpr (unsigned flags, int (*f) (struct expent*), struct expent* lval);
/* Will evaluate an expression via the given function. If the result is a
* constant, 0 is returned and the value is put in the lval struct. If the
* result is not constant, exprhs is called to bring the value into the
* primary register and 1 is returned.
*/
void constexpr (struct expent* lval);
/* Get a constant value */
void intexpr (struct expent* lval);
/* Get an integer expression */
void boolexpr (struct expent* lval);
/* Get a boolean expression */
void test (unsigned label, int cond);
/* Generate code to perform test and jump if false. */
int hie1 (struct expent* lval);
/* Parse first level of expression hierarchy. */
int hie0 (struct expent* lval);
/* Parse comma operator (highest level of expression hierarchy) */
void DefineData (struct expent* lval);
/* Output a data definition for the given expression */
/* End of expr.h */
#endif

Some files were not shown because too many files have changed in this diff Show More