mirror of
https://github.com/cc65/cc65.git
synced 2025-01-10 19:29:45 +00:00
Introduce a -E flag that activates just the preprocessor.
Use variable sized string buffers for input and macro processing instead of the fixed buffers used before. Many changes in the preprocessor to make it more standards compliant (which it is still not). git-svn-id: svn://svn.cc65.org/cc65/trunk@3182 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
3925f0cac9
commit
06b57e6e7e
@ -56,6 +56,7 @@
|
||||
#include "litpool.h"
|
||||
#include "macrotab.h"
|
||||
#include "pragma.h"
|
||||
#include "preproc.h"
|
||||
#include "standard.h"
|
||||
#include "symtab.h"
|
||||
|
||||
@ -178,7 +179,7 @@ static void Parse (void)
|
||||
/* Size is unknown and not an array */
|
||||
Error ("Variable `%s' has unknown size", Decl.Ident);
|
||||
}
|
||||
} else if (ANSI) {
|
||||
} else if (IS_Get (&Standard) != STD_CC65) {
|
||||
/* We cannot declare variables of type void */
|
||||
Error ("Illegal type for variable `%s'", Decl.Ident);
|
||||
}
|
||||
@ -332,18 +333,34 @@ void Compile (const char* FileName)
|
||||
/* Open the input file */
|
||||
OpenMainFile (FileName);
|
||||
|
||||
/* Ok, start the ball rolling... */
|
||||
Parse ();
|
||||
/* Are we supposed to compile or just preprocess the input? */
|
||||
if (PreprocessOnly) {
|
||||
|
||||
/* Dump the literal pool. */
|
||||
DumpLiteralPool ();
|
||||
while (NextLine ()) {
|
||||
Preprocess ();
|
||||
printf ("%.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
}
|
||||
|
||||
/* Write imported/exported symbols */
|
||||
EmitExternals ();
|
||||
if (Debug) {
|
||||
PrintMacroStats (stdout);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Ok, start the ball rolling... */
|
||||
Parse ();
|
||||
|
||||
/* Dump the literal pool. */
|
||||
DumpLiteralPool ();
|
||||
|
||||
/* Write imported/exported symbols */
|
||||
EmitExternals ();
|
||||
|
||||
if (Debug) {
|
||||
PrintLiteralPoolStats (stdout);
|
||||
PrintMacroStats (stdout);
|
||||
}
|
||||
|
||||
if (Debug) {
|
||||
PrintLiteralPoolStats (stdout);
|
||||
PrintMacroStats (stdout);
|
||||
}
|
||||
|
||||
/* Leave the main lexical level */
|
||||
|
@ -68,15 +68,15 @@ unsigned WarningCount = 0;
|
||||
|
||||
|
||||
|
||||
static void IntWarning (const char* Filename, unsigned Line, const char* Msg, va_list ap)
|
||||
static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
|
||||
/* Print warning message - internal function. */
|
||||
{
|
||||
if (!IS_Get (&WarnDisable)) {
|
||||
fprintf (stderr, "%s(%u): Warning: ", Filename, Line);
|
||||
fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo);
|
||||
vfprintf (stderr, Msg, ap);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
Print (stderr, 1, "Line: %s\n", line);
|
||||
Print (stderr, 1, "Input: %.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
++WarningCount;
|
||||
}
|
||||
}
|
||||
@ -105,14 +105,14 @@ void PPWarning (const char* Format, ...)
|
||||
|
||||
|
||||
|
||||
static void IntError (const char* Filename, unsigned Line, const char* Msg, va_list ap)
|
||||
static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
|
||||
/* Print an error message - internal function*/
|
||||
{
|
||||
fprintf (stderr, "%s(%u): Error: ", Filename, Line);
|
||||
fprintf (stderr, "%s(%u): Error: ", Filename, LineNo);
|
||||
vfprintf (stderr, Msg, ap);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
Print (stderr, 1, "Line: %s\n", line);
|
||||
Print (stderr, 1, "Input: %.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
++ErrorCount;
|
||||
if (ErrorCount > 10) {
|
||||
Fatal ("Too many errors");
|
||||
@ -165,7 +165,7 @@ void Fatal (const char* Format, ...)
|
||||
va_end (ap);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
Print (stderr, 1, "Line: %s\n", line);
|
||||
Print (stderr, 1, "Input: %.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ void Internal (const char* Format, ...)
|
||||
va_start (ap, Format);
|
||||
vfprintf (stderr, Format, ap);
|
||||
va_end (ap);
|
||||
fprintf (stderr, "\nLine: %s\n", line);
|
||||
fprintf (stderr, "\nInput: %.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
|
||||
/* Use abort to create a core dump */
|
||||
abort ();
|
||||
@ -203,12 +203,8 @@ void Internal (const char* Format, ...)
|
||||
void ErrorReport (void)
|
||||
/* Report errors (called at end of compile) */
|
||||
{
|
||||
if (ErrorCount == 0 && Verbosity > 0) {
|
||||
printf ("No errors.\n");
|
||||
}
|
||||
Print (stdout, 1, "%u errors, %u warnings\n", ErrorCount, WarningCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
unsigned char AddSource = 0; /* Add source lines as comments */
|
||||
unsigned char DebugInfo = 0; /* Add debug info to the obj */
|
||||
unsigned char CreateDep = 0; /* Create a dependency file */
|
||||
unsigned char ANSI = 0; /* Strict ANSI flag */
|
||||
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
|
||||
unsigned RegisterSpace = 6; /* Space available for register vars */
|
||||
|
||||
/* Stackable options */
|
||||
@ -64,4 +64,3 @@ IntStack CodeSizeFactor = INTSTACK(100);/* Size factor for generated code */
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
||||
extern unsigned char AddSource; /* Add source lines as comments */
|
||||
extern unsigned char DebugInfo; /* Add debug info to the obj */
|
||||
extern unsigned char CreateDep; /* Create a dependency file */
|
||||
extern unsigned char ANSI; /* Strict ANSI flag */
|
||||
extern unsigned char PreprocessOnly; /* Just preprocess the input */
|
||||
extern unsigned RegisterSpace; /* Space available for register vars */
|
||||
|
||||
/* Stackable options */
|
||||
|
253
src/cc65/input.c
253
src/cc65/input.c
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -46,7 +46,6 @@
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "asmcode.h"
|
||||
#include "codegen.h"
|
||||
#include "error.h"
|
||||
#include "incpath.h"
|
||||
@ -61,10 +60,8 @@
|
||||
|
||||
|
||||
|
||||
/* Input line stuff */
|
||||
static char LineBuf [LINESIZE];
|
||||
char* line = LineBuf;
|
||||
const char* lptr = LineBuf;
|
||||
/* The current input line */
|
||||
StrBuf* Line;
|
||||
|
||||
/* Current and next input character */
|
||||
char CurC = '\0';
|
||||
@ -87,6 +84,9 @@ static Collection IFiles = STATIC_COLLECTION_INITIALIZER;
|
||||
/* List of all active files */
|
||||
static Collection AFiles = STATIC_COLLECTION_INITIALIZER;
|
||||
|
||||
/* Input stack used when preprocessing. */
|
||||
static Collection InputStack = STATIC_COLLECTION_INITIALIZER;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -217,6 +217,9 @@ void OpenMainFile (const char* Name)
|
||||
|
||||
/* Allocate a new AFile structure for the file */
|
||||
(void) NewAFile (IF, F);
|
||||
|
||||
/* Allocate the input line buffer */
|
||||
Line = NewStrBuf ();
|
||||
}
|
||||
|
||||
|
||||
@ -297,48 +300,101 @@ static void CloseIncludeFile (void)
|
||||
|
||||
|
||||
|
||||
void ClearLine (void)
|
||||
/* Clear the current input line */
|
||||
static void GetInputChar (void)
|
||||
/* Read the next character from the input stream and make CurC and NextC
|
||||
* valid. If end of line is reached, both are set to NUL, no more lines
|
||||
* are read by this function.
|
||||
*/
|
||||
{
|
||||
line[0] = '\0';
|
||||
lptr = line;
|
||||
CurC = '\0';
|
||||
NextC = '\0';
|
||||
}
|
||||
/* Drop all pushed fragments that don't have data left */
|
||||
while (SB_GetIndex (Line) >= SB_GetLen (Line)) {
|
||||
/* Cannot read more from this line, check next line on stack if any */
|
||||
if (CollCount (&InputStack) == 0) {
|
||||
/* This is THE line */
|
||||
break;
|
||||
}
|
||||
FreeStrBuf (Line);
|
||||
Line = CollPop (&InputStack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void InitLine (const char* Buf)
|
||||
/* Initialize lptr from Buf and read CurC and NextC from the new input line */
|
||||
{
|
||||
lptr = Buf;
|
||||
CurC = lptr[0];
|
||||
if (CurC != '\0') {
|
||||
NextC = lptr[1];
|
||||
/* Now get the next characters from the line */
|
||||
if (SB_GetIndex (Line) >= SB_GetLen (Line)) {
|
||||
CurC = NextC = '\0';
|
||||
} else {
|
||||
NextC = '\0';
|
||||
CurC = SB_AtUnchecked (Line, SB_GetIndex (Line));
|
||||
if (SB_GetIndex (Line) + 1 < SB_GetLen (Line)) {
|
||||
/* NextC comes from this fragment */
|
||||
NextC = SB_AtUnchecked (Line, SB_GetIndex (Line) + 1);
|
||||
} else {
|
||||
/* NextC comes from next fragment */
|
||||
if (CollCount (&InputStack) > 0) {
|
||||
NextC = ' ';
|
||||
} else {
|
||||
NextC = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void NextChar (void)
|
||||
/* Read the next character from the input stream and make CurC and NextC
|
||||
* valid. If end of line is reached, both are set to NUL, no more lines
|
||||
* are read by this function.
|
||||
/* Skip the current input character and read the next one from the input
|
||||
* stream. CurC and NextC are valid after the call. If end of line is
|
||||
* reached, both are set to NUL, no more lines are read by this function.
|
||||
*/
|
||||
{
|
||||
if (lptr[0] != '\0') {
|
||||
++lptr;
|
||||
CurC = lptr[0];
|
||||
if (CurC != '\0') {
|
||||
NextC = lptr[1];
|
||||
} else {
|
||||
NextC = '\0';
|
||||
}
|
||||
} else {
|
||||
CurC = NextC = '\0';
|
||||
/* Skip the last character read */
|
||||
SB_Skip (Line);
|
||||
|
||||
/* Read the next one */
|
||||
GetInputChar ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClearLine (void)
|
||||
/* Clear the current input line */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Remove all pushed fragments from the input stack */
|
||||
for (I = 0; I < CollCount (&InputStack); ++I) {
|
||||
FreeStrBuf (CollAtUnchecked (&InputStack, I));
|
||||
}
|
||||
CollDeleteAll (&InputStack);
|
||||
|
||||
/* Clear the contents of Line */
|
||||
SB_Clear (Line);
|
||||
CurC = '\0';
|
||||
NextC = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
StrBuf* InitLine (StrBuf* Buf)
|
||||
/* Initialize Line from Buf and read CurC and NextC from the new input line.
|
||||
* The function returns the old input line.
|
||||
*/
|
||||
{
|
||||
StrBuf* OldLine = Line;
|
||||
Line = Buf;
|
||||
CurC = SB_LookAt (Buf, SB_GetIndex (Buf));
|
||||
NextC = SB_LookAt (Buf, SB_GetIndex (Buf) + 1);
|
||||
return OldLine;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PushLine (const StrBuf* Buf)
|
||||
/* Push a copy of Buf onto the input stack */
|
||||
{
|
||||
CollAppend (&InputStack, Line);
|
||||
Line = NewStrBuf ();
|
||||
SB_Copy (Line, Buf);
|
||||
|
||||
/* Make CurC and NextC valid */
|
||||
GetInputChar ();
|
||||
}
|
||||
|
||||
|
||||
@ -346,74 +402,83 @@ void NextChar (void)
|
||||
int NextLine (void)
|
||||
/* Get a line from the current input. Returns 0 on end of file. */
|
||||
{
|
||||
AFile* Input;
|
||||
unsigned Len;
|
||||
unsigned Part;
|
||||
unsigned Start;
|
||||
int Done;
|
||||
AFile* Input;
|
||||
|
||||
/* Setup the line */
|
||||
/* Clear the current line */
|
||||
ClearLine ();
|
||||
|
||||
/* If there is no file open, bail out, otherwise get the current input file */
|
||||
if (CollCount (&AFiles) == 0) {
|
||||
return 0;
|
||||
}
|
||||
Input = (AFile*) CollLast (&AFiles);
|
||||
Input = CollLast (&AFiles);
|
||||
|
||||
/* Read lines until we get one with real contents */
|
||||
Len = 0;
|
||||
Done = 0;
|
||||
while (!Done && Len < LINESIZE) {
|
||||
/* Read characters until we have one complete line */
|
||||
while (1) {
|
||||
|
||||
while (fgets (line + Len, LINESIZE - Len, Input->F) == 0) {
|
||||
/* Read the next character */
|
||||
int C = fgetc (Input->F);
|
||||
|
||||
/* Assume EOF */
|
||||
ClearLine ();
|
||||
/* Check for EOF */
|
||||
if (C == EOF) {
|
||||
|
||||
/* Leave the current file */
|
||||
CloseIncludeFile ();
|
||||
|
||||
/* If there is no file open, bail out, otherwise get the
|
||||
* current input file
|
||||
*/
|
||||
if (CollCount (&AFiles) == 0) {
|
||||
return 0;
|
||||
}
|
||||
Input = (AFile*) CollLast (&AFiles);
|
||||
/* Accept files without a newline at the end */
|
||||
if (SB_NotEmpty (Line)) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/* If there is no file open, bail out, otherwise get the
|
||||
* previous input file and start over.
|
||||
*/
|
||||
if (CollCount (&AFiles) == 0) {
|
||||
return 0;
|
||||
}
|
||||
Input = CollLast (&AFiles);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We got a new line */
|
||||
++Input->Line;
|
||||
/* Check for end of line */
|
||||
if (C == '\n') {
|
||||
|
||||
/* Remove the trailing cr/lf if we have one. We will ignore both, cr
|
||||
* and lf on all systems since this enables us to compile DOS/Windows
|
||||
* stuff also on unix systems (where fgets does not remove the cr).
|
||||
*/
|
||||
Part = strlen (line + Len);
|
||||
Start = Len;
|
||||
Len += Part;
|
||||
while (Len > 0 && (line[Len-1] == '\n' || line[Len-1] == '\r')) {
|
||||
--Len;
|
||||
}
|
||||
line [Len] = '\0';
|
||||
/* We got a new line */
|
||||
++Input->Line;
|
||||
|
||||
/* Check if we have a line continuation character at the end. If not,
|
||||
* we're done.
|
||||
*/
|
||||
if (Len > 0 && line[Len-1] == '\\') {
|
||||
line[Len-1] = '\n'; /* Replace by newline */
|
||||
} else {
|
||||
Done = 1;
|
||||
}
|
||||
/* If the \n is preceeded by a \r, remove the \r, so we can read
|
||||
* DOS/Windows files under *nix.
|
||||
*/
|
||||
if (SB_LookAtLast (Line) == '\r') {
|
||||
SB_Drop (Line, 1);
|
||||
}
|
||||
|
||||
/* If we don't have a line continuation character at the end,
|
||||
* we're done with this line. Otherwise replace the character
|
||||
* by a newline and continue reading.
|
||||
*/
|
||||
if (SB_LookAtLast (Line) == '\\') {
|
||||
Line->Buf[Line->Len-1] = '\n';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (C != '\0') { /* Ignore embedded NULs */
|
||||
|
||||
/* Just some character, add it to the line */
|
||||
SB_AppendChar (Line, C);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Got a line. Initialize the current and next characters. */
|
||||
InitLine (line);
|
||||
/* Add a termination character to the string buffer */
|
||||
SB_Terminate (Line);
|
||||
|
||||
/* Initialize the current and next characters. */
|
||||
InitLine (Line);
|
||||
|
||||
/* Create line information for this line */
|
||||
UpdateLineInfo (Input->Input, Input->Line, line);
|
||||
UpdateLineInfo (Input->Input, Input->Line, SB_GetConstBuf (Line));
|
||||
|
||||
/* Done */
|
||||
return 1;
|
||||
@ -426,17 +491,17 @@ const char* GetCurrentFile (void)
|
||||
{
|
||||
unsigned AFileCount = CollCount (&AFiles);
|
||||
if (AFileCount > 0) {
|
||||
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
||||
return AF->Input->Name;
|
||||
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
||||
return AF->Input->Name;
|
||||
} else {
|
||||
/* No open file. Use the main file if we have one. */
|
||||
unsigned IFileCount = CollCount (&IFiles);
|
||||
if (IFileCount > 0) {
|
||||
const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
|
||||
return IF->Name;
|
||||
} else {
|
||||
/* No open file. Use the main file if we have one. */
|
||||
unsigned IFileCount = CollCount (&IFiles);
|
||||
if (IFileCount > 0) {
|
||||
const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
|
||||
return IF->Name;
|
||||
} else {
|
||||
return "(outside file scope)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -40,6 +40,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -48,13 +51,8 @@
|
||||
|
||||
|
||||
|
||||
/* Maximum length of an input line and the corresponding char array */
|
||||
#define LINEMAX 4095
|
||||
#define LINESIZE LINEMAX+1
|
||||
|
||||
/* Input line stuff */
|
||||
extern char* line;
|
||||
extern const char* lptr; /* ### Remove this */
|
||||
/* The current input line */
|
||||
extern StrBuf* Line;
|
||||
|
||||
/* Current and next input character */
|
||||
extern char CurC;
|
||||
@ -64,7 +62,7 @@ extern char NextC;
|
||||
typedef struct IFile IFile;
|
||||
struct IFile {
|
||||
unsigned Index; /* File index */
|
||||
unsigned Usage; /* Usage counter */
|
||||
unsigned Usage; /* Usage counter */
|
||||
unsigned long Size; /* File size */
|
||||
unsigned long MTime; /* Time of last modification */
|
||||
char Name[1]; /* Name of file (dynamically allocated) */
|
||||
@ -73,7 +71,7 @@ struct IFile {
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -84,18 +82,20 @@ void OpenMainFile (const char* Name);
|
||||
void OpenIncludeFile (const char* Name, unsigned DirSpec);
|
||||
/* Open an include file and insert it into the tables. */
|
||||
|
||||
void ClearLine (void);
|
||||
/* Clear the current input line */
|
||||
|
||||
void InitLine (const char* Buf);
|
||||
/* Initialize lptr from Buf and read CurC and NextC from the new input line */
|
||||
|
||||
void NextChar (void);
|
||||
/* Read the next character from the input stream and make CurC and NextC
|
||||
* valid. If end of line is reached, both are set to NUL, no more lines
|
||||
* are read by this function.
|
||||
*/
|
||||
|
||||
void ClearLine (void);
|
||||
/* Clear the current input line */
|
||||
|
||||
StrBuf* InitLine (StrBuf* Buf);
|
||||
/* Initialize Line from Buf and read CurC and NextC from the new input line.
|
||||
* The function returns the old input line.
|
||||
*/
|
||||
|
||||
int NextLine (void);
|
||||
/* Get a line from the current input. Returns 0 on end of file. */
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -56,12 +56,6 @@
|
||||
#define MACRO_TAB_SIZE 211
|
||||
static Macro* MacroTab[MACRO_TAB_SIZE];
|
||||
|
||||
/* A table that holds the count of macros that start with a specific character.
|
||||
* It is used to determine quickly, if an identifier may be a macro or not
|
||||
* without calculating the hash over the name.
|
||||
*/
|
||||
static unsigned short MacroFlagTab[256];
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -83,11 +77,11 @@ Macro* NewMacro (const char* Name)
|
||||
|
||||
/* Initialize the data */
|
||||
M->Next = 0;
|
||||
M->Expanding = 0;
|
||||
M->ArgCount = -1; /* Flag: Not a function like macro */
|
||||
M->MaxArgs = 0;
|
||||
M->FormalArgs = 0;
|
||||
M->ActualArgs = 0;
|
||||
M->Replacement = 0;
|
||||
InitCollection (&M->FormalArgs);
|
||||
InitStrBuf (&M->Replacement);
|
||||
memcpy (M->Name, Name, Len+1);
|
||||
|
||||
/* Return the new macro */
|
||||
@ -101,14 +95,13 @@ void FreeMacro (Macro* M)
|
||||
* table, use UndefineMacro for that.
|
||||
*/
|
||||
{
|
||||
int I;
|
||||
unsigned I;
|
||||
|
||||
for (I = 0; I < M->ArgCount; ++I) {
|
||||
xfree (M->FormalArgs[I]);
|
||||
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
|
||||
xfree (CollAtUnchecked (&M->FormalArgs, I));
|
||||
}
|
||||
xfree (M->FormalArgs);
|
||||
xfree (M->ActualArgs);
|
||||
xfree (M->Replacement);
|
||||
DoneCollection (&M->FormalArgs);
|
||||
DoneStrBuf (&M->Replacement);
|
||||
xfree (M);
|
||||
}
|
||||
|
||||
@ -135,7 +128,7 @@ void DefineTextMacro (const char* Name, const char* Val)
|
||||
Macro* M = NewMacro (Name);
|
||||
|
||||
/* Set the value as replacement text */
|
||||
M->Replacement = xstrdup (Val);
|
||||
SB_CopyStr (&M->Replacement, Val);
|
||||
|
||||
/* Insert the macro into the macro table */
|
||||
InsertMacro (M);
|
||||
@ -144,26 +137,14 @@ void DefineTextMacro (const char* Name, const char* Val)
|
||||
|
||||
|
||||
void InsertMacro (Macro* M)
|
||||
/* Insert the given macro into the macro table. This call will also allocate
|
||||
* the ActualArgs parameter array.
|
||||
*/
|
||||
/* Insert the given macro into the macro table. */
|
||||
{
|
||||
unsigned Hash;
|
||||
|
||||
/* Allocate the ActualArgs parameter array */
|
||||
if (M->ArgCount > 0) {
|
||||
M->ActualArgs = (char const**) xmalloc (M->ArgCount * sizeof(char*));
|
||||
}
|
||||
|
||||
/* Get the hash value of the macro name */
|
||||
Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
|
||||
unsigned Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
|
||||
|
||||
/* Insert the macro */
|
||||
M->Next = MacroTab[Hash];
|
||||
MacroTab[Hash] = M;
|
||||
|
||||
/* Increment the number of macros starting with this char */
|
||||
MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]++;
|
||||
}
|
||||
|
||||
|
||||
@ -191,9 +172,6 @@ int UndefineMacro (const char* Name)
|
||||
L->Next = M->Next;
|
||||
}
|
||||
|
||||
/* Decrement the number of macros starting with this char */
|
||||
MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]--;
|
||||
|
||||
/* Delete the macro */
|
||||
FreeMacro (M);
|
||||
|
||||
@ -236,38 +214,21 @@ Macro* FindMacro (const char* Name)
|
||||
|
||||
|
||||
|
||||
int IsMacro (const char* Name)
|
||||
/* Return true if the given name is the name of a macro, return false otherwise */
|
||||
{
|
||||
return MaybeMacro(Name[0]) && FindMacro(Name) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MaybeMacro (unsigned char C)
|
||||
/* Return true if the given character may be the start of the name of an
|
||||
* existing macro, return false if not.
|
||||
int FindMacroArg (Macro* M, const char* Arg)
|
||||
/* Search for a formal macro argument. If found, return the index of the
|
||||
* argument. If the argument was not found, return -1.
|
||||
*/
|
||||
{
|
||||
return (MacroFlagTab[C] > 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* FindMacroArg (Macro* M, const char* Arg)
|
||||
/* Search for a formal macro argument. If found, return the actual
|
||||
* (replacement) argument. If the argument was not found, return NULL.
|
||||
*/
|
||||
{
|
||||
int I;
|
||||
for (I = 0; I < M->ArgCount; ++I) {
|
||||
if (strcmp (M->FormalArgs[I], Arg) == 0) {
|
||||
/* Found */
|
||||
return M->ActualArgs[I];
|
||||
unsigned I;
|
||||
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
|
||||
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
|
||||
/* Found */
|
||||
return I;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -279,29 +240,18 @@ void AddMacroArg (Macro* M, const char* Arg)
|
||||
* Beware: Don't use FindMacroArg here, since the actual argument array
|
||||
* may not be initialized.
|
||||
*/
|
||||
int I;
|
||||
for (I = 0; I < M->ArgCount; ++I) {
|
||||
if (strcmp (M->FormalArgs[I], Arg) == 0) {
|
||||
unsigned I;
|
||||
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
|
||||
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
|
||||
/* Found */
|
||||
Error ("Duplicate macro parameter: `%s'", Arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have enough room available, otherwise expand the array
|
||||
* that holds the formal argument list.
|
||||
*/
|
||||
if (M->ArgCount >= (int) M->MaxArgs) {
|
||||
/* We must expand the array */
|
||||
char** OldArgs = M->FormalArgs;
|
||||
M->MaxArgs += 10;
|
||||
M->FormalArgs = (char**) xmalloc (M->MaxArgs * sizeof(char*));
|
||||
memcpy (M->FormalArgs, OldArgs, M->ArgCount * sizeof (char*));
|
||||
xfree (OldArgs);
|
||||
}
|
||||
|
||||
/* Add the new argument */
|
||||
M->FormalArgs[M->ArgCount++] = xstrdup (Arg);
|
||||
CollAppend (&M->FormalArgs, xstrdup (Arg));
|
||||
++M->ArgCount;
|
||||
}
|
||||
|
||||
|
||||
@ -318,13 +268,14 @@ int MacroCmp (const Macro* M1, const Macro* M2)
|
||||
|
||||
/* Compare the arguments */
|
||||
for (I = 0; I < M1->ArgCount; ++I) {
|
||||
if (strcmp (M1->FormalArgs[I], M2->FormalArgs[I]) != 0) {
|
||||
if (strcmp (CollConstAt (&M1->FormalArgs, I),
|
||||
CollConstAt (&M2->FormalArgs, I)) != 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare the replacement */
|
||||
return strcmp (M1->Replacement, M2->Replacement);
|
||||
return SB_Compare (&M1->Replacement, &M2->Replacement);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -38,27 +38,35 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
/* data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Structure describing a macro */
|
||||
typedef struct Macro Macro;
|
||||
struct Macro {
|
||||
Macro* Next; /* Next macro with same hash value */
|
||||
int Expanding; /* Are we currently expanding this macro? */
|
||||
int ArgCount; /* Number of parameters, -1 = no parens */
|
||||
unsigned MaxArgs; /* Size of formal argument list */
|
||||
char** FormalArgs; /* Formal argument list */
|
||||
char const** ActualArgs; /* Actual argument list */
|
||||
char* Replacement; /* Replacement text */
|
||||
Collection FormalArgs; /* Formal argument list (char*) */
|
||||
StrBuf Replacement; /* Replacement text */
|
||||
char Name[1]; /* Name, dynamically allocated */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -80,9 +88,7 @@ void DefineTextMacro (const char* Name, const char* Val);
|
||||
/* Define a macro for a textual constant */
|
||||
|
||||
void InsertMacro (Macro* M);
|
||||
/* Insert the given macro into the macro table. This call will also allocate
|
||||
* the ActualArgs parameter array.
|
||||
*/
|
||||
/* Insert the given macro into the macro table. */
|
||||
|
||||
int UndefineMacro (const char* Name);
|
||||
/* Search for the macro with the given name and remove it from the macro
|
||||
@ -93,17 +99,19 @@ int UndefineMacro (const char* Name);
|
||||
Macro* FindMacro (const char* Name);
|
||||
/* Find a macro with the given name. Return the macro definition or NULL */
|
||||
|
||||
int IsMacro (const char* Name);
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsMacro (const char* Name)
|
||||
/* Return true if the given name is the name of a macro, return false otherwise */
|
||||
{
|
||||
return FindMacro (Name) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsMacro(Name) (FindMacro (Name) != 0)
|
||||
#endif
|
||||
|
||||
int MaybeMacro (unsigned char C);
|
||||
/* Return true if the given character may be the start of the name of an
|
||||
* existing macro, return false if not.
|
||||
*/
|
||||
|
||||
const char* FindMacroArg (Macro* M, const char* Arg);
|
||||
/* Search for a formal macro argument. If found, return the actual
|
||||
* (replacement) argument. If the argument was not found, return NULL.
|
||||
int FindMacroArg (Macro* M, const char* Arg);
|
||||
/* Search for a formal macro argument. If found, return the index of the
|
||||
* argument. If the argument was not found, return -1.
|
||||
*/
|
||||
|
||||
void AddMacroArg (Macro* M, const char* Arg);
|
||||
|
@ -82,6 +82,7 @@ static void Usage (void)
|
||||
"Short options:\n"
|
||||
" -Cl\t\t\tMake local variables static\n"
|
||||
" -Dsym[=defn]\t\tDefine a symbol\n"
|
||||
" -E\t\t\tStop after the preprocessing stage\n"
|
||||
" -I dir\t\tSet an include directory search path\n"
|
||||
" -O\t\t\tOptimize code\n"
|
||||
" -Oi\t\t\tOptimize code, inline more code\n"
|
||||
@ -802,6 +803,10 @@ int main (int argc, char* argv[])
|
||||
DefineSym (GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
PreprocessOnly = 1;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
OptIncludeDir (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
@ -908,7 +913,7 @@ int main (int argc, char* argv[])
|
||||
/* Create dependencies if requested */
|
||||
if (CreateDep) {
|
||||
DoCreateDep (OutputFile);
|
||||
Print (stdout, 1, "Creating dependeny file");
|
||||
Print (stdout, 1, "Creating dependeny file\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -181,7 +181,7 @@ static int SkipWhite (void)
|
||||
*/
|
||||
{
|
||||
while (1) {
|
||||
while (CurC == 0) {
|
||||
while (CurC == '\0') {
|
||||
if (NextLine () == 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -197,27 +197,30 @@ static int SkipWhite (void)
|
||||
|
||||
|
||||
|
||||
void SymName (char* s)
|
||||
/* Get symbol from input stream */
|
||||
void SymName (char* S)
|
||||
/* Read a symbol from the input stream. The first character must have been
|
||||
* checked before calling this function. The buffer is expected to be at
|
||||
* least of size MAX_IDENTLEN+1.
|
||||
*/
|
||||
{
|
||||
unsigned k = 0;
|
||||
unsigned Len = 0;
|
||||
do {
|
||||
if (k != MAX_IDENTLEN) {
|
||||
++k;
|
||||
*s++ = CurC;
|
||||
}
|
||||
if (Len < MAX_IDENTLEN) {
|
||||
++Len;
|
||||
*S++ = CurC;
|
||||
}
|
||||
NextChar ();
|
||||
} while (IsIdent (CurC) || IsDigit (CurC));
|
||||
*s = '\0';
|
||||
*S = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsSym (char *s)
|
||||
/* Get symbol from input stream or return 0 if not a symbol. */
|
||||
int IsSym (char* S)
|
||||
/* If a symbol follows, read it and return 1, otherwise return 0 */
|
||||
{
|
||||
if (IsIdent (CurC)) {
|
||||
SymName (s);
|
||||
SymName (S);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@ -245,7 +248,7 @@ static void SetTok (int tok)
|
||||
|
||||
|
||||
static int ParseChar (void)
|
||||
/* Parse a character. Converts \n into EOL, etc. */
|
||||
/* Parse a character. Converts escape chars into character codes. */
|
||||
{
|
||||
int I;
|
||||
unsigned Val;
|
||||
@ -292,9 +295,20 @@ static int ParseChar (void)
|
||||
case 'X':
|
||||
/* Hex character constant */
|
||||
NextChar ();
|
||||
Val = HexVal (CurC) << 4;
|
||||
NextChar ();
|
||||
C = Val | HexVal (CurC); /* Do not translate */
|
||||
if (!IsXDigit (CurC)) {
|
||||
Error ("\\x used with no following hex digits");
|
||||
C = ' ';
|
||||
}
|
||||
I = 0;
|
||||
C = 0;
|
||||
while (IsXDigit (CurC)) {
|
||||
if (++I <= 2) {
|
||||
C = (C << 4) | HexVal (CurC);
|
||||
} else if (I == 3) {
|
||||
Error ("Too many digits in hex character constant");
|
||||
}
|
||||
NextChar ();
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
@ -304,16 +318,16 @@ static int ParseChar (void)
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
/* Octal constant */
|
||||
/* Octal constant ### FIXME: Eat all available octal chars! */
|
||||
I = 0;
|
||||
Val = CurC - '0';
|
||||
while (NextC >= '0' && NextC <= '7' && ++I <= 3) {
|
||||
while (IsODigit (NextC) && ++I <= 3) {
|
||||
NextChar ();
|
||||
Val = (Val << 3) | (CurC - '0');
|
||||
}
|
||||
C = (int) Val;
|
||||
if (Val >= 256) {
|
||||
Error ("Character constant out of range");
|
||||
Error ("Character constant out of range: %u", Val);
|
||||
C = ' ';
|
||||
}
|
||||
break;
|
||||
|
@ -223,11 +223,14 @@ INLINE int TokIsTypeQual (const Token* T)
|
||||
# define TokIsTypeQual(T) ((T)->Tok >= TOK_FIRST_TYPEQUAL && (T)->Tok <= TOK_LAST_TYPEQUAL)
|
||||
#endif
|
||||
|
||||
void SymName (char* s);
|
||||
/* Get symbol from input stream */
|
||||
void SymName (char* S);
|
||||
/* Read a symbol from the input stream. The first character must have been
|
||||
* checked before calling this function. The buffer is expected to be at
|
||||
* least of size MAX_IDENTLEN+1.
|
||||
*/
|
||||
|
||||
int IsSym (char* s);
|
||||
/* Get symbol from input stream or return 0 if not a symbol. */
|
||||
int IsSym (char* S);
|
||||
/* If a symbol follows, read it and return 1, otherwise return 0 */
|
||||
|
||||
void NextToken (void);
|
||||
/* Get next token from input stream */
|
||||
|
Loading…
x
Reference in New Issue
Block a user