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