/* */
/* */
/* */
-/* (C) 1998-2007, Ullrich von Bassewitz */
+/* (C) 1998-2010, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* 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);
}
-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;
}
}
/* Check for end of macro param list */
- if (CurC == ')') {
+ if (CurC == ')') {
NextChar ();
break;
}
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, ' ');
}
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);
}
/* Deallocate string buf resources */
- DoneStrBuf (&Arg);
+ SB_Done (&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);
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.
/* ## 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 {
/* Switch back the input */
InitLine (OldSource);
+ SB_SetIndex (&E->M->Replacement, OldIndex);
}
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
}
int C89;
/* Read the macro name */
- SkipWhitespace ();
+ SkipWhitespace (0);
if (!MacName (Ident)) {
return;
}
while (1) {
/* Skip white space and check for end of parameter list */
- SkipWhitespace ();
+ SkipWhitespace (0);
if (CurC == ')') {
break;
}
/* 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;
}
}
/* 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.
/* 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 {
static void DoError (void)
/* Print an error */
{
- SkipWhitespace ();
+ SkipWhitespace (0);
if (CurC == '\0') {
PPError ("Invalid #error directive");
} else {
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;
{
ident Ident;
- SkipWhitespace ();
+ SkipWhitespace (0);
if (MacName (Ident) == 0) {
return 0;
} else {
/* 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.
case '\"':
RTerm = '\"';
- DirSpec = INC_USER;
+ IT = IT_USRINC;
break;
case '<':
RTerm = '>';
- DirSpec = INC_SYS;
+ IT = IT_SYSINC;
break;
default:
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 <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)
*/
{
/* Skip blanks following the #pragma directive */
- SkipWhitespace ();
+ SkipWhitespace (0);
/* Copy the remainder of the line into MLine removing comments and ws */
SB_Clear (MLine);
{
ident Ident;
- SkipWhitespace ();
+ SkipWhitespace (0);
if (MacName (Ident)) {
UndefineMacro (Ident);
}
static void DoWarning (void)
/* Print a warning */
{
- SkipWhitespace ();
+ SkipWhitespace (0);
if (CurC == '\0') {
PPError ("Invalid #warning directive");
} else {
}
/* Skip white space at the beginning of the line */
- SkipWhitespace ();
+ SkipWhitespace (0);
/* Check for stuff to skip */
Skip = 0;
/* Check for preprocessor lines lines */
if (CurC == '#') {
NextChar ();
- SkipWhitespace ();
+ SkipWhitespace (0);
if (CurC == '\0') {
/* Ignore the empty preprocessor directive */
continue;
DoWarning ();
}
} else {
- PPError ("Preprocessor directive expected");
+ if (!Skip) {
+ PPError ("Preprocessor directive expected");
+ }
ClearLine ();
}
break;
default:
- PPError ("Preprocessor directive expected");
+ if (!Skip) {
+ PPError ("Preprocessor directive expected");
+ }
ClearLine ();
}
}
}
return;
}
- SkipWhitespace ();
+ 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));
}
}