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

📄 preproc.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
    return false;
}

/*
 * Open an include file. This routine must always return a valid
 * file pointer if it returns - it's responsible for throwing an
 * ERR_FATAL and bombing out completely if not. It should also try
 * the include path one by one until it finds the file or reaches
 * the end of the path.
 */
static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
		       bool missing_ok)
{
    FILE *fp;
    char *prefix = "";
    IncPath *ip = ipath;
    int len = strlen(file);
    size_t prefix_len = 0;
    StrList *sl;

    while (1) {
        sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
	memcpy(sl->str, prefix, prefix_len);
	memcpy(sl->str+prefix_len, file, len+1);
        fp = fopen(sl->str, "r");
	if (fp && dhead && !in_list(*dhead, sl->str)) {
	    sl->next = NULL;
	    **dtail = sl;
	    *dtail = &sl->next;
        } else {
	    nasm_free(sl);
	}
        if (fp)
            return fp;
	if (!ip) {
	    if (!missing_ok)
		break;
	    prefix = NULL;
	} else {
	    prefix = ip->path;
	    ip = ip->next;
	}
	if (prefix) {
	    prefix_len = strlen(prefix);
	} else {
	    /* -MG given and file not found */
	    if (dhead && !in_list(*dhead, file)) {
		sl = nasm_malloc(len+1+sizeof sl->next);
		sl->next = NULL;
		strcpy(sl->str, file);
		**dtail = sl;
		*dtail = &sl->next;
	    }
	    return NULL;
	}
    }

    error(ERR_FATAL, "unable to open include file `%s'", file);
    return NULL;                /* never reached - placate compilers */
}

/*
 * Determine if we should warn on defining a single-line macro of
 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
 * return true if _any_ single-line macro of that name is defined.
 * Otherwise, will return true if a single-line macro with either
 * `nparam' or no parameters is defined.
 *
 * If a macro with precisely the right number of parameters is
 * defined, or nparam is -1, the address of the definition structure
 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
 * is NULL, no action will be taken regarding its contents, and no
 * error will occur.
 *
 * Note that this is also called with nparam zero to resolve
 * `ifdef'.
 *
 * 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 bool
smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
               bool nocase)
{
    struct hash_table *smtbl;
    SMacro *m;

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

    while (m) {
        if (!mstrcmp(m->name, name, m->casesense && nocase) &&
            (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
            if (defn) {
                if (nparam == (int) 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) {
	/* +1: we need space for the final NULL */
        if (*nparam+1 >= 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 (true) {
            skip_white_(tline);
            if (!tline)
                break;
            if (tline->type != TOK_ID) {
                error(ERR_NONFATAL,
                      "`%s' expects context identifiers", pp_directives[ct]);
                free_tlist(origline);
                return -1;
            }
            if (cstk && cstk->name && !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;
            }
            /* When comparing strings, need to unquote them first */
            if (t->type == TOK_STRING) {
		size_t l1 = nasm_unquote(t->text, NULL);
		size_t l2 = nasm_unquote(tt->text, NULL);

		if (l1 != l2) {
		    j = false;
		    break;
		}
		if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
		    j = false;
		    break;
		}
            } else 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;
	    }
            if(tline && tline->next)
                error(ERR_WARNING|ERR_PASS1,
		      "trailing garbage after %%ifmacro ignored");
            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:
	t = tline = expand_smacro(tline);

	while (tok_type_(t, TOK_WHITESPACE) ||
	       (needtype == TOK_NUMBER &&
		tok_type_(t, TOK_OTHER) &&
		(t->text[0] == '-' || t->text[0] == '+') &&
		!t->text[1]))
	    t = t->next;

	j = tok_type_(t, needtype);
	break;

    case PPC_IFTOKEN:
	t = tline = expand_smacro(tline);
	while (tok_type_(t, TOK_WHITESPACE))
	    t = t->next;

	j = false;
	if (t) {
	    t = t->next;	/* Skip the actual token */
	    while (tok_type_(t, TOK_WHITESPACE))
		t = t->next;
	    j = !t;		/* Should be nothing left */
	}
	break;

    case PPC_IFEMPTY:
	t = tline = expand_smacro(tline);
	while (tok_type_(t, TOK_WHITESPACE))
	    t = t->next;

	j = !t;			/* Should be empty */
	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|ERR_PASS1,
                  "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;
	break;

    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;
}

/*

⌨️ 快捷键说明

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