diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-06-03 00:25:56 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 21:02:00 -0700 |
| commit | 8d180a68d6c68182e532964e67e49503ca668257 (patch) | |
| tree | 206380af8fbfe5c341bdd95a68ab0bc908255bb3 /pre-process.c | |
| parent | a34e893c4eaaf80ca243d6c73c7be4130f96f9ae (diff) | |
| download | sparse-dev-8d180a68d6c68182e532964e67e49503ca668257.tar.gz | |
This should largely fix token pasting.
It's not perfect now either, but it makes a hell of a lot more
sense now, and gets all the kernel cases I've tested right. Which
is actually saying quite a lot, since the kernel uses things that
are arguably not standard (the token fragments it pastes are not
valid tokens on their own, and I think that may be borderline in
ANSI - who knows).
It still doesn't do the _really_ strange cases, ie trying to
paste
a ## 0.e10
and expecting that to become "a0" "." "e10" is just not going
to happen. I think that's undefined behaviour anyway.
Diffstat (limited to 'pre-process.c')
| -rw-r--r-- | pre-process.c | 119 |
1 files changed, 70 insertions, 49 deletions
diff --git a/pre-process.c b/pre-process.c index 1f2fc937..c9708c68 100644 --- a/pre-process.c +++ b/pre-process.c @@ -347,20 +347,28 @@ static void expand_arguments(struct token *parent, * Possibly valid combinations: * - anything + 'empty_arg_token' is empty. * - ident + ident - combine (==ident) + * a1 ## bb = 'a1bb' * - ident + number - combine (==ident) + * a ## 0x5 = 'a0x5' * - number + number - combine (==number) + * 12 ## 12 = '1212' * - number + ident - combine (==number) + * 0x ## aaa = '0xaaa' + * - number + FP - combine (==FP or number) + * 0x ## '0e11' = '0x0e11' = number + * 1 ## 0.123 = '10.123' = FP) + * - ident + FP - combine (and split?) + * a ## 0e11 = 'a0e11', but + * a ## 0.e1 should be 'a0' '.' 'e1') * - string + string - leave as is, C will combine them anyway - * others cause an error and leave the two tokens as separate tokens. + * others cause an error and leave the tokens as separate tokens. */ -static struct token *hashhash(struct token *head, struct token *first, struct token *second) +static struct token *hashhash(struct token *head, struct token *first) { + struct token *token; static char buffer[512], *p; struct token *newtoken; - static const char *src; - int len; - - first->next = second; + int i = 2; /* * Special case for gcc 'x ## arg' semantics: if 'arg' is empty @@ -368,55 +376,71 @@ static struct token *hashhash(struct token *head, struct token *first, struct to * * See expand_one_arg. */ - if (token_type(second) == TOKEN_EOF) { - head->next = second->next; - return head; - } + if (token_type(first->next) == TOKEN_EOF) + return first->next->next; p = buffer; - switch (token_type(first)) { - case TOKEN_INTEGER: - len = strlen(first->integer); - src = first->integer; - break; - case TOKEN_IDENT: - len = first->ident->len; - src = first->ident->name; - break; - default: - return second; - } - memcpy(p, src, len); - p += len; + token = first; + do { + static const char *src; + int len; - switch (token_type(second)) { - case TOKEN_INTEGER: - len = strlen(second->integer); - src = second->integer; - break; - case TOKEN_IDENT: - len = second->ident->len; - src = second->ident->name; - break; - default: - return second; - } - memcpy(p, src, len); - p += len; + switch (token_type(token)) { + case TOKEN_INTEGER: + src = token->integer; + len = strlen(src); + switch (*src) { + case 'o': case 'x': + *p++ = '0'; + len--; + src++; + } + break; + case TOKEN_IDENT: + len = token->ident->len; + src = token->ident->name; + break; + case TOKEN_FP: + src = token->fp; + len = strlen(src); + break; + default: + goto out; + } + memcpy(p, src, len); + p += len; + token = token->next; + } while (--i > 0 || !(token->pos.whitespace | token->pos.newline)); + +out: *p++ = 0; + if (!*buffer) + return token; newtoken = alloc_token(&first->pos); - head->next = newtoken; + newtoken->next = token; + token_type(newtoken) = token_type(first); switch (token_type(newtoken)) { case TOKEN_IDENT: newtoken->ident = built_in_ident(buffer); break; - case TOKEN_INTEGER: + case TOKEN_INTEGER: { + if (buffer[0] == '0') { + switch (buffer[1]) { + case 'x': case 'X': + buffer[0] = 'x'; + break; + case '0' ... '7': + buffer[0] = 'o'; + break; + } + } newtoken->integer = __alloc_bytes(p - buffer); memcpy(newtoken->integer, buffer, p - buffer); break; } + } return newtoken; } @@ -434,16 +458,13 @@ static void retokenize(struct token *head) break; if (match_op(nextnext, SPECIAL_HASHHASH)) { - struct token *newtoken = hashhash(head, next, nextnextnext); - - next = newtoken; - nextnext = nextnextnext->next; + next->next = nextnextnext; + next = hashhash(head, next); + head->next = next; + nextnext = next->next; nextnextnext = nextnext->next; - - newtoken->next = nextnext; - if (!eof_token(nextnext)) - continue; - break; + continue; + } head = next; |
