#define INP_READ_IN_ONE 1 /* read input file in one */
-!File: nopp.h
-#define NOPP 1 /* if NOT defined, use built-int preprocessor */
-
-
!File: nobitfield.h
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
int idfsize = IDFSIZE;
char sp_occurred[SP_TOTAL + 1];
-#ifndef NOPP
-int ReplaceMacros = 1; /* replacing macros */
-int AccDefined = 0; /* accept "defined(...)" */
-int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
-int Unstacked = 0; /* an unstack is done */
-extern int InputLevel;
-#endif
int AccFileSpecifier = 0; /* return filespecifier <...> */
int EoiForNewline = 0; /* return EOI upon encountering newline */
int File_Inserted = 0; /* a file has just been inserted */
extern int lint_skip_comment;
#endif
-#ifndef NOPP
-static struct token LexStack[MAX_LL_DEPTH];
-static LexSP = 0;
-
-void skipcomment();
-void skiplinecomment();
-
-/* In PushLex() the actions are taken in order to initialise or
- re-initialise the lexical scanner.
- E.g. at the invocation of a sub-parser that uses LLlex(), the
- state of the current parser should be saved.
-*/
-PushLex()
-{
- assert(LexSP < MAX_LL_DEPTH);
- assert(ASIDE == 0); /* ASIDE = 0; */
- GetToken(&ahead);
- LexStack[LexSP++] = dot;
-}
-
-PopLex()
-{
- assert(LexSP > 0);
- dot = LexStack[--LexSP];
-}
-#endif /* NOPP */
-
int LLlex()
{
/* LLlex() plays the role of Lexical Analyzer for the C parser.
return ptok->tk_symb = EOI;
while ((ch = GetChar()), (ch == '#'
-#ifndef NOPP
- || ch == '/'
-#endif
|| class(ch) == STSKIP))
{
/* blanks are allowed before hashes */
{
/* a control line follows */
domacro();
-#ifndef NOPP
- if (File_Inserted)
- {
- File_Inserted = 0;
- goto firstline;
- }
- }
- else if ((ch == '/') && !InputLevel)
- {
- int nch = GetChar();
- if (nch == '*')
- skipcomment();
- else if (nch == '/')
- skiplinecomment();
- else
- {
- UnGetChar();
- break;
- }
-#endif /* NOPP */
}
}
/* We have to loop here, because in
case STSKIP: /* just skip the skip characters */
goto again;
case STGARB: /* garbage character */
-#ifndef NOPP
- garbage:
-#endif
if (040 < ch && ch < 0177)
{
return ptok->tk_symb = ch;
return ptok->tk_symb = XORAB;
break;
case '/':
-#ifndef NOPP
- if (!InputLevel)
- {
- if (nch == '*')
- {
- skipcomment();
- goto again;
- }
- else if (nch == '/')
- {
- skiplinecomment();
- goto again;
- }
- }
-#endif
if (nch == '=')
return ptok->tk_symb = DIVAB;
break;
register int pos = -1;
register struct idf* idef;
extern int idfsize; /* ??? */
-#ifndef NOPP
- int NoExpandNext = 0;
-
- if (Unstacked)
- EnableMacros(); /* unstack macro's when allowed. */
- if (ch == NOEXPM)
- {
- NoExpandNext = 1;
- ch = GetChar();
- }
-#endif
do
{ /* read the identifier */
if (++pos < idfsize)
sp_occurred[idef->id_special] = 1;
idef->id_file = ptok->tk_file;
idef->id_line = ptok->tk_line;
-#ifndef NOPP
- if (idef->id_macro && ReplaceMacros && !NoExpandNext)
- {
- if (replace(idef))
- goto again;
- }
- if (UnknownIdIsZero && idef->id_reserved != SIZEOF)
- {
- ptok->tk_ival = (arith)0;
- ptok->tk_fund = INT;
- return ptok->tk_symb = INTEGER;
- }
-#endif /* NOPP */
ptok->tk_symb
= (idef->id_reserved
? idef->id_reserved
}
case STEOI: /* end of text on source file */
return ptok->tk_symb = EOI;
-#ifndef NOPP
- case STMSPEC:
- if (!InputLevel)
- goto garbage;
- if (ch == TOKSEP)
- goto again;
-/* fallthrough shouldn't happen */
-#endif
default: /* this cannot happen */
crash("bad class for char 0%o", ch);
}
/*NOTREACHED*/
}
-#ifndef NOPP
-void skipcomment()
-{
- /* The last character read has been the '*' of '/_*'. The
- characters, except NL and EOI, between '/_*' and the first
- occurring '*_/' are not interpreted.
- NL only affects the LineNumber. EOI is not legal.
-
- Important note: it is not possible to stop skipping comment
- beyond the end-of-file of an included file.
- EOI is returned by LoadChar only on encountering EOF of the
- top-level file...
- */
- register int c, oldc = '\0';
-
- NoUnstack++;
- c = GetChar();
-#ifdef LINT
- if (!lint_skip_comment)
- {
- lint_start_comment();
- lint_comment_char(c);
- }
-#endif /* LINT */
- do
- {
- while (c != '*')
- {
- if (class(c) == STNL)
- {
- ++LineNumber;
- }
- else if (c == EOI)
- {
- NoUnstack--;
-#ifdef LINT
- if (!lint_skip_comment)
- lint_end_comment();
-#endif /* LINT */
- return;
- }
- oldc = c;
- c = GetChar();
-#ifdef LINT
- if (!lint_skip_comment)
- lint_comment_char(c);
-#endif /* LINT */
- } /* last Character seen was '*' */
- c = GetChar();
- if (c != '/' && oldc == '/')
- lexwarning("comment inside comment ?");
- oldc = '*';
-#ifdef LINT
- if (!lint_skip_comment)
- lint_comment_char(c);
-#endif /* LINT */
- } while (c != '/');
-#ifdef LINT
- if (!lint_skip_comment)
- lint_end_comment();
-#endif /* LINT */
- NoUnstack--;
-}
-
-void skiplinecomment(void)
-{
- /* The last character read has been the '/' of '//'. We read
- and discard all characters up to but not including the next
- NL. */
-
- for (;;) {
- int c = GetChar();
- if ((class(c) == STNL) || (c == EOI))
- {
- UnGetChar();
- break;
- }
- }
-}
-#endif /* NOPP */
-
arith char_constant(nm) char* nm;
{
register arith val = 0;
*/
register int ch;
-#ifndef NOPP
-again:
-#endif
LoadChar(ch);
-
-#ifndef NOPP
- /* possible trigraph sequence */
- if (ch == '?')
- ch = trigraph();
-
- /* \<newline> is removed from the input stream */
- if (ch == '\\')
- {
- LoadChar(ch);
- if (ch == '\n')
- {
- ++LineNumber;
- goto again;
- }
- PushBack();
- ch = '\\';
- }
-#endif
return (LexSave = ch);
}
-#ifndef NOPP
-int trigraph()
-{
- register int ch;
-
- LoadChar(ch);
- if (ch == '?')
- {
- LoadChar(ch);
- switch (ch)
- { /* its a trigraph */
- case '=':
- ch = '#';
- return (ch);
- case '(':
- ch = '[';
- return (ch);
- case '/':
- ch = '\\';
- return (ch);
- case ')':
- ch = ']';
- return (ch);
- case '\'':
- ch = '^';
- return (ch);
- case '<':
- ch = '{';
- return (ch);
- case '!':
- ch = '|';
- return (ch);
- case '>':
- ch = '}';
- return (ch);
- case '-':
- ch = '~';
- return (ch);
- }
- PushBack();
- }
- PushBack();
- return ('?');
-}
-#endif
-
/* strflt2tok only checks the syntax of the floating-point number and
* selects the right type for the number.
*/
extern int token_nmb; /* number of the ahead token */
extern int tk_nmb_at_last_syn_err; /* token number at last syntax error */
-#ifndef NOPP
-extern int ReplaceMacros; /* "LLlex.c" */
-extern int AccDefined; /* "LLlex.c" */
-extern int Unstacked; /* "LLlex.c" */
-extern int UnknownIdIsZero; /* "LLlex.c" */
-#endif /* NOPP */
extern int EoiForNewline; /* "LLlex.c" */
extern int AccFileSpecifier; /* "LLlex.c" */
extern int File_Inserted; /* "LLlex.c" */
/*#define INP_READ_IN_ONE 1 /* read input file in one */
-!File: nopp.h
-#define NOPP 1 /* if NOT defined, use built-int preprocessor */
-
-
!File: nobitfield.h
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
"./field.c",
"./fltcstoper.c",
"./idf.c",
- "./init.c",
"./input.c",
"./l_comment.c",
"./l_ev_ord.c",
"./options.c",
"./pragma.c",
"./proto.c",
- "./replace.c",
"./skip.c",
"./stab.c",
"./stack.c",
extern char options[];
-#ifndef NOPP
-#include <alloc.h>
-#include "class.h"
-#include "macro.h"
-
-extern char** inctable; /* list of include directories */
-extern char* getwdir();
-char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
-/* 1 if a corresponding ELSE has been */
-/* encountered. */
-
-int nestlevel = -1;
-
-void macro_def();
-void do_define();
-
-struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */
-{
- /* returns a pointer to the descriptor of the identifier that is
- read from the input stream. When the input doe not contain
- an identifier, the rest of the line is skipped when
- skiponerr is on, and a null-pointer is returned.
- The substitution of macros is disabled.
- */
- int tmp = UnknownIdIsZero;
- int tok;
- struct token tk;
-
- UnknownIdIsZero = ReplaceMacros = 0;
- tok = GetToken(&tk);
- ReplaceMacros = 1;
- UnknownIdIsZero = tmp;
- if (tok != IDENTIFIER)
- {
- if (skiponerr && tok != EOI)
- SkipToNewLine();
- return (struct idf*)0;
- }
- return tk.tk_idf;
-}
-
-/* domacro() is the control line interpreter. The '#' has already
- been read by the lexical analyzer by which domacro() is called.
- The token appearing directly after the '#' is obtained by calling
- the basic lexical analyzing function GetToken() and is interpreted
- to perform the action belonging to that token.
- An error message is produced when the token is not recognized,
- i.e. it is not one of "define" .. "undef" , integer or newline.
-*/
-domacro()
-{
- struct token tk; /* the token itself */
- int toknum;
-
- EoiForNewline = 1;
- ReplaceMacros = 0;
- toknum = GetToken(&tk);
- ReplaceMacros = 1;
- switch (toknum)
- { /* select control line action */
- case IDENTIFIER: /* is it a macro keyword? */
- switch (tk.tk_idf->id_resmac)
- {
- case K_DEFINE: /* "define" */
- do_define();
- break;
- case K_ELIF: /* "elif" */
- do_elif();
- break;
- case K_ELSE: /* "else" */
- do_else();
- break;
- case K_ENDIF: /* "endif" */
- do_endif();
- break;
- case K_IF: /* "if" */
- do_if();
- break;
- case K_IFDEF: /* "ifdef" */
- do_ifdef(1);
- break;
- case K_IFNDEF: /* "ifndef" */
- do_ifdef(0);
- break;
- case K_INCLUDE: /* "include" */
- do_include();
- break;
- case K_LINE: /* "line" */
- /* set LineNumber and FileName according to
- the arguments.
- */
- if (GetToken(&tk) != INTEGER)
- {
- lexerror("bad #line syntax");
- SkipToNewLine();
- }
- else
- do_line((unsigned int)tk.tk_ival);
- break;
- case K_ERROR: /* "error" */
- do_error();
- break;
- case K_PRAGMA: /* "pragma" */
- do_pragma();
- break;
- case K_UNDEF: /* "undef" */
- do_undef((struct idf*)0);
- break;
- default:
- /* invalid word seen after the '#' */
- lexerror("%s: unknown control", tk.tk_idf->id_text);
- SkipToNewLine();
- }
- break;
- case INTEGER: /* # <integer> [<filespecifier>]? */
- do_line((unsigned int)tk.tk_ival);
- break;
- case EOI: /* only `#' on this line: do nothing, ignore */
- break;
- default: /* invalid token following '#' */
- lexerror("illegal # line");
- SkipToNewLine();
- }
- EoiForNewline = 0;
-}
-
-#ifdef LINT
-int lint_skip_comment;
-#endif
-
-void skip_block(to_endif) int to_endif;
-{
- /* skip_block() skips the input from
- 1) a false #if, #ifdef, #ifndef or #elif until the
- corresponding #elif (resulting in true), #else or
- #endif is read.
- 2) a #else corresponding to a true #if, #ifdef,
- #ifndef or #elif until the corresponding #endif is
- seen.
- */
- register int ch;
- register int skiplevel = nestlevel; /* current nesting level */
- struct token tk;
- int toknum;
-
-#ifdef LINT
- lint_skip_comment++;
-#endif
- NoUnstack++;
- for (;;)
- {
- ch = GetChar(); /* read first character after newline */
- while (class(ch) == STSKIP)
- ch = GetChar();
- if (ch != '#')
- {
- if (ch == EOI)
- {
- NoUnstack--;
-#ifdef LINT
- lint_skip_comment--;
-#endif
- return;
- }
- /* A possible '/' is not pushed back */
- if (ch == '/')
- {
- ch = GetChar();
- if (ch == '/')
- {
- skiplinecomment();
- continue;
- }
- else if (ch == '*')
- {
- skipcomment();
- continue;
- }
- else
- UnGetChar();
- }
- else
- UnGetChar();
- SkipToNewLine();
- continue;
- }
- ReplaceMacros = 0;
- toknum = GetToken(&tk);
- ReplaceMacros = 1;
- if (toknum != IDENTIFIER)
- {
- if (toknum != INTEGER)
- {
- lexerror("illegal # line");
- }
- SkipToNewLine();
- continue;
- }
- /* an IDENTIFIER: look for #if, #ifdef and #ifndef
- without interpreting them.
- Interpret #else, #elif and #endif if they occur
- on the same level.
- */
- switch (tk.tk_idf->id_resmac)
- {
- default:
- case K_UNKNOWN:
- /* invalid word seen after the '#' */
- lexwarning("%s: unknown control", tk.tk_idf->id_text);
- /* fallthrough */
- case K_DEFINE:
- case K_ERROR:
- case K_INCLUDE:
- case K_LINE:
- case K_PRAGMA:
- case K_UNDEF:
- case K_FILE:
- SkipToNewLine();
- break;
- case K_IF:
- case K_IFDEF:
- case K_IFNDEF:
- push_if();
- SkipToNewLine();
- break;
- case K_ELIF:
- if (ifstack[nestlevel])
- lexerror("#elif after #else");
- if (!to_endif && nestlevel == skiplevel)
- {
- nestlevel--;
- push_if();
- if (ifexpr())
- {
- NoUnstack--;
-#ifdef LINT
- lint_skip_comment--;
-#endif
- return;
- }
- }
- else
- SkipToNewLine(); /* otherwise done in ifexpr() */
- break;
- case K_ELSE:
- if (ifstack[nestlevel])
- lexerror("#else after #else");
- ++(ifstack[nestlevel]);
- if (!to_endif && nestlevel == skiplevel)
- {
- if (SkipToNewLine())
- {
- if (!options['o'])
- lexstrict("garbage following #else");
- }
- NoUnstack--;
-#ifdef LINT
- lint_skip_comment--;
-#endif
- return;
- }
- else
- SkipToNewLine();
- break;
- case K_ENDIF:
- assert(nestlevel > nestlow);
- if (nestlevel == skiplevel)
- {
- if (SkipToNewLine())
- {
- if (!options['o'])
- lexstrict("garbage following #endif");
- }
- nestlevel--;
- NoUnstack--;
-#ifdef LINT
- lint_skip_comment--;
-#endif
- return;
- }
- else
- SkipToNewLine();
- nestlevel--;
- break;
- }
- }
-}
-
-ifexpr()
-{
- /* ifexpr() returns whether the restricted constant
- expression following #if or #elif evaluates to true. This
- is done by calling the LLgen generated subparser for
- constant expressions. The result of this expression will
- be given in the extern long variable "ifval".
- */
- extern arith ifval;
- int errors = err_occurred;
-
- ifval = (arith)0;
- AccDefined = 1;
- UnknownIdIsZero = 1;
- PushLex(); /* NEW parser */
- If_expr(); /* invoke constant expression parser */
- PopLex(); /* OLD parser */
- AccDefined = 0;
- UnknownIdIsZero = 0;
- return (errors == err_occurred) && (ifval != (arith)0);
-}
-
-do_include()
-{
- /* do_include() performs the inclusion of a file.
- */
- char* filenm;
- char* result;
- int tok;
- struct token tk;
-
- AccFileSpecifier = 1;
- if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
- filenm = tk.tk_bts;
- else
- {
- lexerror("bad include syntax");
- filenm = (char*)0;
- }
- AccFileSpecifier = 0;
- if (SkipToNewLine())
- {
- lexerror("bad include syntax");
- }
- inctable[0] = WorkingDir;
- if (filenm)
- {
- if (!InsertFile(filenm, &inctable[tok == FILESPECIFIER], &result))
- {
- lexerror("cannot open include file \"%s\"", filenm);
- add_dependency(filenm);
- free(filenm);
- }
- else
- {
- add_dependency(result);
- WorkingDir = getwdir(result);
- File_Inserted = 1;
- FileName = result;
- LineNumber = 0;
- nestlow = nestlevel;
-#ifdef DBSYMTAB
- IncludeLevel++;
- if (options['g'])
- {
- C_ms_stb_cst(FileName, N_BINCL, 0, (arith)0);
- }
-#endif /* DBSYMTAB */
- if (result != filenm)
- free(filenm);
- }
- }
-}
-
-void do_define()
-{
- /* do_define() interprets a #define control line.
- */
- struct idf* id; /* the #defined identifier's descriptor */
- int nformals = -1; /* keep track of the number of formals */
- char* formals[NPARAMS]; /* pointers to the names of the formals */
- char parbuf[PARBUFSIZE]; /* names of formals */
- char* repl_text; /* start of the replacement text */
- int length; /* length of the replacement text */
- register ch;
- char* get_text();
-
- /* read the #defined macro's name */
- if (!(id = GetIdentifier(1)))
- {
- lexerror("illegal #define line");
- return;
- }
- /* there is a formal parameter list if the identifier is
- followed immediately by a '('.
- */
- ch = GetChar();
- if (ch == '(')
- {
- if ((nformals = getparams(formals, parbuf)) == -1)
- {
- SkipToNewLine();
- return; /* an error occurred */
- }
- ch = GetChar();
- }
- /* read the replacement text if there is any */
- ch = skipspaces(ch, 0); /* find first character of the text */
- assert(ch != EOI);
- /* UnGetChar() is not right when replacement starts with a '/' */
- ChPushBack(ch);
- repl_text = get_text((nformals > 0) ? formals : 0, &length);
- macro_def(id, repl_text, nformals, length, NOFLAG);
- LineNumber++;
-}
-
-push_if()
-{
- if (nestlevel >= IFDEPTH)
- fatal("too many nested #if/#ifdef/#ifndef");
- else
- ifstack[++nestlevel] = 0;
-}
-
-do_elif()
-{
- if (nestlevel <= nestlow)
- {
- lexerror("#elif without corresponding #if");
- SkipToNewLine();
- }
- else
- { /* restart at this level as if a #if is detected. */
- if (ifstack[nestlevel])
- {
- lexerror("#elif after #else");
- SkipToNewLine();
- }
- nestlevel--;
- push_if();
- skip_block(1);
- }
-}
-
-do_else()
-{
- if (SkipToNewLine())
- if (!options['o'])
- lexstrict("garbage following #else");
- if (nestlevel <= nestlow)
- lexerror("#else without corresponding #if");
- else
- { /* mark this level as else-d */
- if (ifstack[nestlevel])
- {
- lexerror("#else after #else");
- }
- ++(ifstack[nestlevel]);
- skip_block(1);
- }
-}
-
-do_endif()
-{
- if (SkipToNewLine())
- {
- if (!options['o'])
- lexstrict("garbage following #endif");
- }
- if (nestlevel <= nestlow)
- {
- lexerror("#endif without corresponding #if");
- }
- else
- nestlevel--;
-}
-
-do_if()
-{
- push_if();
- if (!ifexpr()) /* a false #if/#elif expression */
- skip_block(0);
-}
-
-do_ifdef(how)
-{
- register struct idf* id;
-
- /* how == 1 : ifdef; how == 0 : ifndef
- */
- push_if();
- if (!(id = GetIdentifier(1)))
- lexerror("illegal #ifdef construction");
- else if (SkipToNewLine())
- if (!options['o'])
- lexstrict("garbage following #%s <identifier>", how ? "ifdef" : "ifndef");
-
- /* The next test is a shorthand for:
- (how && !id->id_macro) || (!how && id->id_macro)
- */
- if (how ^ (id && id->id_macro != 0))
- skip_block(0);
-}
-
-/* argidf != NULL when the undef came from a -U option */
-do_undef(argidf) struct idf* argidf;
-{
- register struct idf* id = argidf;
-
- /* Forget a macro definition. */
- if (id || (id = GetIdentifier(1)))
- {
- if (id->id_macro)
- { /* forget the macro */
- if (id->id_macro->mc_flag & NOUNDEF)
- {
- lexerror("it is not allowed to undef %s", id->id_text);
- }
- else
- {
- free(id->id_macro->mc_text);
- free_macro(id->id_macro);
- id->id_macro = (struct macro*)0;
- }
- } /* else: don't complain */
- if (!argidf)
- {
- if (SkipToNewLine())
- if (!options['o'])
- lexstrict("garbage following #undef");
- }
- }
- else
- lexerror("illegal #undef construction");
-}
-
-do_error()
-{
- int len;
- char* get_text();
- char* bp = get_text((char**)0, &len);
-
- lexerror("user error: %s", bp);
- free(bp);
- LineNumber++;
-}
-
-int getparams(buf, parbuf) char* buf[];
-char parbuf[];
-{
- /* getparams() reads the formal parameter list of a macro
- definition.
- The number of parameters is returned.
- As a formal parameter list is expected when calling this
- routine, -1 is returned if an error is detected, for
- example:
- #define one(1), where 1 is not an identifier.
- Note that the '(' has already been eaten.
- The names of the formal parameters are stored into parbuf.
- */
- register char** pbuf = &buf[0];
- register int c;
- register char* ptr = &parbuf[0];
- register char** pbuf2;
-
- c = GetChar();
- c = skipspaces(c, 0);
- if (c == ')')
- { /* no parameters: #define name() */
- *pbuf = (char*)0;
- return 0;
- }
- for (;;)
- { /* eat the formal parameter list */
- if (class(c) != STIDF && class(c) != STELL)
- {
- lexerror("#define: bad formal parameter");
- return -1;
- }
- *pbuf = ptr; /* name of the formal */
- *ptr++ = c;
- if (ptr >= &parbuf[PARBUFSIZE])
- fatal("formal parameter buffer overflow");
- do
- { /* eat the identifier name */
- c = GetChar();
- *ptr++ = c;
- if (ptr >= &parbuf[PARBUFSIZE])
- fatal("formal parameter buffer overflow");
- } while (in_idf(c));
- *(ptr - 1) = '\0'; /* mark end of the name */
-
- /* Check if this formal parameter is already used.
- Usually, macros do not have many parameters, so ...
- */
- for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--)
- {
- if (!strcmp(*pbuf2, *pbuf))
- {
- lexerror("formal parameter \"%s\" already used", *pbuf);
- }
- }
-
- pbuf++;
- c = skipspaces(c, 0);
- if (c == ')')
- { /* end of the formal parameter list */
- *pbuf = (char*)0;
- return pbuf - buf;
- }
- if (c != ',')
- {
- lexerror("#define: bad formal parameter list");
- return -1;
- }
- c = GetChar();
- c = skipspaces(c, 0);
- }
- /*NOTREACHED*/
-}
-
-void macro_def(id, text, nformals, length, flags) register struct idf* id;
-char* text;
-{
- register struct macro* newdef = id->id_macro;
-
- /* macro_def() puts the contents and information of a macro
- definition into a structure and stores it into the symbol
- table entry belonging to the name of the macro.
- An error is given if there was already a definition
- */
- if (newdef)
- { /* is there a redefinition? */
- if (newdef->mc_flag & NOUNDEF)
- {
- lexerror("it is not allowed to redefine %s", id->id_text);
- }
- else if (!macroeq(newdef->mc_text, text))
- lexerror("illegal redefine of \"%s\"", id->id_text);
- free(text);
- return;
- }
- id->id_macro = newdef = new_macro();
- newdef->mc_text = text; /* replacement text */
- newdef->mc_nps = nformals; /* nr of formals */
- newdef->mc_length = length; /* length of repl. text */
- newdef->mc_flag = flags; /* special flags */
-}
-
-int find_name(nm, index) char *nm, *index[];
-{
- /* find_name() returns the index of "nm" in the namelist
- "index" if it can be found there. 0 is returned if it is
- not there.
- */
- register char** ip = &index[0];
-
- while (*ip)
- if (strcmp(nm, *ip++) == 0)
- return ip - &index[0];
- /* arrived here, nm is not in the name list. */
- return 0;
-}
-
-#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
-
-char* get_text(formals, length) char* formals[];
-int* length;
-{
- /* get_text() copies the replacement text of a macro
- definition with zero, one or more parameters, thereby
- substituting each formal parameter by a special character
- (non-ascii: 0200 & (order-number in the formal parameter
- list)) in order to substitute this character later by the
- actual parameter. The replacement text is copied into
- itself because the copied text will contain fewer or the
- same amount of characters. The length of the replacement
- text is returned.
-
- Implementation:
- finite automaton : we are interested in
- 1- white space, sequences must be mapped onto 1 single
- blank.
- 2- identifiers, since they might be replaced by some
- actual parameter.
- 3- strings and character constants, since replacing
- variables within them is illegal, and white-space is
- significant.
- 4- comment, same as for 1
- Other tokens will not be seen as such.
- */
- register int c;
- struct repl repls;
- register struct repl* repl = &repls;
- int blank = 0;
-
- c = GetChar();
-
- repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
- *repl->r_ptr = '\0';
- while ((c != EOI) && (class(c) != STNL))
- {
- if (BLANK(c))
- {
- blank++;
- c = GetChar();
- continue;
- }
-
- if (c == '\'' || c == '"')
- {
- register int delim = c;
-
- if (blank)
- {
- blank = 0;
- add2repl(repl, ' ');
- }
- do
- {
- add2repl(repl, c);
- if (c == '\\')
- add2repl(repl, GetChar());
- c = GetChar();
- } while (c != delim && c != EOI && class(c) != STNL);
- if (c == EOI || class(c) == STNL)
- {
- lexstrict("unclosed opening %c", delim);
- break;
- }
- add2repl(repl, c);
- c = GetChar();
- }
- else if (c == '/')
- {
- c = GetChar();
- if (c == '*')
- {
- skipcomment();
- blank++;
- c = GetChar();
- continue;
- }
- else if (c == '/')
- {
- skiplinecomment();
- blank++;
- c = GetChar();
- continue;
- }
- if (blank)
- {
- blank = 0;
- add2repl(repl, ' ');
- }
- add2repl(repl, '/');
- }
- else if (formals && (class(c) == STIDF || class(c) == STELL))
- {
- char id_buf[IDFSIZE + 1];
- register char* idp = id_buf;
- int n;
-
- /* read identifier: it may be a formal parameter */
- *idp++ = c;
- do
- {
- c = GetChar();
- if (idp <= &id_buf[IDFSIZE])
- *idp++ = c;
- } while (in_idf(c));
- *--idp = '\0';
-
- if (blank)
- {
- blank = 0;
- add2repl(repl, ' ');
- }
- /* construct the formal parameter mark or identifier */
- if (n = find_name(id_buf, formals))
- add2repl(repl, FORMALP | (char)n);
- else
- {
- idp = id_buf;
- while (*idp)
- add2repl(repl, *idp++);
- }
- }
- else if (class(c) == STNUM)
- {
- if (blank)
- {
- blank = 0;
- add2repl(repl, ' ');
- }
- add2repl(repl, c);
- if (c == '.')
- {
- c = GetChar();
- if (class(c) != STNUM)
- {
- continue;
- }
- add2repl(repl, c);
- }
- c = GetChar();
- while (in_idf(c) || c == '.')
- {
- add2repl(repl, c);
- if ((c = GetChar()) == 'e' || c == 'E')
- {
- add2repl(repl, c);
- c = GetChar();
- if (c == '+' || c == '-')
- {
- add2repl(repl, c);
- c = GetChar();
- }
- }
- }
- }
- else
- {
- if (blank)
- {
- blank = 0;
- add2repl(repl, ' ');
- }
- add2repl(repl, c);
- c = GetChar();
- }
- }
- *length = repl->r_ptr - repl->r_text;
- return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text + 1));
-}
-
-/* macroeq() decides whether two macro replacement texts are
- identical. This version compares the texts, which occur
- as strings, without taking care of the leading and trailing
- blanks (spaces and tabs).
-*/
-macroeq(s, t) register char* s, *t;
-{
-
- /* skip leading spaces */
- while (BLANK(*s))
- s++;
- while (BLANK(*t))
- t++;
- /* first non-blank encountered in both strings */
- /* The actual comparison loop: */
- while (*s && *s == *t)
- s++, t++;
- /* two cases are possible when arrived here: */
- if (*s == '\0')
- { /* *s == '\0' */
- while (BLANK(*t))
- t++;
- return *t == '\0';
- }
- else
- { /* *s != *t */
- while (BLANK(*s))
- s++;
- while (BLANK(*t))
- t++;
- return (*s == '\0') && (*t == '\0');
- }
-}
-#else /* NOPP */
-
struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */
{
/* returns a pointer to the descriptor of the identifier that is
EoiForNewline = 0;
SkipToNewLine();
}
-#endif /* NOPP */
do_line(l) unsigned int l;
{
if (!idf)
return;
-#ifndef NOPP
- if ((opt&1) && idf->id_macro) {
- if (!started++) {
- newline();
- print("%s:", idf->id_text);
- }
- print(" macro");
- }
-#endif /* NOPP */
if ((opt&2) && idf->id_reserved) {
if (!started++) {
newline();
#include "parameters.h"
struct id_u {
-#ifndef NOPP
- struct macro *idd_macro;
- int idd_resmac; /* if nonzero: keyword of macroproc. */
-#endif /* NOPP */
int idd_reserved; /* non-zero for reserved words */
char *idd_file; /* file containing the occurrence */
unsigned int idd_line; /* line number of the occurrence */
#include <idf_pkg.spec>
-#ifndef NOPP
-struct dependency {
- struct dependency *next;
- struct idf *dep_idf;
-};
-
-/* ALLOCDEF "dependency" 10 */
-#endif /* NOPP */
-
extern int level;
extern struct idf *gen_idf();
+++ /dev/null
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
-/* $Id$ */
-/* PREPROCESSOR: INITIALIZATION ROUTINES */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "parameters.h"
-
-#ifndef NOPP
-#include <system.h>
-#include <alloc.h>
-#include <time.h>
-#include "idf.h"
-#include "class.h"
-#include "macro.h"
-
-extern char *sprint();
-
-struct mkey {
- char *mk_reserved;
- int mk_key;
-} mkey[] = {
- {"define", K_DEFINE},
- {"elif", K_ELIF},
- {"else", K_ELSE},
- {"endif", K_ENDIF},
- {"error", K_ERROR},
- {"if", K_IF},
- {"ifdef", K_IFDEF},
- {"ifndef", K_IFNDEF},
- {"include", K_INCLUDE},
- {"line", K_LINE},
- {"pragma", K_PRAGMA},
- {"undef", K_UNDEF},
- {0, K_UNKNOWN}
-};
-
-init_pp()
-{
- static char *months[12] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- time_t clock;
- static char dbuf[30];
- static char tbuf[30];
- struct tm *tp;
-
- /* Initialise the control line keywords (if, include, define, etc)
- Although the lexical analyzer treats them as identifiers, the
- control line handler can recognize them as keywords by the
- id_resmac field of the identifier.
- */
- {
- register struct mkey *mk = &mkey[0];
-
- while (mk->mk_reserved) {
- register struct idf *idf = str2idf(mk->mk_reserved, 0);
-
- if (idf->id_resmac)
- fatal("maximum identifier length insufficient");
- idf->id_resmac = mk->mk_key;
- mk++;
- }
- }
-
- /* Initialize __LINE__, __FILE__, __DATE__, __TIME__,
- and __STDC__ macro definitions.
- */
- clock = time(NULL);
- tp = localtime(&clock);
-
- /* __DATE__ */
- sprint(dbuf, "\"%s %02d %d\"", months[tp->tm_mon],
- tp->tm_mday, tp->tm_year+1900);
- if (tp->tm_mday < 10) dbuf[5] = ' '; /* hack */
- macro_def(str2idf("__DATE__", 0), dbuf, -1, strlen(dbuf), NOUNDEF);
-
- /* __TIME__ */
- sprint(tbuf, "\"%02d:%02d:%02d\"", tp->tm_hour, tp->tm_min, tp->tm_sec);
- macro_def(str2idf("__TIME__", 0), tbuf, -1, strlen(tbuf), NOUNDEF);
-
- /* __LINE__ */
- macro_def(str2idf("__LINE__", 0), "0", -1, 1, NOUNDEF | FUNC);
-
- /* __FILE__ */
- macro_def(str2idf("__FILE__", 0), "", -1, 1, NOUNDEF | FUNC);
-
- /* __STDC__ */
- macro_def(str2idf("__STDC__", 0), "1", -1, 1, NOUNDEF);
-
- /* defined(??) */
- macro_def(str2idf("defined", 0), "", 1, 1, NOUNDEF | FUNC);
-}
-#endif /* NOPP */
#include <inp_pkg.body>
#include <alloc.h>
-#ifndef NOPP
-#ifdef DBSYMTAB
-#include <stb.h>
-#include <em.h>
-extern int IncludeLevel;
-extern char options[];
-#endif
-
-char *
-getwdir(fn)
- register char *fn;
-{
- register char *p;
- char *strrchr();
-
- p = strrchr(fn, '/');
- while (p && *(p + 1) == '\0') { /* remove trailing /'s */
- *p = '\0';
- p = strrchr(fn, '/');
- }
-
- if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
- return "";
- if (p) {
- *p = '\0';
- fn = Salloc(fn,(unsigned) (p - &fn[0] + 1));
- *p = '/';
- return fn;
- }
- return "";
-}
-
-int InputLevel;
-extern int nestlevel;
-#endif /* NOPP */
-
int NoUnstack;
AtEoIT()
{
-#ifndef NOPP
- InputLevel--;
- unstackrepl();
-#endif /* NOPP */
return 0;
}
AtEoIF()
{
-#ifndef NOPP
- if (nestlevel != nestlow) lexwarning("missing #endif");
- else
-#endif /* NOPP */
if (NoUnstack) lexerror("unexpected EOF");
-#ifndef NOPP
- nestlevel = nestlow;
-#ifdef DBSYMTAB
- if (options['g'] && IncludeLevel > 0) {
- C_ms_stb_cst(FileName, N_EINCL, 0, (arith) 0);
- }
- IncludeLevel--;
-#endif
- /* We don't free WorkingDir and FileName here because the rest of the
- * compiler may be holding pointers to them for displaying error messages.
- */
-#endif /* NOPP */
return 0;
}
/* PREPROCESSOR: DEFINITION OF MACRO DESCRIPTOR */
#include "parameters.h"
-
-#ifndef NOPP
-/* The flags of the mc_flag field of the macro structure. Note that
- these flags can be set simultaneously.
-*/
-#define NOFLAG 0 /* no special flags */
-#define FUNC 0x1 /* function attached */
-#define NOUNDEF 0x2 /* reserved macro */
-#define NOREPLACE 0x4 /* prevent recursion */
-
-#define FORMALP 0200 /* mask for creating macro formal parameter */
-
-/* The macro descriptor is very simple, except the fact that the
- mc_text, which points to the replacement text, contains the
- non-ascii characters \201, \202, etc, indicating the position of a
- formal parameter in this text.
-*/
-struct macro {
- struct macro *next;
- char * mc_text; /* the replacement text */
- int mc_nps; /* number of formal parameters */
- int mc_length; /* length of replacement text */
- char mc_flag; /* marking this macro */
-};
-
-/* ALLOCDEF "macro" 20 */
-
-/* `token' numbers of keywords of command-line processor
-*/
-#define K_UNKNOWN 0
-#define K_DEFINE 1
-#define K_ELIF 2
-#define K_ELSE 3
-#define K_ENDIF 4
-#define K_ERROR 5
-#define K_IF 6
-#define K_IFDEF 7
-#define K_IFNDEF 8
-#define K_INCLUDE 9
-#define K_LINE 10
-#define K_PRAGMA 11
-#define K_UNDEF 12
-#define K_FILE 100 /* for dependency generator */
-#endif /* NOPP */
extern char *symbol2str();
extern char options[128];
-#ifndef NOPP
-int inc_pos = 1; /* place where next -I goes */
-int inc_total = 0;
-int inc_max;
-char **inctable;
-
-extern int do_dependencies;
-extern char *dep_file;
-static File *dep_fd = STDOUT;
-
-extern char *getwdir();
-#endif /* NOPP */
-
struct sp_id special_ids[] = {
{"__setjmp", SP_SETJMP}, /* non-local goto's are registered */
{0, 0}
union_align = AL_UNION;
#endif /* NOCROSS */
-#ifndef NOPP
-arith ifval; /* ifval will contain the result of the #if expression */
-#endif /* NOPP */
-
char *prog_name;
main(argc, argv)
/* parse and interpret the command line options */
prog_name = argv[0];
-#ifndef NOPP
- inctable = (char **) Malloc(10 * sizeof(char *));
- inctable[0] = "";
- inctable[1] = 0;
- inctable[2] = 0;
- inc_total = 3;
- inc_max = 10;
-
- init_pp(); /* initialise the preprocessor macros */
-#endif /* NOPP */
-
/* Note: source file "-" indicates that the source is supplied
as standard input. This is only allowed if INP_READ_IN_ONE is
not defined!
if (options['m']) Info();
#endif /* DEBUG */
-#ifndef NOPP
- if (do_dependencies) {
- extern char *source;
-
- list_dependencies(source);
- }
-#endif
sys_stop(err_occurred ? S_EXIT : S_END);
/*NOTREACHED*/
}
-#ifndef NOPP
-
-struct dependency *file_head;
-extern char *strrchr();
-
-list_dependencies(source)
-char *source;
-{
- register struct dependency *p = file_head;
-
- if (source) {
- register char *s = strrchr(source, '.');
-
- if (s && *(s+1)) {
- s++;
- *s++ = 'o';
- *s = '\0';
- /* the source may be in another directory than the
- * object generated, so don't include the pathname
- * leading to it.
- */
- if (s = strrchr(source, '/')) {
- source = s + 1;
- }
- }
- else source = 0;
- }
- if (dep_file && !sys_open(dep_file, OP_WRITE, &dep_fd)) {
- fatal("could not open %s", dep_file);
- }
- while (p) {
- dependency(p->dep_idf->id_text, source);
- p = p->next;
- }
-}
-
-add_dependency(s)
-char *s;
-{
- register struct idf *p = str2idf(s, 1);
-
- if (! p->id_resmac) {
- register struct dependency *q = new_dependency();
-
- p->id_resmac = K_FILE;
- q->dep_idf = p;
- q->next = file_head;
- file_head = q;
- }
-}
-
-void
-dependency(s, source)
-char *s, *source;
-{
- if (options['i'] && !strncmp(s, "/usr/include/", 13)) {
- return;
- }
- if (options['m'] && source) {
- fprint(dep_fd, "%s: %s\n", source, s);
- }
- else fprint(dep_fd, "%s\n", s);
-}
-
-#endif /* NOPP */
-
char *source = 0;
#ifdef GEN_NM_LIST
register char *destination = 0;
#endif /* LINT */
-#ifdef DEBUG
-#ifndef NOPP
- int pp_only = options['E'] || options['P'] || options['C'];
-#endif /* NOPP */
-#endif
-
switch (argc) {
case 1:
#ifndef LINT
#ifdef DEBUG
-#ifndef NOPP
- if (!pp_only)
-#endif /* NOPP */
#endif
fatal("%s: destination file not specified", prog_name);
#endif /* LINT */
: 0);
#endif /* LINT */
-#ifndef NOPP
- WorkingDir = getwdir(source);
- PushLex(); /* initialize lex machine */
-#else /* NOPP */
GetToken(&ahead);
-#endif /* NOPP */
-
-#ifdef DEBUG
-#ifndef NOPP
- if (pp_only) /* run the preprocessor as if it is stand-alone */
- preprocess();
- else
-#endif /* NOPP */
-#endif /* DEBUG */
{
/* compile the source text */
C_program();
dumpidftab("end of main", options['f'] ? 7 : 0);
#endif /* DEBUG */
}
-#ifndef NOPP
- PopLex();
-#endif /* NOPP */
}
init()
}
#ifdef DEBUG
-#ifndef NOPP
-preprocess()
-{
- /* preprocess() is the "stand-alone" preprocessor which
- consecutively calls the lexical analyzer LLlex() to get
- the tokens and prints them in a suitable way.
- */
- static unsigned int lastlineno = 0;
- static char *lastfilenm = "";
-
- while (LLlex() != EOI) {
- if (lastlineno != dot.tk_line) {
- if (strcmp(lastfilenm, dot.tk_file) == 0) {
- if (dot.tk_line - lastlineno <= 1) {
- lastlineno++;
- print("\n");
- }
- else {
- lastlineno = dot.tk_line;
- if (!options['P'])
- print("\n#line %ld \"%s\"\n",
- lastlineno,
- lastfilenm
- );
- }
- }
- else {
- lastfilenm = dot.tk_file;
- lastlineno = dot.tk_line;
- if (!options['P'])
- print("\n#line %ld \"%s\"\n",
- lastlineno, lastfilenm);
- }
- }
- else
- if (strcmp(lastfilenm, dot.tk_file) != 0) {
- lastfilenm = dot.tk_file;
- if (!options['P'])
- print("\n#line %ld \"%s\"\n",
- lastlineno, lastfilenm);
- }
- switch (DOT) {
- case IDENTIFIER:
- case TYPE_IDENTIFIER:
- print("%s ", dot.tk_idf->id_text);
- break;
- case STRING:
- {
- char sbuf[1024]; /* a transient buffer */
-
- print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len -
- 1, sbuf));
- break;
- }
- case INTEGER:
- print("%ld ", dot.tk_ival);
- break;
- case FLOATING:
- print("%s ", dot.tk_fval);
- break;
- case EOI:
- case EOF:
- return;
- default: /* very expensive... */
- print("%s ", symbol2str(DOT));
- }
- }
-}
-#endif /* NOPP */
-
Info()
{
extern int cnt_string_cst, cnt_formal,
#include "sizes.h"
#include "align.h"
-#ifndef NOPP
-extern char **inctable;
-extern int inc_pos;
-extern int inc_max;
-extern int inc_total;
-int do_dependencies = 0;
-char *dep_file = 0;
-
-#endif /* NOPP */
-
char options[128]; /* one for every char */
#ifdef LINT
char loptions[128]; /* one for every char */
goto next_option;
#ifndef LINT
-#ifndef NOPP
- case 'A' : /* Amake dependency generation */
- do_dependencies = 1;
- if (*text) {
- dep_file = text;
- }
- break;
- case 'i':
- case 'm':
- options[opt] = 1;
- break;
-#endif /* NOPP */
#endif /* LINT */
#ifdef DBSYMTAB
case 'g': /* symbol table for debugger */
goto next_option;
#endif /* LINT */
-#ifndef NOPP
- case 'D' : { /* -Dname : predefine name */
- register char *cp = text, *name, *mactext;
- unsigned maclen;
-
- if (class(*cp) != STIDF && class(*cp) != STELL) {
- error("identifier missing in -D%s", text);
- break;
- }
-
- name = cp;
-
- while (*cp && in_idf(*cp)) {
- ++cp;
- }
-
- if (!*cp) { /* -Dname */
- maclen = 1;
- mactext = Salloc("1", 2);
- }
- else
- if (*cp == '=') { /* -Dname=text */
- *cp++ = '\0'; /* end of name */
- maclen = (unsigned) strlen(cp);
- mactext = Salloc(cp, maclen + 1);
- }
- else { /* -Dname?? */
- error("malformed option -D%s", text);
- break;
- }
-
- macro_def(str2idf(name, 0), mactext, -1, (int)maclen, NOFLAG);
- break;
- }
-
- case 'I' : /* -Ipath : insert "path" into include list */
- if (*text) {
- int i;
- register char *new = text;
-
- if (inc_total >= inc_max) {
- inctable = (char **)
- Realloc((char *)inctable,
- (unsigned)((inc_max+=10)*sizeof(char *)));
- }
-
- for (i = inc_pos++; i < inc_total ; i++) {
- char *tmp = inctable[i];
-
- inctable[i] = new;
- new = tmp;
- }
- inc_total++;
- }
- else inctable[inc_pos] = 0;
- break;
-#endif /* NOPP */
-
case 'M': /* maximum identifier length */
idfsize = txt2int(&text);
if (*text || idfsize <= 0)
break;
}
-#ifndef NOPP
- case 'U' : /* -Uname : undefine predefined */
- if (*text) do_undef(str2idf(text, 0));
- break;
-#endif /* NOPP */
-
#ifndef LINT
#ifndef NOCROSS
case 'V' : /* set object sizes and alignment requirements */
#include "l_lint.h"
#endif /* LINT */
-#ifndef NOPP
-extern arith ifval;
-#endif /* NOPP */
-
extern error();
}
:
constant_expression(&exprX)
{
-#ifndef NOPP
- register struct expr *expr = exprX;
- if (expr->ex_flags & EX_SIZEOF)
- expr_error(expr,
- "sizeof not allowed in preprocessor");
- ifval = expr->VL_VALUE;
- free_expression(expr);
-#endif /* NOPP */
}
;
+++ /dev/null
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
-/* $Id$ */
-/* M A C R O R E P L A C E M E N T */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "parameters.h"
-
-#ifndef NOPP
-
-#include <ack_string.h>
-#include <alloc.h>
-#include "idf.h"
-#include "input.h"
-#include "macro.h"
-#include "arith.h"
-#include "LLlex.h"
-#include "class.h"
-#include "replace.h"
-
-extern struct idf *GetIdentifier();
-extern int InputLevel;
-struct repl *ReplaceList; /* list of currently active macros */
-
-void macro2buffer();
-void getactuals();
-void expand_defined();
-
-int
-replace(idf)
- register struct idf *idf;
-{
- /* replace is called by the lexical analyzer to perform
- macro replacement. The routine actualy functions as a
- higher interface to the real thing: expand_macro().
- */
- struct repl *repl;
-
- if (!(idf->id_macro)) return 0;
- if (idf->id_macro->mc_flag & NOREPLACE)
- return 0;
- repl = new_repl();
- repl->r_ptr = repl->r_text = Malloc(repl->r_size = LAPBUF);
- repl->r_args = new_args();
- repl->r_idf = idf;
- if (!expand_macro(repl, idf))
- return 0;
- InputLevel++;
- InsertText(repl->r_text, (int)(repl->r_ptr - repl->r_text));
- idf->id_macro->mc_flag |= NOREPLACE;
- repl->r_level = InputLevel;
- repl->next = ReplaceList;
- ReplaceList = repl;
- return 1;
-}
-
-unstackrepl()
-{
- Unstacked++;
-}
-
-freeargs(args)
- struct args *args;
-{
- register int i;
-
- /* We must don't know how many parameters were specified, so be
- * prepared to free all NPARAMS parameters.
- * When an expvec is !0, the rawvec will also be !0.
- * When an expvec is 0, all remaining vectors will also be 0.
- */
- for (i = 0; i < NPARAMS; i++) {
- if (args->a_expvec[i]) {
- free(args->a_expvec[i]);
- free(args->a_rawvec[i]);
- } else break;
- }
- free_args(args);
-}
-
-EnableMacros()
-{
- register struct repl *r = ReplaceList, *prev = 0;
-
- assert(Unstacked > 0);
- while(r) {
- struct repl *nxt = r->next;
-
- if (r->r_level > InputLevel) {
- r->r_idf->id_macro->mc_flag &= ~NOREPLACE;
- if (!prev) ReplaceList = nxt;
- else prev->next = nxt;
- free(r->r_text);
- freeargs(r->r_args);
- free_repl(r);
- }
- else prev = r;
- r = nxt;
- }
- Unstacked = 0;
-}
-
-expand_macro(repl, idf)
- register struct repl *repl;
- register struct idf *idf;
-{
- /* expand_macro() does the actual macro replacement.
- "idf" is a description of the identifier which
- caused the replacement.
- If the identifier represents a function-like macro
- call, the number of actual parameters is checked
- against the number of formal parameters. Note that
- in ANSI C the parameters are expanded first;
- this is done by calling getactuals().
- When the possible parameters are expanded, the replace-
- ment list associated with "idf" is expanded.
- expand_macro() returns 1 if the replacement succeeded
- and 0 if some error occurred.
-
- A special case is "defined". This acts as a unary operator
- on a single, unexpanded identifier, which may be surrounded
- by parenthesis. The function expand_defined() handles this.
- */
- register struct macro *mac = idf->id_macro;
- struct args *args = repl->r_args;
- register int ch;
-
- if (mac->mc_nps != -1) { /* with parameter list */
- if (mac->mc_flag & FUNC) {
- /* the following assertion won't compile:
- assert(!strcmp("defined", idf->id_text));
- expand the assert macro by hand (??? dirty, temporary)
- */
-#ifdef DEBUG
- if (strcmp("defined", idf->id_text))
- crash("in %s, %u: assertion %s failed",
- __FILE__, __LINE__ - 2,
- "strcmp(\"defined\", idf->id_text)");
-#endif
- if (!AccDefined) return 0;
- expand_defined(repl);
- return 1;
- }
-
- ch = GetChar();
- ch = skipspaces(ch,1);
- if (ch != '(') { /* no replacement if no () */
- ChPushBack(ch);
- return 0;
- } else
- getactuals(repl, idf);
-
- }
-
- if (mac->mc_flag & FUNC) /* this macro leads to special action */
- macro_func(idf);
-
- macro2buffer(repl, idf, args);
-
- /* According to the ANSI definition:
-
- #define a +
- a+b; --> + + b ;
-
- 'a' must be substituded, but the result should be
- three tokens: + + ID. Therefore a token separator is
- inserted after the replacement.
- */
- if (repl->r_text == repl->r_ptr || *(repl->r_ptr - 1) != TOKSEP) {
- add2repl(repl, TOKSEP);
- }
- return 1;
-}
-
-void
-expand_defined(repl)
- register struct repl *repl;
-{
- register int ch = GetChar();
- struct idf *id;
- int parens = 0;
-
- ch = skipspaces(ch, 0);
-
- if (ch == '(') {
- parens++;
- ch = GetChar();
- ch = skipspaces(ch, 0);
- }
- if ((class(ch) != STIDF) && (class(ch) != STELL)) {
- error("identifier missing");
- if (parens && ch != ')') error(") missing");
- if (!parens || ch != ')') ChPushBack(ch);
- add2repl(repl, '0');
- return;
- }
- ChPushBack(ch);
- id = GetIdentifier(0);
- assert(id || class(ch) == STELL);
- ch = GetChar();
- ch = skipspaces(ch, 0);
- if (parens && ch != ')') error(") missing");
- if (!parens || ch != ')') ChPushBack(ch);
- add2repl(repl, (id && id->id_macro) ? '1' : '0');
- add2repl(repl, ' ');
-}
-
-newarg(args)
- struct args *args;
-{
- args->a_expptr = args->a_expbuf = Malloc(args->a_expsize = ARGBUF);
- args->a_rawptr = args->a_rawbuf = Malloc(args->a_rawsize = ARGBUF);
-}
-
-void
-getactuals(repl, idf)
- struct repl *repl;
- register struct idf *idf;
-{
- /* Get the actual parameters from the input stream.
- The hard part is done by actual(), only comma's and
- other syntactic trivialities are checked here.
- */
- register struct args *args = repl->r_args;
- register int nps = idf->id_macro->mc_nps;
- register int argcnt;
- register int ch;
-
- argcnt = 0;
- newarg(args);
- if ((ch = GetChar()) != ')') {
- UnGetChar();
- while ((ch = actual(repl)) != ')' ) {
- if (ch != ',') {
- lexerror("illegal macro call");
- return;
- }
- stash(repl, '\0', 1);
- args->a_expvec[argcnt] = args->a_expbuf;
- args->a_rawvec[argcnt] = args->a_rawbuf;
- ++argcnt;
- if (argcnt == STDC_NPARAMS)
- lexstrict("number of parameters exceeds ANSI standard");
- if (argcnt >= NPARAMS)
- fatal("argument vector overflow");
- newarg(args);
- }
- stash(repl, '\0', 1);
- args->a_expvec[argcnt] = args->a_expbuf;
- args->a_rawvec[argcnt] = args->a_rawbuf;
- ++argcnt;
- }
- if (argcnt < nps)
- lexerror("too few macro arguments");
- else if (argcnt > nps)
- lexerror("too many macro arguments");
-}
-
-saveraw(repl)
-struct repl *repl;
-{
- register struct repl *nrepl = ReplaceList;
- register struct args *ap = nrepl->r_args;
- register char *p;
-
- /* stash identifier name */
- for (p = nrepl->r_idf->id_text; *p != '\0'; p++)
- stash(repl, *p, -1);
-
- /* The following code deals with expanded function
- like macro calls. It makes the following code
- work:
-
- #define def(a,b) x(a,b)
- #define glue(a,b) a ## b
-
- glue(abc,def(a,b))
-
- Results in:
-
- abcdef(a,b);
- */
- if (ap->a_rawvec[0]) {
- /* stash arguments */
- register int i;
-
- for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
- if (i == 0) stash(repl, '(', -1);
- else stash(repl, ',', -1);
- for (p = ap->a_rawvec[i]; *p != '\0'; p++)
- stash(repl, *p, -1);
- }
- stash(repl, ')', -1);
- }
-}
-
-int
-actual(repl)
- struct repl *repl;
-{
- /* This routine deals with the scanning of an actual parameter.
- It keeps in account the opening and closing brackets,
- preprocessor numbers, strings and character constants.
- */
- register int ch = 0;
- register int level = 0, nostashraw = 0;
- int lastch;
- static int Unstacked_missed;
-
- while (1) {
- lastch = ch;
- ch = GetChar();
-
- if (nostashraw
- && nostashraw >= Unstacked_missed) {
- nostashraw -= Unstacked_missed;
- Unstacked_missed = 0;
- }
- if (Unstacked) {
- nostashraw -= Unstacked;
- if (nostashraw < 0) {
- Unstacked_missed = -nostashraw;
- nostashraw = 0;
- }
- EnableMacros();
- }
- if (class(ch) == STIDF || class(ch) == STELL) {
- /* Scan a preprocessor identifier token. If the
- token is a macro, it is expanded first.
- */
- char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
- register char *p = buf;
- register struct idf *idef;
- register int pos = -1;
- extern int idfsize;
- int NoExpandMacro;
-
- if (ch == NOEXPM) {
- NoExpandMacro= 1;
- ch = GetChar();
- } else NoExpandMacro = 0;
-
- do {
- if (++pos < idfsize) {
- *p++ = ch;
- }
- ch = GetChar();
- } while (in_idf(ch));
- *p++ = '\0';
- ch = '\0'; /* It could be an unstashed TOKSEP */
- UnGetChar();
-
- /* When the identifier has an associated macro
- replacement list, it's expanded.
- */
- idef = findidf(buf);
- if (!idef || NoExpandMacro || !replace(idef)) {
- if (NoExpandMacro
- || (idef && idef->id_macro
- && (idef->id_macro->mc_flag & NOREPLACE)))
- stash(repl, NOEXPM, !nostashraw);
- for (p = buf; *p != '\0'; p++)
- stash(repl, *p, !nostashraw);
- } else {
- if (!nostashraw) saveraw(repl);
- nostashraw++;
- }
- } else if (class(ch) == STNUM) {
- /* a preprocessing number has the following
- regular expression:
- [0-9|"."[0-9]]{[0-9"."a-zA-Z_]|{[Ee][+-]}}*
- */
- stash(repl, ch, !nostashraw);
- if (ch == '.') {
- ch = GetChar();
- if (class(ch) != STNUM) {
- ch = '\0'; /* It could be an unstashed TOKSEP */
- UnGetChar();
- continue;
- }
- else stash(repl, ch, !nostashraw);
- }
- ch = GetChar();
- while (in_idf(ch) || ch == '.') {
- stash(repl, ch, !nostashraw);
- if ((ch = GetChar()) == 'e' || ch == 'E') {
- stash(repl, ch, !nostashraw);
- ch = GetChar();
- if (ch == '+' || ch == '-') {
- stash(repl, ch, !nostashraw);
- ch = GetChar();
- }
- }
- }
- ch = '\0'; /* It could be an unstashed TOKSEP */
- UnGetChar();
- } else if (ch == '(') {
- /* a comma may occur between parentheses */
- level++;
- stash(repl, ch, !nostashraw);
- } else if (ch == ')') {
- level--;
- /* closing parenthesis of macro call */
- if (level < 0) return ')';
- stash(repl, ch, !nostashraw);
- } else if (ch == ',') {
- if (level <= 0) { /* comma separator for next argument */
- if (level)
- lexerror("unbalanced parenthesis");
- if (!nostashraw)
- return ','; /* ??? */
- }
- stash(repl, ch, !nostashraw);
- } else if (ch == '\n') {
- /* newlines are accepted as white spaces */
- LineNumber++;
- /* This piece of code needs some explanation:
- consider the call of a macro defined as:
- #define sum(a,b) (a+b)
- in the following form:
- sum(
- /_* comment *_/ #include phone_number
- ,2);
- in which case the include must be handled
- interpreted as such.
- */
-
-a_new_line: ch = GetChar();
- while (class(ch) == STSKIP || ch == '/') {
- if (ch == '/') {
- if ((ch = GetChar()) == '*' && !InputLevel) {
- skipcomment();
- stash(repl, ' ', !nostashraw);
- ch = GetChar();
- continue;
- } else {
- UnGetChar();
- ch = '/';
- }
- stash(repl, '/', !nostashraw);
- break;
- } else ch = GetChar();
- }
-
- if (ch == '#') {
- domacro();
- /* Clear File_Inserted since domacro could
- * be called again, which calls GetToken().
- */
- File_Inserted = 0;
- goto a_new_line;
- } else if (ch == EOI) {
- lexerror("unterminated macro call");
- return ')';
- }
- if (ch != '/') {
- UnGetChar();
- ch = ' ';
- stash(repl, ' ', !nostashraw);
- }
- } else if (ch == '/') {
- /* comments are treated as one white space token */
- if ((ch = GetChar()) == '*' && !InputLevel) {
- skipcomment();
- stash(repl, ' ', !nostashraw);
- } else {
- UnGetChar();
- ch = '/';
- stash(repl, '/', !nostashraw);
- }
- } else if (ch == '\'' || ch == '"') {
- /* Strings are considered as ONE token, thus no
- replacement within strings.
- */
- register int match = ch;
-
- stash(repl, ch, !nostashraw);
- while ((ch = GetChar()) != EOI) {
- if (ch == match)
- break;
- if (ch == '\\') {
- stash(repl, ch, !nostashraw);
- ch = GetChar();
- } else if (ch == '\n') {
- lexerror("newline in string");
- LineNumber++;
- stash(repl, match, !nostashraw);
- break;
- }
- stash(repl, ch, !nostashraw);
- }
- if (ch != match) {
- lexerror("unterminated macro call");
- return ')';
- }
- stash(repl, ch, !nostashraw);
- } else {
- if (lastch == TOKSEP && ch == TOKSEP) continue;
- stash(repl, ch, !nostashraw);
- }
- }
-}
-
-macro_func(idef)
- register struct idf *idef;
-{
- /* macro_func() performs the special actions needed with some
- macros. These macros are __FILE__ and __LINE__ which
- replacement texts must be evaluated at the time they are
- used.
- */
- register struct macro *mac = idef->id_macro;
- static char FilNamBuf[PATHLENGTH];
-
- switch (idef->id_text[2]) {
- case 'F': /* __FILE__ */
- FilNamBuf[0] = '"';
- strcpy(&FilNamBuf[1], FileName);
- strcat(FilNamBuf, "\"");
- mac->mc_text = FilNamBuf;
- mac->mc_length = strlen(FilNamBuf);
- break;
- case 'L': /* __LINE__ */
- mac->mc_text = long2str((long)LineNumber, 10);
- mac->mc_length = strlen(mac->mc_text);
- break;
- default:
- crash("(macro_func)");
- /*NOTREACHED*/
- }
-}
-
-void
-macro2buffer(repl, idf, args)
- register struct repl *repl;
- register struct idf *idf;
- register struct args *args;
-{
- /* macro2buffer expands the replacement list and places the
- result onto the replacement buffer. It deals with the #
- and ## operators, and inserts the actual parameters.
- The argument buffer contains the raw argument (needed
- for the ## operator), and the expanded argument (for
- all other parameter substitutions).
-
- The grammar of the replacement list is:
-
- repl_list: TOKEN repl_list
- | PARAMETER repl_list
- | '#' PARAMETER
- | TOKEN '##' TOKEN
- | PARAMETER '##' TOKEN
- | TOKEN '##' PARAMETER
- | PARAMETER '##' PARAMETER
- ;
-
- As the grammar indicates, we could make a DFA and
- use this finite state machine for the replacement
- list parsing (inserting the arguments, etc.).
-
- Currently we go through the replacement list in a
- linear fashion. This is VERY expensive, something
- smarter should be done (but even a DFA is O(|s|)).
- */
- register char *ptr = idf->id_macro->mc_text;
- int err = 0;
- int func = idf->id_macro->mc_nps != -1;
- char *stringify();
-
- assert(ptr[idf->id_macro->mc_length] == '\0');
- while (*ptr) {
- if (*ptr == '\'' || *ptr == '"') {
- register int delim = *ptr;
-
- do {
- add2repl(repl, *ptr);
- if (*ptr == '\\')
- add2repl(repl, *++ptr);
- if (*ptr == '\0') {
- lexerror("unterminated string");
- return;
- }
- ptr++;
- } while (*ptr != delim || *ptr == '\0');
- add2repl(repl, *ptr++);
- } else if (*ptr == '#' && (func || *(ptr+1) == '#')) {
- if (*++ptr == '#') {
- register int tmpindex;
- /* ## - paste operator */
- ptr++;
-
- /* trim the actual replacement list */
- --repl->r_ptr;
- while (repl->r_ptr >= repl->r_text
- && is_wsp(*repl->r_ptr))
- --repl->r_ptr;
-
- /* ## occurred at the beginning of the replacement list.
- */
- if (repl->r_ptr < repl->r_text) {
- err = 1;
- break;
- }
-
- if (repl->r_ptr >= repl->r_text
- && *repl->r_ptr == TOKSEP)
- --repl->r_ptr;
-
- ++repl->r_ptr;
- tmpindex = repl->r_ptr - repl->r_text;
- /* tmpindex can be 0 */
-
- /* skip space in macro replacement list */
- while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
- ptr++;
-
- /* ## occurred at the end of the replacement list.
- */
- if (*ptr & FORMALP) {
- register int n = *ptr++ & 0177;
- register char *p;
-
- assert(n > 0);
- p = args->a_rawvec[n-1];
- if (p) { /* else macro argument missing */
- while (is_wsp(*p)) p++;
- if (*p == NOEXPM) p++;
- while (*p)
- add2repl(repl, *p++);
- }
- while (tmpindex > 0
- && in_idf(repl->r_text[tmpindex]))
- tmpindex--;
- if (tmpindex >= 0
- && repl->r_text[tmpindex] == NOEXPM)
- repl->r_text[tmpindex] = TOKSEP;
- } else if (*ptr == '\0') {
- err = 1;
- break;
- } else {
- if (in_idf(*ptr)) {
- tmpindex--;
- while (tmpindex > 0
- && in_idf(repl->r_text[tmpindex]))
- tmpindex--;
- if (tmpindex >= 0
- && repl->r_text[tmpindex] == NOEXPM)
- repl->r_text[tmpindex] = TOKSEP;
- }
- }
- } else { /* # operator */
- ptr = stringify(repl, ptr, args);
- }
- } else if (*ptr & FORMALP) {
- /* insert actual parameter */
- register int n = *ptr++ & 0177;
- register char *p, *q;
-
- assert(n > 0);
-
- /* This is VERY dirty, we look ahead for the
- ## operator. If it's found we use the raw
- argument buffer instead of the expanded
- one.
- */
- for (p = ptr; (*p & FORMALP) == 0 && is_wsp(*p); p++)
- /* EMPTY */;
- if (*p == '#' && p[1] == '#')
- q = args->a_rawvec[n-1];
- else
- q = args->a_expvec[n-1];
-
- if (q) /* else macro argument missing */
- while (*q)
- add2repl(repl, *q++);
-
- if (repl->r_text == repl->r_ptr || *(repl->r_ptr - 1) != TOKSEP)
- add2repl(repl, TOKSEP);
- } else {
- add2repl(repl, *ptr++);
- }
- }
- if (err)
- lexerror("illegal use of the ## operator");
-}
-
-char *
-stringify(repl, ptr, args)
- register struct repl *repl;
- register char *ptr;
- register struct args *args;
-{
- /* If a parameter is immediately preceded by a # token
- both are replaced by a single string literal that
- contains the spelling of the token sequence for the
- corresponding argument.
- Each occurrence of white space between the argument's
- tokens become a single space character in the string
- literal. White spaces before the first token and after
- the last token comprising the argument are deleted.
- To retain the original spelling we insert backslashes
- as appropriate. We only escape backslashes if they
- occure within string tokens.
- */
- register int space = 1; /* skip leading spaces */
- register int delim = 0; /* string or character constant delim */
- register int backslash = 0; /* last character was a \ */
-
- /* skip spaces macro replacement list */
- while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
- ptr++;
-
- if (*ptr & FORMALP) {
- register int n = *ptr++ & 0177;
- register char *p;
-
- assert(n != 0);
- p = args->a_rawvec[n-1];
- add2repl(repl, '"');
- while (*p) {
- if (is_wsp(*p)) {
- if (!space) {
- space = 1;
- add2repl(repl, ' ');
- }
- p++;
- continue;
- }
- space = 0;
-
- if (!delim && (*p == '"' || *p == '\''))
- delim = *p;
- else if (*p == delim && !backslash)
- delim = 0;
- backslash = *p == '\\';
- if (*p == '"' || (delim && *p == '\\'))
- add2repl(repl, '\\');
- if (*p == TOKSEP || *p == NOEXPM) p++;
- else add2repl(repl, *p++);
- }
-
- /* trim spaces in the replacement list */
- for (--repl->r_ptr; is_wsp(*repl->r_ptr); repl->r_ptr--)
- /* EMPTY */;
- ++repl->r_ptr; /* oops, one to far */
- add2repl(repl, '"');
- } else
- error("illegal use of # operator");
- return ptr;
-}
-
-/* The following routine is also called from domacro.c.
- */
-add2repl(repl, ch)
- register struct repl *repl;
- int ch;
-{
- register int index = repl->r_ptr - repl->r_text;
-
- assert(index < repl->r_size);
- if (index + 2 >= repl->r_size) {
- repl->r_text = Realloc(repl->r_text, (unsigned) (repl->r_size <<= 1));
- repl->r_ptr = repl->r_text + index;
- }
- *repl->r_ptr++ = ch;
- *repl->r_ptr = '\0';
-}
-
-/* If the variable stashraw is negative, we must only stash into the raw
- * buffer. If the variable is zero, we must only stash into the expanded
- * buffer. Otherwise, we must use both buffers.
- */
-stash(repl, ch, stashraw)
- struct repl *repl;
- register int ch;
- int stashraw;
-{
- /* Stash characters into the macro expansion buffer.
- */
- register struct args *args = repl->r_args;
- register int index = args->a_expptr - args->a_expbuf;
-
- if (stashraw >= 0) {
- assert(index < args->a_expsize);
- if (index + 1 >= args->a_expsize) {
- args->a_expbuf = Realloc(args->a_expbuf,
- (unsigned) (args->a_expsize <<= 1));
- args->a_expptr = args->a_expbuf + index;
- }
- *args->a_expptr++ = ch;
- }
-
- if (stashraw) {
- index = args->a_rawptr - args->a_rawbuf;
- assert(index < args->a_rawsize);
- if (index + 1 >= args->a_rawsize) {
- args->a_rawbuf = Realloc(args->a_rawbuf,
- (unsigned)(args->a_rawsize <<= 1));
- args->a_rawptr = args->a_rawbuf + index;
- }
- *args->a_rawptr++ = ch;
- }
-}
-#endif /* NOPP */
+++ /dev/null
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
-/* $Id$ */
-/* DEFINITIONS FOR THE MACRO REPLACEMENT ROUTINES */
-
-struct repl {
- struct repl *next;
- struct idf *r_idf; /* name of the macro */
- struct args *r_args; /* replacement parameters */
- int r_level; /* level of insertion */
- int r_size; /* current size of replacement buffer */
- char *r_ptr; /* replacement text index pointer */
- char *r_text; /* replacement text */
-};
-
-/* ALLOCDEF "repl" 4 */
-
-#define NO_REPL (struct repl *)0
-
-/* The implementation of the ## operator is currently very clumsy.
- When the the ## operator is used the arguments are taken from
- the raw buffer; this buffer contains a precise copy of the
- original argument. The fully expanded copy is in the arg buffer.
- The two copies are here explicitely because:
-
- #define ABC f()
- #define ABCD 2
- #define g(x, y) x ## y + h(x)
-
- g(ABC, D); // gives: 2 + h(f())
-
- In this case we need two copies: one raw copy for the pasting
- operator, and an expanded one as argument for h().
-*/
-struct args {
- char *a_expptr; /* expanded argument index pointer */
- char *a_expbuf; /* expanded argument buffer pointer */
- int a_expsize; /* current size of expanded buffer */
- char *a_expvec[NPARAMS]; /* expanded argument vector */
- char *a_rawptr; /* raw argument index pointer */
- char *a_rawbuf; /* raw argument buffer pointer */
- int a_rawsize; /* current size of raw buffer */
- char *a_rawvec[NPARAMS]; /* raw argument vector */
-};
-
-/* ALLOCDEF "args" 2 */
-
-#define NO_ARGS (struct args *)0
-
#include "class.h"
#include "input.h"
-#ifndef NOPP
-extern int InputLevel;
-
-int skipspaces(ch, skipnl) register int ch;
-{
- /* skipspaces() skips any white space and returns the first
- non-space character.
- */
- register int nlseen = 0;
-
- for (;;)
- {
- while (class(ch) == STSKIP)
- ch = GetChar();
- if (skipnl && class(ch) == STNL)
- {
- ch = GetChar();
- LineNumber++;
- nlseen++;
- continue;
- }
- if (ch == TOKSEP && InputLevel)
- {
- ch = GetChar();
- continue;
- }
-
- /* \\\n are handled by trigraph */
-
- if (ch == '/')
- {
- ch = GetChar();
- if (ch == '*' && !InputLevel)
- {
- skipcomment();
- ch = GetChar();
- }
- else if (ch == '/' && !InputLevel)
- {
- skiplinecomment();
- ch = GetChar();
- }
- else
- {
- UnGetChar();
- return '/';
- }
- }
- else if (nlseen && ch == '#')
- {
- domacro();
- ch = GetChar();
- }
- else
- return ch;
- }
-}
-#endif /* NOPP */
SkipToNewLine()
{
register int ch;
register int garbage = 0;
-#ifndef NOPP
- register int delim = 0;
-#endif
while ((ch = GetChar()) != '\n')
{
-#ifndef NOPP
- if (delim)
- {
- if (ch == '\\')
- {
- if (GetChar() == '\n')
- break;
- }
- else if (ch == delim)
- {
- delim = 0;
- }
- continue;
- }
- else if (ch == '\'' || ch == '\"')
- {
- delim = ch;
- garbage = 1;
- }
- else if (ch == '/')
- {
- if (!InputLevel)
- {
- int nch = GetChar();
- if (nch == '*')
- {
- skipcomment();
- continue;
- }
- else if (nch == '/')
- {
- skiplinecomment();
- continue;
- }
- else
- UnGetChar();
- }
- }
- else if (ch == TOKSEP && InputLevel)
- {
- continue;
- }
-#endif
if (!is_wsp(ch))
garbage = 1;
}
-#ifndef NOPP
- if (delim)
- strict("unclosed opening %c", delim);
-#endif
++LineNumber;
return garbage;
}