Print this page
Address Robert's feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libsysdemangle/common/cpp.c
+++ new/usr/src/lib/libsysdemangle/common/cxx.c
1 1 /*
2 2 * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3 3 * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
4 4 *
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
5 5 * The LLVM Compiler Infrastructure
6 6 *
7 7 * This file is dual licensed under the MIT and the University of Illinois Open
8 8 * Source Licenses. See LICENSE.TXT for details.
9 9 *
10 10 */
11 11
12 12 /*
13 13 * Copyright 2017 Jason King.
14 14 */
15 -
15 +#include <ctype.h>
16 16 #include <errno.h>
17 +#include <locale.h>
17 18 #include <string.h>
18 19 #include <setjmp.h>
19 20 #include <stdio.h>
20 21 #include <stdlib.h>
21 22 #include <sys/isa_defs.h>
22 23 #include <sys/debug.h>
23 24 #include "sysdemangle.h"
24 25 #include "sysdemangle_int.h"
25 -#include "cpp.h"
26 +#include "cxx.h"
26 27
28 +#ifndef ARRAY_SIZE
27 29 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
30 +#endif
28 31
29 32 #define CPP_QUAL_CONST (1U)
30 33 #define CPP_QUAL_VOLATILE (2U)
31 34 #define CPP_QUAL_RESTRICT (4U)
32 35
33 36 typedef struct cpp_db_s {
34 37 sysdem_ops_t *cpp_ops;
35 38 jmp_buf cpp_jmp;
36 39 name_t cpp_name;
37 40 sub_t cpp_subs;
38 41 templ_t cpp_templ;
39 42 unsigned cpp_cv;
40 43 unsigned cpp_ref;
41 44 unsigned cpp_depth;
42 45 boolean_t cpp_parsed_ctor_dtor_cv;
43 46 boolean_t cpp_tag_templates;
44 47 boolean_t cpp_fix_forward_references;
45 48 boolean_t cpp_try_to_parse_template_args;
49 + locale_t cpp_loc;
46 50 } cpp_db_t;
47 51
48 52 #define CK(x) \
49 53 do { \
50 54 if (!(x)) \
51 55 longjmp(db->cpp_jmp, 1); \
52 56 } while (0)
53 57
54 58 #define TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
55 59 #define RLEN(f, l) ((size_t)((l) - (f)))
56 60 #define NAMT(db, n) (nlen(db) - n)
57 61
58 -static inline boolean_t is_digit(int);
59 -static inline boolean_t is_upper(int);
60 62 static inline boolean_t is_xdigit(int);
61 63
62 64 static boolean_t nempty(cpp_db_t *);
63 65 static size_t nlen(cpp_db_t *);
64 66 static void nadd_l(cpp_db_t *, const char *, size_t);
65 67 static void njoin(cpp_db_t *, size_t, const char *);
66 68 static void nfmt(cpp_db_t *, const char *, const char *);
67 69
68 70 static void save_top(cpp_db_t *, size_t);
69 71 static void sub(cpp_db_t *, size_t);
70 72
71 73 static boolean_t tempty(const cpp_db_t *);
72 74 static size_t ttlen(const cpp_db_t *);
73 75
74 76 static void tsub(cpp_db_t *, size_t);
75 77 static void tpush(cpp_db_t *);
76 78 static void tpop(cpp_db_t *);
77 79 static void tsave(cpp_db_t *, size_t);
78 80
79 -static void db_init(cpp_db_t *, sysdem_ops_t *);
81 +static boolean_t db_init(cpp_db_t *, sysdem_ops_t *);
80 82 static void db_fini(cpp_db_t *);
81 83 static void dump(cpp_db_t *, FILE *);
82 84
83 85 static void demangle(const char *, const char *, cpp_db_t *);
84 86
85 87 static const char *parse_type(const char *, const char *, cpp_db_t *);
86 88 static const char *parse_builtin_type(const char *, const char *, cpp_db_t *);
87 89 static const char *parse_qual_type(const char *, const char *, cpp_db_t *);
88 90 static const char *parse_encoding(const char *, const char *, cpp_db_t *);
89 91 static const char *parse_dot_suffix(const char *, const char *, cpp_db_t *);
90 92 static const char *parse_block_invoke(const char *, const char *, cpp_db_t *);
91 93 static const char *parse_special_name(const char *, const char *, cpp_db_t *);
92 94 static const char *parse_name(const char *, const char *, boolean_t *,
93 95 cpp_db_t *);
94 -static const char *parse_call_offset(const char *, const char *);
95 -static const char *parse_number(const char *, const char *);
96 +static const char *parse_call_offset(const char *, const char *, locale_t);
97 +static const char *parse_number(const char *, const char *, locale_t);
96 98 static const char *parse_nested_name(const char *, const char *, boolean_t *,
97 99 cpp_db_t *);
98 100 static const char *parse_local_name(const char *, const char *, boolean_t *,
99 101 cpp_db_t *);
100 102 static const char *parse_unscoped_name(const char *, const char *, cpp_db_t *);
101 103 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
102 104 static const char *parse_substitution(const char *, const char *, cpp_db_t *);
103 -static const char *parse_discriminator(const char *, const char *);
105 +static const char *parse_discriminator(const char *, const char *, locale_t);
104 106 static const char *parse_cv_qualifiers(const char *, const char *, unsigned *);
105 107 static const char *parse_template_param(const char *, const char *, cpp_db_t *);
106 108 static const char *parse_decltype(const char *, const char *, cpp_db_t *);
107 109 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
108 110 static const char *parse_unqualified_name(const char *, const char *,
109 111 cpp_db_t *);
110 112 static const char *parse_template_arg(const char *, const char *, cpp_db_t *);
111 113 static const char *parse_expression(const char *, const char *, cpp_db_t *);
112 114 static const char *parse_expr_primary(const char *, const char *, cpp_db_t *);
113 115 static const char *parse_binary_expr(const char *, const char *,
114 116 const char *, cpp_db_t *);
115 117 static const char *parse_prefix_expr(const char *, const char *,
116 118 const char *, cpp_db_t *);
117 119 static const char *parse_gs(const char *, const char *, cpp_db_t *);
118 120 static const char *parse_idx_expr(const char *, const char *, cpp_db_t *);
119 121 static const char *parse_mm_expr(const char *, const char *, cpp_db_t *);
120 122 static const char *parse_pp_expr(const char *, const char *, cpp_db_t *);
121 123 static const char *parse_trinary_expr(const char *, const char *, cpp_db_t *);
122 124 static const char *parse_new_expr(const char *, const char *, cpp_db_t *);
123 125 static const char *parse_del_expr(const char *, const char *, cpp_db_t *);
124 126 static const char *parse_cast_expr(const char *, const char *, cpp_db_t *);
125 127 static const char *parse_sizeof_param_pack_expr(const char *, const char *,
126 128 cpp_db_t *);
127 129 static const char *parse_typeid_expr(const char *, const char *, cpp_db_t *);
128 130 static const char *parse_throw_expr(const char *, const char *, cpp_db_t *);
129 131 static const char *parse_dot_star_expr(const char *, const char *, cpp_db_t *);
130 132 static const char *parse_dot_expr(const char *, const char *, cpp_db_t *);
131 133 static const char *parse_call_expr(const char *, const char *, cpp_db_t *);
132 134 static const char *parse_arrow_expr(const char *, const char *, cpp_db_t *);
133 135 static const char *parse_conv_expr(const char *, const char *, cpp_db_t *);
134 136 static const char *parse_function_param(const char *, const char *, cpp_db_t *);
135 137 static const char *parse_base_unresolved_name(const char *, const char *,
136 138 cpp_db_t *);
137 139 static const char *parse_unresolved_name(const char *, const char *,
138 140 cpp_db_t *);
139 141 static const char *parse_noexcept_expr(const char *, const char *, cpp_db_t *);
140 142 static const char *parse_alignof(const char *, const char *, cpp_db_t *);
141 143 static const char *parse_sizeof(const char *, const char *, cpp_db_t *);
142 144 static const char *parse_unnamed_type_name(const char *, const char *,
143 145 cpp_db_t *);
144 146 static const char *parse_ctor_dtor_name(const char *, const char *, cpp_db_t *);
145 147 static const char *parse_source_name(const char *, const char *, cpp_db_t *);
146 148 static const char *parse_operator_name(const char *, const char *, cpp_db_t *);
147 149 static const char *parse_pack_expansion(const char *, const char *, cpp_db_t *);
148 150 static const char *parse_unresolved_type(const char *, const char *,
149 151 cpp_db_t *);
150 152 static const char *parse_unresolved_qualifier_level(const char *, const char *,
151 153 cpp_db_t *);
152 154 static const char *parse_destructor_name(const char *, const char *,
153 155 cpp_db_t *);
154 156 static const char *parse_function_type(const char *, const char *, cpp_db_t *);
155 157 static const char *parse_array_type(const char *, const char *, cpp_db_t *);
156 158 static const char *parse_pointer_to_member_type(const char *, const char *,
157 159 cpp_db_t *);
158 160 static const char *parse_vector_type(const char *, const char *, cpp_db_t *);
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
159 161
160 162 size_t cpp_name_max_depth = 1024; /* max depth of name stack */
161 163
162 164 char *
163 165 cpp_demangle(const char *src, sysdem_ops_t *ops)
164 166 {
165 167 char *result = NULL;
166 168 cpp_db_t db;
167 169 size_t srclen = strlen(src);
168 170
169 - db_init(&db, ops);
170 -
171 + if (!db_init(&db, ops))
172 + goto done;
171 173 if (setjmp(db.cpp_jmp) != 0)
172 174 goto done;
173 175
174 176 errno = 0;
175 177 demangle(src, src + srclen, &db);
176 178
177 179 if (errno == 0 && db.cpp_fix_forward_references &&
178 180 !templ_empty(&db.cpp_templ) &&
179 181 !sub_empty(&db.cpp_templ.tpl_items[0])) {
180 182 db.cpp_fix_forward_references = B_FALSE;
181 183 db.cpp_tag_templates = B_FALSE;
182 184 name_clear(&db.cpp_name);
183 185 sub_clear(&db.cpp_subs);
184 186
185 187 if (setjmp(db.cpp_jmp) != 0)
186 188 goto done;
187 189
188 190 demangle(src, src + srclen, &db);
189 191
190 192 if (db.cpp_fix_forward_references) {
191 193 errno = EINVAL;
192 194 goto done;
193 195 }
194 196 }
195 197
196 198 if (errno != 0)
197 199 goto done;
198 200
199 201 if (nempty(&db)) {
200 202 errno = EINVAL;
201 203 goto done;
202 204 }
203 205
204 206 njoin(&db, 1, "");
205 207
206 208 if (nlen(&db) > 0) {
207 209 str_t *s = TOP_L(&db);
208 210 result = zalloc(ops, s->str_len + 1);
209 211 if (result == NULL)
210 212 goto done;
211 213
212 214 (void) memcpy(result, s->str_s, s->str_len);
213 215 }
214 216
215 217 done:
216 218 if (getenv("DEMANGLE_DEBUG") != NULL)
217 219 dump(&db, stdout);
218 220
219 221 db_fini(&db);
220 222 return (result);
221 223 }
222 224
223 225 static void
224 226 demangle(const char *first, const char *last, cpp_db_t *db)
225 227 {
226 228 const char *t = NULL;
227 229
228 230 if (first >= last) {
229 231 errno = EINVAL;
230 232 return;
231 233 }
232 234
233 235 if (first[0] != '_') {
234 236 t = parse_type(first, last, db);
235 237 if (t == first) {
236 238 errno = EINVAL;
237 239 return;
238 240 }
239 241 goto done;
240 242 }
241 243
242 244 if (last - first < 4) {
243 245 errno = EINVAL;
244 246 return;
245 247 }
246 248
247 249 if (first[1] == 'Z') {
248 250 t = parse_encoding(first + 2, last, db);
249 251
250 252 if (t != first + 2 && t != last && t[0] == '.') {
251 253 t = parse_dot_suffix(t, last, db);
252 254 if (nlen(db) > 1)
253 255 njoin(db, 2, "");
254 256 }
255 257
256 258 goto done;
257 259 }
258 260
259 261 if (first[1] != '_' || first[2] != '_' || first[3] != 'Z')
260 262 goto done;
261 263
262 264 t = parse_encoding(first + 4, last, db);
263 265 if (t != first + 4 && t != last)
↓ open down ↓ |
83 lines elided |
↑ open up ↑ |
264 266 t = parse_block_invoke(t, last, db);
265 267
266 268 done:
267 269 if (t != last)
268 270 errno = EINVAL;
269 271 }
270 272
271 273 static const char *
272 274 parse_dot_suffix(const char *first, const char *last, cpp_db_t *db)
273 275 {
274 - ASSERT3P(first, <=, last);
276 + VERIFY3P(first, <=, last);
275 277
276 278 if (first == last || first[0] != '.')
277 279 return (first);
278 280
279 281 if (nempty(db))
280 282 return (first);
281 283
282 284 nadd_l(db, first, RLEN(first, last));
283 285 nfmt(db, " ({0})", NULL);
284 286
285 287 return (last);
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
286 288 }
287 289
288 290 /*
289 291 * _block_invoke
290 292 * _block_invoke<digit>+ XXX: should it be <digit>* ?
291 293 * _block_invoke_<digit>+
292 294 */
293 295 static const char *
294 296 parse_block_invoke(const char *first, const char *last, cpp_db_t *db)
295 297 {
296 - ASSERT3P(first, <=, last);
298 + VERIFY3P(first, <=, last);
297 299
298 300 if (last - first < 13)
299 301 return (first);
300 302
301 303 const char test[] = "_block_invoke";
302 304 const char *t = first;
303 305
304 306 if (strncmp(first, test, sizeof (test) - 1) != 0)
305 307 return (first);
306 308
307 309 t += sizeof (test);
308 310 if (t == last)
309 311 goto done;
310 312
311 313 if (t[0] == '_') {
312 314 /* need at least one digit */
313 - if (t + 1 == last || !is_digit(t[1]))
315 + if (t + 1 == last || !isdigit_l(t[1], db->cpp_loc))
314 316 return (first);
315 317 t += 2;
316 318 }
317 319
318 - while (t < last && is_digit(t[0]))
320 + while (t < last && isdigit_l(t[0], db->cpp_loc))
319 321 t++;
320 322
321 323 done:
322 324 if (nempty(db))
323 325 return (first);
324 326
325 327 nfmt(db, "invocation function for block in {0}", NULL);
326 328 return (t);
327 329 }
328 330
329 331 /*
330 332 * <encoding> ::= <function name><bare-function-type>
331 333 * ::= <data name>
332 334 * ::= <special name>
333 335 */
334 336 static const char *
335 337 parse_encoding(const char *first, const char *last, cpp_db_t *db)
336 338 {
337 - ASSERT3P(first, <=, last);
339 + VERIFY3P(first, <=, last);
338 340
339 341 if (first == last)
340 342 return (first);
341 343
342 344 const char *t = NULL;
343 345 const char *t2 = NULL;
344 346 unsigned cv = 0;
345 347 unsigned ref = 0;
346 348 boolean_t tag_templ_save = db->cpp_tag_templates;
347 349
348 350 if (++db->cpp_depth > 1)
349 351 db->cpp_tag_templates = B_TRUE;
350 352
351 353 if (first[0] == 'G' || first[0] == 'T') {
352 354 t = parse_special_name(first, last, db);
353 355 goto done;
354 356 }
355 357
356 358 boolean_t ends_with_template_args = B_FALSE;
357 359 t = parse_name(first, last, &ends_with_template_args, db);
358 360 if (t == first)
359 361 goto fail;
360 362
361 363 cv = db->cpp_cv;
362 364 ref = db->cpp_ref;
363 365
364 366 if (t == last || t[0] == 'E' || t[0] == '.')
365 367 goto done;
366 368
367 369 db->cpp_tag_templates = B_FALSE;
368 370 if (nempty(db) || str_length(TOP_L(db)) == 0)
369 371 goto fail;
370 372
371 373 if (!db->cpp_parsed_ctor_dtor_cv && ends_with_template_args) {
372 374 t2 = parse_type(t, last, db);
373 375 if (t2 == t || nlen(db) < 2)
374 376 goto fail;
375 377
376 378 str_pair_t *sp = name_top(&db->cpp_name);
377 379
378 380 if (str_length(&sp->strp_r) == 0)
379 381 str_append(&sp->strp_l, " ", 1);
380 382
381 383 nfmt(db, "{0:L}{1:L}", "{1:R}{0:R}");
382 384 t = t2;
383 385 }
384 386
385 387 if (t == last || nempty(db))
386 388 goto fail;
387 389
388 390 size_t n = nlen(db);
389 391
390 392 if (t[0] == 'v') {
391 393 t++;
392 394 } else {
393 395
394 396 /*CONSTCOND*/
395 397 while (1) {
396 398 t2 = parse_type(t, last, db);
397 399 if (t2 == t || t == last)
398 400 break;
399 401
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
400 402 t = t2;
401 403 }
402 404 }
403 405
404 406 /*
405 407 * a bit of a hack, but a template substitution can apparently be
406 408 * an empty string at the end of an argument list, so avoid
407 409 * <...., >
408 410 */
409 411 if (NAMT(db, n) > 1 && str_pair_len(name_top(&db->cpp_name)) == 0)
410 - (void) name_pop(&db->cpp_name, NULL);
412 + name_pop(&db->cpp_name, NULL);
411 413
412 414 njoin(db, NAMT(db, n), ", ");
413 415 nfmt(db, "({0})", NULL);
414 416
415 417 str_t *s = TOP_L(db);
416 418
417 419 if (cv & CPP_QUAL_CONST) {
418 420 CK(str_append(s, " const", 0));
419 421 }
420 422 if (cv & CPP_QUAL_VOLATILE) {
421 423 CK(str_append(s, " volatile", 0));
422 424 }
423 425 if (cv & CPP_QUAL_RESTRICT) {
424 426 CK(str_append(s, " restrict", 0));
425 427 }
426 428 if (ref == 1) {
427 429 CK(str_append(s, " &", 0));
428 430 }
429 431 if (ref == 2) {
430 432 CK(str_append(s, " &&", 0));
431 433 }
432 434
433 435 nfmt(db, "{1:L}{0}{1:R}", NULL);
434 436
435 437 done:
436 438 db->cpp_tag_templates = tag_templ_save;
437 439 db->cpp_depth--;
438 440 return (t);
439 441
440 442 fail:
441 443 db->cpp_tag_templates = tag_templ_save;
442 444 db->cpp_depth--;
443 445 return (first);
444 446 }
445 447
446 448 /*
447 449 * <special-name> ::= TV <type> # virtual table
448 450 * ::= TT <type> # VTT structure (construction vtable index)
449 451 * ::= TI <type> # typeinfo structure
450 452 * ::= TS <type> # typeinfo name (null-terminated byte string)
451 453 * ::= Tc <call-offset> <call-offset> <base encoding>
452 454 * # base is the nominal target function of thunk
453 455 * # first call-offset is 'this' adjustment
454 456 * # second call-offset is result adjustment
455 457 * ::= T <call-offset> <base encoding>
456 458 * # base is the nominal target function of thunk
457 459 * ::= GV <object name> # Guard variable for one-time init
↓ open down ↓ |
37 lines elided |
↑ open up ↑ |
458 460 * # No <type>
459 461 * ::= TW <object name> # Thread-local wrapper
460 462 * ::= TH <object name> # Thread-local initialization
461 463 * extension ::= TC <first type> <number> _ <second type>
462 464 * # construction vtable for second-in-first
463 465 * extension ::= GR <object name> # reference temporary for object
464 466 */
465 467 static const char *
466 468 parse_special_name(const char *first, const char *last, cpp_db_t *db)
467 469 {
468 - ASSERT3P(first, <=, last);
470 + VERIFY3P(first, <=, last);
469 471
470 472 const char *t = first;
471 473 const char *t1 = NULL;
472 474 size_t n = nlen(db);
473 475
474 476 if (last - first < 2)
475 477 return (first);
476 478
477 479 switch (t[0]) {
478 480 case 'T':
479 481 switch (t[1]) {
480 482 case 'V':
481 483 nadd_l(db, "vtable for", 0);
482 484 t = parse_type(first + 2, last, db);
483 485 break;
484 486 case 'T':
485 487 nadd_l(db, "VTT for", 0);
486 488 t = parse_type(first + 2, last, db);
487 489 break;
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
488 490 case 'I':
489 491 nadd_l(db, "typeinfo for", 0);
490 492 t = parse_type(first + 2, last, db);
491 493 break;
492 494 case 'S':
493 495 nadd_l(db, "typeinfo name for", 0);
494 496 t = parse_type(first + 2, last, db);
495 497 break;
496 498 case 'c':
497 499 nadd_l(db, "covariant return thunk to", 0);
498 - t1 = parse_call_offset(first + 2, last);
500 + t1 = parse_call_offset(first + 2, last, db->cpp_loc);
499 501 if (t1 == t)
500 502 return (first);
501 - t = parse_call_offset(t1, last);
503 + t = parse_call_offset(t1, last, db->cpp_loc);
502 504 if (t == t1)
503 505 return (first);
504 506 t1 = parse_encoding(t, last, db);
505 507 if (t1 == t)
506 508 return (first);
507 509 break;
508 510 case 'C':
509 511 t = parse_type(first + 2, last, db);
510 512 if (t == first + 2)
511 513 return (first);
512 - t1 = parse_number(t, last);
514 + t1 = parse_number(t, last, db->cpp_loc);
513 515 if (*t1 != '_')
514 516 return (first);
515 517 t = parse_type(t1 + 1, last, db);
516 518 if (t == t1 + 1 || nlen(db) < 2)
517 519 return (first);
518 520 nfmt(db, "construction vtable for {0}-in-{1}", NULL);
519 521 return (t);
520 522 case 'W':
521 523 nadd_l(db, "thread-local wrapper routine for", 0);
522 524 t = parse_name(first + 2, last, NULL, db);
523 525 break;
524 526 case 'H':
525 527 nadd_l(db, "thread-local initialization routine for",
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
526 528 0);
527 529 t = parse_name(first + 2, last, NULL, db);
528 530 break;
529 531 default:
530 532 if (first[1] == 'v') {
531 533 nadd_l(db, "virtual thunk to", 0);
532 534 } else {
533 535 nadd_l(db, "non-virtual thunk to", 0);
534 536 }
535 537
536 - t = parse_call_offset(first + 1, last);
538 + t = parse_call_offset(first + 1, last, db->cpp_loc);
537 539 if (t == first + 1)
538 540 return (first);
539 541 t1 = parse_encoding(t, last, db);
540 542 if (t == t1)
541 543 return (first);
542 544 t = t1;
543 545 break;
544 546 }
545 547 break;
546 548 case 'G':
547 549 switch (first[1]) {
548 550 case 'V':
549 551 nadd_l(db, "guard variable for", 0);
550 552 t = parse_name(first + 2, last, NULL, db);
551 553 break;
552 554 case 'R':
553 555 nadd_l(db, "reference temporary for", 0);
554 556 t = parse_name(first + 2, last, NULL, db);
555 557 break;
556 558 default:
557 559 return (first);
558 560 }
559 561 break;
560 562 default:
561 563 return (first);
562 564 }
563 565
564 566 size_t amt = NAMT(db, n);
565 567 if (t == first + 2 || amt < 2)
566 568 return (first);
567 569
568 570 njoin(db, amt, " ");
569 571 return (t);
570 572 }
571 573
572 574 /*
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
573 575 * <call-offset> ::= h <nv-offset> _
574 576 * ::= v <v-offset> _
575 577 *
576 578 * <nv-offset> ::= <offset number>
577 579 * # non-virtual base override
578 580 *
579 581 * <v-offset> ::= <offset number> _ <virtual offset number>
580 582 * # virtual base override, with vcall offset
581 583 */
582 584 static const char *
583 -parse_call_offset(const char *first, const char *last)
585 +parse_call_offset(const char *first, const char *last, locale_t loc)
584 586 {
585 - ASSERT3P(first, <=, last);
587 + VERIFY3P(first, <=, last);
586 588
587 589 const char *t = NULL;
588 590 const char *t1 = NULL;
589 591
590 592 if (first == last)
591 593 return (first);
592 594
593 595 if (first[0] != 'h' && first[0] != 'v')
594 596 return (first);
595 597
596 - t = parse_number(first + 1, last);
598 + t = parse_number(first + 1, last, loc);
597 599 if (t == first + 1 || t == last || t[0] != '_')
598 600 return (first);
599 601
600 602 /* skip _ */
601 603 t++;
602 604
603 605 if (first[0] == 'h')
604 606 return (t);
605 607
606 - t1 = parse_number(t, last);
608 + t1 = parse_number(t, last, loc);
607 609 if (t == t1 || t1 == last || t1[0] != '_')
608 610 return (first);
609 611
610 612 /* skip _ */
611 613 t1++;
612 614
613 615 return (t1);
614 616 }
615 617
616 618 /*
617 619 * <name> ::= <nested-name> // N
618 620 * ::= <local-name> # See Scope Encoding below // Z
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
619 621 * ::= <unscoped-template-name> <template-args>
620 622 * ::= <unscoped-name>
621 623 *
622 624 * <unscoped-template-name> ::= <unscoped-name>
623 625 * ::= <substitution>
624 626 */
625 627 static const char *
626 628 parse_name(const char *first, const char *last,
627 629 boolean_t *ends_with_template_args, cpp_db_t *db)
628 630 {
629 - ASSERT3P(first, <=, last);
631 + VERIFY3P(first, <=, last);
630 632
631 633 const char *t = first;
632 634 const char *t1 = NULL;
633 635
634 636 if (last - first < 2)
635 637 return (first);
636 638
637 639 /* extension: ignore L here */
638 640 if (t[0] == 'L')
639 641 t++;
640 642
641 643 switch (t[0]) {
642 644 case 'N':
643 645 t1 = parse_nested_name(t, last, ends_with_template_args, db);
644 646 return ((t == t1) ? first : t1);
645 647 case 'Z':
646 648 t1 = parse_local_name(t, last, ends_with_template_args, db);
647 649 return ((t == t1) ? first : t1);
648 650 }
649 651
650 652 /*
651 653 * <unscoped-name>
652 654 * <unscoped-name> <template-args>
653 655 * <substitution> <template-args>
654 656 */
655 657 t1 = parse_unscoped_name(t, last, db);
656 658
657 659 /* <unscoped-name> */
658 660 if (t != t1 && t1[0] != 'I')
659 661 return (t1);
660 662
661 663 if (t == t1) {
662 664 t1 = parse_substitution(t, last, db);
663 665 if (t == t1 || t1 == last || t1[0] != 'I')
664 666 return (first);
665 667 } else {
666 668 save_top(db, 1);
667 669 }
668 670
669 671 t = parse_template_args(t1, last, db);
670 672 if (t1 == t || nlen(db) < 2)
671 673 return (first);
672 674
673 675 nfmt(db, "{1:L}{0}", "{1:R}");
674 676
675 677 if (ends_with_template_args != NULL)
676 678 *ends_with_template_args = B_TRUE;
677 679
678 680 return (t);
679 681 }
680 682
681 683 /* BEGIN CSTYLED */
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
682 684 /*
683 685 * <local-name> := Z <function encoding> E <entity name> [<discriminator>]
684 686 * := Z <function encoding> E s [<discriminator>]
685 687 * := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
686 688 */
687 689 /* END CSTYLED */
688 690 const char *
689 691 parse_local_name(const char *first, const char *last,
690 692 boolean_t *ends_with_template_args, cpp_db_t *db)
691 693 {
692 - ASSERT3P(first, <=, last);
694 + VERIFY3P(first, <=, last);
693 695
694 696 const char *t = NULL;
695 697 const char *t1 = NULL;
696 698 const char *t2 = NULL;
697 699
698 700 if (first == last || first[0] != 'Z')
699 701 return (first);
700 702
701 703 t = parse_encoding(first + 1, last, db);
702 704 if (t == first + 1 || t == last || t[0] != 'E')
703 705 return (first);
704 706
705 - ASSERT(!nempty(db));
707 + VERIFY(!nempty(db));
706 708
707 709 /* skip E */
708 710 t++;
709 711
710 712 if (t[0] == 's') {
711 713 nfmt(db, "{0:L}::string literal", "{0:R}");
712 - return (parse_discriminator(t, last));
714 + return (parse_discriminator(t, last, db->cpp_loc));
713 715 }
714 716
715 717 if (t[0] == 'd') {
716 - t1 = parse_number(t + 1, last);
718 + t1 = parse_number(t + 1, last, db->cpp_loc);
717 719 if (t1[0] != '_')
718 720 return (first);
719 721 t1++;
720 722 } else {
721 723 t1 = t;
722 724 }
723 725
724 726 t2 = parse_name(t1, last, ends_with_template_args, db);
725 727 if (t2 == t1)
726 728 return (first);
727 729
728 730 nfmt(db, "{1:L}::{0}", "{1:R}");
729 731
730 732 /* parsed, but ignored */
731 733 if (t[0] != 'd')
732 - t2 = parse_discriminator(t2, last);
734 + t2 = parse_discriminator(t2, last, db->cpp_loc);
733 735
734 736 return (t2);
735 737 }
736 738
737 739 /* BEGIN CSTYLED */
738 740 /*
739 741 * <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
740 742 * ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
741 743 *
742 744 * <prefix> ::= <prefix> <unqualified-name>
743 745 * ::= <template-prefix> <template-args>
744 746 * ::= <template-param>
745 747 * ::= <decltype>
746 748 * ::= # empty
747 749 * ::= <substitution>
748 750 * ::= <prefix> <data-member-prefix>
749 751 * extension ::= L
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
750 752 *
751 753 * <template-prefix> ::= <prefix> <template unqualified-name>
752 754 * ::= <template-param>
753 755 * ::= <substitution>
754 756 */
755 757 /* END CSTYLED */
756 758 static const char *
757 759 parse_nested_name(const char *first, const char *last,
758 760 boolean_t *ends_with_template_args, cpp_db_t *db)
759 761 {
760 - ASSERT3P(first, <=, last);
762 + VERIFY3P(first, <=, last);
761 763
762 764 if (first == last || first[0] != 'N')
763 765 return (first);
764 766
765 767 unsigned cv = 0;
766 768 const char *t = parse_cv_qualifiers(first + 1, last, &cv);
767 769
768 770 if (t == last)
769 771 return (first);
770 772
771 773 boolean_t more = B_FALSE;
772 774
773 775 switch (t[0]) {
774 776 case 'R':
775 777 db->cpp_ref = 1;
776 778 t++;
777 779 break;
778 780 case 'O':
779 781 db->cpp_ref = 2;
780 782 t++;
781 783 break;
782 784 case 'S':
783 785 if (last - first < 2 || t[1] != 't')
784 786 break;
785 787 if (last - first == 2)
786 788 return (first);
787 789 nadd_l(db, "std", 3);
788 790 more = B_TRUE;
789 791 t += 2;
790 792 break;
791 793 }
792 794
793 795 boolean_t pop_subs = B_FALSE;
794 796 boolean_t component_ends_with_template_args = B_FALSE;
795 797
796 798 while (t[0] != 'E' && t != last) {
797 799 const char *t1 = NULL;
798 800 size_t n = nlen(db);
799 801 component_ends_with_template_args = B_FALSE;
800 802
801 803 switch (t[0]) {
802 804 case 'S':
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
803 805 if (t + 1 != last && t[1] == 't')
804 806 break;
805 807
806 808 t1 = parse_substitution(t, last, db);
807 809 if (t1 == t || t1 == last || NAMT(db, n) != 1)
808 810 return (first);
809 811
810 812 if (!more) {
811 813 nfmt(db, "{0}", NULL);
812 814 } else {
813 - ASSERT3U(nlen(db), >, 1);
815 + VERIFY3U(nlen(db), >, 1);
814 816 nfmt(db, "{1:L}::{0}", "{1:R}");
815 817 save_top(db, 1);
816 818 }
817 819
818 820 more = B_TRUE;
819 821 pop_subs = B_TRUE;
820 822 t = t1;
821 823 continue;
822 824
823 825 case 'T':
824 826 t1 = parse_template_param(t, last, db);
825 827 if (t1 == t || t1 == last || NAMT(db, n) != 1)
826 828 return (first);
827 829
828 830 if (!more) {
829 831 nfmt(db, "{0}", NULL);
830 832 } else {
831 - ASSERT3U(nlen(db), >, 1);
833 + VERIFY3U(nlen(db), >, 1);
832 834 nfmt(db, "{1:L}::{0}", "{1:R}");
833 835 }
834 836
835 837 save_top(db, 1);
836 838 more = B_TRUE;
837 839 pop_subs = B_TRUE;
838 840 t = t1;
839 841 continue;
840 842
841 843 case 'D':
842 844 if (t + 1 != last && t[1] != 't' && t[1] != 'T')
843 845 break;
844 846 t1 = parse_decltype(t, last, db);
845 847 if (t1 == t || t1 == last || NAMT(db, n) != 1)
846 848 return (first);
847 849
848 850 if (!more) {
849 851 nfmt(db, "{0}", NULL);
850 852 } else {
851 - ASSERT3U(nlen(db), >, 1);
853 + VERIFY3U(nlen(db), >, 1);
852 854 nfmt(db, "{1:L}::{0}", "{1:R}");
853 855 }
854 856
855 857 save_top(db, 1);
856 858 more = B_TRUE;
857 859 pop_subs = B_TRUE;
858 860 t = t1;
859 861 continue;
860 862
861 863 case 'I':
862 864 /*
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
863 865 * Must have at least one component before
864 866 * <template-args>
865 867 */
866 868 if (!more)
867 869 return (first);
868 870
869 871 t1 = parse_template_args(t, last, db);
870 872 if (t1 == t || t1 == last)
871 873 return (first);
872 874
873 - ASSERT3U(nlen(db), >, 1);
875 + VERIFY3U(nlen(db), >, 1);
874 876 nfmt(db, "{1:L}{0}", "{1:R}");
875 877 save_top(db, 1);
876 878 t = t1;
877 879 component_ends_with_template_args = B_TRUE;
878 880 continue;
879 881
880 882 case 'L':
881 883 if (t + 1 == last)
882 884 return (first);
883 885 t++;
884 886 continue;
885 887
886 888 default:
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
887 889 break;
888 890 }
889 891
890 892 t1 = parse_unqualified_name(t, last, db);
891 893 if (t1 == t || t1 == last || NAMT(db, n) != 1)
892 894 return (first);
893 895
894 896 if (!more) {
895 897 nfmt(db, "{0}", NULL);
896 898 } else {
897 - ASSERT3U(nlen(db), >, 1);
899 + VERIFY3U(nlen(db), >, 1);
898 900 nfmt(db, "{1:L}::{0}", "{1:R}");
899 901 }
900 902
901 903 save_top(db, 1);
902 904 more = B_TRUE;
903 905 pop_subs = B_TRUE;
904 906 t = t1;
905 907 }
906 908
907 909 /* need to parse at least one thing */
908 910 if (!more)
909 911 return (first);
910 912
911 913 db->cpp_cv = cv;
912 914 if (pop_subs && !sub_empty(&db->cpp_subs))
913 915 sub_pop(&db->cpp_subs);
914 916
915 917 if (ends_with_template_args != NULL)
916 918 *ends_with_template_args = component_ends_with_template_args;
917 919
918 920 if (t[0] != 'E')
919 921 return (first);
920 922
921 923 return (t + 1);
922 924 }
923 925
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
924 926 /*
925 927 * <template-arg> ::= <type> # type or template
926 928 * ::= X <expression> E # expression
927 929 * ::= <expr-primary> # simple expressions
928 930 * ::= J <template-arg>* E # argument pack
929 931 * ::= LZ <encoding> E # extension
930 932 */
931 933 static const char *
932 934 parse_template_arg(const char *first, const char *last, cpp_db_t *db)
933 935 {
934 - ASSERT3P(first, <=, last);
936 + VERIFY3P(first, <=, last);
935 937
936 938 const char *t = NULL;
937 939 const char *t1 = NULL;
938 940
939 941 if (first == last)
940 942 return (first);
941 943
942 944 switch (first[0]) {
943 945 case 'X':
944 946 t = parse_expression(first + 1, last, db);
945 947 if (t == first + 1 || t[0] != 'E')
946 948 return (first);
947 949
948 950 /* E */
949 951 t++;
950 952 break;
951 953
952 954 case 'J':
953 955 t = first + 1;
954 956 if (t == last)
955 957 return (first);
956 958
957 959 while (t[0] != 'E') {
958 960 t1 = parse_template_arg(t, last, db);
959 961 if (t == t1)
960 962 return (first);
961 963 t = t1;
962 964 }
963 965
964 966 /* E */
965 967 t++;
966 968 break;
967 969
968 970 case 'L':
969 971 if (first + 1 == last || first[1] != 'Z') {
970 972 t = parse_expr_primary(first, last, db);
971 973 } else {
972 974 t = parse_encoding(first + 2, last, db);
973 975 if (t == first + 2 || t == last || t[0] != 'E')
974 976 return (first);
975 977
976 978 /* E */
977 979 t++;
978 980 }
979 981 break;
980 982
981 983 default:
982 984 t = parse_type(first, last, db);
983 985 }
984 986
985 987 return (t);
986 988 }
987 989
988 990 /* BEGIN CSTYLED */
989 991 /*
990 992 * <expression> ::= <unary operator-name> <expression>
991 993 * ::= <binary operator-name> <expression> <expression>
992 994 * ::= <ternary operator-name> <expression> <expression> <expression>
993 995 * ::= cl <expression>+ E # call
994 996 * ::= cv <type> <expression> # conversion with one argument
995 997 * ::= cv <type> _ <expression>* E # conversion with a different number of arguments
996 998 * ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
997 999 * ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
998 1000 * ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
999 1001 * ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1000 1002 * ::= [gs] dl <expression> # delete expression
1001 1003 * ::= [gs] da <expression> # delete[] expression
1002 1004 * ::= pp_ <expression> # prefix ++
1003 1005 * ::= mm_ <expression> # prefix --
1004 1006 * ::= ti <type> # typeid (type)
1005 1007 * ::= te <expression> # typeid (expression)
1006 1008 * ::= dc <type> <expression> # dynamic_cast<type> (expression)
1007 1009 * ::= sc <type> <expression> # static_cast<type> (expression)
1008 1010 * ::= cc <type> <expression> # const_cast<type> (expression)
1009 1011 * ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1010 1012 * ::= st <type> # sizeof (a type)
1011 1013 * ::= sz <expression> # sizeof (an expression)
1012 1014 * ::= at <type> # alignof (a type)
1013 1015 * ::= az <expression> # alignof (an expression)
1014 1016 * ::= nx <expression> # noexcept (expression)
1015 1017 * ::= <template-param>
1016 1018 * ::= <function-param>
1017 1019 * ::= dt <expression> <unresolved-name> # expr.name
1018 1020 * ::= pt <expression> <unresolved-name> # expr->name
1019 1021 * ::= ds <expression> <expression> # expr.*expr
1020 1022 * ::= sZ <template-param> # size of a parameter pack
1021 1023 * ::= sZ <function-param> # size of a function parameter pack
1022 1024 * ::= sp <expression> # pack expansion
1023 1025 * ::= tw <expression> # throw expression
1024 1026 * ::= tr # throw with no operand (rethrow)
1025 1027 * ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1026 1028 * # freestanding dependent name (e.g., T::x),
1027 1029 * # objectless nonstatic member reference
1028 1030 * ::= <expr-primary>
1029 1031 */
1030 1032 /* END CSTYLED */
1031 1033
1032 1034 #define PA(cd, arg, fn) { \
1033 1035 .code = cd, \
1034 1036 .p.parse_expr_arg = fn, \
1035 1037 .fntype = EXPR_ARG, \
1036 1038 .val = arg \
1037 1039 }
1038 1040
1039 1041 #define PN(cd, fn) { \
1040 1042 .code = cd, \
1041 1043 .p.parse_expr_noarg = fn, \
1042 1044 .fntype = EXPR_NOARG \
1043 1045 }
1044 1046
1045 1047 static struct {
1046 1048 const char code[3];
1047 1049 union {
1048 1050 const char *(*parse_expr_arg)(const char *, const char *,
1049 1051 const char *, cpp_db_t *);
1050 1052 const char *(*parse_expr_noarg)(const char *, const char *,
1051 1053 cpp_db_t *);
1052 1054 } p;
1053 1055 enum {
1054 1056 EXPR_ARG,
1055 1057 EXPR_NOARG
1056 1058 } fntype;
1057 1059 const char val[4];
1058 1060 } expr_tbl[] = {
1059 1061 PA("aN", "&=", parse_binary_expr),
1060 1062 PA("aS", "=", parse_binary_expr),
1061 1063 PA("aa", "&&", parse_binary_expr),
1062 1064 PA("ad", "&", parse_prefix_expr),
1063 1065 PA("an", "&", parse_binary_expr),
1064 1066 PN("at", parse_alignof),
1065 1067 PN("az", parse_alignof),
1066 1068 PN("cc", parse_cast_expr),
1067 1069 PN("cl", parse_call_expr),
1068 1070 PA("cm", ",", parse_binary_expr),
1069 1071 PA("co", "~", parse_prefix_expr),
1070 1072 PN("cv", parse_conv_expr),
1071 1073 PN("da", parse_del_expr),
1072 1074 PA("dV", "/=", parse_binary_expr),
1073 1075 PN("dc", parse_cast_expr),
1074 1076 PA("de", "*", parse_prefix_expr),
1075 1077 PN("dl", parse_del_expr),
1076 1078 PN("dn", parse_unresolved_name),
1077 1079 PN("ds", parse_dot_star_expr),
1078 1080 PN("dt", parse_dot_expr),
1079 1081 PA("dv", "/", parse_binary_expr),
1080 1082 PA("eO", "^=", parse_binary_expr),
1081 1083 PA("eo", "^", parse_binary_expr),
1082 1084 PA("eq", "==", parse_binary_expr),
1083 1085 PA("ge", ">=", parse_binary_expr),
1084 1086 PN("gs", parse_gs),
1085 1087 PA("gt", ">", parse_binary_expr),
1086 1088 PN("ix", parse_idx_expr),
1087 1089 PA("lS", "<<=", parse_binary_expr),
1088 1090 PA("le", "<=", parse_binary_expr),
1089 1091 PA("ls", "<<", parse_binary_expr),
1090 1092 PA("lt", "<", parse_binary_expr),
1091 1093 PA("mI", "-=", parse_binary_expr),
1092 1094 PA("mL", "*=", parse_binary_expr),
1093 1095 PN("mm", parse_mm_expr),
1094 1096 PA("mi", "-", parse_binary_expr),
1095 1097 PA("ml", "*", parse_binary_expr),
1096 1098 PN("na", parse_new_expr),
1097 1099 PA("ne", "!=", parse_binary_expr),
1098 1100 PA("ng", "-", parse_prefix_expr),
1099 1101 PA("nt", "!", parse_prefix_expr),
1100 1102 PN("nw", parse_new_expr),
1101 1103 PN("nx", parse_noexcept_expr),
1102 1104 PA("oR", "|=", parse_binary_expr),
1103 1105 PN("on", parse_unresolved_name),
1104 1106 PA("oo", "||", parse_binary_expr),
1105 1107 PA("or", "|", parse_binary_expr),
1106 1108 PA("pL", "+=", parse_binary_expr),
1107 1109 PA("pl", "+", parse_binary_expr),
1108 1110 PA("pm", "->*", parse_binary_expr),
1109 1111 PN("pp", parse_pp_expr),
1110 1112 PA("ps", "+", parse_prefix_expr),
1111 1113 PN("pt", parse_arrow_expr),
1112 1114 PN("qu", parse_trinary_expr),
1113 1115 PA("rM", "%=", parse_binary_expr),
1114 1116 PA("rS", ">>=", parse_binary_expr),
1115 1117 PN("rc", parse_cast_expr),
1116 1118 PA("rm", "%", parse_binary_expr),
1117 1119 PA("rs", ">>", parse_binary_expr),
1118 1120 PN("sc", parse_cast_expr),
1119 1121 PN("sp", parse_pack_expansion),
1120 1122 PN("sr", parse_unresolved_name),
1121 1123 PN("st", parse_sizeof),
1122 1124 PN("sz", parse_sizeof),
1123 1125 PN("sZ", parse_sizeof_param_pack_expr),
↓ open down ↓ |
179 lines elided |
↑ open up ↑ |
1124 1126 PN("te", parse_typeid_expr),
1125 1127 PN("tr", parse_throw_expr),
1126 1128 PN("tw", parse_throw_expr)
1127 1129 };
1128 1130 #undef PA
1129 1131 #undef PN
1130 1132
1131 1133 static const char *
1132 1134 parse_expression(const char *first, const char *last, cpp_db_t *db)
1133 1135 {
1134 - ASSERT3P(first, <=, last);
1136 + VERIFY3P(first, <=, last);
1135 1137
1136 1138 if (last - first < 2)
1137 1139 return (first);
1138 1140
1139 1141 for (size_t i = 0; i < ARRAY_SIZE(expr_tbl); i++) {
1140 1142 if (strncmp(expr_tbl[i].code, first, 2) != 0)
1141 1143 continue;
1142 1144 switch (expr_tbl[i].fntype) {
1143 1145 case EXPR_ARG:
1144 1146 return (expr_tbl[i].p.parse_expr_arg(first, last,
1145 1147 expr_tbl[i].val, db));
1146 1148 case EXPR_NOARG:
1147 1149 return (expr_tbl[i].p.parse_expr_noarg(first, last,
1148 1150 db));
1149 1151 }
1150 1152 }
1151 1153
1152 1154 switch (first[0]) {
1153 1155 case 'L':
1154 1156 return (parse_expr_primary(first, last, db));
1155 1157 case 'T':
1156 1158 return (parse_template_param(first, last, db));
1157 1159 case 'f':
1158 1160 return (parse_function_param(first, last, db));
1159 1161 case '1':
1160 1162 case '2':
1161 1163 case '3':
1162 1164 case '4':
1163 1165 case '5':
1164 1166 case '6':
1165 1167 case '7':
1166 1168 case '8':
1167 1169 case '9':
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
1168 1170 return (parse_unresolved_name(first, last, db));
1169 1171 }
1170 1172
1171 1173 return (first);
1172 1174 }
1173 1175
1174 1176 static const char *
1175 1177 parse_binary_expr(const char *first, const char *last, const char *op,
1176 1178 cpp_db_t *db)
1177 1179 {
1178 - ASSERT3P(first, <=, last);
1180 + VERIFY3P(first, <=, last);
1179 1181
1180 1182 if (last - first < 2)
1181 1183 return (first);
1182 1184
1183 1185 size_t n = nlen(db);
1184 1186
1185 1187 const char *t1 = parse_expression(first + 2, last, db);
1186 1188 if (t1 == first + 2)
1187 1189 return (first);
1188 1190
1189 1191 nadd_l(db, op, 0);
1190 1192
1191 1193 const char *t2 = parse_expression(t1, last, db);
1192 1194 if (t2 == t1)
1193 1195 return (first);
1194 1196
1195 1197 if (NAMT(db, n) != 3)
1196 1198 return (first);
1197 1199
1198 - ASSERT3U(nlen(db), >, 2);
1200 + VERIFY3U(nlen(db), >, 2);
1199 1201
1200 1202 nfmt(db, "({2}) {1} ({0})", NULL);
1201 1203 if (strcmp(op, ">") == 0)
1202 1204 nfmt(db, "({0})", NULL);
1203 1205
1204 1206 return (t2);
1205 1207 }
1206 1208
1207 1209 static const char *
1208 1210 parse_prefix_expr(const char *first, const char *last, const char *op,
1209 1211 cpp_db_t *db)
1210 1212 {
1211 - ASSERT3P(first, <=, last);
1213 + VERIFY3P(first, <=, last);
1212 1214
1213 1215 if (last - first < 2)
1214 1216 return (first);
1215 1217
1216 1218 nadd_l(db, op, 0);
1217 1219
1218 1220 const char *t = parse_expression(first + 2, last, db);
1219 1221 if (t == first + 2) {
1220 1222 return (first);
1221 1223 }
1222 1224
1223 - ASSERT3U(nlen(db), >, 1);
1225 + VERIFY3U(nlen(db), >, 1);
1224 1226
1225 1227 nfmt(db, "{1}({0})", NULL);
1226 1228 return (t);
1227 1229 }
1228 1230
1229 1231 static const char *
1230 1232 parse_gs(const char *first, const char *last, cpp_db_t *db)
1231 1233 {
1232 - ASSERT3P(first, <=, last);
1234 + VERIFY3P(first, <=, last);
1233 1235
1234 1236 const char *t = NULL;
1235 1237
1236 1238 if (last - first < 4)
1237 1239 return (first);
1238 1240
1239 1241 if (first[2] == 'n' && (first[3] == 'a' || first[3] == 'w'))
1240 1242 t = parse_new_expr(first + 2, last, db);
1241 1243 else if (first[2] == 'd' && (first[3] == 'l' || first[3] == 'a'))
1242 1244 t = parse_del_expr(first + 2, last, db);
1243 1245 else
1244 1246 return (first);
1245 1247
1246 1248 if (t == first + 2)
1247 1249 return (first);
1248 1250
1249 - ASSERT3U(nlen(db), >, 0);
1251 + VERIFY3U(nlen(db), >, 0);
1250 1252
1251 1253 nfmt(db, "::{0}", NULL);
1252 1254 return (t);
1253 1255 }
1254 1256
1255 1257 /*
1256 1258 * [gs] nw <expression>* _ <type> E # new (expr-list) type
1257 1259 * [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1258 1260 * [gs] na <expression>* _ <type> E # new[] (expr-list) type
1259 1261 * [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1260 1262 * <initializer> ::= pi <expression>* E # parenthesized initialization
1261 1263 */
1262 1264 static const char *
1263 1265 parse_new_expr(const char *first, const char *last, cpp_db_t *db)
1264 1266 {
1265 - ASSERT3P(first, <=, last);
1267 + VERIFY3P(first, <=, last);
1266 1268
1267 1269 /* note [gs] is already handled by parse_gs() */
1268 1270 if (last - first < 3)
1269 1271 return (first);
1270 1272
1271 - ASSERT3U(first[0], ==, 'n');
1272 - ASSERT(first[1] == 'a' || first[1] == 'w');
1273 + VERIFY3U(first[0], ==, 'n');
1274 + VERIFY(first[1] == 'a' || first[1] == 'w');
1273 1275
1274 1276 const char *t1 = first + 2;
1275 1277 const char *t2 = NULL;
1276 1278 size_t n = nlen(db);
1277 1279
1278 1280 nadd_l(db, (first[1] == 'w') ? "new" : "new[]", 0);
1279 1281
1280 1282 while (t1 != last && t1[0] != '_') {
1281 1283 t2 = parse_expression(t1, last, db);
1282 - ASSERT3P(t2, !=, NULL);
1284 + VERIFY3P(t2, !=, NULL);
1283 1285 if (t2 == t1)
1284 1286 return (first);
1285 1287 t1 = t2;
1286 1288 }
1287 1289 if (t1 == last)
1288 1290 return (first);
1289 1291
1290 1292 if (NAMT(db, n) > 1) {
1291 1293 njoin(db, NAMT(db, n) - 1, ", ");
1292 1294 nfmt(db, "({0})", NULL);
1293 1295 }
1294 1296
1295 1297 t2 = parse_type(t1 + 1, last, db);
1296 1298 if (t1 + 1 == t2)
1297 1299 return (first);
1298 1300
1299 1301 if (t2[0] != 'E') {
1300 1302 if (last - t2 < 3)
1301 1303 return (first);
1302 1304 if (t2[0] != 'p' && t2[1] != 'i')
1303 1305 return (first);
1304 1306
1305 1307 t2 += 2;
1306 1308 const char *t3 = t2;
1307 1309 size_t n1 = nlen(db);
1308 1310
1309 1311 while (t2[0] != 'E' && t2 != last) {
1310 1312 t3 = parse_expression(t2, last, db);
1311 1313
1312 1314 if (t2 == t3)
1313 1315 return (first);
1314 1316 t2 = t3;
1315 1317 }
1316 1318 if (t3 == last || t3[0] != 'E')
1317 1319 return (first);
1318 1320
1319 1321 if (NAMT(db, n1) > 0) {
1320 1322 njoin(db, NAMT(db, n1), ", ");
1321 1323 nfmt(db, "({0})", NULL);
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
1322 1324 }
1323 1325 }
1324 1326
1325 1327 njoin(db, NAMT(db, n), " ");
1326 1328 return (t2 + 1);
1327 1329 }
1328 1330
1329 1331 static const char *
1330 1332 parse_del_expr(const char *first, const char *last, cpp_db_t *db)
1331 1333 {
1332 - ASSERT3P(first, <=, last);
1334 + VERIFY3P(first, <=, last);
1333 1335
1334 1336 if (last - first < 3)
1335 1337 return (first);
1336 1338
1337 - ASSERT3U(first[0], ==, 'd');
1338 - ASSERT(first[1] == 'l' || first[1] == 'a');
1339 + VERIFY3U(first[0], ==, 'd');
1340 + VERIFY(first[1] == 'l' || first[1] == 'a');
1339 1341
1340 1342 size_t n = nlen(db);
1341 1343 const char *t = parse_expression(first + 2, last, db);
1342 1344 if (t == first + 2 || NAMT(db, n) != 1)
1343 1345 return (first);
1344 1346
1345 1347 nfmt(db, (first[1] == 'a') ? "delete[] {0}" : "delete {0}", NULL);
1346 1348 return (t);
1347 1349 }
1348 1350
1349 1351 static const char *
1350 1352 parse_idx_expr(const char *first, const char *last, cpp_db_t *db)
1351 1353 {
1352 - ASSERT3P(first, <=, last);
1353 - ASSERT3U(first[0], ==, 'i');
1354 - ASSERT3U(first[1], ==, 'x');
1354 + VERIFY3P(first, <=, last);
1355 + VERIFY3U(first[0], ==, 'i');
1356 + VERIFY3U(first[1], ==, 'x');
1355 1357
1356 1358 size_t n = nlen(db);
1357 1359 const char *t1 = parse_expression(first + 2, last, db);
1358 1360 if (t1 == first + 2)
1359 1361 return (first);
1360 1362
1361 1363 const char *t2 = parse_expression(t1, last, db);
1362 1364 if (t2 == t1 || NAMT(db, n) != 2)
1363 1365 return (first);
1364 1366
1365 1367 nfmt(db, "({0})[{1}]", NULL);
1366 1368 return (t2);
1367 1369 }
1368 1370
1369 1371 static const char *
1370 1372 parse_ppmm_expr(const char *first, const char *last, const char *fmt,
1371 1373 cpp_db_t *db)
1372 1374 {
1373 - ASSERT3P(first, <=, last);
1375 + VERIFY3P(first, <=, last);
1374 1376
1375 1377 if (last - first < 3)
1376 1378 return (first);
1377 1379
1378 1380 const char *t = NULL;
1379 1381 size_t n = nlen(db);
1380 1382
1381 1383 if (first[2] == '_') {
1382 1384 t = parse_binary_expr(first + 3, last, "--", db);
1383 1385 if (t == first + 3)
1384 1386 return (first);
1385 1387 return (t);
1386 1388 }
1387 1389
1388 1390 t = parse_expression(first + 2, last, db);
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1389 1391 if (t == first + 2 || NAMT(db, n) < 1)
1390 1392 return (first);
1391 1393
1392 1394 nfmt(db, fmt, NULL);
1393 1395 return (t);
1394 1396 }
1395 1397
1396 1398 static const char *
1397 1399 parse_mm_expr(const char *first, const char *last, cpp_db_t *db)
1398 1400 {
1399 - ASSERT3P(first, <=, last);
1400 - ASSERT3U(first[0], ==, 'm');
1401 - ASSERT3U(first[1], ==, 'm');
1401 + VERIFY3P(first, <=, last);
1402 + VERIFY3U(first[0], ==, 'm');
1403 + VERIFY3U(first[1], ==, 'm');
1402 1404
1403 1405 return (parse_ppmm_expr(first, last, "({0})--", db));
1404 1406 }
1405 1407
1406 1408 static const char *
1407 1409 parse_pp_expr(const char *first, const char *last, cpp_db_t *db)
1408 1410 {
1409 - ASSERT3P(first, <=, last);
1411 + VERIFY3P(first, <=, last);
1410 1412
1411 - ASSERT3U(first[0], ==, 'p');
1412 - ASSERT3U(first[0], ==, 'p');
1413 + VERIFY3U(first[0], ==, 'p');
1414 + VERIFY3U(first[0], ==, 'p');
1413 1415
1414 1416 return (parse_ppmm_expr(first, last, "({0})++", db));
1415 1417 }
1416 1418
1417 1419 static const char *
1418 1420 parse_trinary_expr(const char *first, const char *last, cpp_db_t *db)
1419 1421 {
1420 - ASSERT3P(first, <=, last);
1422 + VERIFY3P(first, <=, last);
1421 1423
1422 1424 const char *t1, *t2, *t3;
1423 1425 size_t n = nlen(db);
1424 1426
1425 1427 if (last - first < 2)
1426 1428 return (first);
1427 1429
1428 1430 t1 = parse_expression(first + 2, last, db);
1429 1431 if (t1 == first + 2)
1430 1432 return (first);
1431 1433 t2 = parse_expression(t1, last, db);
1432 1434 if (t1 == t2)
1433 1435 return (first);
1434 1436 t3 = parse_expression(t2, last, db);
1435 1437 if (t3 == t2)
1436 1438 return (first);
1437 1439
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
1438 1440 if (NAMT(db, n) != 3)
1439 1441 return (first);
1440 1442
1441 1443 nfmt(db, "({2}) ? ({1}) : ({0})", NULL);
1442 1444 return (t3);
1443 1445 }
1444 1446
1445 1447 static const char *
1446 1448 parse_noexcept_expr(const char *first, const char *last, cpp_db_t *db)
1447 1449 {
1448 - ASSERT3P(first, <=, last);
1450 + VERIFY3P(first, <=, last);
1449 1451
1450 1452 if (last - first < 2)
1451 1453 return (first);
1452 1454
1453 1455 size_t n = nlen(db);
1454 1456 const char *t = parse_expression(first + 2, last, db);
1455 1457 if (t == first + 2 || NAMT(db, n) != 1)
1456 1458 return (first);
1457 1459
1458 1460 nfmt(db, "noexcept ({0})", NULL);
1459 1461 return (t);
1460 1462 }
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1461 1463
1462 1464 /*
1463 1465 * cc <type> <expression> # const_cast<type> (expression)
1464 1466 * dc <type> <expression> # dynamic_cast<type> (expression)
1465 1467 * rc <type> <expression> # reinterpret_cast<type> (expression)
1466 1468 * sc <type> <expression> # static_cast<type> (expression)
1467 1469 */
1468 1470 static const char *
1469 1471 parse_cast_expr(const char *first, const char *last, cpp_db_t *db)
1470 1472 {
1471 - ASSERT3P(first, <=, last);
1473 + VERIFY3P(first, <=, last);
1472 1474
1473 1475 if (last - first < 2)
1474 1476 return (first);
1475 1477
1476 1478 const char *fmt = NULL;
1477 1479 switch (first[0]) {
1478 1480 case 'c':
1479 1481 fmt = "const_cast<{1}> ({0})";
1480 1482 break;
1481 1483 case 'd':
1482 1484 fmt = "dynamic_cast<{1}> ({0})";
1483 1485 break;
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1484 1486 case 'r':
1485 1487 fmt = "reinterpret_cast<{1}> ({0})";
1486 1488 break;
1487 1489 case 's':
1488 1490 fmt = "static_cast<{1}> ({0})";
1489 1491 break;
1490 1492 default:
1491 1493 return (first);
1492 1494 }
1493 1495
1494 - ASSERT3U(first[1], ==, 'c');
1496 + VERIFY3U(first[1], ==, 'c');
1495 1497
1496 1498 const char *t1 = parse_type(first + 2, last, db);
1497 1499 if (t1 == first + 2)
1498 1500 return (first);
1499 1501
1500 1502 const char *t2 = parse_expression(t1, last, db);
1501 1503 if (t2 == t1)
1502 1504 return (first);
1503 1505
1504 - ASSERT3U(nlen(db), >, 1);
1506 + VERIFY3U(nlen(db), >, 1);
1505 1507
1506 1508 nfmt(db, fmt, NULL);
1507 1509 return (t2);
1508 1510 }
1509 1511
1510 1512 /* pt <expression> <expression> # expr->name */
1511 1513 static const char *
1512 1514 parse_arrow_expr(const char *first, const char *last, cpp_db_t *db)
1513 1515 {
1514 - ASSERT3P(first, <=, last);
1516 + VERIFY3P(first, <=, last);
1515 1517
1516 1518 if (last - first < 4)
1517 1519 return (first);
1518 1520
1519 1521 size_t n = nlen(db);
1520 1522
1521 1523 const char *t1 = parse_expression(first + 2, last, db);
1522 1524 if (t1 == first + 2)
1523 1525 return (first);
1524 1526
1525 1527 const char *t2 = parse_expression(t1, last, db);
1526 1528 if (t2 == t1 || NAMT(db, n) != 2)
1527 1529 return (first);
1528 1530
1529 1531 nfmt(db, "{1}->{0}", NULL);
1530 1532 return (t2);
1531 1533 }
1532 1534
1533 1535 /* wrap value in () when necessary */
1534 1536 static void
1535 1537 paren(str_pair_t *sp)
1536 1538 {
1537 1539 str_t *l = &sp->strp_l;
1538 1540 str_t *r = &sp->strp_r;
1539 1541
1540 1542 if (str_length(r) > 1 &&
1541 1543 r->str_s[0] == ' ' && r->str_s[1] == '[') {
1542 1544 str_append(l, " (", 2);
1543 1545 str_insert(r, 0, ")", 1);
1544 1546 } else if (str_length(r) > 0 && r->str_s[0] == '(') {
1545 1547 str_append(l, "(", 1);
1546 1548 str_insert(r, 0, ")", 1);
1547 1549 }
1548 1550 }
1549 1551
1550 1552 /* BEGIN CSTYLED */
1551 1553 /*
1552 1554 * <type> ::= <builtin-type>
1553 1555 * ::= <function-type>
1554 1556 * ::= <class-enum-type>
1555 1557 * ::= <array-type>
1556 1558 * ::= <pointer-to-member-type>
1557 1559 * ::= <template-param>
1558 1560 * ::= <template-template-param> <template-args>
1559 1561 * ::= <decltype>
1560 1562 * ::= <substitution>
1561 1563 * ::= <CV-qualifiers> <type>
1562 1564 * ::= P <type> # pointer-to
1563 1565 * ::= R <type> # reference-to
1564 1566 * ::= O <type> # rvalue reference-to (C++0x)
1565 1567 * ::= C <type> # complex pair (C 2000)
1566 1568 * ::= G <type> # imaginary (C 2000)
1567 1569 * ::= Dp <type> # pack expansion (C++0x)
1568 1570 * ::= U <source-name> <type> # vendor extended type qualifier
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
1569 1571 * extension := U <objc-name> <objc-type> # objc-type<identifier>
1570 1572 * extension := <vector-type> # <vector-type> starts with Dv
1571 1573 *
1572 1574 * <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1573 1575 * <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1574 1576 */
1575 1577 /* END CSTYLED */
1576 1578 static const char *
1577 1579 parse_type(const char *first, const char *last, cpp_db_t *db)
1578 1580 {
1579 - ASSERT3P(first, <=, last);
1581 + VERIFY3P(first, <=, last);
1580 1582
1581 1583 if (first == last)
1582 1584 return (first);
1583 1585
1584 1586 switch (first[0]) {
1585 1587 case 'r':
1586 1588 case 'V':
1587 1589 case 'K':
1588 1590 return (parse_qual_type(first, last, db));
1589 1591 }
1590 1592
1591 1593 const char *t = first;
1592 1594 const char *t1 = NULL;
1593 1595 str_pair_t *sp = NULL;
1594 1596 size_t n = nlen(db);
1595 1597 size_t amt = 0;
1596 1598
1597 1599 t = parse_builtin_type(first, last, db);
1598 1600 if (t != first)
1599 1601 return (t);
1600 1602
1601 1603 switch (first[0]) {
1602 1604 case 'A':
1603 1605 t = parse_array_type(first, last, db);
1604 1606 if (t == first || NAMT(db, n) == 0)
1605 1607 return (first);
1606 1608 save_top(db, 1);
1607 1609 return (t);
1608 1610
1609 1611 case 'C':
1610 1612 t = parse_type(first + 1, last, db);
1611 1613 if (t == first + 1 || NAMT(db, n) == 0)
1612 1614 return (first);
1613 1615
1614 1616 str_append(TOP_L(db), " complex", 8);
1615 1617 save_top(db, 1);
1616 1618 return (t);
1617 1619
1618 1620 case 'F':
1619 1621 t = parse_function_type(first, last, db);
1620 1622 if (t == first || NAMT(db, n) == 0)
1621 1623 return (first);
1622 1624 save_top(db, 1);
1623 1625 return (t);
1624 1626
1625 1627 case 'G':
1626 1628 t = parse_type(first + 1, last, db);
1627 1629 if (t == first + 1 || NAMT(db, n) == 0)
1628 1630 return (first);
1629 1631
1630 1632 str_append(TOP_L(db), " imaginary", 10);
1631 1633 save_top(db, 1);
1632 1634 return (t);
1633 1635
1634 1636 case 'M':
1635 1637 t = parse_pointer_to_member_type(first, last, db);
1636 1638 if (t == first || NAMT(db, n) == 0)
1637 1639 return (first);
1638 1640 save_top(db, 1);
1639 1641 return (t);
1640 1642
1641 1643 case 'O':
1642 1644 t = parse_type(first + 1, last, db);
1643 1645 amt = NAMT(db, n);
1644 1646 if (t == first + 1 || amt == 0)
1645 1647 return (first);
1646 1648
1647 1649 sp = name_at(&db->cpp_name, amt - 1);
1648 1650 for (size_t i = 0; i < amt; i++, sp++) {
1649 1651 paren(sp);
1650 1652 if (str_pair_len(sp) > 0)
1651 1653 str_append(&sp->strp_l, "&&", 2);
1652 1654 }
1653 1655
1654 1656 save_top(db, amt);
1655 1657 return (t);
1656 1658
1657 1659 case 'P':
1658 1660 t = parse_type(first + 1, last, db);
1659 1661 amt = NAMT(db, n);
1660 1662 if (t == first + 1 || amt == 0)
1661 1663 return (first);
1662 1664
1663 1665 sp = name_at(&db->cpp_name, amt - 1);
1664 1666 for (size_t i = 0; i < amt; i++, sp++) {
1665 1667 str_t *l = &sp->strp_l;
1666 1668
1667 1669 if (str_pair_len(sp) == 0)
1668 1670 continue;
1669 1671
1670 1672 paren(sp);
1671 1673 if (first[1] != 'U' ||
1672 1674 strncmp(l->str_s, "objc_object<", 12) != 0) {
1673 1675 str_append(l, "*", 1);
1674 1676 } else {
1675 1677 str_erase(l, 0, 11);
1676 1678 str_insert(l, 0, "id", 2);
1677 1679 }
1678 1680 }
1679 1681 save_top(db, amt);
1680 1682 return (t);
1681 1683
1682 1684 case 'R':
1683 1685 t = parse_type(first + 1, last, db);
1684 1686 amt = NAMT(db, n);
1685 1687 if (t == first + 1 || amt == 0)
1686 1688 return (first);
1687 1689
1688 1690 sp = name_at(&db->cpp_name, amt - 1);
1689 1691 for (size_t i = 0; i < amt; i++, sp++) {
1690 1692 if (str_length(&sp->strp_l) == 0 &&
1691 1693 str_length(&sp->strp_r) == 0)
1692 1694 continue;
1693 1695
1694 1696 paren(sp);
1695 1697 str_append(&sp->strp_l, "&", 1);
1696 1698 }
1697 1699
1698 1700 save_top(db, amt);
1699 1701 return (t);
1700 1702
1701 1703 case 'T':
1702 1704 t = parse_template_param(first, last, db);
1703 1705 if (t == first)
1704 1706 return (first);
1705 1707
1706 1708 amt = NAMT(db, n);
1707 1709 save_top(db, amt);
1708 1710 if (!db->cpp_try_to_parse_template_args || amt != 1)
1709 1711 return (t);
1710 1712
1711 1713 t1 = parse_template_args(t, last, db);
1712 1714 if (t1 == t)
1713 1715 return (t);
1714 1716
1715 1717 nfmt(db, "{1:L}{0}", "{1:R}");
1716 1718 save_top(db, 1);
1717 1719 return (t1);
1718 1720
1719 1721 case 'U':
1720 1722 if (first + 1 == last)
1721 1723 return (first);
1722 1724
1723 1725 t = parse_source_name(first + 1, last, db);
1724 1726 if (t == first + 1)
1725 1727 return (first);
1726 1728
1727 1729 nfmt(db, "{0}", NULL);
1728 1730
1729 1731 t1 = parse_type(t, last, db);
1730 1732 if (t1 == t || NAMT(db, n) < 2)
1731 1733 return (first);
1732 1734
1733 1735 const str_t *name = &name_at(&db->cpp_name, 1)->strp_l;
1734 1736
1735 1737 if (str_length(name) > 0 &&
↓ open down ↓ |
146 lines elided |
↑ open up ↑ |
1736 1738 strncmp(name->str_s, "objcproto", 9) != 0) {
1737 1739 nfmt(db, "{0} {1}", NULL);
1738 1740 } else {
1739 1741 t = parse_source_name(name->str_s + 9,
1740 1742 name->str_s + name->str_len, db);
1741 1743 if (t != name->str_s + 9) {
1742 1744 nfmt(db, "{1}<{0}>", NULL);
1743 1745
1744 1746 str_pair_t save = {0};
1745 1747
1746 - (void) name_pop(&db->cpp_name, &save);
1748 + name_pop(&db->cpp_name, &save);
1747 1749
1748 1750 /* get rid of 'objcproto' */
1749 - (void) name_pop(&db->cpp_name, NULL);
1751 + name_pop(&db->cpp_name, NULL);
1750 1752 CK(name_add_str(&db->cpp_name, &save.strp_l,
1751 1753 &save.strp_r));
1752 1754 } else {
1753 1755 nfmt(db, "{1} {0}", NULL);
1754 1756 }
1755 1757 }
1756 1758
1757 1759 save_top(db, 1);
1758 1760 return (t1);
1759 1761
1760 1762 case 'S':
1761 1763 if (first + 1 != last && first[1] == 't') {
1762 1764 t = parse_name(first, last, NULL, db);
1763 1765 if (t == first || NAMT(db, n) == 0)
1764 1766 return (first);
1765 1767
1766 1768 save_top(db, 1);
1767 1769 return (t);
1768 1770 }
1769 1771
1770 1772 t = parse_substitution(first, last, db);
1771 1773 if (t == first)
1772 1774 return (first);
1773 1775
1774 1776 /*
1775 1777 * If the substitution is a <template-param>, it might
1776 1778 * be followed by <template-args>
1777 1779 */
1778 1780 t1 = parse_template_args(t, last, db);
1779 1781 if (t1 == t)
1780 1782 return (t);
1781 1783
1782 1784 if (NAMT(db, n) < 2)
1783 1785 return (t);
1784 1786
1785 1787 nfmt(db, "{1:L}{0}", "{1:R}");
1786 1788 save_top(db, 1);
1787 1789 return (t1);
1788 1790
1789 1791 case 'D':
1790 1792 if (first + 1 == last)
1791 1793 return (first);
1792 1794
1793 1795 switch (first[1]) {
1794 1796 case 'p':
1795 1797 t = parse_type(first + 2, last, db);
1796 1798 if (t == first + 2)
1797 1799 break;
1798 1800
1799 1801 save_top(db, NAMT(db, n));
1800 1802 return (t);
1801 1803
1802 1804 case 't':
1803 1805 case 'T':
1804 1806 t = parse_decltype(first, last, db);
1805 1807 if (first == t)
1806 1808 break;
1807 1809
1808 1810 save_top(db, 1);
1809 1811 return (t);
1810 1812
1811 1813 case 'v':
1812 1814 t = parse_vector_type(first, last, db);
1813 1815 if (first == t)
1814 1816 break;
1815 1817
1816 1818 if (NAMT(db, n) == 0)
1817 1819 return (first);
1818 1820
1819 1821 save_top(db, 1);
1820 1822 return (t);
1821 1823 }
1822 1824 break;
1823 1825 }
1824 1826
1825 1827 /*
1826 1828 * must check for builtin-types before class-enum-types to avoid
1827 1829 * ambiguities with operator-names
1828 1830 */
1829 1831 t = parse_builtin_type(first, last, db);
1830 1832 if (t != first)
1831 1833 return (t);
1832 1834
1833 1835 t = parse_name(first, last, NULL, db);
↓ open down ↓ |
74 lines elided |
↑ open up ↑ |
1834 1836 if (t == first || NAMT(db, n) == 0)
1835 1837 return (first);
1836 1838
1837 1839 save_top(db, 1);
1838 1840 return (t);
1839 1841 }
1840 1842
1841 1843 static const char *
1842 1844 parse_qual_type(const char *first, const char *last, cpp_db_t *db)
1843 1845 {
1844 - ASSERT3P(first, <=, last);
1846 + VERIFY3P(first, <=, last);
1845 1847
1846 1848 const char *t = NULL;
1847 1849 const char *t1 = NULL;
1848 1850 unsigned cv = 0;
1849 1851
1850 1852 t = parse_cv_qualifiers(first, last, &cv);
1851 1853 if (t == first)
1852 1854 return (first);
1853 1855
1854 1856 size_t n = nlen(db);
1855 1857 boolean_t is_func = !!(t[0] == 'F');
1856 1858
1857 1859 t1 = parse_type(t, last, db);
1858 1860 size_t amt = NAMT(db, n);
1859 1861 if (t == t1 || amt == 0)
1860 1862 return (first);
1861 1863
1862 1864 if (is_func)
1863 1865 sub_pop(&db->cpp_subs);
1864 1866
1865 1867 str_pair_t *sp = name_at(&db->cpp_name, amt - 1);
1866 1868
1867 1869 for (size_t i = 0; i < amt; i++, sp++) {
1868 1870 str_t *s = NULL;
1869 1871
1870 1872 if (!is_func) {
1871 1873 s = &sp->strp_l;
1872 1874
1873 1875 if (str_length(s) == 0)
1874 1876 continue;
1875 1877
1876 1878 if (cv & 1)
1877 1879 str_append(s, " const", 6);
1878 1880 if (cv & 2)
1879 1881 str_append(s, " volatile", 9);
1880 1882 if (cv & 4)
1881 1883 str_append(s, " restrict", 9);
1882 1884
1883 1885 continue;
1884 1886 }
1885 1887
1886 1888 s = &sp->strp_r;
1887 1889 size_t pos = str_length(s);
1888 1890
1889 1891 if (pos > 0 && s->str_s[pos - 1] == '&') {
1890 1892 pos--;
1891 1893 if (s->str_s[pos - 1] == '&')
1892 1894 pos--;
1893 1895 }
1894 1896
1895 1897 if (cv & 1) {
1896 1898 str_insert(s, pos, " const", 6);
1897 1899 pos += 6;
1898 1900 }
1899 1901 if (cv & 2) {
1900 1902 str_insert(s, pos, " volatile", 9);
1901 1903 pos += 9;
1902 1904 }
1903 1905 if (cv & 4) {
1904 1906 str_insert(s, pos, " restrict", 9);
1905 1907 }
1906 1908 }
1907 1909
1908 1910 save_top(db, amt);
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
1909 1911 return (t1);
1910 1912 }
1911 1913
1912 1914 /*
1913 1915 * at <type> # alignof (a type)
1914 1916 * az <expression> # alignof (a expression)
1915 1917 */
1916 1918 static const char *
1917 1919 parse_alignof(const char *first, const char *last, cpp_db_t *db)
1918 1920 {
1919 - ASSERT3P(first, <=, last);
1921 + VERIFY3P(first, <=, last);
1920 1922
1921 1923 if (last - first < 2)
1922 1924 return (first);
1923 1925
1924 1926 const char *(*fn)(const char *, const char *, cpp_db_t *);
1925 1927
1926 1928 fn = (first[1] == 't') ? parse_type : parse_expression;
1927 1929
1928 1930 size_t n = nlen(db);
1929 1931 const char *t = fn(first + 2, last, db);
1930 1932 if (t == first + 2 || NAMT(db, n) != 1)
1931 1933 return (first);
1932 1934
1933 1935 nfmt(db, "alignof ({0})", NULL);
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
1934 1936 return (t);
1935 1937 }
1936 1938
1937 1939 /*
1938 1940 * st <type> # sizeof (a type)
1939 1941 * sz <expr> # sizeof (a expression)
1940 1942 */
1941 1943 static const char *
1942 1944 parse_sizeof(const char *first, const char *last, cpp_db_t *db)
1943 1945 {
1944 - ASSERT3P(first, <=, last);
1946 + VERIFY3P(first, <=, last);
1945 1947
1946 1948 if (last - first < 2)
1947 1949 return (first);
1948 1950
1949 - ASSERT3U(first[0], ==, 's');
1951 + VERIFY3U(first[0], ==, 's');
1950 1952
1951 1953 const char *t = NULL;
1952 1954 size_t n = nlen(db);
1953 1955
1954 1956 switch (first[1]) {
1955 1957 case 't':
1956 1958 t = parse_type(first + 2, last, db);
1957 1959 break;
1958 1960 case 'z':
1959 1961 t = parse_expression(first + 2, last, db);
1960 1962 break;
1961 1963 default:
1962 1964 return (first);
1963 1965 }
1964 1966 if (t == first + 2 || NAMT(db, n) != 1)
1965 1967 return (first);
1966 1968
1967 1969 nfmt(db, "sizeof ({0})", NULL);
1968 1970 return (t);
1969 1971 }
1970 1972
1971 1973 /* BEGIN CSTYLED */
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1972 1974 /*
1973 1975 * <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
1974 1976 * ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
1975 1977 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
1976 1978 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
1977 1979 */
1978 1980 /* END CSTYLED */
1979 1981 static const char *
1980 1982 parse_function_param(const char *first, const char *last, cpp_db_t *db)
1981 1983 {
1982 - ASSERT3P(first, <=, last);
1984 + VERIFY3P(first, <=, last);
1983 1985
1984 1986 if (last - first < 3 || first[0] != 'f')
1985 1987 return (first);
1986 1988
1987 1989 const char *t1 = first + 2;
1988 1990 const char *t2 = NULL;
1989 1991 unsigned cv = 0;
1990 1992
1991 1993 if (first[1] == 'L') {
1992 - t2 = parse_number(t1, last);
1994 + t2 = parse_number(t1, last, db->cpp_loc);
1993 1995 if (t2 == last || t2[0] != 'p')
1994 1996 return (first);
1995 1997 t1 = t2;
1996 1998 }
1997 1999
1998 2000 if (first[1] != 'p')
1999 2001 return (first);
2000 2002
2001 2003 t1 = parse_cv_qualifiers(t1, last, &cv);
2002 - t2 = parse_number(t1, last);
2004 + t2 = parse_number(t1, last, db->cpp_loc);
2003 2005 if (t2 == last || t2[0] != '_')
2004 2006 return (first);
2005 2007
2006 2008 if (t2 - t1 > 0)
2007 2009 nadd_l(db, t1, (size_t)(t2 - t1));
2008 2010 else
2009 2011 nadd_l(db, "", 0);
2010 2012
2011 2013 nfmt(db, "fp{0}", NULL);
2012 2014 return (t2 + 1);
2013 2015 }
2014 2016
2015 2017 /*
2016 2018 * sZ <template-param> # size of a parameter pack
2017 2019 * sZ <function-param> # size of a function parameter pack
2018 2020 */
2019 2021 static const char *
2020 2022 parse_sizeof_param_pack_expr(const char *first, const char *last, cpp_db_t *db)
2021 2023 {
2022 - ASSERT3P(first, <=, last);
2024 + VERIFY3P(first, <=, last);
2023 2025
2024 2026 if (last - first < 3)
2025 2027 return (first);
2026 2028
2027 - ASSERT3U(first[0], ==, 's');
2028 - ASSERT3U(first[1], ==, 'Z');
2029 + VERIFY3U(first[0], ==, 's');
2030 + VERIFY3U(first[1], ==, 'Z');
2029 2031
2030 2032 if (first[2] != 'T' && first[2] != 'f')
2031 2033 return (first);
2032 2034
2033 2035 const char *t = NULL;
2034 2036 size_t n = nlen(db);
2035 2037
2036 2038 if (first[2] == 'T')
2037 2039 t = parse_template_param(first + 2, last, db);
2038 2040 else
2039 2041 t = parse_function_param(first + 2, last, db);
2040 2042
2041 2043 if (t == first + 2)
2042 2044 return (first);
2043 2045
2044 2046 njoin(db, NAMT(db, n), ", ");
2045 2047 nfmt(db, "sizeof...({0})", NULL);
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
2046 2048 return (t);
2047 2049 }
2048 2050
2049 2051 /*
2050 2052 * te <expression> # typeid (expression)
2051 2053 * ti <type> # typeid (type)
2052 2054 */
2053 2055 static const char *
2054 2056 parse_typeid_expr(const char *first, const char *last, cpp_db_t *db)
2055 2057 {
2056 - ASSERT3P(first, <=, last);
2058 + VERIFY3P(first, <=, last);
2057 2059
2058 2060 if (last - first < 3)
2059 2061 return (first);
2060 2062
2061 - ASSERT3U(first[0], ==, 't');
2062 - ASSERT(first[1] == 'e' || first[1] == 'i');
2063 + VERIFY3U(first[0], ==, 't');
2064 + VERIFY(first[1] == 'e' || first[1] == 'i');
2063 2065
2064 2066 const char *t = NULL;
2065 2067 size_t n = nlen(db);
2066 2068
2067 2069 if (first[1] == 'e')
2068 2070 t = parse_expression(first + 2, last, db);
2069 2071 else
2070 2072 t = parse_type(first + 2, last, db);
2071 2073
2072 2074 if (t == first + 2 || NAMT(db, n) != 1)
2073 2075 return (first);
2074 2076
2075 2077 nfmt(db, "typeid ({0})", NULL);
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
2076 2078 return (t);
2077 2079 }
2078 2080
2079 2081 /*
2080 2082 * tr # throw
2081 2083 * tw <expression> # throw expression
2082 2084 */
2083 2085 static const char *
2084 2086 parse_throw_expr(const char *first, const char *last, cpp_db_t *db)
2085 2087 {
2086 - ASSERT3P(first, <=, last);
2088 + VERIFY3P(first, <=, last);
2087 2089
2088 2090 if (last - first < 3)
2089 2091 return (first);
2090 2092
2091 - ASSERT3U(first[0], ==, 't');
2092 - ASSERT(first[1] == 'w' || first[1] == 'r');
2093 + VERIFY3U(first[0], ==, 't');
2094 + VERIFY(first[1] == 'w' || first[1] == 'r');
2093 2095
2094 2096 if (first[1] == 'r') {
2095 2097 nadd_l(db, "throw", 0);
2096 2098 return (first + 2);
2097 2099 }
2098 2100
2099 2101 size_t n = nlen(db);
2100 2102 const char *t = parse_expression(first + 2, last, db);
2101 2103 if (t == first + 2 || NAMT(db, n) != 1)
2102 2104 return (first);
2103 2105
2104 2106 nfmt(db, "throw {0}", NULL);
2105 2107 return (t);
2106 2108 }
2107 2109
2108 2110 /* ds <expression> <expression> # expr.*expr */
2109 2111 static const char *
2110 2112 parse_dot_star_expr(const char *first, const char *last, cpp_db_t *db)
2111 2113 {
2112 - ASSERT3P(first, <=, last);
2114 + VERIFY3P(first, <=, last);
2113 2115
2114 2116 if (last - first < 3)
2115 2117 return (first);
2116 2118
2117 - ASSERT3U(first[0], ==, 'd');
2118 - ASSERT3U(first[1], ==, 's');
2119 + VERIFY3U(first[0], ==, 'd');
2120 + VERIFY3U(first[1], ==, 's');
2119 2121
2120 2122 size_t n = nlen(db);
2121 2123 const char *t = parse_expression(first + 2, last, db);
2122 2124 if (t == first + 2)
2123 2125 return (first);
2124 2126
2125 2127 const char *t2 = parse_expression(t, last, db);
2126 2128 if (t == t2 || NAMT(db, n) != 2)
2127 2129 return (first);
2128 2130
2129 2131 nfmt(db, "{1}.*{0}", NULL);
2130 2132 return (t2);
2131 2133 }
2132 2134
2133 2135 /* dt <expression> <unresolved-name> # expr.name */
2134 2136 static const char *
2135 2137 parse_dot_expr(const char *first, const char *last, cpp_db_t *db)
2136 2138 {
2137 - ASSERT3P(first, <=, last);
2139 + VERIFY3P(first, <=, last);
2138 2140
2139 2141 if (last - first < 3)
2140 2142 return (first);
2141 2143
2142 - ASSERT3U(first[0], ==, 'd');
2143 - ASSERT3U(first[1], ==, 't');
2144 + VERIFY3U(first[0], ==, 'd');
2145 + VERIFY3U(first[1], ==, 't');
2144 2146
2145 2147 const char *t = parse_expression(first + 2, last, db);
2146 2148 if (t == first + 2)
2147 2149 return (first);
2148 2150
2149 2151 const char *t1 = parse_unresolved_name(t, last, db);
2150 2152 if (t1 == t)
2151 2153 return (first);
2152 2154
2153 2155 nfmt(db, "{1}.{0}", NULL);
2154 2156 return (t1);
2155 2157 }
2156 2158
2157 2159 /* cl <expression>+ E # call */
2158 2160 static const char *
2159 2161 parse_call_expr(const char *first, const char *last, cpp_db_t *db)
2160 2162 {
2161 - ASSERT3P(first, <=, last);
2163 + VERIFY3P(first, <=, last);
2162 2164
2163 2165 if (last - first < 4)
2164 2166 return (first);
2165 2167
2166 - ASSERT3U(first[0], ==, 'c');
2167 - ASSERT3U(first[1], ==, 'l');
2168 + VERIFY3U(first[0], ==, 'c');
2169 + VERIFY3U(first[1], ==, 'l');
2168 2170
2169 2171 const char *t = first + 2;
2170 2172 const char *t1 = NULL;
2171 2173 size_t n = nlen(db);
2172 2174
2173 2175 for (t = first + 2; t != last && t[0] != 'E'; t = t1) {
2174 2176 t1 = parse_expression(t, last, db);
2175 2177 if (t1 == t)
2176 2178 return (first);
2177 2179 }
2178 2180
2179 2181 size_t amt = NAMT(db, n);
2180 2182
2181 2183 if (t == last || amt == 0)
2182 2184 return (first);
2183 2185
2184 2186 njoin(db, amt - 1, ", ");
2185 2187 nfmt(db, "{1}({0})", NULL);
2186 2188
2187 - ASSERT3U(t[0], ==, 'E');
2189 + VERIFY3U(t[0], ==, 'E');
2188 2190 return (t + 1);
2189 2191 }
2190 2192
2191 2193 /* BEGIN CSTYLED */
2192 2194 /*
2193 2195 * cv <type> <expression> # conversion with one argument
2194 2196 * cv <type> _ <expression>* E # conversion with a different number of arguments
2195 2197 */
2196 2198 /* END CSTYLED */
2197 2199 static const char *
2198 2200 parse_conv_expr(const char *first, const char *last, cpp_db_t *db)
2199 2201 {
2200 - ASSERT3P(first, <=, last);
2202 + VERIFY3P(first, <=, last);
2201 2203
2202 2204 if (last - first < 3)
2203 2205 return (first);
2204 2206
2205 - ASSERT3U(first[0], ==, 'c');
2206 - ASSERT3U(first[1], ==, 'v');
2207 + VERIFY3U(first[0], ==, 'c');
2208 + VERIFY3U(first[1], ==, 'v');
2207 2209
2208 2210 const char *t = NULL;
2209 2211 const char *t1 = NULL;
2210 2212 size_t n = nlen(db);
2211 2213
2212 2214 boolean_t try_to_parse_template_args =
2213 2215 db->cpp_try_to_parse_template_args;
2214 2216
2215 2217 db->cpp_try_to_parse_template_args = B_FALSE;
2216 2218 t = parse_type(first + 2, last, db);
2217 2219 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
2218 2220
2219 2221 if (t == first + 2)
2220 2222 return (first);
2221 2223
2222 2224 if (t[0] != '_') {
2223 2225 t1 = parse_expression(t, last, db);
2224 2226 if (t1 == t)
2225 2227 return (first);
2226 2228
2227 2229 t = t1;
2228 2230 } else {
2229 2231 size_t n1 = nlen(db);
2230 2232
2231 2233 /* skip _ */
2232 2234 t++;
2233 2235 while (t[0] != 'E' && t != last) {
2234 2236 t1 = parse_expression(t, last, db);
2235 2237 if (t1 == t)
2236 2238 return (first);
2237 2239 t1 = t;
2238 2240 }
2239 2241
2240 2242 /* E */
2241 2243 t++;
2242 2244
2243 2245 njoin(db, NAMT(db, n1), ", ");
2244 2246 }
2245 2247
2246 2248 if (NAMT(db, n) < 2)
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
2247 2249 return (first);
2248 2250
2249 2251 nfmt(db, "({1})({0})", NULL);
2250 2252 return (t);
2251 2253 }
2252 2254
2253 2255 /* <simple-id> ::= <source-name> [ <template-args> ] */
2254 2256 static const char *
2255 2257 parse_simple_id(const char *first, const char *last, cpp_db_t *db)
2256 2258 {
2257 - ASSERT3P(first, <=, last);
2259 + VERIFY3P(first, <=, last);
2258 2260
2259 2261 const char *t = parse_source_name(first, last, db);
2260 2262 if (t == first)
2261 2263 return (t);
2262 2264
2263 2265 const char *t1 = parse_template_args(t, last, db);
2264 2266 if (t == t1)
2265 2267 return (t);
2266 2268
2267 2269 nfmt(db, "{1}{0}", NULL);
2268 2270 return (t1);
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
2269 2271 }
2270 2272
2271 2273 /*
2272 2274 * <unresolved-type> ::= <template-param>
2273 2275 * ::= <decltype>
2274 2276 * ::= <substitution>
2275 2277 */
2276 2278 static const char *
2277 2279 parse_unresolved_type(const char *first, const char *last, cpp_db_t *db)
2278 2280 {
2279 - ASSERT3P(first, <=, last);
2281 + VERIFY3P(first, <=, last);
2280 2282
2281 2283 if (first == last)
2282 2284 return (first);
2283 2285
2284 2286 const char *t = first;
2285 2287 size_t n = nlen(db);
2286 2288
2287 2289 switch (first[0]) {
2288 2290 case 'T':
2289 2291 t = parse_template_param(first, last, db);
2290 2292 if (t == first || NAMT(db, n) != 1) {
2291 2293 for (size_t i = 0; i < NAMT(db, n); i++)
2292 - (void) name_pop(&db->cpp_name, NULL);
2294 + name_pop(&db->cpp_name, NULL);
2293 2295 return (first);
2294 2296 }
2295 2297 save_top(db, 1);
2296 2298 return (t);
2297 2299
2298 2300 case 'D':
2299 2301 t = parse_decltype(first, last, db);
2300 2302 if (t == first || NAMT(db, n) == 0)
2301 2303 return (first);
2302 2304 save_top(db, 1);
2303 2305 return (t);
2304 2306
2305 2307 case 'S':
2306 2308 t = parse_substitution(first, last, db);
2307 2309 if (t != first)
2308 2310 return (t);
2309 2311
2310 2312 if (last - first < 2 || first[1] != 't')
2311 2313 return (first);
2312 2314
2313 2315 t = parse_unqualified_name(first + 2, last, db);
2314 2316 if (t == first + 2 || NAMT(db, n) == 0)
2315 2317 return (first);
2316 2318
2317 2319 nfmt(db, "std::{0:L}", "{0:R}");
2318 2320 save_top(db, 1);
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
2319 2321 return (t);
2320 2322 }
2321 2323
2322 2324 return (first);
2323 2325 }
2324 2326
2325 2327 /* sp <expression> # pack expansion */
2326 2328 static const char *
2327 2329 parse_pack_expansion(const char *first, const char *last, cpp_db_t *db)
2328 2330 {
2329 - ASSERT3P(first, <=, last);
2331 + VERIFY3P(first, <=, last);
2330 2332
2331 2333 if (last - first < 3)
2332 2334 return (first);
2333 2335
2334 - ASSERT3U(first[0], ==, 's');
2335 - ASSERT3U(first[1], ==, 'p');
2336 + VERIFY3U(first[0], ==, 's');
2337 + VERIFY3U(first[1], ==, 'p');
2336 2338
2337 2339 const char *t = parse_expression(first + 2, last, db);
2338 2340 if (t == first +2)
2339 2341 return (first);
2340 2342
2341 2343 return (t);
2342 2344 }
2343 2345
2344 2346 /*
2345 2347 * <unscoped-name> ::= <unqualified-name>
2346 2348 * ::= St <unqualified-name> # ::std::
2347 2349 * extension ::= StL<unqualified-name>
2348 2350 */
2349 2351 static const char *
2350 2352 parse_unscoped_name(const char *first, const char *last, cpp_db_t *db)
2351 2353 {
2352 - ASSERT3P(first, <=, last);
2354 + VERIFY3P(first, <=, last);
2353 2355
2354 2356 if (last - first < 2)
2355 2357 return (first);
2356 2358
2357 2359 const char *t = first;
2358 2360 const char *t1 = NULL;
2359 2361 boolean_t st = B_FALSE;
2360 2362
2361 2363 if (first[0] == 'S' && first[1] == 't') {
2362 2364 st = B_TRUE;
2363 2365 t = first + 2;
2364 2366
2365 2367 if (first + 3 != last && first[2] == 'L')
2366 2368 t++;
2367 2369 }
2368 2370
2369 2371 t1 = parse_unqualified_name(t, last, db);
2370 2372 if (t == t1)
2371 2373 return (first);
2372 2374
2373 2375 if (st)
2374 2376 nfmt(db, "std::{0}", NULL);
2375 2377
2376 2378 return (t1);
2377 2379 }
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
2378 2380
2379 2381 /*
2380 2382 * <unqualified-name> ::= <operator-name>
2381 2383 * ::= <ctor-dtor-name>
2382 2384 * ::= <source-name>
2383 2385 * ::= <unnamed-type-name>
2384 2386 */
2385 2387 const char *
2386 2388 parse_unqualified_name(const char *first, const char *last, cpp_db_t *db)
2387 2389 {
2388 - ASSERT3P(first, <=, last);
2390 + VERIFY3P(first, <=, last);
2389 2391
2390 2392 if (first == last)
2391 2393 return (first);
2392 2394
2393 2395 switch (*first) {
2394 2396 case 'C':
2395 2397 case 'D':
2396 2398 return (parse_ctor_dtor_name(first, last, db));
2397 2399 case 'U':
2398 2400 return (parse_unnamed_type_name(first, last, db));
2399 2401
2400 2402 case '1':
2401 2403 case '2':
2402 2404 case '3':
2403 2405 case '4':
2404 2406 case '5':
2405 2407 case '6':
2406 2408 case '7':
2407 2409 case '8':
2408 2410 case '9':
2409 2411 return (parse_source_name(first, last, db));
2410 2412 default:
2411 2413 return (parse_operator_name(first, last, db));
2412 2414 }
2413 2415 }
2414 2416
2415 2417 /*
2416 2418 * <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
2417 2419 * ::= <closure-type-name>
2418 2420 *
2419 2421 * <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2420 2422 *
2421 2423 * <lambda-sig> ::= <parameter type>+
2422 2424 * # Parameter types or "v" if the lambda has no parameters
2423 2425 */
2424 2426 static const char *
2425 2427 parse_unnamed_type_name(const char *first, const char *last, cpp_db_t *db)
2426 2428 {
2427 - ASSERT3P(first, <=, last);
2429 + VERIFY3P(first, <=, last);
2428 2430
2429 2431 if (last - first < 2 || first[0] != 'U')
2430 2432 return (first);
2431 2433
2432 2434 if (first[1] != 't' && first[1] != 'l')
2433 2435 return (first);
2434 2436
2435 2437 const char *t1 = first + 2;
2436 2438 const char *t2 = NULL;
2437 2439
2438 2440 if (first[1] == 't') {
2439 - while (t1 != last && t1[0] != '_' && is_digit(t1[0]))
2441 + while (t1 != last && t1[0] != '_' &&
2442 + isdigit_l(t1[0], db->cpp_loc))
2440 2443 t1++;
2441 2444
2442 2445 if (t1[0] != '_')
2443 2446 return (first);
2444 2447
2445 2448 if (t1 == first + 2)
2446 2449 nadd_l(db, "", 0);
2447 2450 else
2448 2451 nadd_l(db, first + 2, (size_t)(t1 - first - 2));
2449 2452
2450 2453 nfmt(db, "'unnamed{0}'", NULL);
2451 2454 return (t1 + 1);
2452 2455 }
2453 2456
2454 2457 size_t n = nlen(db);
2455 2458
2456 2459 if (first[2] != 'v') {
2457 2460 do {
2458 2461 t2 = parse_type(t1, last, db);
2459 2462 if (t1 == t2)
2460 2463 return (first);
2461 2464 t1 = t2;
2462 2465 } while (t1 != last && t1[0] != 'E');
2463 2466
2464 2467 if (t1 == last || NAMT(db, n) < 1)
2465 2468 return (first);
2466 2469
2467 2470 if (NAMT(db, n) < 1)
2468 2471 return (first);
2469 2472 } else {
2470 2473 t1++;
2471 2474 if (t1[0] != 'E')
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
2472 2475 return (first);
2473 2476 }
2474 2477
2475 2478 njoin(db, NAMT(db, n), ", ");
2476 2479
2477 2480 /* E */
2478 2481 t1++;
2479 2482
2480 2483 t2 = t1;
2481 2484 while (t2 != last && t2[0] != '_') {
2482 - if (!is_digit(*t2++))
2485 + if (!isdigit_l(*t2++, db->cpp_loc))
2483 2486 return (first);
2484 2487 }
2485 2488
2486 2489 if (t2[0] != '_')
2487 2490 return (first);
2488 2491
2489 2492 if (t2 - t1 > 0)
2490 2493 nadd_l(db, t1, (size_t)(t2 - t1));
2491 2494 else
2492 2495 nadd_l(db, "", 0);
2493 2496
2494 2497 nfmt(db, "'lambda{0}'({1})", NULL);
2495 2498
2496 2499 /* _ */
2497 2500 return (t2 + 1);
2498 2501 }
2499 2502
2500 2503 static struct {
2501 2504 const char *alias;
2502 2505 const char *fullname;
2503 2506 const char *basename;
2504 2507 } aliases[] = {
2505 2508 {
2506 2509 "std::string",
2507 2510 "std::basic_string<char, std::char_traits<char>, "
2508 2511 "std::allocator<char> >",
2509 2512 "basic_string"
2510 2513 },
2511 2514 {
2512 2515 "std::istream",
2513 2516 "std::basic_istream<char, std::char_traits<char> >",
2514 2517 "basic_istream"
2515 2518 },
2516 2519 {
2517 2520 "std::ostream",
2518 2521 "std::basic_ostream<char, std::char_traits<char> >",
2519 2522 "basic_ostream"
2520 2523 },
2521 2524 {
2522 2525 "std::iostream",
2523 2526 "std::basic_iostream<char, std::char_traits<char> >",
2524 2527 "basic_iostream"
2525 2528 }
2526 2529 };
2527 2530
2528 2531 static void
2529 2532 basename(cpp_db_t *db)
2530 2533 {
2531 2534 str_t *s = TOP_L(db);
2532 2535
2533 2536 for (size_t i = 0; i < ARRAY_SIZE(aliases); i++) {
2534 2537 if (str_length(s) != strlen(aliases[i].alias))
2535 2538 continue;
2536 2539 if (strncmp(aliases[i].alias, s->str_s, str_length(s)) != 0)
2537 2540 continue;
2538 2541
2539 2542 /* swap out alias for full name */
2540 2543 sysdem_ops_t *ops = s->str_ops;
2541 2544 str_fini(s);
2542 2545 str_init(s, ops);
2543 2546 str_set(s, aliases[i].fullname, 0);
2544 2547
2545 2548 nadd_l(db, aliases[i].basename, 0);
2546 2549 return;
2547 2550 }
2548 2551
2549 2552 const char *start = s->str_s;
2550 2553 const char *end = s->str_s + s->str_len;
2551 2554
2552 2555 /*
2553 2556 * if name ends with a template i.e. <.....> back up to start
2554 2557 * of outermost template
2555 2558 */
2556 2559 unsigned c = 0;
2557 2560
2558 2561 if (end[-1] == '>') {
2559 2562 for (; end > start; end--) {
2560 2563 switch (end[-1]) {
2561 2564 case '<':
2562 2565 if (--c == 0) {
2563 2566 end--;
2564 2567 goto out;
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
2565 2568 }
2566 2569 break;
2567 2570 case '>':
2568 2571 c++;
2569 2572 break;
2570 2573 }
2571 2574 }
2572 2575 }
2573 2576
2574 2577 out:
2575 - ASSERT3P(end, >=, start);
2578 + VERIFY3P(end, >=, start);
2576 2579
2577 2580 if (end - start < 2) {
2578 2581 nadd_l(db, "", 0);
2579 2582 return;
2580 2583 }
2581 2584
2582 2585 for (start = end - 1; start > s->str_s; start--) {
2583 2586 if (start[0] == ':') {
2584 2587 start++;
2585 2588 break;
2586 2589 }
2587 2590 }
2588 2591
2589 - ASSERT3P(end, >=, start);
2592 + VERIFY3P(end, >=, start);
2590 2593
2591 2594 nadd_l(db, start, (size_t)(end - start));
2592 2595 }
2593 2596
2594 2597 /*
2595 2598 * <ctor-dtor-name> ::= C1 # complete object constructor
2596 2599 * ::= C2 # base object constructor
2597 2600 * ::= C3 # complete object allocating constructor
2598 2601 * extension ::= C5 # ?
2599 2602 * ::= D0 # deleting destructor
2600 2603 * ::= D1 # complete object destructor
2601 2604 * ::= D2 # base object destructor
2602 2605 * extension ::= D5 # ?
2603 2606 */
2604 2607 static const char *
2605 2608 parse_ctor_dtor_name(const char *first, const char *last, cpp_db_t *db)
2606 2609 {
2607 - ASSERT3P(first, <=, last);
2610 + VERIFY3P(first, <=, last);
2608 2611
2609 2612 if (last - first < 2 || nempty(db) || str_length(TOP_L(db)) == 0)
2610 2613 return (first);
2611 2614
2612 2615 switch (first[0]) {
2613 2616 case 'C':
2614 2617 switch (first[1]) {
2615 2618 case '1':
2616 2619 case '2':
2617 2620 case '3':
2618 2621 case '5':
2619 2622 basename(db);
2620 2623 break;
2621 2624 default:
2622 2625 return (first);
2623 2626 }
2624 2627 break;
2625 2628 case 'D':
2626 2629 switch (first[1]) {
2627 2630 case '0':
2628 2631 case '1':
2629 2632 case '2':
2630 2633 case '5':
2631 2634 basename(db);
2632 2635 str_insert(TOP_L(db), 0, "~", 1);
2633 2636 break;
2634 2637 default:
2635 2638 return (first);
2636 2639 }
2637 2640 break;
2638 2641 default:
2639 2642 return (first);
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
2640 2643 }
2641 2644
2642 2645 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
2643 2646 return (first + 2);
2644 2647 }
2645 2648
2646 2649 static const char *
2647 2650 parse_integer_literal(const char *first, const char *last, const char *fmt,
2648 2651 cpp_db_t *db)
2649 2652 {
2650 - ASSERT3P(first, <=, last);
2653 + VERIFY3P(first, <=, last);
2651 2654
2652 - const char *t = parse_number(first, last);
2655 + const char *t = parse_number(first, last, db->cpp_loc);
2653 2656 const char *start = first;
2654 2657
2655 2658 if (t == first || t == last || t[0] != 'E')
2656 2659 return (first);
2657 2660
2658 2661 if (first[0] == 'n')
2659 2662 start++;
2660 2663
2661 2664 nadd_l(db, start, (size_t)(t - start));
2662 2665 if (start != first)
2663 2666 nfmt(db, "-{0}", NULL);
2664 2667
2665 2668 nfmt(db, fmt, NULL);
2666 2669 return (t + 1);
2667 2670 }
2668 2671
2669 2672 static struct float_data_s {
2670 2673 const char *spec;
2671 2674 size_t mangled_size;
2672 2675 size_t max_demangled_size;
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
2673 2676 char type;
2674 2677 } float_info[] = {
2675 2678 { "%af", 8, 24, 'f' }, /* float */
2676 2679 { "%a", 16, 32, 'd' }, /* double */
2677 2680 { "%LaL", 20, 40, 'e' } /* long double */
2678 2681 };
2679 2682
2680 2683 static const char *
2681 2684 parse_floating_literal(const char *first, const char *last, cpp_db_t *db)
2682 2685 {
2683 - ASSERT3P(first, <=, last);
2684 - ASSERT(first[0] == 'f' || first[0] == 'd' || first[0] == 'e');
2686 + VERIFY3P(first, <=, last);
2687 + VERIFY(first[0] == 'f' || first[0] == 'd' || first[0] == 'e');
2685 2688
2686 2689 const struct float_data_s *fd = NULL;
2687 2690
2688 2691 for (size_t i = 0; i < ARRAY_SIZE(float_info); i++) {
2689 2692 if (float_info[i].type != first[0])
2690 2693 continue;
2691 2694
2692 2695 fd = &float_info[i];
2693 2696 break;
2694 2697 }
2695 2698
2696 2699 if (fd == NULL || (size_t)(last - first) < fd->mangled_size)
2697 2700 return (first);
2698 2701
2699 2702 union {
2700 2703 union {
2701 2704 float v;
2702 2705 char buf[sizeof (float)];
2703 2706 } f;
2704 2707 union {
2705 2708 double v;
2706 2709 char buf[sizeof (double)];
2707 2710 } d;
2708 2711 union {
2709 2712 long double v;
2710 2713 char buf[sizeof (long double)];
2711 2714 } ld;
2712 2715 } conv;
2713 2716
2714 2717 const char *t = NULL;
2715 2718 char *e = NULL;
2716 2719
2717 2720 switch (first[0]) {
2718 2721 case 'f':
2719 2722 e = conv.f.buf;
2720 2723 break;
2721 2724 case 'd':
2722 2725 e = conv.d.buf;
2723 2726 break;
2724 2727 case 'e':
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
2725 2728 e = conv.ld.buf;
2726 2729 break;
2727 2730 }
2728 2731 last = first + fd->mangled_size + 1;
2729 2732
2730 2733 #if defined(_BIG_ENDIAN)
2731 2734 for (t = first + 1; t != last; t++, e++) {
2732 2735 if (!is_xdigit(t[0]))
2733 2736 return (first);
2734 2737
2735 - unsigned d1 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2738 + unsigned d1 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2736 2739 t++;
2737 - unsigned d0 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2740 + unsigned d0 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2738 2741
2739 2742 *e = (d1 << 4) + d0;
2740 2743 }
2741 2744 #elif defined(_LITTLE_ENDIAN)
2742 2745 for (t = last - 1; t > first; t--, e++) {
2743 2746 if (!is_xdigit(t[0]))
2744 2747 return (first);
2745 2748
2746 - unsigned d0 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2749 + unsigned d0 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2747 2750 t--;
2748 - unsigned d1 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2751 + unsigned d1 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2749 2752
2750 2753 *e = (d1 << 4) + d0;
2751 2754 }
2752 2755 t = last;
2753 2756 #else
2754 2757 #error One of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined
2755 2758 #endif
2756 2759
2757 2760 if (t[0] != 'E')
2758 2761 return (first);
2759 2762
2760 2763 str_t num = { 0 };
2761 2764 str_init(&num, db->cpp_ops);
2762 2765
2763 2766 num.str_size = fd->max_demangled_size + 1;
2764 2767 num.str_s = zalloc(db->cpp_ops, num.str_size);
2765 2768 CK(num.str_s != NULL);
2766 2769
2767 2770 int n = 0;
2768 2771
2769 2772 switch (first[0]) {
2770 2773 case 'f':
2771 2774 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2772 2775 conv.f.v);
2773 2776 break;
2774 2777 case 'd':
2775 2778 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2776 2779 conv.d.v);
2777 2780 break;
2778 2781 case 'e':
2779 2782 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2780 2783 conv.ld.v);
2781 2784 }
2782 2785
2783 2786 if (n >= fd->max_demangled_size || n <= 0) {
2784 2787 str_fini(&num);
2785 2788 return (first);
2786 2789 }
2787 2790
2788 2791 num.str_len = n;
2789 2792 name_add_str(&db->cpp_name, &num, NULL);
2790 2793
2791 2794 return (t + 1);
2792 2795 }
2793 2796
2794 2797 /*
2795 2798 * <expr-primary> ::= L <type> <value number> E # integer literal
2796 2799 * ::= L <type> <value float> E # floating literal
2797 2800 * ::= L <string type> E # string literal
2798 2801 * ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2799 2802 *
2800 2803 * ::= L <type> <real-part float> _ <imag-part float> E
2801 2804 * # complex floating point
2802 2805 * # literal (C 2000)
2803 2806 *
2804 2807 * ::= L <mangled-name> E # external name
2805 2808 */
2806 2809 static struct {
2807 2810 int c;
2808 2811 const char *fmt;
2809 2812 } int_lits[] = {
2810 2813 { 'a', "(signed char){0}" },
2811 2814 { 'c', "(char){0}" },
2812 2815 { 'h', "(unsigned char){0}" },
2813 2816 { 'i', "{0}" },
2814 2817 { 'j', "{0}u" },
2815 2818 { 'l', "{0}l" },
2816 2819 { 'm', "{0}ul" },
2817 2820 { 'n', "(__int128){0}" },
2818 2821 { 'o', "(unsigned __int128){0}" },
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
2819 2822 { 's', "(short){0}" },
2820 2823 { 't', "(unsigned short){0}" },
2821 2824 { 'w', "(wchar_t){0}" },
2822 2825 { 'x', "{0}ll" },
2823 2826 { 'y', "{0}ull" }
2824 2827 };
2825 2828
2826 2829 static const char *
2827 2830 parse_expr_primary(const char *first, const char *last, cpp_db_t *db)
2828 2831 {
2829 - ASSERT3P(first, <=, last);
2832 + VERIFY3P(first, <=, last);
2830 2833
2831 2834 if (last - first < 4 || first[0] != 'L')
2832 2835 return (first);
2833 2836
2834 2837 const char *t = NULL;
2835 2838
2836 2839 for (size_t i = 0; i < ARRAY_SIZE(int_lits); i++) {
2837 2840 if (first[1] == int_lits[i].c) {
2838 2841 t = parse_integer_literal(first + 2, last,
2839 2842 int_lits[i].fmt, db);
2840 2843 return ((t == first + 2) ? first : t);
2841 2844 }
2842 2845 }
2843 2846
2844 2847 switch (first[1]) {
2845 2848 case 'b':
2846 2849 if (first[3] != 'E')
2847 2850 return (first);
2848 2851
2849 2852 switch (first[2]) {
2850 2853 case '0':
2851 2854 nadd_l(db, "false", 5);
2852 2855 break;
2853 2856 case '1':
2854 2857 nadd_l(db, "true", 4);
2855 2858 break;
2856 2859 default:
2857 2860 return (first);
2858 2861 }
2859 2862 return (first + 4);
2860 2863 case 'd': /* double */
2861 2864 case 'e': /* long double */
2862 2865 case 'f': /* float */
2863 2866 t = parse_floating_literal(first + 1, last, db);
2864 2867 return ((t == first + 1) ? first : t);
2865 2868 case 'T':
2866 2869 /* BEGIN CSTYLED */
2867 2870 /*
2868 2871 * Invalid mangled name per
2869 2872 * http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2870 2873 *
2871 2874 */
2872 2875 /* END CSTYLED */
2873 2876 return (first);
2874 2877 case '_':
2875 2878 if (first[2] != 'Z')
2876 2879 return (first);
2877 2880
2878 2881 t = parse_encoding(first + 3, last, db);
2879 2882 if (t == first + 3 || t == last || t[0] != 'E')
2880 2883 return (first);
2881 2884
2882 2885 /* skip E */
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
2883 2886 return (t + 1);
2884 2887 default:
2885 2888 t = parse_type(first + 1, last, db);
2886 2889 if (t == first + 1 || t == last)
2887 2890 return (first);
2888 2891
2889 2892 if (t[0] == 'E')
2890 2893 return (t + 1);
2891 2894
2892 2895 const char *n;
2893 - for (n = t; n != last && is_digit(n[0]); n++)
2896 + for (n = t; n != last && isdigit_l(n[0], db->cpp_loc); n++)
2894 2897 ;
2895 2898 if (n == last || nempty(db) || n[0] != 'E')
2896 2899 return (first);
2897 2900 if (n == t)
2898 2901 return (t);
2899 2902
2900 2903 nadd_l(db, t, (size_t)(n - t));
2901 2904 nfmt(db, "({1}){0}", NULL);
2902 2905
2903 2906 return (n + 1);
2904 2907 }
2905 2908 }
2906 2909
2907 2910 /*
2908 2911 * <operator-name>
2909 2912 * ::= aa # &&
2910 2913 * ::= ad # & (unary)
2911 2914 * ::= an # &
2912 2915 * ::= aN # &=
2913 2916 * ::= aS # =
2914 2917 * ::= cl # ()
2915 2918 * ::= cm # ,
2916 2919 * ::= co # ~
2917 2920 * ::= cv <type> # (cast)
2918 2921 * ::= da # delete[]
2919 2922 * ::= de # * (unary)
2920 2923 * ::= dl # delete
2921 2924 * ::= dv # /
2922 2925 * ::= dV # /=
2923 2926 * ::= eo # ^
2924 2927 * ::= eO # ^=
2925 2928 * ::= eq # ==
2926 2929 * ::= ge # >=
2927 2930 * ::= gt # >
2928 2931 * ::= ix # []
2929 2932 * ::= le # <=
2930 2933 * ::= li <source-name> # operator ""
2931 2934 * ::= ls # <<
2932 2935 * ::= lS # <<=
2933 2936 * ::= lt # <
2934 2937 * ::= mi # -
2935 2938 * ::= mI # -=
2936 2939 * ::= ml # *
2937 2940 * ::= mL # *=
2938 2941 * ::= mm # -- (postfix in <expression> context)
2939 2942 * ::= na # new[]
2940 2943 * ::= ne # !=
2941 2944 * ::= ng # - (unary)
2942 2945 * ::= nt # !
2943 2946 * ::= nw # new
2944 2947 * ::= oo # ||
2945 2948 * ::= or # |
2946 2949 * ::= oR # |=
2947 2950 * ::= pm # ->*
2948 2951 * ::= pl # +
2949 2952 * ::= pL # +=
2950 2953 * ::= pp # ++ (postfix in <expression> context)
2951 2954 * ::= ps # + (unary)
2952 2955 * ::= pt # ->
2953 2956 * ::= qu # ?
2954 2957 * ::= rm # %
2955 2958 * ::= rM # %=
2956 2959 * ::= rs # >>
2957 2960 * ::= rS # >>=
2958 2961 * ::= v <digit> <source-name> # vendor extended operator
2959 2962 */
2960 2963 static struct {
2961 2964 const char code[3];
2962 2965 const char *op;
2963 2966 } op_tbl[] = {
2964 2967 { "aa", "operator&&" },
2965 2968 { "ad", "operator&" },
2966 2969 { "an", "operator&" },
2967 2970 { "aN", "operator&=" },
2968 2971 { "aS", "operator=" },
2969 2972 { "cl", "operator()" },
2970 2973 { "cm", "operator," },
2971 2974 { "co", "operator~" },
2972 2975 { "da", "operator delete[]" },
2973 2976 { "de", "operator*" },
2974 2977 { "dl", "operator delete" },
2975 2978 { "dv", "operator/" },
2976 2979 { "dV", "operator/=" },
2977 2980 { "eo", "operator^" },
2978 2981 { "eO", "operator^=" },
2979 2982 { "eq", "operator==" },
2980 2983 { "ge", "operator>=" },
2981 2984 { "gt", "operator>" },
2982 2985 { "ix", "operator[]" },
2983 2986 { "le", "operator<=" },
2984 2987 { "ls", "operator<<" },
2985 2988 { "lS", "operator<<=" },
2986 2989 { "lt", "operator<" },
2987 2990 { "mi", "operator-" },
2988 2991 { "mI", "operator-=" },
2989 2992 { "ml", "operator*" },
2990 2993 { "mL", "operator*=" },
2991 2994 { "mm", "operator--" },
2992 2995 { "na", "operator new[]" },
2993 2996 { "ne", "operator!=" },
2994 2997 { "ng", "operator-" },
2995 2998 { "nt", "operator!" },
2996 2999 { "nw", "operator new" },
2997 3000 { "oo", "operator||" },
2998 3001 { "or", "operator|" },
2999 3002 { "oR", "operator|=" },
3000 3003 { "pm", "operator->*" },
3001 3004 { "pl", "operator+" },
3002 3005 { "pL", "operator+=" },
3003 3006 { "pp", "operator++" },
3004 3007 { "ps", "operator+" },
3005 3008 { "pt", "operator->" },
↓ open down ↓ |
102 lines elided |
↑ open up ↑ |
3006 3009 { "qu", "operator?" },
3007 3010 { "rm", "operator%" },
3008 3011 { "rM", "operator%=" },
3009 3012 { "rs", "operator>>" },
3010 3013 { "rS", "operator>>=" }
3011 3014 };
3012 3015
3013 3016 static const char *
3014 3017 parse_operator_name(const char *first, const char *last, cpp_db_t *db)
3015 3018 {
3016 - ASSERT3P(first, <=, last);
3019 + VERIFY3P(first, <=, last);
3017 3020
3018 3021 if (last - first < 2)
3019 3022 return (first);
3020 3023
3021 3024 for (size_t i = 0; i < ARRAY_SIZE(op_tbl); i++) {
3022 3025 if (strncmp(first, op_tbl[i].code, 2) != 0)
3023 3026 continue;
3024 3027
3025 3028 nadd_l(db, op_tbl[i].op, 0);
3026 3029 return (first + 2);
3027 3030 }
3028 3031
3029 3032 const char *t = NULL;
3030 3033
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
3031 3034 if (first[0] == 'l' && first[1] == 'i') {
3032 3035 t = parse_source_name(first + 2, last, db);
3033 3036 if (t == first + 2 || nempty(db))
3034 3037 return (first);
3035 3038
3036 3039 nfmt(db, "operator\"\" {0}", NULL);
3037 3040 return (t);
3038 3041 }
3039 3042
3040 3043 if (first[0] == 'v') {
3041 - if (!is_digit(first[1]))
3044 + if (!isdigit_l(first[1], db->cpp_loc))
3042 3045 return (first);
3043 3046
3044 3047 t = parse_source_name(first + 2, last, db);
3045 3048 if (t == first + 2)
3046 3049 return (first);
3047 3050
3048 3051 nfmt(db, "operator {0}", NULL);
3049 3052 return (t);
3050 3053 }
3051 3054
3052 3055 if (first[0] != 'c' && first[1] != 'v')
3053 3056 return (first);
3054 3057
3055 3058 boolean_t try_to_parse_template_args =
3056 3059 db->cpp_try_to_parse_template_args;
3057 3060
3058 3061 db->cpp_try_to_parse_template_args = B_FALSE;
3059 3062 t = parse_type(first + 2, last, db);
3060 3063 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
3061 3064
3062 3065 if (t == first + 2 || nempty(db))
3063 3066 return (first);
3064 3067
3065 3068 nfmt(db, "operator {0}", NULL);
3066 3069 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
3067 3070 return (t);
3068 3071 }
3069 3072
3070 3073 struct type_tbl_s {
3071 3074 int code;
3072 3075 const char *name;
3073 3076 };
3074 3077
3075 3078 static struct type_tbl_s type_tbl1[] = {
3076 3079 { 'a', "signed char" },
3077 3080 { 'b', "bool" },
3078 3081 { 'c', "char" },
3079 3082 { 'd', "double" },
3080 3083 { 'e', "long double" },
3081 3084 { 'f', "float" },
3082 3085 { 'g', "__float128" },
3083 3086 { 'h', "unsigned char" },
3084 3087 { 'i', "int" },
3085 3088 { 'j', "unsigned int" },
3086 3089 { 'l', "long" },
3087 3090 { 'm', "unsigned long" },
3088 3091 { 'n', "__int128" },
3089 3092 { 'o', "unsigned __int128" },
3090 3093 { 's', "short" },
3091 3094 { 't', "unsigned short" },
3092 3095 { 'v', "void" },
3093 3096 { 'w', "wchar_t" },
3094 3097 { 'x', "long long" },
3095 3098 { 'y', "unsigned long long" },
3096 3099 { 'z', "..." }
3097 3100 };
3098 3101
3099 3102 static struct type_tbl_s type_tbl2[] = {
3100 3103 { 'a', "auto" },
3101 3104 { 'c', "decltype(auto)" },
3102 3105 { 'd', "decimal64" },
3103 3106 { 'e', "decimal128" },
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
3104 3107 { 'f', "decimal32" },
3105 3108 { 'h', "decimal16" },
3106 3109 { 'i', "char32_t" },
3107 3110 { 'n', "std::nullptr_t" },
3108 3111 { 's', "char16_t" }
3109 3112 };
3110 3113
3111 3114 static const char *
3112 3115 parse_builtin_type(const char *first, const char *last, cpp_db_t *db)
3113 3116 {
3114 - ASSERT3P(first, <=, last);
3117 + VERIFY3P(first, <=, last);
3115 3118
3116 3119 if (first == last)
3117 3120 return (first);
3118 3121
3119 3122 size_t i;
3120 3123
3121 3124 for (i = 0; i < ARRAY_SIZE(type_tbl1); i++) {
3122 3125 if (first[0] == type_tbl1[i].code) {
3123 3126 nadd_l(db, type_tbl1[i].name, 0);
3124 3127 return (first + 1);
3125 3128 }
3126 3129 }
3127 3130
3128 3131 if (first[0] == 'D') {
3129 3132 if (first + 1 == last)
3130 3133 return (first);
3131 3134 for (i = 0; i < ARRAY_SIZE(type_tbl2); i++) {
3132 3135 if (first[1] == type_tbl2[i].code) {
3133 3136 nadd_l(db, type_tbl2[i].name, 0);
3134 3137 return (first + 2);
3135 3138 }
3136 3139 }
3137 3140 }
3138 3141
3139 3142 if (first[0] == 'u') {
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
3140 3143 const char *t = parse_source_name(first + 1, last, db);
3141 3144 if (t == first + 1)
3142 3145 return (first);
3143 3146 return (t);
3144 3147 }
3145 3148
3146 3149 return (first);
3147 3150 }
3148 3151
3149 3152 static const char *
3150 -parse_base36(const char *first, const char *last, size_t *val)
3153 +parse_base36(const char *first, const char *last, size_t *val, locale_t loc)
3151 3154 {
3152 - ASSERT3P(first, <=, last);
3155 + VERIFY3P(first, <=, last);
3153 3156
3154 3157 const char *t;
3155 3158
3156 3159 for (t = first, *val = 0; t != last; t++) {
3157 - if (!is_digit(t[0]) && !is_upper(t[0]))
3160 + if (!isdigit_l(t[0], loc) && !isupper_l(t[0], loc))
3158 3161 return (t);
3159 3162
3160 3163 *val *= 36;
3161 3164
3162 - if (is_digit(t[0]))
3165 + if (isdigit_l(t[0], loc))
3163 3166 *val += t[0] - '0';
3164 3167 else
3165 3168 *val += t[0] - 'A' + 10;
3166 3169 }
3167 3170 return (t);
3168 3171 }
3169 3172
3170 3173 static struct type_tbl_s sub_tbl[] = {
3171 3174 { 'a', "std::allocator" },
3172 3175 { 'b', "std::basic_string" },
3173 3176 { 's', "std::string" },
3174 3177 { 'i', "std::istream" },
3175 3178 { 'o', "std::ostream" },
3176 3179 { 'd', "std::iostream" }
3177 3180 };
3178 3181
3179 3182 static const char *
3180 3183 parse_substitution(const char *first, const char *last, cpp_db_t *db)
3181 3184 {
3182 - ASSERT3P(first, <=, last);
3185 + VERIFY3P(first, <=, last);
3183 3186
3184 3187 if (first == last || last - first < 2)
3185 3188 return (first);
3186 3189
3187 3190 if (first[0] != 'S')
3188 3191 return (first);
3189 3192
3190 3193 for (size_t i = 0; i < ARRAY_SIZE(sub_tbl); i++) {
3191 3194 if (first[1] == sub_tbl[i].code) {
3192 3195 nadd_l(db, sub_tbl[i].name, 0);
3193 3196 return (first + 2);
3194 3197 }
3195 3198 }
3196 3199
3197 3200 const char *t = first + 1;
3198 3201 size_t n = 0;
3199 3202
3200 3203 if (t[0] != '_') {
3201 - t = parse_base36(first + 1, last, &n);
3204 + t = parse_base36(first + 1, last, &n, db->cpp_loc);
3202 3205 if (t == first + 1 || t[0] != '_')
3203 3206 return (first);
3204 3207
3205 3208 /*
3206 3209 * S_ == substitution 0,
3207 3210 * S0_ == substituion 1,
3208 3211 * ...
3209 3212 */
3210 3213 n++;
3211 3214 }
3212 3215
3213 3216 if (n >= sub_len(&db->cpp_subs))
3214 3217 return (first);
3215 3218
3216 3219 sub(db, n);
3217 3220
3218 3221 /* skip _ */
3219 - ASSERT3U(t[0], ==, '_');
3222 + VERIFY3U(t[0], ==, '_');
3220 3223
3221 3224 return (t + 1);
3222 3225 }
3223 3226
3224 3227 static const char *
3225 3228 parse_source_name(const char *first, const char *last, cpp_db_t *db)
3226 3229 {
3227 - ASSERT3P(first, <=, last);
3230 + VERIFY3P(first, <=, last);
3228 3231
3229 3232 if (first == last)
3230 3233 return (first);
3231 3234
3232 3235 const char *t = NULL;
3233 3236 size_t n = 0;
3234 3237
3235 - for (t = first; t != last && is_digit(t[0]); t++) {
3238 + for (t = first; t != last && isdigit_l(t[0], db->cpp_loc); t++) {
3236 3239 /* make sure we don't overflow */
3237 3240 size_t nn = n * 10;
3238 3241 if (nn < n)
3239 3242 return (first);
3240 3243
3241 3244 nn += t[0] - '0';
3242 3245 if (nn < n)
3243 3246 return (first);
3244 3247
3245 3248 n = nn;
3246 3249 }
3247 3250
3248 3251 if (n == 0 || t == last || t + n > last ||
3249 3252 (uintptr_t)t + n < (uintptr_t)t)
3250 3253 return (first);
3251 3254
3252 3255 if (strncmp(t, "_GLOBAL__N", 10) == 0)
3253 3256 nadd_l(db, "(anonymous namespace)", 0);
3254 3257 else
3255 3258 nadd_l(db, t, n);
3256 3259
3257 3260 return (t + n);
3258 3261 }
3259 3262
3260 3263 /*
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
3261 3264 * extension:
3262 3265 * <vector-type> ::= Dv <positive dimension number> _
3263 3266 * <extended element type>
3264 3267 * ::= Dv [<dimension expression>] _ <element type>
3265 3268 * <extended element type> ::= <element type>
3266 3269 * ::= p # AltiVec vector pixel
3267 3270 */
3268 3271 static const char *
3269 3272 parse_vector_type(const char *first, const char *last, cpp_db_t *db)
3270 3273 {
3271 - ASSERT3P(first, <=, last);
3274 + VERIFY3P(first, <=, last);
3272 3275
3273 3276 if (last - first < 3)
3274 3277 return (first);
3275 3278
3276 - ASSERT3U(first[0], ==, 'D');
3277 - ASSERT3U(first[1], ==, 'v');
3279 + VERIFY3U(first[0], ==, 'D');
3280 + VERIFY3U(first[1], ==, 'v');
3278 3281
3279 3282 const char *t = first + 2;
3280 3283 const char *t1 = NULL;
3281 3284
3282 - if (is_digit(first[2]) && first[2] != '0') {
3283 - t1 = parse_number(t, last);
3285 + if (isdigit_l(first[2], db->cpp_loc) && first[2] != '0') {
3286 + t1 = parse_number(t, last, db->cpp_loc);
3284 3287 if (t1 == last || t1 + 1 == last || t1[0] != '_')
3285 3288 return (first);
3286 3289
3287 3290 nadd_l(db, t, (size_t)(t1 - t));
3288 3291
3289 3292 /* skip _ */
3290 3293 t = t1 + 1;
3291 3294
3292 3295 if (t[0] != 'p') {
3293 3296 t1 = parse_type(t, last, db);
3294 3297 if (t1 == t)
3295 3298 return (first);
3296 3299
3297 3300 nfmt(db, "{0} vector[{1}]", NULL);
3298 3301 return (t1);
3299 3302 }
3300 3303 nfmt(db, "{0} pixel vector[{1}]", NULL);
3301 3304 return (t1);
3302 3305 }
3303 3306
3304 3307 if (first[2] != '_') {
3305 3308 t1 = parse_expression(first + 2, last, db);
3306 3309 if (first == last || t1 == first + 2 || t1[0] != '_')
3307 3310 return (first);
3308 3311
3309 3312 /* skip _ */
3310 3313 t = t1 + 1;
3311 3314 } else {
3312 3315 nadd_l(db, "", 0);
3313 3316 }
3314 3317
3315 3318 t1 = parse_type(t, last, db);
3316 3319 if (t == t1)
3317 3320 return (first);
3318 3321
3319 3322 nfmt(db, "{1:L} vector[{0}]", "{1:R}");
3320 3323 return (t1);
3321 3324 }
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
3322 3325
3323 3326 /* BEGIN CSTYLED */
3324 3327 /*
3325 3328 * <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3326 3329 * ::= DT <expression> E # decltype of an expression (C++0x)
3327 3330 */
3328 3331 /* END CSTYLED */
3329 3332 static const char *
3330 3333 parse_decltype(const char *first, const char *last, cpp_db_t *db)
3331 3334 {
3332 - ASSERT3P(first, <=, last);
3335 + VERIFY3P(first, <=, last);
3333 3336
3334 3337 if (last - first < 4)
3335 3338 return (first);
3336 3339
3337 - ASSERT3U(first[0], ==, 'D');
3340 + VERIFY3U(first[0], ==, 'D');
3338 3341
3339 3342 if (first[1] != 't' && first[1] != 'T')
3340 3343 return (first);
3341 3344
3342 3345 size_t n = nlen(db);
3343 3346 const char *t = parse_expression(first + 2, last, db);
3344 3347 if (NAMT(db, n) != 1 || t == first + 2 || t == last || t[0] != 'E')
3345 3348 return (first);
3346 3349
3347 3350 nfmt(db, "decltype({0})", NULL);
3348 3351
3349 3352 /* skip E */
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3350 3353 return (t + 1);
3351 3354 }
3352 3355
3353 3356 /*
3354 3357 * <array-type> ::= A <positive dimension number> _ <element type>
3355 3358 * ::= A [<dimension expression>] _ <element type>
3356 3359 */
3357 3360 static const char *
3358 3361 parse_array_type(const char *first, const char *last, cpp_db_t *db)
3359 3362 {
3360 - ASSERT3P(first, <=, last);
3361 - ASSERT3U(first[0], ==, 'A');
3363 + VERIFY3P(first, <=, last);
3364 + VERIFY3U(first[0], ==, 'A');
3362 3365
3363 3366 if (last - first < 3)
3364 3367 return (first);
3365 3368
3366 3369 const char *t = first + 1;
3367 3370 const char *t1 = NULL;
3368 3371 size_t n = nlen(db);
3369 3372
3370 3373 if (t[0] != '_') {
3371 - if (is_digit(t[0]) && t[0] != '0') {
3372 - t1 = parse_number(t, last);
3374 + if (isdigit_l(t[0], db->cpp_loc) && t[0] != '0') {
3375 + t1 = parse_number(t, last, db->cpp_loc);
3373 3376 if (t1 == last)
3374 3377 return (first);
3375 3378
3376 3379 nadd_l(db, t, (size_t)(t1 - t));
3377 3380 } else {
3378 3381 t1 = parse_expression(t, last, db);
3379 3382 if (t1 == last || t == t1)
3380 3383 return (first);
3381 3384 }
3382 3385
3383 3386 if (t1[0] != '_')
3384 3387 return (first);
3385 3388
3386 3389 t = t1;
3387 3390 } else {
3388 3391 nadd_l(db, "", 0);
3389 3392 }
3390 3393
3391 - ASSERT3U(t[0], ==, '_');
3394 + VERIFY3U(t[0], ==, '_');
3392 3395
3393 3396 t1 = parse_type(t + 1, last, db);
3394 3397 if (t1 == t + 1 || NAMT(db, n) != 2)
3395 3398 return (first);
3396 3399
3397 3400 /*
3398 3401 * if we have " [xxx]" already, want new result to be
3399 3402 * " [yyy][xxx]"
3400 3403 */
3401 3404 str_t *r = &name_top(&db->cpp_name)->strp_r;
3402 3405 if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
3403 3406 str_erase(r, 0, 1);
3404 3407
3405 3408 nfmt(db, "{0:L}", " [{1}]{0:R}");
3406 3409 return (t1);
3407 3410 }
3408 3411
3409 3412 /* <pointer-to-member-type> ::= M <class type> <member type> */
3410 3413 static const char *
3411 3414 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3412 3415 {
3413 - ASSERT3P(first, <=, last);
3416 + VERIFY3P(first, <=, last);
3414 3417
3415 3418 if (last - first < 3)
3416 3419 return (first);
3417 3420
3418 - ASSERT3U(first[0], ==, 'M');
3421 + VERIFY3U(first[0], ==, 'M');
3419 3422
3420 3423 const char *t1 = first + 1;
3421 3424 const char *t2 = NULL;
3422 3425 size_t n = nlen(db);
3423 3426
3424 3427 t2 = parse_type(t1, last, db);
3425 3428 if (t1 == t2)
3426 3429 return (first);
3427 3430
3428 3431 t1 = t2;
3429 3432 t2 = parse_type(t1, last, db);
3430 3433 if (t1 == t2)
3431 3434 return (first);
3432 3435
3433 3436 if (NAMT(db, n) != 2)
3434 3437 return (first);
3435 3438
3436 3439 str_pair_t *func = name_top(&db->cpp_name);
3437 3440
3438 3441 if (str_length(&func->strp_r) > 0 && func->strp_r.str_s[0] == '(')
3439 3442 nfmt(db, "{0:L}({1}::*", "){0:R}");
3440 3443 else
3441 3444 nfmt(db, "{0:L} {1}::*", "{0:R}");
3442 3445
3443 3446 return (t2);
3444 3447 }
3445 3448
3446 3449 /* BEGIN CSTYLED */
3447 3450 /*
3448 3451 * <unresolved-name>
3449 3452 * extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3450 3453 * ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3451 3454 * ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
3452 3455 * # A::x, N::y, A<T>::z; "gs" means leading "::"
3453 3456 * ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3454 3457 * extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3455 3458 * # T::N::x /decltype(p)::N::x
3456 3459 * (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3457 3460 */
3458 3461 /* END CSTYLED */
3459 3462 static const char *
3460 3463 parse_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3461 3464 {
3462 - ASSERT3P(first, <=, last);
3465 + VERIFY3P(first, <=, last);
3463 3466
3464 3467 if (last - first < 2)
3465 3468 return (first);
3466 3469
3467 3470 const char *t = first;
3468 3471 const char *t2 = NULL;
3469 3472 boolean_t global = B_FALSE;
3470 3473 size_t n;
3471 3474
3472 3475 if (t[0] == 'g' && t[1] == 's') {
3473 3476 global = B_TRUE;
3474 3477 t += 2;
3475 3478 }
3476 3479 if (t == last)
3477 3480 return (first);
3478 3481
3479 3482 t2 = parse_base_unresolved_name(t, last, db);
3480 3483 if (t != t2) {
3481 3484 if (global) {
3482 3485 if (nempty(db))
3483 3486 return (first);
3484 3487
3485 3488 str_insert(TOP_L(db), 0, "::", 2);
3486 3489 }
3487 3490 return (t2);
3488 3491 }
3489 3492
3490 3493 if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3491 3494 return (first);
3492 3495
3493 3496 n = nlen(db);
3494 3497 if (t[2] == 'N') {
3495 3498 t += 3;
3496 3499 t2 = parse_unresolved_type(t, last, db);
3497 3500 if (t2 == t || t2 == last)
3498 3501 return (first);
3499 3502 t = t2;
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
3500 3503
3501 3504 t2 = parse_template_args(t, last, db);
3502 3505 if (t2 != t) {
3503 3506 if (NAMT(db, n) < 2 || t2 == last)
3504 3507 return (first);
3505 3508
3506 3509 nfmt(db, "{1:L}{0}", "{1:R}");
3507 3510 t = t2;
3508 3511 }
3509 3512
3510 - ASSERT3U(NAMT(db, n), ==, 1);
3513 + VERIFY3U(NAMT(db, n), ==, 1);
3511 3514
3512 3515 while (t[0] != 'E') {
3513 3516 size_t nn = nlen(db);
3514 3517 t2 = parse_unresolved_qualifier_level(t, last, db);
3515 3518 if (t == t2 || t == last || NAMT(db, nn) != 1)
3516 3519 return (first);
3517 3520
3518 3521 t = t2;
3519 3522 }
3520 3523
3521 3524 /* skip E */
3522 3525 t++;
3523 3526
3524 3527 t2 = parse_base_unresolved_name(t, last, db);
3525 3528 if (t == t2 || NAMT(db, n) < 2)
3526 3529 return (first);
3527 3530
3528 3531 njoin(db, NAMT(db, n), "::");
3529 3532 return (t2);
3530 3533 }
3531 3534
3532 3535 t += 2;
3533 3536
3534 3537 t2 = parse_unresolved_type(t, last, db);
3535 3538 if (t != t2) {
3536 3539 t = t2;
3537 3540 t2 = parse_template_args(t, last, db);
3538 3541 if (t2 != t)
3539 3542 nfmt(db, "{1:L}{0}", "{1:R}");
3540 3543 t = t2;
3541 3544
3542 3545 t2 = parse_base_unresolved_name(t, last, db);
3543 3546 if (t == t2 || nlen(db) < 2)
3544 3547 return (first);
3545 3548
3546 3549 nfmt(db, "{1:L}::{0}", "{1:R}");
3547 3550 return (t2);
3548 3551 }
3549 3552
3550 3553 t2 = parse_unresolved_qualifier_level(t, last, db);
3551 3554 if (t2 == t || t2 == last)
3552 3555 return (first);
3553 3556
3554 3557 t = t2;
3555 3558 if (global && nlen(db) > 0)
3556 3559 nfmt(db, "::{0:L}", "{0:R}");
3557 3560
3558 3561 while (t[0] != 'E') {
3559 3562 t2 = parse_unresolved_qualifier_level(t, last, db);
3560 3563 if (t == t2 || t == last || nlen(db) < 2)
3561 3564 return (first);
3562 3565
3563 3566 t = t2;
3564 3567 }
3565 3568
3566 3569 /* skip E */
3567 3570 t++;
3568 3571
3569 3572 t2 = parse_base_unresolved_name(t, last, db);
3570 3573 if (t == t2 || nlen(db) < 2)
3571 3574 return (first);
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
3572 3575
3573 3576 njoin(db, NAMT(db, n), "::");
3574 3577 return (t2);
3575 3578 }
3576 3579
3577 3580 /* <unresolved-qualifier-level> ::= <simple-id> */
3578 3581 static const char *
3579 3582 parse_unresolved_qualifier_level(const char *first, const char *last,
3580 3583 cpp_db_t *db)
3581 3584 {
3582 - ASSERT3P(first, <=, last);
3585 + VERIFY3P(first, <=, last);
3583 3586 return (parse_simple_id(first, last, db));
3584 3587 }
3585 3588
3586 3589 /* BEGIN CSTYLED */
3587 3590 /*
3588 3591 * <base-unresolved-name> ::= <simple-id> # unresolved name
3589 3592 * extension ::= <operator-name> # unresolved operator-function-id
3590 3593 * extension ::= <operator-name> <template-args> # unresolved operator template-id
3591 3594 * ::= on <operator-name> # unresolved operator-function-id
3592 3595 * ::= on <operator-name> <template-args> # unresolved operator template-id
3593 3596 * ::= dn <destructor-name> # destructor or pseudo-destructor;
3594 3597 * # e.g. ~X or ~X<N-1>
3595 3598 */
3596 3599 /* END CSTYLED */
3597 3600 static const char *
3598 3601 parse_base_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3599 3602 {
3600 - ASSERT3P(first, <=, last);
3603 + VERIFY3P(first, <=, last);
3601 3604
3602 3605 if (last - first < 2)
3603 3606 return (first);
3604 3607
3605 3608 const char *t = NULL;
3606 3609 const char *t1 = NULL;
3607 3610
3608 3611 if ((first[0] != 'o' && first[0] != 'd') || first[1] != 'n') {
3609 3612 t = parse_simple_id(first, last, db);
3610 3613 if (t != first)
3611 3614 return (t);
3612 3615
3613 3616 t = parse_operator_name(first, last, db);
3614 3617 if (t == first)
3615 3618 return (first);
3616 3619
3617 3620 t1 = parse_template_args(t, last, db);
3618 3621 if (t1 != t) {
3619 3622 if (nlen(db) < 2)
3620 3623 return (first);
3621 3624 nfmt(db, "{1:L}{0}", "{1:R}");
3622 3625 }
3623 3626
3624 3627 return (t1);
3625 3628 }
3626 3629
3627 3630 if (first[0] == 'd') {
3628 3631 t = parse_destructor_name(first + 2, last, db);
3629 3632 return ((t != first + 2) ? t : first);
3630 3633 }
3631 3634
3632 3635 t = parse_operator_name(first + 2, last, db);
3633 3636 if (t == first + 2)
3634 3637 return (first);
3635 3638
3636 3639 t1 = parse_template_args(t, last, db);
3637 3640 if (t1 != t)
3638 3641 nfmt(db, "{1:L}{0}", "{1:R}");
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
3639 3642 return (t1);
3640 3643 }
3641 3644
3642 3645 /*
3643 3646 * <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3644 3647 * ::= <simple-id> # e.g., ~A<2*N>
3645 3648 */
3646 3649 static const char *
3647 3650 parse_destructor_name(const char *first, const char *last, cpp_db_t *db)
3648 3651 {
3649 - ASSERT3P(first, <=, last);
3652 + VERIFY3P(first, <=, last);
3650 3653
3651 3654 if (first == last)
3652 3655 return (first);
3653 3656
3654 3657 const char *t = parse_unresolved_type(first, last, db);
3655 3658
3656 3659 if (t == first)
3657 3660 t = parse_simple_id(first, last, db);
3658 3661
3659 3662 if (t == first)
3660 3663 return (first);
3661 3664
3662 3665 nfmt(db, "~{0:L}", "{0:R}");
3663 3666 return (t);
3664 3667 }
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
3665 3668
3666 3669 /*
3667 3670 * <ref-qualifier> ::= R # & ref-qualifier
3668 3671 * <ref-qualifier> ::= O # && ref-qualifier
3669 3672 *
3670 3673 * <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
3671 3674 */
3672 3675 static const char *
3673 3676 parse_function_type(const char *first, const char *last, cpp_db_t *db)
3674 3677 {
3675 - ASSERT3P(first, <=, last);
3678 + VERIFY3P(first, <=, last);
3676 3679
3677 3680 if (last - first < 2)
3678 3681 return (first);
3679 3682
3680 - ASSERT3U(first[0], ==, 'F');
3683 + VERIFY3U(first[0], ==, 'F');
3681 3684
3682 3685 const char *t = first + 1;
3683 3686
3684 3687 /* extern "C" */
3685 3688 if (t[0] == 'Y')
3686 3689 t++;
3687 3690
3688 3691 const char *t1 = parse_type(t, last, db);
3689 3692 if (t1 == t)
3690 3693 return (first);
3691 3694
3692 3695 size_t n = nlen(db);
3693 3696 int ref_qual = 0;
3694 3697
3695 3698 t = t1;
3696 3699
3697 3700 while (t != last && t[0] != 'E') {
3698 3701 if (t[0] == 'v') {
3699 3702 t++;
3700 3703 continue;
3701 3704 }
3702 3705
3703 3706 if (t[0] == 'R' && t + 1 != last && t[1] == 'E') {
3704 3707 ref_qual = 1;
3705 3708 t++;
3706 3709 continue;
3707 3710 }
3708 3711
3709 3712 if (t[0] == 'O' && t + 1 != last && t[1] == 'E') {
3710 3713 ref_qual = 2;
3711 3714 t++;
3712 3715 continue;
3713 3716 }
3714 3717
3715 3718
3716 3719 t1 = parse_type(t, last, db);
3717 3720 if (t1 == t || t == last)
3718 3721 return (first);
3719 3722
3720 3723 t = t1;
3721 3724 }
3722 3725
3723 3726 if (t == last)
3724 3727 return (first);
3725 3728
3726 3729 njoin(db, NAMT(db, n), ", ");
3727 3730 nfmt(db, "({0})", NULL);
3728 3731
3729 3732 switch (ref_qual) {
3730 3733 case 1:
3731 3734 nfmt(db, "{0} &", NULL);
3732 3735 break;
3733 3736 case 2:
3734 3737 nfmt(db, "{0} &&", NULL);
3735 3738 break;
3736 3739 }
3737 3740
3738 3741 nfmt(db, "{1:L} ", "{0}{1:R}");
3739 3742
3740 3743 /* skip E */
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
3741 3744 return (t + 1);
3742 3745 }
3743 3746
3744 3747 /*
3745 3748 * <template-param> ::= T_ # first template parameter
3746 3749 * ::= T <parameter-2 non-negative number> _
3747 3750 */
3748 3751 static const char *
3749 3752 parse_template_param(const char *first, const char *last, cpp_db_t *db)
3750 3753 {
3751 - ASSERT3P(first, <=, last);
3754 + VERIFY3P(first, <=, last);
3752 3755
3753 3756 if (last - first < 2 || first[0] != 'T')
3754 3757 return (first);
3755 3758
3756 3759 const char *t = first + 1;
3757 3760 size_t idx = 0;
3758 3761
3759 3762 while (t != last && t[0] != '_') {
3760 - if (!is_digit(t[0]))
3763 + if (!isdigit_l(t[0], db->cpp_loc))
3761 3764 return (first);
3762 3765
3763 3766 idx *= 10;
3764 3767 idx += t[0] - '0';
3765 3768 t++;
3766 3769 }
3767 3770
3768 3771 if (t == last)
3769 3772 return (first);
3770 3773
3771 - ASSERT3U(t[0], ==, '_');
3774 + VERIFY3U(t[0], ==, '_');
3772 3775
3773 3776 /*
3774 3777 * T_ -> idx 0
3775 3778 * T0 -> idx 1
3776 3779 * T1 -> idx 2
3777 3780 * ...
3778 3781 */
3779 3782 if (first[1] != '_')
3780 3783 idx++;
3781 3784
3782 3785 /* skip _ */
3783 3786 t++;
3784 3787
3785 3788 if (tempty(db))
3786 3789 return (first);
3787 3790
3788 3791 if (idx >= ttlen(db)) {
3789 3792 nadd_l(db, first, (size_t)(t - first));
3790 3793 db->cpp_fix_forward_references = B_TRUE;
3791 3794 return (t);
3792 3795 }
3793 3796
3794 3797 tsub(db, idx);
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
3795 3798 return (t);
3796 3799 }
3797 3800
3798 3801 /*
3799 3802 * <template-args> ::= I <template-arg>* E
3800 3803 * extension, the abi says <template-arg>+
3801 3804 */
3802 3805 static const char *
3803 3806 parse_template_args(const char *first, const char *last, cpp_db_t *db)
3804 3807 {
3805 - ASSERT3P(first, <=, last);
3808 + VERIFY3P(first, <=, last);
3806 3809
3807 3810 if (last - first < 2 || first[0] != 'I')
3808 3811 return (first);
3809 3812
3810 3813 if (db->cpp_tag_templates)
3811 3814 sub_clear(templ_top(&db->cpp_templ));
3812 3815
3813 3816 const char *t = first + 1;
3814 3817 size_t n = nlen(db);
3815 3818
3816 3819 while (t[0] != 'E') {
3817 3820 if (db->cpp_tag_templates)
3818 3821 tpush(db);
3819 3822
3820 3823 size_t n1 = nlen(db);
3821 3824 const char *t1 = parse_template_arg(t, last, db);
3822 3825
3823 3826 if (db->cpp_tag_templates)
3824 3827 tpop(db);
3825 3828
3826 3829 if (t1 == t || t == last)
3827 3830 return (first);
3828 3831
3829 3832 if (db->cpp_tag_templates)
3830 3833 tsave(db, NAMT(db, n1));
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
3831 3834
3832 3835 t = t1;
3833 3836 }
3834 3837
3835 3838 /*
3836 3839 * ugly, but if the last thing pushed was an empty string,
3837 3840 * get rid of it so we dont get "<..., >"
3838 3841 */
3839 3842 if (NAMT(db, n) > 1 &&
3840 3843 str_pair_len(name_top(&db->cpp_name)) == 0)
3841 - (void) name_pop(&db->cpp_name, NULL);
3844 + name_pop(&db->cpp_name, NULL);
3842 3845
3843 3846 njoin(db, NAMT(db, n), ", ");
3844 3847
3845 - ASSERT3U(nlen(db), >, 0);
3848 + VERIFY3U(nlen(db), >, 0);
3846 3849
3847 3850 /* make sure we don't bitshift ourselves into oblivion */
3848 3851 str_t *top = TOP_L(db);
3849 3852 if (str_length(top) > 0 &&
3850 3853 top->str_s[top->str_len - 1] == '>')
3851 3854 nfmt(db, "<{0} >", NULL);
3852 3855 else
3853 3856 nfmt(db, "<{0}>", NULL);
3854 3857
3855 3858 /* skip E */
3856 3859 return (t + 1);
3857 3860 }
3858 3861
3859 3862 /*
3860 3863 * <discriminator> := _ <non-negative number> # when number < 10
3861 3864 * := __ <non-negative number> _ # when number >= 10
3862 3865 * extension := decimal-digit+ # at the end of string
3863 3866 */
3864 3867 static const char *
3865 -parse_discriminator(const char *first, const char *last)
3868 +parse_discriminator(const char *first, const char *last, locale_t loc)
3866 3869 {
3867 - ASSERT3P(first, <=, last);
3870 + VERIFY3P(first, <=, last);
3868 3871
3869 3872 const char *t = NULL;
3870 3873
3871 3874 if (first == last)
3872 3875 return (first);
3873 3876
3874 - if (is_digit(first[0])) {
3875 - for (t = first; t != last && is_digit(t[0]); t++)
3877 + if (isdigit_l(first[0], loc)) {
3878 + for (t = first; t != last && isdigit_l(t[0], loc); t++)
3876 3879 ;
3877 3880
3878 3881 /* not at the end of the string */
3879 3882 if (t != last)
3880 3883 return (first);
3881 3884
3882 3885 return (t);
3883 3886 } else if (first[0] != '_' || first + 1 == last) {
3884 3887 return (first);
3885 3888 }
3886 3889
3887 3890 t = first + 1;
3888 - if (is_digit(t[0]))
3891 + if (isdigit_l(t[0], loc))
3889 3892 return (t + 1);
3890 3893
3891 3894 if (t[0] != '_' || t + 1 == last)
3892 3895 return (first);
3893 3896
3894 - for (t++; t != last && is_digit(t[0]); t++)
3897 + for (t++; t != last && isdigit_l(t[0], loc); t++)
3895 3898 ;
3896 3899 if (t == last || t[0] != '_')
3897 3900 return (first);
3898 3901
3899 3902 return (t);
3900 3903 }
3901 3904
3902 3905 /* <CV-qualifiers> ::= [r] [V] [K] */
3903 3906 const char *
3904 3907 parse_cv_qualifiers(const char *first, const char *last, unsigned *cv)
3905 3908 {
3906 - ASSERT3P(first, <=, last);
3909 + VERIFY3P(first, <=, last);
3907 3910
3908 3911 if (first == last)
3909 3912 return (first);
3910 3913
3911 3914 *cv = 0;
3912 3915 if (first[0] == 'r') {
3913 3916 *cv |= CPP_QUAL_RESTRICT;
3914 3917 first++;
3915 3918 }
3916 3919 if (first != last && first[0] == 'V') {
3917 3920 *cv |= CPP_QUAL_VOLATILE;
3918 3921 first++;
3919 3922 }
3920 3923 if (first != last && first[0] == 'K') {
3921 3924 *cv |= CPP_QUAL_CONST;
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
3922 3925 first++;
3923 3926 }
3924 3927
3925 3928 return (first);
3926 3929 }
3927 3930
3928 3931 /*
3929 3932 * <number> ::= [n] <non-negative decimal integer>
3930 3933 */
3931 3934 static const char *
3932 -parse_number(const char *first, const char *last)
3935 +parse_number(const char *first, const char *last, locale_t loc)
3933 3936 {
3934 - ASSERT3P(first, <=, last);
3937 + VERIFY3P(first, <=, last);
3935 3938
3936 3939 const char *t = first;
3937 3940
3938 - if (first == last || (first[0] != 'n' && !is_digit(first[0])))
3941 + if (first == last || (first[0] != 'n' && !isdigit_l(first[0], loc)))
3939 3942 return (first);
3940 3943
3941 3944 if (t[0] == 'n')
3942 3945 t++;
3943 3946
3944 3947 if (t[0] == '0')
3945 3948 return (t + 1);
3946 3949
3947 - while (is_digit(t[0]))
3950 + while (isdigit_l(t[0], loc))
3948 3951 t++;
3949 3952
3950 3953 return (t);
3951 3954 }
3952 3955
3953 3956 /*
3954 - * we only ever use ASCII versions of these
3957 + * Like isxdigit(3C), except we can only accept lower case letters as
3958 + * that's only what is allowed when [de]mangling floating point constants into
3959 + * their hex representation.
3955 3960 */
3956 3961 static inline boolean_t
3957 -is_digit(int c)
3958 -{
3959 - if (c < '0' || c > '9')
3960 - return (B_FALSE);
3961 - return (B_TRUE);
3962 -}
3963 -
3964 -static inline boolean_t
3965 -is_upper(int c)
3966 -{
3967 - if (c < 'A' || c > 'Z')
3968 - return (B_FALSE);
3969 - return (B_TRUE);
3970 -}
3971 -
3972 -static inline boolean_t
3973 3962 is_xdigit(int c)
3974 3963 {
3975 3964 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
3976 3965 return (B_TRUE);
3977 3966 return (B_FALSE);
3978 3967 }
3979 3968
3980 3969 static boolean_t
3981 3970 nempty(cpp_db_t *db)
3982 3971 {
3983 3972 return (name_empty(&db->cpp_name));
3984 3973 }
3985 3974
3986 3975 static size_t
3987 3976 nlen(cpp_db_t *db)
3988 3977 {
3989 3978 return (name_len(&db->cpp_name));
3990 3979 }
3991 3980
3992 3981 static void
3993 3982 nadd_l(cpp_db_t *db, const char *s, size_t len)
3994 3983 {
3995 3984 CK(name_add(&db->cpp_name, s, len, NULL, 0));
3996 3985 }
3997 3986
3998 3987 static void
3999 3988 njoin(cpp_db_t *db, size_t amt, const char *sep)
4000 3989 {
4001 3990 name_t *nm = &db->cpp_name;
4002 3991
4003 3992 CK(name_join(nm, amt, sep));
4004 3993 }
4005 3994
4006 3995 static void
4007 3996 nfmt(cpp_db_t *db, const char *fmt_l, const char *fmt_r)
4008 3997 {
4009 3998 CK(name_fmt(&db->cpp_name, fmt_l, fmt_r));
4010 3999 }
4011 4000
4012 4001 static void
4013 4002 save_top(cpp_db_t *db, size_t amt)
4014 4003 {
4015 4004 CK(sub_save(&db->cpp_subs, &db->cpp_name, amt));
4016 4005 }
4017 4006
4018 4007 static void
4019 4008 sub(cpp_db_t *db, size_t n)
4020 4009 {
4021 4010 CK(sub_substitute(&db->cpp_subs, n, &db->cpp_name));
4022 4011 }
4023 4012
4024 4013 static boolean_t
4025 4014 tempty(const cpp_db_t *db)
4026 4015 {
4027 4016 return (templ_empty(&db->cpp_templ) ? B_TRUE : B_FALSE);
4028 4017 }
4029 4018
4030 4019 static size_t
4031 4020 ttlen(const cpp_db_t *db)
4032 4021 {
4033 4022 return (templ_top_len(&db->cpp_templ));
4034 4023 }
4035 4024
4036 4025 static void
4037 4026 tsub(cpp_db_t *db, size_t n)
4038 4027 {
4039 4028 CK(templ_sub(&db->cpp_templ, n, &db->cpp_name));
4040 4029 }
4041 4030
4042 4031 static void
4043 4032 tpush(cpp_db_t *db)
4044 4033 {
4045 4034 CK(templ_push(&db->cpp_templ));
4046 4035 }
4047 4036
4048 4037 static void
4049 4038 tpop(cpp_db_t *db)
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
4050 4039 {
4051 4040 templ_pop(&db->cpp_templ);
4052 4041 }
4053 4042
4054 4043 static void
4055 4044 tsave(cpp_db_t *db, size_t amt)
4056 4045 {
4057 4046 CK(templ_save(&db->cpp_name, amt, &db->cpp_templ));
4058 4047 }
4059 4048
4060 -static void
4049 +static boolean_t
4061 4050 db_init(cpp_db_t *db, sysdem_ops_t *ops)
4062 4051 {
4063 4052 (void) memset(db, 0, sizeof (*db));
4064 4053 db->cpp_ops = ops;
4065 4054 name_init(&db->cpp_name, ops);
4066 4055 sub_init(&db->cpp_subs, ops);
4067 4056 templ_init(&db->cpp_templ, ops);
4068 4057 db->cpp_tag_templates = B_TRUE;
4069 4058 db->cpp_try_to_parse_template_args = B_TRUE;
4070 4059 tpush(db);
4060 + db->cpp_loc = newlocale(LC_CTYPE_MASK, "C", 0);
4061 + return ((db->cpp_loc != NULL) ? B_TRUE : B_FALSE);
4071 4062 }
4072 4063
4073 4064 static void
4074 4065 db_fini(cpp_db_t *db)
4075 4066 {
4076 4067 name_fini(&db->cpp_name);
4077 4068 sub_fini(&db->cpp_subs);
4078 4069 templ_fini(&db->cpp_templ);
4070 + freelocale(db->cpp_loc);
4079 4071 (void) memset(db, 0, sizeof (*db));
4080 4072 }
4081 4073
4082 4074 static void
4083 4075 print_sp(const str_pair_t *sp, FILE *out)
4084 4076 {
4085 4077 (void) fprintf(out, "{%.*s#%.*s}",
4086 4078 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4087 4079 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4088 4080 }
4089 4081
4090 4082 static void
4091 4083 print_name(const name_t *n, FILE *out)
4092 4084 {
4093 4085 const str_pair_t *sp = name_top((name_t *)n);
4094 4086 size_t i;
4095 4087
4096 4088 (void) fprintf(out, "Name:\n");
4097 4089
4098 4090 if (name_len(n) == 0)
4099 4091 return;
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
4100 4092
4101 4093 for (i = 0; i < n->nm_len; i++, sp--) {
4102 4094 (void) fprintf(out, " [%02zu] ", i);
4103 4095 print_sp(sp, out);
4104 4096 (void) fputc('\n', out);
4105 4097 }
4106 4098
4107 4099 (void) fputc('\n', out);
4108 4100 }
4109 4101
4110 -
4102 +/* Print a base-36 number (for substitutions) */
4111 4103 static char *
4112 4104 base36(char *buf, size_t val)
4113 4105 {
4114 4106 char tmp[16] = { 0 };
4115 4107 char *p = tmp;
4116 4108
4117 4109 if (val == 0) {
4118 4110 buf[0] = '0';
4119 4111 buf[1] = '\0';
4120 4112 return (buf);
4121 4113 }
4122 4114
4123 4115 while (val > 0) {
4124 4116 size_t r = val % 36;
4125 4117
4126 4118 if (r < 10)
4127 4119 *p++ = r + '0';
4128 4120 else
4129 4121 *p++ = r - 10 + 'A';
4130 4122
4131 4123 val /= 36;
4132 4124 }
4133 4125
4134 4126 char *q = buf;
4135 4127 while (--p >= tmp)
4136 4128 *q++ = *p;
4137 4129
4138 4130 return (buf);
4139 4131 }
4140 4132
4141 4133 static void
4142 4134 print_sub(const sub_t *sub, FILE *out)
4143 4135 {
4144 4136 const name_t *n = sub->sub_items;
4145 4137
4146 4138 (void) fprintf(out, "Substitutions:\n");
4147 4139
4148 4140 if (sub->sub_len == 0)
4149 4141 return;
4150 4142
4151 4143 for (size_t i = 0; i < sub->sub_len; i++, n++) {
4152 4144 (void) printf(" ");
4153 4145 if (i == 0) {
4154 4146 (void) fprintf(out, "%-4s", "S_");
4155 4147 } else {
4156 4148 char buf[16] = { 0 };
4157 4149 char buf2[16] = { 0 };
4158 4150
4159 4151 (void) snprintf(buf, sizeof (buf), "S%s_",
4160 4152 base36(buf2, i));
4161 4153 (void) fprintf(out, "%-4s", buf);
4162 4154 }
4163 4155 (void) fprintf(out, " = ");
4164 4156
4165 4157 (void) fputc('{', out);
4166 4158 for (size_t j = 0; j < n->nm_len; j++) {
4167 4159 if (j > 0)
4168 4160 (void) fputc(' ', out);
4169 4161 print_sp(&n->nm_items[j], out);
4170 4162 }
4171 4163 (void) fputc('}', out);
4172 4164
4173 4165 (void) fputc('\n', out);
4174 4166 }
4175 4167 (void) fputc('\n', out);
4176 4168 }
4177 4169
4178 4170 static void
4179 4171 print_templ(const templ_t *tpl, FILE *out)
4180 4172 {
4181 4173
4182 4174 (void) fprintf(out, "Template\n");
4183 4175
4184 4176 const sub_t *s = templ_top((templ_t *)tpl);
4185 4177
4186 4178 for (size_t i = 0; i < s->sub_len; i++) {
4187 4179 char buf[16] = { 0 };
4188 4180
4189 4181 if (i == 0)
4190 4182 (void) snprintf(buf, sizeof (buf), "%s", "T_");
4191 4183 else
4192 4184 (void) snprintf(buf, sizeof (buf), "T%zu_", i - 1);
4193 4185
4194 4186 (void) fprintf(out, " %-4s = ", buf);
4195 4187
4196 4188 (void) fputc('{', out);
4197 4189
4198 4190 const name_t *n = &s->sub_items[i];
4199 4191 for (size_t j = 0; j < n->nm_len; j++) {
4200 4192 const str_pair_t *sp = &n->nm_items[j];
4201 4193
4202 4194 if (j > 0)
4203 4195 (void) fputc(' ', out);
4204 4196
4205 4197 (void) fprintf(out, "{%.*s#%.*s}",
4206 4198 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4207 4199 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4208 4200 }
4209 4201 (void) fprintf(out, "}\n");
4210 4202 }
4211 4203 (void) fprintf(out, "\n");
4212 4204 }
4213 4205
4214 4206 static void
4215 4207 dump(cpp_db_t *db, FILE *out)
4216 4208 {
4217 4209 print_name(&db->cpp_name, out);
4218 4210 print_sub(&db->cpp_subs, out);
4219 4211 print_templ(&db->cpp_templ, out);
4220 4212 }
↓ open down ↓ |
100 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX