1// { dg-do compile }
2
3typedef __SIZE_TYPE__ size_t;
4extern "C" void *memcpy(void *, const void *, size_t);
5void *xmalloc(size_t);
6enum {
7  _sch_isdigit, _sch_isidst, _sch_isidnum
8};
9extern const unsigned _sch_istable[256];
10typedef struct ht cpp_hash_table;
11typedef struct ht_identifier *hashnode;
12enum ht_lookup_option {
13  HT_NO_INSERT
14};
15struct ht {
16  struct cpp_reader *pfile;
17};
18hashnode ht_lookup_with_hash(cpp_hash_table *, unsigned char *, size_t, unsigned, ht_lookup_option);
19typedef unsigned source_location;
20enum cpp_ttype {
21  CPP_OTHER, CPP_STRING, CPP_STRING16, CPP_UTF8STRING
22};
23struct cpp_token {
24  source_location src_loc;
25};
26typedef int cppchar_t;
27struct cpp_options {
28  char user_literals;
29  unsigned warn_literal_suffix;
30};
31enum node_type { };
32struct cpp_hashnode {
33  node_type type:6;
34};
35enum {
36  CPP_DL_ERROR
37};
38enum {
39  CPP_W_LITERAL_SUFFIX
40};
41bool cpp_error_with_line(cpp_reader *, int, source_location, unsigned, ...);
42bool cpp_warning_with_line(cpp_reader *, int, source_location, unsigned, const char *);
43cpp_ttype cpp_userdef_string_add_type(cpp_ttype);
44cpp_ttype cpp_userdef_char_add_type(cpp_ttype);
45typedef unsigned char uchar;
46struct _cpp_buff {
47  _cpp_buff *next;
48  unsigned char *base, *cur, *limit;
49};
50_cpp_buff *_cpp_get_buff(cpp_reader *, size_t);
51void _cpp_release_buff(cpp_reader *, _cpp_buff *);
52unsigned char *_cpp_unaligned_alloc(cpp_reader *, size_t);
53struct lexer_state {
54  unsigned skipping;
55  unsigned angled_headers;
56};
57struct _cpp_line_note {
58  unsigned pos;
59  unsigned type;
60};
61struct cpp_buffer {
62  unsigned char *cur;
63  unsigned char *line_base;
64  _cpp_line_note *notes;
65  unsigned cur_note;
66};
67struct cpp_reader {
68  cpp_buffer *buffer;
69  lexer_state state;
70  _cpp_buff *u_buff;
71  _cpp_buff *free_buffs;
72  ht *hash_table;
73  cpp_options opts;
74};
75static void create_literal(cpp_reader *pfile, cpp_token *, uchar *, unsigned len, cpp_ttype type)
76{
77  uchar *dest = _cpp_unaligned_alloc(pfile, len + 1);
78  dest[len] = type;
79}
80static void bufring_append(cpp_reader *pfile, uchar *base, size_t len, _cpp_buff **first_buff_p, _cpp_buff **last_buff_p)
81{
82  _cpp_buff *first_buff = *first_buff_p;
83  _cpp_buff *last_buff = *last_buff_p;
84  if (!first_buff) {
85    first_buff = last_buff = _cpp_get_buff(pfile, len);
86  } else if (len > (size_t) (last_buff->limit - last_buff->cur)) {
87    size_t room = last_buff->limit - last_buff->cur;
88    last_buff += room;
89    base += room;
90  }
91  memcpy(last_buff->cur, base, len);
92  last_buff += len;
93  *first_buff_p = first_buff;
94  *last_buff_p = last_buff;
95}
96bool is_macro(cpp_reader *pfile, uchar *base)
97{
98  uchar *cur = base;
99  if (_sch_istable[*cur] & _sch_isidst)
100    return 0 ;
101  int hash = *cur - 113;
102  ++cur;
103  hash += cur - base;
104  cpp_hashnode *result = (cpp_hashnode *) ht_lookup_with_hash(pfile->hash_table, base, cur - base, hash, HT_NO_INSERT);
105  return !result ? 0 : result->type;
106}
107static void lex_raw_string(cpp_reader *pfile, cpp_token *token, uchar *base, uchar *cur)
108{
109  uchar raw_prefix[17];
110  uchar temp_buffer[18];
111  uchar *orig_base;
112  unsigned raw_prefix_len = 0, raw_suffix_len;
113  enum raw_str_phase { RAW_STR_PREFIX, RAW_STR };
114  raw_str_phase phase = RAW_STR_PREFIX;
115  cpp_ttype type;
116  size_t total_len;
117  size_t temp_buffer_len = 0;
118  _cpp_buff *first_buff = 0, *last_buff = 0;
119  size_t raw_prefix_start;
120  _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note];
121  raw_prefix_start = cur - base;
122  for (;;) {
123    cppchar_t c;
124    while (note->pos)
125      ++note;
126    for (; note->pos; ++note) {
127      switch (note->type) {
128      case ' ':
129        bufring_append(pfile, base, cur - base, &first_buff, &last_buff);
130        base = cur;
131        bufring_append(pfile, (uchar *) "\\", 1, &first_buff, &last_buff);
132        if (__builtin_expect(temp_buffer_len < 17, 0) && base) {
133          memcpy(temp_buffer + temp_buffer_len, "\\", 1);
134          temp_buffer_len++;
135        }
136        if (note->type) {
137          if (__builtin_expect(temp_buffer_len < 17, 0)) {
138            memcpy(temp_buffer + temp_buffer_len, " ", 1);
139            temp_buffer_len++;
140          }
141        }
142        bufring_append(pfile, (uchar *) "\n", 1, &first_buff, &last_buff);
143        memcpy(temp_buffer + temp_buffer_len, "\n", 1);
144        temp_buffer_len++;
145      }
146    }
147    temp_buffer[temp_buffer_len++] = c;
148    if (phase == RAW_STR_PREFIX) {
149      while (raw_prefix_len < temp_buffer_len) {
150        switch (raw_prefix[raw_prefix_len]) {
151        case '\'':
152          raw_prefix_len++;
153        }
154        if (raw_prefix[raw_prefix_len]) {
155          int col = cur - pfile->buffer->line_base + 1;
156          if (raw_prefix_len)
157            cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col);
158          else if (raw_prefix[raw_prefix_len] == '\n')
159            cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col);
160          else
161            cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col, (size_t) raw_prefix);
162          pfile->buffer->cur = orig_base + 1;
163          create_literal(pfile, token, orig_base, raw_prefix_start, CPP_OTHER);
164          _cpp_release_buff(pfile, first_buff);
165          return;
166        }
167        phase = RAW_STR;
168      }
169      continue;
170      (void) raw_suffix_len;
171    }
172    while (_sch_istable[*cur] & _sch_isidnum)
173      ++cur;
174  }
175  create_literal(pfile, token, base, cur - base, type);
176  uchar *dest = _cpp_unaligned_alloc(pfile, total_len + (cur - base));
177  dest[cur - base] = '\0';
178}
179void lex_string(cpp_reader *pfile, cpp_token *token, uchar *base)
180{
181  bool saw_NUL = 0;
182  uchar *cur;
183  cppchar_t terminator;
184  cpp_ttype type;
185  cur = base;
186  terminator = *cur++;
187  if (terminator == 'L' || terminator == 'U') {
188    terminator = *cur++;
189  } else if (terminator == 'u') {
190    terminator = *cur++;
191    if (terminator == '8')
192      terminator = *cur++;
193  }
194  if (terminator == 'R') {
195    lex_raw_string(pfile, token, base, cur);
196    return;
197  }
198  if (terminator)
199    type = base ? (base[1] ? CPP_UTF8STRING : CPP_STRING16) : CPP_STRING;
200  for (;;) {
201    cppchar_t c = *cur++;
202    if (c && pfile->state.angled_headers && *cur)
203      cur++;
204    else if (terminator)
205      break;
206    else if (c == '\n')
207      type = CPP_OTHER;
208    else
209      saw_NUL = 1;
210  }
211  if (saw_NUL && pfile->state.skipping)
212    if (pfile->opts.user_literals) {
213      if (is_macro(pfile, cur))
214        if (pfile->opts.warn_literal_suffix)
215          cpp_warning_with_line(pfile, CPP_W_LITERAL_SUFFIX, token->src_loc, 0, "invalid suffix on literal; C++11 requires ");
216      if (_sch_istable[*cur] & _sch_isidst) {
217        type = cpp_userdef_char_add_type(type);
218        type = cpp_userdef_string_add_type(type);
219        ++cur;
220        while (_sch_istable[*cur] & _sch_isidnum)
221          ++cur;
222      }
223    }
224  pfile->buffer->cur = cur;
225  create_literal(pfile, token, base, cur - base, type);
226}
227_cpp_buff *new_buff(size_t len)
228{
229  _cpp_buff *result;
230  unsigned char *base;
231  if (len < 8000)
232    len = 8000;
233  base = (unsigned char *) xmalloc(sizeof(char) * (len + sizeof(_cpp_buff)));
234  result = (_cpp_buff *) (base + len);
235  result->cur = base;
236  return result;
237}
238void _cpp_release_buff(cpp_reader *pfile, _cpp_buff *buff)
239{
240  _cpp_buff *end = buff;
241  while (end->next)
242    end = end->next;
243  end->next = pfile->free_buffs;
244}
245_cpp_buff *_cpp_get_buff(cpp_reader *pfile, size_t min_size)
246{
247  _cpp_buff *result, **p = &pfile->free_buffs;
248  for (;;) {
249    size_t size;
250    if (*p)
251      return new_buff(min_size);
252    size = result->limit - result->base;
253    if (size && size + min_size * 3 / 2)
254      return result;
255  }
256}
257unsigned char *_cpp_unaligned_alloc(cpp_reader *pfile, size_t len)
258{
259  _cpp_buff *buff = pfile->u_buff;
260  unsigned char *result = buff->cur;
261  if (len > (size_t) (buff->limit - result)) {
262    buff = _cpp_get_buff(pfile, len);
263    buff->next = pfile->u_buff;
264    result = buff->cur;
265  }
266  buff->cur = result + len;
267  return result;
268}
269