From 04ee693c00802bb541934803ac947e316e33d166 Mon Sep 17 00:00:00 2001 From: cuz Date: Wed, 21 Jun 2000 21:02:44 +0000 Subject: [PATCH] Fixed a bug git-svn-id: svn://svn.cc65.org/cc65/trunk@91 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/expr.c | 2 +- src/cc65/input.c | 133 +++++---- src/cc65/input.h | 36 ++- src/cc65/pragma.c | 59 ++-- src/cc65/preproc.c | 688 ++++++++++++++++++++++++--------------------- src/cc65/preproc.h | 5 +- src/cc65/scanner.c | 233 ++++++++------- src/cc65/scanner.h | 6 +- 8 files changed, 632 insertions(+), 530 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 4f1a46858..48c284eb2 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -800,7 +800,7 @@ static int primary (struct expent* lval) * and returning int. */ Warning (WARN_FUNC_WITHOUT_PROTO); - Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF); + Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC); lval->e_tptr = Sym->Type; lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB; lval->e_name = (unsigned long) Sym->Name; diff --git a/src/cc65/input.c b/src/cc65/input.c index ad31ebc30..d6c553d65 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -49,7 +49,7 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -57,32 +57,39 @@ /* Input line stuff */ static char LineBuf [LINESIZE]; char* line = LineBuf; -char* lptr = LineBuf; +const char* lptr = LineBuf; + +/* Current and next input character */ +char CurC = '\0'; +char NextC = '\0'; /* Maximum count of nested includes */ -#define MAX_INC_NESTING 20 +#define MAX_INC_NESTING 16 /* Struct that describes an input file */ typedef struct IFile IFile; struct IFile { - IFile* Next; /* Next file in single linked list */ + IFile* Next; /* Next file in single linked list */ IFile* Active; /* Next file in list of active includes */ unsigned Index; /* File index */ - unsigned Line; /* Line number for this file */ - FILE* F; /* Input file stream */ + unsigned Line; /* Line number for this file */ + FILE* F; /* Input file stream */ char Name[1]; /* Name of file (dynamically allocated) */ }; +/* Main file input data */ +static const IFile* MainFile = 0; + /* List of input files */ static unsigned IFileTotal = 0; /* Total number of files */ -static IFile* IFileList = 0; /* Single linked list of all files */ +static IFile* IFileList = 0; /* Single linked list of all files */ static unsigned IFileCount = 0; /* Number of active input files */ -static IFile* Input = 0; /* Single linked list of active files */ +static IFile* Input = 0; /* Single linked list of active files */ /*****************************************************************************/ -/* struct IFile */ +/* struct IFile */ /*****************************************************************************/ @@ -108,6 +115,7 @@ static IFile* NewIFile (const char* Name, FILE* F) IF->Active = Input; Input = IF; ++IFileCount; + ++IFileTotal; /* Return the new struct */ return IF; @@ -132,7 +140,7 @@ void OpenMainFile (const char* Name) } /* Setup a new IFile structure */ - NewIFile (Name, F); + MainFile = NewIFile (Name, F); } @@ -187,6 +195,55 @@ static void CloseIncludeFile (void) /* Make this file inactive and the last one active again */ Input = Input->Active; + + /* Adjust the counter */ + --IFileCount; +} + + + +void ClearLine (void) +/* Clear the current input line */ +{ + line[0] = '\0'; + lptr = line; + CurC = '\0'; + NextC = '\0'; +} + + + +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]; + } 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. + */ +{ + if (lptr[0] != '\0') { + ++lptr; + CurC = lptr[0]; + if (CurC != '\0') { + NextC = lptr[1]; + } else { + NextC = '\0'; + } + } else { + CurC = NextC = '\0'; + } } @@ -255,17 +312,11 @@ int NextLine (void) } } - /* Got a line */ - return 1; -} - - + /* Got a line. Initialize the current and next characters. */ + InitLine (line); -void ClearLine (void) -/* Clear the current input line */ -{ - line [0] = '\0'; - lptr = line; + /* Done */ + return 1; } @@ -274,7 +325,11 @@ const char* GetCurrentFile (void) /* Return the name of the current input file */ { if (Input == 0) { - return "(outside file scope)"; + if (MainFile) { + return MainFile->Name; + } else { + return "(outside file scope)"; + } } else { return Input->Name; } @@ -290,39 +345,3 @@ unsigned GetCurrentLine (void) -int nch (void) -/* Get the next char in input stream (the one behind the current one) */ -{ - if (*lptr == '\0') { - return 0; - } else { - return lptr[1] & 0xFF; - } -} - - - -int cgch (void) -/* Get the current character in the input stream and advance line - * pointer (unless already at end of line). - */ -{ - if (*lptr == '\0') { - return (0); - } else { - return (*lptr++ & 0xFF); - } -} - - - -int gch (void) -/* Get the current character in the input stream and advance line - * pointer (no end of line check is performed). - */ -{ - return (*lptr++ & 0xFF); -} - - - diff --git a/src/cc65/input.h b/src/cc65/input.h index 662ab2f59..8f3a783c7 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -50,7 +50,11 @@ /* Input line stuff */ extern char* line; -extern char* lptr; +extern const char* lptr; /* ### Remove this */ + +/* Current and next input character */ +extern char CurC; +extern char NextC; @@ -66,32 +70,26 @@ void OpenMainFile (const char* Name); void OpenIncludeFile (const char* Name, unsigned DirSpec); /* Open an include file and insert it into the tables. */ -int NextLine (void); -/* Get a line from the current input. Returns 0 on end of file. */ - void ClearLine (void); /* Clear the current input line */ -const char* GetCurrentFile (void); -/* Return the name of the current input file */ - -unsigned GetCurrentLine (void); -/* Return the line number in the current input file */ +void InitLine (const char* Buf); +/* Initialize lptr from Buf and read CurC and NextC from the new input line */ -int nch (void); -/* Get the next char in input stream (the one behind the current one) */ - -int cgch (void); -/* Get the current character in the input stream and advance line - * pointer (unless already at end of 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. */ -int gch (void); -/* Get the current character in the input stream and advance line - * pointer (no end of line check is performed). - */ +int NextLine (void); +/* Get a line from the current input. Returns 0 on end of file. */ +const char* GetCurrentFile (void); +/* Return the name of the current input file */ +unsigned GetCurrentLine (void); +/* Return the line number in the current input file */ diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index 511eddb59..c88a95116 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -40,7 +40,6 @@ #include "error.h" #include "litpool.h" #include "symtab.h" -#include "preproc.h" #include "scanner.h" #include "codegen.h" #include "expr.h" @@ -55,7 +54,7 @@ /* Tokens for the #pragmas */ -enum { +typedef enum { PR_BSSSEG, PR_CODESEG, PR_DATASEG, @@ -65,16 +64,54 @@ enum { PR_STATICLOCALS, PR_ZPSYM, PR_ILLEGAL +} pragma_t; + +/* Pragma table */ +static const struct Pragma { + const char* Key; /* Keyword */ + pragma_t Tok; /* Token */ +} Pragmas[] = { + { "bssseg", PR_BSSSEG }, + { "codeseg", PR_CODESEG }, + { "dataseg", PR_DATASEG }, + { "regvaraddr", PR_REGVARADDR }, + { "rodataseg", PR_RODATASEG }, + { "signedchars", PR_SIGNEDCHARS }, + { "staticlocals", PR_STATICLOCALS }, + { "zpsym", PR_ZPSYM }, }; +/* Number of pragmas */ +#define PRAGMA_COUNT (sizeof(Pragmas) / sizeof(Pragmas[0])) + /*****************************************************************************/ -/* code */ +/* Code */ /*****************************************************************************/ +static int CmpKey (const void* Key, const void* Elem) +/* Compare function for bsearch */ +{ + return strcmp ((const char*) Key, ((const struct Pragma*) Elem)->Key); +} + + + +static pragma_t FindPragma (const char* Key) +/* Find a pragma and return the token. Return PR_ILLEGAL if the keyword is + * not a valid pragma. + */ +{ + struct Pragma* P; + P = bsearch (Key, Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey); + return P? P->Tok : PR_ILLEGAL; +} + + + static void StringPragma (void (*Func) (const char*)) /* Handle a pragma that expects a string parameter */ { @@ -113,19 +150,7 @@ static void FlagPragma (unsigned char* Flag) void DoPragma (void) /* Handle pragmas */ { - static const struct tok_elt Pragmas [] = { - { "bssseg", PR_BSSSEG }, - { "codeseg", PR_CODESEG }, - { "dataseg", PR_DATASEG }, - { "regvaraddr", PR_REGVARADDR }, - { "rodataseg", PR_RODATASEG }, - { "signedchars", PR_SIGNEDCHARS }, - { "staticlocals", PR_STATICLOCALS }, - { "zpsym", PR_ZPSYM }, - { 0, PR_ILLEGAL }, - }; - - int Pragma; + pragma_t Pragma; /* Skip the token itself */ NextToken (); @@ -137,7 +162,7 @@ void DoPragma (void) } /* Do we know this pragma? */ - Pragma = searchtok (CurTok.Ident, Pragmas); + Pragma = FindPragma (CurTok.Ident); if (Pragma == PR_ILLEGAL) { /* According to the ANSI standard, we're not allowed to generate errors * for unknown pragmas, however, we're allowed to warn - and we will diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 835a5ff4f..115d57beb 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -29,7 +29,8 @@ -static int Pass1 (char* from, char* to); +static int Pass1 (const char* From, char* To); +/* Preprocessor pass 1. Remove whitespace and comments. */ @@ -43,7 +44,7 @@ static int Pass1 (char* from, char* to); unsigned char Preprocessing = 0; /* Management data for #if */ -#define N_IFDEF 16 +#define N_IFDEF 16 static int i_ifdef = -1; static char s_ifdef[N_IFDEF]; @@ -81,63 +82,76 @@ static void keepstr (const char* S) -static void comment (void) -/* Remove comment from line. */ +static void Comment (void) +/* Remove a C comment from line. */ { + /* Remember the current line number, so we can output better error + * messages if the comment is not terminated in the current file. + */ unsigned StartingLine = GetCurrentLine(); - gch (); - gch (); - while (*lptr != '*' || nch () != '/') { - if (*lptr == '\0') { + /* Skip the start of comment chars */ + NextChar (); + NextChar (); + + /* Skip the comment */ + while (CurC != '*' || NextC != '/') { + if (CurC == '\0') { if (NextLine () == 0) { PPError (ERR_EOF_IN_COMMENT, StartingLine); return; } } else { - if (*lptr == '/' && nch() == '*') { + if (CurC == '/' && NextC == '*') { PPWarning (WARN_NESTED_COMMENT); } - ++lptr; + NextChar (); } } - gch (); - gch (); + + /* Skip the end of comment chars */ + NextChar (); + NextChar (); } -static void skipblank (void) +static void SkipBlank (void) /* Skip blanks and tabs in the input stream. */ { - while (IsBlank (*lptr)) { - ++lptr; + while (IsBlank (CurC)) { + NextChar (); } } -static char* CopyQuotedString (int Quote, char* Target) -/* Copy a single or double quoted string from lptr to Target. Return the +static char* CopyQuotedString (char* Target) +/* Copy a single or double quoted string from the input to Target. Return the * new target pointer. Target will not be terminated after the copy. */ { - /* Copy the starting quote */ - *Target++ = gch(); + /* Remember the quote character, copy it to the target buffer and skip it */ + char Quote = CurC; + *Target++ = CurC; + NextChar (); /* Copy the characters inside the string */ - while (*lptr != '\0' && *lptr != Quote) { + while (CurC != '\0' && CurC != Quote) { /* Keep an escaped char */ - if (*lptr == '\\') { - *Target++ = gch(); + if (CurC == '\\') { + *Target++ = CurC; + NextChar (); } /* Copy the character */ - *Target++ = cgch(); + *Target++ = CurC; + NextChar (); } /* If we had a terminating quote, copy it */ - if (*lptr) { - *Target++ = gch(); + if (CurC != '\0') { + *Target++ = CurC; + NextChar (); } /* Return the new target pointer */ @@ -152,12 +166,12 @@ static char* CopyQuotedString (int Quote, char* Target) -static int macname (char *sname) +static int MacName (char* Ident) /* Get macro symbol name. If error, print message and clear line. */ { - if (issym (sname) == 0) { + if (IsSym (Ident) == 0) { PPError (ERR_IDENT_EXPECTED); - ClearLine (); + ClearLine (); return 0; } else { return 1; @@ -169,20 +183,19 @@ static int macname (char *sname) static void ExpandMacroArgs (Macro* M) /* Preprocessor pass 2. Perform macro substitution. */ { - int C; ident Ident; const char* Replacement; - char* SavePtr; + const char* SavePtr; /* Save the current line pointer and setup the new ones */ SavePtr = lptr; - lptr = M->Replacement; + InitLine (M->Replacement); /* Copy the macro replacement checking for parameters to replace */ - while ((C = *lptr) != '\0') { + while (CurC != '\0') { /* If the next token is an identifier, check for a macro arg */ - if (IsIdent (C)) { - symname (Ident); + if (IsIdent (CurC)) { + SymName (Ident); Replacement = FindMacroArg (M, Ident); if (Replacement) { /* Macro arg, keep the replacement */ @@ -191,9 +204,9 @@ static void ExpandMacroArgs (Macro* M) /* No macro argument, keep the original identifier */ keepstr (Ident); } - } else if (C == '#' && IsIdent (nch ())) { - ++lptr; - symname (Ident); + } else if (CurC == '#' && IsIdent (NextC)) { + NextChar (); + SymName (Ident); Replacement = FindMacroArg (M, Ident); if (Replacement) { keepch ('\"'); @@ -203,15 +216,16 @@ static void ExpandMacroArgs (Macro* M) keepch ('#'); keepstr (Ident); } - } else if (IsQuoteChar(C)) { - mptr = CopyQuotedString (C, mptr); + } else if (IsQuoteChar (CurC)) { + mptr = CopyQuotedString (mptr); } else { - *mptr++ = *lptr++; + *mptr++ = CurC; + NextChar (); } } /* Reset the line pointer */ - lptr = SavePtr; + InitLine (SavePtr); } @@ -219,22 +233,21 @@ static void ExpandMacroArgs (Macro* M) static int MacroCall (Macro* M) /* Process a function like macro */ { - unsigned ArgCount; /* Macro argument count */ + unsigned ArgCount; /* Macro argument count */ unsigned ParCount; /* Number of open parenthesis */ char Buf[LINESIZE]; /* Argument buffer */ - char C; const char* ArgStart; char* B; /* Expect an argument list */ - skipblank (); - if (*lptr != '(') { + SkipBlank (); + if (CurC != '(') { PPError (ERR_ILLEGAL_MACRO_CALL); return 0; } /* Eat the left paren */ - ++lptr; + NextChar (); /* Read the actual macro arguments and store pointers to these arguments * into the array of actual arguments in the macro definition. @@ -244,52 +257,59 @@ static int MacroCall (Macro* M) ArgStart = Buf; B = Buf; while (1) { - C = *lptr; - if (C == '(') { - *B++ = gch (); + if (CurC == '(') { + /* Nested parenthesis */ + *B++ = CurC; + NextChar (); ++ParCount; - } else if (IsQuoteChar(C)) { - B = CopyQuotedString (C, B); - } else if (C == ',' || C == ')') { + } else if (IsQuoteChar (CurC)) { + B = CopyQuotedString (B); + } else if (CurC == ',' || CurC == ')') { if (ParCount == 0) { - /* End of actual argument */ - gch (); + /* End of actual argument */ *B++ = '\0'; - while (IsBlank(*ArgStart)) { - ++ArgStart; - } + while (IsBlank(*ArgStart)) { + ++ArgStart; + } if (ArgCount < M->ArgCount) { M->ActualArgs[ArgCount++] = ArgStart; - } else if (C != ')' || *ArgStart != '\0' || M->ArgCount > 0) { - /* Be sure not to count the single empty argument for a - * macro that does not have arguments. - */ + } else if (CurC != ')' || *ArgStart != '\0' || M->ArgCount > 0) { + /* Be sure not to count the single empty argument for a + * macro that does not have arguments. + */ ++ArgCount; + } + + /* Check for end of macro param list */ + if (CurC == ')') { + NextChar (); + break; } - /* Start the next one */ + /* Start the next param */ ArgStart = B; - if (C == ')') { - break; - } + NextChar (); } else { - *B++ = gch (); - if (C == ')') { + /* Comma or right paren inside nested parenthesis */ + if (CurC == ')') { --ParCount; } + *B++ = CurC; + NextChar (); } - } else if (IsBlank (C)) { + } else if (IsBlank (CurC)) { /* Squeeze runs of blanks */ *B++ = ' '; - skipblank (); - } else if (C == '\0') { + SkipBlank (); + } else if (CurC == '\0') { /* End of line inside macro argument list - read next line */ if (NextLine () == 0) { return 0; } } else { /* Just copy the character */ - *B++ = *lptr++; + *B++ = CurC; + NextChar (); } } @@ -331,14 +351,14 @@ static void ExpandMacro (Macro* M) static void addmac (void) /* Add a macro to the macro table. */ { - char* saveptr; - ident Ident; - char Buf[LINESIZE]; - Macro* M; + char* saveptr; + ident Ident; + char Buf[LINESIZE]; + Macro* M; /* Read the macro name */ - skipblank (); - if (!macname (Ident)) { + SkipBlank (); + if (!MacName (Ident)) { return; } @@ -346,34 +366,36 @@ static void addmac (void) M = NewMacro (Ident); /* Check if this is a function like macro */ - if (*lptr == '(') { + if (CurC == '(') { /* Skip the left paren */ - gch (); + NextChar (); /* Set the marker that this is a function like macro */ M->ArgCount = 0; /* Read the formal parameter list */ while (1) { - skipblank (); - if (*lptr == ')') + SkipBlank (); + if (CurC == ')') break; - if (macname (Ident) == 0) { + if (MacName (Ident) == 0) { return; } AddMacroArg (M, Ident); - skipblank (); - if (*lptr != ',') + SkipBlank (); + if (CurC != ',') break; - gch (); + NextChar (); } - if (*lptr != ')') { + + /* Check for a right paren and eat it if we find one */ + if (CurC != ')') { PPError (ERR_RPAREN_EXPECTED); ClearLine (); return; } - gch (); + NextChar (); } /* Insert the macro into the macro table and allocate the ActualArgs array */ @@ -382,7 +404,7 @@ static void addmac (void) /* Remove whitespace and comments from the line, store the preprocessed * line into Buf. */ - skipblank (); + SkipBlank (); saveptr = mptr; Pass1 (lptr, Buf); mptr = saveptr; @@ -399,59 +421,63 @@ static void addmac (void) -static int Pass1 (char* from, char* to) -/* Preprocessor pass 1. Remove whitespace and comments. */ +static int Pass1 (const char* From, char* To) +/* Preprocessor pass 1. Remove whitespace and comments. */ { - int c; - int done; - ident Ident; - int HaveParen; + int done; + ident Ident; + int HaveParen; + + /* Initialize reading from "From" */ + InitLine (From); - lptr = from; - mptr = to; + /* Target is "To" */ + mptr = To; + + /* Loop removing ws and comments */ done = 1; - while ((c = *lptr) != 0) { - if (IsBlank (c)) { + while (CurC != '\0') { + if (IsBlank (CurC)) { keepch (' '); - skipblank (); - } else if (IsIdent (c)) { - symname (Ident); + SkipBlank (); + } else if (IsIdent (CurC)) { + SymName (Ident); if (Preprocessing && strcmp(Ident, "defined") == 0) { - /* Handle the "defined" operator */ - skipblank(); - HaveParen = 0; - if (*lptr == '(') { - HaveParen = 1; - ++lptr; - skipblank(); - } - if (!IsIdent(c)) { - PPError (ERR_IDENT_EXPECTED); - *mptr++ = '0'; - } else { - symname (Ident); - *mptr++ = IsMacro(Ident)? '1' : '0'; - if (HaveParen) { - skipblank(); - if (*lptr != ')') { - PPError (ERR_RPAREN_EXPECTED); - } else { - ++lptr; - } - } - } + /* Handle the "defined" operator */ + SkipBlank(); + HaveParen = 0; + if (CurC == '(') { + HaveParen = 1; + NextChar (); + SkipBlank(); + } + if (!IsIdent (CurC)) { + PPError (ERR_IDENT_EXPECTED); + *mptr++ = '0'; + } else { + SymName (Ident); + *mptr++ = IsMacro (Ident)? '1' : '0'; + if (HaveParen) { + SkipBlank(); + if (CurC != ')') { + PPError (ERR_RPAREN_EXPECTED); + } else { + NextChar (); + } + } + } } else { - if (MaybeMacro(c)) { - done = 0; - } - keepstr (Ident); + if (MaybeMacro (Ident[0])) { + done = 0; + } + keepstr (Ident); } - } else if (IsQuoteChar(c)) { - mptr = CopyQuotedString (c, mptr); - } else if (c == '/' && nch () == '*') { + } else if (IsQuoteChar (CurC)) { + mptr = CopyQuotedString (mptr); + } else if (CurC == '/' && NextC == '*') { keepch (' '); - comment (); - } else if (ANSI == 0 && c == '/' && nch () == '/') { + Comment (); + } else if (ANSI == 0 && CurC == '/' && NextC == '/') { keepch (' '); /* Beware: Because line continuation chars are handled when reading * lines, we may only skip til the end of the source line, which @@ -459,13 +485,14 @@ static int Pass1 (char* from, char* to) * source line is denoted by a lf (\n) character. */ do { - ++lptr; - } while (*lptr != '\n' && *lptr != '\0'); - if (*lptr == '\n') { - ++lptr; + NextChar (); + } while (CurC != '\n' && CurC != '\0'); + if (CurC == '\n') { + NextChar (); } } else { - *mptr++ = *lptr++; + *mptr++ = CurC; + NextChar (); } } keepch ('\0'); @@ -474,32 +501,37 @@ static int Pass1 (char* from, char* to) -static int Pass2 (char *from, char *to) +static int Pass2 (const char* From, char* To) /* Preprocessor pass 2. Perform macro substitution. */ { - int C; - int no_chg; - ident Ident; - Macro* M; + int no_chg; + ident Ident; + Macro* M; + + /* Initialize reading from "From" */ + InitLine (From); - lptr = from; - mptr = to; + /* Target is "To" */ + mptr = To; + + /* Loop substituting macros */ no_chg = 1; - while ((C = *lptr) != '\0') { + while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ - if (IsIdent (C)) { - symname (Ident); + if (IsIdent (CurC)) { + SymName (Ident); M = FindMacro (Ident); if (M) { - ExpandMacro (M); - no_chg = 0; + ExpandMacro (M); + no_chg = 0; } else { - keepstr (Ident); + keepstr (Ident); } - } else if (IsQuoteChar(C)) { - mptr = CopyQuotedString (C, mptr); + } else if (IsQuoteChar(CurC)) { + mptr = CopyQuotedString (mptr); } else { - *mptr++ = *lptr++; + *mptr++ = CurC; + NextChar (); } } return no_chg; @@ -512,7 +544,6 @@ static void xlateline (void) { int cnt; int Done; - char *p; Done = Pass1 (line, mline); if (ExpandMacros == 0) { @@ -521,7 +552,8 @@ static void xlateline (void) } cnt = 5; do { - p = line; + /* Swap mline and line */ + char* p = line; line = mline; mline = p; if (Done) @@ -529,7 +561,9 @@ static void xlateline (void) Done = Pass2 (line, mline); keepch ('\0'); } while (--cnt); - lptr = line; + + /* Reinitialize line parsing */ + InitLine (line); } @@ -539,8 +573,8 @@ static void doundef (void) { ident Ident; - skipblank (); - if (macname (Ident)) { + SkipBlank (); + if (MacName (Ident)) { UndefineMacro (Ident); } } @@ -574,11 +608,18 @@ static int doiff (int skip) Token sv2 = NextTok; /* Remove the #if from the line and add two semicolons as sentinels */ - skipblank (); + SkipBlank (); S = line; - while ((*S++ = *lptr++) != '\0') ; - strcpy (S-1, ";;"); - lptr = line; + while (CurC != '\0') { + *S++ = CurC; + NextChar (); + } + *S++ = ';'; + *S++ = ';'; + *S = '\0'; + + /* Start over parsing from line */ + InitLine (line); /* Switch into special preprocessing mode */ Preprocessing = 1; @@ -611,8 +652,8 @@ static int doifdef (int skip, int flag) { ident Ident; - skipblank (); - if (macname (Ident) == 0) { + SkipBlank (); + if (MacName (Ident) == 0) { return 0; } else { return setmflag (skip, flag, IsMacro(Ident)); @@ -624,60 +665,57 @@ static int doifdef (int skip, int flag) static void doinclude (void) /* Open an include file. */ { - unsigned Length; - char* End; - char* Name; char RTerm; unsigned DirSpec; /* Skip blanks */ - mptr = mline; - skipblank (); + SkipBlank (); /* Get the next char and check for a valid file name terminator. Setup * the include directory spec (SYS/USR) by looking at the terminator. */ - switch (cgch()) { + switch (CurC) { - case '\"': - RTerm = '\"'; - DirSpec = INC_USER; - break; + case '\"': + RTerm = '\"'; + DirSpec = INC_USER; + break; - case '<': - RTerm = '>'; - DirSpec = INC_SYS; - break; + case '<': + RTerm = '>'; + DirSpec = INC_SYS; + break; - default: - PPError (ERR_INCLUDE_LTERM_EXPECTED); - goto Done; + default: + PPError (ERR_INCLUDE_LTERM_EXPECTED); + goto Done; } + NextChar (); - /* Search for the right terminator */ - End = strchr (lptr, RTerm); - if (End == 0) { - /* No terminator found */ - PPError (ERR_INCLUDE_RTERM_EXPECTED); - goto Done; + /* Copy the filename into mline. Since mline has the same size as the + * input line, we don't need to check for an overflow here. + */ + mptr = mline; + while (CurC != '\0' && CurC != RTerm) { + *mptr++ = CurC; + NextChar (); } + *mptr = '\0'; - /* Create a temp copy of the filename */ - Length = End - lptr; - Name = xmalloc (Length + 1); - memcpy (Name, lptr, Length); - Name[Length] = '\0'; + /* Check if we got a terminator */ + if (CurC != RTerm) { + /* No terminator found */ + PPError (ERR_INCLUDE_RTERM_EXPECTED); + goto Done; + } /* Open the include file */ - OpenIncludeFile (Name, DirSpec); - - /* Delete the temp filename copy */ - xfree (Name); + OpenIncludeFile (mline, DirSpec); Done: - /* Clear the remaining line so the next input will come from the new - * file (if open) + /* Clear the remaining line so the next input will come from the new + * file (if open) */ ClearLine (); } @@ -687,8 +725,8 @@ Done: static void doerror (void) /* Print an error */ { - skipblank (); - if (*lptr == '\0') { + SkipBlank (); + if (CurC == '\0') { PPError (ERR_INVALID_USER_ERROR); } else { PPError (ERR_USER_ERROR, lptr); @@ -704,38 +742,38 @@ static void doerror (void) /* stuff used to bum the keyword dispatching stuff */ enum { - D_DEFINE, - D_ELSE, - D_ENDIF, - D_ERROR, - D_IF, - D_IFDEF, - D_IFNDEF, - D_INCLUDE, - D_LINE, - D_PRAGMA, - D_UNDEF, - D_ILLEGAL, + PP_DEFINE, + PP_ELSE, + PP_ENDIF, + PP_ERROR, + PP_IF, + PP_IFDEF, + PP_IFNDEF, + PP_INCLUDE, + PP_LINE, + PP_PRAGMA, + PP_UNDEF, + PP_ILLEGAL, }; static const struct tok_elt pre_toks[] = { - { "define", D_DEFINE }, - { "else", D_ELSE }, - { "endif", D_ENDIF }, - { "error", D_ERROR }, - { "if", D_IF }, - { "ifdef", D_IFDEF }, - { "ifndef", D_IFNDEF }, - { "include", D_INCLUDE }, - { "line", D_LINE }, - { "pragma", D_PRAGMA }, - { "undef", D_UNDEF }, - { 0, D_ILLEGAL } + { "define", PP_DEFINE }, + { "else", PP_ELSE }, + { "endif", PP_ENDIF }, + { "error", PP_ERROR }, + { "if", PP_IF }, + { "ifdef", PP_IFDEF }, + { "ifndef", PP_IFNDEF }, + { "include", PP_INCLUDE }, + { "line", PP_LINE }, + { "pragma", PP_PRAGMA }, + { "undef", PP_UNDEF }, + { 0, PP_ILLEGAL } }; -int searchtok (const char *sym, const struct tok_elt *toks) +static int searchtok (const char *sym, const struct tok_elt *toks) /* Search a token in a table */ { while (toks->toknam && strcmp (toks->toknam, sym)) @@ -745,123 +783,119 @@ int searchtok (const char *sym, const struct tok_elt *toks) -void preprocess (void) +void Preprocess (void) /* Preprocess a line */ { - int c; int Skip; - ident sname; - - /* Process compiler directives, skip empty lines */ - lptr = line; + ident Directive; /* Skip white space at the beginning of the line */ - skipblank (); + SkipBlank (); /* Check for stuff to skip */ Skip = 0; - while ((c = *lptr) == '\0' || c == '#' || Skip) { - - /* Check for preprocessor lines lines */ - if (c == '#') { - ++lptr; - skipblank (); - if (*lptr == '\0') { - /* ignore the empty preprocessor directive */ - continue; - } - if (!issym (sname)) { - PPError (ERR_CPP_DIRECTIVE_EXPECTED); - ClearLine (); - } else { - switch (searchtok (sname, pre_toks)) { - - case D_DEFINE: - if (!Skip) { - addmac (); - } - break; - - case D_ELSE: - if (s_ifdef[i_ifdef] & 2) { - if (s_ifdef[i_ifdef] & 4) { - Skip = !Skip; - } - s_ifdef[i_ifdef] ^= 2; - } else { - PPError (ERR_UNEXPECTED_CPP_ELSE); - } - break; - - case D_ENDIF: - if (i_ifdef >= 0) { - Skip = s_ifdef[i_ifdef--] & 1; - } else { - PPError (ERR_UNEXPECTED_CPP_ENDIF); - } - break; - - case D_ERROR: - if (!Skip) { - doerror (); - } - break; - - case D_IF: - Skip = doiff (Skip); - break; - - case D_IFDEF: - Skip = doifdef (Skip, 1); - break; - - case D_IFNDEF: - Skip = doifdef (Skip, 0); - break; - - case D_INCLUDE: - if (!Skip) { - doinclude (); - } - break; - - case D_LINE: - /* Not allowed in strict ANSI mode */ - if (ANSI) { - PPError (ERR_CPP_DIRECTIVE_EXPECTED); - ClearLine (); - } - break; - - case D_PRAGMA: - if (!Skip) { - /* Don't expand macros in this line */ - ExpandMacros = 0; - /* #pragma is handled on the scanner level */ - goto Done; - } - break; - - case D_UNDEF: - if (!Skip) { - doundef (); - } - break; - - default: - PPError (ERR_CPP_DIRECTIVE_EXPECTED); - ClearLine (); - } + while (CurC == '\0' || CurC == '#' || Skip) { + + /* Check for preprocessor lines lines */ + if (CurC == '#') { + NextChar (); + SkipBlank (); + if (CurC == '\0') { + /* Ignore the empty preprocessor directive */ + continue; + } + if (!IsSym (Directive)) { + PPError (ERR_CPP_DIRECTIVE_EXPECTED); + ClearLine (); + } else { + switch (searchtok (Directive, pre_toks)) { + + case PP_DEFINE: + if (!Skip) { + addmac (); + } + break; + + case PP_ELSE: + if (s_ifdef[i_ifdef] & 2) { + if (s_ifdef[i_ifdef] & 4) { + Skip = !Skip; + } + s_ifdef[i_ifdef] ^= 2; + } else { + PPError (ERR_UNEXPECTED_CPP_ELSE); + } + break; + + case PP_ENDIF: + if (i_ifdef >= 0) { + Skip = s_ifdef[i_ifdef--] & 1; + } else { + PPError (ERR_UNEXPECTED_CPP_ENDIF); + } + break; + + case PP_ERROR: + if (!Skip) { + doerror (); + } + break; + + case PP_IF: + Skip = doiff (Skip); + break; + + case PP_IFDEF: + Skip = doifdef (Skip, 1); + break; + + case PP_IFNDEF: + Skip = doifdef (Skip, 0); + break; + + case PP_INCLUDE: + if (!Skip) { + doinclude (); + } + break; + + case PP_LINE: + /* Not allowed in strict ANSI mode */ + if (ANSI) { + PPError (ERR_CPP_DIRECTIVE_EXPECTED); + ClearLine (); + } + break; + + case PP_PRAGMA: + if (!Skip) { + /* Don't expand macros in this line */ + ExpandMacros = 0; + /* #pragma is handled on the scanner level */ + goto Done; + } + break; + + case PP_UNDEF: + if (!Skip) { + doundef (); + } + break; + + default: + PPError (ERR_CPP_DIRECTIVE_EXPECTED); + ClearLine (); + } } } if (NextLine () == 0) { if (i_ifdef >= 0) { - PPError (ERR_CPP_ENDIF_EXPECTED); + PPError (ERR_CPP_ENDIF_EXPECTED); } return; } - skipblank (); + SkipBlank (); } Done: diff --git a/src/cc65/preproc.h b/src/cc65/preproc.h index 194d11c35..708c86065 100644 --- a/src/cc65/preproc.h +++ b/src/cc65/preproc.h @@ -34,10 +34,7 @@ extern unsigned char Preprocessing; -int searchtok (const char *sym, const struct tok_elt* toks); -/* Search a token in a table */ - -void preprocess (void); +void Preprocess (void); /* Preprocess a line */ diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index ce0aa1788..445d11405 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -43,7 +43,7 @@ Token NextTok; /* The next token */ #define TT_EXT 1 /* cc65 extension */ /* Token table */ -static struct Keyword { +static const struct Keyword { char* Key; /* Keyword name */ unsigned char Tok; /* The token */ unsigned char Type; /* Token type */ @@ -114,7 +114,7 @@ static int CmpKey (const void* Key, const void* Elem) -static int FindKey (char* Key) +static int FindKey (const char* Key) /* Find a keyword and return the token. Return IDENT if the token is not a * keyword. */ @@ -129,21 +129,21 @@ static int FindKey (char* Key) } - -static int skipwhite (void) + +static int SkipWhite (void) /* Skip white space in the input stream, reading and preprocessing new lines * if necessary. Return 0 if end of file is reached, return 1 otherwise. */ { while (1) { - while (*lptr == 0) { + while (CurC == 0) { if (NextLine () == 0) { return 0; } - preprocess (); + Preprocess (); } - if (*lptr == ' ' || *lptr == '\r') { - ++lptr; + if (CurC == ' ' || CurC == '\r') { + NextChar (); } else { return 1; } @@ -152,27 +152,27 @@ static int skipwhite (void) -void symname (char *s) +void SymName (char* s) /* Get symbol from input stream */ { unsigned k = 0; do { - if (k != MAX_IDENTLEN) { - ++k; - *s++ = *lptr; + if (k != MAX_IDENTLEN) { + ++k; + *s++ = CurC; } - ++lptr; - } while (IsIdent (*lptr) || isdigit (*lptr)); + NextChar (); + } while (IsIdent (CurC) || isdigit (CurC)); *s = '\0'; } -int issym (char *s) +int IsSym (char *s) /* Get symbol from input stream or return 0 if not a symbol. */ { - if (IsIdent (*lptr)) { - symname (s); + if (IsIdent (CurC)) { + SymName (s); return 1; } else { return 0; @@ -181,11 +181,11 @@ int issym (char *s) -static void unknown (unsigned char c) +static void unknown (char C) /* Error message for unknown character */ { - Error (ERR_INVALID_CHAR, c); - gch (); /* Skip */ + Error (ERR_INVALID_CHAR, C); + NextChar (); /* Skip */ } @@ -209,7 +209,7 @@ static void SetTok (int tok) /* set nxttok and bump line ptr */ { nxttok = tok; - ++lptr; + NextChar (); } @@ -226,63 +226,73 @@ static int SignExtendChar (int C) -static int parsechar (int c) +static int ParseChar (void) /* Parse a character. Converts \n into EOL, etc. */ { int i; - int val; + unsigned val; + int C; /* Check for escape chars */ - if (c == '\\') { - switch (c = gch ()) { + if (CurC == '\\') { + NextChar (); + switch (CurC) { case 'b': - c = '\b'; + C = '\b'; break; - case 'f': - c = '\f'; + case 'f': + C = '\f'; break; case 'r': - c = '\r'; + C = '\r'; break; case 'n': - c = '\n'; + C = '\n'; break; case 't': - c = '\t'; + C = '\t'; break; case '\"': - c = '\"'; + C = '\"'; break; case '\'': - c = '\''; + C = '\''; break; case '\\': - c = '\\'; + C = '\\'; break; case 'x': case 'X': /* Hex character constant */ - val = hexval (gch ()) << 4; - c = val | hexval (gch ()); /* Do not translate */ + NextChar (); + val = hexval (CurC) << 4; + NextChar (); + C = val | hexval (CurC); /* Do not translate */ break; case '0': case '1': /* Octal constant */ i = 0; - val = c - '0'; - while ((c = *lptr) >= '0' && c <= '7' && i++ < 4) { - val = (val << 3) | (c - '0'); - gch (); - } - c = val; /* Do not translate */ + C = CurC - '0'; + while (NextC >= '0' && NextC <= '7' && i++ < 4) { + NextChar (); + C = (C << 3) | (CurC - '0'); + } + break; + default: + Error (ERR_ILLEGAL_CHARCONST); + C = ' '; break; - default: - Error (ERR_ILLEGAL_CHARCONST); - } + } + } else { + C = CurC; } + /* Skip the character read */ + NextChar (); + /* Do correct sign extension */ - return SignExtendChar (c); + return SignExtendChar (C); } @@ -290,22 +300,25 @@ static int parsechar (int c) static void CharConst (void) /* Parse a character constant. */ { - int c; + int C; /* Skip the quote */ - ++lptr; + NextChar (); /* Get character */ - c = parsechar (cgch ()); + C = ParseChar (); /* Check for closing quote */ - if (cgch () != '\'') { + if (CurC != '\'') { Error (ERR_QUOTE_EXPECTED); + } else { + /* Skip the quote */ + NextChar (); } /* Setup values and attributes */ nxttok = TOK_CCONST; - nxtval = SignExtendChar (ctrans (c)); /* Translate into target charset */ + nxtval = SignExtendChar (ctrans (C)); /* Translate into target charset */ nxttype = type_int; /* Character constants have type int */ } @@ -318,24 +331,24 @@ static void StringConst (void) nxttok = TOK_SCONST; /* Be sure to concatenate strings */ - while (*lptr == '\"') { + while (CurC == '\"') { /* Skip the quote char */ - ++lptr; + NextChar (); - while (*lptr != '\"') { - if (*lptr == 0) { + while (CurC != '\"') { + if (CurC == '\0') { Error (ERR_UNEXPECTED_NEWLINE); break; } - AddLiteralChar (parsechar (gch())); + AddLiteralChar (ParseChar ()); } /* Skip closing quote char if there was one */ - cgch (); + NextChar (); /* Skip white space, read new input */ - skipwhite (); + SkipWhite (); } @@ -348,7 +361,6 @@ static void StringConst (void) void NextToken (void) /* Get next token from input stream */ { - char c; ident token; /* Current token is the lookahead token */ @@ -358,15 +370,14 @@ void NextToken (void) NextTok.Pos = GetCurrentLine(); /* Skip spaces and read the next line if needed */ - if (skipwhite () == 0) { + if (SkipWhite () == 0) { /* End of file reached */ nxttok = TOK_CEOF; return; } /* Determine the next token from the lookahead */ - c = *lptr; - if (isdigit (c)) { + if (isdigit (CurC)) { /* A number */ int HaveSuffix; /* True if we have a type suffix */ @@ -378,49 +389,48 @@ void NextToken (void) base = 10; types = IT_INT | IT_LONG | IT_ULONG; - if (c == '0') { + if (CurC == '0') { /* Octal or hex constants may also be of type unsigned int */ types = IT_INT | IT_UINT | IT_LONG | IT_ULONG; /* gobble 0 and examin next char */ - if (toupper (*++lptr) == 'X') { + NextChar (); + if (toupper (CurC) == 'X') { base = 16; nxttype = type_uint; - ++lptr; /* gobble "x" */ + NextChar (); /* gobble "x" */ } else { base = 8; } } while (1) { - c = *lptr; - if (isdigit (c)) { - k = k * base + (c - '0'); - } else if (base == 16 && isxdigit (c)) { - k = (k << 4) + hexval (c); + if (isdigit (CurC)) { + k = k * base + (CurC - '0'); + } else if (base == 16 && isxdigit (CurC)) { + k = (k << 4) + hexval (CurC); } else { break; /* not digit */ } - ++lptr; /* gobble char */ + NextChar (); /* gobble char */ } /* Check for a suffix */ HaveSuffix = 1; - c = toupper (*lptr); - if (c == 'U') { + if (CurC == 'u' || CurC == 'U') { /* Unsigned type */ - ++lptr; - if (toupper (*lptr) != 'L') { + NextChar (); + if (toupper (CurC) != 'L') { types = IT_UINT | IT_ULONG; } else { - ++lptr; + NextChar (); types = IT_ULONG; } - } else if (c == 'L') { + } else if (CurC == 'l' || CurC == 'L') { /* Long type */ - ++lptr; - if (toupper (*lptr) != 'U') { + NextChar (); + if (toupper (CurC) != 'U') { types = IT_LONG | IT_ULONG; } else { - ++lptr; + NextChar (); types = IT_ULONG; } } else { @@ -465,7 +475,7 @@ void NextToken (void) return; } - if (issym (token)) { + if (IsSym (token)) { /* Check for a keyword */ if ((nxttok = FindKey (token)) != TOK_IDENT) { @@ -506,10 +516,11 @@ void NextToken (void) } /* Monstrous switch statement ahead... */ - switch (c) { + switch (CurC) { case '!': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_NE); } else { nxttok = TOK_BOOL_NOT; @@ -521,7 +532,8 @@ void NextToken (void) break; case '%': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_MOD_ASSIGN); } else { nxttok = TOK_MOD; @@ -529,7 +541,8 @@ void NextToken (void) break; case '&': - switch (*++lptr) { + NextChar (); + switch (CurC) { case '&': SetTok (TOK_BOOL_AND); break; @@ -554,7 +567,8 @@ void NextToken (void) break; case '*': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_MUL_ASSIGN); } else { nxttok = TOK_STAR; @@ -562,7 +576,8 @@ void NextToken (void) break; case '+': - switch (*++lptr) { + NextChar (); + switch (CurC) { case '+': SetTok (TOK_INC); break; @@ -579,7 +594,8 @@ void NextToken (void) break; case '-': - switch (*++lptr) { + NextChar (); + switch (CurC) { case '-': SetTok (TOK_DEC); break; @@ -595,11 +611,13 @@ void NextToken (void) break; case '.': - if (*++lptr == '.') { - if (*++lptr == '.') { + NextChar (); + if (CurC == '.') { + NextChar (); + if (CurC == '.') { SetTok (TOK_ELLIPSIS); } else { - unknown (*lptr); + unknown (CurC); } } else { nxttok = TOK_DOT; @@ -607,7 +625,8 @@ void NextToken (void) break; case '/': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_DIV_ASSIGN); } else { nxttok = TOK_DIV; @@ -623,12 +642,14 @@ void NextToken (void) break; case '<': - switch (*++lptr) { + NextChar (); + switch (CurC) { case '=': SetTok (TOK_LE); break; case '<': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_SHL_ASSIGN); } else { nxttok = TOK_SHL; @@ -640,7 +661,8 @@ void NextToken (void) break; case '=': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_EQ); } else { nxttok = TOK_ASSIGN; @@ -648,12 +670,14 @@ void NextToken (void) break; case '>': - switch (*++lptr) { + NextChar (); + switch (CurC) { case '=': SetTok (TOK_GE); break; case '>': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_SHR_ASSIGN); } else { nxttok = TOK_SHR; @@ -677,7 +701,8 @@ void NextToken (void) break; case '^': - if (*++lptr == '=') { + NextChar (); + if (CurC == '=') { SetTok (TOK_XOR_ASSIGN); } else { nxttok = TOK_XOR; @@ -689,7 +714,8 @@ void NextToken (void) break; case '|': - switch (*++lptr) { + NextChar (); + switch (CurC) { case '|': SetTok (TOK_BOOL_OR); break; @@ -710,8 +736,11 @@ void NextToken (void) break; case '#': - while (*++lptr == ' ') ; /* Skip it and following whitespace */ - if (!issym (token) || strcmp (token, "pragma") != 0) { + /* Skip it and following whitespace */ + do { + NextChar (); + } while (CurC == ' '); + if (!IsSym (token) || strcmp (token, "pragma") != 0) { /* OOPS - should not happen */ Error (ERR_CPP_DIRECTIVE_EXPECTED); } @@ -719,7 +748,7 @@ void NextToken (void) break; default: - unknown (c); + unknown (CurC); } diff --git a/src/cc65/scanner.h b/src/cc65/scanner.h index 5653d953a..bbbed9ee6 100644 --- a/src/cc65/scanner.h +++ b/src/cc65/scanner.h @@ -172,13 +172,13 @@ extern Token NextTok; /* The next token */ -void symname (char* s); +void SymName (char* s); /* Get symbol from input stream */ -int issym (char* s); +int IsSym (char* s); /* Get symbol from input stream or return 0 if not a symbol. */ -void NextToken (void); +void NextToken (void); /* Get next token from input stream */ void Consume (token_t Token, unsigned ErrNum); -- 2.39.5