parseh: support octal in C macro string literal

master
Andrew Kelley 2016-07-09 12:17:31 -07:00
parent 100e8e15fa
commit a5251a1c10
4 changed files with 79 additions and 6 deletions

View File

@ -251,7 +251,7 @@ static bool is_digit(uint8_t c) {
} }
static bool is_printable(uint8_t c) { static bool is_printable(uint8_t c) {
return is_alpha_under(c) || is_digit(c); return is_alpha_under(c) || is_digit(c) || c == ' ';
} }
static void string_literal_escape(Buf *source, Buf *dest) { static void string_literal_escape(Buf *source, Buf *dest) {
@ -463,10 +463,14 @@ static void render_node(AstRender *ar, AstNode *node) {
} }
break; break;
case NodeTypeStringLiteral: case NodeTypeStringLiteral:
{
if (node->data.string_literal.c) { if (node->data.string_literal.c) {
fprintf(ar->f, "c"); fprintf(ar->f, "c");
} }
fprintf(ar->f, "\"%s\"", buf_ptr(&node->data.string_literal.buf)); Buf tmp_buf = BUF_INIT;
string_literal_escape(&node->data.string_literal.buf, &tmp_buf);
fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf));
}
break; break;
case NodeTypeCharLiteral: case NodeTypeCharLiteral:
{ {

View File

@ -539,8 +539,17 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
case 'v': case 'v':
add_char(ctok, '\v'); add_char(ctok, '\v');
break; break;
case DIGIT: case '0':
zig_panic("TODO octal"); case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
ctok->state = CTokStateStrOctal;
ctok->cur_char = *c - '0';
ctok->octal_index = 1;
break; break;
case 'x': case 'x':
zig_panic("TODO hex"); zig_panic("TODO hex");
@ -555,6 +564,53 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
return mark_error(ctok); return mark_error(ctok);
} }
break; break;
case CTokStateStrOctal:
switch (*c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
// TODO @mul_with_overflow
if (((long)ctok->cur_char) * 8 >= 256) {
zig_panic("TODO");
}
ctok->cur_char *= 8;
// TODO @add_with_overflow
if (((long)ctok->cur_char) + (long)(*c - '0') >= 256) {
zig_panic("TODO");
}
ctok->cur_char += *c - '0';
ctok->octal_index += 1;
if (ctok->octal_index == 3) {
if (ctok->cur_tok->id == CTokIdStrLit) {
add_char(ctok, ctok->cur_char);
ctok->state = CTokStateString;
} else if (ctok->cur_tok->id == CTokIdCharLit) {
ctok->cur_tok->data.char_lit = ctok->cur_char;
ctok->state = CTokStateExpectEndQuot;
} else {
zig_unreachable();
}
}
break;
default:
c -= 1;
if (ctok->cur_tok->id == CTokIdStrLit) {
add_char(ctok, ctok->cur_char);
ctok->state = CTokStateString;
} else if (ctok->cur_tok->id == CTokIdCharLit) {
ctok->cur_tok->data.char_lit = ctok->cur_char;
ctok->state = CTokStateExpectEndQuot;
} else {
zig_unreachable();
}
continue;
}
break;
case CTokStateExpectEndQuot: case CTokStateExpectEndQuot:
switch (*c) { switch (*c) {
case '\'': case '\'':
@ -644,6 +700,7 @@ found_end_of_macro:
case CTokStateString: case CTokStateString:
case CTokStateExpSign: case CTokStateExpSign:
case CTokStateFloatExpFirst: case CTokStateFloatExpFirst:
case CTokStateStrOctal:
return mark_error(ctok); return mark_error(ctok);
} }

View File

@ -53,6 +53,7 @@ enum CTokState {
CTokStateExpSign, CTokStateExpSign,
CTokStateFloatExp, CTokStateFloatExp,
CTokStateFloatExpFirst, CTokStateFloatExpFirst,
CTokStateStrOctal,
}; };
struct CTokenize { struct CTokenize {
@ -63,6 +64,8 @@ struct CTokenize {
Buf buf; Buf buf;
bool unsigned_suffix; bool unsigned_suffix;
bool long_suffix; bool long_suffix;
uint8_t cur_char;
int octal_index;
}; };
void tokenize_c_macro(CTokenize *ctok, const uint8_t *c); void tokenize_c_macro(CTokenize *ctok, const uint8_t *c);

View File

@ -1731,6 +1731,15 @@ struct type {
)SOURCE", 2, R"(export struct struct_type { )SOURCE", 2, R"(export struct struct_type {
@"defer": c_int, @"defer": c_int,
})", R"(pub const @"type" = struct_type;)"); })", R"(pub const @"type" = struct_type;)");
add_parseh_case("macro defines string literal with octal", R"SOURCE(
#define FOO "aoeu\023 derp"
#define FOO2 "aoeu\0234 derp"
#define FOO_CHAR '\077'
)SOURCE", 3,
R"(pub const FOO = c"aoeu\x13 derp")",
R"(pub const FOO2 = c"aoeu\x134 derp")",
R"(pub const FOO_CHAR = '\x3f')");
} }
static void run_self_hosted_test(bool is_release_mode) { static void run_self_hosted_test(bool is_release_mode) {