| ... | ... | @@ -2469,6 +2469,74 @@ static void render_macros(Context *c) { |
| 2469 | 2469 | } |
| 2470 | 2470 | } |
| 2471 | 2471 | |
| 2472 | static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, bool negate) { |
| 2473 | CTok *tok = &ctok->tokens.at(*tok_i); |
| 2474 | if (tok->id == CTokIdNumLitInt) { |
| 2475 | *tok_i += 1; |
| 2476 | switch (tok->data.num_lit_int.suffix) { |
| 2477 | case CNumLitSuffixNone: |
| 2478 | return trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate); |
| 2479 | case CNumLitSuffixL: |
| 2480 | return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_long"); |
| 2481 | case CNumLitSuffixU: |
| 2482 | return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_uint"); |
| 2483 | case CNumLitSuffixLU: |
| 2484 | return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulong"); |
| 2485 | case CNumLitSuffixLL: |
| 2486 | return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_longlong"); |
| 2487 | case CNumLitSuffixLLU: |
| 2488 | return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulonglong"); |
| 2489 | } |
| 2490 | zig_unreachable(); |
| 2491 | } else if (tok->id == CTokIdNumLitFloat) { |
| 2492 | *tok_i += 1; |
| 2493 | double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float; |
| 2494 | return trans_create_node_float_lit(c, value); |
| 2495 | } |
| 2496 | return nullptr; |
| 2497 | } |
| 2498 | |
| 2499 | static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) { |
| 2500 | CTok *tok = &ctok->tokens.at(*tok_i); |
| 2501 | switch (tok->id) { |
| 2502 | case CTokIdCharLit: |
| 2503 | *tok_i += 1; |
| 2504 | return trans_create_node_unsigned(c, tok->data.char_lit); |
| 2505 | case CTokIdStrLit: |
| 2506 | *tok_i += 1; |
| 2507 | return trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit)); |
| 2508 | case CTokIdMinus: |
| 2509 | *tok_i += 1; |
| 2510 | return parse_ctok_num_lit(c, ctok, tok_i, true); |
| 2511 | case CTokIdNumLitInt: |
| 2512 | case CTokIdNumLitFloat: |
| 2513 | return parse_ctok_num_lit(c, ctok, tok_i, false); |
| 2514 | case CTokIdSymbol: |
| 2515 | { |
| 2516 | *tok_i += 1; |
| 2517 | Buf *symbol_name = buf_create_from_buf(&tok->data.symbol); |
| 2518 | return trans_create_node_symbol(c, symbol_name); |
| 2519 | } |
| 2520 | case CTokIdLParen: |
| 2521 | { |
| 2522 | *tok_i += 1; |
| 2523 | AstNode *inner_node = parse_ctok(c, ctok, tok_i); |
| 2524 | |
| 2525 | CTok *next_tok = &ctok->tokens.at(*tok_i); |
| 2526 | if (next_tok->id != CTokIdRParen) { |
| 2527 | return nullptr; |
| 2528 | } |
| 2529 | *tok_i += 1; |
| 2530 | return inner_node; |
| 2531 | } |
| 2532 | case CTokIdEOF: |
| 2533 | case CTokIdRParen: |
| 2534 | // not able to make sense of this |
| 2535 | return nullptr; |
| 2536 | } |
| 2537 | zig_unreachable(); |
| 2538 | } |
| 2539 | |
| 2472 | 2540 | static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) { |
| 2473 | 2541 | tokenize_c_macro(ctok, (const uint8_t *)char_ptr); |
| 2474 | 2542 | |
| ... | ... | @@ -2476,81 +2544,29 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 2476 | 2544 | return; |
| 2477 | 2545 | } |
| 2478 | 2546 | |
| 2479 | | bool negate = false; |
| 2480 | | for (size_t i = 0; i < ctok->tokens.length; i += 1) { |
| 2481 | | bool is_first = (i == 0); |
| 2482 | | bool is_last = (i == ctok->tokens.length - 1); |
| 2483 | | CTok *tok = &ctok->tokens.at(i); |
| 2484 | | switch (tok->id) { |
| 2485 | | case CTokIdCharLit: |
| 2486 | | if (is_last && is_first) { |
| 2487 | | AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit); |
| 2488 | | c->macro_table.put(name, node); |
| 2489 | | } |
| 2490 | | return; |
| 2491 | | case CTokIdStrLit: |
| 2492 | | if (is_last && is_first) { |
| 2493 | | AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit)); |
| 2494 | | c->macro_table.put(name, node); |
| 2495 | | } |
| 2496 | | return; |
| 2497 | | case CTokIdNumLitInt: |
| 2498 | | if (is_last) { |
| 2499 | | AstNode *node; |
| 2500 | | switch (tok->data.num_lit_int.suffix) { |
| 2501 | | case CNumLitSuffixNone: |
| 2502 | | node = trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate); |
| 2503 | | break; |
| 2504 | | case CNumLitSuffixL: |
| 2505 | | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, |
| 2506 | | "c_long"); |
| 2507 | | break; |
| 2508 | | case CNumLitSuffixU: |
| 2509 | | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, |
| 2510 | | "c_uint"); |
| 2511 | | break; |
| 2512 | | case CNumLitSuffixLU: |
| 2513 | | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, |
| 2514 | | "c_ulong"); |
| 2515 | | break; |
| 2516 | | case CNumLitSuffixLL: |
| 2517 | | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, |
| 2518 | | "c_longlong"); |
| 2519 | | break; |
| 2520 | | case CNumLitSuffixLLU: |
| 2521 | | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, |
| 2522 | | "c_ulonglong"); |
| 2523 | | break; |
| 2524 | | } |
| 2525 | | c->macro_table.put(name, node); |
| 2526 | | } |
| 2527 | | return; |
| 2528 | | case CTokIdNumLitFloat: |
| 2529 | | if (is_last) { |
| 2530 | | double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float; |
| 2531 | | AstNode *node = trans_create_node_float_lit(c, value); |
| 2532 | | c->macro_table.put(name, node); |
| 2533 | | } |
| 2534 | | return; |
| 2535 | | case CTokIdSymbol: |
| 2536 | | if (is_last && is_first) { |
| 2537 | | // if it equals itself, ignore. for example, from stdio.h: |
| 2538 | | // #define stdin stdin |
| 2539 | | Buf *symbol_name = buf_create_from_buf(&tok->data.symbol); |
| 2540 | | if (buf_eql_buf(name, symbol_name)) { |
| 2541 | | return; |
| 2542 | | } |
| 2543 | | c->macro_symbols.append({name, symbol_name}); |
| 2544 | | return; |
| 2545 | | } |
| 2546 | | case CTokIdMinus: |
| 2547 | | if (is_first) { |
| 2548 | | negate = true; |
| 2549 | | break; |
| 2550 | | } else { |
| 2551 | | return; |
| 2552 | | } |
| 2547 | size_t tok_i = 0; |
| 2548 | CTok *name_tok = &ctok->tokens.at(tok_i); |
| 2549 | assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name)); |
| 2550 | tok_i += 1; |
| 2551 | |
| 2552 | AstNode *result_node = parse_ctok(c, ctok, &tok_i); |
| 2553 | if (result_node == nullptr) { |
| 2554 | return; |
| 2555 | } |
| 2556 | CTok *eof_tok = &ctok->tokens.at(tok_i); |
| 2557 | if (eof_tok->id != CTokIdEOF) { |
| 2558 | return; |
| 2559 | } |
| 2560 | if (result_node->type == NodeTypeSymbol) { |
| 2561 | // if it equals itself, ignore. for example, from stdio.h: |
| 2562 | // #define stdin stdin |
| 2563 | Buf *symbol_name = result_node->data.symbol_expr.symbol; |
| 2564 | if (buf_eql_buf(name, symbol_name)) { |
| 2565 | return; |
| 2553 | 2566 | } |
| 2567 | c->macro_symbols.append({name, symbol_name}); |
| 2568 | } else { |
| 2569 | c->macro_table.put(name, result_node); |
| 2554 | 2570 | } |
| 2555 | 2571 | } |
| 2556 | 2572 | |
| ... | ... | @@ -2613,8 +2629,8 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 2613 | 2629 | continue; |
| 2614 | 2630 | } |
| 2615 | 2631 | |
| 2616 | | const char *end_c = c->source_manager->getCharacterData(end_loc); |
| 2617 | | process_macro(c, &ctok, name, end_c); |
| 2632 | const char *begin_c = c->source_manager->getCharacterData(begin_loc); |
| 2633 | process_macro(c, &ctok, name, begin_c); |
| 2618 | 2634 | } |
| 2619 | 2635 | } |
| 2620 | 2636 | } |