cpplib.c (special_symbol): Rewrite.

1999-02-08 23:25 -0500  Zack Weinberg  <zack@midnite.ec.rhno.columbia.edu>
	* cpplib.c (special_symbol): Rewrite.  Don't copy things
	  multiple times.  Handle __STDC__ specially.  T_CONST
	  indicates a constant /string/.  Don't handle T_*_TYPE and
	  T_SPEC_DEFINED.  Use cpp_buf_line_and_col instead of
	  adjust_position.  Determine the file buffer only if needed.
	  (initialize_builtins): Handle __SIZE_TYPE__,
	  __PTRDIFF_TYPE__, __WCHAR_TYPE__, __USER_LABEL_PREFIX__, and
	  __REGISTER_PREFIX__ with T_CONST special hashtab entries.
	  Don't provide __OBJC__; the driver does that.	 Provide
	  __STDC_VERSION__, using T_CONST.  Use T_STDC for
	  __STDC__.  Give install the length of all symbols defined.
	  (eval_if_expression): Drop code to insert and remove the
	  "defined" special symbol.
	* cpplib.h: Remove SELF_DIR_DUMMY (no longer used).  Remove
	  T_*_TYPE and T_SPEC_DEFINED from enum node_type; add T_STDC.
	* cpphash.c (install): Drop the `ivalue' parameter.  Constify
	  the `value' parameter.  All callers changed.
	* cpphash.h (install): Change prototype to match.
	  (union hashval): Remove `ival' member.
	* cppexp.c (cpp_lex): Handle `defined' here.

From-SVN: r25097
This commit is contained in:
Zack Weinberg 1999-02-08 20:27:27 +00:00 committed by Zack Weinberg
parent 1c6c21c8a8
commit 5dfa4da130
6 changed files with 188 additions and 215 deletions

View File

@ -1,3 +1,28 @@
1999-02-08 23:25 -0500 Zack Weinberg <zack@midnite.ec.rhno.columbia.edu>
* cpplib.c (special_symbol): Rewrite. Don't copy things
multiple times. Handle __STDC__ specially. T_CONST
indicates a constant /string/. Don't handle T_*_TYPE and
T_SPEC_DEFINED. Use cpp_buf_line_and_col instead of
adjust_position. Determine the file buffer only if needed.
(initialize_builtins): Handle __SIZE_TYPE__,
__PTRDIFF_TYPE__, __WCHAR_TYPE__, __USER_LABEL_PREFIX__, and
__REGISTER_PREFIX__ with T_CONST special hashtab entries.
Don't provide __OBJC__; the driver does that. Provide
__STDC_VERSION__, using T_CONST. Use T_STDC for
__STDC__. Give install the length of all symbols defined.
(eval_if_expression): Drop code to insert and remove the
"defined" special symbol.
* cpplib.h: Remove SELF_DIR_DUMMY (no longer used). Remove
T_*_TYPE and T_SPEC_DEFINED from enum node_type; add T_STDC.
* cpphash.c (install): Drop the `ivalue' parameter. Constify
the `value' parameter. All callers changed.
* cpphash.h (install): Change prototype to match.
(union hashval): Remove `ival' member.
* cppexp.c (cpp_lex): Handle `defined' here.
Mon Feb 8 17:29:42 1999 Jeffrey A Law (law@cygnus.com)
* pa.h (EXTRA_CONSTRAINT): Fix comment.

View File

