⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccpp.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
		    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 + -