| ... | @@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) { | ... | @@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) { |
| 319 | } | 319 | } |
| 320 | | 320 | |
| 321 | static bool is_printable(uint8_t c) { | 321 | static bool is_printable(uint8_t c) { |
| | 322 | if (c == 0) { |
| | 323 | return false; |
| | 324 | } |
| 322 | static const uint8_t printables[] = | 325 | static const uint8_t printables[] = |
| 323 | " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; | 326 | " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; |
| 324 | for (size_t i = 0; i < array_length(printables); i += 1) { | 327 | for (size_t i = 0; i < array_length(printables); i += 1) { |
| ... | @@ -337,20 +340,12 @@ static void string_literal_escape(Buf *source, Buf *dest) { | ... | @@ -337,20 +340,12 @@ static void string_literal_escape(Buf *source, Buf *dest) { |
| 337 | buf_append_str(dest, "\\\""); | 340 | buf_append_str(dest, "\\\""); |
| 338 | } else if (c == '\\') { | 341 | } else if (c == '\\') { |
| 339 | buf_append_str(dest, "\\\\"); | 342 | buf_append_str(dest, "\\\\"); |
| 340 | } else if (c == '\a') { | | |
| 341 | buf_append_str(dest, "\\a"); | | |
| 342 | } else if (c == '\b') { | | |
| 343 | buf_append_str(dest, "\\b"); | | |
| 344 | } else if (c == '\f') { | | |
| 345 | buf_append_str(dest, "\\f"); | | |
| 346 | } else if (c == '\n') { | 343 | } else if (c == '\n') { |
| 347 | buf_append_str(dest, "\\n"); | 344 | buf_append_str(dest, "\\n"); |
| 348 | } else if (c == '\r') { | 345 | } else if (c == '\r') { |
| 349 | buf_append_str(dest, "\\r"); | 346 | buf_append_str(dest, "\\r"); |
| 350 | } else if (c == '\t') { | 347 | } else if (c == '\t') { |
| 351 | buf_append_str(dest, "\\t"); | 348 | buf_append_str(dest, "\\t"); |
| 352 | } else if (c == '\v') { | | |
| 353 | buf_append_str(dest, "\\v"); | | |
| 354 | } else if (is_printable(c)) { | 349 | } else if (is_printable(c)) { |
| 355 | buf_append_char(dest, c); | 350 | buf_append_char(dest, c); |
| 356 | } else { | 351 | } else { |
| ... | @@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 630 | case NodeTypeCharLiteral: | 625 | case NodeTypeCharLiteral: |
| 631 | { | 626 | { |
| 632 | uint8_t c = node->data.char_literal.value; | 627 | uint8_t c = node->data.char_literal.value; |
| 633 | if (is_printable(c)) { | 628 | if (c == '\'') { |
| | 629 | fprintf(ar->f, "'\\''"); |
| | 630 | } else if (c == '\"') { |
| | 631 | fprintf(ar->f, "'\\\"'"); |
| | 632 | } else if (c == '\\') { |
| | 633 | fprintf(ar->f, "'\\\\'"); |
| | 634 | } else if (c == '\n') { |
| | 635 | fprintf(ar->f, "'\\n'"); |
| | 636 | } else if (c == '\r') { |
| | 637 | fprintf(ar->f, "'\\r'"); |
| | 638 | } else if (c == '\t') { |
| | 639 | fprintf(ar->f, "'\\t'"); |
| | 640 | } else if (is_printable(c)) { |
| 634 | fprintf(ar->f, "'%c'", c); | 641 | fprintf(ar->f, "'%c'", c); |
| 635 | } else { | 642 | } else { |
| 636 | fprintf(ar->f, "'\\x%02x'", (int)c); | 643 | fprintf(ar->f, "'\\x%02x'", (int)c); |