Commit 7682e7bc by Neil Booth Committed by Neil Booth

tradcif.y: Move lexptr to top of file.

        * tradcif.y: Move lexptr to top of file.  Add rule to handle
        assertions in conditional expressions.
        * tradcpp.c (parse_answer): Assertions do not need to go to
        end of line in conditional directives.
        (parse_assertion): Get first character of identifiers correct.
        (test_assertion): New function.
        * tradcpp.h (test_assertion): New prototype.

From-SVN: r38011
parent 23a535c4
2000-12-04 Neil Booth <neilb@earthling.net>
* tradcif.y: Move lexptr to top of file. Add rule to handle
assertions in conditional expressions.
* tradcpp.c (parse_answer): Assertions do not need to go to
end of line in conditional directives.
(parse_assertion): Get first character of identifiers correct.
(test_assertion): New function.
* tradcpp.h (test_assertion): New prototype.
2000-12-01 Rodney Brown <RodneyBrown@mynd.com> 2000-12-01 Rodney Brown <RodneyBrown@mynd.com>
* config.gcc: Fix typo for UnixWare 7. * config.gcc: Fix typo for UnixWare 7.
......
...@@ -36,6 +36,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ...@@ -36,6 +36,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
static int expression_value; static int expression_value;
static jmp_buf parse_return_error; static jmp_buf parse_return_error;
/* During parsing of a C expression, the pointer to the next
character is in this variable. */
static const char *lexptr;
%} %}
%union { %union {
...@@ -199,14 +204,11 @@ exp : exp '*' exp ...@@ -199,14 +204,11 @@ exp : exp '*' exp
| NAME | NAME
{ $$.value = 0; { $$.value = 0;
$$.unsignedp = 0; } $$.unsignedp = 0; }
| '#' { $$.value =
test_assertion ((unsigned char **) &lexptr); }
; ;
%% %%
/* During parsing of a C expression, the pointer to the next character
is in this variable. */
static const char *lexptr;
/* Take care of parsing a number (anything that starts with a digit). /* Take care of parsing a number (anything that starts with a digit).
Set yylval and return the token type; update lexptr. Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */ LEN is the number of characters in it. */
...@@ -389,6 +391,7 @@ yylex () ...@@ -389,6 +391,7 @@ yylex ()
case '{': case '{':
case '}': case '}':
case ',': case ',':
case '#':
lexptr++; lexptr++;
return c; return c;
......
...@@ -3057,11 +3057,14 @@ parse_answer (buf, limit, answerp, type) ...@@ -3057,11 +3057,14 @@ parse_answer (buf, limit, answerp, type)
buf++; buf++;
/* Parentheses are optional here. */ /* Parentheses are optional here. */
if (buf == limit && (type == T_IF || type == T_UNASSERT)) if (buf == limit && type == T_UNASSERT)
return 0; return 0;
if (buf == limit || *buf++ != '(') if (buf == limit || *buf++ != '(')
{ {
if (type == T_IF)
return 0;
error ("missing '(' after predicate"); error ("missing '(' after predicate");
return 1; return 1;
} }
...@@ -3118,8 +3121,12 @@ parse_assertion (buf, limit, answerp, type) ...@@ -3118,8 +3121,12 @@ parse_assertion (buf, limit, answerp, type)
unsigned int len; unsigned int len;
bp = symname; bp = symname;
while (bp < climit && is_idchar[*bp]) if (bp < climit && is_idstart[*bp])
bp++; {
do
bp++;
while (bp < climit && is_idchar[*bp]);
}
len = bp - symname; len = bp - symname;
*answerp = 0; *answerp = 0;
...@@ -3130,6 +3137,8 @@ parse_assertion (buf, limit, answerp, type) ...@@ -3130,6 +3137,8 @@ parse_assertion (buf, limit, answerp, type)
else else
error ("predicate must be an identifier"); error ("predicate must be an identifier");
} }
/* Unfortunately, because of the way we handle #if, we don't avoid
macro expansion in answers. This is not easy to fix. */
else if (parse_answer (bp, climit, answerp, type) == 0) else if (parse_answer (bp, climit, answerp, type) == 0)
{ {
unsigned char *sym = alloca (len + 1); unsigned char *sym = alloca (len + 1);
...@@ -3148,6 +3157,40 @@ parse_assertion (buf, limit, answerp, type) ...@@ -3148,6 +3157,40 @@ parse_assertion (buf, limit, answerp, type)
return result; return result;
} }
/* Test an assertion within a preprocessor conditional. Returns zero
on error or failure, one on success. */
int
test_assertion (pbuf)
unsigned char **pbuf; /* NUL-terminated. */
{
unsigned char *buf = *pbuf;
unsigned char *limit = buf + strlen ((char *) buf);
struct answer *answer;
HASHNODE *node;
int result = 0;
node = parse_assertion (buf, limit, &answer, T_IF);
if (node)
{
result = (node->type == T_ASSERT &&
(answer == 0 || *find_answer (node, answer) != 0));
/* Yuk. We update pbuf to point after the assertion test.
First, move past the identifier. */
if (is_space[*buf])
buf++;
while (is_idchar[*buf])
buf++;
/* If we have an answer, we need to move past the parentheses. */
if (answer)
while (*buf++ != ')')
;
*pbuf = buf;
}
return result;
}
/* Handle a #assert directive. */ /* Handle a #assert directive. */
static void static void
do_assert (buf, limit, op) do_assert (buf, limit, op)
......
...@@ -34,6 +34,7 @@ extern void fancy_abort PARAMS ((int, const char *)) ATTRIBUTE_NORETURN; ...@@ -34,6 +34,7 @@ extern void fancy_abort PARAMS ((int, const char *)) ATTRIBUTE_NORETURN;
extern struct hashnode *lookup PARAMS ((const unsigned char *, int, int)); extern struct hashnode *lookup PARAMS ((const unsigned char *, int, int));
extern int parse_c_expression PARAMS ((const char *)); /* in tradcif.y */ extern int parse_c_expression PARAMS ((const char *)); /* in tradcif.y */
extern int test_assertion PARAMS ((unsigned char **));
/* some external tables of character types */ /* some external tables of character types */
extern unsigned char is_idstart[], is_idchar[]; extern unsigned char is_idstart[], is_idchar[];
......
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