Commit 82c03907 by Ian Lance Taylor Committed by Ian Lance Taylor

godump.c (go_define): Improve lexing of macro expansion to only accept…

godump.c (go_define): Improve lexing of macro expansion to only accept expressions which match Go spec.

	* godump.c (go_define): Improve lexing of macro expansion to only
	accept expressions which match Go spec.

From-SVN: r169270
parent d4dba752
2011-01-25 Ian Lance Taylor <iant@google.com>
* godump.c (go_define): Improve lexing of macro expansion to only
accept expressions which match Go spec.
2011-01-26 Dave Korn <dave.korn.cygwin@gmail.com> 2011-01-26 Dave Korn <dave.korn.cygwin@gmail.com>
PR c++/43601 PR c++/43601
......
...@@ -79,6 +79,8 @@ go_define (unsigned int lineno, const char *buffer) ...@@ -79,6 +79,8 @@ go_define (unsigned int lineno, const char *buffer)
const char *name_end; const char *name_end;
char *out_buffer; char *out_buffer;
char *q; char *q;
bool saw_operand;
bool need_operand;
char *copy; char *copy;
hashval_t hashval; hashval_t hashval;
void **slot; void **slot;
...@@ -115,77 +117,252 @@ go_define (unsigned int lineno, const char *buffer) ...@@ -115,77 +117,252 @@ go_define (unsigned int lineno, const char *buffer)
initial underscore, and let the user undo this as needed. */ initial underscore, and let the user undo this as needed. */
out_buffer = XNEWVEC (char, strlen (p) * 2 + 1); out_buffer = XNEWVEC (char, strlen (p) * 2 + 1);
q = out_buffer; q = out_buffer;
saw_operand = false;
need_operand = false;
while (*p != '\0') while (*p != '\0')
{ {
if (ISALPHA (*p) || *p == '_') switch (*p)
{ {
const char *start; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
char *n; case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
start = p; case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
while (ISALNUM (*p) || *p == '_') case 'Y': case 'Z':
++p; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
n = XALLOCAVEC (char, p - start + 1); case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
memcpy (n, start, p - start); case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
n[p - start] = '\0'; case 's': case 't': case 'u': case 'v': case 'w': case 'x':
slot = htab_find_slot (macro_hash, n, NO_INSERT); case 'y': case 'z':
if (slot == NULL || *slot == NULL) case '_':
{ {
/* This is a reference to a name which was not defined /* The start of an identifier. Technically we should also
as a macro. */ worry about UTF-8 identifiers, but they are not a
fprintf (go_dump_file, "// unknowndefine %s\n", buffer); problem for practical uses of -fdump-go-spec so we
return; don't worry about them. */
} const char *start;
char *n;
start = p;
while (ISALNUM (*p) || *p == '_')
++p;
n = XALLOCAVEC (char, p - start + 1);
memcpy (n, start, p - start);
n[p - start] = '\0';
slot = htab_find_slot (macro_hash, n, NO_INSERT);
if (slot == NULL || *slot == NULL)
{
/* This is a reference to a name which was not defined
as a macro. */
goto unknown;
}
*q++ = '_'; *q++ = '_';
memcpy (q, start, p - start); memcpy (q, start, p - start);
q += p - start; q += p - start;
}
else if (ISDIGIT (*p) saw_operand = true;
|| (*p == '.' && ISDIGIT (p[1]))) need_operand = false;
{ }
const char *start; break;
bool is_hex;
case '.':
if (!ISDIGIT (p[1]))
goto unknown;
/* Fall through. */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
const char *start;
bool is_hex;
start = p;
is_hex = false;
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
{
p += 2;
is_hex = true;
}
while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
|| (is_hex
&& ((*p >= 'a' && *p <= 'f')
|| (*p >= 'A' && *p <= 'F'))))
++p;
memcpy (q, start, p - start);
q += p - start;
while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
|| *p == 'f' || *p == 'F'
|| *p == 'd' || *p == 'D')
{
/* Go doesn't use any of these trailing type
modifiers. */
++p;
}
/* We'll pick up the exponent, if any, as an
expression. */
start = p; saw_operand = true;
is_hex = false; need_operand = false;
if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) }
break;
case ' ': case '\t':
*q++ = *p++;
break;
case '(':
/* Always OK, not part of an operand, presumed to start an
operand. */
*q++ = *p++;
saw_operand = false;
need_operand = false;
break;
case ')':
/* OK if we don't need an operand, and presumed to indicate
an operand. */
if (need_operand)
goto unknown;
*q++ = *p++;
saw_operand = true;
break;
case '+': case '-':
/* Always OK, but not part of an operand. */
*q++ = *p++;
saw_operand = false;
break;
case '*': case '/': case '%': case '|': case '&': case '^':
/* Must be a binary operator. */
if (!saw_operand)
goto unknown;
*q++ = *p++;
saw_operand = false;
need_operand = true;
break;
case '=':
*q++ = *p++;
if (*p != '=')
goto unknown;
/* Must be a binary operator. */
if (!saw_operand)
goto unknown;
*q++ = *p++;
saw_operand = false;
need_operand = true;
break;
case '!':
*q++ = *p++;
if (*p == '=')
{ {
p += 2; /* Must be a binary operator. */
is_hex = true; if (!saw_operand)
goto unknown;
*q++ = *p++;
saw_operand = false;
need_operand = true;
} }
while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E' else
|| (is_hex
&& ((*p >= 'a' && *p <= 'f')
|| (*p >= 'A' && *p <= 'F'))))
++p;
memcpy (q, start, p - start);
q += p - start;
while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
|| *p == 'f' || *p == 'F'
|| *p == 'd' || *p == 'D')
{ {
/* Go doesn't use any of these trailing type /* Must be a unary operator. */
modifiers. */ if (saw_operand)
++p; goto unknown;
need_operand = true;
} }
} break;
else if (ISSPACE (*p)
|| *p == '+' || *p == '-' case '<': case '>':
|| *p == '*' || *p == '/' || *p == '%' /* Must be a binary operand, may be << or >> or <= or >=. */
|| *p == '|' || *p == '&' if (!saw_operand)
|| *p == '>' || *p == '<' goto unknown;
|| *p == '!' *q++ = *p++;
|| *p == '(' || *p == ')' if (*p == *(p - 1) || *p == '=')
|| *p == '"' || *p == '\'') *q++ = *p++;
*q++ = *p++; saw_operand = false;
else need_operand = true;
{ break;
/* Something we don't recognize. */
fprintf (go_dump_file, "// unknowndefine %s\n", buffer); case '~':
return; /* Must be a unary operand, must be translated for Go. */
if (saw_operand)
goto unknown;
*q++ = '^';
p++;
need_operand = true;
break;
case '"':
case '\'':
{
char quote = *p;
*q++ = *p++;
while (*p != quote)
{
int c;
if (*p == '\0')
goto unknown;
if (*p != '\\')
{
*q++ = *p++;
continue;
}
*q++ = *p++;
switch (*p)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = 0;
while (*p >= '0' && *p <= '7')
{
*q++ = *p++;
++c;
}
/* Go octal characters are always 3
digits. */
if (c != 3)
goto unknown;
break;
case 'x':
*q++ = *p++;
c = 0;
while (ISXDIGIT (*p))
{
*q++ = *p++;
++c;
}
/* Go hex characters are always 2 digits. */
if (c != 2)
goto unknown;
break;
case 'a': case 'b': case 'f': case 'n': case 'r':
case 't': case 'v': case '\\': case '\'': case '"':
*q++ = *p++;
break;
default:
goto unknown;
}
}
*q++ = *p++;
break;
}
default:
goto unknown;
} }
} }
if (need_operand)
goto unknown;
*q = '\0'; *q = '\0';
slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT); slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
...@@ -194,6 +371,12 @@ go_define (unsigned int lineno, const char *buffer) ...@@ -194,6 +371,12 @@ go_define (unsigned int lineno, const char *buffer)
fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer); fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
XDELETEVEC (out_buffer); XDELETEVEC (out_buffer);
return;
unknown:
fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
XDELETEVEC (out_buffer);
XDELETEVEC (copy);
} }
/* A macro undef. */ /* A macro undef. */
......
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