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

📄 preproc.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 5 页
字号:
		    size = MAX(StackSize, 10);
		}
		else
		{
		    error(ERR_NONFATAL,
			    "Invalid size type for `%%local' missing directive");
		    free_tlist(tt);
		    free_tlist(origline);
		    return DIRECTIVE_FOUND;
		}
		free_tlist(tt);

		/* Now define the macro for the argument */
		sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
			offset);
		do_directive(tokenise(directive));
		offset += size;

		/* Now define the assign to setup the enter_c macro correctly */
		sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
			size);
		do_directive(tokenise(directive));

		/* Move to the next argument in the list */
		tline = tline->next;
		if (tline && tline->type == TOK_WHITESPACE)
		    tline = tline->next;
	    }
	    while (tline && tline->type == TOK_OTHER
		    && tline->text[0] == ',');
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_CLEAR:
	    if (tline->next)
		error(ERR_WARNING,
			"trailing garbage after `%%clear' ignored");
	    for (j = 0; j < NHASH; j++)
	    {
		while (mmacros[j])
		{
		    MMacro *m = mmacros[j];
		    mmacros[j] = m->next;
		    free_mmacro(m);
		}
		while (smacros[j])
		{
		    SMacro *s = smacros[j];
		    smacros[j] = smacros[j]->next;
		    nasm_free(s->name);
		    free_tlist(s->expansion);
		    nasm_free(s);
		}
	    }
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_INCLUDE:
	    tline = tline->next;
	    skip_white_(tline);
	    if (!tline || (tline->type != TOK_STRING &&
			    tline->type != TOK_INTERNAL_STRING))
	    {
		error(ERR_NONFATAL, "`%%include' expects a file name");
		free_tlist(origline);
		return DIRECTIVE_FOUND;	/* but we did _something_ */
	    }
	    if (tline->next)
		error(ERR_WARNING,
			"trailing garbage after `%%include' ignored");
	    if (tline->type != TOK_INTERNAL_STRING)
	    {
		p = tline->text + 1;	/* point past the quote to the name */
		p[strlen(p) - 1] = '\0';	/* remove the trailing quote */
	    }
	    else
		p = tline->text;	/* internal_string is easier */
	    expand_macros_in_string(&p);
	    inc = nasm_malloc(sizeof(Include));
	    inc->next = istk;
	    inc->conds = NULL;
	    inc->fp = inc_fopen(p);
	    inc->fname = src_set_fname(p);
	    inc->lineno = src_set_linnum(0);
	    inc->lineinc = 1;
	    inc->expansion = NULL;
	    inc->mstk = NULL;
	    istk = inc;
	    list->uplevel(LIST_INCLUDE);
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_PUSH:
	    tline = tline->next;
	    skip_white_(tline);
	    tline = expand_id(tline);
	    if (!tok_type_(tline, TOK_ID))
	    {
		error(ERR_NONFATAL, "`%%push' expects a context identifier");
		free_tlist(origline);
		return DIRECTIVE_FOUND;	/* but we did _something_ */
	    }
	    if (tline->next)
		error(ERR_WARNING, "trailing garbage after `%%push' ignored");
	    ctx = nasm_malloc(sizeof(Context));
	    ctx->next = cstk;
	    ctx->localmac = NULL;
	    ctx->name = nasm_strdup(tline->text);
	    ctx->number = unique++;
	    cstk = ctx;
	    free_tlist(origline);
	    break;

	case PP_REPL:
	    tline = tline->next;
	    skip_white_(tline);
	    tline = expand_id(tline);
	    if (!tok_type_(tline, TOK_ID))
	    {
		error(ERR_NONFATAL, "`%%repl' expects a context identifier");
		free_tlist(origline);
		return DIRECTIVE_FOUND;	/* but we did _something_ */
	    }
	    if (tline->next)
		error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
	    if (!cstk)
		error(ERR_NONFATAL, "`%%repl': context stack is empty");
	    else
	    {
		nasm_free(cstk->name);
		cstk->name = nasm_strdup(tline->text);
	    }
	    free_tlist(origline);
	    break;

	case PP_POP:
	    if (tline->next)
		error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
	    if (!cstk)
		error(ERR_NONFATAL,
			"`%%pop': context stack is already empty");
	    else
		ctx_pop();
	    free_tlist(origline);
	    break;

	case PP_ERROR:
	    tline->next = expand_smacro(tline->next);
	    tline = tline->next;
	    skip_white_(tline);
	    if (tok_type_(tline, TOK_STRING))
	    {
		p = tline->text + 1;	/* point past the quote to the name */
		p[strlen(p) - 1] = '\0';	/* remove the trailing quote */
		expand_macros_in_string(&p);
		error(ERR_NONFATAL, "%s", p);
		nasm_free(p);
	    }
	    else
	    {
		p = detoken(tline, FALSE);
		error(ERR_WARNING, "%s", p);
		nasm_free(p);
	    }
	    free_tlist(origline);
	    break;

	case PP_IF:
	case PP_IFCTX:
	case PP_IFDEF:
	case PP_IFID:
	case PP_IFIDN:
	case PP_IFIDNI:
        case PP_IFMACRO:
	case PP_IFNCTX:
	case PP_IFNDEF:
	case PP_IFNID:
	case PP_IFNIDN:
	case PP_IFNIDNI:
        case PP_IFNMACRO:
	case PP_IFNNUM:
	case PP_IFNSTR:
	case PP_IFNUM:
	case PP_IFSTR:
	    if (istk->conds && !emitting(istk->conds->state))
		j = COND_NEVER;
	    else
	    {
		j = if_condition(tline->next, i);
		tline->next = NULL;	/* it got freed */
		free_tlist(origline);
		j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
	    }
	    cond = nasm_malloc(sizeof(Cond));
	    cond->next = istk->conds;
	    cond->state = j;
	    istk->conds = cond;
	    return DIRECTIVE_FOUND;

	case PP_ELIF:
	case PP_ELIFCTX:
	case PP_ELIFDEF:
	case PP_ELIFID:
	case PP_ELIFIDN:
	case PP_ELIFIDNI:
        case PP_ELIFMACRO:
	case PP_ELIFNCTX:
	case PP_ELIFNDEF:
	case PP_ELIFNID:
	case PP_ELIFNIDN:
	case PP_ELIFNIDNI:
        case PP_ELIFNMACRO:
	case PP_ELIFNNUM:
	case PP_ELIFNSTR:
	case PP_ELIFNUM:
	case PP_ELIFSTR:
	    if (!istk->conds)
		error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
	    if (emitting(istk->conds->state)
		    || istk->conds->state == COND_NEVER)
		istk->conds->state = COND_NEVER;
	    else
	    {
		/*
		 * IMPORTANT: In the case of %if, we will already have
		 * called expand_mmac_params(); however, if we're
		 * processing an %elif we must have been in a
		 * non-emitting mode, which would have inhibited
		 * the normal invocation of expand_mmac_params().  Therefore,
		 * we have to do it explicitly here.
		 */
		 j = if_condition(expand_mmac_params(tline->next), i);
		 tline->next = NULL; /* it got freed */
		free_tlist(origline);
		istk->conds->state =
			j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
	    }
	    return DIRECTIVE_FOUND;

	case PP_ELSE:
	    if (tline->next)
		error(ERR_WARNING, "trailing garbage after `%%else' ignored");
	    if (!istk->conds)
		error(ERR_FATAL, "`%%else': no matching `%%if'");
	    if (emitting(istk->conds->state)
		    || istk->conds->state == COND_NEVER)
		istk->conds->state = COND_ELSE_FALSE;
	    else
		istk->conds->state = COND_ELSE_TRUE;
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_ENDIF:
	    if (tline->next)
		error(ERR_WARNING,
			"trailing garbage after `%%endif' ignored");
	    if (!istk->conds)
		error(ERR_FATAL, "`%%endif': no matching `%%if'");
	    cond = istk->conds;
	    istk->conds = cond->next;
	    nasm_free(cond);
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_MACRO:
	case PP_IMACRO:
	    if (defining)
		error(ERR_FATAL,
			"`%%%smacro': already defining a macro",
			(i == PP_IMACRO ? "i" : ""));
	    tline = tline->next;
	    skip_white_(tline);
	    tline = expand_id(tline);
	    if (!tok_type_(tline, TOK_ID))
	    {
		error(ERR_NONFATAL,
			"`%%%smacro' expects a macro name",
			(i == PP_IMACRO ? "i" : ""));
		return DIRECTIVE_FOUND;
	    }
	    defining = nasm_malloc(sizeof(MMacro));
	    defining->name = nasm_strdup(tline->text);
	    defining->casesense = (i == PP_MACRO);
	    defining->plus = FALSE;
	    defining->nolist = FALSE;
	    defining->in_progress = FALSE;
	    defining->rep_nest = NULL;
	    tline = expand_smacro(tline->next);
	    skip_white_(tline);
	    if (!tok_type_(tline, TOK_NUMBER))
	    {
		error(ERR_NONFATAL,
			"`%%%smacro' expects a parameter count",
			(i == PP_IMACRO ? "i" : ""));
		defining->nparam_min = defining->nparam_max = 0;
	    }
	    else
	    {
		defining->nparam_min = defining->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, "*"))
		    defining->nparam_max = INT_MAX;
		else if (!tok_type_(tline, TOK_NUMBER))
		    error(ERR_NONFATAL,
			    "`%%%smacro' expects a parameter count after `-'",
			    (i == PP_IMACRO ? "i" : ""));
		else
		{
		    defining->nparam_max = readnum(tline->text, &j);
		    if (j)
			error(ERR_NONFATAL,
				"unable to parse parameter count `%s'",
				tline->text);
		    if (defining->nparam_min > defining->nparam_max)
			error(ERR_NONFATAL,
				"minimum parameter count exceeds maximum");
		}
	    }
	    if (tline && tok_is_(tline->next, "+"))
	    {
		tline = tline->next;
		defining->plus = TRUE;
	    }
	    if (tline && tok_type_(tline->next, TOK_ID) &&
		    !nasm_stricmp(tline->next->text, ".nolist"))
	    {
		tline = tline->next;
		defining->nolist = TRUE;
	    }
	    mmac = mmacros[hash(defining->name)];
	    while (mmac)
	    {
		if (!strcmp(mmac->name, defining->name) &&
			(mmac->nparam_min <= defining->nparam_max
				|| defining->plus)
			&& (defining->nparam_min <= mmac->nparam_max
				|| mmac->plus))
		{
		    error(ERR_WARNING,
			    "redefining multi-line macro `%s'",
			    defining->name);
		    break;
		}
		mmac = mmac->next;
	    }
	    /*
	     * Handle default parameters.
	     */
	    if (tline && tline->next)
	    {
		defining->dlist = tline->next;
		tline->next = NULL;
		count_mmac_params(defining->dlist, &defining->ndefs,
			&defining->defaults);
	    }
	    else
	    {
		defining->dlist = NULL;
		defining->defaults = NULL;
	    }
	    defining->expansion = NULL;
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_ENDM:
	case PP_ENDMACRO:
	    if (!defining)
	    {
		error(ERR_NONFATAL, "`%s': not defining a macro",
			tline->text);
		return DIRECTIVE_FOUND;
	    }
	    k = hash(defining->name);
	    defining->next = mmacros[k];
	    mmacros[k] = defining;
	    defining = NULL;
	    free_tlist(origline);
	    return DIRECTIVE_FOUND;

	case PP_ROTATE:
	    if (tline->next && tline->next->type == TOK_WHITESPACE)
		tline = tline->next;
	    if (tline->next == NULL)
	    {
		free_tlist(origline);
		error(ERR_NONFATAL, "`%%rotate' missing rotate count");
		return DIRECTIVE_FOUND;
	    }
	    t = expand_smacro(tline->next);
	    tline->next = NULL;
	    free_tlist(origline);
	    tline = t;
	    tptr = &t;
	    tokval.t_type = TOKEN_INVALID;
	    evalresult =
		    evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
	    free_tlist(tline);
	    if (!evalresult)
		return DIRECTIVE_FOUND;
	    if (tokval.t_type)
		error(ERR_WARNING,
			"trailing garbage after expression ignored");
	    if (!is_simple(evalresult))
	    {
		error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
		return DIRECTIVE_FOUND;
	    }
	    mmac = istk->mstk;
	    while (mmac && !mmac->name)	/* avoid mistaking %reps for macros */
		mmac = mmac->next_active;
	    if (!mmac)
	    {
		error(ERR_NONFATAL,
			"`%%rotate' invoked outside a macro call");
	    } 
	    else if (mmac->nparam == 0)
	    {
		error(ERR_NONFATAL,
			"`%%rotate' invoked within macro without parameters");
	    }
	    else
	    {
		mmac->rotate = mmac->rotate + reloc_value(evalresult);
		
		if (mmac->rotate < 0)
		    mmac->rotate = 
			mmac->nparam - (-mmac->rotate) % mmac->nparam;
		mmac->rotate %= mmac->nparam;
	    }
	    return DIRECTIVE_FOUND;

	case PP_REP:
	    nolist = FALSE;
	    do {
		tline = tline->next;
	    } while (tok_type_(tline, TOK_WHITESPACE));

	    if (tok_type_(tline, TOK_ID) &&
		nasm_stricmp(tline->text, ".nolist") == 0)
	    {
		nolist = TRUE;
		do {
		    tline = tline->next;
		} while (tok_type_(tline, TOK_WHITESPACE));
	    }

	    if (tline)
	    {
		t = expand_smacro(tline);
		tptr = &t;
		tokval.t_type = TOKEN_INVALID;
		evalresult =
		    evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
		if (!evalresult)
		{
		    free_tlist(origline);
		    return DIRECTIVE_FOUND;
		}
		if (tokval.t_type)
		    error(ERR_WARNING,
			  "trailing garbage after expression ignored");
		if (!is_simple(evalresult))
		{
		    error(ERR_NONFATAL, "non-constant value given to `%%rep'");
		    return DIRECTIVE_FOUND;
		}
		i = (int)reloc_value(evalresult) + 1;
	    }
	    else
	    {
		error(ERR_NONFATAL, "`%%rep' expects a repeat count");
		i = 0;
	    }
	    free_tlist(origline);

	    tmp_defining = defining;
	    defining = nasm_malloc(sizeof(MMacro));
	    defining->name = NULL;	/* flags this macro as a %rep block */
	    defining->casesense = 0;
	    defining->plus = FALSE;
	    defining->nolist = nolist;
	    defining->in_progress = i;
	    defining->nparam_min = defining->nparam_max = 0;
	    defining->defaults = NULL;
	    defining->dlist = NULL;
	    defining->expansion = NULL;
	    defining->next_active = istk->mstk;
	    defining->rep_nest = tmp_defining;
	    return DIRECTIVE_FOUND;

	case PP_ENDREP:
	    if (!defining || defining->name)
	    {
		error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
		return DIRECTIVE_FOUND;
	    }

	    /*
	     * Now we ha

⌨️ 快捷键说明

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