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
This commit is contained in:
parent
23a535c4ff
commit
7682e7bc2e
@ -1,3 +1,13 @@
|
||||
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>
|
||||
|
||||
* config.gcc: Fix typo for UnixWare 7.
|
||||
|
@ -36,6 +36,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
static int expression_value;
|
||||
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 {
|
||||
@ -199,14 +204,11 @@ exp : exp '*' exp
|
||||
| NAME
|
||||
{ $$.value = 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).
|
||||
Set yylval and return the token type; update lexptr.
|
||||
LEN is the number of characters in it. */
|
||||
@ -389,6 +391,7 @@ yylex ()
|
||||
case '{':
|
||||
case '}':
|
||||
case ',':
|
||||
case '#':
|
||||
lexptr++;
|
||||
return c;
|
||||
|
||||
|
@ -3057,11 +3057,14 @@ parse_answer (buf, limit, answerp, type)
|
||||
buf++;
|
||||
|
||||
/* Parentheses are optional here. */
|
||||
if (buf == limit && (type == T_IF || type == T_UNASSERT))
|
||||
if (buf == limit && type == T_UNASSERT)
|
||||
return 0;
|
||||
|
||||
if (buf == limit || *buf++ != '(')
|
||||
{
|
||||
if (type == T_IF)
|
||||
return 0;
|
||||
|
||||
error ("missing '(' after predicate");
|
||||
return 1;
|
||||
}
|
||||
@ -3118,8 +3121,12 @@ parse_assertion (buf, limit, answerp, type)
|
||||
unsigned int len;
|
||||
|
||||
bp = symname;
|
||||
while (bp < climit && is_idchar[*bp])
|
||||
bp++;
|
||||
if (bp < climit && is_idstart[*bp])
|
||||
{
|
||||
do
|
||||
bp++;
|
||||
while (bp < climit && is_idchar[*bp]);
|
||||
}
|
||||
len = bp - symname;
|
||||
|
||||
*answerp = 0;
|
||||
@ -3130,6 +3137,8 @@ parse_assertion (buf, limit, answerp, type)
|
||||
else
|
||||
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)
|
||||
{
|
||||
unsigned char *sym = alloca (len + 1);
|
||||
@ -3148,6 +3157,40 @@ parse_assertion (buf, limit, answerp, type)
|
||||
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. */
|
||||
static void
|
||||
do_assert (buf, limit, op)
|
||||
|
@ -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 int parse_c_expression PARAMS ((const char *)); /* in tradcif.y */
|
||||
extern int test_assertion PARAMS ((unsigned char **));
|
||||
|
||||
/* some external tables of character types */
|
||||
extern unsigned char is_idstart[], is_idchar[];
|
||||
|
Loading…
x
Reference in New Issue
Block a user