X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fpreproc.c;h=8edeacdd79bb20ab8761b88f402feb3445358986;hb=35e1184901ca38bdb2e56d154ed3b71f6096eacc;hp=4f7e77fce4caea776ed1c94b769b25a1c4602284;hpb=f02698b66d78aaf0607cc45ca38c40a6fa73fd99;p=cc65 diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 4f7e77fce..8edeacdd7 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (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 */ /* */ @@ -128,7 +128,8 @@ typedef enum { PP_INCLUDE, PP_LINE, PP_PRAGMA, - PP_UNDEF + PP_UNDEF, + PP_WARNING, } pptoken_t; @@ -150,6 +151,7 @@ static const struct PPToken { { "line", PP_LINE }, { "pragma", PP_PRAGMA }, { "undef", PP_UNDEF }, + { "warning", PP_WARNING }, }; /* Number of preprocessor tokens */ @@ -187,7 +189,7 @@ static MacroExp* InitMacroExp (MacroExp* E, Macro* M) /* Initialize a MacroExp structure */ { InitCollection (&E->ActualArgs); - InitStrBuf (&E->Replacement); + SB_Init (&E->Replacement); E->M = M; return E; } @@ -204,7 +206,7 @@ static void DoneMacroExp (MacroExp* E) FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I)); } DoneCollection (&E->ActualArgs); - DoneStrBuf (&E->Replacement); + SB_Done (&E->Replacement); } @@ -333,12 +335,31 @@ static void NewStyleComment (void) -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; } @@ -444,7 +465,7 @@ static void ReadMacroArgs (MacroExp* E) } /* Check for end of macro param list */ - if (CurC == ')') { + if (CurC == ')') { NextChar (); break; } @@ -453,12 +474,11 @@ static void ReadMacroArgs (MacroExp* E) NextChar (); SB_Clear (&Arg); } - } else if (IsSpace (CurC)) { + } else if (SkipWhitespace (1)) { /* Squeeze runs of blanks within an arg */ if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } - SkipWhitespace (); } else if (CurC == '/' && NextC == '*') { if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); @@ -470,14 +490,11 @@ static void ReadMacroArgs (MacroExp* E) } NewStyleComment (); } else if (CurC == '\0') { - /* End of line inside macro argument list - read next line */ - if (SB_NotEmpty (&Arg)) { - SB_AppendChar (&Arg, ' '); - } - if (NextLine () == 0) { - ClearLine (); - break; - } + /* 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); @@ -486,7 +503,7 @@ static void ReadMacroArgs (MacroExp* E) } /* Deallocate string buf resources */ - DoneStrBuf (&Arg); + SB_Done (&Arg); } @@ -502,6 +519,7 @@ static void MacroArgSubst (MacroExp* E) /* 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); @@ -518,10 +536,7 @@ static void MacroArgSubst (MacroExp* E) 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. @@ -558,7 +573,7 @@ static void MacroArgSubst (MacroExp* E) /* ## 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 @@ -594,7 +609,7 @@ static void MacroArgSubst (MacroExp* E) * macro parameter. */ NextChar (); - SkipWhitespace (); + SkipWhitespace (0); if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) { PPError ("`#' is not followed by a macro parameter"); } else { @@ -621,6 +636,7 @@ static void MacroArgSubst (MacroExp* E) /* Switch back the input */ InitLine (OldSource); + SB_SetIndex (&E->M->Replacement, OldIndex); } @@ -672,14 +688,15 @@ static void MacroCall (StrBuf* Target, Macro* M) static void ExpandMacro (StrBuf* Target, Macro* M) /* Expand a macro into Target */ { +#if 0 + static unsigned V = 0; + printf ("Expanding %s(%u)\n", M->Name, ++V); +#endif + /* Check if this is a function like macro */ - //printf ("Expanding %s(%u)\n", M->Name, ++V); 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); @@ -710,7 +727,9 @@ static void ExpandMacro (StrBuf* Target, Macro* M) DoneMacroExp (&E); } - //printf ("Done with %s(%u)\n", M->Name, V--); +#if 0 + printf ("Done with %s(%u)\n", M->Name, V--); +#endif } @@ -724,7 +743,7 @@ static void DefineMacro (void) int C89; /* Read the macro name */ - SkipWhitespace (); + SkipWhitespace (0); if (!MacName (Ident)) { return; } @@ -751,7 +770,7 @@ static void DefineMacro (void) while (1) { /* Skip white space and check for end of parameter list */ - SkipWhitespace (); + SkipWhitespace (0); if (CurC == ')') { break; } @@ -770,7 +789,7 @@ static void DefineMacro (void) NextChar (); NextChar (); - /* Remember that the macro is variadic and use __VA_ARGS__ as + /* Remember that the macro is variadic and use __VA_ARGS__ as * the argument name. */ AddMacroArg (M, "__VA_ARGS__"); @@ -795,7 +814,7 @@ static void DefineMacro (void) /* If we had an ellipsis, or the next char is not a comma, we've * reached the end of the macro argument list. */ - SkipWhitespace (); + SkipWhitespace (0); if (M->Variadic || CurC != ',') { break; } @@ -812,7 +831,7 @@ static void DefineMacro (void) } /* Skip whitespace before the macro replacement */ - SkipWhitespace (); + SkipWhitespace (0); /* Insert the macro into the macro table and allocate the ActualArgs array */ InsertMacro (M); @@ -826,8 +845,9 @@ static void DefineMacro (void) 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. @@ -860,26 +880,25 @@ static unsigned Pass1 (StrBuf* Source, StrBuf* Target) /* 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 (); + SkipWhitespace (0); HaveParen = 0; if (CurC == '(') { HaveParen = 1; NextChar (); - SkipWhitespace (); + SkipWhitespace (0); } if (IsSym (Ident)) { SB_AppendChar (Target, IsMacro (Ident)? '1' : '0'); if (HaveParen) { - SkipWhitespace (); + SkipWhitespace (0); if (CurC != ')') { PPError ("`)' expected"); } else { @@ -982,19 +1001,6 @@ static void PreprocessLine (void) -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 */ { @@ -1017,6 +1023,22 @@ static int PushIf (int Skip, int Invert, int Cond) +static void DoError (void) +/* Print an error */ +{ + SkipWhitespace (0); + if (CurC == '\0') { + PPError ("Invalid #error directive"); + } else { + PPError ("#error: %s", SB_GetConstBuf (Line) + SB_GetIndex (Line)); + } + + /* Clear the rest of line */ + ClearLine (); +} + + + static int DoIf (int Skip) /* Process #if directive */ { @@ -1038,20 +1060,6 @@ static int DoIf (int Skip) UseLineInfo (SavedNextTok.LI); } -#if 0 - /* Remove the #if from the line */ - SkipWhitespace (); - S = line; - while (CurC != '\0') { - *S++ = CurC; - NextChar (); - } - *S = '\0'; - - /* Start over parsing from line */ - InitLine (line); -#endif - /* Switch into special preprocessing mode */ Preprocessing = 1; @@ -1063,6 +1071,7 @@ static int DoIf (int Skip) * the following line. */ SB_AppendStr (Line, ";;"); + SB_Terminate (Line); /* Load CurTok and NextTok with tokens from the new input */ NextToken (); @@ -1089,7 +1098,7 @@ static int DoIfDef (int skip, int flag) { ident Ident; - SkipWhitespace (); + SkipWhitespace (0); if (MacName (Ident) == 0) { return 0; } else { @@ -1103,12 +1112,15 @@ static void DoInclude (void) /* Open an include file. */ { char RTerm; - unsigned DirSpec; + 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. @@ -1117,12 +1129,12 @@ static void DoInclude (void) case '\"': RTerm = '\"'; - DirSpec = INC_USER; + IT = IT_USRINC; break; case '<': RTerm = '>'; - DirSpec = INC_SYS; + IT = IT_SYSINC; break; default: @@ -1139,18 +1151,17 @@ static void DoInclude (void) SB_Terminate (&Filename); /* Check if we got a terminator */ - if (CurC != RTerm) { + if (CurC == RTerm) { + /* Open the include file */ + OpenIncludeFile (SB_GetConstBuf (&Filename), IT); + } else if (CurC == '\0') { /* No terminator found */ - PPError ("Missing terminator or file name too long"); - goto Done; + PPError ("#include expects \"FILENAME\" or "); } - /* 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) @@ -1160,29 +1171,13 @@ Done: -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); @@ -1201,6 +1196,35 @@ static void DoPragma (void) +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 */ { @@ -1213,7 +1237,7 @@ void Preprocess (void) } /* Skip white space at the beginning of the line */ - SkipWhitespace (); + SkipWhitespace (0); /* Check for stuff to skip */ Skip = 0; @@ -1222,7 +1246,7 @@ void Preprocess (void) /* Check for preprocessor lines lines */ if (CurC == '#') { NextChar (); - SkipWhitespace (); + SkipWhitespace (0); if (CurC == '\0') { /* Ignore the empty preprocessor directive */ continue; @@ -1338,8 +1362,24 @@ void Preprocess (void) } 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: - PPError ("Preprocessor directive expected"); + if (!Skip) { + PPError ("Preprocessor directive expected"); + } ClearLine (); } } @@ -1351,7 +1391,7 @@ void Preprocess (void) } return; } - SkipWhitespace (); + SkipWhitespace (0); } PreprocessLine (); @@ -1359,7 +1399,7 @@ void Preprocess (void) 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)); } }