/* */
/* */
/* */
-/* (C) 1998-2005, Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/*****************************************************************************/
-/* Forwards */
+/* Forwards */
/*****************************************************************************/
/*****************************************************************************/
-/* Low level preprocessor token handling */
+/* Low level preprocessor token handling */
/*****************************************************************************/
PP_INCLUDE,
PP_LINE,
PP_PRAGMA,
- PP_UNDEF
+ PP_UNDEF,
+ PP_WARNING,
} pptoken_t;
/* Preprocessor keyword to token mapping table */
static const struct PPToken {
- const char* Key; /* Keyword */
- pptoken_t Tok; /* Token */
+ const char* Key; /* Keyword */
+ pptoken_t Tok; /* Token */
} PPTokens[] = {
- { "define", PP_DEFINE },
+ { "define", PP_DEFINE },
{ "elif", PP_ELIF },
- { "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 },
+ { "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 },
+ { "warning", PP_WARNING },
};
/* Number of preprocessor tokens */
-#define PPTOKEN_COUNT (sizeof(PPTokens) / sizeof(PPTokens[0]))
+#define PPTOKEN_COUNT (sizeof(PPTokens) / sizeof(PPTokens[0]))
/* Initialize a MacroExp structure */
{
InitCollection (&E->ActualArgs);
- InitStrBuf (&E->Replacement);
+ SB_Init (&E->Replacement);
E->M = M;
return E;
}
FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I));
}
DoneCollection (&E->ActualArgs);
- DoneStrBuf (&E->Replacement);
+ SB_Done (&E->Replacement);
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
/* Skip the comment */
while (CurC != '*' || NextC != '/') {
- if (CurC == '\0') {
- if (NextLine () == 0) {
- PPError ("End-of-file reached in comment starting at line %u",
- StartingLine);
- return;
- }
- } else {
- if (CurC == '/' && NextC == '*') {
- PPWarning ("`/*' found inside a comment");
- }
- NextChar ();
- }
+ if (CurC == '\0') {
+ if (NextLine () == 0) {
+ PPError ("End-of-file reached in comment starting at line %u",
+ StartingLine);
+ return;
+ }
+ } else {
+ if (CurC == '/' && NextC == '*') {
+ PPWarning ("`/*' found inside a comment");
+ }
+ NextChar ();
+ }
}
/* Skip the end of comment chars */
* source line is denoted by a lf (\n) character.
*/
do {
- NextChar ();
+ NextChar ();
} while (CurC != '\n' && CurC != '\0');
if (CurC == '\n') {
- NextChar ();
+ NextChar ();
}
}
-static void SkipWhitespace (void)
-/* Skip white space in the input stream. */
+static int SkipWhitespace (int SkipLines)
+/* Skip white space in the input stream. Do also skip newlines if SkipLines
+ * is true. Return zero if nothing was skipped, otherwise return a
+ * value != zero.
+ */
{
- while (IsSpace (CurC)) {
- NextChar ();
+ int Skipped = 0;
+ while (1) {
+ if (IsSpace (CurC)) {
+ NextChar ();
+ Skipped = 1;
+ } else if (CurC == '\0' && SkipLines) {
+ /* End of line, read next */
+ if (NextLine () != 0) {
+ Skipped = 1;
+ } else {
+ /* End of input */
+ break;
+ }
+ } else {
+ /* No more white space */
+ break;
+ }
}
+ return Skipped;
}
/* Copy the characters inside the string */
while (CurC != '\0' && CurC != Quote) {
- /* Keep an escaped char */
- if (CurC == '\\') {
- SB_AppendChar (Target, CurC);
- NextChar ();
- }
- /* Copy the character */
- SB_AppendChar (Target, CurC);
- NextChar ();
+ /* Keep an escaped char */
+ if (CurC == '\\') {
+ SB_AppendChar (Target, CurC);
+ NextChar ();
+ }
+ /* Copy the character */
+ SB_AppendChar (Target, CurC);
+ NextChar ();
}
/* If we had a terminating quote, copy it */
if (CurC != '\0') {
- SB_AppendChar (Target, CurC);
- NextChar ();
+ SB_AppendChar (Target, CurC);
+ NextChar ();
}
}
/*****************************************************************************/
-/* Macro stuff */
+/* Macro stuff */
/*****************************************************************************/
*/
{
if (IsSym (Ident) == 0) {
- PPError ("Identifier expected");
- ClearLine ();
- return 0;
+ PPError ("Identifier expected");
+ ClearLine ();
+ return 0;
} else {
- return 1;
+ return 1;
}
}
static void ReadMacroArgs (MacroExp* E)
/* Identify the arguments to a macro call */
{
- unsigned Parens; /* Number of open parenthesis */
+ unsigned Parens; /* Number of open parenthesis */
StrBuf Arg = STATIC_STRBUF_INITIALIZER;
/* Read the actual macro arguments */
Parens = 0;
while (1) {
- if (CurC == '(') {
+ if (CurC == '(') {
- /* Nested parenthesis */
- SB_AppendChar (&Arg, CurC);
- NextChar ();
- ++Parens;
+ /* Nested parenthesis */
+ SB_AppendChar (&Arg, CurC);
+ NextChar ();
+ ++Parens;
- } else if (IsQuote (CurC)) {
+ } else if (IsQuote (CurC)) {
/* Quoted string - just copy */
- CopyQuotedString (&Arg);
+ CopyQuotedString (&Arg);
- } else if (CurC == ',' || CurC == ')') {
+ } else if (CurC == ',' || CurC == ')') {
- if (Parens) {
- /* Comma or right paren inside nested parenthesis */
- if (CurC == ')') {
- --Parens;
- }
- SB_AppendChar (&Arg, CurC);
- NextChar ();
+ if (Parens) {
+ /* Comma or right paren inside nested parenthesis */
+ if (CurC == ')') {
+ --Parens;
+ }
+ SB_AppendChar (&Arg, CurC);
+ NextChar ();
} else if (CurC == ',' && ME_ArgIsVariadic (E)) {
/* It's a comma, but we're inside a variadic macro argument, so
* just copy it and proceed.
*/
SB_AppendChar (&Arg, CurC);
NextChar ();
- } else {
- /* End of actual argument. Remove whitespace from the end. */
+ } else {
+ /* End of actual argument. Remove whitespace from the end. */
while (IsSpace (SB_LookAtLast (&Arg))) {
SB_Drop (&Arg, 1);
}
*/
if (CurC != ')' || SB_NotEmpty (&Arg) || E->M->ArgCount > 0) {
ME_AppendActual (E, &Arg);
- }
+ }
- /* Check for end of macro param list */
- if (CurC == ')') {
- NextChar ();
- break;
- }
+ /* Check for end of macro param list */
+ if (CurC == ')') {
+ NextChar ();
+ break;
+ }
- /* Start the next param */
- NextChar ();
+ /* Start the next param */
+ NextChar ();
SB_Clear (&Arg);
- }
- } else if (IsSpace (CurC)) {
- /* Squeeze runs of blanks within an arg */
- if (SB_NotEmpty (&Arg)) {
- SB_AppendChar (&Arg, ' ');
}
- SkipWhitespace ();
- } else if (CurC == '/' && NextC == '*') {
+ } else if (SkipWhitespace (1)) {
+ /* Squeeze runs of blanks within an arg */
if (SB_NotEmpty (&Arg)) {
SB_AppendChar (&Arg, ' ');
}
- OldStyleComment ();
- } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
+ } else if (CurC == '/' && NextC == '*') {
if (SB_NotEmpty (&Arg)) {
SB_AppendChar (&Arg, ' ');
}
- NewStyleComment ();
- } else if (CurC == '\0') {
- /* End of line inside macro argument list - read next line */
+ OldStyleComment ();
+ } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
if (SB_NotEmpty (&Arg)) {
SB_AppendChar (&Arg, ' ');
}
- if (NextLine () == 0) {
- ClearLine ();
- break;
- }
- } else {
- /* Just copy the character */
- SB_AppendChar (&Arg, CurC);
- NextChar ();
- }
+ NewStyleComment ();
+ } else if (CurC == '\0') {
+ /* End of input inside macro argument list */
+ PPError ("Unterminated argument list invoking macro `%s'", E->M->Name);
+
+ ClearLine ();
+ break;
+ } else {
+ /* Just copy the character */
+ SB_AppendChar (&Arg, CurC);
+ NextChar ();
+ }
}
/* Deallocate string buf resources */
- DoneStrBuf (&Arg);
+ SB_Done (&Arg);
}
static void MacroArgSubst (MacroExp* E)
/* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */
{
- ident Ident;
+ ident Ident;
int ArgIdx;
StrBuf* OldSource;
StrBuf* Arg;
/* Remember the current input and switch to the macro replacement. */
+ int OldIndex = SB_GetIndex (&E->M->Replacement);
SB_Reset (&E->M->Replacement);
OldSource = InitLine (&E->M->Replacement);
/* Argument handling loop */
while (CurC != '\0') {
- /* If we have an identifier, check if it's a macro */
- if (IsSym (Ident)) {
+ /* If we have an identifier, check if it's a macro */
+ if (IsSym (Ident)) {
/* Check if it's a macro argument */
if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) {
Arg = ME_GetActual (E, ArgIdx);
/* Copy any following whitespace */
- HaveSpace = IsSpace (CurC);
- if (HaveSpace) {
- SkipWhitespace ();
- }
+ HaveSpace = SkipWhitespace (0);
/* If a ## operator follows, we have to insert the actual
* argument as is, otherwise it must be macro replaced.
} else {
/* An identifier, keep it */
- SB_AppendStr (&E->Replacement, Ident);
+ SB_AppendStr (&E->Replacement, Ident);
- }
+ }
} else if (CurC == '#' && NextC == '#') {
/* ## operator. */
NextChar ();
NextChar ();
- SkipWhitespace ();
+ SkipWhitespace (0);
/* Since we need to concatenate the token sequences, remove
* any whitespace that was added to target, since it must come
* macro parameter.
*/
NextChar ();
- SkipWhitespace ();
+ SkipWhitespace (0);
if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) {
PPError ("`#' is not followed by a macro parameter");
} else {
Stringize (Arg, &E->Replacement);
}
- } else if (IsQuote (CurC)) {
- CopyQuotedString (&E->Replacement);
- } else {
- SB_AppendChar (&E->Replacement, CurC);
- NextChar ();
- }
+ } else if (IsQuote (CurC)) {
+ CopyQuotedString (&E->Replacement);
+ } else {
+ SB_AppendChar (&E->Replacement, CurC);
+ NextChar ();
+ }
}
#if 0
/* Switch back the input */
InitLine (OldSource);
+ SB_SetIndex (&E->M->Replacement, OldIndex);
}
StrBuf Arg = STATIC_STRBUF_INITIALIZER;
/* Argument count mismatch */
- PPError ("Macro argument count mismatch");
+ PPError ("Macro argument count mismatch");
- /* Be sure to make enough empty arguments available */
- while (CollCount (&E.ActualArgs) < (unsigned) M->ArgCount) {
+ /* Be sure to make enough empty arguments available */
+ while (CollCount (&E.ActualArgs) < (unsigned) M->ArgCount) {
ME_AppendActual (&E, &Arg);
- }
+ }
}
/* Replace macro arguments handling the # and ## operators */
static void ExpandMacro (StrBuf* Target, Macro* M)
/* Expand a macro into Target */
{
- /* ### printf ("Expanding %s(%u)\n", M->Name, ++V); */
+#if 0
+ static unsigned V = 0;
+ printf ("Expanding %s(%u)\n", M->Name, ++V);
+#endif
/* Check if this is a function like macro */
if (M->ArgCount >= 0) {
- int Whitespace = IsSpace (CurC);
- if (Whitespace) {
- SkipWhitespace ();
- }
+ int Whitespace = SkipWhitespace (1);
if (CurC != '(') {
/* Function like macro but no parameter list */
SB_AppendStr (Target, M->Name);
DoneMacroExp (&E);
}
- /* ### printf ("Done with %s(%u)\n", M->Name, V--); */
+#if 0
+ printf ("Done with %s(%u)\n", M->Name, V--);
+#endif
}
static void DefineMacro (void)
/* Handle a macro definition. */
{
- ident Ident;
- Macro* M;
- Macro* Existing;
+ ident Ident;
+ Macro* M;
+ Macro* Existing;
int C89;
/* Read the macro name */
- SkipWhitespace ();
+ SkipWhitespace (0);
if (!MacName (Ident)) {
- return;
+ return;
}
/* Remember if we're in C89 mode */
/* Check if this is a function like macro */
if (CurC == '(') {
- /* Skip the left paren */
- NextChar ();
+ /* Skip the left paren */
+ NextChar ();
- /* Set the marker that this is a function like macro */
- M->ArgCount = 0;
+ /* Set the marker that this is a function like macro */
+ M->ArgCount = 0;
- /* Read the formal parameter list */
- while (1) {
+ /* Read the formal parameter list */
+ while (1) {
/* Skip white space and check for end of parameter list */
- SkipWhitespace ();
- if (CurC == ')') {
- break;
+ SkipWhitespace (0);
+ if (CurC == ')') {
+ break;
}
/* The next token must be either an identifier, or - if not in
}
/* Add the macro argument */
- AddMacroArg (M, Ident);
+ AddMacroArg (M, Ident);
}
/* If we had an ellipsis, or the next char is not a comma, we've
* reached the end of the macro argument list.
*/
- SkipWhitespace ();
- if (M->Variadic || CurC != ',') {
- break;
+ SkipWhitespace (0);
+ if (M->Variadic || CurC != ',') {
+ break;
}
- NextChar ();
- }
-
- /* Check for a right paren and eat it if we find one */
- if (CurC != ')') {
- PPError ("`)' expected");
- ClearLine ();
- return;
- }
- NextChar ();
+ NextChar ();
+ }
+
+ /* Check for a right paren and eat it if we find one */
+ if (CurC != ')') {
+ PPError ("`)' expected");
+ ClearLine ();
+ return;
+ }
+ NextChar ();
}
/* Skip whitespace before the macro replacement */
- SkipWhitespace ();
+ SkipWhitespace (0);
/* Insert the macro into the macro table and allocate the ActualArgs array */
InsertMacro (M);
while (IsSpace (SB_LookAtLast (&M->Replacement))) {
SB_Drop (&M->Replacement, 1);
}
-
- /* ### printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement)); */
+#if 0
+ printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement));
+#endif
/* If we have an existing macro, check if the redefinition is identical.
* Print a diagnostic if not.
/*****************************************************************************/
-/* Preprocessing */
+/* Preprocessing */
/*****************************************************************************/
*/
{
unsigned IdentCount;
- ident Ident;
- int HaveParen;
+ ident Ident;
+ int HaveParen;
/* Switch to the new input source */
StrBuf* OldSource = InitLine (Source);
/* Loop removing ws and comments */
IdentCount = 0;
while (CurC != '\0') {
- if (IsSpace (CurC)) {
+ if (SkipWhitespace (0)) {
/* Squeeze runs of blanks */
if (!IsSpace (SB_LookAtLast (Target))) {
SB_AppendChar (Target, ' ');
}
- SkipWhitespace ();
- } else if (IsSym (Ident)) {
- if (Preprocessing && strcmp (Ident, "defined") == 0) {
- /* Handle the "defined" operator */
- SkipWhitespace ();
- HaveParen = 0;
- if (CurC == '(') {
- HaveParen = 1;
- NextChar ();
- SkipWhitespace ();
- }
- if (IsSym (Ident)) {
- SB_AppendChar (Target, IsMacro (Ident)? '1' : '0');
- if (HaveParen) {
- SkipWhitespace ();
- if (CurC != ')') {
- PPError ("`)' expected");
- } else {
- NextChar ();
- }
- }
- } else {
- PPError ("Identifier expected");
- SB_AppendChar (Target, '0');
- }
- } else {
- ++IdentCount;
- SB_AppendStr (Target, Ident);
- }
- } else if (IsQuote (CurC)) {
- CopyQuotedString (Target);
- } else if (CurC == '/' && NextC == '*') {
+ } else if (IsSym (Ident)) {
+ if (Preprocessing && strcmp (Ident, "defined") == 0) {
+ /* Handle the "defined" operator */
+ SkipWhitespace (0);
+ HaveParen = 0;
+ if (CurC == '(') {
+ HaveParen = 1;
+ NextChar ();
+ SkipWhitespace (0);
+ }
+ if (IsSym (Ident)) {
+ SB_AppendChar (Target, IsMacro (Ident)? '1' : '0');
+ if (HaveParen) {
+ SkipWhitespace (0);
+ if (CurC != ')') {
+ PPError ("`)' expected");
+ } else {
+ NextChar ();
+ }
+ }
+ } else {
+ PPError ("Identifier expected");
+ SB_AppendChar (Target, '0');
+ }
+ } else {
+ ++IdentCount;
+ SB_AppendStr (Target, Ident);
+ }
+ } else if (IsQuote (CurC)) {
+ CopyQuotedString (Target);
+ } else if (CurC == '/' && NextC == '*') {
if (!IsSpace (SB_LookAtLast (Target))) {
SB_AppendChar (Target, ' ');
}
- OldStyleComment ();
- } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
+ OldStyleComment ();
+ } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
if (!IsSpace (SB_LookAtLast (Target))) {
SB_AppendChar (Target, ' ');
}
- NewStyleComment ();
- } else {
- SB_AppendChar (Target, CurC);
- NextChar ();
- }
+ NewStyleComment ();
+ } else {
+ SB_AppendChar (Target, CurC);
+ NextChar ();
+ }
}
/* Switch back to the old source */
static void MacroReplacement (StrBuf* Source, StrBuf* Target)
/* Perform macro replacement. */
{
- ident Ident;
- Macro* M;
+ ident Ident;
+ Macro* M;
/* Remember the current input and switch to Source */
StrBuf* OldSource = InitLine (Source);
/* Loop substituting macros */
while (CurC != '\0') {
- /* If we have an identifier, check if it's a macro */
- if (IsSym (Ident)) {
+ /* If we have an identifier, check if it's a macro */
+ if (IsSym (Ident)) {
/* Check if it's a macro */
if ((M = FindMacro (Ident)) != 0 && !M->Expanding) {
/* It's a macro, expand it */
ExpandMacro (Target, M);
} else {
/* An identifier, keep it */
- SB_AppendStr (Target, Ident);
- }
- } else if (IsQuote (CurC)) {
- CopyQuotedString (Target);
- } else if (IsSpace (CurC)) {
+ SB_AppendStr (Target, Ident);
+ }
+ } else if (IsQuote (CurC)) {
+ CopyQuotedString (Target);
+ } else if (IsSpace (CurC)) {
if (!IsSpace (SB_LookAtLast (Target))) {
SB_AppendChar (Target, CurC);
}
NextChar ();
} else {
- SB_AppendChar (Target, CurC);
- NextChar ();
- }
+ SB_AppendChar (Target, CurC);
+ NextChar ();
+ }
}
/* Switch back the input */
-static void DoUndef (void)
-/* Process the #undef directive */
-{
- ident Ident;
-
- SkipWhitespace ();
- if (MacName (Ident)) {
- UndefineMacro (Ident);
- }
-}
-
-
-
static int PushIf (int Skip, int Invert, int Cond)
/* Push a new if level onto the if stack */
{
/* Check for an overflow of the if stack */
if (IfIndex >= MAX_IFS-1) {
- PPError ("Too many nested #if clauses");
- return 1;
+ PPError ("Too many nested #if clauses");
+ return 1;
}
/* Push the #if condition */
++IfIndex;
if (Skip) {
- IfStack[IfIndex] = IFCOND_SKIP | IFCOND_NEEDTERM;
- return 1;
+ IfStack[IfIndex] = IFCOND_SKIP | IFCOND_NEEDTERM;
+ return 1;
+ } else {
+ IfStack[IfIndex] = IFCOND_NONE | IFCOND_NEEDTERM;
+ return (Invert ^ Cond);
+ }
+}
+
+
+
+static void DoError (void)
+/* Print an error */
+{
+ SkipWhitespace (0);
+ if (CurC == '\0') {
+ PPError ("Invalid #error directive");
} else {
- IfStack[IfIndex] = IFCOND_NONE | IFCOND_NEEDTERM;
- return (Invert ^ Cond);
+ PPError ("#error: %s", SB_GetConstBuf (Line) + SB_GetIndex (Line));
}
+
+ /* Clear the rest of line */
+ ClearLine ();
}
/* Make sure the line infos for the tokens won't get removed */
if (SavedCurTok.LI) {
- UseLineInfo (SavedCurTok.LI);
+ UseLineInfo (SavedCurTok.LI);
}
if (SavedNextTok.LI) {
- UseLineInfo (SavedNextTok.LI);
- }
-
-#if 0
- /* Remove the #if from the line */
- SkipWhitespace ();
- S = line;
- while (CurC != '\0') {
- *S++ = CurC;
- NextChar ();
+ UseLineInfo (SavedNextTok.LI);
}
- *S = '\0';
-
- /* Start over parsing from line */
- InitLine (line);
-#endif
/* Switch into special preprocessing mode */
Preprocessing = 1;
{
ident Ident;
- SkipWhitespace ();
+ SkipWhitespace (0);
if (MacName (Ident) == 0) {
- return 0;
+ return 0;
} else {
- return PushIf (skip, flag, IsMacro(Ident));
+ return PushIf (skip, flag, IsMacro(Ident));
}
}
static void DoInclude (void)
/* Open an include file. */
{
- char RTerm;
- unsigned DirSpec;
+ char RTerm;
+ InputType IT;
StrBuf Filename = STATIC_STRBUF_INITIALIZER;
+ /* Preprocess the remainder of the line */
+ PreprocessLine ();
+
/* Skip blanks */
- SkipWhitespace ();
+ SkipWhitespace (0);
/* 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 (CurC) {
- case '\"':
- RTerm = '\"';
- DirSpec = INC_USER;
- break;
+ case '\"':
+ RTerm = '\"';
+ IT = IT_USRINC;
+ break;
- case '<':
- RTerm = '>';
- DirSpec = INC_SYS;
- break;
+ case '<':
+ RTerm = '>';
+ IT = IT_SYSINC;
+ break;
- default:
- PPError ("`\"' or `<' expected");
- goto Done;
+ default:
+ PPError ("`\"' or `<' expected");
+ goto Done;
}
NextChar ();
/* Get a copy of the filename */
while (CurC != '\0' && CurC != RTerm) {
- SB_AppendChar (&Filename, CurC);
- NextChar ();
+ SB_AppendChar (&Filename, CurC);
+ NextChar ();
}
SB_Terminate (&Filename);
/* Check if we got a terminator */
- if (CurC != RTerm) {
- /* No terminator found */
- PPError ("Missing terminator or file name too long");
- goto Done;
+ if (CurC == RTerm) {
+ /* Open the include file */
+ OpenIncludeFile (SB_GetConstBuf (&Filename), IT);
+ } else if (CurC == '\0') {
+ /* No terminator found */
+ PPError ("#include expects \"FILENAME\" or <FILENAME>");
}
- /* Open the include file */
- OpenIncludeFile (SB_GetConstBuf (&Filename), DirSpec);
-
Done:
/* Free the allocated filename data */
- DoneStrBuf (&Filename);
+ SB_Done (&Filename);
/* Clear the remaining line so the next input will come from the new
* file (if open)
-static void DoError (void)
-/* Print an error */
-{
- SkipWhitespace ();
- if (CurC == '\0') {
- PPError ("Invalid #error directive");
- } else {
- PPError ("#error: %s", SB_GetConstBuf (Line) + SB_GetIndex (Line));
- }
-
- /* Clear the rest of line */
- ClearLine ();
-}
-
-
-
static void DoPragma (void)
/* Handle a #pragma line by converting the #pragma preprocessor directive into
* the _Pragma() compiler operator.
*/
{
/* Skip blanks following the #pragma directive */
- SkipWhitespace ();
+ SkipWhitespace (0);
/* Copy the remainder of the line into MLine removing comments and ws */
SB_Clear (MLine);
+static void DoUndef (void)
+/* Process the #undef directive */
+{
+ ident Ident;
+
+ SkipWhitespace (0);
+ if (MacName (Ident)) {
+ UndefineMacro (Ident);
+ }
+}
+
+
+
+static void DoWarning (void)
+/* Print a warning */
+{
+ SkipWhitespace (0);
+ if (CurC == '\0') {
+ PPError ("Invalid #warning directive");
+ } else {
+ PPWarning ("#warning: %s", SB_GetConstBuf (Line) + SB_GetIndex (Line));
+ }
+
+ /* Clear the rest of line */
+ ClearLine ();
+}
+
+
+
void Preprocess (void)
/* Preprocess a line */
{
- int Skip;
- ident Directive;
+ int Skip;
+ ident Directive;
/* Create the output buffer if we don't already have one */
if (MLine == 0) {
}
/* Skip white space at the beginning of the line */
- SkipWhitespace ();
+ SkipWhitespace (0);
/* Check for stuff to skip */
Skip = 0;
while (CurC == '\0' || CurC == '#' || Skip) {
- /* Check for preprocessor lines lines */
- if (CurC == '#') {
- NextChar ();
- SkipWhitespace ();
- if (CurC == '\0') {
- /* Ignore the empty preprocessor directive */
- continue;
- }
- if (!IsSym (Directive)) {
- PPError ("Preprocessor directive expected");
- ClearLine ();
- } else {
- switch (FindPPToken (Directive)) {
-
- case PP_DEFINE:
- if (!Skip) {
- DefineMacro ();
- }
- break;
-
- case PP_ELIF:
- if (IfIndex >= 0) {
- if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
-
- /* Handle as #else/#if combination */
- if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
- Skip = !Skip;
- }
- IfStack[IfIndex] |= IFCOND_ELSE;
- Skip = DoIf (Skip);
-
- /* #elif doesn't need a terminator */
- IfStack[IfIndex] &= ~IFCOND_NEEDTERM;
- } else {
- PPError ("Duplicate #else/#elif");
- }
- } else {
- PPError ("Unexpected #elif");
- }
- break;
-
- case PP_ELSE:
- if (IfIndex >= 0) {
- if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
- if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
- Skip = !Skip;
- }
- IfStack[IfIndex] |= IFCOND_ELSE;
- } else {
- PPError ("Duplicate #else");
- }
- } else {
- PPError ("Unexpected `#else'");
- }
- break;
-
- case PP_ENDIF:
- if (IfIndex >= 0) {
- /* Remove any clauses on top of stack that do not
- * need a terminating #endif.
- */
- while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
- --IfIndex;
- }
-
- /* Stack may not be empty here or something is wrong */
- CHECK (IfIndex >= 0);
-
- /* Remove the clause that needs a terminator */
- Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0;
- } else {
- PPError ("Unexpected `#endif'");
- }
- break;
-
- case PP_ERROR:
- if (!Skip) {
- DoError ();
- }
- break;
-
- case PP_IF:
- Skip = DoIf (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:
- /* Should do something in C99 at least, but we ignore it */
- if (!Skip) {
- ClearLine ();
- }
- break;
-
- case PP_PRAGMA:
- if (!Skip) {
+ /* Check for preprocessor lines lines */
+ if (CurC == '#') {
+ NextChar ();
+ SkipWhitespace (0);
+ if (CurC == '\0') {
+ /* Ignore the empty preprocessor directive */
+ continue;
+ }
+ if (!IsSym (Directive)) {
+ PPError ("Preprocessor directive expected");
+ ClearLine ();
+ } else {
+ switch (FindPPToken (Directive)) {
+
+ case PP_DEFINE:
+ if (!Skip) {
+ DefineMacro ();
+ }
+ break;
+
+ case PP_ELIF:
+ if (IfIndex >= 0) {
+ if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
+
+ /* Handle as #else/#if combination */
+ if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
+ Skip = !Skip;
+ }
+ IfStack[IfIndex] |= IFCOND_ELSE;
+ Skip = DoIf (Skip);
+
+ /* #elif doesn't need a terminator */
+ IfStack[IfIndex] &= ~IFCOND_NEEDTERM;
+ } else {
+ PPError ("Duplicate #else/#elif");
+ }
+ } else {
+ PPError ("Unexpected #elif");
+ }
+ break;
+
+ case PP_ELSE:
+ if (IfIndex >= 0) {
+ if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
+ if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
+ Skip = !Skip;
+ }
+ IfStack[IfIndex] |= IFCOND_ELSE;
+ } else {
+ PPError ("Duplicate #else");
+ }
+ } else {
+ PPError ("Unexpected `#else'");
+ }
+ break;
+
+ case PP_ENDIF:
+ if (IfIndex >= 0) {
+ /* Remove any clauses on top of stack that do not
+ * need a terminating #endif.
+ */
+ while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
+ --IfIndex;
+ }
+
+ /* Stack may not be empty here or something is wrong */
+ CHECK (IfIndex >= 0);
+
+ /* Remove the clause that needs a terminator */
+ Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0;
+ } else {
+ PPError ("Unexpected `#endif'");
+ }
+ break;
+
+ case PP_ERROR:
+ if (!Skip) {
+ DoError ();
+ }
+ break;
+
+ case PP_IF:
+ Skip = DoIf (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:
+ /* Should do something in C99 at least, but we ignore it */
+ if (!Skip) {
+ ClearLine ();
+ }
+ break;
+
+ case PP_PRAGMA:
+ if (!Skip) {
DoPragma ();
goto Done;
- }
- break;
-
- case PP_UNDEF:
- if (!Skip) {
- DoUndef ();
- }
- break;
-
- default:
- PPError ("Preprocessor directive expected");
- ClearLine ();
- }
- }
-
- }
- if (NextLine () == 0) {
- if (IfIndex >= 0) {
- PPError ("`#endif' expected");
- }
- return;
- }
- SkipWhitespace ();
+ }
+ break;
+
+ case PP_UNDEF:
+ if (!Skip) {
+ DoUndef ();
+ }
+ break;
+
+ case PP_WARNING:
+ /* #warning is a non standard extension */
+ if (IS_Get (&Standard) > STD_C99) {
+ if (!Skip) {
+ DoWarning ();
+ }
+ } else {
+ if (!Skip) {
+ PPError ("Preprocessor directive expected");
+ }
+ ClearLine ();
+ }
+ break;
+
+ default:
+ if (!Skip) {
+ PPError ("Preprocessor directive expected");
+ }
+ ClearLine ();
+ }
+ }
+
+ }
+ if (NextLine () == 0) {
+ if (IfIndex >= 0) {
+ PPError ("`#endif' expected");
+ }
+ return;
+ }
+ SkipWhitespace (0);
}
PreprocessLine ();
Done:
if (Verbosity > 1 && SB_NotEmpty (Line)) {
printf ("%s(%u): %.*s\n", GetCurrentFile (), GetCurrentLine (),
- SB_GetLen (Line), SB_GetConstBuf (Line));
+ (int) SB_GetLen (Line), SB_GetConstBuf (Line));
}
}
-