Beispiel #1
0
static char *tag_function (int argc, char *argv[])
{
  if (argc >= 1) {
    MACRO *macro, *submacro;
    STREAM *stream;
    char buf[32];
    int c;

    /* remove the macro */
    remove_macro (macros_space[nmacros_space-1], argv[0]);

    /* create the new functional macro */
    macro = new_macro (FUNCTIONAL_MACRO, strdup (argv[0]), NULL);

    /* create macros for the function */
    for (c = 1; c < argc; c++) {
      sprintf (buf, "%d", c);

      submacro = new_macro (NORMAL_MACRO, strdup (argv[c]), strdup (""));

      add_macro (macro->data, submacro, FALSE);
    }

    /* read the function stream */
    stream = stopen (NULL, NULL);
    read_function_body (_i_stream, stream);
    macro->value = stbuffer (stream);
    if (!macro->value)
      macro->value = strdup ("");

    add_macro (macros_space[nmacros_space-1], macro, TRUE);
  }
  return NULL;
}
Beispiel #2
0
/*
 * add the special macros to the macro table
 */
static void add_special_macros(void)
{
	struct macro *m;

	HTT_put(&macros, new_macro(), "__LINE__");
	HTT_put(&macros, new_macro(), "__FILE__");
	HTT_put(&macros, new_macro(), "__DATE__");
	HTT_put(&macros, new_macro(), "__TIME__");
	HTT_put(&macros, new_macro(), "__STDC__");
	m = new_macro(); m->narg = 1;
	m->arg = getmem(sizeof(char *)); m->arg[0] = sdup("foo");
	HTT_put(&macros, m, "_Pragma");
	if (c99_compliant) {

		m = new_macro();
		m->cval.t = getmem(9);
		m->cval.t[0] = NUMBER;
		mmv(m->cval.t + 1, "199901L", 8);
		m->cval.length = 9;
		HTT_put(&macros, m, "__STDC_VERSION__");
	}
	if (c99_hosted) {
		m = new_macro();
		m->cval.t = getmem(3);
		m->cval.t[0] = NUMBER;
		mmv(m->cval.t + 1, "1", 2);
		m->cval.length = 3;
	}
}
Beispiel #3
0
static char *tag_macro (int argc, char *argv[])
{
  if (argc >= 1) {
    if (argc >= 2) {
      char *value = process_text (argv[1]);
      MACRO *macro = get_macro (macros_space[0], argv[0]);

      /* modify macro */
      if (macro) {
	modify_macro (macro, value);
      }
      /* new macro */
      else {
	macro = new_macro (NORMAL_MACRO, strdup (argv[0]), value);
	add_macro (macros_space[0], macro, TRUE);
      }
    }
    else {
      /* remove macro */
      remove_macro (macros_space[0], argv[0]);
    }
  }

  return NULL;
}
Beispiel #4
0
static void handle_macro(char *s)
{
  char *name;

  if (name = parse_identifier(&s)) {
    eol(s);
    new_macro(name,nodotneeded ?"endm":".endm");
    myfree(name);
  }
  else
    syntax_error(10);  /* identifier expected */
}
Beispiel #5
0
int
insert_macro(const char *macroname, const char *macrodef,
			 dbref player, struct macrotable **node)
{
	struct macrotable *newmacro;

	newmacro = new_macro(macroname, macrodef, player);
	if (!(*node)) {
		*node = newmacro;
		return 1;
	} else
		return (grow_macro_tree((*node), newmacro));
}
Beispiel #6
0
static void handle_macro(char *s)
{
  char *name;

  if (name = parse_identifier(&s)) {
    s = skip(s);
    if (ISEOL(s))
      s = NULL;  /* no named arguments */
    new_macro(name,endm_dirlist,s);
    myfree(name);
  }
  else
    syntax_error(10);  /* identifier expected */
}
static int
process_macros(struct state *cur, struct block *info,
		const char *dummy, scconf_block *blk)
{
	scconf_item	*item;
	const char	*name;

	for (item = blk->items; item; item = item->next) {
		name = item->key;
		if (item->type != SCCONF_ITEM_TYPE_VALUE)
			continue;
#if 0
		printf("Defining %s\n", name);
#endif
		new_macro(cur->profile, name, item->value.list);
	}

	return 0;
}
Beispiel #8
0
int
macrochain(struct macrotable *lastnode, FILE * f)
{
	char *line, *line2;
	struct macrotable *newmacro;

	if (!(line = file_line(f)))
		return 0;
	line2 = file_line(f);

	newmacro = (struct macrotable *) new_macro(line, line2, getref(f));
	free(line);
	free(line2);

	if (!macrotop)
		macrotop = (struct macrotable *) newmacro;
	else {
		newmacro->left = lastnode;
		lastnode->right = newmacro;
	}
	return (1 + macrochain(newmacro, f));
}
Beispiel #9
0
/*
 * We found a #define directive; parse the end of the line, perform
 * sanity checks, store the new macro into the "macros" hash table.
 *
 * In case of a redefinition of a macro: we enforce the rule that a
 * macro should be redefined identically, including the spelling of
 * parameters. We emit an error on offending code; dura lex, sed lex.
 * After all, it is easy to avoid such problems, with a #undef directive.
 */
