| Index: gcc/libcpp/lex.c
|
| diff --git a/gcc/libcpp/lex.c b/gcc/libcpp/lex.c
|
| index e08c5bd81436c5fd5e6fd04d57de308b243c9842..f29998225340954e0affb7f59da3c1d66ea51bd9 100644
|
| --- a/gcc/libcpp/lex.c
|
| +++ b/gcc/libcpp/lex.c
|
| @@ -76,7 +76,7 @@ cpp_ideq (const cpp_token *token, const char *string)
|
| if (token->type != CPP_NAME)
|
| return 0;
|
|
|
| - return !ustrcmp (NODE_NAME (token->val.node), (const uchar *) string);
|
| + return !ustrcmp (NODE_NAME (token->val.node.node), (const uchar *) string);
|
| }
|
|
|
| /* Record a note TYPE at byte POS into the current cleaned logical
|
| @@ -314,6 +314,8 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment)
|
| }
|
| }
|
| }
|
| + else if (note->type == 0)
|
| + /* Already processed in lex_raw_string. */;
|
| else
|
| abort ();
|
| }
|
| @@ -540,6 +542,12 @@ lex_identifier_intern (cpp_reader *pfile, const uchar *base)
|
| cpp_error (pfile, CPP_DL_PEDWARN,
|
| "__VA_ARGS__ can only appear in the expansion"
|
| " of a C99 variadic macro");
|
| +
|
| + /* For -Wc++-compat, warn about use of C++ named operators. */
|
| + if (result->flags & NODE_WARN_OPERATOR)
|
| + cpp_error (pfile, CPP_DL_WARNING,
|
| + "identifier \"%s\" is a special operator name in C++",
|
| + NODE_NAME (result));
|
| }
|
|
|
| return result;
|
| @@ -611,6 +619,12 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
| cpp_error (pfile, CPP_DL_PEDWARN,
|
| "__VA_ARGS__ can only appear in the expansion"
|
| " of a C99 variadic macro");
|
| +
|
| + /* For -Wc++-compat, warn about use of C++ named operators. */
|
| + if (result->flags & NODE_WARN_OPERATOR)
|
| + cpp_error (pfile, CPP_DL_WARNING,
|
| + "identifier \"%s\" is a special operator name in C++",
|
| + NODE_NAME (result));
|
| }
|
|
|
| return result;
|
| @@ -662,12 +676,291 @@ create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base,
|
| token->val.str.text = dest;
|
| }
|
|
|
| +/* Subroutine of lex_raw_string: Append LEN chars from BASE to the buffer
|
| + sequence from *FIRST_BUFF_P to LAST_BUFF_P. */
|
| +
|
| +static void
|
| +bufring_append (cpp_reader *pfile, const uchar *base, size_t len,
|
| + _cpp_buff **first_buff_p, _cpp_buff **last_buff_p)
|
| +{
|
| + _cpp_buff *first_buff = *first_buff_p;
|
| + _cpp_buff *last_buff = *last_buff_p;
|
| +
|
| + if (first_buff == NULL)
|
| + first_buff = last_buff = _cpp_get_buff (pfile, len);
|
| + else if (len > BUFF_ROOM (last_buff))
|
| + {
|
| + size_t room = BUFF_ROOM (last_buff);
|
| + memcpy (BUFF_FRONT (last_buff), base, room);
|
| + BUFF_FRONT (last_buff) += room;
|
| + base += room;
|
| + len -= room;
|
| + last_buff = _cpp_append_extend_buff (pfile, last_buff, len);
|
| + }
|
| +
|
| + memcpy (BUFF_FRONT (last_buff), base, len);
|
| + BUFF_FRONT (last_buff) += len;
|
| +
|
| + *first_buff_p = first_buff;
|
| + *last_buff_p = last_buff;
|
| +}
|
| +
|
| +/* Lexes a raw string. The stored string contains the spelling, including
|
| + double quotes, delimiter string, '(' and ')', any leading
|
| + 'L', 'u', 'U' or 'u8' and 'R' modifier. It returns the type of the
|
| + literal, or CPP_OTHER if it was not properly terminated.
|
| +
|
| + The spelling is NUL-terminated, but it is not guaranteed that this
|
| + is the first NUL since embedded NULs are preserved. */
|
| +
|
| +static void
|
| +lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
|
| + const uchar *cur)
|
| +{
|
| + source_location saw_NUL = 0;
|
| + const uchar *raw_prefix;
|
| + unsigned int raw_prefix_len = 0;
|
| + enum cpp_ttype type;
|
| + size_t total_len = 0;
|
| + _cpp_buff *first_buff = NULL, *last_buff = NULL;
|
| + _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note];
|
| +
|
| + type = (*base == 'L' ? CPP_WSTRING :
|
| + *base == 'U' ? CPP_STRING32 :
|
| + *base == 'u' ? (base[1] == '8' ? CPP_UTF8STRING : CPP_STRING16)
|
| + : CPP_STRING);
|
| +
|
| + raw_prefix = cur + 1;
|
| + while (raw_prefix_len < 16)
|
| + {
|
| + switch (raw_prefix[raw_prefix_len])
|
| + {
|
| + case ' ': case '(': case ')': case '\\': case '\t':
|
| + case '\v': case '\f': case '\n': default:
|
| + break;
|
| + /* Basic source charset except the above chars. */
|
| + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
| + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
|
| + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
|
| + case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
| + case 'y': case 'z':
|
| + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
| + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
|
| + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
| + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
| + case 'Y': case 'Z':
|
| + case '0': case '1': case '2': case '3': case '4': case '5':
|
| + case '6': case '7': case '8': case '9':
|
| + case '_': case '{': case '}': case '#': case '[': case ']':
|
| + case '<': case '>': case '%': case ':': case ';': case '.':
|
| + case '?': case '*': case '+': case '-': case '/': case '^':
|
| + case '&': case '|': case '~': case '!': case '=': case ',':
|
| + case '"': case '\'':
|
| + raw_prefix_len++;
|
| + continue;
|
| + }
|
| + break;
|
| + }
|
| +
|
| + if (raw_prefix[raw_prefix_len] != '(')
|
| + {
|
| + int col = CPP_BUF_COLUMN (pfile->buffer, raw_prefix + raw_prefix_len)
|
| + + 1;
|
| + if (raw_prefix_len == 16)
|
| + cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, col,
|
| + "raw string delimiter longer than 16 characters");
|
| + else
|
| + cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, col,
|
| + "invalid character '%c' in raw string delimiter",
|
| + (int) raw_prefix[raw_prefix_len]);
|
| + pfile->buffer->cur = raw_prefix - 1;
|
| + create_literal (pfile, token, base, raw_prefix - 1 - base, CPP_OTHER);
|
| + return;
|
| + }
|
| +
|
| + cur = raw_prefix + raw_prefix_len + 1;
|
| + for (;;)
|
| + {
|
| +#define BUF_APPEND(STR,LEN) \
|
| + do { \
|
| + bufring_append (pfile, (const uchar *)(STR), (LEN), \
|
| + &first_buff, &last_buff); \
|
| + total_len += (LEN); \
|
| + } while (0);
|
| +
|
| + cppchar_t c;
|
| +
|
| + /* If we previously performed any trigraph or line splicing
|
| + transformations, undo them within the body of the raw string. */
|
| + while (note->pos < cur)
|
| + ++note;
|
| + for (; note->pos == cur; ++note)
|
| + {
|
| + switch (note->type)
|
| + {
|
| + case '\\':
|
| + case ' ':
|
| + /* Restore backslash followed by newline. */
|
| + BUF_APPEND (base, cur - base);
|
| + base = cur;
|
| + BUF_APPEND ("\\", 1);
|
| + after_backslash:
|
| + if (note->type == ' ')
|
| + {
|
| + /* GNU backslash whitespace newline extension. FIXME
|
| + could be any sequence of non-vertical space. When we
|
| + can properly restore any such sequence, we should mark
|
| + this note as handled so _cpp_process_line_notes
|
| + doesn't warn. */
|
| + BUF_APPEND (" ", 1);
|
| + }
|
| +
|
| + BUF_APPEND ("\n", 1);
|
| + break;
|
| +
|
| + case 0:
|
| + /* Already handled. */
|
| + break;
|
| +
|
| + default:
|
| + if (_cpp_trigraph_map[note->type])
|
| + {
|
| + /* Don't warn about this trigraph in
|
| + _cpp_process_line_notes, since trigraphs show up as
|
| + trigraphs in raw strings. */
|
| + uchar type = note->type;
|
| + note->type = 0;
|
| +
|
| + if (!CPP_OPTION (pfile, trigraphs))
|
| + /* If we didn't convert the trigraph in the first
|
| + place, don't do anything now either. */
|
| + break;
|
| +
|
| + BUF_APPEND (base, cur - base);
|
| + base = cur;
|
| + BUF_APPEND ("??", 2);
|
| +
|
| + /* ??/ followed by newline gets two line notes, one for
|
| + the trigraph and one for the backslash/newline. */
|
| + if (type == '/' && note[1].pos == cur)
|
| + {
|
| + if (note[1].type != '\\'
|
| + && note[1].type != ' ')
|
| + abort ();
|
| + BUF_APPEND ("/", 1);
|
| + ++note;
|
| + goto after_backslash;
|
| + }
|
| + /* The ) from ??) could be part of the suffix. */
|
| + else if (type == ')'
|
| + && strncmp ((const char *) cur+1,
|
| + (const char *) raw_prefix,
|
| + raw_prefix_len) == 0
|
| + && cur[raw_prefix_len+1] == '"')
|
| + {
|
| + cur += raw_prefix_len+2;
|
| + goto break_outer_loop;
|
| + }
|
| + else
|
| + {
|
| + /* Skip the replacement character. */
|
| + base = ++cur;
|
| + BUF_APPEND (&type, 1);
|
| + }
|
| + }
|
| + else
|
| + abort ();
|
| + break;
|
| + }
|
| + }
|
| + c = *cur++;
|
| +
|
| + if (c == ')'
|
| + && strncmp ((const char *) cur, (const char *) raw_prefix,
|
| + raw_prefix_len) == 0
|
| + && cur[raw_prefix_len] == '"')
|
| + {
|
| + cur += raw_prefix_len + 1;
|
| + break;
|
| + }
|
| + else if (c == '\n')
|
| + {
|
| + if (pfile->state.in_directive
|
| + || pfile->state.parsing_args
|
| + || pfile->state.in_deferred_pragma)
|
| + {
|
| + cur--;
|
| + type = CPP_OTHER;
|
| + cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, 0,
|
| + "unterminated raw string");
|
| + break;
|
| + }
|
| +
|
| + BUF_APPEND (base, cur - base);
|
| +
|
| + if (pfile->buffer->cur < pfile->buffer->rlimit)
|
| + CPP_INCREMENT_LINE (pfile, 0);
|
| + pfile->buffer->need_line = true;
|
| +
|
| + pfile->buffer->cur = cur-1;
|
| + _cpp_process_line_notes (pfile, false);
|
| + if (!_cpp_get_fresh_line (pfile))
|
| + {
|
| + source_location src_loc = token->src_loc;
|
| + token->type = CPP_EOF;
|
| + /* Tell the compiler the line number of the EOF token. */
|
| + token->src_loc = pfile->line_table->highest_line;
|
| + token->flags = BOL;
|
| + if (first_buff != NULL)
|
| + _cpp_release_buff (pfile, first_buff);
|
| + cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
|
| + "unterminated raw string");
|
| + return;
|
| + }
|
| +
|
| + cur = base = pfile->buffer->cur;
|
| + note = &pfile->buffer->notes[pfile->buffer->cur_note];
|
| + }
|
| + else if (c == '\0' && !saw_NUL)
|
| + LINEMAP_POSITION_FOR_COLUMN (saw_NUL, pfile->line_table,
|
| + CPP_BUF_COLUMN (pfile->buffer, cur));
|
| + }
|
| + break_outer_loop:
|
| +
|
| + if (saw_NUL && !pfile->state.skipping)
|
| + cpp_error_with_line (pfile, CPP_DL_WARNING, saw_NUL, 0,
|
| + "null character(s) preserved in literal");
|
| +
|
| + pfile->buffer->cur = cur;
|
| + if (first_buff == NULL)
|
| + create_literal (pfile, token, base, cur - base, type);
|
| + else
|
| + {
|
| + uchar *dest = _cpp_unaligned_alloc (pfile, total_len + (cur - base) + 1);
|
| +
|
| + token->type = type;
|
| + token->val.str.len = total_len + (cur - base);
|
| + token->val.str.text = dest;
|
| + last_buff = first_buff;
|
| + while (last_buff != NULL)
|
| + {
|
| + memcpy (dest, last_buff->base,
|
| + BUFF_FRONT (last_buff) - last_buff->base);
|
| + dest += BUFF_FRONT (last_buff) - last_buff->base;
|
| + last_buff = last_buff->next;
|
| + }
|
| + _cpp_release_buff (pfile, first_buff);
|
| + memcpy (dest, base, cur - base);
|
| + dest[cur - base] = '\0';
|
| + }
|
| +}
|
| +
|
| /* Lexes a string, character constant, or angle-bracketed header file
|
| name. The stored string contains the spelling, including opening
|
| - quote and leading any leading 'L', 'u' or 'U'. It returns the type
|
| - of the literal, or CPP_OTHER if it was not properly terminated, or
|
| - CPP_LESS for an unterminated header name which must be relexed as
|
| - normal tokens.
|
| + quote and any leading 'L', 'u', 'U' or 'u8' and optional
|
| + 'R' modifier. It returns the type of the literal, or CPP_OTHER
|
| + if it was not properly terminated, or CPP_LESS for an unterminated
|
| + header name which must be relexed as normal tokens.
|
|
|
| The spelling is NUL-terminated, but it is not guaranteed that this
|
| is the first NUL since embedded NULs are preserved. */
|
| @@ -681,12 +974,24 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
|
|
| cur = base;
|
| terminator = *cur++;
|
| - if (terminator == 'L' || terminator == 'u' || terminator == 'U')
|
| + if (terminator == 'L' || terminator == 'U')
|
| terminator = *cur++;
|
| - if (terminator == '\"')
|
| + else if (terminator == 'u')
|
| + {
|
| + terminator = *cur++;
|
| + if (terminator == '8')
|
| + terminator = *cur++;
|
| + }
|
| + if (terminator == 'R')
|
| + {
|
| + lex_raw_string (pfile, token, base, cur);
|
| + return;
|
| + }
|
| + if (terminator == '"')
|
| type = (*base == 'L' ? CPP_WSTRING :
|
| *base == 'U' ? CPP_STRING32 :
|
| - *base == 'u' ? CPP_STRING16 : CPP_STRING);
|
| + *base == 'u' ? (base[1] == '8' ? CPP_UTF8STRING : CPP_STRING16)
|
| + : CPP_STRING);
|
| else if (terminator == '\'')
|
| type = (*base == 'L' ? CPP_WCHAR :
|
| *base == 'U' ? CPP_CHAR32 :
|
| @@ -1146,10 +1451,21 @@ _cpp_lex_direct (cpp_reader *pfile)
|
| case 'L':
|
| case 'u':
|
| case 'U':
|
| - /* 'L', 'u' or 'U' may introduce wide characters or strings. */
|
| + case 'R':
|
| + /* 'L', 'u', 'U', 'u8' or 'R' may introduce wide characters,
|
| + wide strings or raw strings. */
|
| if (c == 'L' || CPP_OPTION (pfile, uliterals))
|
| {
|
| - if (*buffer->cur == '\'' || *buffer->cur == '"')
|
| + if ((*buffer->cur == '\'' && c != 'R')
|
| + || *buffer->cur == '"'
|
| + || (*buffer->cur == 'R'
|
| + && c != 'R'
|
| + && buffer->cur[1] == '"'
|
| + && CPP_OPTION (pfile, uliterals))
|
| + || (*buffer->cur == '8'
|
| + && c == 'u'
|
| + && (buffer->cur[1] == '"'
|
| + || (buffer->cur[1] == 'R' && buffer->cur[2] == '"'))))
|
| {
|
| lex_string (pfile, result, buffer->cur - 1);
|
| break;
|
| @@ -1165,22 +1481,22 @@ _cpp_lex_direct (cpp_reader *pfile)
|
| case 'y': case 'z':
|
| case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
| case 'G': case 'H': case 'I': case 'J': case 'K':
|
| - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
| + case 'M': case 'N': case 'O': case 'P': case 'Q':
|
| case 'S': case 'T': case 'V': case 'W': case 'X':
|
| case 'Y': case 'Z':
|
| result->type = CPP_NAME;
|
| {
|
| struct normalize_state nst = INITIAL_NORMALIZE_STATE;
|
| - result->val.node = lex_identifier (pfile, buffer->cur - 1, false,
|
| - &nst);
|
| + result->val.node.node = lex_identifier (pfile, buffer->cur - 1, false,
|
| + &nst);
|
| warn_about_normalization (pfile, result, &nst);
|
| }
|
|
|
| /* Convert named operators to their proper types. */
|
| - if (result->val.node->flags & NODE_OPERATOR)
|
| + if (result->val.node.node->flags & NODE_OPERATOR)
|
| {
|
| result->flags |= NAMED_OP;
|
| - result->type = (enum cpp_ttype) result->val.node->directive_index;
|
| + result->type = (enum cpp_ttype) result->val.node.node->directive_index;
|
| }
|
| break;
|
|
|
| @@ -1295,7 +1611,7 @@ _cpp_lex_direct (cpp_reader *pfile)
|
| result->flags |= DIGRAPH;
|
| result->type = CPP_HASH;
|
| if (*buffer->cur == '%' && buffer->cur[1] == ':')
|
| - buffer->cur += 2, result->type = CPP_PASTE;
|
| + buffer->cur += 2, result->type = CPP_PASTE, result->val.token_no = 0;
|
| }
|
| else if (*buffer->cur == '>')
|
| {
|
| @@ -1376,7 +1692,7 @@ _cpp_lex_direct (cpp_reader *pfile)
|
| case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break;
|
| case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break;
|
| case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break;
|
| - case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break;
|
| + case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); result->val.token_no = 0; break;
|
|
|
| case '?': result->type = CPP_QUERY; break;
|
| case '~': result->type = CPP_COMPL; break;
|
| @@ -1401,7 +1717,7 @@ _cpp_lex_direct (cpp_reader *pfile)
|
| if (forms_identifier_p (pfile, true, &nst))
|
| {
|
| result->type = CPP_NAME;
|
| - result->val.node = lex_identifier (pfile, base, true, &nst);
|
| + result->val.node.node = lex_identifier (pfile, base, true, &nst);
|
| warn_about_normalization (pfile, result, &nst);
|
| break;
|
| }
|
| @@ -1427,7 +1743,7 @@ cpp_token_len (const cpp_token *token)
|
| {
|
| default: len = 6; break;
|
| case SPELL_LITERAL: len = token->val.str.len; break;
|
| - case SPELL_IDENT: len = NODE_LEN (token->val.node) * 10; break;
|
| + case SPELL_IDENT: len = NODE_LEN (token->val.node.node) * 10; break;
|
| }
|
|
|
| return len;
|
| @@ -1467,6 +1783,13 @@ utf8_to_ucn (unsigned char *buffer, const unsigned char *name)
|
| return ucn_len;
|
| }
|
|
|
| +/* Given a token TYPE corresponding to a digraph, return a pointer to
|
| + the spelling of the digraph. */
|
| +static const unsigned char *
|
| +cpp_digraph2name (enum cpp_ttype type)
|
| +{
|
| + return digraph_spellings[(int) type - (int) CPP_FIRST_DIGRAPH];
|
| +}
|
|
|
| /* Write the spelling of a token TOKEN to BUFFER. The buffer must
|
| already contain the enough space to hold the token's spelling.
|
| @@ -1486,8 +1809,7 @@ cpp_spell_token (cpp_reader *pfile, const cpp_token *token,
|
| unsigned char c;
|
|
|
| if (token->flags & DIGRAPH)
|
| - spelling
|
| - = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH];
|
| + spelling = cpp_digraph2name (token->type);
|
| else if (token->flags & NAMED_OP)
|
| goto spell_ident;
|
| else
|
| @@ -1502,23 +1824,23 @@ cpp_spell_token (cpp_reader *pfile, const cpp_token *token,
|
| case SPELL_IDENT:
|
| if (forstring)
|
| {
|
| - memcpy (buffer, NODE_NAME (token->val.node),
|
| - NODE_LEN (token->val.node));
|
| - buffer += NODE_LEN (token->val.node);
|
| + memcpy (buffer, NODE_NAME (token->val.node.node),
|
| + NODE_LEN (token->val.node.node));
|
| + buffer += NODE_LEN (token->val.node.node);
|
| }
|
| else
|
| {
|
| size_t i;
|
| - const unsigned char * name = NODE_NAME (token->val.node);
|
| + const unsigned char * name = NODE_NAME (token->val.node.node);
|
|
|
| - for (i = 0; i < NODE_LEN (token->val.node); i++)
|
| + for (i = 0; i < NODE_LEN (token->val.node.node); i++)
|
| if (name[i] & ~0x7F)
|
| {
|
| i += utf8_to_ucn (buffer, name + i) - 1;
|
| buffer += 10;
|
| }
|
| else
|
| - *buffer++ = NODE_NAME (token->val.node)[i];
|
| + *buffer++ = NODE_NAME (token->val.node.node)[i];
|
| }
|
| break;
|
|
|
| @@ -1550,11 +1872,17 @@ cpp_token_as_text (cpp_reader *pfile, const cpp_token *token)
|
| return start;
|
| }
|
|
|
| -/* Used by C front ends, which really should move to using
|
| - cpp_token_as_text. */
|
| +/* Returns a pointer to a string which spells the token defined by
|
| + TYPE and FLAGS. Used by C front ends, which really should move to
|
| + using cpp_token_as_text. */
|
| const char *
|
| -cpp_type2name (enum cpp_ttype type)
|
| +cpp_type2name (enum cpp_ttype type, unsigned char flags)
|
| {
|
| + if (flags & DIGRAPH)
|
| + return (const char *) cpp_digraph2name (type);
|
| + else if (flags & NAMED_OP)
|
| + return cpp_named_operator2name (type);
|
| +
|
| return (const char *) token_spellings[type].name;
|
| }
|
|
|
| @@ -1572,8 +1900,7 @@ cpp_output_token (const cpp_token *token, FILE *fp)
|
| int c;
|
|
|
| if (token->flags & DIGRAPH)
|
| - spelling
|
| - = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH];
|
| + spelling = cpp_digraph2name (token->type);
|
| else if (token->flags & NAMED_OP)
|
| goto spell_ident;
|
| else
|
| @@ -1590,9 +1917,9 @@ cpp_output_token (const cpp_token *token, FILE *fp)
|
| case SPELL_IDENT:
|
| {
|
| size_t i;
|
| - const unsigned char * name = NODE_NAME (token->val.node);
|
| + const unsigned char * name = NODE_NAME (token->val.node.node);
|
|
|
| - for (i = 0; i < NODE_LEN (token->val.node); i++)
|
| + for (i = 0; i < NODE_LEN (token->val.node.node); i++)
|
| if (name[i] & ~0x7F)
|
| {
|
| unsigned char buffer[10];
|
| @@ -1600,7 +1927,7 @@ cpp_output_token (const cpp_token *token, FILE *fp)
|
| fwrite (buffer, 1, 10, fp);
|
| }
|
| else
|
| - fputc (NODE_NAME (token->val.node)[i], fp);
|
| + fputc (NODE_NAME (token->val.node.node)[i], fp);
|
| }
|
| break;
|
|
|
| @@ -1623,11 +1950,14 @@ _cpp_equiv_tokens (const cpp_token *a, const cpp_token *b)
|
| {
|
| default: /* Keep compiler happy. */
|
| case SPELL_OPERATOR:
|
| - return 1;
|
| + /* token_no is used to track where multiple consecutive ##
|
| + tokens were originally located. */
|
| + return (a->type != CPP_PASTE || a->val.token_no == b->val.token_no);
|
| case SPELL_NONE:
|
| - return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no);
|
| + return (a->type != CPP_MACRO_ARG
|
| + || a->val.macro_arg.arg_no == b->val.macro_arg.arg_no);
|
| case SPELL_IDENT:
|
| - return a->val.node == b->val.node;
|
| + return a->val.node.node == b->val.node.node;
|
| case SPELL_LITERAL:
|
| return (a->val.str.len == b->val.str.len
|
| && !memcmp (a->val.str.text, b->val.str.text,
|
| @@ -1937,6 +2267,11 @@ cpp_token_val_index (cpp_token *tok)
|
| return CPP_TOKEN_FLD_NODE;
|
| case SPELL_LITERAL:
|
| return CPP_TOKEN_FLD_STR;
|
| + case SPELL_OPERATOR:
|
| + if (tok->type == CPP_PASTE)
|
| + return CPP_TOKEN_FLD_TOKEN_NO;
|
| + else
|
| + return CPP_TOKEN_FLD_NONE;
|
| case SPELL_NONE:
|
| if (tok->type == CPP_MACRO_ARG)
|
| return CPP_TOKEN_FLD_ARG_NO;
|
|
|