| author | |
| committer | |
| log | a5251a1c102334a5dcb07e4fcc2b676be55fe2be |
| tree | 459d720365823b10473be028d25ad86b87b825f5 |
| parent | 100e8e15fa087be8975173c03a2f89b227b16730 |
4 files changed, 79 insertions(+), 6 deletions(-)
src/ast_render.cpp+8-4| ... | ... | @@ -251,7 +251,7 @@ static bool is_digit(uint8_t c) { |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 253 | static bool is_printable(uint8_t c) { |
| 254 | return is_alpha_under(c) || is_digit(c); | |
| 254 | return is_alpha_under(c) || is_digit(c) || c == ' '; | |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | 257 | static void string_literal_escape(Buf *source, Buf *dest) { |
| ... | ... | @@ -463,10 +463,14 @@ static void render_node(AstRender *ar, AstNode *node) { |
| 463 | 463 | } |
| 464 | 464 | break; |
| 465 | 465 | case NodeTypeStringLiteral: |
| 466 | if (node->data.string_literal.c) { | |
| 467 | fprintf(ar->f, "c"); | |
| 466 | { | |
| 467 | if (node->data.string_literal.c) { | |
| 468 | fprintf(ar->f, "c"); | |
| 469 | } | |
| 470 | Buf tmp_buf = BUF_INIT; | |
| 471 | string_literal_escape(&node->data.string_literal.buf, &tmp_buf); | |
| 472 | fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf)); | |
| 468 | 473 | } |
| 469 | fprintf(ar->f, "\"%s\"", buf_ptr(&node->data.string_literal.buf)); | |
| 470 | 474 | break; |
| 471 | 475 | case NodeTypeCharLiteral: |
| 472 | 476 | { |
src/c_tokenizer.cpp+59-2| ... | ... | @@ -539,8 +539,17 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) { |
| 539 | 539 | case 'v': |
| 540 | 540 | add_char(ctok, '\v'); |
| 541 | 541 | break; |
| 542 | case DIGIT: | |
| 543 | zig_panic("TODO octal"); | |
| 542 | case '0': | |
| 543 | case '1': | |
| 544 | case '2': | |
| 545 | case '3': | |
| 546 | case '4': | |
| 547 | case '5': | |
| 548 | case '6': | |
| 549 | case '7': | |
| 550 | ctok->state = CTokStateStrOctal; | |
| 551 | ctok->cur_char = *c - '0'; | |
| 552 | ctok->octal_index = 1; | |
| 544 | 553 | break; |
| 545 | 554 | case 'x': |
| 546 | 555 | zig_panic("TODO hex"); |
| ... | ... | @@ -555,6 +564,53 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) { |
| 555 | 564 | return mark_error(ctok); |
| 556 | 565 | } |
| 557 | 566 | break; |
| 567 | case CTokStateStrOctal: | |
| 568 | switch (*c) { | |
| 569 | case '0': | |
| 570 | case '1': | |
| 571 | case '2': | |
| 572 | case '3': | |
| 573 | case '4': | |
| 574 | case '5': | |
| 575 | case '6': | |
| 576 | case '7': | |
| 577 | // TODO @mul_with_overflow | |
| 578 | if (((long)ctok->cur_char) * 8 >= 256) { | |
| 579 | zig_panic("TODO"); | |
| 580 | } | |
| 581 | ctok->cur_char *= 8; | |
| 582 | // TODO @add_with_overflow | |
| 583 | if (((long)ctok->cur_char) + (long)(*c - '0') >= 256) { | |
| 584 | zig_panic("TODO"); | |
| 585 | } | |
| 586 | ctok->cur_char += *c - '0'; | |
| 587 | ctok->octal_index += 1; | |
| 588 | if (ctok->octal_index == 3) { | |
| 589 | if (ctok->cur_tok->id == CTokIdStrLit) { | |
| 590 | add_char(ctok, ctok->cur_char); | |
| 591 | ctok->state = CTokStateString; | |
| 592 | } else if (ctok->cur_tok->id == CTokIdCharLit) { | |
| 593 | ctok->cur_tok->data.char_lit = ctok->cur_char; | |
| 594 | ctok->state = CTokStateExpectEndQuot; | |
| 595 | } else { | |
| 596 | zig_unreachable(); | |
| 597 | } | |
| 598 | } | |
| 599 | break; | |
| 600 | default: | |
| 601 | c -= 1; | |
| 602 | if (ctok->cur_tok->id == CTokIdStrLit) { | |
| 603 | add_char(ctok, ctok->cur_char); | |
| 604 | ctok->state = CTokStateString; | |
| 605 | } else if (ctok->cur_tok->id == CTokIdCharLit) { | |
| 606 | ctok->cur_tok->data.char_lit = ctok->cur_char; | |
| 607 | ctok->state = CTokStateExpectEndQuot; | |
| 608 | } else { | |
| 609 | zig_unreachable(); | |
| 610 | } | |
| 611 | continue; | |
| 612 | } | |
| 613 | break; | |
| 558 | 614 | case CTokStateExpectEndQuot: |
| 559 | 615 | switch (*c) { |
| 560 | 616 | case '\'': |
| ... | ... | @@ -644,6 +700,7 @@ found_end_of_macro: |
| 644 | 700 | case CTokStateString: |
| 645 | 701 | case CTokStateExpSign: |
| 646 | 702 | case CTokStateFloatExpFirst: |
| 703 | case CTokStateStrOctal: | |
| 647 | 704 | return mark_error(ctok); |
| 648 | 705 | } |
| 649 | 706 |
src/c_tokenizer.hpp+3| ... | ... | @@ -53,6 +53,7 @@ enum CTokState { |
| 53 | 53 | CTokStateExpSign, |
| 54 | 54 | CTokStateFloatExp, |
| 55 | 55 | CTokStateFloatExpFirst, |
| 56 | CTokStateStrOctal, | |
| 56 | 57 | }; |
| 57 | 58 | |
| 58 | 59 | struct CTokenize { |
| ... | ... | @@ -63,6 +64,8 @@ struct CTokenize { |
| 63 | 64 | Buf buf; |
| 64 | 65 | bool unsigned_suffix; |
| 65 | 66 | bool long_suffix; |
| 67 | uint8_t cur_char; | |
| 68 | int octal_index; | |
| 66 | 69 | }; |
| 67 | 70 | |
| 68 | 71 | void tokenize_c_macro(CTokenize *ctok, const uint8_t *c); |
test/run_tests.cpp+9| ... | ... | @@ -1731,6 +1731,15 @@ struct type { |
| 1731 | 1731 | )SOURCE", 2, R"(export struct struct_type { |
| 1732 | 1732 | @"defer": c_int, |
| 1733 | 1733 | })", R"(pub const @"type" = struct_type;)"); |
| 1734 | ||
| 1735 | add_parseh_case("macro defines string literal with octal", R"SOURCE( | |
| 1736 | #define FOO "aoeu\023 derp" | |
| 1737 | #define FOO2 "aoeu\0234 derp" | |
| 1738 | #define FOO_CHAR '\077' | |
| 1739 | )SOURCE", 3, | |
| 1740 | R"(pub const FOO = c"aoeu\x13 derp")", | |
| 1741 | R"(pub const FOO2 = c"aoeu\x134 derp")", | |
| 1742 | R"(pub const FOO_CHAR = '\x3f')"); | |
| 1734 | 1743 | } |
| 1735 | 1744 | |
| 1736 | 1745 | static void run_self_hosted_test(bool is_release_mode) { |