Commit 91dbf5e7 by Richard Kenner

(rescan): Add support for %: and %:%: digraphs.

(collect_expansion, skip_if_group, dump_single_macro): Likewise.
(union hashval): Remove ival member; it doesn't suffice for `199409L'.
(special_symbol): Use cpval instead of ival for T_CONST macros.
(install): Remove ivalue argument, since string value now suffices.
All callers changed.
(initialize_builtins): Switch from int to string values for T_CONST.
If not traditional, initialize __STDC_VERSION__ to 199409L.
(STDC_VALUE): Remove no-longer-used configuration macro.

From-SVN: r8983
parent 1f746936
...@@ -57,10 +57,6 @@ typedef unsigned char U_CHAR; ...@@ -57,10 +57,6 @@ typedef unsigned char U_CHAR;
#include "pcp.h" #include "pcp.h"
#ifndef STDC_VALUE
#define STDC_VALUE 1
#endif
/* By default, colon separates directories in a path. */ /* By default, colon separates directories in a path. */
#ifndef PATH_SEPARATOR #ifndef PATH_SEPARATOR
#define PATH_SEPARATOR ':' #define PATH_SEPARATOR ':'
...@@ -714,10 +710,14 @@ struct definition { ...@@ -714,10 +710,14 @@ struct definition {
char rest_args; /* Nonzero if last arg. absorbs the rest */ char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist { struct reflist {
struct reflist *next; struct reflist *next;
/* The following three members have the value '#' if spelled with "#",
and '%' if spelled with "%:". */
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. */
char raw_after; /* Nonzero if a ## operator after arg. */ char raw_after; /* Nonzero if a ## operator after arg. */
char rest_args; /* Nonzero if this arg. absorbs the rest */ char rest_args; /* Nonzero if this arg. absorbs the rest */
int nchars; /* Number of literal chars to copy before int nchars; /* Number of literal chars to copy before
this arg occurrence. */ this arg occurrence. */
...@@ -735,7 +735,6 @@ struct definition { ...@@ -735,7 +735,6 @@ struct definition {
/* different kinds of things that can appear in the value field /* different kinds of things that can appear in the value field
of a hash node. Actually, this may be useless now. */ of a hash node. Actually, this may be useless now. */
union hashval { union hashval {
int ival;
char *cpval; char *cpval;
DEFINITION *defn; DEFINITION *defn;
KEYDEF *keydef; KEYDEF *keydef;
...@@ -955,7 +954,7 @@ static struct directive directive_table[] = { ...@@ -955,7 +954,7 @@ static struct directive directive_table[] = {
}; };
/* When a directive handler is called, /* When a directive handler is called,
this points to the # that started the directive. */ this points to the # (or the : of the %:) that started the directive. */
U_CHAR *directive_start; U_CHAR *directive_start;
/* table to tell if char can be part of a C identifier. */ /* table to tell if char can be part of a C identifier. */
...@@ -2581,9 +2580,24 @@ do { ip = &instack[indepth]; \ ...@@ -2581,9 +2580,24 @@ do { ip = &instack[indepth]; \
*obp++ = *ibp++; *obp++ = *ibp++;
break; break;
case '%':
if (ident_length || ip->macro || traditional)
goto randomchar;
if (ip->fname == 0 && beg_of_line == ip->buf)
goto randomchar;
while (*ibp == '\\' && ibp[1] == '\n') {
ibp += 2;
++ip->lineno;
}
if (*ibp != ':')
break;
/* Treat this %: digraph as if it were #. */
/* Fall through. */
case '#': case '#':
if (assertions_flag) { if (assertions_flag) {
/* Copy #foo (bar lose) without macro expansion. */ /* Copy #foo (bar lose) without macro expansion. */
obp[-1] = '#'; /* In case it was '%'. */
SKIP_WHITE_SPACE (ibp); SKIP_WHITE_SPACE (ibp);
while (is_idchar[*ibp]) while (is_idchar[*ibp])
*obp++ = *ibp++; *obp++ = *ibp++;
...@@ -2621,7 +2635,7 @@ do { ip = &instack[indepth]; \ ...@@ -2621,7 +2635,7 @@ do { ip = &instack[indepth]; \
If not, this # is not special. */ If not, this # is not special. */
bp = beg_of_line; bp = beg_of_line;
/* If -traditional, require # to be at beginning of line. */ /* If -traditional, require # to be at beginning of line. */
if (!traditional) if (!traditional) {
while (1) { while (1) {
if (is_hor_space[*bp]) if (is_hor_space[*bp])
bp++; bp++;
...@@ -2638,6 +2652,18 @@ do { ip = &instack[indepth]; \ ...@@ -2638,6 +2652,18 @@ do { ip = &instack[indepth]; \
comment and we would never reach here. */ comment and we would never reach here. */
else break; else break;
} }
if (c == '%') {
if (bp[0] != '%')
break;
while (bp[1] == '\\' && bp[2] == '\n')
bp += 2;
if (bp + 1 != ibp)
break;
/* %: appears at start of line; skip past the ':' too. */
bp++;
ibp++;
}
}
if (bp + 1 != ibp) if (bp + 1 != ibp)
goto randomchar; goto randomchar;
} }
...@@ -2663,7 +2689,7 @@ do { ip = &instack[indepth]; \ ...@@ -2663,7 +2689,7 @@ do { ip = &instack[indepth]; \
beg_of_line = ibp; beg_of_line = ibp;
break; break;
} }
++obp; /* Copy the '#' after all */ *obp++ = '#'; /* Copy # (even if it was originally %:). */
/* Don't expand an identifier that could be a macro directive. /* Don't expand an identifier that could be a macro directive.
(Section 3.8.3 of the ANSI C standard) */ (Section 3.8.3 of the ANSI C standard) */
SKIP_WHITE_SPACE (ibp); SKIP_WHITE_SPACE (ibp);
...@@ -3295,7 +3321,8 @@ startagain: ...@@ -3295,7 +3321,8 @@ startagain:
before the macro call. */ before the macro call. */
if (!traditional && obp != op->buf) { if (!traditional && obp != op->buf) {
switch (obp[-1]) { switch (obp[-1]) {
case '&': case '+': case '-': case '<': case '>': case '|': case '%': case '&': case '+': case '-':
case ':': case '<': case '>': case '|':
/* If we are expanding a macro arg, make a newline marker /* If we are expanding a macro arg, make a newline marker
to separate the tokens. If we are making real output, to separate the tokens. If we are making real output,
a plain space will do. */ a plain space will do. */
...@@ -3956,11 +3983,10 @@ special_symbol (hp, op) ...@@ -3956,11 +3983,10 @@ special_symbol (hp, op)
break; break;
case T_CONST: case T_CONST:
buf = (char *) alloca (4 * sizeof (int)); buf = hp->value.cpval;
sprintf (buf, "%d", hp->value.ival);
if (pcp_inside_if && pcp_outfile) if (pcp_inside_if && pcp_outfile)
/* Output a precondition for this macro use */ /* Output a precondition for this macro use */
fprintf (pcp_outfile, "#define %s %d\n", hp->name, hp->value.ival); fprintf (pcp_outfile, "#define %s %s\n", hp->name, buf);
break; break;
case T_SPECLINE: case T_SPECLINE:
...@@ -5221,7 +5247,7 @@ pcfinclude (buf, limit, name, op) ...@@ -5221,7 +5247,7 @@ pcfinclude (buf, limit, name, op)
hp = lookup (tmpbuf.bufp, -1, -1); hp = lookup (tmpbuf.bufp, -1, -1);
if (hp == NULL) { if (hp == NULL) {
kp->chain = 0; kp->chain = 0;
install (tmpbuf.bufp, -1, T_PCSTRING, 0, (char *) kp, -1); install (tmpbuf.bufp, -1, T_PCSTRING, (char *) kp, -1);
} }
else if (hp->type == T_PCSTRING) { else if (hp->type == T_PCSTRING) {
kp->chain = hp->value.keydef; kp->chain = hp->value.keydef;
...@@ -5586,7 +5612,7 @@ do_define (buf, limit, op, keyword) ...@@ -5586,7 +5612,7 @@ do_define (buf, limit, op, keyword)
that for this new definition now. */ that for this new definition now. */
if (debug_output && op) if (debug_output && op)
pass_thru_directive (buf, limit, op, keyword); pass_thru_directive (buf, limit, op, keyword);
install (mdef.symnam, mdef.symlen, T_MACRO, 0, install (mdef.symnam, mdef.symlen, T_MACRO,
(char *) mdef.defn, hashcode); (char *) mdef.defn, hashcode);
} }
} }
...@@ -5735,6 +5761,9 @@ collect_expansion (buf, end, nargs, arglist) ...@@ -5735,6 +5761,9 @@ collect_expansion (buf, end, nargs, arglist)
U_CHAR *concat = 0; U_CHAR *concat = 0;
/* Pointer to first nonspace after last single-# seen. */ /* Pointer to first nonspace after last single-# seen. */
U_CHAR *stringify = 0; U_CHAR *stringify = 0;
/* How those tokens were spelled: 0, '#', or '%' (meaning %:). */
char concat_spelling = 0;
char stringify_spelling = 0;
int maxsize; int maxsize;
int expected_delimiter = '\0'; int expected_delimiter = '\0';
...@@ -5775,9 +5804,11 @@ collect_expansion (buf, end, nargs, arglist) ...@@ -5775,9 +5804,11 @@ collect_expansion (buf, end, nargs, arglist)
*exp_p++ = *p++; *exp_p++ = *p++;
} }
if (limit - p >= 2 && p[0] == '#' && p[1] == '#') { if (p[0] == '#'
? p[1] == '#'
: p[0] == '%' && p[1] == ':' && p[2] == '%' && p[3] == ':') {
error ("`##' at start of macro definition"); error ("`##' at start of macro definition");
p += 2; p += p[0] == '#' ? 2 : 4;
} }
/* Process the main body of the definition. */ /* Process the main body of the definition. */
...@@ -5806,11 +5837,32 @@ collect_expansion (buf, end, nargs, arglist) ...@@ -5806,11 +5837,32 @@ collect_expansion (buf, end, nargs, arglist)
} }
break; break;
case '%':
if (!expected_delimiter && *p == ':') {
/* %: is not a digraph if preceded by an odd number of '<'s. */
U_CHAR *p0 = p - 1;
while (buf < p0 && p0[-1] == '<')
p0--;
if ((p - p0) & 1) {
/* Treat %:%: as ## and %: as #. */
if (p[1] == '%' && p[2] == ':') {
p += 2;
goto hash_hash_token;
}
if (nargs >= 0) {
p++;
goto hash_token;
}
}
}
break;
case '#': case '#':
/* # is ordinary inside a string. */ /* # is ordinary inside a string. */
if (expected_delimiter) if (expected_delimiter)
break; break;
if (p < limit && *p == '#') { if (*p == '#') {
hash_hash_token:
/* ##: concatenate preceding and following tokens. */ /* ##: concatenate preceding and following tokens. */
/* Take out the first #, discard preceding whitespace. */ /* Take out the first #, discard preceding whitespace. */
exp_p--; exp_p--;
...@@ -5821,17 +5873,21 @@ collect_expansion (buf, end, nargs, arglist) ...@@ -5821,17 +5873,21 @@ collect_expansion (buf, end, nargs, arglist)
/* Discard following whitespace. */ /* Discard following whitespace. */
SKIP_WHITE_SPACE (p); SKIP_WHITE_SPACE (p);
concat = p; concat = p;
concat_spelling = c;
if (p == limit) if (p == limit)
error ("`##' at end of macro definition"); error ("`##' at end of macro definition");
} else if (nargs >= 0) { } else if (nargs >= 0) {
/* Single #: stringify following argument ref. /* Single #: stringify following argument ref.
Don't leave the # in the expansion. */ Don't leave the # in the expansion. */
hash_token:
exp_p--; exp_p--;
SKIP_WHITE_SPACE (p); SKIP_WHITE_SPACE (p);
if (p == limit || ! is_idstart[*p] || nargs == 0) if (! is_idstart[*p] || nargs == 0)
error ("`#' operator is not followed by a macro argument name"); error ("`#' operator is not followed by a macro argument name");
else else {
stringify = p; stringify = p;
stringify_spelling = c;
}
} }
break; break;
} }
...@@ -5913,11 +5969,11 @@ collect_expansion (buf, end, nargs, arglist) ...@@ -5913,11 +5969,11 @@ collect_expansion (buf, end, nargs, arglist)
the pat list */ the pat list */
tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
tpat->next = NULL; tpat->next = NULL;
tpat->raw_before = concat == id_beg; tpat->raw_before = concat == id_beg ? concat_spelling : 0;
tpat->raw_after = 0; tpat->raw_after = 0;
tpat->rest_args = arg->rest_args; tpat->rest_args = arg->rest_args;
tpat->stringify = (traditional ? expected_delimiter != '\0' tpat->stringify = (traditional ? expected_delimiter != '\0'
: stringify == id_beg); : stringify == id_beg) ? stringify_spelling : 0;
if (endpat == NULL) if (endpat == NULL)
defn->pattern = tpat; defn->pattern = tpat;
...@@ -5930,8 +5986,10 @@ collect_expansion (buf, end, nargs, arglist) ...@@ -5930,8 +5986,10 @@ collect_expansion (buf, end, nargs, arglist)
{ {
register U_CHAR *p1 = p; register U_CHAR *p1 = p;
SKIP_WHITE_SPACE (p1); SKIP_WHITE_SPACE (p1);
if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#') if (p1[0]=='#'
tpat->raw_after = 1; ? p1[1]=='#'
: p1[0]=='%' && p1[1]==':' && p1[2]=='%' && p1[3]==':')
tpat->raw_after = p1[0];
} }
lastp = exp_p; /* place to start copying from next time */ lastp = exp_p; /* place to start copying from next time */
skipped_arg = 1; skipped_arg = 1;
...@@ -6841,7 +6899,7 @@ eval_if_expression (buf, length) ...@@ -6841,7 +6899,7 @@ eval_if_expression (buf, length)
HASHNODE *save_defined; HASHNODE *save_defined;
HOST_WIDE_INT value; HOST_WIDE_INT value;
save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, NULL_PTR, -1); save_defined = install ("defined", -1, T_SPEC_DEFINED, NULL_PTR, -1);
pcp_inside_if = 1; pcp_inside_if = 1;
temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1); temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1);
pcp_inside_if = 0; pcp_inside_if = 0;
...@@ -7044,18 +7102,27 @@ skip_if_group (ip, any, op) ...@@ -7044,18 +7102,27 @@ skip_if_group (ip, any, op)
++ip->lineno; ++ip->lineno;
beg_of_line = bp; beg_of_line = bp;
break; break;
case '#': case '%':
if (beg_of_line == 0 || traditional)
break;
ip->bufp = bp - 1; ip->bufp = bp - 1;
while (bp[0] == '\\' && bp[1] == '\n')
bp += 2;
if (*bp == ':')
goto hash_token;
break;
case '#':
/* # keyword: a # must be first nonblank char on the line */ /* # keyword: a # must be first nonblank char on the line */
if (beg_of_line == 0) if (beg_of_line == 0)
break; break;
ip->bufp = bp - 1;
hash_token:
/* Scan from start of line, skipping whitespace, comments /* Scan from start of line, skipping whitespace, comments
and backslash-newlines, and see if we reach this #. and backslash-newlines, and see if we reach this #.
If not, this # is not special. */ If not, this # is not special. */
bp = beg_of_line; bp = beg_of_line;
/* If -traditional, require # to be at beginning of line. */ /* If -traditional, require # to be at beginning of line. */
if (!traditional) if (!traditional) {
while (1) { while (1) {
if (is_hor_space[*bp]) if (is_hor_space[*bp])
bp++; bp++;
...@@ -7072,12 +7139,21 @@ skip_if_group (ip, any, op) ...@@ -7072,12 +7139,21 @@ skip_if_group (ip, any, op)
comment and we would never reach here. */ comment and we would never reach here. */
else break; else break;
} }
}
if (bp != ip->bufp) { if (bp != ip->bufp) {
bp = ip->bufp + 1; /* Reset bp to after the #. */ bp = ip->bufp + 1; /* Reset bp to after the #. */
break; break;
} }
bp = ip->bufp + 1; /* Point after the '#' */ bp = ip->bufp + 1; /* Point after the '#' */
if (ip->bufp[0] == '%') {
/* Skip past the ':' again. */
while (*bp == '\\') {
ip->lineno++;
bp += 2;
}
bp++;
}
/* Skip whitespace and \-newline. */ /* Skip whitespace and \-newline. */
while (1) { while (1) {
...@@ -8902,11 +8978,10 @@ grow_outbuf (obuf, needed) ...@@ -8902,11 +8978,10 @@ grow_outbuf (obuf, needed)
* Otherwise, compute the hash code. * Otherwise, compute the hash code.
*/ */
static HASHNODE * static HASHNODE *
install (name, len, type, ivalue, value, hash) install (name, len, type, value, hash)
U_CHAR *name; U_CHAR *name;
int len; int len;
enum node_type type; enum node_type type;
int ivalue;
char *value; char *value;
int hash; int hash;
{ {
...@@ -8935,10 +9010,7 @@ install (name, len, type, ivalue, value, hash) ...@@ -8935,10 +9010,7 @@ install (name, len, type, ivalue, value, hash)
hp->next->prev = hp; hp->next->prev = hp;
hp->type = type; hp->type = type;
hp->length = len; hp->length = len;
if (hp->type == T_CONST) hp->value.cpval = value;
hp->value.ival = ivalue;
else
hp->value.cpval = value;
hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
p = hp->name; p = hp->name;
q = name; q = name;
...@@ -9086,14 +9158,14 @@ dump_single_macro (hp, of) ...@@ -9086,14 +9158,14 @@ dump_single_macro (hp, of)
if (ap->nchars != 0) if (ap->nchars != 0)
concat = 0; concat = 0;
if (ap->stringify) if (ap->stringify)
fprintf (of, " #"); fprintf (of, ap->stringify == '#' ? " #" : " %:");
if (ap->raw_before && !concat) if (ap->raw_before && !concat)
fprintf (of, " ## "); fprintf (of, ap->raw_before == '#' ? " ## " : " %:%: ");
concat = 0; concat = 0;
} }
dump_arg_n (defn, ap->argno, of); dump_arg_n (defn, ap->argno, of);
if (!traditional && ap->raw_after) { if (!traditional && ap->raw_after) {
fprintf (of, " ## "); fprintf (of, ap->raw_after == '#' ? " ## " : " %:%: ");
concat = 1; concat = 1;
} }
} }
...@@ -9227,29 +9299,31 @@ initialize_builtins (inp, outp) ...@@ -9227,29 +9299,31 @@ initialize_builtins (inp, outp)
FILE_BUF *inp; FILE_BUF *inp;
FILE_BUF *outp; FILE_BUF *outp;
{ {
install ("__LINE__", -1, T_SPECLINE, 0, NULL_PTR, -1); install ("__LINE__", -1, T_SPECLINE, NULL_PTR, -1);
install ("__DATE__", -1, T_DATE, 0, NULL_PTR, -1); install ("__DATE__", -1, T_DATE, NULL_PTR, -1);
install ("__FILE__", -1, T_FILE, 0, NULL_PTR, -1); install ("__FILE__", -1, T_FILE, NULL_PTR, -1);
install ("__BASE_FILE__", -1, T_BASE_FILE, 0, NULL_PTR, -1); install ("__BASE_FILE__", -1, T_BASE_FILE, NULL_PTR, -1);
install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, NULL_PTR, -1); install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, NULL_PTR, -1);
install ("__VERSION__", -1, T_VERSION, 0, NULL_PTR, -1); install ("__VERSION__", -1, T_VERSION, NULL_PTR, -1);
#ifndef NO_BUILTIN_SIZE_TYPE #ifndef NO_BUILTIN_SIZE_TYPE
install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, NULL_PTR, -1); install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, NULL_PTR, -1);
#endif #endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE #ifndef NO_BUILTIN_PTRDIFF_TYPE
install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, NULL_PTR, -1); install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, NULL_PTR, -1);
#endif #endif
install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, NULL_PTR, -1); install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, NULL_PTR, -1);
install ("__USER_LABEL_PREFIX__",-1,T_USER_LABEL_PREFIX_TYPE,0,NULL_PTR, -1); install ("__USER_LABEL_PREFIX__",-1,T_USER_LABEL_PREFIX_TYPE, NULL_PTR, -1);
install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, NULL_PTR, -1); install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, NULL_PTR, -1);
install ("__TIME__", -1, T_TIME, 0, NULL_PTR, -1); install ("__TIME__", -1, T_TIME, NULL_PTR, -1);
if (!traditional) if (!traditional) {
install ("__STDC__", -1, T_CONST, STDC_VALUE, NULL_PTR, -1); install ("__STDC__", -1, T_CONST, "1", -1);
install ("__STDC_VERSION__", -1, T_CONST, "199409L", -1);
}
if (objc) if (objc)
install ("__OBJC__", -1, T_CONST, 1, NULL_PTR, -1); install ("__OBJC__", -1, T_CONST, "1", -1);
/* This is supplied using a -D by the compiler driver /* This is supplied using a -D by the compiler driver
so that it is present only when truly compiling with GNU C. */ so that it is present only when truly compiling with GNU C. */
/* install ("__GNUC__", -1, T_CONST, 2, NULL_PTR, -1); */ /* install ("__GNUC__", -1, T_CONST, "2", -1); */
if (debug_output) if (debug_output)
{ {
......
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