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