@ -1,5 +1,5 @@
/* Parse C expressions for CCCP.
Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998 Free Software Foundation.
Copyright (C) 1987, 92, 94, 95, 97, 98, 1999 Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@ -109,6 +109,8 @@ static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long));
#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
#endif
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
struct operation {
short op;
char rprio; /* Priority of op (relative to it right operand). */
@ -435,12 +437,52 @@ cpp_lex (pfile, skip_evaluation)
return parse_charconst (pfile, tok_start, tok_end);
case CPP_NAME:
if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
cpp_warning (pfile, "`%.*s' is not defined",
(int) (tok_end - tok_start), tok_start);
op.op = INT;
op.unsignedp = 0;
op.value = 0;
if (strcmp (tok_start, "defined"))
{
if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
cpp_warning (pfile, "`%.*s' is not defined",
(int) (tok_end - tok_start), tok_start);
}
else
{
int paren = 0, len;
cpp_buffer *ip = CPP_BUFFER (pfile);
U_CHAR *tok;
SKIP_WHITE_SPACE (ip->cur);
if (*ip->cur == '(')
{
paren++;
ip->cur++; /* Skip over the paren */
SKIP_WHITE_SPACE (ip->cur);
}
if (!is_idstart[*ip->cur])
goto oops;
if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
goto oops;
tok = ip->cur;
while (is_idchar[*ip->cur])
++ip->cur;
len = ip->cur - tok;
SKIP_WHITE_SPACE (ip->cur);
if (paren)
{
if (*ip->cur != ')')
goto oops;
++ip->cur;
}
if (cpp_lookup (pfile, tok, len, -1))
op.value = 1;
}
return op;
oops:
cpp_error (pfile, "`defined' without an identifier");
return op;
case CPP_OTHER:

View File

