/* Parse C expressions for CCCP.
- Copyright (C) 1987 Free Software Foundation.
+ Copyright (C) 1987, 2000, 2001 Free Software Foundation.
+ Adapted from expread.y of GDB by Paul Rubin, July 1986.
+ Adapted to ANSI C, Richard Stallman, Jan 1987
+ Dusted off, polished, and adapted for use as traditional
+ preprocessor only, Zack Weinberg, Jul 2000
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
-Free Software Foundation; either version 1, or (at your option) any
+Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
-
- Adapted from expread.y of GDB by Paul Rubin, July 1986.
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Parse a C expression from text in a string */
%{
#include "config.h"
#include "system.h"
+#include "intl.h"
+#include "tradcpp.h"
#include <setjmp.h>
- int yylex PARAMS ((void));
- void yyerror PARAMS ((const char *msgid));
- extern void error PARAMS ((const char *msgid, ...));
- extern void warning PARAMS ((const char *msgid, ...));
- extern struct hashnode *lookup PARAMS ((const unsigned char *, int, int));
+ static int yylex PARAMS ((void));
+ static void yyerror PARAMS ((const char *msgid)) ATTRIBUTE_NORETURN;
- int parse_number PARAMS ((int));
- int parse_escape PARAMS ((char **));
- int parse_c_expression PARAMS ((char *));
+ static int parse_number PARAMS ((int));
+ static int parse_escape PARAMS ((const char **));
- int expression_value;
+ static int expression_value;
static jmp_buf parse_return_error;
- /* some external tables of character types */
- extern unsigned char is_idstart[], is_idchar[];
+ /* During parsing of a C expression, the pointer to the next
+ character is in this variable. */
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
+ static const char *lexptr;
%}
%union {
| NAME
{ $$.value = 0;
$$.unsignedp = 0; }
+ | '#' { $$.value =
+ test_assertion ((unsigned char **) &lexptr); }
;
%%
\f
-/* During parsing of a C expression, the pointer to the next character
- is in this variable. */
-
-static char *lexptr;
-
/* Take care of parsing a number (anything that starts with a digit).
Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */
/* maybe needs to actually deal with floating point numbers */
-int
+static int
parse_number (olen)
int olen;
{
- register char *p = lexptr;
- register long n = 0;
- register int c;
- register int base = 10;
- register int len = olen;
+ const char *p = lexptr;
+ long n = 0;
+ int c;
+ int base = 10;
+ int len = olen;
for (c = 0; c < len; c++)
if (p[c] == '.') {
return ERROR;
}
+ /* Traditionally, all numbers are signed. However, we make it
+ unsigned if requested with a suffix. */
yylval.integer.unsignedp = 0;
if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
while (len > 0) {
c = *p++;
len--;
- if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
-
- if (c >= '0' && c <= '9') {
- n *= base;
- n += c - '0';
- } else if (base == 16 && c >= 'a' && c <= 'f') {
- n *= base;
- n += c - 'a' + 10;
+ if (ISUPPER (c))
+ c = TOLOWER (c);
+
+ if (ISDIGIT (c)
+ || (base == 16 && ISXDIGIT (c))) {
+ n = (n * base) + hex_value (c);
} else {
/* `l' means long, and `u' means unsigned. */
while (1) {
return ERROR;
}
- /* If too big to be signed, consider it unsigned. */
- if (n < 0)
- yylval.integer.unsignedp = 1;
-
lexptr = p;
yylval.integer.value = n;
return INT;
}
struct token {
- const char *operator;
- int token;
+ const char *const operator;
+ const int token;
};
#ifndef NULL
#define NULL 0
#endif
-static struct token tokentab2[] = {
+static const struct token tokentab2[] = {
{"&&", AND},
{"||", OR},
{"<<", LSH},
/* Read one token, getting characters through lexptr. */
-int
+static int
yylex ()
{
- register int c;
- register int namelen;
- register char *tokstart;
- register struct token *toktab;
+ int c;
+ int namelen;
+ const char *tokstart;
+ const struct token *toktab;
retry:
case '{':
case '}':
case ',':
+ case '#':
lexptr++;
return c;
yyerror ("double quoted strings not allowed in #if expressions");
return ERROR;
}
- if (c >= '0' && c <= '9') {
+ if (ISDIGIT (c)) {
/* It's a number */
for (namelen = 0;
- c = tokstart[namelen], is_idchar[c] || c == '.';
+ c = tokstart[namelen], is_idchar (c) || c == '.';
namelen++)
;
return parse_number (namelen);
}
- if (!is_idstart[c]) {
+ if (!is_idstart (c)) {
yyerror ("Invalid token in expression");
return ERROR;
}
/* It is a name. See how long it is. */
for (namelen = 0;
- is_idchar[(int)(unsigned char)tokstart[namelen]];
+ is_idchar (tokstart[namelen]);
namelen++)
;
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
-int
+static int
parse_escape (string_ptr)
- char **string_ptr;
+ const char **string_ptr;
{
- register int c = *(*string_ptr)++;
+ int c = *(*string_ptr)++;
switch (c)
{
case 'a':
case '6':
case '7':
{
- register int i = c - '0';
- register int count = 0;
+ int i = c - '0';
+ int count = 0;
while (++count < 3)
{
c = *(*string_ptr)++;
}
case 'x':
{
- register int i = 0;
+ int i = 0;
for (;;)
{
c = *(*string_ptr)++;
- if (c >= '0' && c <= '9')
- i = (i << 4) + c - '0';
- else if (c >= 'a' && c <= 'f')
- i = (i << 4) + c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- i = (i << 4) + c - 'A' + 10;
+ if (hex_p (c))
+ i = (i << 4) + hex_value (c);
else
{
(*string_ptr)--;
}
}
-void
-yyerror (s)
- const char *s;
+static void
+yyerror (msgid)
+ const char *msgid;
{
- error (s);
+ error ("%s", _(msgid));
longjmp (parse_return_error, 1);
}
\f
int
parse_c_expression (string)
- char *string;
+ const char *string;
{
lexptr = string;