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

📄 preproc.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 bool
smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
               bool 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 = (SMacro *) hash_findix(smacros, 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 bool if_condition(Token * tline, enum preproc_token ct)
{
    enum pp_conditional i = PP_COND(ct);
    bool j;
    Token *t, *tt, **tptr, *origline;
    struct tokenval tokval;
    expr *evalresult;
    enum pp_token_type needtype;

    origline = tline;

    switch (i) {
    case PPC_IFCTX:
        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", pp_directives[ct]);
                free_tlist(origline);
                return -1;
            }
            if (!nasm_stricmp(tline->text, cstk->name))
                j = true;
            tline = tline->next;
        }
	break;

    case PPC_IFDEF:
        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", pp_directives[ct]);
		goto fail;
            }
            if (smacro_defined(NULL, tline->text, 0, NULL, true))
                j = true;
            tline = tline->next;
        }
	break;

    case PPC_IFIDN:
    case PPC_IFIDNI:
        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",
                  pp_directives[ct]);
	    goto fail;
        }
        tt = tt->next;
        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",
                      pp_directives[ct]);
		goto fail;
            }
            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, i == PPC_IFIDN) != 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 */
	break;

    case PPC_IFMACRO:
        {
            bool found = false;
            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", pp_directives[ct]);
		goto fail;
            }
            searching.name = nasm_strdup(tline->text);
            searching.casesense = true;
            searching.plus = false;
            searching.nolist = false;
            searching.in_progress = 0;
            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",
                      pp_directives[ct]);
            } 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 `-'",
                          pp_directives[ct]);
                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 = (MMacro *) hash_findix(mmacros, 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);
	    j = found;
	    break;
        }

    case PPC_IFID:
	needtype = TOK_ID;
	goto iftype;
    case PPC_IFNUM:
	needtype = TOK_NUMBER;
	goto iftype;
    case PPC_IFSTR:
	needtype = TOK_STRING;
	goto iftype;

    iftype:
        tline = expand_smacro(tline);
        t = tline;
        while (tok_type_(t, TOK_WHITESPACE))
            t = t->next;
        j = false;              /* placate optimiser */
        if (t)
	    j = t->type == needtype;
	break;

    case PPC_IF:
        t = tline = expand_smacro(tline);
        tptr = &t;
        tokval.t_type = TOKEN_INVALID;
        evalresult = evaluate(ppscan, tptr, &tokval,
                              NULL, pass | CRITICAL, error, NULL);
        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'", pp_directives[ct]);
	    goto fail;
        }
        j = reloc_value(evalresult) != 0;
        return j;

    default:
        error(ERR_FATAL,
              "preprocessor directive `%s' not yet implemented",
              pp_directives[ct]);
	goto fail;
    }

    free_tlist(origline);
    return j ^ PP_NEGATIVE(ct);
    
fail:
    free_tlist(origline);
    return -1;
}

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

/*
 * Common code for defining an smacro
 */
static bool define_smacro(Context *ctx, char *mname, bool casesense,
			  int nparam, Token *expansion)
{
    SMacro *smac, **smhead;
    
    if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
	if (!smac) {
	    error(ERR_WARNING,
		  "single-line macro `%s' defined both with and"
		  " without parameters", mname);

	    /* Some instances of the old code considered this a failure,
	       some others didn't.  What is the right thing to do here? */
	    free_tlist(expansion);
	    return false;	/* Failure */
	} else {
	    /*
	     * We're redefining, so we have to take over an
	     * existing SMacro structure. This means freeing
	     * what was already in it.
	     */
	    nasm_free(smac->name);
	    free_tlist(smac->expansion);
	}
    } else {
	if (!ctx)
	    smhead = (SMacro **) hash_findi_add(smacros, mname);
	else
	    smhead = &ctx->localmac;
	
	smac = nasm_malloc(sizeof(SMacro));
	smac->next = *smhead;
	*smhead = smac;
    }
    smac->name = nasm_strdup(mname);
    smac->casesense = casesense;
    smac->nparam = nparam;
    smac->expansion = expansion;
    smac->in_progress = false;
    return true;		/* Success */
}

/*
 * Undefine an smacro
 */
static void undef_smacro(Context *ctx, const char *mname)
{
    SMacro **smhead, *s, **sp;

    if (!ctx)
	smhead = (SMacro **) hash_findi(smacros, mname, NULL);
    else
	smhead = &ctx->localmac;
    
    if (smhead) {
	/*
	 * We now have a macro name... go hunt for it.
	 */
	sp = smhead;
	while ((s = *sp) != NULL) {
	    if (!mstrcmp(s->name, mname, s->casesense)) {
		*sp = s->next;
		nasm_free(s->name);
		free_tlist(s->expansion);
		nasm_free(s);
	    } else {
		sp = &s->next;
	    }
	}
    }
}

/**
 * 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)
{
    enum preproc_token i;
    int j;

⌨️ 快捷键说明

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