📄 cpp.c
字号:
error(MSG_Xmiscls, p->name);
Token = save;
return (t);
}
while (iswhite(t) || t == '\n')
t = egettok();
Parms[i] = Token;
nest = 0;
while (t != 0 &&
(t != ',' && t != ')' || nest != 0)) {
if (t == '(')
nest++;
else if (t == ')')
nest--;
else if (t == '\n')
*Token = ' ';
Token = Tail;
t = egettok();
}
while (Token > Parms[i] && iswhite(Token[-1]))
Token--;
*Token++ = '\0';
if (t == ',')
t = skip_egettok();
}
if (i != p->nparms)
error(MSG_Xnumpar, p->name);
for (; i < p->nparms; i++)
Parms[i] = "";
}
/* let macro p sleep */
p->flags &= ~DEFINED;
if (Sleep >= SleepStack + MACNEST)
error(MSG_macnst, NULL), exit(1);
*Sleep++ = p;
unget(MACFLAG);
/* expand body */
s = p->u.body;
for (q = s + strlen(s); --q >= s; )
if (*q == MACFLAG)
ungets(Parms[get() - '0']);
else
unget(*q);
Token = save;
}
return (t);
}
recursive
char egettok()
{
char c;
if ((c = egettok_eof()) == 0)
error(MSG_unxeof, NULL), exit(1);
return (c);
}
recursive
char skip_egettok()
{
char t;
while (t = egettok(), iswhite(t))
;
return (t);
}
void skip_eol()
{
while (Lex != '\n')
gettok();
put('\n');
}
void do_include()
{
char t, c, buff[100], *p;
t = skip_egettok();
if (t == '"') {
strcpy(buff, Token + 1);
if (buff[strlen(buff) - 1] != '"')
error(MSG_incmisquo, NULL);
buff[strlen(buff) - 1] = '\0';
}
else if (t == '<') {
p = buff;
while ((c = get()) != '>') {
if (c == '\n') {
error(MSG_incmisbra, NULL);
return;
}
*p++ = c;
}
*p = '\0';
}
else {
error(MSG_incmisfil, NULL);
return;
}
#if 0
skip_eol();
#endif
pushFile(buff, t, NULL);
}
void do_define()
{
char *name, *body, *p;
char t;
int i, np;
char *Parms[MAXPARM];
bool quote;
/* get macro name */
if (skip_gettok() != NAME) {
error(MSG_defmisnam, NULL);
skip_eol();
return;
}
name = Token;
Token = Tail + 1;
np = -1;
if ((t = gettok()) == '(') {
/* parameter macro */
np = 0;
while ((t = skip_gettok()) == NAME) {
Parms[np++] = Token;
Token = Tail + 1;
if ((t = skip_gettok()) != ',')
break;
}
if (t != ')') {
error(MSG_defbadpar, NULL);
skip_eol();
Token = Pool;
return;
}
t = ' ';
}
/* get macro body */
while (iswhite(t))
t = gettok();
body = p = Token;
quote = NO;
for (; t != '\n'; t = gettok()) {
if (t == '#') {
if ((t = get()) == '#') {
/* ##: name concatenation */
Token = p;
t = get();
} else {
/* #: surround by double quote */
quote = YES;
Token = Tail;
}
while (iswhite(t))
t = get();
unget(t);
continue;
}
if (quote)
Token[-1] = '"'; /* change # to " */
if (t == NAME) {
for (i = 0; i < np; i++)
if (strcmp(Parms[i], Token) == 0) {
Token[0] = MACFLAG;
Token[1] = '0' + i;
Tail = Token + 2;
break;
}
}
if (quote)
*Tail++ = '"';
Token = Tail;
if (! iswhite(t))
p = Token;
quote = NO;
}
*p = '\0';
unget(t);
/* register */
install(name, body, np);
Token = Pool;
}
void do_undef()
{
char t;
MACRO *p;
if ((t = skip_gettok()) != NAME)
error(MSG_undmisnam, NULL);
else {
if ((p = lookup(Token)) != NULL)
p->flags &= ~DEFINED;
}
skip_eol();
}
/* Conditional Compilation */
int search_else_endif()
{
int nest;
char t;
FILEST *fsave;
int lsave;
fsave = FileSp;
lsave = fsave->lineno;
t = 0;
nest = 1;
for (;;) {
skip_eol();
if ((t = skip_gettok()) == '#') {
t = skip_egettok();
if (strcmp(Token, "if") == 0 ||
strcmp(Token, "ifdef") == 0 ||
strcmp(Token, "ifndef") == 0)
nest++;
else if (strcmp(Token, "endif") == 0) {
if (--nest == 0) {
Ifnest--;
return (0);
}
} else if (nest == 1 &&
(strcmp(Token, "else") == 0 ||
strcmp(Token, "elif") == 0))
return (1);
} else if (t == 0) {
error1(MSG_misendif, NULL, fsave->name, lsave);
exit(1);
}
}
}
/* special lex for #if */
char twinlex(char c1, char c2, char l2, char c3, char l3)
{
char c;
if ((c = get()) == c2)
return (l2);
if (c == c3)
return (l3);
unget(c);
return (c1);
}
char getlex1(char lex)
{
switch (lex) {
Case '<':
return (twinlex('<', '<', SHR, '=', LE));
Case '>':
return (twinlex('>', '>', SHL, '=', GE));
Case '=':
return (twinlex('=', '=', EQ, 0, 0));
Case '!':
return (twinlex('!', '=', NE, 0, 0));
Case '&':
return (twinlex('&', '&', AND, 0, 0));
Case '|':
return (twinlex('|', '|', OR, 0, 0));
Default:
return (lex);
}
}
char ugetlex()
{
return (EvalLex = getlex1(skip_gettok()));
}
recursive
char getlex()
{
return (EvalLex = getlex1(skip_egettok()));
}
tiny levelof(char lex)
{
switch (lex) {
Case '?': return (0);
Case OR: return (1);
Case AND: return (2);
Case '|': return (3);
Case '^': return (4);
Case '&': return (5);
Case EQ: case NE: return (6);
Case '<': case LE: case '>': case GE:
return (7);
Case SHR: case SHL: return (8);
Case '+': case '-': return (9);
Case '*': case '/': case '%':
return (10);
Default: return (11);
}
}
#define PRIMLEV 11
jmp_buf Env;
void synerror()
{
error(MSG_ifsynX, Token);
skip_eol();
longjmp(Env, 1);
}
void checkLex(char lex)
{
if (EvalLex != lex)
synerror();
}
char digval(char c)
{
c = tolower(c);
if (isdigit(c))
return (c - '0');
if (islower(c))
return (c - 'a' + 10);
return (100);
}
long valof(char *s)
{
long v, radix;
char c, *p;
p = s;
c = *p;
if (c != '0')
radix = 10; /* decimal */
else if (*++p == 'x' || *p == 'X')
p++, radix = 16; /* hexadecimal */
else
radix = 8; /* octal */
v = 0;
while ((c = digval(*p)) < radix) {
v = v * radix + c;
p++;
}
/* skip suffixes */
while ((c = tolower(*p)) == 'u' || c == 'l')
p++;
if (*p)
error(MSG_badnum, s);
return (v);
}
long chaval(char *s)
{
char c, d;
int n;
long v;
v = 0;
while ((c = *s++) != '\0' && c != '\'') {
if (is2byte(c) && *s) {
v = (v << 16) | (c << 8) | *s++;
continue;
}
if (c == '\\')
switch (c = *s++) {
Case 'a': c = '\a';
Case 'b': c = '\b';
Case 'f': c = '\f';
Case 'n': c = '\n';
Case 'r': c = '\r';
Case 't': c = '\t';
Case 'v': c = '\v';
Case 'x':
c = 0;
for (n = 0; n < 3; n++) {
if ((d = digval(*s)) >= 16)
break;
c = c << 4 | d;
s++;
}
Default:
if ('0' <= c && c <= '7') {
s--;
c = 0;
for (n = 0; n < 3; n++) {
if ((d = digval(*s)) >= 8)
break;
c = c << 3 | d;
s++;
}
}
}
v = v << 8 | c;
}
return (v);
}
recursive
long eval1(tiny lev)
{
long v, w, u;
char op;
if (lev == PRIMLEV) {
if (EvalLex == '(') {
v = eval0(0);
checkLex(')');
getlex();
return (v);
}
if (EvalLex == '-')
return (-eval0(PRIMLEV));
if (EvalLex == '+')
return (eval0(PRIMLEV));
if (EvalLex == '~')
return (~eval0(PRIMLEV));
if (EvalLex == '!')
return (!eval0(PRIMLEV));
if (EvalLex == NUMBER) {
v = valof(Token);
getlex();
return (v);
}
if (EvalLex == '\'') {
v = chaval(Token + 1);
getlex();
return (v);
}
if (EvalLex == NAME && strcmp(Token, "defined") == 0) {
if (ugetlex() == '(') {
ugetlex(), checkLex(NAME);
v = lookup(Token) != NULL;
getlex(), checkLex(')');
} else
v = lookup(Token) != NULL;
getlex();
return (v);
}
if (EvalLex == NAME) { /* undefined macro name */
if (Undeferr)
error(MSG_undefmacX, Token);
getlex();
return (0);
}
synerror();
}
v = eval1(lev + 1);
while (levelof(EvalLex) == lev) {
op = EvalLex;
if (op == '?') {
w = eval0(lev);
checkLex(':');
u = eval0(lev);
return (v ? w : u);
}
w = eval0(lev + 1);
switch (op) {
Case '+': v += w;
Case '-': v -= w;
Case '*': v *= w;
Case '/': v /= w;
Case '%': v %= w;
Case '&': v &= w;
Case '|': v |= w;
Case '^': v ^= w;
Case SHR: v <<= w;
Case SHL: v >>= w;
Case EQ: v = v == w;
Case NE: v = v != w;
Case '>': v = v > w;
Case '<': v = v < w;
Case GE: v = v >= w;
Case LE: v = v <= w;
Case AND: v = v && w;
Case OR: v = v || w;
Default: bug("eval1");
}
}
return (v);
}
recursive
long eval0(tiny lev)
{
getlex();
return (eval1(lev));
}
long eval()
{
long v;
if (setjmp(Env) == 0) {
v = eval0(0);
checkLex('\n');
return (v);
} else
return (0);
}
void do_if()
{
if (Ifnest >= IFNEST)
error(MSG_ifnst, NULL);
else
memcpy(&IfStack[Ifnest++], FileSp, sizeof(*FileSp));
if (eval() == 0) {
do {
search_else_endif();
if (strcmp(Token, "elif") != 0) {
skip_eol();
return;
}
} while (eval() == 0);
}
}
void do_ifdef(bool whendef)
{
if (Ifnest >= IFNEST)
error(MSG_ifnst, NULL);
else
memcpy(&IfStack[Ifnest++], FileSp, sizeof(*FileSp));
if (skip_gettok() != NAME)
error(MSG_ifdmisnam, NULL);
else if ((lookup(Token) != NULL) != whendef) {
do {
search_else_endif();
if (strcmp(Token, "elif") != 0) {
skip_eol();
return;
}
} while (eval() == 0);
}
}
void do_else_elif()
{
if (Ifnest == 0)
error(MSG_misif, NULL);
/* skip until #endif */
while (search_else_endif() != 0)
;
skip_eol();
}
void do_endif()
{
if (Ifnest == 0)
error(MSG_misif, NULL);
else
Ifnest--;
skip_eol();
}
void do_line()
{
if (skip_egettok() != NUMBER) {
error(MSG_linmisnum, NULL);
skip_eol();
return;
}
FileSp->lineno = atoi(Token) - 1;
if (skip_egettok() == '"') {
Token[strlen(Token) - 1] = '\0';
strcpy(FileSp->name, Token + 1);
}
while (Lex != '\n')
gettok();
Lineno = -1;
}
void do_pragma()
{
char c;
if (NoSharp)
skip_eol();
else {
fput("#p");
do {
c = gettok();
fput(Token);
} while (c != '\n');
}
}
void do_error()
{
char msg[100];
char *p, c;
p = msg;
while ((c = get()) == ' ' || c == '\t')
;
while (p < msg + sizeof(msg) - 1 && c != '\n' && c != 0) {
*p++ = c;
c = get();
}
*p = '\0';
while (c != '\n' && c != 0)
c = get();
unget(c);
error(MSG_errordir, msg);
get();
}
void do_cpp()
{
bool tol;
char t;
/* main loop */
tol = YES;
t = 0;
while ((t = egettok_eof()) != 0) {
if (t == '#' && tol) {
DirectiveMode = YES;
t = skip_gettok();
if (t == '\n')
;
else if (strcmp(Token, "include") == 0)
do_include();
else if (strcmp(Token, "define") == 0)
do_define();
else if (strcmp(Token, "undef") == 0)
do_undef();
else if (strcmp(Token, "if") == 0)
do_if();
else if (strcmp(Token, "ifdef") == 0)
do_ifdef(YES);
else if (strcmp(Token, "ifndef") == 0)
do_ifdef(NO);
else if (strcmp(Token, "elif") == 0)
do_else_elif();
else if (strcmp(Token, "else") == 0)
do_else_elif();
else if (strcmp(Token, "endif") == 0)
do_endif();
else if (strcmp(Token, "line") == 0)
do_line();
else if (strcmp(Token, "pragma") == 0)
do_pragma();
else if (strcmp(Token, "error") == 0)
do_error();
else {
error(MSG_badstmX, Token);
skip_eol();
}
DirectiveMode = NO;
lineadj();
} else {
fput(Token);
if (t == '\n') {
lineadj();
tol = YES;
}
else if (!isspace(t))
tol = NO;
}
}
if (Ifnest != 0) {
Ifnest--;
error1(MSG_misendif, NULL, IfStack[Ifnest].name, IfStack[Ifnest].lineno);
}
}
void main(int argc, char *argv[])
{
static char usage[] =
"LSI C preprocessor ver 1.5 [" __DATE__ "]\n\
\twritten by Mori Koichiro\n\
\tusage: cpp [-s] [-w] [-c] [-DMACRO] [-IINCDIR] [-ooutput] [input...]\n";
char c, *p, *s, *outf;
int i, inc;
char name[100];
time_t t;
time(&t);
Timep = localtime(&t);
inc = 0;
installf("__FILE__", macFile);
installf("__LINE__", macLine);
installf("__TIME__", macTime);
installf("__DATE__", macDate);
installf("__eval__", macEval);
outf = NULL;
while (++argv, --argc != 0 && argv[0][0] == '-') {
p = argv[0] + 1;
switch (*p++) {
Case 'x':
while (c = *p++)
if (isalpha(c))
Debug[tolower(c) - 'a'] = YES;
else if (c == '#')
setmem(Debug, 26, YES);
Case 'w':
NoWarn = YES;
Case 'B':
BCPL_comment = YES;
#if 0
Case 'C':
Keep_comment = YES;
#endif
Case 'd':
fprintf(stderr, "cpp: Warning: -d is obsolete; use -D\n");
/* fall thru */
case 'D':
/* get macro definition */
s = name;
while ((c = *p++) != '\0' && c != '=')
*s++ = c;
*s = '\0';
if (c == '\0')
p = "1";
install(name, p, -1);
Case 'i':
fprintf(stderr, "cpp: Warning: -i is obsolete; use -I\n");
/* fall thru */
case 'I':
/* include directory */
if (inc >= MAXDIR)
fprintf(stderr, "too many -i\n"), exit(1);
Incdir[inc++] = p;
Case 's':
NoSharp = YES;
Case 'o':
if (*p != '\0')
outf = p;
else if (++argv, --argc != 0)
outf = *argv;
else
fprintf(stderr, usage), exit(1);
Case 'j':
Jap = *p - '0';
Case 'c':
CommNest = YES;
Case 'y':
Charcode = *p;
if (Charcode != 0 && Charcode != '0' && Charcode != '1' && Charcode != '2')
goto err;
Default:
err:
fprintf(stderr, usage), exit(1);
}
}
Incdir[inc] = NULL;
if (outf == NULL)
Ofp = stdout;
else
Ofp = efopen(outf, "w");
if (argc == 0) {
pushFile("", ' ', stdin);
do_cpp();
} else {
for (i = 0; i < argc; i++) {
pushFile(argv[i], ' ', NULL);
do_cpp();
}
}
efclose(Ofp);
exit(Errcode);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -