/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* 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 */
/*****************************************************************************/
IF->Active = Input;
Input = IF;
++IFileCount;
+ ++IFileTotal;
/* Return the new struct */
return IF;
}
/* Setup a new IFile structure */
- NewIFile (Name, F);
+ MainFile = NewIFile (Name, F);
}
/* 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';
+ }
}
}
}
- /* 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;
}
/* 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;
}
-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);
-}
-
-
-
-static int Pass1 (char* from, char* to);
+static int Pass1 (const char* From, char* To);
+/* Preprocessor pass 1. Remove whitespace and comments. */
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];
-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 */
-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;
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 */
/* 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 ('\"');
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);
}
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.
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 ();
}
}
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;
}
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 */
/* Remove whitespace and comments from the line, store the preprocessed
* line into Buf.
*/
- skipblank ();
+ SkipBlank ();
saveptr = mptr;
Pass1 (lptr, Buf);
mptr = saveptr;
-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
* 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');
-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;
{
int cnt;
int Done;
- char *p;
Done = Pass1 (line, mline);
if (ExpandMacros == 0) {
}
cnt = 5;
do {
- p = line;
+ /* Swap mline and line */
+ char* p = line;
line = mline;
mline = p;
if (Done)
Done = Pass2 (line, mline);
keepch ('\0');
} while (--cnt);
- lptr = line;
+
+ /* Reinitialize line parsing */
+ InitLine (line);
}
{
ident Ident;
- skipblank ();
- if (macname (Ident)) {
+ SkipBlank ();
+ if (MacName (Ident)) {
UndefineMacro (Ident);
}
}
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;
{
ident Ident;
- skipblank ();
- if (macname (Ident) == 0) {
+ SkipBlank ();
+ if (MacName (Ident) == 0) {
return 0;
} else {
return setmflag (skip, flag, IsMacro(Ident));
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 ();
}
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);
/* 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))
-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:
#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 */
-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.
*/
}
-
-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;
}
-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;
-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 */
}
/* set nxttok and bump line ptr */
{
nxttok = tok;
- ++lptr;
+ NextChar ();
}
-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);
}
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 */
}
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 ();
}
void NextToken (void)
/* Get next token from input stream */
{
- char c;
ident token;
/* Current token is the lookahead token */
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 */
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 {
return;
}
- if (issym (token)) {
+ if (IsSym (token)) {
/* Check for a keyword */
if ((nxttok = FindKey (token)) != TOK_IDENT) {
}
/* Monstrous switch statement ahead... */
- switch (c) {
+ switch (CurC) {
case '!':
- if (*++lptr == '=') {
+ NextChar ();
+ if (CurC == '=') {
SetTok (TOK_NE);
} else {
nxttok = TOK_BOOL_NOT;
break;
case '%':
- if (*++lptr == '=') {
+ NextChar ();
+ if (CurC == '=') {
SetTok (TOK_MOD_ASSIGN);
} else {
nxttok = TOK_MOD;
break;
case '&':
- switch (*++lptr) {
+ NextChar ();
+ switch (CurC) {
case '&':
SetTok (TOK_BOOL_AND);
break;
break;
case '*':
- if (*++lptr == '=') {
+ NextChar ();
+ if (CurC == '=') {
SetTok (TOK_MUL_ASSIGN);
} else {
nxttok = TOK_STAR;
break;
case '+':
- switch (*++lptr) {
+ NextChar ();
+ switch (CurC) {
case '+':
SetTok (TOK_INC);
break;
break;
case '-':
- switch (*++lptr) {
+ NextChar ();
+ switch (CurC) {
case '-':
SetTok (TOK_DEC);
break;
break;
case '.':
- if (*++lptr == '.') {
- if (*++lptr == '.') {
+ NextChar ();
+ if (CurC == '.') {
+ NextChar ();
+ if (CurC == '.') {
SetTok (TOK_ELLIPSIS);
} else {
- unknown (*lptr);
+ unknown (CurC);
}
} else {
nxttok = TOK_DOT;
break;
case '/':
- if (*++lptr == '=') {
+ NextChar ();
+ if (CurC == '=') {
SetTok (TOK_DIV_ASSIGN);
} else {
nxttok = TOK_DIV;
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;
break;
case '=':
- if (*++lptr == '=') {
+ NextChar ();
+ if (CurC == '=') {
SetTok (TOK_EQ);
} else {
nxttok = TOK_ASSIGN;
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;
break;
case '^':
- if (*++lptr == '=') {
+ NextChar ();
+ if (CurC == '=') {
SetTok (TOK_XOR_ASSIGN);
} else {
nxttok = TOK_XOR;
break;
case '|':
- switch (*++lptr) {
+ NextChar ();
+ switch (CurC) {
case '|':
SetTok (TOK_BOOL_OR);
break;
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);
}
break;
default:
- unknown (c);
+ unknown (CurC);
}