@ -131,8 +131,8 @@ delete_macro (hp)
}
/* Install a name in the main hash table, even if it is already there.
name stops with first non alphanumeric, except leading '#'.
caller must check against redefinition if that is desired.
Name stops with first non alphanumeric, except leading '#'.
Caller must check against redefinition if that is desired.
delete_macro () removes things installed by install () in fifo order.
this is important because of the `defined' special symbol used
in #if, and also if pushdef/popdef directives are ever implemented.
@ -144,12 +144,11 @@ delete_macro (hp)
Otherwise, compute the hash code. */
HASHNODE *
install (name, len, type, ivalue, value, hash)
install (name, len, type, value, hash)
U_CHAR *name;
int len;
enum node_type type;
int ivalue;
char *value;
const char *value;
int hash;
{
register HASHNODE *hp;
@ -177,10 +176,7 @@ install (name, len, type, ivalue, value, hash)
hp->next->prev = hp;
hp->type = type;
hp->length = len;
if (hp->type == T_CONST)
hp->value.ival = ivalue;
else
hp->value.cpval = value;
hp->value.cpval = value;
hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
bcopy (name, hp->name, len);
hp->name[len] = 0;

View File

@ -16,12 +16,12 @@ along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* different kinds of things that can appear in the value field
of a hash node. Actually, this may be useless now. */
union hashval {
int ival;
char *cpval;
DEFINITION *defn;
struct hashnode *aschain; /* for #assert */
of a hash node. */
union hashval
{
const char *cpval; /* some predefined macros */
DEFINITION *defn; /* #define */
struct hashnode *aschain; /* #assert */
};
struct hashnode {
@ -49,6 +49,7 @@ typedef struct hashnode HASHNODE;
#define HASHSTEP(old, c) ((old << 2) + c)
#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
extern HASHNODE *install PARAMS ((U_CHAR *,int,enum node_type, int,char *,int));
extern HASHNODE *install PARAMS ((U_CHAR *, int, enum node_type,
const char *, int));
extern int hashf PARAMS ((const U_CHAR *, int, int));
extern void delete_macro PARAMS ((HASHNODE *));

View File

@ -1435,7 +1435,7 @@ do_define (pfile, keyword)
that for this new definition now. */
if (CPP_OPTIONS (pfile)->debug_output && keyword)
pass_thru_directive (macro, end, pfile, keyword);
install (mdef.symnam, mdef.symlen, T_MACRO, 0,
install (mdef.symnam, mdef.symlen, T_MACRO,
(char *) mdef.defn, hashcode);
}
@ -1883,201 +1883,121 @@ special_symbol (hp, pfile)
cpp_reader *pfile;
{
const char *buf;
char *wbuf;
int len;
int true_indepth;
cpp_buffer *ip = NULL;
struct tm *timebuf;
int paren = 0; /* For special `defined' keyword */
#if 0
if (pcp_outfile && pcp_inside_if
&& hp->type != T_SPEC_DEFINED && hp->type != T_CONST)
cpp_error (pfile,
"Predefined macro `%s' used inside `#if' during precompilation",
hp->name);
#endif
for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
{
if (ip == CPP_NULL_BUFFER (pfile))
{
cpp_error (pfile, "cccp error: not in any file?!");
return; /* the show must go on */
}
if (ip->fname != NULL)
break;
}
switch (hp->type)
{
case T_FILE:
case T_BASE_FILE:
{
char *string;
cpp_buffer *ip = CPP_BUFFER (pfile);
if (hp->type == T_BASE_FILE)
{
while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
}
string = ip->nominal_fname;
else
{
ip = CPP_BUFFER (pfile);
while (! ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
}
if (!string)
string = "";
CPP_RESERVE (pfile, 3 + 4 * strlen (string));
quote_string (pfile, string);
buf = ip->nominal_fname;
if (!buf)
buf = "";
CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
quote_string (pfile, buf);
return;
}
case T_INCLUDE_LEVEL:
true_indepth = 0;
ip = CPP_BUFFER (pfile);
for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
if (ip->fname != NULL)
true_indepth++;
{
int true_indepth = 0;
cpp_buffer *ip = CPP_BUFFER (pfile);
for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
if (ip->fname != NULL)
true_indepth++;
wbuf = (char *) alloca (8); /* Eight bytes ought to be more than enough*/
sprintf (wbuf, "%d", true_indepth - 1);
buf = wbuf;
break;
CPP_RESERVE (pfile, 10);
sprintf (CPP_PWRITTEN (pfile), "%d", true_indepth);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
return;
}
case T_VERSION:
wbuf = (char *) alloca (3 + strlen (version_string));
sprintf (wbuf, "\"%s\"", version_string);
buf = wbuf;
break;
case T_VERSION:
len = strlen (version_string);
CPP_RESERVE (pfile, 3 + len);
CPP_PUTC_Q (pfile, '"');
CPP_PUTS_Q (pfile, version_string, len);
CPP_PUTC_Q (pfile, '"');
CPP_NUL_TERMINATE_Q (pfile);
return;
#ifndef NO_BUILTIN_SIZE_TYPE
case T_SIZE_TYPE:
buf = SIZE_TYPE;
break;
#endif
case T_CONST:
buf = hp->value.cpval;
if (!buf)
return;
#ifndef NO_BUILTIN_PTRDIFF_TYPE
case T_PTRDIFF_TYPE:
buf = PTRDIFF_TYPE;
break;
#endif
len = strlen (buf);
CPP_RESERVE (pfile, len + 1);
CPP_PUTS_Q (pfile, buf, len);
CPP_NUL_TERMINATE_Q (pfile);
return;
case T_WCHAR_TYPE:
buf = CPP_WCHAR_TYPE (pfile);
break;
case T_USER_LABEL_PREFIX_TYPE:
buf = user_label_prefix;
break;
case T_REGISTER_PREFIX_TYPE:
buf = REGISTER_PREFIX;
break;
case T_CONST:
wbuf = (char *) alloca (4 * sizeof (int));
sprintf (wbuf, "%d", hp->value.ival);
case T_STDC:
CPP_RESERVE (pfile, 2);
#ifdef STDC_0_IN_SYSTEM_HEADERS
ip = CPP_BUFFER (pfile);
while (! ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
if (ip->system_header_p
&& hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
&& ! cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", -1, -1))
strcpy (wbuf, "0");
&& ! cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", 15, -1))
CPP_PUTC_Q (pfile, '0');
else
#endif
#if 0
if (pcp_inside_if && pcp_outfile)
/* Output a precondition for this macro use */
fprintf (pcp_outfile, "#define %s %d\n", hp->name, hp->value.ival);
#endif
buf = wbuf;
break;
CPP_PUTC_Q (pfile, '1');
CPP_NUL_TERMINATE_Q (pfile);
return;
case T_SPECLINE:
{
long line = ip->lineno;
long col = ip->colno;
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
long line;
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, NULL);
wbuf = (char *) alloca (10);
sprintf (wbuf, "%ld", line);
buf = wbuf;
CPP_RESERVE (pfile, 10);
sprintf (CPP_PWRITTEN (pfile), "%ld", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
return;
}
break;
case T_DATE:
case T_TIME:
wbuf = (char *) alloca (20);
timebuf = timestamp (pfile);
if (hp->type == T_DATE)
sprintf (wbuf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
timebuf->tm_mday, timebuf->tm_year + 1900);
else
sprintf (wbuf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
timebuf->tm_sec);
buf = wbuf;
break;
{
struct tm *timebuf;
case T_SPEC_DEFINED:
buf = " 0 "; /* Assume symbol is not defined */
ip = CPP_BUFFER (pfile);
SKIP_WHITE_SPACE (ip->cur);
if (*ip->cur == '(')
{
paren++;
ip->cur++; /* Skip over the paren */
SKIP_WHITE_SPACE (ip->cur);
}
CPP_RESERVE (pfile, 20);
timebuf = timestamp (pfile);
if (hp->type == T_DATE)
sprintf (CPP_PWRITTEN (pfile), "\"%s %2d %4d\"",
monthnames[timebuf->tm_mon],
timebuf->tm_mday, timebuf->tm_year + 1900);
else
sprintf (CPP_PWRITTEN (pfile), "\"%02d:%02d:%02d\"",
timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
if (!is_idstart[*ip->cur])
goto oops;
if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
goto oops;
if ((hp = cpp_lookup (pfile, ip->cur, -1, -1)))
{
#if 0
if (pcp_outfile && pcp_inside_if
&& (hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
/* Output a precondition for this macro use. */
fprintf (pcp_outfile, "#define %s\n", hp->name);
#endif
buf = " 1 ";
}
#if 0
else
if (pcp_outfile && pcp_inside_if)
{
/* Output a precondition for this macro use */
U_CHAR *cp = ip->bufp;
fprintf (pcp_outfile, "#undef ");
while (is_idchar[*cp]) /* Ick! */
fputc (*cp++, pcp_outfile);
putc ('\n', pcp_outfile);
}
#endif
while (is_idchar[*ip->cur])
++ip->cur;
SKIP_WHITE_SPACE (ip->cur);
if (paren)
{
if (*ip->cur != ')')
goto oops;
++ip->cur;
}
break;
oops:
cpp_error (pfile, "`defined' without an identifier");
break;
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
return;
}
default:
cpp_error (pfile, "cccp error: invalid special hash type"); /* time for gdb */
abort ();
cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
return;
}
len = strlen (buf);
CPP_RESERVE (pfile, len + 1);
CPP_PUTS_Q (pfile, buf, len);
CPP_NUL_TERMINATE_Q (pfile);
return;
/* This point should be unreachable. */
abort();
}
/* Write out a #define command for the special named MACRO_NAME
@ -2105,29 +2025,34 @@ static void
initialize_builtins (pfile)
cpp_reader *pfile;
{
install ((U_CHAR *)"__LINE__", -1, T_SPECLINE, 0, 0, -1);
install ((U_CHAR *)"__DATE__", -1, T_DATE, 0, 0, -1);
install ((U_CHAR *)"__FILE__", -1, T_FILE, 0, 0, -1);
install ((U_CHAR *)"__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
install ((U_CHAR *)"__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
install ((U_CHAR *)"__VERSION__", -1, T_VERSION, 0, 0, -1);
#define NAME(str) (U_CHAR *)str, sizeof str - 1
install (NAME("__TIME__"), T_TIME, 0, -1);
install (NAME("__DATE__"), T_DATE, 0, -1);
install (NAME("__FILE__"), T_FILE, 0, -1);
install (NAME("__BASE_FILE__"), T_BASE_FILE, 0, -1);
install (NAME("__LINE__"), T_SPECLINE, 0, -1);
install (NAME("__INCLUDE_LEVEL__"), T_INCLUDE_LEVEL, 0, -1);
install (NAME("__VERSION__"), T_VERSION, 0, -1);
#ifndef NO_BUILTIN_SIZE_TYPE
install ((U_CHAR *)"__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
install (NAME("__SIZE_TYPE__"), T_CONST, SIZE_TYPE, -1);
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
install ((U_CHAR *)"__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
install (NAME("__PTRDIFF_TYPE__ "), T_CONST, PTRDIFF_TYPE, -1);
#endif
install ((U_CHAR *)"__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
install ((U_CHAR *)"__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
install ((U_CHAR *)"__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
install ((U_CHAR *)"__TIME__", -1, T_TIME, 0, 0, -1);
install (NAME("__WCHAR_TYPE__"), T_CONST, WCHAR_TYPE, -1);
install (NAME("__USER_LABEL_PREFIX__"), T_CONST, user_label_prefix, -1);
install (NAME("__REGISTER_PREFIX__"), T_CONST, REGISTER_PREFIX, -1);
if (!CPP_TRADITIONAL (pfile))
install ((U_CHAR *)"__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
if (CPP_OPTIONS (pfile)->objc)
install ((U_CHAR *)"__OBJC__", -1, T_CONST, 1, 0, -1);
/* This is supplied using a -D by the compiler driver
so that it is present only when truly compiling with GNU C. */
/* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */
{
install (NAME("__STDC__"), T_STDC, 0, -1);
#if 0
if (CPP_OPTIONS (pfile)->c9x)
install (NAME("__STDC_VERSION__"),T_CONST, "199909L", -1);
else
#endif
install (NAME("__STDC_VERSION__"),T_CONST, "199409L", -1);
}
#undef NAME
if (CPP_OPTIONS (pfile)->debug_output)
{
@ -2144,8 +2069,6 @@ initialize_builtins (pfile)
dump_special_to_buffer (pfile, "__TIME__");
if (!CPP_TRADITIONAL (pfile))
dump_special_to_buffer (pfile, "__STDC__");
if (CPP_OPTIONS (pfile)->objc)
dump_special_to_buffer (pfile, "__OBJC__");
}
}
@ -3377,16 +3300,12 @@ static HOST_WIDE_INT
eval_if_expression (pfile)
cpp_reader *pfile;
{
HASHNODE *save_defined;
HOST_WIDE_INT value;
long old_written = CPP_WRITTEN (pfile);
save_defined = install ((U_CHAR *)"defined", -1, T_SPEC_DEFINED, 0, 0, -1);
pfile->pcp_inside_if = 1;
value = cpp_parse_expr (pfile);
pfile->pcp_inside_if = 0;
delete_macro (save_defined); /* clean up special symbol */
CPP_SET_WRITTEN (pfile, old_written); /* Pop */
@ -5818,7 +5737,7 @@ do_assert (pfile, keyword)
base = cpp_lookup (pfile, sym, baselen, -1);
if (! base)
base = install (sym, baselen, T_ASSERT, 0, 0, -1);
base = install (sym, baselen, T_ASSERT, 0, -1);
else if (base->type != T_ASSERT)
{
/* Token clash - but with what?! */
@ -5827,7 +5746,7 @@ do_assert (pfile, keyword)
goto error;
}
this = install (sym, thislen, T_ASSERT, 0,
this = install (sym, thislen, T_ASSERT,
(char *)base->value.aschain, -1);
base->value.aschain = this;

View File

@ -526,12 +526,7 @@ struct include_hash
redundant_include_p */
char *buf, *limit; /* for file content cache, not yet implemented */
};
/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
via the same directory as the file that #included it. */
#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
/* Name under which this program was invoked. */
extern char *progname;
@ -570,16 +565,11 @@ enum node_type {
T_BASE_FILE, /* `__BASE_FILE__' */
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
T_VERSION, /* `__VERSION__' */
T_SIZE_TYPE, /* `__SIZE_TYPE__' */
T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */
T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */
T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */
T_REGISTER_PREFIX_TYPE, /* `__REGISTER_PREFIX__' */
T_TIME, /* `__TIME__' */
T_CONST, /* Constant value, used by `__STDC__' */
T_STDC, /* `__STDC__' */
T_CONST, /* Constant string, used by `__SIZE_TYPE__' etc */
T_MACRO, /* macro defined by `#define' */
T_DISABLED, /* macro temporarily turned off for rescan */
T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
T_UNUSED /* Used for something not defined. */
};