📄 cpp.c
字号:
}
return token;
} // CPPifdef
static int CPPinclude()
{
int tok = Cg->currentInput->scan(Cg->currentInput);
int file = 0;
if (tok == STRCONST_SY) {
file = yylval.sc_ident;
} else if (tok == '<') {
file = scan_include_name();
} else {
SemanticError(Cg->tokenLoc, ERROR___CPP_SYNTAX, "include");
}
while (tok != '\n')
tok = Cg->currentInput->scan(Cg->currentInput);
SetInputFile(GetAtomString(atable, file));
return '\n';
} // CPPinclude
static int CPPline(int token) {
if (token == INTCONST_SY) {
int line = yylval.sc_int;
token = Cg->currentInput->scan(Cg->currentInput);
if (token == STRCONST_SY) {
Cg->currentInput->name = yylval.sc_ident;
Cg->currentInput->line = line - 1; // Will get bumped by one.
token = Cg->currentInput->scan(Cg->currentInput);
}
}
return token;
}
static int CPPpragma(void)
{
int identa, identb, identc;
int ival, HasIval, NegSign, numfvals;
float fval[4];
int token;
int err;
#define NEXTTOKEN \
/* get the next token, while expanding macros */ \
do { \
token = Cg->currentInput->scan(Cg->currentInput); \
} while (token == IDENT_SY && MacroExpand(yylval.sc_ident))
NEXTTOKEN;
if (token == IDENT_SY && yylval.sc_ident == bindAtom) {
// Parse: # "pragma" "bind" <conn-id> "." <memb-id> "=" <reg-id>
// # "pragma" "bind" <prog-id> "." <parm-id> "=" <reg-id> <i-const>
// # "pragma" "bind" <prog-id> "." <parm-id> "=" "texunit" <i-const>
// # "pragma" "bind" <prog-id> "." <memb-id> "=" "const" <number>+
// # "pragma" "bind" <prog-id> "." <memb-id> "=" "default" <number>+
//
// <number> ::= [ "-" ] ( <i-const> | <f-const> )
err = 0;
NEXTTOKEN;
if (token == IDENT_SY) {
identa = yylval.sc_ident;
NEXTTOKEN;
if (token == '.') {
NEXTTOKEN;
} else {
err = 1;
}
if (token == IDENT_SY) {
identb = yylval.sc_ident;
NEXTTOKEN;
if (token == '=') {
NEXTTOKEN;
} else {
err = 1;
}
if (token == IDENT_SY) {
identc = yylval.sc_ident;
NEXTTOKEN;
} else {
err = 1;
}
numfvals = 0;
HasIval = 0;
while (token == INTCONST_SY ||
token == CFLOATCONST_SY ||
token == '-'
) {
if (token == '-') {
NegSign = 1;
NEXTTOKEN;
} else {
NegSign = 0;
}
if (token == INTCONST_SY) {
if (numfvals == 0 && !NegSign) {
ival = yylval.sc_int;
HasIval = 1;
}
if (NegSign)
yylval.sc_int = -yylval.sc_int;
if (numfvals < 4) {
fval[numfvals] = (float) yylval.sc_int;
numfvals++;
} else {
err = 1;
break;
}
NEXTTOKEN;
} else if (token == CFLOATCONST_SY) {
if (NegSign)
yylval.sc_fval = -yylval.sc_fval;
if (numfvals < 4) {
fval[numfvals] = yylval.sc_fval;
numfvals++;
} else {
err = 1;
break;
}
NEXTTOKEN;
} else {
err = 1;
break;
}
}
if (!err) {
if (identc == texunitAtom) {
if (HasIval && numfvals == 1) {
DefineTexunitBinding(Cg->tokenLoc, identa, identb, ival);
} else {
err = 1;
}
} else if (identc == constAtom) {
if (numfvals > 0) {
DefineConstantBinding(Cg->tokenLoc, identa, identb, numfvals, fval);
} else {
err = 1;
}
} else if (identc == defaultAtom) {
if (numfvals > 0) {
DefineDefaultBinding(Cg->tokenLoc, identa, identb, numfvals, fval);
} else {
err = 1;
}
} else if (HasIval) {
DefineRegArrayBinding(Cg->tokenLoc, identa, identb, identc, ival, 0);
} else {
DefineConnectorBinding(Cg->tokenLoc, identa, identb, identc);
}
}
} else {
err = 1;
}
} else {
err = 1;
}
if (err == 1) {
SemanticError(Cg->tokenLoc, ERROR___CPP_BIND_PRAGMA_ERROR);
}
}
return token;
} // CPPpragma
void readCPPline(void)
{
int token = Cg->currentInput->scan(Cg->currentInput);
if (token == IDENT_SY) {
if (yylval.sc_ident == defineAtom) {
token = CPPdefine();
} else if (yylval.sc_ident == elseAtom) {
if (!ifdepth)
SemanticWarning(Cg->tokenLoc, WARNING___CPP_IF_MISMATCH, "else");
token = CPPelse(0);
} else if (yylval.sc_ident == elifAtom) {
if (!ifdepth)
SemanticWarning(Cg->tokenLoc, WARNING___CPP_IF_MISMATCH, "elif");
token = CPPelse(0);
} else if (yylval.sc_ident == endifAtom) {
if (!ifdepth)
SemanticWarning(Cg->tokenLoc, WARNING___CPP_IF_MISMATCH, "endif");
else
ifdepth--;
} else if (yylval.sc_ident == ifAtom) {
token = CPPif();
} else if (yylval.sc_ident == ifdefAtom) {
token = CPPifdef(1);
} else if (yylval.sc_ident == ifndefAtom) {
token = CPPifdef(0);
} else if (yylval.sc_ident == includeAtom) {
token = CPPinclude();
} else if (yylval.sc_ident == lineAtom) {
token = CPPline(Cg->currentInput->scan(Cg->currentInput));
} else if (yylval.sc_ident == pragmaAtom) {
token = CPPpragma();
} else if (yylval.sc_ident == undefAtom) {
token = CPPundef();
} else {
SemanticError(Cg->tokenLoc, ERROR___CPP_UNKNOWN_DIRECTIVE,
GetAtomString(atable, yylval.sc_ident));
}
} else if (token == INTCONST_SY) {
token = CPPline(token);
}
while (token != '\n' && token != 0 /* EOF */) {
token = Cg->currentInput->scan(Cg->currentInput);
}
} // readCPPline
void FreeMacro(MacroSymbol *s) {
DeleteTokenStream(s->body);
}
static int eof_scan(InputSrc *in) { return -1; }
static void noop(InputSrc *in, int ch) { }
static void PushEofSrc() {
InputSrc *in = malloc(sizeof(InputSrc));
memset(in, 0, sizeof(InputSrc));
in->scan = eof_scan;
in->getch = eof_scan;
in->ungetch = noop;
in->prev = Cg->currentInput;
Cg->currentInput = in;
}
static void PopEofSrc() {
if (Cg->currentInput->scan == eof_scan) {
InputSrc *in = Cg->currentInput;
Cg->currentInput = in->prev;
free(in);
}
}
static TokenStream *PrescanMacroArg(TokenStream *a) {
int token;
TokenStream *n;
RewindTokenStream(a);
do {
token = ReadToken(a);
if (token == IDENT_SY && LookUpSymbol(macros, yylval.sc_ident))
break;
} while (token > 0);
if (token <= 0) return a;
n = NewTokenStream("macro arg");
PushEofSrc();
ReadFromTokenStream(a, 0, 0);
while ((token = Cg->currentInput->scan(Cg->currentInput)) > 0) {
if (token == IDENT_SY && MacroExpand(yylval.sc_ident))
continue;
RecordToken(n, token);
}
PopEofSrc();
DeleteTokenStream(a);
return n;
} // PrescanMacroArg
typedef struct MacroInputSrc {
InputSrc base;
MacroSymbol *mac;
TokenStream **args;
} MacroInputSrc;
/* macro_scan ---
** return the next token for a macro expanion, handling macro args
*/
static int macro_scan(MacroInputSrc *in) {
int i;
int token = ReadToken(in->mac->body);
if (token == IDENT_SY) {
for (i = in->mac->argc-1; i>=0; i--)
if (in->mac->args[i] == yylval.sc_ident) break;
if (i >= 0) {
ReadFromTokenStream(in->args[i], yylval.sc_ident, 0);
return Cg->currentInput->scan(Cg->currentInput);
}
}
if (token > 0) return token;
in->mac->busy = 0;
Cg->currentInput = in->base.prev;
if (in->args) {
for (i=in->mac->argc-1; i>=0; i--)
DeleteTokenStream(in->args[i]);
free(in->args);
}
free(in);
return Cg->currentInput->scan(Cg->currentInput);
} // macro_scan
/* MacroExpand
** check an identifier (atom) to see if it a macro that should be expanded.
** If it is, push an InputSrc that will produce the appropriate expandsion
** and return TRUE. If not, return FALSE.
*/
int MacroExpand(int atom)
{
Symbol *sym = LookUpSymbol(macros, atom);
MacroInputSrc *in;
SourceLoc loc = *Cg->tokenLoc;
int i, token, depth;
if (atom == __LINE__Atom) {
yylval.sc_int = Cg->currentInput->line;
UngetToken(INTCONST_SY);
return 1;
}
if (atom == __FILE__Atom) {
yylval.sc_ident = Cg->currentInput->name;
UngetToken(STRCONST_SY);
return 1;
}
if (!sym || sym->details.mac.undef) return 0;
if (sym->details.mac.busy) return 0; // no recursive expansions
in = malloc(sizeof(*in));
memset(in, 0, sizeof(*in));
in->base.scan = (void *)macro_scan;
in->base.line = Cg->currentInput->line;
in->base.name = Cg->currentInput->name;
in->mac = &sym->details.mac;
if (sym->details.mac.args) {
token = Cg->currentInput->scan(Cg->currentInput);
if (token != '(') {
UngetToken(token);
yylval.sc_ident = atom;
return 0;
}
in->args = malloc(in->mac->argc * sizeof(TokenStream *));
for (i=0; i<in->mac->argc; i++)
in->args[i] = NewTokenStream("macro arg");
for (i=0; i<in->mac->argc; i++) {
depth = 0;
while(1) {
token = Cg->currentInput->scan(Cg->currentInput);
if (token <= 0) {
SemanticError(&loc, ERROR___CPP_MACRO_EOF,
GetAtomString(atable, atom));
return 1;
}
if (depth == 0 && (token == ',' || token == ')')) break;
if (token == '(') depth++;
if (token == ')') depth--;
RecordToken(in->args[i], token);
}
if (token == ')') {
i++;
break;
}
}
if (i < in->mac->argc) {
SemanticError(&loc, ERROR___CPP_MACRO_TOOFEW,
GetAtomString(atable, atom));
} else if (token != ')') {
while (token >= 0 && (depth > 0 || token != ')')) {
if (token == ')') depth--;
token = Cg->currentInput->scan(Cg->currentInput);
if (token == '(') depth++;
}
if (token <= 0) {
SemanticError(&loc, ERROR___CPP_MACRO_EOF,
GetAtomString(atable, atom));
return 1;
}
SemanticError(&loc, ERROR___CPP_MACRO_TOOMANY,
GetAtomString(atable, atom));
}
for (i=0; i<in->mac->argc; i++) {
in->args[i] = PrescanMacroArg(in->args[i]);
}
}
#if 0
printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
loc.line, GetAtomString(atable, atom));
for (i=0; i<in->mac->argc; i++) {
printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
DumpTokenStream(stdout, in->args[i]);
printf("'\n");
}
#endif
in->base.prev = Cg->currentInput;
sym->details.mac.busy = 1;
RewindTokenStream(sym->details.mac.body);
Cg->currentInput = &in->base;
return 1;
} // MacroExpand
/* PredefineMacro
** define a macro (no args) based on the input string, as from a -D
** argument. The string is either "NAME=expansion" or just "NAME", which
** is equivalent to "NAME=1". Return TRUE if everything is ok, or
** FALSE if the string is malformed.
*/
int PredefineMacro(char *def) {
char *name = def;
MacroSymbol mac;
Symbol *symb;
SourceLoc dummyLoc;
while (isalnum(*def) || *def == '_') def++;
if (def != name && *def == '=') {
*def = 0;
def++;
} else if (def == name || *def != 0) {
return 0;
} else {
def = 0;
}
memset(&mac, 0, sizeof(mac));
mac.body = NewTokenStream(name);
if (def) {
int token;
PushEofSrc();
ScanFromString(def);
while ((token = Cg->currentInput->scan(Cg->currentInput)) > 0)
RecordToken(mac.body, token);
PopEofSrc();
} else {
yylval.sc_int = 1;
RecordToken(mac.body, INTCONST_SY);
}
symb = LookUpSymbol(macros, LookUpAddString(atable, name));
if (symb) {
FreeMacro(&symb->details.mac);
} else {
dummyLoc.file = 0;
dummyLoc.line = 0;
symb = AddSymbol(&dummyLoc, macros, LookUpAddString(atable, name), 0, MACRO_S);
}
symb->details.mac = mac;
if (def) {
// undo change to arg string
def[-1] = '=';
}
return 1;
} // PredefineMacro
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -