1 // { dg-do compile }
2 
3 typedef __SIZE_TYPE__ size_t;
4 extern "C" void *memcpy(void *, const void *, size_t);
5 void *xmalloc(size_t);
6 enum {
7   _sch_isdigit, _sch_isidst, _sch_isidnum
8 };
9 extern const unsigned _sch_istable[256];
10 typedef struct ht cpp_hash_table;
11 typedef struct ht_identifier *hashnode;
12 enum ht_lookup_option {
13   HT_NO_INSERT
14 };
15 struct ht {
16   struct cpp_reader *pfile;
17 };
18 hashnode ht_lookup_with_hash(cpp_hash_table *, unsigned char *, size_t, unsigned, ht_lookup_option);
19 typedef unsigned source_location;
20 enum cpp_ttype {
21   CPP_OTHER, CPP_STRING, CPP_STRING16, CPP_UTF8STRING
22 };
23 struct cpp_token {
24   source_location src_loc;
25 };
26 typedef int cppchar_t;
27 struct cpp_options {
28   char user_literals;
29   unsigned warn_literal_suffix;
30 };
31 enum node_type { };
32 struct cpp_hashnode {
33   node_type type:6;
34 };
35 enum {
36   CPP_DL_ERROR
37 };
38 enum {
39   CPP_W_LITERAL_SUFFIX
40 };
41 bool cpp_error_with_line(cpp_reader *, int, source_location, unsigned, ...);
42 bool cpp_warning_with_line(cpp_reader *, int, source_location, unsigned, const char *);
43 cpp_ttype cpp_userdef_string_add_type(cpp_ttype);
44 cpp_ttype cpp_userdef_char_add_type(cpp_ttype);
45 typedef unsigned char uchar;
46 struct _cpp_buff {
47   _cpp_buff *next;
48   unsigned char *base, *cur, *limit;
49 };
50 _cpp_buff *_cpp_get_buff(cpp_reader *, size_t);
51 void _cpp_release_buff(cpp_reader *, _cpp_buff *);
52 unsigned char *_cpp_unaligned_alloc(cpp_reader *, size_t);
53 struct lexer_state {
54   unsigned skipping;
55   unsigned angled_headers;
56 };
57 struct _cpp_line_note {
58   unsigned pos;
59   unsigned type;
60 };
61 struct cpp_buffer {
62   unsigned char *cur;
63   unsigned char *line_base;
64   _cpp_line_note *notes;
65   unsigned cur_note;
66 };
67 struct 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 };
create_literal(cpp_reader * pfile,cpp_token *,uchar *,unsigned len,cpp_ttype type)75 static 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 }
bufring_append(cpp_reader * pfile,uchar * base,size_t len,_cpp_buff ** first_buff_p,_cpp_buff ** last_buff_p)80 static 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 }
is_macro(cpp_reader * pfile,uchar * base)96 bool 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 }
lex_raw_string(cpp_reader * pfile,cpp_token * token,uchar * base,uchar * cur)107 static 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 }
lex_string(cpp_reader * pfile,cpp_token * token,uchar * base)179 void 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 }
new_buff(size_t len)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 }
_cpp_release_buff(cpp_reader * pfile,_cpp_buff * buff)238 void _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 }
_cpp_get_buff(cpp_reader * pfile,size_t min_size)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 }
_cpp_unaligned_alloc(cpp_reader * pfile,size_t len)257 unsigned 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