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

📄 cpp.c

📁 nVidia开发的图形语言 Cg
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
    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 + -