1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-13 08:25:28 +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:
cuz
2004-09-16 12:42:41 +00:00
parent 3925f0cac9
commit 06b57e6e7e
12 changed files with 865 additions and 627 deletions

View File

@@ -56,6 +56,7 @@
#include "litpool.h" #include "litpool.h"
#include "macrotab.h" #include "macrotab.h"
#include "pragma.h" #include "pragma.h"
#include "preproc.h"
#include "standard.h" #include "standard.h"
#include "symtab.h" #include "symtab.h"
@@ -178,7 +179,7 @@ static void Parse (void)
/* Size is unknown and not an array */ /* Size is unknown and not an array */
Error ("Variable `%s' has unknown size", Decl.Ident); 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 */ /* We cannot declare variables of type void */
Error ("Illegal type for variable `%s'", Decl.Ident); Error ("Illegal type for variable `%s'", Decl.Ident);
} }
@@ -332,18 +333,34 @@ void Compile (const char* FileName)
/* Open the input file */ /* Open the input file */
OpenMainFile (FileName); OpenMainFile (FileName);
/* Ok, start the ball rolling... */ /* Are we supposed to compile or just preprocess the input? */
Parse (); if (PreprocessOnly) {
/* Dump the literal pool. */ while (NextLine ()) {
DumpLiteralPool (); Preprocess ();
printf ("%.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
}
/* Write imported/exported symbols */ if (Debug) {
EmitExternals (); 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 */ /* Leave the main lexical level */

View File

@@ -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. */ /* Print warning message - internal function. */
{ {
if (!IS_Get (&WarnDisable)) { if (!IS_Get (&WarnDisable)) {
fprintf (stderr, "%s(%u): Warning: ", Filename, Line); fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo);
vfprintf (stderr, Msg, ap); vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n"); fprintf (stderr, "\n");
Print (stderr, 1, "Line: %s\n", line); Print (stderr, 1, "Input: %.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
++WarningCount; ++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*/ /* Print an error message - internal function*/
{ {
fprintf (stderr, "%s(%u): Error: ", Filename, Line); fprintf (stderr, "%s(%u): Error: ", Filename, LineNo);
vfprintf (stderr, Msg, ap); vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n"); fprintf (stderr, "\n");
Print (stderr, 1, "Line: %s\n", line); Print (stderr, 1, "Input: %.*s\n", SB_GetLen (Line), SB_GetConstBuf (Line));
++ErrorCount; ++ErrorCount;
if (ErrorCount > 10) { if (ErrorCount > 10) {
Fatal ("Too many errors"); Fatal ("Too many errors");
@@ -165,7 +165,7 @@ void Fatal (const char* Format, ...)
va_end (ap); va_end (ap);
fprintf (stderr, "\n"); 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); exit (EXIT_FAILURE);
} }
@@ -192,7 +192,7 @@ void Internal (const char* Format, ...)
va_start (ap, Format); va_start (ap, Format);
vfprintf (stderr, Format, ap); vfprintf (stderr, Format, ap);
va_end (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 */ /* Use abort to create a core dump */
abort (); abort ();
@@ -203,12 +203,8 @@ void Internal (const char* Format, ...)
void ErrorReport (void) void ErrorReport (void)
/* Report errors (called at end of compile) */ /* Report errors (called at end of compile) */
{ {
if (ErrorCount == 0 && Verbosity > 0) { Print (stdout, 1, "%u errors, %u warnings\n", ErrorCount, WarningCount);
printf ("No errors.\n");
}
} }

View File

@@ -46,7 +46,7 @@
unsigned char AddSource = 0; /* Add source lines as comments */ unsigned char AddSource = 0; /* Add source lines as comments */
unsigned char DebugInfo = 0; /* Add debug info to the obj */ unsigned char DebugInfo = 0; /* Add debug info to the obj */
unsigned char CreateDep = 0; /* Create a dependency file */ 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 */ unsigned RegisterSpace = 6; /* Space available for register vars */
/* Stackable options */ /* Stackable options */
@@ -64,4 +64,3 @@ IntStack CodeSizeFactor = INTSTACK(100);/* Size factor for generated code */

View File

@@ -53,7 +53,7 @@
extern unsigned char AddSource; /* Add source lines as comments */ extern unsigned char AddSource; /* Add source lines as comments */
extern unsigned char DebugInfo; /* Add debug info to the obj */ extern unsigned char DebugInfo; /* Add debug info to the obj */
extern unsigned char CreateDep; /* Create a dependency file */ 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 */ extern unsigned RegisterSpace; /* Space available for register vars */
/* Stackable options */ /* Stackable options */

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* R<EFBFBD>merstrasse 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -46,7 +46,6 @@
#include "xmalloc.h" #include "xmalloc.h"
/* cc65 */ /* cc65 */
#include "asmcode.h"
#include "codegen.h" #include "codegen.h"
#include "error.h" #include "error.h"
#include "incpath.h" #include "incpath.h"
@@ -61,10 +60,8 @@
/* Input line stuff */ /* The current input line */
static char LineBuf [LINESIZE]; StrBuf* Line;
char* line = LineBuf;
const char* lptr = LineBuf;
/* Current and next input character */ /* Current and next input character */
char CurC = '\0'; char CurC = '\0';
@@ -87,6 +84,9 @@ static Collection IFiles = STATIC_COLLECTION_INITIALIZER;
/* List of all active files */ /* List of all active files */
static Collection AFiles = STATIC_COLLECTION_INITIALIZER; 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 */ /* Allocate a new AFile structure for the file */
(void) NewAFile (IF, F); (void) NewAFile (IF, F);
/* Allocate the input line buffer */
Line = NewStrBuf ();
} }
@@ -297,48 +300,101 @@ static void CloseIncludeFile (void)
void ClearLine (void) static void GetInputChar (void)
/* Clear the current input line */ /* 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'; /* Drop all pushed fragments that don't have data left */
lptr = line; while (SB_GetIndex (Line) >= SB_GetLen (Line)) {
CurC = '\0'; /* Cannot read more from this line, check next line on stack if any */
NextC = '\0'; if (CollCount (&InputStack) == 0) {
} /* This is THE line */
break;
}
FreeStrBuf (Line);
Line = CollPop (&InputStack);
}
/* Now get the next characters from the line */
if (SB_GetIndex (Line) >= SB_GetLen (Line)) {
void InitLine (const char* Buf) CurC = NextC = '\0';
/* 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];
} else { } 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) void NextChar (void)
/* Read the next character from the input stream and make CurC and NextC /* Skip the current input character and read the next one from the input
* valid. If end of line is reached, both are set to NUL, no more lines * stream. CurC and NextC are valid after the call. If end of line is
* are read by this function. * reached, both are set to NUL, no more lines are read by this function.
*/ */
{ {
if (lptr[0] != '\0') { /* Skip the last character read */
++lptr; SB_Skip (Line);
CurC = lptr[0];
if (CurC != '\0') { /* Read the next one */
NextC = lptr[1]; GetInputChar ();
} else { }
NextC = '\0';
}
} else {
CurC = NextC = '\0'; 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) int NextLine (void)
/* Get a line from the current input. Returns 0 on end of file. */ /* Get a line from the current input. Returns 0 on end of file. */
{ {
AFile* Input; AFile* Input;
unsigned Len;
unsigned Part;
unsigned Start;
int Done;
/* Setup the line */ /* Clear the current line */
ClearLine (); ClearLine ();
/* If there is no file open, bail out, otherwise get the current input file */ /* If there is no file open, bail out, otherwise get the current input file */
if (CollCount (&AFiles) == 0) { if (CollCount (&AFiles) == 0) {
return 0; return 0;
} }
Input = (AFile*) CollLast (&AFiles); Input = CollLast (&AFiles);
/* Read lines until we get one with real contents */ /* Read characters until we have one complete line */
Len = 0; while (1) {
Done = 0;
while (!Done && Len < LINESIZE) {
while (fgets (line + Len, LINESIZE - Len, Input->F) == 0) { /* Read the next character */
int C = fgetc (Input->F);
/* Assume EOF */ /* Check for EOF */
ClearLine (); if (C == EOF) {
/* Leave the current file */ /* Leave the current file */
CloseIncludeFile (); CloseIncludeFile ();
/* If there is no file open, bail out, otherwise get the /* Accept files without a newline at the end */
* current input file if (SB_NotEmpty (Line)) {
*/ break;
if (CollCount (&AFiles) == 0) { }
return 0;
}
Input = (AFile*) CollLast (&AFiles);
} /* 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 */ /* Check for end of line */
++Input->Line; if (C == '\n') {
/* Remove the trailing cr/lf if we have one. We will ignore both, cr /* We got a new line */
* and lf on all systems since this enables us to compile DOS/Windows ++Input->Line;
* 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';
/* Check if we have a line continuation character at the end. If not, /* If the \n is preceeded by a \r, remove the \r, so we can read
* we're done. * DOS/Windows files under *nix.
*/ */
if (Len > 0 && line[Len-1] == '\\') { if (SB_LookAtLast (Line) == '\r') {
line[Len-1] = '\n'; /* Replace by newline */ SB_Drop (Line, 1);
} else { }
Done = 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. */ /* Add a termination character to the string buffer */
InitLine (line); SB_Terminate (Line);
/* Initialize the current and next characters. */
InitLine (Line);
/* Create line information for this line */ /* Create line information for this line */
UpdateLineInfo (Input->Input, Input->Line, line); UpdateLineInfo (Input->Input, Input->Line, SB_GetConstBuf (Line));
/* Done */ /* Done */
return 1; return 1;
@@ -426,17 +491,17 @@ const char* GetCurrentFile (void)
{ {
unsigned AFileCount = CollCount (&AFiles); unsigned AFileCount = CollCount (&AFiles);
if (AFileCount > 0) { if (AFileCount > 0) {
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1); const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
return AF->Input->Name; return AF->Input->Name;
} else { } else {
/* No open file. Use the main file if we have one. */ /* No open file. Use the main file if we have one. */
unsigned IFileCount = CollCount (&IFiles); unsigned IFileCount = CollCount (&IFiles);
if (IFileCount > 0) { if (IFileCount > 0) {
const IFile* IF = (const IFile*) CollAt (&IFiles, 0); const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
return IF->Name; return IF->Name;
} else { } else {
return "(outside file scope)"; return "(outside file scope)";
} }
} }
} }

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* R<EFBFBD>merstrasse 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -40,6 +40,9 @@
#include <stdio.h> #include <stdio.h>
/* common */
#include "strbuf.h"
/*****************************************************************************/ /*****************************************************************************/
@@ -48,13 +51,8 @@
/* Maximum length of an input line and the corresponding char array */ /* The current input line */
#define LINEMAX 4095 extern StrBuf* Line;
#define LINESIZE LINEMAX+1
/* Input line stuff */
extern char* line;
extern const char* lptr; /* ### Remove this */
/* Current and next input character */ /* Current and next input character */
extern char CurC; extern char CurC;
@@ -64,7 +62,7 @@ extern char NextC;
typedef struct IFile IFile; typedef struct IFile IFile;
struct IFile { struct IFile {
unsigned Index; /* File index */ unsigned Index; /* File index */
unsigned Usage; /* Usage counter */ unsigned Usage; /* Usage counter */
unsigned long Size; /* File size */ unsigned long Size; /* File size */
unsigned long MTime; /* Time of last modification */ unsigned long MTime; /* Time of last modification */
char Name[1]; /* Name of file (dynamically allocated) */ 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); void OpenIncludeFile (const char* Name, unsigned DirSpec);
/* Open an include file and insert it into the tables. */ /* 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); void NextChar (void);
/* Read the next character from the input stream and make CurC and NextC /* 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 * valid. If end of line is reached, both are set to NUL, no more lines
* are read by this function. * 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); int NextLine (void);
/* Get a line from the current input. Returns 0 on end of file. */ /* Get a line from the current input. Returns 0 on end of file. */

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* R<>merstra<72>e 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -56,12 +56,6 @@
#define MACRO_TAB_SIZE 211 #define MACRO_TAB_SIZE 211
static Macro* MacroTab[MACRO_TAB_SIZE]; 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 */ /* Initialize the data */
M->Next = 0; M->Next = 0;
M->Expanding = 0;
M->ArgCount = -1; /* Flag: Not a function like macro */ M->ArgCount = -1; /* Flag: Not a function like macro */
M->MaxArgs = 0; M->MaxArgs = 0;
M->FormalArgs = 0; InitCollection (&M->FormalArgs);
M->ActualArgs = 0; InitStrBuf (&M->Replacement);
M->Replacement = 0;
memcpy (M->Name, Name, Len+1); memcpy (M->Name, Name, Len+1);
/* Return the new macro */ /* Return the new macro */
@@ -101,14 +95,13 @@ void FreeMacro (Macro* M)
* table, use UndefineMacro for that. * table, use UndefineMacro for that.
*/ */
{ {
int I; unsigned I;
for (I = 0; I < M->ArgCount; ++I) { for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
xfree (M->FormalArgs[I]); xfree (CollAtUnchecked (&M->FormalArgs, I));
} }
xfree (M->FormalArgs); DoneCollection (&M->FormalArgs);
xfree (M->ActualArgs); DoneStrBuf (&M->Replacement);
xfree (M->Replacement);
xfree (M); xfree (M);
} }
@@ -135,7 +128,7 @@ void DefineTextMacro (const char* Name, const char* Val)
Macro* M = NewMacro (Name); Macro* M = NewMacro (Name);
/* Set the value as replacement text */ /* Set the value as replacement text */
M->Replacement = xstrdup (Val); SB_CopyStr (&M->Replacement, Val);
/* Insert the macro into the macro table */ /* Insert the macro into the macro table */
InsertMacro (M); InsertMacro (M);
@@ -144,26 +137,14 @@ void DefineTextMacro (const char* Name, const char* Val)
void InsertMacro (Macro* M) void InsertMacro (Macro* M)
/* Insert the given macro into the macro table. This call will also allocate /* Insert the given macro into the macro table. */
* the ActualArgs parameter array.
*/
{ {
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 */ /* 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 */ /* Insert the macro */
M->Next = MacroTab[Hash]; M->Next = MacroTab[Hash];
MacroTab[Hash] = M; 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; L->Next = M->Next;
} }
/* Decrement the number of macros starting with this char */
MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]--;
/* Delete the macro */ /* Delete the macro */
FreeMacro (M); FreeMacro (M);
@@ -236,38 +214,21 @@ Macro* FindMacro (const char* Name)
int IsMacro (const char* Name) int FindMacroArg (Macro* M, const char* Arg)
/* Return true if the given name is the name of a macro, return false otherwise */ /* Search for a formal macro argument. If found, return the index of the
{ * argument. If the argument was not found, return -1.
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.
*/ */
{ {
return (MacroFlagTab[C] > 0); unsigned I;
} for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
/* Found */
return I;
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];
} }
} }
/* Not found */ /* 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 * Beware: Don't use FindMacroArg here, since the actual argument array
* may not be initialized. * may not be initialized.
*/ */
int I; unsigned I;
for (I = 0; I < M->ArgCount; ++I) { for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
if (strcmp (M->FormalArgs[I], Arg) == 0) { if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
/* Found */ /* Found */
Error ("Duplicate macro parameter: `%s'", Arg); Error ("Duplicate macro parameter: `%s'", Arg);
break; 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 */ /* 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 */ /* Compare the arguments */
for (I = 0; I < M1->ArgCount; ++I) { 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; return 1;
} }
} }
/* Compare the replacement */ /* Compare the replacement */
return strcmp (M1->Replacement, M2->Replacement); return SB_Compare (&M1->Replacement, &M2->Replacement);
} }

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* R<>merstra<72>e 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* 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; typedef struct Macro Macro;
struct Macro { struct Macro {
Macro* Next; /* Next macro with same hash value */ Macro* Next; /* Next macro with same hash value */
int Expanding; /* Are we currently expanding this macro? */
int ArgCount; /* Number of parameters, -1 = no parens */ int ArgCount; /* Number of parameters, -1 = no parens */
unsigned MaxArgs; /* Size of formal argument list */ unsigned MaxArgs; /* Size of formal argument list */
char** FormalArgs; /* Formal argument list */ Collection FormalArgs; /* Formal argument list (char*) */
char const** ActualArgs; /* Actual argument list */ StrBuf Replacement; /* Replacement text */
char* Replacement; /* Replacement text */
char Name[1]; /* Name, dynamically allocated */ 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 */ /* Define a macro for a textual constant */
void InsertMacro (Macro* M); void InsertMacro (Macro* M);
/* Insert the given macro into the macro table. This call will also allocate /* Insert the given macro into the macro table. */
* the ActualArgs parameter array.
*/
int UndefineMacro (const char* Name); int UndefineMacro (const char* Name);
/* Search for the macro with the given name and remove it from the macro /* 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); Macro* FindMacro (const char* Name);
/* Find a macro with the given name. Return the macro definition or NULL */ /* 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 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); int FindMacroArg (Macro* M, const char* Arg);
/* Return true if the given character may be the start of the name of an /* Search for a formal macro argument. If found, return the index of the
* existing macro, return false if not. * argument. If the argument was not found, return -1.
*/
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.
*/ */
void AddMacroArg (Macro* M, const char* Arg); void AddMacroArg (Macro* M, const char* Arg);

View File

@@ -82,6 +82,7 @@ static void Usage (void)
"Short options:\n" "Short options:\n"
" -Cl\t\t\tMake local variables static\n" " -Cl\t\t\tMake local variables static\n"
" -Dsym[=defn]\t\tDefine a symbol\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" " -I dir\t\tSet an include directory search path\n"
" -O\t\t\tOptimize code\n" " -O\t\t\tOptimize code\n"
" -Oi\t\t\tOptimize code, inline more code\n" " -Oi\t\t\tOptimize code, inline more code\n"
@@ -802,7 +803,11 @@ int main (int argc, char* argv[])
DefineSym (GetArg (&I, 2)); DefineSym (GetArg (&I, 2));
break; break;
case 'I': case 'E':
PreprocessOnly = 1;
break;
case 'I':
OptIncludeDir (Arg, GetArg (&I, 2)); OptIncludeDir (Arg, GetArg (&I, 2));
break; break;
@@ -908,7 +913,7 @@ int main (int argc, char* argv[])
/* Create dependencies if requested */ /* Create dependencies if requested */
if (CreateDep) { if (CreateDep) {
DoCreateDep (OutputFile); 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

View File

@@ -181,7 +181,7 @@ static int SkipWhite (void)
*/ */
{ {
while (1) { while (1) {
while (CurC == 0) { while (CurC == '\0') {
if (NextLine () == 0) { if (NextLine () == 0) {
return 0; return 0;
} }
@@ -197,27 +197,30 @@ static int SkipWhite (void)
void SymName (char* s) void SymName (char* S)
/* Get symbol from input stream */ /* 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 { do {
if (k != MAX_IDENTLEN) { if (Len < MAX_IDENTLEN) {
++k; ++Len;
*s++ = CurC; *S++ = CurC;
} }
NextChar (); NextChar ();
} while (IsIdent (CurC) || IsDigit (CurC)); } while (IsIdent (CurC) || IsDigit (CurC));
*s = '\0'; *S = '\0';
} }
int IsSym (char *s) int IsSym (char* S)
/* Get symbol from input stream or return 0 if not a symbol. */ /* If a symbol follows, read it and return 1, otherwise return 0 */
{ {
if (IsIdent (CurC)) { if (IsIdent (CurC)) {
SymName (s); SymName (S);
return 1; return 1;
} else { } else {
return 0; return 0;
@@ -245,7 +248,7 @@ static void SetTok (int tok)
static int ParseChar (void) static int ParseChar (void)
/* Parse a character. Converts \n into EOL, etc. */ /* Parse a character. Converts escape chars into character codes. */
{ {
int I; int I;
unsigned Val; unsigned Val;
@@ -292,9 +295,20 @@ static int ParseChar (void)
case 'X': case 'X':
/* Hex character constant */ /* Hex character constant */
NextChar (); NextChar ();
Val = HexVal (CurC) << 4; if (!IsXDigit (CurC)) {
NextChar (); Error ("\\x used with no following hex digits");
C = Val | HexVal (CurC); /* Do not translate */ 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; break;
case '0': case '0':
case '1': case '1':
@@ -304,16 +318,16 @@ static int ParseChar (void)
case '5': case '5':
case '6': case '6':
case '7': case '7':
/* Octal constant */ /* Octal constant ### FIXME: Eat all available octal chars! */
I = 0; I = 0;
Val = CurC - '0'; Val = CurC - '0';
while (NextC >= '0' && NextC <= '7' && ++I <= 3) { while (IsODigit (NextC) && ++I <= 3) {
NextChar (); NextChar ();
Val = (Val << 3) | (CurC - '0'); Val = (Val << 3) | (CurC - '0');
} }
C = (int) Val; C = (int) Val;
if (Val >= 256) { if (Val >= 256) {
Error ("Character constant out of range"); Error ("Character constant out of range: %u", Val);
C = ' '; C = ' ';
} }
break; break;

View File

@@ -223,11 +223,14 @@ INLINE int TokIsTypeQual (const Token* T)
# define TokIsTypeQual(T) ((T)->Tok >= TOK_FIRST_TYPEQUAL && (T)->Tok <= TOK_LAST_TYPEQUAL) # define TokIsTypeQual(T) ((T)->Tok >= TOK_FIRST_TYPEQUAL && (T)->Tok <= TOK_LAST_TYPEQUAL)
#endif #endif
void SymName (char* s); void SymName (char* S);
/* Get symbol from input stream */ /* 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); int IsSym (char* S);
/* Get symbol from input stream or return 0 if not a symbol. */ /* If a symbol follows, read it and return 1, otherwise return 0 */
void NextToken (void); void NextToken (void);
/* Get next token from input stream */ /* Get next token from input stream */