int handle_define(struct lexer_state *ls)
{
	struct macro *m = 0, *n;
	struct token_fifo mv;
	int ltwws = 1, redef = 0;
	char *mname = 0;
	int narg;
	size_t nt;
	long l = ls->line;

	mv.art = mv.nt = 0;
	mv.t = NULL;
	/* find the next non-white token on the line, this should be
	   the macro name */
	while (!next_token(ls) && ls->ctok->type != NEWLINE) {
		if (ttMWS(ls->ctok->type)) continue;
		if (ls->ctok->type == NAME) mname = sdup(ls->ctok->name);
		break;
	}
	if (mname == 0) {
		error(l, "missing macro name");
		return 1;
	}
	if (check_special_macro(mname)) {
		error(l, "trying to redefine the special macro %s", mname);
		goto warp_error;
	}
	/*
	 * If a macro with this name was already defined: the K&R
	 * states that the new macro should be identical to the old one
	 * (with some arcane rule of equivalence of whitespace); otherwise,
	 * redefining the macro is an error. Most preprocessors would
	 * only emit a warning (or nothing at all) on an unidentical
	 * redefinition.
	 *
	 * Since it is easy to avoid this error (with a #undef directive),
	 * we choose to enforce the rule and emit an error.
	 */
	if ((n = HTT_get(&macros, mname)) != 0) {
		/* redefinition of a macro: we must check that we define
		   it identical */
		redef = 1;
		n->cval.rp = 0;
		freemem(mname);
		mname = 0;
	}
	if (!redef) {
		m = new_macro();
		m->narg = -1;
#define mval	mv
	}
	if (next_token(ls)) goto define_end;
	/*
	 * Check if the token immediately following the macro name is
	 * a left parenthesis; if so, then this is a macro with arguments.
	 * Collect their names and try to match the next parenthesis.
	 */
	if (ls->ctok->type == LPAR) {
		int i, j;
		int need_comma = 0, saw_mdots = 0;

		narg = 0;
		while (!next_token(ls)) {
			if (ls->ctok->type == NEWLINE) {
				error(l, "truncated macro definition");
				goto define_error;
			}
			if (ls->ctok->type == COMMA) {
				if (saw_mdots) {
					error(l, "'...' must end the macro "
						"argument list");
					goto warp_error;
				}
				if (!need_comma) {
					error(l, "void macro argument");
					goto warp_error;
				}
				need_comma = 0;
				continue;
			} else if (ls->ctok->type == NAME) {
				if (saw_mdots) {
					error(l, "'...' must end the macro "
						"argument list");
					goto warp_error;
				}
				if (need_comma) {
					error(l, "missing comma in "
						"macro argument list");
					goto warp_error;
				}
				if (!redef) {
					aol(m->arg, narg,
						sdup(ls->ctok->name), 8);
					/* we must keep track of m->narg
					   so that cleanup in case of
					   error works. */
					m->narg = narg;
					if (narg == 128
						&& (ls->flags & WARN_STANDARD))
						warning(l, "more arguments to "
							"macro than the ISO "
							"limit (127)");
					if (narg == 32767) {
						error(l, "too many arguments "
							"in macro definition "
							"(max 32766)");
						goto warp_error;
					}
				} else {
					/* this is a redefinition of the
					   macro; check equality between
					   old and new definitions */
					if (narg >= n->narg) goto redef_error;
					if (strcmp(ls->ctok->name,
						n->arg[narg ++]))
						goto redef_error;
				}
				need_comma = 1;
				continue;
			} else if ((ls->flags & MACRO_VAARG)
				&& ls->ctok->type == MDOTS) {
				if (need_comma) {
					error(l, "missing comma before '...'");
					goto warp_error;
				}
				if (redef && !n->vaarg) goto redef_error;
				if (!redef) m->vaarg = 1;
				saw_mdots = 1;
				need_comma = 1;
				continue;
			} else if (ls->ctok->type == RPAR) {
				if (narg > 0 && !need_comma) {
					error(l, "void macro argument");
					goto warp_error;
				}
				if (redef && n->vaarg && !saw_mdots)
					goto redef_error;
				break;
			} else if (ttMWS(ls->ctok->type)) {
				continue;
			}
			error(l, "invalid macro argument");
			goto warp_error;
		}
		if (!redef) {
			for (i = 1; i < narg; i ++) for (j = 0; j < i; j ++)
				if (!strcmp(m->arg[i], m->arg[j])) {
					error(l, "duplicate macro "
						"argument");
					goto warp_error;
				}
		}
		if (!redef) m->narg = narg;
	} else {
		if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD))
			warning(ls->line, "identifier not followed by "
				"whitespace in #define");
		ls->flags |= READ_AGAIN;
		narg = 0;
	}
	if (redef) nt = 0;

	/* now, we have the arguments. Let's get the macro contents. */
	while (!next_token(ls) && ls->ctok->type != NEWLINE) {
		struct token t;

		t.type = ls->ctok->type;
		if (ltwws && ttMWS(t.type)) continue;
		t.line = 0;
		if (t.type == NAME) {
			int i;

			if ((ls->flags & MACRO_VAARG)
				&& !strcmp(ls->ctok->name, "__VA_ARGS__")) {
				if (redef) {
					if (!n->vaarg) goto redef_error;
				} else if (!m->vaarg) {
					error(l, "'__VA_ARGS__' is forbidden "
						"in macros with a fixed "
						"number of arguments");
					goto warp_error;
				}
				t.type = MACROARG;
				t.line = redef ? n->narg : m->narg;
			}
			for (i = 0; i < narg; i ++)
				if (!strcmp(redef ? n->arg[i] : m->arg[i],
					ls->ctok->name)) {
					t.type = MACROARG;
					/* this is a hack: we store the
					   argument number in the line field */
					t.line = i;
					break;
				}
		}
		if (!redef && S_TOKEN(t.type)) t.name = sdup(ls->ctok->name);
		if (ttMWS(t.type)) {
			if (ltwws) continue;
#ifdef SEMPER_FIDELIS
			t.type = OPT_NONE;
#else
			t.type = NONE;
#endif
			ltwws = 1;
		} else ltwws = 0;
		if (!redef) {
			/* we ensure that each macro token has a correct
			   line number */
			if (t.type != MACROARG) t.line = 1;
			aol(mval.t, mval.nt, t, TOKEN_LIST_MEMG);
		} else {
			int tt;

			if (n->cval.rp >= n->cval.length) {
#ifdef SEMPER_FIDELIS
				if (t.type != OPT_NONE) goto redef_error;
#else
				if (t.type != NONE) goto redef_error;
#endif
			} else if (t.type != n->cval.t[n->cval.rp]) {
				goto redef_error;
			} else if (t.type == MACROARG) {
				unsigned anum = n->cval.t[n->cval.rp + 1];

				if (anum >= 128U) anum = ((anum & 127U) << 8)
					| m->cval.t[n->cval.rp + 2];
				if (anum != (unsigned)t.line) goto redef_error;
			} else if (S_TOKEN(t.type) && strcmp(ls->ctok->name,
				   (char *)(n->cval.t + n->cval.rp + 1))) {
				goto redef_error;
			}
			tt = n->cval.t[n->cval.rp ++];
			if (S_TOKEN(tt)) n->cval.rp += 1
				+ strlen((char *)(n->cval.t + n->cval.rp));
			else if (tt == MACROARG) {
				if (n->cval.t[++ n->cval.rp] >= 128)
					n->cval.rp ++;
			}
			nt ++;
		}
	}

	if (redef) {
		if (n->cval.rp < n->cval.length) goto redef_error_2;
		return 0;
	}

	/* now we have the complete macro; perform some checks about
	   the operators # and ##, and, if everything is ok,
	   store the macro into the hash table */
define_end:
#ifdef SEMPER_FIDELIS
	if (mval.nt && mval.t[mval.nt - 1].type == OPT_NONE) {
#else
	if (mval.nt && mval.t[mval.nt - 1].type == NONE) {
#endif
		mval.nt --;
		if (mval.nt == 0) freemem(mval.t);
	}
	if (mval.nt != 0) {
		/* some checks about the macro */
		if (mval.t[0].type == DSHARP
			|| mval.t[0].type == DIG_DSHARP
			|| mval.t[mval.nt - 1].type == DSHARP
			|| mval.t[mval.nt - 1].type == DIG_DSHARP) {
			error(l, "operator '##' may neither begin "
				"nor end a macro");
			goto define_error;
		}
		if (m->narg >= 0) {
			size_t i;
			for (i = 0; i < mval.nt; i ++)
				if ((mval.t[i].type == SHARP
					|| mval.t[i].type == DIG_SHARP) &&
					(i == (mval.nt - 1)
					|| (ttMWS(mval.t[i + 1].type) &&
					    (i == mval.nt - 2
					     || mval.t[i + 2].type != MACROARG))
					|| (!ttMWS(mval.t[i + 1].type)
					     && mval.t[i + 1].type != MACROARG))) {
					error(l, "operator '#' not followed "
						"by a macro argument");
					goto define_error;
				}
		}
	}
	{
		size_t i, l;

		for (i = 0, l = 0; i < mval.nt; i ++) {
			l ++;
			if (S_TOKEN(mval.t[i].type))
				l += 1 + strlen(mval.t[i].name);
			else if (mval.t[i].type == MACROARG) {
				l ++;
				if (mval.t[i].line >= 128) l ++;
			}
		}
		m->cval.length = l;
		if (l) m->cval.t = getmem(l);
		for (i = 0, l = 0; i < mval.nt; i ++) {
			m->cval.t[l ++] = mval.t[i].type;
			if (S_TOKEN(mval.t[i].type)) {
				size_t x = 1 + strlen(mval.t[i].name);

				mmv(m->cval.t + l, mval.t[i].name, x);
				l += x;
				freemem(mval.t[i].name);
			}
			else if (mval.t[i].type == MACROARG) {
				unsigned anum = mval.t[i].line;

				if (anum >= 128) {
					m->cval.t[l ++] = 128 | (anum >> 8);
					m->cval.t[l ++] = anum & 0xFF;
				} else {
					m->cval.t[l ++] = anum;
				}
			}
		}