authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-07-09 12:17:31-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-07-09 12:17:31-07:00
loga5251a1c102334a5dcb07e4fcc2b676be55fe2be
tree459d720365823b10473be028d25ad86b87b825f5
parent100e8e15fa087be8975173c03a2f89b227b16730

parseh: support octal in C macro string literal


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,7 +251,7 @@ static bool is_digit(uint8_t c) {
251}251}
252252
253static bool is_printable(uint8_t c) {253static 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}
256256
257static void string_literal_escape(Buf *source, Buf *dest) {257static void string_literal_escape(Buf *source, Buf *dest) {
...@@ -463,10 +463,14 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -463,10 +463,14 @@ static void render_node(AstRender *ar, AstNode *node) {
463 }463 }
464 break;464 break;
465 case NodeTypeStringLiteral:465 case NodeTypeStringLiteral:
466 if (node->data.string_literal.c) {466 {
467 fprintf(ar->f, "c");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 break;474 break;
471 case NodeTypeCharLiteral: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,8 +539,17 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
539 case 'v':539 case 'v':
540 add_char(ctok, '\v');540 add_char(ctok, '\v');
541 break;541 break;
542 case DIGIT:542 case '0':
543 zig_panic("TODO octal");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 break;553 break;
545 case 'x':554 case 'x':
546 zig_panic("TODO hex");555 zig_panic("TODO hex");
...@@ -555,6 +564,53 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {...@@ -555,6 +564,53 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
555 return mark_error(ctok);564 return mark_error(ctok);
556 }565 }
557 break;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 case CTokStateExpectEndQuot:614 case CTokStateExpectEndQuot:
559 switch (*c) {615 switch (*c) {
560 case '\'':616 case '\'':
...@@ -644,6 +700,7 @@ found_end_of_macro:...@@ -644,6 +700,7 @@ found_end_of_macro:
644 case CTokStateString:700 case CTokStateString:
645 case CTokStateExpSign:701 case CTokStateExpSign:
646 case CTokStateFloatExpFirst:702 case CTokStateFloatExpFirst:
703 case CTokStateStrOctal:
647 return mark_error(ctok);704 return mark_error(ctok);
648 }705 }
649706
src/c_tokenizer.hpp+3
...@@ -53,6 +53,7 @@ enum CTokState {...@@ -53,6 +53,7 @@ enum CTokState {
53 CTokStateExpSign,53 CTokStateExpSign,
54 CTokStateFloatExp,54 CTokStateFloatExp,
55 CTokStateFloatExpFirst,55 CTokStateFloatExpFirst,
56 CTokStateStrOctal,
56};57};
5758
58struct CTokenize {59struct CTokenize {
...@@ -63,6 +64,8 @@ struct CTokenize {...@@ -63,6 +64,8 @@ struct CTokenize {
63 Buf buf;64 Buf buf;
64 bool unsigned_suffix;65 bool unsigned_suffix;
65 bool long_suffix;66 bool long_suffix;
67 uint8_t cur_char;
68 int octal_index;
66};69};
6770
68void tokenize_c_macro(CTokenize *ctok, const uint8_t *c);71void tokenize_c_macro(CTokenize *ctok, const uint8_t *c);
test/run_tests.cpp+9
...@@ -1731,6 +1731,15 @@ struct type {...@@ -1731,6 +1731,15 @@ struct type {
1731 )SOURCE", 2, R"(export struct struct_type {1731 )SOURCE", 2, R"(export struct struct_type {
1732 @"defer": c_int,1732 @"defer": c_int,
1733})", R"(pub const @"type" = struct_type;)");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}
17351744
1736static void run_self_hosted_test(bool is_release_mode) {1745static void run_self_hosted_test(bool is_release_mode) {