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

📄 preproc.c

📁 一个汇编语言编译器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*
		 * The expression was bogus, but let's make
		 * %endif not complain about missing %if
		 */
		j = COND_NEVER;
	    else
		istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE;
	}
	return (istk->conds->state == COND_IF_TRUE ? 5 : 1);

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

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

      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);
	if (!tok_type_(tline, TOK_ID)) {
	    error (ERR_NONFATAL,
		   "`%%%smacro' expects a macro name",
		   (i == PP_IMACRO ? "i" : ""));
	    return 3;
	}
	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 = 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 1;

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

      case PP_ROTATE:
	if (tline->next && tline->next->type == TOK_WHITESPACE)
	    tline = tline->next;
	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 3;
	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 3;
	}
	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");
	mmac->rotate = mmac->rotate + reloc_value(evalresult);
	if (mmac->rotate < 0)
	    mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
	mmac->rotate %= mmac->nparam;
	return 1;

      case PP_REP:
	nolist = FALSE;
	tline = tline->next;
	if (tline->next && tline->next->type == TOK_WHITESPACE)
	    tline = tline->next;
	if (tline->next && tline->next->type == TOK_ID &&
	    !nasm_stricmp(tline->next->text, ".nolist")) {
	    tline = tline->next;
	    nolist = TRUE;
	}
	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 3;
	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 3;
	}
	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 = reloc_value(evalresult) + 1;
	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 1;

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

	/*
	 * Now we have a "macro" defined - although it has no name
	 * and we won't be entering it in the hash tables - we must
	 * push a macro-end marker for it on to istk->expansion.
	 * After that, it will take care of propagating itself (a
	 * macro-end marker line for a macro which is really a %rep
	 * block will cause the macro to be re-expanded, complete
	 * with another macro-end marker to ensure the process
	 * continues) until the whole expansion is forcibly removed
	 * from istk->expansion by a %exitrep.
	 */
    	l = nasm_malloc(sizeof(Line));
	l->next = istk->expansion;
	l->finishes = defining;
	l->first = NULL;
	istk->expansion = l;

	istk->mstk = defining;

	list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
	tmp_defining = defining;
	defining = defining->rep_nest;
	free_tlist (origline);
	return 1;

      case PP_EXITREP:
	/*
	 * We must search along istk->expansion until we hit a
	 * macro-end marker for a macro with no name. Then we set
	 * its `in_progress' flag to 0.
	 */
	for (l = istk->expansion; l; l = l->next)
	    if (l->finishes && !l->finishes->name)
		break;

	if (l)
	    l->finishes->in_progress = 0;
	else
	    error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
	free_tlist (origline);
	return 1;

      case PP_DEFINE:
      case PP_IDEFINE:
	tline = tline->next;
	skip_white_(tline);
	if (!tline || (tline->type != TOK_ID &&
		       (tline->type != TOK_PREPROC_ID ||
			tline->text[1] != '$'))) {
	    error (ERR_NONFATAL,
		   "`%%%sdefine' expects a macro identifier",
		   (i == PP_IDEFINE ? "i" : ""));
	    free_tlist (origline);
	    return 3;
	}
	mname = tline->text;
	if (tline->type == TOK_ID) {
	    p = tline->text;
	    smhead = &smacros[hash(mname)];
	} else {
	    ctx = get_ctx (tline->text);
	    if (ctx == NULL)
		return 3;
	    else {
		p = tline->text+1;
		p += strspn(p, "$");
		smhead = &ctx->localmac;
	    }
	}
	last = tline;
	param_start = tline = tline->next;
	nparam = 0;
	if (tok_is_(tline, "(")) {
	    /*
	     * This macro has parameters.
	     */

	    tline = tline->next;
	    while (1) {
		skip_white_(tline);
		if (!tline) {
		    error (ERR_NONFATAL,
			   "parameter identifier expected");
		    free_tlist (origline);
		    return 3;
		}
		if (tline->type != TOK_ID) {
		    error (ERR_NONFATAL,
			   "`%s': parameter identifier expected",
			   tline->text);
		    free_tlist (origline);
		    return 3;
		}
		tline->type = TOK_SMAC_PARAM + nparam++;
		tline = tline->next;
		skip_white_(tline);
		if (tok_is_(tline, ",")) {
		    tline = tline->next;
		    continue;
		}
		if (!tok_is_(tline, ")")) {
		    error (ERR_NONFATAL,
			   "`)' expected to terminate macro template");
		    free_tlist (origline);
		    return 3;
		}
		break;
	    }
	    last = tline;
	    tline = tline->next;
	}
	if (tok_type_(tline, TOK_WHITESPACE))
	    last = tline, tline = tline->next;
	macro_start = NULL;
	last->next = NULL;
	t = tline;
	while (t) {
	    if (t->type == TOK_ID) {
		for (tt = param_start; tt; tt = tt->next)
		    if (tt->type >= TOK_SMAC_PARAM &&
			!strcmp(tt->text, t->text))
			t->type = tt->type;
	    }
	    tt = t->next;
	    t->next = macro_start;
	    macro_start = t;
	    t = tt;
	}
	/*
	 * Good. We now have a macro name, a parameter count, and a
	 * token list (in reverse order) for an expansion. We ought
	 * to be OK just to create an SMacro, store it, and let
	 * free_tlist have the rest of the line (which we have
	 * carefully re-terminated after chopping off the expansion
	 * from the end).
	 */
	if (smacro_defined (mname, nparam, &smac, i==PP_DEFINE)) {
	    if (!smac) {
		error (ERR_WARNING,
		       "single-line macro `%s' defined both with and"
		       " without parameters", mname);
		free_tlist (origline);
		free_tlist (macro_start);
		return 3;
	    } 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 {
	    smac = nasm_malloc(sizeof(SMacro));
	    smac->next = *smhead;
	    *smhead = smac;
	}
	smac->name = nasm_strdup(p);
	smac->casesense = (i == PP_DEFINE);
	smac->nparam = nparam;
	smac->expansion = macro_start;
	smac->in_progress = FALSE;
	free_tlist (origline);
	return 3;

    case PP_UNDEF:
	tline = tline->next;
	skip_white_(tline);
	if (!tline || (tline->type != TOK_ID &&
		       (tline->type != TOK_PREPROC_ID ||
			tline->text[1] != '$'))) {
	    error (ERR_NONFATAL,
		   "`%%undef' expects a macro identifier");
	    free_tlist (origline);
	    return 3;
	}
	mname = tline->text;
	if (tline->type == TOK_ID) {
	    p = tline->text;
	    smhead = &smacros[hash(mname)];
	} else {
	    ctx = get_ctx (tline->text);
	    if (ctx == NULL) {
		free_tlist (origline);
		return 3;
	    } else {
		p = tline->text+1;
		p += strspn(p, "$");
		smhead = &ctx->localmac;
	    }
	}
	last = tline;
	tline = tline->next;
	last->next = NULL;

	if (tline)
	    error(ERR_WARNING,
		  "trailing garbage after macro name ignored");

	/*
	 * We now have a macro name... go hunt for it.
	 */
	while (smacro_defined (mname, -1, &smac, 1)) {
	  /* Defined, so we need to find its predecessor and nuke it */
	  SMacro **s;
	  for ( s = smhead ; *s && *s != smac ; s = &(*s)->next );
	  if ( *s ) {
	    *s = smac->next;
	    nasm_free(smac->name);
	    free_tlist(smac->expansion);
	    nasm_free(smac);
	  }
	}
	return 3;

      case PP_ASSIGN:
      case PP_IASSIGN:
	tline = tline->next;
	skip_white_(tline);
	if (!tline || (tline->type != TOK_ID &&
		       (tline->type != TOK_PREPROC_ID ||
			tline->text[1] != '$'))) {
	    error (ERR_NONFATAL,
		   "`%%%sassign' expects a macro identifier",
		   (i == PP_IASSIGN ? "i" : ""));
	    free_tlist (origline);
	    return 3;
	}
	mname = tline->text;
	if (tline->type == TOK_ID) {
	    p = tline->text;
	    smhead = &smacros[hash(mname)];
	} else {
	    ctx = get_ctx (tline->text);
	    if (ctx == NULL) {
		free_tlist (origline);
		return 3;
	    } else {
		p = tline->text+1;
		p += strspn(p, "$");
		smhead = &ctx->localmac;
	    }
	}
	last = tline;
	tline = tline->next;
	last->next = NULL;

	tline = expand_smacro (tline);
	t = tline;
	tptr = &t;
	tokval.t_type = TOKEN_INVALID;
	evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
	free_tlist (tline);
	if (!evalresult) {
	    free_tlist (origline);
	    return 3;
	}

⌨️ 快捷键说明

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