📄 cpp.c
字号:
/*
* cpp.c - c compiler preprocessor
*
* 23-Jun-87 include
* 24-Jun-87 define, ifdef, ifndef, else, endif
* 25-Jun-87 if, elif, undef, -d option, -s option, line, #, ##
* 27-Jun-87 add __eval__
* 14-Jul-87 debug lineadj
* 5-Sep-87 automatic directory search
* 17-Sep-87 add -i
* 29-Sep-87 long computation in #if
* 30-Sep-87 add -w
* 25-Dec-87 debug lineadj
* 08-Jan-88 debug error
* 18-Feb-88 debug recursive death
* add __TIME__, __DATE__
* 22-Feb-88 edit error messages
* 23-Feb-88 add Japanese messages
* 02-Mar-88 bug fix: character value
* 03-Nov-1988 02:36 add -c option (allows nested comment)
* 22-Dec-1988 17:29 add -y option (select character set)
* 06-Feb-1989 22:21 add code to check the validity of #endif
* 07-Feb-1989 16:53 ...
* 07-Feb-1989 17:50 add code to remove trailing blanks
* from macro parameter
* 07-Feb-1989 18:09 add code to remove comments in #pragma
* 08-Feb-1989 17:23 tako
* 18-Apr-1989 14:56 change value of FILENEST: 6 -> 8
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <time.h>
#pragma nonrec
typedef char bool, tiny;
typedef unsigned nat;
#define YES 1
#define NO 0
#define MAXBUFF 10000
#define MAXPARM 200
#define FILENEST 8
#define IFNEST 8
#define MACNEST 100
bool Debug[26];
bool NoSharp;
bool NoWarn;
bool Jap;
bool CommNest;
bool BCPL_comment;
#if 0
bool Keep_comment;
#endif
char Charcode = '0';
#define Case break; case
#define Default break; default
#define MACFLAG 0x7F
#undef MAXDIR
#define MAXDIR 10
char *Incdir[MAXDIR + 1];
typedef struct {
FILE *fp;
char name[80];
int lineno;
} FILEST;
FILEST FileStack[FILENEST];
FILEST *FileSp = FileStack - 1;
FILE *Ofp;
int Lineno;
int Errcode = 0;
FILEST IfStack[IFNEST];
int Ifnest = 0;
/*
* error messages
*/
char MSG_cntopnX[] = "can't open: %s: %s\0"
"僼傽僀儖 %s 偑僆乕僾儞偱偒側偄 (%s)";
char MSG_cntwrt[] = "can't write\0"
"僨傿僗僋偑堦攖";
char MSG_incnst[] = "#include too nested\0"
"#include 偺僱僗僩偑怺偡偓傞";
char MSG_outmem[] = "out of memory\0"
"儊儌儕偑懌傝側偄";
char MSG_bigmac[] = "too big macro\0"
"儅僋儘掕媊偑戝偒偡偓傞";
char MSG_unxeof[] = "unexpected EOF\0"
"婜懸偟側偄僼傽僀儖偺廔傝";
char MSG_opencomm[] = "missing */\0"
"僐儊儞僩偑暵偠偰偄側偄";
char MSG_Xmisopn[] = "%s: missing '('\0"
"儅僋儘 %s 偺 ( 偑側偄";
char MSG_Xmiscls[] = "%s: missing ')'\0"
"儅僋儘 %s 偺 ) 偑側偄";
char MSG_Xnumpar[] = "%s: conflicting # of parameters\0"
"儅僋儘 %s 偺僷儔儊僞偺悢偑崌傢側偄";
char MSG_macnst[] = "macro too nested\0"
"儅僋儘偺僱僗僩偑怺偡偓傞";
char MSG_incmisquo[] = "#include: missing \"\0"
"#include 偺 \" 偑側偄";
char MSG_incmisbra[] = "#include: missing >\0"
"#include 偺 > 偑側偄";
char MSG_incmisfil[] = "#include: missing filename\0"
"#include 偺僼傽僀儖柤偑側偄";
char MSG_defmisnam[] = "#define: missing macro name\0"
"#define 偺儅僋儘柤偑側偄";
char MSG_defbadpar[] = "#define: bad macro parameter\0"
"#define 偺儅僋儘偺僷儔儊僞掕媊偵岆傝偑偁傞";
char MSG_undmisnam[] = "#undef: missing macro name\0"
"#undef 偵柤慜偑側偄";
char MSG_misif[] = "missing #if\0"
"#if 偑側偄";
char MSG_misendif[] = "missing #endif\0"
"#endif 偑側偄";
char MSG_ifnst[] = "#if/#ifdef too nested\0"
"#if/#ifdef 偺僱僗僩偑怺偡偓傞";
char MSG_ifsynX[] = "#if/#elif: syntax error near %s\0"
"#if 傑偨偼 #elif 拞偺 %s 偺嬤偔偵岆傝偑偁傞";
char MSG_badnum[] = "bad number '%s'\0"
"%s 偼晄惓側悢";
char MSG_ifdmisnam[] = "#ifdef: missing identifier\0"
"#ifdef 偵柤慜偑側偄";
char MSG_linmisnum[] = "#line: missing number\0"
"#line 偵峴斣崋偑側偄";
char MSG_badstmX[] = "undefined stmt: #%s\0"
"#%s 偲偄偆僾儕僾儘僙僢僒暥偼側偄";
char MSG_undefmacX[] = "undefined macro: %s\0"
"儅僋儘 %s 偑枹掕媊";
char MSG_errordir[] = "#error: %s\0"
"#error: %s";
char MSG_Xredef[] = "Warning: macro '%s' redefined\0"
"寈崘: 儅僋儘 %s 偼俀偮偺堎側傞掕媊傪傕偮";
char *chooseMsg(char *s)
{
return (Jap ? s + strlen(s) + 1: s);
}
void warn(char *msg, char *s)
{
if (NoWarn)
return;
if (FileSp >= FileStack)
fprintf(stderr, "%s %d: ", FileSp->name, FileSp->lineno);
fprintf(stderr, chooseMsg(msg), s);
putc('\n', stderr);
if (Errcode != 1)
Errcode = 2;
}
void error1(char *msg, char *s, char *file, int lineno)
{
if (file != NULL)
fprintf(stderr, "%s %d: ", file, lineno);
fprintf(stderr, chooseMsg(msg), s, strerror(errno));
putc('\n', stderr);
Errcode = 1;
}
void error(char *msg, char *s)
{
if (FileSp >= FileStack)
error1(msg, s, FileSp->name, FileSp->lineno);
else if ((FileSp + 1)->lineno != 0)
error1(msg, s, (FileSp + 1)->name, (FileSp + 1)->lineno);
else
error1(msg, s, NULL, 0);
}
void bug(char *msg)
{
if (FileSp >= FileStack)
fprintf(stderr, "%s %d: ", FileSp->name, FileSp->lineno);
fprintf(stderr, "cpp error (%s)\n", msg);
exit(1);
}
void lineadj()
{
int n;
if ((n = FileSp->lineno) != Lineno)
if (Lineno < 0 || n < Lineno) {
Lineno = FileSp->lineno;
if (!NoSharp)
fprintf(Ofp, "# %d \"%s\"\n",
Lineno, FileSp->name);
} else {
while (Lineno < n)
putc('\n', Ofp), Lineno++;
}
}
void put(char c)
{
if (c == MACFLAG)
bug("put");
putc(c, Ofp);
if (c == '\n')
Lineno++;
}
void fput(char *s)
{
char c;
while (c = *s++)
put(c);
}
FILE *efopen(char *file, char *mode)
{
FILE *fp;
if ((fp = fopen(file, mode)) == NULL)
error(MSG_cntopnX, file), exit(1);
return (fp);
}
void efclose(FILE *fp)
{
if (ferror(fp) || fclose(fp))
error(MSG_cntwrt, NULL), exit(1);
}
char *directory(char *buf, char *s)
{
char *p, *r, c;
r = p = buf;
while (c = *s++) {
*p++ = c;
if (c == ':' || c == '/' || c == '\\')
r = p;
}
*r = '\0';
return (buf);
}
char *appendsl(char *buf, char *s)
{
char c;
strcpy(buf, s);
if (buf[0] != '\0') {
c = buf[strlen(buf) - 1];
if (c != ':' && c != '/' && c != '\\')
strcat(buf, "\\");
}
return (buf);
}
void pushFile(char *file, char tag, FILE *fp)
{
char fn[100];
int i;
if (FileSp >= FileStack + FILENEST - 1) {
error(MSG_incnst, NULL);
return;
}
if (fp != NULL)
;
else if (tag == '"' && FileSp >= FileStack &&
(fp = fopen(strcat(directory(fn, FileSp->name), file), "r"))
!= NULL)
file = fn;
else {
fp = NULL;
if (tag != ' ')
for (i = 0; Incdir[i] != NULL; i++)
if ((fp = fopen(strcat(appendsl(fn, Incdir[i]),
file), "r")) != NULL)
break;
if (fp == NULL && (fp = fopen(file, "r")) == NULL) {
error(MSG_cntopnX, file);
return;
}
}
FileSp++;
FileSp->fp = fp;
strcpy(FileSp->name, file);
FileSp->lineno = 1;
Lineno = -1;
lineadj();
}
void *rawnew(nat s)
{
void *p;
if ((p = sbrk(s)) == (void *)-1)
error(MSG_outmem, NULL), exit(1);
setmem(p, s, 0);
return (p);
}
#define new(t, n) ((t *)rawnew(sizeof(t) * (n)))
char *copy(char *s)
{
return (strcpy(new(char, strlen(s) + 1), s));
}
typedef struct macro {
struct macro *next;
char *name;
union {
char *body;
void (*func)();
} u;
char flags;
#define DEFINED 001
#define ISFUNC 002
int nparms;
} MACRO;
#define HASHSIZE 1024
MACRO *HashTbl[HASHSIZE];
char Pool[MAXBUFF];
MACRO *SleepStack[MACNEST];
MACRO **Sleep = SleepStack;
char *Ungetp = Pool + MAXBUFF;
char *Token = Pool;
char *Tail;
char Lex, EvalLex;
bool DirectiveMode = NO;
bool Undeferr;
void checkPool(char *p)
{
if (p + 1 >= Ungetp)
error(MSG_bigmac, NULL), exit(1);
}
void unget(char c)
{
if (c != 0) {
checkPool(Token);
if ((*--Ungetp = c) == '\n')
FileSp->lineno--;
}
}
void ungets(char *s)
{
char *q;
for (q = s + strlen(s); --q >= s; )
unget(*q);
}
char get1()
{
int c;
bool fc;
if (Ungetp < Pool + MAXBUFF)
c = *Ungetp++;
else {
fc = NO;
for (;;) {
if (FileSp < FileStack)
return (0);
while ((c = getc(FileSp->fp)) == MACFLAG)
;
if (c != EOF)
break;
efclose(FileSp->fp);
Lineno = -2;
fc = YES;
FileSp--;
}
if (fc)
lineadj();
}
if (c == '\n')
FileSp->lineno++;
return (c);
}
char geteof()
{
char c;
if (DirectiveMode) {
while ((c = get1()) == '\\')
if ((c = get1()) != '\n') {
unget(c);
c = '\\';
break;
}
} else
c = get1();
return (c);
}
char get()
{
char c;
if ((c = geteof()) == 0)
error(MSG_unxeof, NULL), exit(1);
return (c);
}
#define NAME 'a'
#define NUMBER '0'
#define SHR 'b'
#define SHL 'c'
#define LE 'd'
#define GE 'e'
#define NE 'f'
#define EQ 'g'
#define AND 'h'
#define OR 'i'
#define isletter(c) (isalpha(c) || (c) == '_')
#define iswhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\f' || (c) == '\v')
bool is2byte(char c)
{
switch (Charcode) {
Default:
return (NO);
Case '0':
return (0x81 <= c && c <= 0x9F || 0xE0 <= c && c <= 0xFC);
Case '1':
return (0x81 <= c && c <= 0xFC);
Case '2':
return (0x81 <= c && c <= 0xFD);
}
}
char gettok_eof()
{
char c, d;
char *p;
if ((c = geteof()) == '/') {
c = geteof();
if (c == '*') {
/* skip comment & change it to ' ' */
FILEST *fsave = FileSp;
int cc, lsave = fsave->lineno;
c = 0;
cc = 1;
for (;;) {
d = c;
c = geteof();
if (c == 0) {
error1(MSG_opencomm, NULL, fsave->name, lsave);
exit(1);
}
if (d == '*' && c == '/') {
if (--cc == 0)
break;
c = 0;
}
if (CommNest && d == '/' && c == '*') {
cc++;
c = 0;
}
}
c = ' ';
} else if (BCPL_comment && c == '/') {
/* skip C++ comment (originally BCPL style) */
while ((c = geteof()) != '\n' && c != 0)
;
} else {
unget(c);
c = '/';
}
}
d = c;
p = Token;
if (isletter(c) || isdigit(c)) {
d = isdigit(c) ? NUMBER : NAME;
while (isletter(c) || isdigit(c)) {
*p++ = c;
c = geteof();
}
unget(c);
} else if (c == '"' || c == '\'') {
*p++ = c;
while (c = get(), c != d && c != '\n' && c != '\0') {
*p++ = c;
if (c == '\\' || is2byte(c))
*p++ = get();
}
if (c == '\n')
unget(c);
else
*p++ = c;
} else
*p++ = c;
*p = '\0';
checkPool(p);
Tail = p;
return (Lex = d);
}
char gettok()
{
char c;
if ((c = gettok_eof()) == 0)
error(MSG_unxeof, NULL), exit(1);
return (c);
}
char skip_gettok()
{
char t;
while (t = gettok(), iswhite(t))
;
return (t);
}
nat hash(char *s)
{
nat v;
char c;
v = 0;
while (c = *s++)
v = v * 257 + c;
return (v % HASHSIZE);
}
MACRO *roomfor(char *name)
{
MACRO *p, **r;
r = &HashTbl[hash(name)];
for (p = *r; p != NULL; p = p->next)
if (strcmp(p->name, name) == 0)
break;
if (p == NULL) {
p = new(MACRO, 1);
p->name = copy(name);
p->next = *r;
*r = p;
}
return (p);
}
MACRO *lookup(char *name)
{
MACRO *p;
for (p = HashTbl[hash(name)]; p != NULL; p = p->next)
if (strcmp(p->name, name) == 0)
return (p->flags & DEFINED ? p : NULL);
return (NULL);
}
void installf(char *name, void (*func)())
{
MACRO *p;
p = roomfor(name);
p->u.func = func;
p->flags = DEFINED | ISFUNC;
p->nparms = -1;
}
void install(char *name, char *body, int nparms)
{
MACRO *p;
p = roomfor(name);
if (p->flags & DEFINED &&
(p->flags & ISFUNC || strcmp(p->u.body, body) != 0))
warn(MSG_Xredef, name);
p->u.body = copy(body);
p->flags = DEFINED;
p->nparms = nparms;
if (Debug['d'-'a'])
fprintf(stderr, "[debug] %s(%d) = {%s}\n",
p->name, p->nparms, p->u.body);
}
char skip_egettok(void);
char egettok(void);
long eval0(tiny);
void macFile()
{
/* replaced by current filename */
unget('"');
ungets(FileSp->name);
unget('"');
}
void macLine()
{
/* replaced by current line# */
char buff[10];
sprintf(buff, "%d", FileSp->lineno);
ungets(buff);
}
struct tm *Timep;
void macTime()
{
/* replaced by current time */
char buff[12];
sprintf(buff, "\"%02d:%02d:%02d\"",
Timep->tm_hour, Timep->tm_min, Timep->tm_sec);
ungets(buff);
}
void macDate()
{
/* replaced by current date */
static char *moname[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
char buff[14];
sprintf(buff, "\"%s %02d %04d\"",
moname[Timep->tm_mon], Timep->tm_mday, 1900 + Timep->tm_year);
ungets(buff);
}
recursive
void macEval()
{
/* replaced by evaluated value */
char buff[12];
bool undeferr;
if (skip_egettok() != '(') {
error(MSG_Xmisopn, "__eval__");
ungets(Token);
return;
}
undeferr = Undeferr;
Undeferr = YES;
sprintf(buff, "%ld", eval0(0));
Undeferr = undeferr;
if (EvalLex != ')')
error(MSG_Xmiscls, "__eval__");
ungets(buff);
}
recursive
char egettok_eof()
{
char t;
MACRO *p;
char *Parms[MAXPARM];
int i, nest;
char *save, *q, *s;
FILEST *fsave;
int lsave;
for (;;) {
if ((t = gettok_eof()) == MACFLAG) {
/* wake up sleeping macro */
if (Sleep <= SleepStack)
bug("egettok");
(*--Sleep)->flags |= DEFINED;
continue;
}
if (t != NAME || (p = lookup(Token)) == NULL)
break;
if (p->flags & ISFUNC) {
/* built-in macro */
(*p->u.func)();
continue;
}
/* replaced by macro body */
save = Token;
fsave = FileSp;
lsave = fsave->lineno;
if (p->nparms >= 0) {
/* expecting parameters */
if ((t = skip_gettok()) != '(') {
#if 0
/* delete 24-Jul-1989 */
error(MSG_Xmisopn, p->name);
return (t);
#endif
ungets(Token);
unget(' ');
ungets(p->name);
return (gettok());
}
t = skip_egettok();
for (i = 0; t != ')'; i++) {
/* get a parameter */
if (t == 0) {
FileSp = fsave;
fsave->lineno = lsave;
error(MSG_Xmiscls, p->name);
exit(1);
}
if (i >= MAXPARM) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -