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

📄 preproc.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
 * If you already know which context macro belongs to, you can pass
 * the context pointer as first parameter; if you won't but name begins
 * with %$ the context will be automatically computed. If all_contexts
 * is true, macro will be searched in outer contexts as well.
 */
static int
smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
               int nocase)
{
    SMacro *m;

    if (ctx)
        m = ctx->localmac;
    else if (name[0] == '%' && name[1] == '$') {
        if (cstk)
            ctx = get_ctx(name, FALSE);
        if (!ctx)
            return FALSE;       /* got to return _something_ */
        m = ctx->localmac;
    } else
        m = smacros[hash(name)];

    while (m) {
        if (!mstrcmp(m->name, name, m->casesense && nocase) &&
            (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
            if (defn) {
                if (nparam == m->nparam || nparam == -1)
                    *defn = m;
                else
                    *defn = NULL;
            }
            return TRUE;
        }
        m = m->next;
    }

    return FALSE;
}

/*
 * Count and mark off the parameters in a multi-line macro call.
 * This is called both from within the multi-line macro expansion
 * code, and also to mark off the default parameters when provided
 * in a %macro definition line.
 */
static void count_mmac_params(Token * t, int *nparam, Token *** params)
{
    int paramsize, brace;

    *nparam = paramsize = 0;
    *params = NULL;
    while (t) {
        if (*nparam >= paramsize) {
            paramsize += PARAM_DELTA;
            *params = nasm_realloc(*params, sizeof(**params) * paramsize);
        }
        skip_white_(t);
        brace = FALSE;
        if (tok_is_(t, "{"))
            brace = TRUE;
        (*params)[(*nparam)++] = t;
        while (tok_isnt_(t, brace ? "}" : ","))
            t = t->next;
        if (t) {                /* got a comma/brace */
            t = t->next;
            if (brace) {
                /*
                 * Now we've found the closing brace, look further
                 * for the comma.
                 */
                skip_white_(t);
                if (tok_isnt_(t, ",")) {
                    error(ERR_NONFATAL,
                          "braces do not enclose all of macro parameter");
                    while (tok_isnt_(t, ","))
                        t = t->next;
                }
                if (t)
                    t = t->next;        /* eat the comma */
            }
        }
    }
}

/*
 * Determine whether one of the various `if' conditions is true or
 * not.
 *
 * We must free the tline we get passed.
 */
static int if_condition(Token * tline, int i)
{
    int j, casesense;
    Token *t, *tt, **tptr, *origline;
    struct tokenval tokval;
    expr *evalresult;

    origline = tline;

    switch (i) {
    case PP_IFCTX:
    case PP_ELIFCTX:
    case PP_IFNCTX:
    case PP_ELIFNCTX:
        j = FALSE;              /* have we matched yet? */
        while (cstk && tline) {
            skip_white_(tline);
            if (!tline || tline->type != TOK_ID) {
                error(ERR_NONFATAL,
                      "`%s' expects context identifiers", directives[i]);
                free_tlist(origline);
                return -1;
            }
            if (!nasm_stricmp(tline->text, cstk->name))
                j = TRUE;
            tline = tline->next;
        }
        if (i == PP_IFNCTX || i == PP_ELIFNCTX)
            j = !j;
        free_tlist(origline);
        return j;

    case PP_IFDEF:
    case PP_ELIFDEF:
    case PP_IFNDEF:
    case PP_ELIFNDEF:
        j = FALSE;              /* have we matched yet? */
        while (tline) {
            skip_white_(tline);
            if (!tline || (tline->type != TOK_ID &&
                           (tline->type != TOK_PREPROC_ID ||
                            tline->text[1] != '$'))) {
                error(ERR_NONFATAL,
                      "`%s' expects macro identifiers", directives[i]);
                free_tlist(origline);
                return -1;
            }
            if (smacro_defined(NULL, tline->text, 0, NULL, 1))
                j = TRUE;
            tline = tline->next;
        }
        if (i == PP_IFNDEF || i == PP_ELIFNDEF)
            j = !j;
        free_tlist(origline);
        return j;

    case PP_IFIDN:
    case PP_ELIFIDN:
    case PP_IFNIDN:
    case PP_ELIFNIDN:
    case PP_IFIDNI:
    case PP_ELIFIDNI:
    case PP_IFNIDNI:
    case PP_ELIFNIDNI:
        tline = expand_smacro(tline);
        t = tt = tline;
        while (tok_isnt_(tt, ","))
            tt = tt->next;
        if (!tt) {
            error(ERR_NONFATAL,
                  "`%s' expects two comma-separated arguments",
                  directives[i]);
            free_tlist(tline);
            return -1;
        }
        tt = tt->next;
        casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
                     i == PP_IFNIDN || i == PP_ELIFNIDN);
        j = TRUE;               /* assume equality unless proved not */
        while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
            if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
                error(ERR_NONFATAL, "`%s': more than one comma on line",
                      directives[i]);
                free_tlist(tline);
                return -1;
            }
            if (t->type == TOK_WHITESPACE) {
                t = t->next;
                continue;
            }
            if (tt->type == TOK_WHITESPACE) {
                tt = tt->next;
                continue;
            }
            if (tt->type != t->type) {
                j = FALSE;      /* found mismatching tokens */
                break;
            }
            /* Unify surrounding quotes for strings */
            if (t->type == TOK_STRING) {
                tt->text[0] = t->text[0];
                tt->text[strlen(tt->text) - 1] = t->text[0];
            }
            if (mstrcmp(tt->text, t->text, casesense) != 0) {
                j = FALSE;      /* found mismatching tokens */
                break;
            }

            t = t->next;
            tt = tt->next;
        }
        if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
            j = FALSE;          /* trailing gunk on one end or other */
        if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
            i == PP_IFNIDNI || i == PP_ELIFNIDNI)
            j = !j;
        free_tlist(tline);
        return j;

    case PP_IFMACRO:
    case PP_ELIFMACRO:
    case PP_IFNMACRO:
    case PP_ELIFNMACRO:
        {
            int found = 0;
            MMacro searching, *mmac;

            tline = tline->next;
            skip_white_(tline);
            tline = expand_id(tline);
            if (!tok_type_(tline, TOK_ID)) {
                error(ERR_NONFATAL,
                      "`%s' expects a macro name", directives[i]);
                return -1;
            }
            searching.name = nasm_strdup(tline->text);
            searching.casesense = (i == PP_MACRO);
            searching.plus = FALSE;
            searching.nolist = FALSE;
            searching.in_progress = FALSE;
            searching.rep_nest = NULL;
            searching.nparam_min = 0;
            searching.nparam_max = INT_MAX;
            tline = expand_smacro(tline->next);
            skip_white_(tline);
            if (!tline) {
            } else if (!tok_type_(tline, TOK_NUMBER)) {
                error(ERR_NONFATAL,
                      "`%s' expects a parameter count or nothing",
                      directives[i]);
            } else {
                searching.nparam_min = searching.nparam_max =
                    readnum(tline->text, &j);
                if (j)
                    error(ERR_NONFATAL,
                          "unable to parse parameter count `%s'",
                          tline->text);
            }
            if (tline && tok_is_(tline->next, "-")) {
                tline = tline->next->next;
                if (tok_is_(tline, "*"))
                    searching.nparam_max = INT_MAX;
                else if (!tok_type_(tline, TOK_NUMBER))
                    error(ERR_NONFATAL,
                          "`%s' expects a parameter count after `-'",
                          directives[i]);
                else {
                    searching.nparam_max = readnum(tline->text, &j);
                    if (j)
                        error(ERR_NONFATAL,
                              "unable to parse parameter count `%s'",
                              tline->text);
                    if (searching.nparam_min > searching.nparam_max)
                        error(ERR_NONFATAL,
                              "minimum parameter count exceeds maximum");
                }
            }
            if (tline && tok_is_(tline->next, "+")) {
                tline = tline->next;
                searching.plus = TRUE;
            }
            mmac = mmacros[hash(searching.name)];
            while (mmac) {
                if (!strcmp(mmac->name, searching.name) &&
                    (mmac->nparam_min <= searching.nparam_max
                     || searching.plus)
                    && (searching.nparam_min <= mmac->nparam_max
                        || mmac->plus)) {
                    found = TRUE;
                    break;
                }
                mmac = mmac->next;
            }
            nasm_free(searching.name);
            free_tlist(origline);
            if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
                found = !found;
            return found;
        }

    case PP_IFID:
    case PP_ELIFID:
    case PP_IFNID:
    case PP_ELIFNID:
    case PP_IFNUM:
    case PP_ELIFNUM:
    case PP_IFNNUM:
    case PP_ELIFNNUM:
    case PP_IFSTR:
    case PP_ELIFSTR:
    case PP_IFNSTR:
    case PP_ELIFNSTR:
        tline = expand_smacro(tline);
        t = tline;
        while (tok_type_(t, TOK_WHITESPACE))
            t = t->next;
        j = FALSE;              /* placate optimiser */
        if (t)
            switch (i) {
            case PP_IFID:
            case PP_ELIFID:
            case PP_IFNID:
            case PP_ELIFNID:
                j = (t->type == TOK_ID);
                break;
            case PP_IFNUM:
            case PP_ELIFNUM:
            case PP_IFNNUM:
            case PP_ELIFNNUM:
                j = (t->type == TOK_NUMBER);
                break;
            case PP_IFSTR:
            case PP_ELIFSTR:
            case PP_IFNSTR:
            case PP_ELIFNSTR:
                j = (t->type == TOK_STRING);
                break;
            }
        if (i == PP_IFNID || i == PP_ELIFNID ||
            i == PP_IFNNUM || i == PP_ELIFNNUM ||
            i == PP_IFNSTR || i == PP_ELIFNSTR)
            j = !j;
        free_tlist(tline);
        return j;

    case PP_IF:
    case PP_ELIF:
        t = tline = expand_smacro(tline);
        tptr = &t;
        tokval.t_type = TOKEN_INVALID;
        evalresult = evaluate(ppscan, tptr, &tokval,
                              NULL, pass | CRITICAL, error, NULL);
        free_tlist(tline);
        if (!evalresult)
            return -1;
        if (tokval.t_type)
            error(ERR_WARNING,
                  "trailing garbage after expression ignored");
        if (!is_simple(evalresult)) {
            error(ERR_NONFATAL,
                  "non-constant value given to `%s'", directives[i]);
            return -1;
        }
        return reloc_value(evalresult) != 0;

    default:
        error(ERR_FATAL,
              "preprocessor directive `%s' not yet implemented",
              directives[i]);
        free_tlist(origline);
        return -1;              /* yeah, right */
    }
}

/*
 * Expand macros in a string. Used in %error and %include directives.
 * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
 * The returned variable should ALWAYS be freed after usage.
 */
void expand_macros_in_string(char **p)
{
    Token *line = tokenise(*p);
    line = expand_smacro(line);
    *p = detoken(line, FALSE);
}

/**
 * find and process preprocessor directive in passed line
 * Find out if a line contains a preprocessor directive, and deal
 * with it if so.
 * 
 * If a directive _is_ found, it is the responsibility of this routine
 * (and not the caller) to free_tlist() the line.
 *
 * @param tline a pointer to the current tokeninzed line linked list
 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
 * 
 */
static int do_directive(Token * tline)
{
    int i, j, k, m, nparam, nolist;
    int offset;
    char *p, *mname;
    Include *inc;
    Context *ctx;
    Cond *cond;
    SMacro *smac, **smhead;
    MMacro *mmac;
    Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
    Line *l;
    struct tokenval tokval;
    expr *evalresult;
    MMacro *tmp_defining;       /* Used when manipulating rep_nest */

    origline = tline;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -