📄 ccpp.c
字号:
pushch(ch);
ch = '\r'; /* put back and drop through */
}
case '\v':
case '\f':
if (indirp) /* Processing directive between # and EOL? */
{
error("invalid whitespace in directive: '\\%#o'", ch);
nextch();
return rawpp = T_EOL;
}
continue;
case '/': /* Possible comment! */
if (nextch() == '*')
{
scancomm (); /* Yep, flush comment */
continue; /* and go get next char after comment */
}
/* KAR-2/93, PPS 4574; C++ comments */
else if (ch == '/' && !clevnocpp)
{
comment_type = CPP;
scancomm ();
pushch (ch); /* FW 2A(50) September 1993*/
comment_type = C;
continue;
}
/* Ugh, not a comment, must back up and leave '/' there */
pushch (ch); /* Push '*' back */
ch = '/';
break;
default:
break; /* do nothing */
}
break;
}
return rawpp = T_WSP;
}
/* SCANCOMM - Skips over a comment; current char must be the '*' opening
** a comment. On return, current char is the '/' closing the
** comment (or EOF).
*/
static
void
scancomm (void)
{
scanning_comment = 1;
for (;;)
{
switch (nextch())
{
case EOF:
error("Unexpected EOF in comment");
break; /* Get out of loop */
/* KAR-2/93, PPS 4574; C++ comments */
case '\n':
if (comment_type == CPP)
break;
else
continue;
case '/': /* Special helpful check */
do
{
if (nextch() == '*')
{
advise("Nested comment");
break;
}
}
while (ch == '/');
if (ch != '*') continue;
/* Drop thru to handle the * we just got */
case '*':
while (nextch() == '*') ; /* Skip all '*'s */
if (ch == '/')
break; /* End of comment, stop! */
default:
continue; /* Not ended yet */
}
break; /* Break from switch is break from loop */
}
scanning_comment = 0;
}
/* Various preprocessor token parsing routines. */
/* PPNCONST - Parse a pp-number, starting with char in "ch", unless
** arg is non-zero in which case arg is the 1st char, "ch" the 2nd.
** This only happens if the first char was '.', ie a floating constant.
*/
static
int
ppnconst(ch1)
{
static int hexconst;
hexconst = 0; /* Set kludge flag */
rawval.cp = ppcbeg(); /* Get ptr into char pool */
if (ch1)
{
ppcput(ch1);
rawpp = T_FCONST; /* Aha, float const */
}
else
rawpp = T_ICONST; /* Assume integer until detect otherwise */
ppcput(ch);
for (;; ppcput(ch))
{
switch (nextch())
{
case 'x':
case 'X': /* Remember if hex constant */
if (ppclen() == 1 && ppclast() == '0')
++hexconst;
continue;
case 'E':
case 'e': /* 'E' means float const, */
if (!hexconst) /* unless already hex const! */
case '.':
rawpp = T_FCONST; /* Remember float const */
continue;
case '-':
case '+': /* If prev char not 'E' or 'e', stop now */
if (toupper(ppclast()) != 'E')
break;
continue;
default:
if (!iscsym(ch)) /* Any identifier char (BARF BARF) */
break;
continue;
}
break; /* Break from switch is break from loop */
}
rawpplen = ppcend(); /* Done with string */
return rawpp; /* Return either T_ICONST or T_FCONST */
}
/* PPSCONST - Parse a string literal or char constant, starting with char
** in "ch", unless
** arg is non-zero in which case arg is the 1st char, "ch" the 2nd.
** "ch" will always contain '\"' or '\'' to indicate type of constant.
** Note no token value is set or returned; the caller must do this.
*/
static
void
ppsconst(ch1)
{
int delim = ch; /* Remember delimiter we're using */
rawval.cp = ppcbeg(); /* Get ptr into char pool */
if (ch1) ppcput(ch1);
ppcput(ch);
for (;; ppcput(ch))
{
switch (nextch())
{
case EOF:
case '\n':
break;
case '\\': /* Escape (just treat as quoter) */
ppcput(ch);
switch (nextch())
{
case EOF:
case '\n':
break;
default:
continue;
}
break;
default:
if (ch != delim)
continue;
ppcput(delim); /* Succeeded! */
rawpplen = ppcend(); /* Done with string */
nextch(); /* Advance past delimiter */
return; /* Done, return */
}
break; /* Break from switch is break from loop */
}
/* Stopped because hit erroneous char. Fix up and barf about it. */
ppcput(delim); /* Ensure token is well-formed */
rawpplen = ppcend(); /* Finish off string */
error("%s in %s",
(ch=='\n' ? "EOL" : (ch==EOF ? "EOF" : "Illegal char")),
(delim=='\'' ? "char constant"
: (delim=='\"' ? "string literal"
: "quoted identifier")));
}
/* PPUNKNWN - "Parse" the unknown char in "ch" into a T_UNKNWN token.
*/
static
int
ppunknwn()
{
rawval.cp = ppcbeg(); /* Get ptr into char pool */
ppcput(ch);
nextch(); /* Consume it, get next */
rawpplen = ppcend(); /* Done with string */
return rawpp = T_UNKNWN;
}
static
void // FW KCC-NT
pptresize()
{
static struct pptlist_s
{
PPTOK *pptblock;
struct pptlist_s
*pptnext;
}
pptfirst, *pptcurr = NULL;
if (pptoks == NULL)
{
if (pptcurr == NULL) /* if NOT pptreset() */
/* First call to pptresize() */
{
pptfirst.pptblock =(PPTOK *) calloc (1, DYN_SIZE * sizeof(PPTOK));
pptfirst.pptnext = NULL;
}
pptcurr = &pptfirst; /* init pptcurr for first pptblock */
}
else if (pptcurr->pptnext == NULL) /* init another pptblock */
{
pptcurr = pptcurr->pptnext =
(struct pptlist_s
*) calloc (1, sizeof(struct pptlist_s
));
pptcurr->pptblock = (PPTOK *) calloc (1, DYN_SIZE * sizeof(PPTOK));
pptcurr->pptnext = NULL;
}
else /* reuse a pptblock */
pptcurr = pptcurr->pptnext;
if (pptcurr == NULL || pptcurr->pptblock == NULL ||
pptfirst.pptblock == NULL)
efatal("Out of memory, preprocessor token table overflow");
pptptr = pptoks = pptcurr->pptblock;
pptmax = &pptoks[DYN_SIZE - 1];
}
static
int
ppcresize()
{
#if 0 /* 5/91 Dynamic tables, ppcresize() was ppcerror() */
ptrdiff_t offset = ppcptr - ppcpool;
ppcpool = (char *) realloc (ppcpool, ppcsize * DYN_SIZE * sizeof(char));
ppcleft += DYN_SIZE * sizeof(char);
ppcptr = (char *) ((ptrdiff_t) ppcpool + offset);
++ppcsize;
if (ppcpool == NULL)
#endif
{
efatal("Preprocessor token char pool overflow");
return -1; /* simulate error (number of remaining chars) */
}
}
/* Translation Phase 4 - directive & macro expansion handling
** If a current token list exists (curtl), uses that; all tokens on
** that list are "cooked" and no longer subject to macro expansion.
** Returns curpp after setting all current stuff.
*/
int
nextpp (void)
{
if ((curptr = curtl.tl_head) != NULL) /* If using token list, */
{
curpp = curptr->pt_typ; /* consume first token on it */
curval = curptr->pt_val;
if (tlpskip(curtl) == NULL)
{
/* Token list ran out. Clean up for next call. */
tlzinit(curtl); /* No active cooked token list */
pptreset(); /* Free all tokens (curptr still OK) */
if (inasm) /* If in #asm, refill token list */
return curtl = asmrefill(), nextpp();
}
return (curpp != T_IDENT) ? curpp : findident();
}
/* Get a new token from input */
ppcreset(); /* Free all token string storage */
if (nextrawpp() == T_EOL) /* At EOL must start directive scan */
{
while (tskiplwsp()==T_SHARP) /* Get 1st non-wsp token */
{
directive(); /* Handle directive! */
if (curtl.tl_head) /* If it set up a cooked list, */
return nextpp(); /* get input from that. */
}
}
curval = rawval;
return ((curpp = rawpp) != T_IDENT) ? curpp : findident();
}
/* PUSHPP() - push back current token.
** So far, only needed by one call in CCLEX.
*/
void
pushpp()
{
if (curptr) /* If current token is from list, */
tlpins(curtl, curptr); /* backup is trivial! */
else /* If current token not from a list, must fake one up -- barf. */
curtl = tlmake(curpp, curval); /* Make a token list with this */
}
/* FINDIDENT - auxiliary for NEXTPP that checks for macro expansion at
** top level.
*/
static
int
findident()
{
register char *cp = curval.cp;
if (*cp == SPC_IDQUOT) /* Special quoted ident? */
{
cursym = NULL; /* Just punt to CCLEX */
return curpp;
}
/* See if this symbol is already defined as a macro or C sym. */
/* Note that if curptr is set, token came from cooked tokenlist and so
** is not to be expanded.
*/
cursym = symfind(cp, 1); /* Find sym or create global symbol! */
if (cursym->Sclass == SC_MACRO)
{
if (!curptr && mexptop(cursym, 0)) /* Is macro! OK to expand? */
return nextpp(); /* Yes, return cooked tokens!*/
/* Sym is macro, but not being expanded, so search again to find
** the C symbol that the macro was shadowing.
** This is tricky since the search has to be continued from AFTER
** the point where the macro symbol exists.
** Even trickier is the requirement that, if no
** existing symbol is found, we must create
** a new global symbol which comes AFTER the macro symbol.
*/
if ((cursym = symfnext(cursym)) == NULL) /* Find next sym. If none, */
{
cursym = shmacsym(symgcreat(cp)); /* create shadow sym */
}
}
return curpp;
}
/* FINDMACSYM - Find macro name symbol if one exists
*/
static
SYMBOL *
findmacsym(id)
char *id;
{
SYMBOL *macsym;
if ((macsym = symfind(id, 0)) != NULL) /* Scan for macro or identifier */
{
if (macsym->Sclass == SC_MACRO) /* Found symbol, see if macro */
return macsym; /* Yup, return the pointer */
else
--(macsym->Srefs); /* Compensate for spurious symfind ref */
}
return NULL;
}
/* NEXTMACPP() - Token input for macro expansion, which is called in place
** of nextrawpp() so input can easily be redirected to token lists.
** "rawptr" is set if the token is a pptok.
** NOTE that the returned token is no longer needed since the
** list pointer has been bumped prior to return, so it is OK to
** mung the token (assuming nothing else needs the overall list).
** The exception is T_EOF, which leaves the list pointer alone so that
** all further calls will return T_EOF until a mtlpop() is done.
*/
static
int
nextmacpp()
{
if ((rawptr = mactl.tl_head) != NULL) /* If using token list, */
{
rawval = rawptr->pt_val; /* get from list */
if (((rawpp = rawptr->pt_typ) != T_EOF) /* If not EOF, */
&& (tlpskip(mactl) == NULL)) /* set up for next call */
{
mtlpop(); /* List ran out, pop it off */
}
return rawpp;
}
/* No token list, now emulate nextpp() without directive processing */
if ((curptr = curtl.tl_head) != NULL) /* If using token list, */
{
rawptr = curptr;
rawpp = curpp = curptr->pt_typ; /* Consume first token on it */
rawval = curval = curptr->pt_val;
if (tlpskip(curtl) == NULL)
{
/* Token list ran out. Clean up for next call. */
tlzinit(curtl); /* No active cooked token list */
}
return curpp;
}
/* Get new token from file input */
return nextrawpp();
}
/* PUSHMP() - Push current token back for nextmacpp().
*/
static
void
pushmp()
{
if (rawptr) tlpins(mactl, rawptr);
else
pushpp();
}
/* MTLPUSH(tl) - Push a token list on stack for nextmacpp() to read from.
*/
static
void
mtlpush(tl)
tlist_t tl;
{
if (mactlev >= MAXMACNEST-1)
{
int_error("mtlpush: mactls overflow");
}
else
{
mactls[mactlev++] = mactl;
mactl = tl;
}
}
/* MTLPOP() - Pop off an exhausted token list
*/
static
void
mtlpop()
{
if (--mactlev < 0)
{
int_error("mtlpop: mactls underflow");
mactlev = 0, mactl.tl_head = NULL;
}
else
mactl = mactls[mactlev];
}
/* Auxiliary token handling routines */
/* TLTOMAC(tl,cp) - Convert token list to macro body string
** Returns updated ptr to end of string
*/
static
char *
tltomac(tl,cp)
tlist_t tl;
char *cp;
{
register int i;
register PPTOK *p;
for (p = tlpcur(tl); p; p = p->pt_nxt)
{
if ((i = p->pt_typ) != 0 && i < NTOKDEFS)
{
*cp++ = i; /* Always stick token type in */
if (!tokstr[i]) switch (i) /* Token not op or punct? */
{
case T_MACARG:
case T_MACSTR:
case T_MACINS: /* Value is param # */
*cp++ = p->pt_val.i + MAC_ARGOFF;
case T_MACCAT:
break;
default: /* Assume rest of string is token */
cp = estrcpy(cp, p->pt_val.cp);
++cp; /* Move over NUL char */
break;
}
}
else
tkerr("tltomac", i);
}
*cp++ = '\0'; /* Add final terminator to whole thing */
return cp;
}
#if 0
/* TLFRMAC(cp) - Convert macro body string to token list
** Returns token list. List will be empty if string is NULL or "".
*/
static
tlist_t
tlfrmac(cp)
char *cp;
{
tlist_t tl;
register int i;
static PPTOK zpptok;
PPTOK pptok;
tlzinit(tl); /* Init to zero */
if (!cp || !*cp)
return tl;
while ((i = *cp++) != '\0') /* Stop when see zero
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -