Commit d2158690 by Zack Weinberg Committed by Zack Weinberg

cpphash.h (enum node_type): Take out T_MCONST.

	* cpphash.h (enum node_type: Take out T_MCONST.
	(union hashval): Move into struct hashnode.
	(struct hashnode): Pack tighter.  Remove file, line, col
	members.
	* cpphash.c: Constify most of the macro-definition structures.
	(struct definition): Replace by struct object_defn
	and struct funct_defn.  Put file, line, column information
	here.  All users updated to match.
	(_cpp_create_definition, _cpp_macroexpand): Remove special
	case for #define WORD OTHERWORD.
	* cpplib.c (do_undef): Remove T_MCONST case.

From-SVN: r33538
parent 10d1117c
2000-04-29 Zack Weinberg <zack@wolery.cumb.org> 2000-04-29 Zack Weinberg <zack@wolery.cumb.org>
* cpphash.h (enum node_type: Take out T_MCONST.
(union hashval): Move into struct hashnode.
(struct hashnode): Pack tighter. Remove file, line, col
members.
* cpphash.c: Constify most of the macro-definition structures.
(struct definition): Replace by struct object_defn
and struct funct_defn. Put file, line, column information
here. All users updated to match.
(_cpp_create_definition, _cpp_macroexpand): Remove special
case for #define WORD OTHERWORD.
* cpplib.c (do_undef): Remove T_MCONST case.
* cpphash.h: Move struct reflist, struct definition, and the * cpphash.h: Move struct reflist, struct definition, and the
DEFINITION typedef to cpphash.c. Use 'struct definition *' in DEFINITION typedef to cpphash.c. Use 'struct definition *' in
union hashval. _cpp_free_definition takes a HASHNODE pointer. union hashval. _cpp_free_definition takes a HASHNODE pointer.
......
...@@ -33,11 +33,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -33,11 +33,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/* Structure allocated for every #define. For a simple replacement /* Structure allocated for every #define. For a simple replacement
such as such as
#define foo bar , #define foo bar
nargs = -1, the `pattern' list is null, and the expansion is just
the replacement text. Nargs = 0 means a functionlike macro with no args, we allocate an object_defn structure; the expansion field points
e.g., to the replacement text. For a function-like macro we allocate a
#define getchar() getc (stdin) . funct_defn structure; nargs is the number of arguments - it can be zero,
e.g.
#define getchar() getc (stdin)
When there are args, the expansion is the replacement text with the When there are args, the expansion is the replacement text with the
args squashed out, and the reflist is a list describing how to args squashed out, and the reflist is a list describing how to
build the output from the input: e.g., "3 chars, then the 1st arg, build the output from the input: e.g., "3 chars, then the 1st arg,
...@@ -50,11 +53,25 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -50,11 +53,25 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and
pattern list pattern list
{ (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
where (x, y) means (nchars, argno). */ where (x, y) means (nchars, argno).
Note that EMPTY and IDENTITY macros have object_defn structures too,
but they're just used to hold the file, line, and column. The
expansion field will be NULL. */
struct object_defn
{
const U_CHAR *expansion;
unsigned int length;
const char *file; /* File, line, column of definition */
int line;
int col;
};
struct reflist struct reflist
{ {
struct reflist *next; const struct reflist *next;
char stringify; /* nonzero if this arg was preceded by a char stringify; /* nonzero if this arg was preceded by a
# operator. */ # operator. */
char raw_before; /* Nonzero if a ## operator before arg. */ char raw_before; /* Nonzero if a ## operator before arg. */
...@@ -65,25 +82,29 @@ struct reflist ...@@ -65,25 +82,29 @@ struct reflist
int argno; /* Number of arg to substitute (origin-0) */ int argno; /* Number of arg to substitute (origin-0) */
}; };
typedef struct definition DEFINITION; struct funct_defn
struct definition
{ {
int nargs; int nargs;
int length; /* length of expansion string */ int length; /* length of expansion string */
U_CHAR *expansion; const U_CHAR *expansion;
char rest_args; /* Nonzero if last arg. absorbs the rest */ char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist *pattern; const struct reflist *pattern;
/* Names of macro args, concatenated in order with \0 between /* Names of macro args, concatenated in order with \0 between
them. The only use of this is that we warn on redefinition if them. The only use of this is that we warn on redefinition if
this differs between the old and new definitions. */ this differs between the old and new definitions. */
U_CHAR *argnames; U_CHAR *argnames;
const char *file; /* File, line, column of definition */
int line;
int col;
}; };
static unsigned int hash_HASHNODE PARAMS ((const void *)); static unsigned int hash_HASHNODE PARAMS ((const void *));
static int eq_HASHNODE PARAMS ((const void *, const void *)); static int eq_HASHNODE PARAMS ((const void *, const void *));
static void del_HASHNODE PARAMS ((void *)); static void del_HASHNODE PARAMS ((void *));
static void dump_DEFINITION PARAMS ((cpp_reader *, DEFINITION *)); static void dump_funlike_macro PARAMS ((cpp_reader *,
const struct funct_defn *));
static int dump_hash_helper PARAMS ((void **, void *)); static int dump_hash_helper PARAMS ((void **, void *));
static void push_macro_expansion PARAMS ((cpp_reader *, const U_CHAR *, static void push_macro_expansion PARAMS ((cpp_reader *, const U_CHAR *,
...@@ -92,22 +113,23 @@ static int unsafe_chars PARAMS ((cpp_reader *, int, int)); ...@@ -92,22 +113,23 @@ static int unsafe_chars PARAMS ((cpp_reader *, int, int));
static int macro_cleanup PARAMS ((cpp_buffer *, cpp_reader *)); static int macro_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
static enum cpp_ttype macarg PARAMS ((cpp_reader *, int)); static enum cpp_ttype macarg PARAMS ((cpp_reader *, int));
static void special_symbol PARAMS ((cpp_reader *, HASHNODE *)); static void special_symbol PARAMS ((cpp_reader *, HASHNODE *));
static int compare_defs PARAMS ((cpp_reader *, DEFINITION *, static int compare_defs PARAMS ((cpp_reader *,
DEFINITION *)); const struct funct_defn *,
const struct funct_defn *));
/* Initial hash table size. (It can grow if necessary - see hashtab.c.) */ /* Initial hash table size. (It can grow if necessary - see hashtab.c.) */
#define HASHSIZE 500 #define HASHSIZE 500
/* The arglist structure is built by create_definition to tell /* The arglist structure is built by collect_params to tell
collect_expansion where the argument names begin. That collect_funlike_expansion where the argument names begin. That is,
is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist for a define like "#define f(x,y,z) foo+x-bar*y", the arglist would
would contain pointers to the strings x, y, and z. contain pointers to the strings x, y, and z.
collect_expansion would then build a DEFINITION node, collect_funlike_expansion would then build a funct_defn node, with
with reflist nodes pointing to the places x, y, and z had reflist nodes pointing to the places x, y, and z had appeared.
appeared. So the arglist is just convenience data passed
between these two routines. It is not kept around after The arglist is just convenience data passed between these two
the current #define has been processed and entered into the routines. It is not kept around after the current #define has been
hash table. */ processed and entered into the hash table. */
struct arg struct arg
{ {
...@@ -124,9 +146,9 @@ struct arglist ...@@ -124,9 +146,9 @@ struct arglist
}; };
static DEFINITION * static struct object_defn *
collect_objlike_expansion PARAMS ((cpp_reader *, cpp_toklist *)); collect_objlike_expansion PARAMS ((cpp_reader *, cpp_toklist *));
static DEFINITION * static struct funct_defn *
collect_funlike_expansion PARAMS ((cpp_reader *, cpp_toklist *, collect_funlike_expansion PARAMS ((cpp_reader *, cpp_toklist *,
struct arglist *, unsigned int)); struct arglist *, unsigned int));
static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *, static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *,
...@@ -160,8 +182,9 @@ struct argdata ...@@ -160,8 +182,9 @@ struct argdata
int stringified_length; int stringified_length;
}; };
static void scan_arguments PARAMS ((cpp_reader *, DEFINITION *, static void scan_arguments PARAMS ((cpp_reader *,
struct argdata *, const U_CHAR *)); const struct funct_defn *,
struct argdata *, const U_CHAR *));
static void stringify PARAMS ((cpp_reader *, struct argdata *)); static void stringify PARAMS ((cpp_reader *, struct argdata *));
static void funlike_macroexpand PARAMS ((cpp_reader *, HASHNODE *, static void funlike_macroexpand PARAMS ((cpp_reader *, HASHNODE *,
struct argdata *)); struct argdata *));
...@@ -318,22 +341,29 @@ void ...@@ -318,22 +341,29 @@ void
_cpp_free_definition (h) _cpp_free_definition (h)
HASHNODE *h; HASHNODE *h;
{ {
if (h->type == T_MCONST || h->type == T_XCONST) if (h->type == T_XCONST)
free ((void *) h->value.cpval); free ((PTR) h->value.cpval);
else if (h->type == T_MACRO || h->type == T_FMACRO) else if (h->type == T_MACRO)
{
if (h->value.odefn->expansion)
free ((PTR) h->value.odefn->expansion);
free ((PTR) h->value.odefn);
}
else if (h->type == T_FMACRO)
{ {
DEFINITION *d = h->value.defn; const struct funct_defn *d = h->value.fdefn;
struct reflist *ap, *nextap; const struct reflist *ap, *nextap;
for (ap = d->pattern; ap != NULL; ap = nextap) for (ap = d->pattern; ap != NULL; ap = nextap)
{ {
nextap = ap->next; nextap = ap->next;
free (ap); free ((PTR) ap);
} }
if (d->argnames) if (d->argnames)
free (d->argnames); free ((PTR) d->argnames);
free (d); free ((PTR) d);
} }
h->value.cpval = NULL;
} }
static int static int
...@@ -344,10 +374,10 @@ macro_cleanup (pbuf, pfile) ...@@ -344,10 +374,10 @@ macro_cleanup (pbuf, pfile)
HASHNODE *m = pbuf->macro; HASHNODE *m = pbuf->macro;
m->disabled = 0; m->disabled = 0;
if (m->type == T_FMACRO && pbuf->buf != m->value.defn->expansion) if ((m->type == T_FMACRO && pbuf->buf != m->value.fdefn->expansion)
free ((PTR) pbuf->buf); || m->type == T_SPECLINE || m->type == T_FILE
else if (m->type != T_MACRO && m->type != T_FMACRO && m->type != T_CONST || m->type == T_BASE_FILE || m->type == T_INCLUDE_LEVEL
&& m->type != T_MCONST && m->type != T_XCONST) || m->type == T_STDC)
free ((PTR) pbuf->buf); free ((PTR) pbuf->buf);
return 0; return 0;
} }
...@@ -466,14 +496,14 @@ trad_stringify (pfile, base, len, argc, argv, pat, endpat, last) ...@@ -466,14 +496,14 @@ trad_stringify (pfile, base, len, argc, argv, pat, endpat, last)
} }
/* Read a replacement list for an object-like macro, and build the /* Read a replacement list for an object-like macro, and build the
DEFINITION structure. LIST contains the replacement list, object_defn structure. LIST contains the replacement list,
beginning at 1. */ beginning at 1. */
static DEFINITION * static struct object_defn *
collect_objlike_expansion (pfile, list) collect_objlike_expansion (pfile, list)
cpp_reader *pfile; cpp_reader *pfile;
cpp_toklist *list; cpp_toklist *list;
{ {
DEFINITION *defn; struct object_defn *defn;
unsigned int i; unsigned int i;
unsigned int start; unsigned int start;
int last_was_paste = 0; int last_was_paste = 0;
...@@ -535,30 +565,26 @@ collect_objlike_expansion (pfile, list) ...@@ -535,30 +565,26 @@ collect_objlike_expansion (pfile, list)
memcpy (exp, pfile->token_buffer + start, len); memcpy (exp, pfile->token_buffer + start, len);
exp[len] = '\0'; exp[len] = '\0';
defn = (DEFINITION *) xmalloc (sizeof (DEFINITION)); defn = (struct object_defn *) xmalloc (sizeof (struct object_defn));
defn->length = len; defn->length = len;
defn->expansion = exp; defn->expansion = exp;
defn->pattern = 0;
defn->rest_args = 0;
defn->argnames = 0;
defn->nargs = -1;
return defn; return defn;
} }
/* Read a replacement list for a function-like macro, and build the /* Read a replacement list for a function-like macro, and build the
DEFINITION structure. LIST contains the replacement list, funct_defn structure. LIST contains the replacement list,
beginning at REPLACEMENT. ARGLIST specifies the formal parameters beginning at REPLACEMENT. ARGLIST specifies the formal parameters
to look for in the text of the definition. */ to look for in the text of the definition. */
static DEFINITION * static struct funct_defn *
collect_funlike_expansion (pfile, list, arglist, replacement) collect_funlike_expansion (pfile, list, arglist, replacement)
cpp_reader *pfile; cpp_reader *pfile;
cpp_toklist *list; cpp_toklist *list;
struct arglist *arglist; struct arglist *arglist;
unsigned int replacement; unsigned int replacement;
{ {
DEFINITION *defn; struct funct_defn *defn;
struct reflist *pat = 0, *endpat = 0; struct reflist *pat = 0, *endpat = 0;
enum cpp_ttype token; enum cpp_ttype token;
unsigned int start, last; unsigned int start, last;
...@@ -694,7 +720,7 @@ collect_funlike_expansion (pfile, list, arglist, replacement) ...@@ -694,7 +720,7 @@ collect_funlike_expansion (pfile, list, arglist, replacement)
memcpy (exp, pfile->token_buffer + start, len); memcpy (exp, pfile->token_buffer + start, len);
exp[len] = '\0'; exp[len] = '\0';
defn = (DEFINITION *) xmalloc (sizeof (DEFINITION)); defn = (struct funct_defn *) xmalloc (sizeof (struct funct_defn));
defn->length = len; defn->length = len;
defn->expansion = exp; defn->expansion = exp;
defn->pattern = pat; defn->pattern = pat;
...@@ -868,9 +894,9 @@ collect_params (pfile, list, arglist) ...@@ -868,9 +894,9 @@ collect_params (pfile, list, arglist)
return i + 1; return i + 1;
} }
/* Create a DEFINITION node for a macro. The replacement text /* Create a definition for a macro. The replacement text (including
(including formal parameters if present) is in LIST. If FUNLIKE is formal parameters if present) is in LIST. If FUNLIKE is true, this
true, this is a function-like macro. */ is a function-like macro. */
int int
_cpp_create_definition (pfile, list, hp) _cpp_create_definition (pfile, list, hp)
...@@ -878,41 +904,29 @@ _cpp_create_definition (pfile, list, hp) ...@@ -878,41 +904,29 @@ _cpp_create_definition (pfile, list, hp)
cpp_toklist *list; cpp_toklist *list;
HASHNODE *hp; HASHNODE *hp;
{ {
DEFINITION *defn = 0; struct funct_defn *fdefn = 0;
U_CHAR *cpval = 0; struct object_defn *odefn = 0;
enum node_type ntype; enum node_type ntype;
int ok; int ok;
/* Special-case a few simple and common idioms: /* Special-case a few simple and common idioms:
#define TOKEN // nothing #define TOKEN // nothing
#define TOKEN TOKEN #define TOKEN TOKEN
#define TOKEN OTHERTOKEN
Might also be good to special-case these: Might also be good to special-case these:
#define FUNC() // nothing #define FUNC() // nothing
#define FUNC(a, b, ...) // nothing #define FUNC(a, b, ...) // nothing
#define FUNC(a, b, c) FUNC(a, b, c) #define FUNC(a, b, c) FUNC(a, b, c) */
#define FUNC(a, b, c) foobar(a, b, c) */
if (list->tokens_used == 2) if (list->tokens_used == 2)
ntype = T_EMPTY; /* Empty definition of object-like macro. */ ntype = T_EMPTY; /* Empty definition of object-like macro. */
else if (list->tokens_used == 3 && list->tokens[1].type == CPP_NAME) else if (list->tokens_used == 3 && list->tokens[1].type == CPP_NAME
{ && list->tokens[0].val.name.len == list->tokens[1].val.name.len
if (list->tokens[0].val.name.len == list->tokens[1].val.name.len && !strncmp (list->tokens[0].val.name.offset + list->namebuf,
&& !strncmp (list->tokens[0].val.name.offset + list->namebuf, list->tokens[1].val.name.offset + list->namebuf,
list->tokens[1].val.name.offset + list->namebuf, list->tokens[0].val.name.len))
list->tokens[0].val.name.len)) ntype = T_IDENTITY; /* Object like macro defined to itself. */
ntype = T_IDENTITY;
else
{
ntype = T_MCONST;
cpval = xmalloc (list->tokens[1].val.name.len + 1);
memcpy (cpval, list->tokens[1].val.name.offset + list->namebuf,
list->tokens[1].val.name.len);
cpval[list->tokens[1].val.name.len] = '\0';
}
}
/* The macro is function-like only if the next character, /* The macro is function-like only if the next character,
with no intervening whitespace, is '('. */ with no intervening whitespace, is '('. */
...@@ -925,8 +939,8 @@ _cpp_create_definition (pfile, list, hp) ...@@ -925,8 +939,8 @@ _cpp_create_definition (pfile, list, hp)
replacement = collect_params (pfile, list, &args); replacement = collect_params (pfile, list, &args);
if (replacement == 0) if (replacement == 0)
return 0; return 0;
defn = collect_funlike_expansion (pfile, list, &args, replacement); fdefn = collect_funlike_expansion (pfile, list, &args, replacement);
if (defn == 0) if (fdefn == 0)
return 0; return 0;
ntype = T_FMACRO; ntype = T_FMACRO;
...@@ -941,13 +955,20 @@ _cpp_create_definition (pfile, list, hp) ...@@ -941,13 +955,20 @@ _cpp_create_definition (pfile, list, hp)
"The C standard requires whitespace after #define %s", "The C standard requires whitespace after #define %s",
hp->name); hp->name);
defn = collect_objlike_expansion (pfile, list); odefn = collect_objlike_expansion (pfile, list);
if (defn == 0) if (odefn == 0)
return 0; return 0;
ntype = T_MACRO; ntype = T_MACRO;
} }
if (ntype == T_EMPTY || ntype == T_IDENTITY)
{
odefn = xmalloc (sizeof (struct object_defn));
odefn->length = 0;
odefn->expansion = 0;
}
/* Check for a redefinition, and its legality. Redefining a macro /* Check for a redefinition, and its legality. Redefining a macro
of whatever stripe is ok if the definitions are the same. of whatever stripe is ok if the definitions are the same.
Redefining a built-in _constant_ (T_CONST or T_XCONST) is ok only Redefining a built-in _constant_ (T_CONST or T_XCONST) is ok only
...@@ -958,16 +979,20 @@ _cpp_create_definition (pfile, list, hp) ...@@ -958,16 +979,20 @@ _cpp_create_definition (pfile, list, hp)
case T_VOID: ok = 1; break; case T_VOID: ok = 1; break;
default: ok = 0; break; default: ok = 0; break;
case T_MACRO: case T_FMACRO: case T_MACRO:
ok = (ntype == hp->type && !compare_defs (pfile, defn, hp->value.defn)); ok = (ntype == hp->type
&& odefn->length == hp->value.odefn->length
&& !strncmp (odefn->expansion, hp->value.odefn->expansion,
odefn->length));
break;
case T_FMACRO:
ok = (ntype == hp->type
&& !compare_defs (pfile, fdefn, hp->value.fdefn));
break; break;
case T_IDENTITY: case T_IDENTITY:
case T_EMPTY: case T_EMPTY:
ok = (ntype == hp->type); ok = (ntype == hp->type);
break; break;
case T_MCONST:
ok = (ntype == hp->type && !strcmp (cpval, hp->value.cpval));
break;
case T_CONST: case T_CONST:
case T_XCONST: case T_XCONST:
ok = ! pfile->done_initializing; ok = ! pfile->done_initializing;
...@@ -979,23 +1004,45 @@ _cpp_create_definition (pfile, list, hp) ...@@ -979,23 +1004,45 @@ _cpp_create_definition (pfile, list, hp)
{ {
cpp_pedwarn (pfile, "\"%s\" redefined", hp->name); cpp_pedwarn (pfile, "\"%s\" redefined", hp->name);
if (pfile->done_initializing) if (pfile->done_initializing)
cpp_pedwarn_with_file_and_line (pfile, hp->file, hp->line, hp->col, {
const char *file;
unsigned int line, col;
if (hp->type == T_FMACRO)
{
file = hp->value.fdefn->file;
line = hp->value.fdefn->line;
col = hp->value.fdefn->col;
}
else
{
file = hp->value.odefn->file;
line = hp->value.odefn->line;
col = hp->value.odefn->col;
}
cpp_pedwarn_with_file_and_line (pfile, file, line, col,
"this is the location of the previous definition"); "this is the location of the previous definition");
}
} }
/* And replace the old definition (if any). */ /* And replace the old definition (if any). */
_cpp_free_definition (hp); _cpp_free_definition (hp);
if (ntype == T_MACRO || ntype == T_FMACRO)
hp->value.defn = defn;
else
hp->value.cpval = cpval;
hp->type = ntype; hp->type = ntype;
hp->file = CPP_BUFFER (pfile)->nominal_fname; if (ntype == T_FMACRO)
hp->line = list->line; {
hp->col = list->tokens[0].col; fdefn->file = CPP_BUFFER (pfile)->nominal_fname;
fdefn->line = list->line;
fdefn->col = list->tokens[0].col;
hp->value.fdefn = fdefn;
}
else
{
odefn->file = CPP_BUFFER (pfile)->nominal_fname;
odefn->line = list->line;
odefn->col = list->tokens[0].col;
hp->value.odefn = odefn;
}
return 1; return 1;
} }
...@@ -1227,7 +1274,7 @@ _cpp_macroexpand (pfile, hp) ...@@ -1227,7 +1274,7 @@ _cpp_macroexpand (pfile, hp)
cpp_reader *pfile; cpp_reader *pfile;
HASHNODE *hp; HASHNODE *hp;
{ {
DEFINITION *defn; const struct funct_defn *defn;
struct argdata *args; struct argdata *args;
unsigned int old_written; unsigned int old_written;
int i; int i;
...@@ -1235,13 +1282,13 @@ _cpp_macroexpand (pfile, hp) ...@@ -1235,13 +1282,13 @@ _cpp_macroexpand (pfile, hp)
/* Object like macro - most common case. */ /* Object like macro - most common case. */
if (hp->type == T_MACRO) if (hp->type == T_MACRO)
{ {
push_macro_expansion (pfile, hp->value.defn->expansion, push_macro_expansion (pfile, hp->value.odefn->expansion,
hp->value.defn->length, hp); hp->value.odefn->length, hp);
return; return;
} }
/* Or might it be a constant string? */ /* Or might it be a constant string? */
if (hp->type == T_MCONST || hp->type == T_CONST || hp->type == T_XCONST) if (hp->type == T_CONST || hp->type == T_XCONST)
{ {
const U_CHAR *cpval = hp->value.cpval; const U_CHAR *cpval = hp->value.cpval;
if (cpval && *cpval != '\0') if (cpval && *cpval != '\0')
...@@ -1253,8 +1300,9 @@ _cpp_macroexpand (pfile, hp) ...@@ -1253,8 +1300,9 @@ _cpp_macroexpand (pfile, hp)
if (hp->type != T_FMACRO) if (hp->type != T_FMACRO)
{ {
U_CHAR *xbuf; U_CHAR *xbuf;
unsigned int len, old_written = CPP_WRITTEN (pfile); unsigned int len;
old_written = CPP_WRITTEN (pfile);
special_symbol (pfile, hp); special_symbol (pfile, hp);
len = CPP_WRITTEN (pfile) - old_written; len = CPP_WRITTEN (pfile) - old_written;
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
...@@ -1270,7 +1318,7 @@ _cpp_macroexpand (pfile, hp) ...@@ -1270,7 +1318,7 @@ _cpp_macroexpand (pfile, hp)
/* Okay, it's a full-on function-like macro... */ /* Okay, it's a full-on function-like macro... */
old_written = CPP_WRITTEN (pfile); old_written = CPP_WRITTEN (pfile);
defn = hp->value.defn; defn = hp->value.fdefn;
args = alloca (MAX (defn->nargs, 1) * sizeof (struct argdata)); args = alloca (MAX (defn->nargs, 1) * sizeof (struct argdata));
for (i = 0; i < MAX (defn->nargs, 1); i++) for (i = 0; i < MAX (defn->nargs, 1); i++)
...@@ -1301,7 +1349,7 @@ _cpp_macroexpand (pfile, hp) ...@@ -1301,7 +1349,7 @@ _cpp_macroexpand (pfile, hp)
static void static void
scan_arguments (pfile, defn, args, name) scan_arguments (pfile, defn, args, name)
cpp_reader *pfile; cpp_reader *pfile;
DEFINITION *defn; const struct funct_defn *defn;
struct argdata *args; struct argdata *args;
const U_CHAR *name; const U_CHAR *name;
{ {
...@@ -1479,13 +1527,13 @@ funlike_macroexpand (pfile, hp, args) ...@@ -1479,13 +1527,13 @@ funlike_macroexpand (pfile, hp, args)
HASHNODE *hp; HASHNODE *hp;
struct argdata *args; struct argdata *args;
{ {
DEFINITION *defn = hp->value.defn; const struct funct_defn *defn = hp->value.fdefn;
register U_CHAR *xbuf; register U_CHAR *xbuf;
int xbuf_len; int xbuf_len;
U_CHAR *exp = defn->expansion; const U_CHAR *exp = defn->expansion;
int offset; /* offset in expansion, copied a piece at a time */ int offset; /* offset in expansion, copied a piece at a time */
int totlen; /* total amount of exp buffer filled so far */ int totlen; /* total amount of exp buffer filled so far */
struct reflist *ap, *last_ap; const struct reflist *ap, *last_ap;
int i; int i;
/* Compute length in characters of the macro's expansion. /* Compute length in characters of the macro's expansion.
...@@ -1776,20 +1824,20 @@ push_macro_expansion (pfile, xbuf, len, hp) ...@@ -1776,20 +1824,20 @@ push_macro_expansion (pfile, xbuf, len, hp)
foo(foo(baz(0, 0)) in K+R. This looks pathological to me. foo(foo(baz(0, 0)) in K+R. This looks pathological to me.
If someone has a real-world example I would love to see it. */ If someone has a real-world example I would love to see it. */
if (hp->type != T_FMACRO if (hp->type != T_FMACRO
|| hp->value.defn->nargs == 0 || hp->value.fdefn->nargs == 0
|| hp->value.defn->pattern == 0 || hp->value.fdefn->pattern == 0
|| !CPP_TRADITIONAL (pfile)) || !CPP_TRADITIONAL (pfile))
hp->disabled = 1; hp->disabled = 1;
} }
/* Return zero if two DEFINITIONs are isomorphic. */ /* Return zero if two funct_defns are isomorphic. */
static int static int
compare_defs (pfile, d1, d2) compare_defs (pfile, d1, d2)
cpp_reader *pfile; cpp_reader *pfile;
DEFINITION *d1, *d2; const struct funct_defn *d1, *d2;
{ {
struct reflist *a1, *a2; const struct reflist *a1, *a2;
if (d1->nargs != d2->nargs) if (d1->nargs != d2->nargs)
return 1; return 1;
...@@ -1842,23 +1890,21 @@ _cpp_dump_definition (pfile, hp) ...@@ -1842,23 +1890,21 @@ _cpp_dump_definition (pfile, hp)
if (hp->type == T_EMPTY) if (hp->type == T_EMPTY)
/* do nothing */; /* do nothing */;
else if (hp->type == T_FMACRO) else if (hp->type == T_FMACRO)
dump_DEFINITION (pfile, hp->value.defn); dump_funlike_macro (pfile, hp->value.fdefn);
else else
{ {
CPP_PUTC_Q (pfile, ' '); CPP_PUTC_Q (pfile, ' ');
if (hp->type == T_IDENTITY) if (hp->type == T_IDENTITY)
CPP_PUTS (pfile, hp->name, hp->length); CPP_PUTS (pfile, hp->name, hp->length);
else if (hp->type == T_MCONST)
CPP_PUTS (pfile, hp->value.cpval, strlen (hp->value.cpval));
else if (hp->type == T_MACRO) else if (hp->type == T_MACRO)
{ {
/* The first and last two characters of a macro expansion are /* The first and last two characters of a macro expansion are
always "\r "; this needs to be trimmed out. always "\r "; this needs to be trimmed out.
So we need length-4 chars of space, plus one for the NUL. */ So we need length-4 chars of space, plus one for the NUL. */
CPP_RESERVE (pfile, hp->value.defn->length - 4 + 1); CPP_RESERVE (pfile, hp->value.odefn->length - 4 + 1);
CPP_PUTS_Q (pfile, hp->value.defn->expansion + 2, CPP_PUTS_Q (pfile, hp->value.odefn->expansion + 2,
hp->value.defn->length - 4); hp->value.odefn->length - 4);
} }
else else
cpp_ice (pfile, "invalid hash type %d in dump_definition", hp->type); cpp_ice (pfile, "invalid hash type %d in dump_definition", hp->type);
...@@ -1868,15 +1914,15 @@ _cpp_dump_definition (pfile, hp) ...@@ -1868,15 +1914,15 @@ _cpp_dump_definition (pfile, hp)
} }
static void static void
dump_DEFINITION (pfile, defn) dump_funlike_macro (pfile, defn)
cpp_reader *pfile; cpp_reader *pfile;
DEFINITION *defn; const struct funct_defn *defn;
{ {
struct reflist *r; const struct reflist *r;
unsigned char **argv = (unsigned char **) alloca (defn->nargs * const U_CHAR **argv = (const U_CHAR **) alloca (defn->nargs *
sizeof(char *)); sizeof(const U_CHAR *));
int *argl = (int *) alloca (defn->nargs * sizeof(int)); int *argl = (int *) alloca (defn->nargs * sizeof(int));
unsigned char *x; const U_CHAR *x;
int i; int i;
/* First extract the argument list. */ /* First extract the argument list. */
......
...@@ -45,35 +45,28 @@ enum node_type ...@@ -45,35 +45,28 @@ enum node_type
T_CONST, /* Constant string, used by `__SIZE_TYPE__' etc */ T_CONST, /* Constant string, used by `__SIZE_TYPE__' etc */
T_XCONST, /* Ditto, but the string is malloced memory */ T_XCONST, /* Ditto, but the string is malloced memory */
T_POISON, /* poisoned identifier */ T_POISON, /* poisoned identifier */
T_MCONST, /* object-like macro defined to a single identifier */ T_MACRO, /* object-like macro */
T_MACRO, /* general object-like macro */ T_FMACRO, /* function-like macro */
T_FMACRO, /* general function-like macro */
T_IDENTITY, /* macro defined to itself */ T_IDENTITY, /* macro defined to itself */
T_EMPTY /* macro defined to nothing */ T_EMPTY /* macro defined to nothing */
}; };
/* different kinds of things that can appear in the value field
of a hash node. */
union hashval
{
const char *cpval; /* some predefined macros */
struct definition *defn; /* #define */
struct hashnode *aschain; /* #assert */
};
typedef struct hashnode HASHNODE; typedef struct hashnode HASHNODE;
struct hashnode struct hashnode
{ {
const U_CHAR *name; /* the actual name */ unsigned int hash; /* cached hash value */
size_t length; /* length of token, for quick comparison */ unsigned short length; /* length of name */
unsigned long hash; /* cached hash value */ ENUM_BITFIELD(node_type) type : 8; /* node type */
union hashval value; /* pointer to expansion, or whatever */ char disabled; /* macro turned off for rescan? */
enum node_type type; /* type of special token */
int disabled; /* macro turned off for rescan? */ union {
const char *cpval; /* some predefined macros */
const char *file; /* File, line, column of definition; */ const struct object_defn *odefn; /* #define foo bar */
int line; const struct funct_defn *fdefn; /* #define foo(x) bar(x) */
int col; struct hashnode *aschain; /* #assert */
} value;
const U_CHAR *name;
}; };
/* List of directories to look for include files in. */ /* List of directories to look for include files in. */
......
...@@ -727,7 +727,6 @@ do_undef (pfile) ...@@ -727,7 +727,6 @@ do_undef (pfile)
pass_thru_directive (hp->name, len, pfile, T_UNDEF); pass_thru_directive (hp->name, len, pfile, T_UNDEF);
if (hp->type != T_MACRO && hp->type != T_FMACRO if (hp->type != T_MACRO && hp->type != T_FMACRO
&& hp->type != T_MCONST
&& hp->type != T_EMPTY && hp->type != T_IDENTITY) && hp->type != T_EMPTY && hp->type != T_IDENTITY)
cpp_warning (pfile, "undefining `%s'", hp->name); cpp_warning (pfile, "undefining `%s'", hp->name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment