authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 01:31:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 01:31:40-07:00
logc1691afdd90b744200f2238afe52d7fd9e6471b6
treead13a4543728df614bb7f1dbe296348a72dcbff5
parent9b2ed1fac53319cbddb2752409e166334bb339bf

parseh understands number literal defines


2 files changed, 91 insertions(+), 36 deletions(-)

src/parseh.cpp+38-5
...@@ -31,7 +31,7 @@ struct Context {...@@ -31,7 +31,7 @@ struct Context {
31 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;31 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;
32 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table;32 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table;
33 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;33 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
34 HashMap<Buf *, bool, buf_hash, buf_eql_buf> macro_table;34 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
35 SourceManager *source_manager;35 SourceManager *source_manager;
36 ZigList<AstNode *> aliases;36 ZigList<AstNode *> aliases;
37};37};
...@@ -715,10 +715,25 @@ static void render_aliases(Context *c) {...@@ -715,10 +715,25 @@ static void render_aliases(Context *c) {
715 if (c->fn_table.maybe_get(name)) {715 if (c->fn_table.maybe_get(name)) {
716 continue;716 continue;
717 }717 }
718 if (c->macro_table.maybe_get(name)) {
719 continue;
720 }
718 c->root->data.root.top_level_decls.append(alias_node);721 c->root->data.root.top_level_decls.append(alias_node);
719 }722 }
720}723}
721724
725static void render_macros(Context *c) {
726 auto it = c->macro_table.entry_iterator();
727 for (;;) {
728 auto *entry = it.next();
729 if (!entry)
730 break;
731
732 AstNode *var_node = entry->value;
733 c->root->data.root.top_level_decls.append(var_node);
734 }
735}
736
722static int parse_c_char_lit(Buf *value, uint8_t *out_c) {737static int parse_c_char_lit(Buf *value, uint8_t *out_c) {
723 enum State {738 enum State {
724 StateExpectStartQuot,739 StateExpectStartQuot,
...@@ -765,19 +780,36 @@ static int parse_c_char_lit(Buf *value, uint8_t *out_c) {...@@ -765,19 +780,36 @@ static int parse_c_char_lit(Buf *value, uint8_t *out_c) {
765 return (state == StateExpectEnd) ? 0 : -1;780 return (state == StateExpectEnd) ? 0 : -1;
766}781}
767782
783static int parse_c_num_lit_unsigned(Buf *buf, uint64_t *out_val) {
784 char *temp;
785 *out_val = strtoull(buf_ptr(buf), &temp, 0);
786
787 if (temp == buf_ptr(buf) || *temp != 0 || *out_val == ULLONG_MAX) {
788 return -1;
789 }
790
791 return 0;
792}
793
768static void process_macro(Context *c, Buf *name, Buf *value) {794static void process_macro(Context *c, Buf *name, Buf *value) {
769 // maybe it's a character literal795 // maybe it's a character literal
770 uint8_t ch;796 uint8_t ch;
771 if (!parse_c_char_lit(value, &ch)) {797 if (!parse_c_char_lit(value, &ch)) {
772 c->macro_table.put(name, true);
773 AstNode *var_node = create_var_decl_node(c, buf_ptr(name), create_char_lit_node(c, ch));798 AstNode *var_node = create_var_decl_node(c, buf_ptr(name), create_char_lit_node(c, ch));
774 c->root->data.root.top_level_decls.append(var_node);799 c->macro_table.put(name, var_node);
775 return;800 return;
776 }801 }
777 // maybe it's a string literal802 // maybe it's a string literal
778 // TODO803 // TODO
779 // maybe it's a number literal804
780 // TODO805 // maybe it's an unsigned integer
806 uint64_t uint;
807 if (!parse_c_num_lit_unsigned(value, &uint)) {
808 AstNode *var_node = create_var_decl_node(c, buf_ptr(name), create_num_lit_unsigned(c, uint));
809 c->macro_table.put(name, var_node);
810 return;
811 }
812
781 // maybe it's a symbol813 // maybe it's a symbol
782 // TODO814 // TODO
783}815}
...@@ -959,6 +991,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,...@@ -959,6 +991,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
959991
960 process_preprocessor_entities(c, *ast_unit);992 process_preprocessor_entities(c, *ast_unit);
961993
994 render_macros(c);
962 render_aliases(c);995 render_aliases(c);
963996
964 normalize_parent_ptrs(c->root);997 normalize_parent_ptrs(c->root);
test/run_tests.cpp+53-31
...@@ -96,21 +96,30 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source...@@ -96,21 +96,30 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
96 return test_case;96 return test_case;
97}97}
9898
99static TestCase *add_parseh_case(const char *case_name, const char *source, const char *output) {99static TestCase *add_parseh_case(const char *case_name, const char *source, int count, ...) {
100 va_list ap;
101 va_start(ap, count);
102
100 TestCase *test_case = allocate<TestCase>(1);103 TestCase *test_case = allocate<TestCase>(1);
101 test_case->case_name = case_name;104 test_case->case_name = case_name;
102 test_case->output = output;
103 test_case->is_parseh = true;105 test_case->is_parseh = true;
104106
105 test_case->source_files.resize(1);107 test_case->source_files.resize(1);
106 test_case->source_files.at(0).relative_path = tmp_h_path;108 test_case->source_files.at(0).relative_path = tmp_h_path;
107 test_case->source_files.at(0).source_code = source;109 test_case->source_files.at(0).source_code = source;
108110
111 for (int i = 0; i < count; i += 1) {
112 const char *arg = va_arg(ap, const char *);
113 test_case->compile_errors.append(arg);
114 }
115
109 test_case->compiler_args.append("parseh");116 test_case->compiler_args.append("parseh");
110 test_case->compiler_args.append(tmp_h_path);117 test_case->compiler_args.append(tmp_h_path);
111 test_case->compiler_args.append("--c-import-warnings");118 test_case->compiler_args.append("--c-import-warnings");
112119
113 test_cases.append(test_case);120 test_cases.append(test_case);
121
122 va_end(ap);
114 return test_case;123 return test_case;
115}124}
116125
...@@ -1894,13 +1903,13 @@ int foo(char a, unsigned char b, signed char c);...@@ -1894,13 +1903,13 @@ int foo(char a, unsigned char b, signed char c);
1894int foo(char a, unsigned char b, signed char c); // test a duplicate prototype1903int foo(char a, unsigned char b, signed char c); // test a duplicate prototype
1895void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);1904void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
1896void baz(int8_t a, int16_t b, int32_t c, int64_t d);1905void baz(int8_t a, int16_t b, int32_t c, int64_t d);
1897 )SOURCE", R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;1906 )SOURCE", 1, R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;
1898pub extern fn bar(a: u8, b: u16, c: u32, d: u64);1907pub extern fn bar(a: u8, b: u16, c: u32, d: u64);
1899pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT");1908pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT");
19001909
1901 add_parseh_case("noreturn attribute", R"SOURCE(1910 add_parseh_case("noreturn attribute", R"SOURCE(
1902void foo(void) __attribute__((noreturn));1911void foo(void) __attribute__((noreturn));
1903 )SOURCE", R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT");1912 )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT");
19041913
1905 add_parseh_case("enums", R"SOURCE(1914 add_parseh_case("enums", R"SOURCE(
1906enum Foo {1915enum Foo {
...@@ -1908,19 +1917,19 @@ enum Foo {...@@ -1908,19 +1917,19 @@ enum Foo {
1908 FooB,1917 FooB,
1909 Foo1,1918 Foo1,
1910};1919};
1911 )SOURCE", R"OUTPUT(export enum enum_Foo {1920 )SOURCE", 1, R"OUTPUT(export enum enum_Foo {
1912 A,1921 A,
1913 B,1922 B,
1914 _1,1923 _1,
1915}1924}
1916pub const FooA = enum_Foo.A;1925pub const FooA = enum_Foo.A;
1917pub const FooB = enum_Foo.B;1926pub const FooB = enum_Foo.B;
1918pub const Foo1 = enum_Foo._1;1927pub const Foo1 = enum_Foo._1;)OUTPUT",
1919pub const Foo = enum_Foo;)OUTPUT");1928 R"OUTPUT(pub const Foo = enum_Foo;)OUTPUT");
19201929
1921 add_parseh_case("restrict -> noalias", R"SOURCE(1930 add_parseh_case("restrict -> noalias", R"SOURCE(
1922void foo(void *restrict bar, void *restrict);1931void foo(void *restrict bar, void *restrict);
1923 )SOURCE", R"OUTPUT(pub const c_void = u8;1932 )SOURCE", 1, R"OUTPUT(pub const c_void = u8;
1924pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");1933pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");
19251934
1926 add_parseh_case("simple struct", R"SOURCE(1935 add_parseh_case("simple struct", R"SOURCE(
...@@ -1928,11 +1937,11 @@ struct Foo {...@@ -1928,11 +1937,11 @@ struct Foo {
1928 int x;1937 int x;
1929 char *y;1938 char *y;
1930};1939};
1931 )SOURCE", R"OUTPUT(export struct struct_Foo {1940 )SOURCE", 2,
1941 R"OUTPUT(export struct struct_Foo {
1932 x: c_int,1942 x: c_int,
1933 y: ?&u8,1943 y: ?&u8,
1934}1944})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
1935pub const Foo = struct_Foo;)OUTPUT");
19361945
1937 add_parseh_case("qualified struct and enum", R"SOURCE(1946 add_parseh_case("qualified struct and enum", R"SOURCE(
1938struct Foo {1947struct Foo {
...@@ -1944,7 +1953,7 @@ enum Bar {...@@ -1944,7 +1953,7 @@ enum Bar {
1944 BarB,1953 BarB,
1945};1954};
1946void func(struct Foo *a, enum Bar **b);1955void func(struct Foo *a, enum Bar **b);
1947 )SOURCE", R"OUTPUT(export struct struct_Foo {1956 )SOURCE", 2, R"OUTPUT(export struct struct_Foo {
1948 x: c_int,1957 x: c_int,
1949 y: c_int,1958 y: c_int,
1950}1959}
...@@ -1954,36 +1963,45 @@ export enum enum_Bar {...@@ -1954,36 +1963,45 @@ export enum enum_Bar {
1954}1963}
1955pub const BarA = enum_Bar.A;1964pub const BarA = enum_Bar.A;
1956pub const BarB = enum_Bar.B;1965pub const BarB = enum_Bar.B;
1957pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);1966pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT",
1958pub const Foo = struct_Foo;1967 R"OUTPUT(pub const Foo = struct_Foo;
1959pub const Bar = enum_Bar;)OUTPUT");1968pub const Bar = enum_Bar;)OUTPUT");
19601969
1961 add_parseh_case("constant size array", R"SOURCE(1970 add_parseh_case("constant size array", R"SOURCE(
1962void func(int array[20]);1971void func(int array[20]);
1963 )SOURCE", R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT");1972 )SOURCE", 1, R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT");
19641973
19651974
1966 add_parseh_case("self referential struct with function pointer", R"SOURCE(1975 add_parseh_case("self referential struct with function pointer", R"SOURCE(
1967struct Foo {1976struct Foo {
1968 void (*derp)(struct Foo *foo);1977 void (*derp)(struct Foo *foo);
1969};1978};
1970 )SOURCE", R"OUTPUT(export struct struct_Foo {1979 )SOURCE", 2, R"OUTPUT(export struct struct_Foo {
1971 derp: ?extern fn (?&struct_Foo),1980 derp: ?extern fn (?&struct_Foo),
1972}1981})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
1973pub const Foo = struct_Foo;)OUTPUT");
19741982
19751983
1976 add_parseh_case("struct prototype used in func", R"SOURCE(1984 add_parseh_case("struct prototype used in func", R"SOURCE(
1977struct Foo;1985struct Foo;
1978struct Foo *some_func(struct Foo *foo, int x);1986struct Foo *some_func(struct Foo *foo, int x);
1979 )SOURCE", R"OUTPUT(pub const struct_Foo = u8;1987 )SOURCE", 2, R"OUTPUT(pub const struct_Foo = u8;
1980pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;1988pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
1981pub const Foo = struct_Foo;)OUTPUT");1989 R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
19821990
19831991
1984 add_parseh_case("#define a char literal", R"SOURCE(1992 add_parseh_case("#define a char literal", R"SOURCE(
1985#define A_CHAR 'a'1993#define A_CHAR 'a'
1986 )SOURCE", R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT");1994 )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT");
1995
1996
1997 add_parseh_case("#define an unsigned integer literal", R"SOURCE(
1998#define CHANNEL_COUNT 24
1999 )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT");
2000
2001 add_parseh_case("overide previous #define", R"SOURCE(
2002#define A_CHAR 'a'
2003#define A_CHAR 'b'
2004 )SOURCE", 1, "pub const A_CHAR = 'b';");
1987}2005}
19882006
1989static void print_compiler_invocation(TestCase *test_case) {2007static void print_compiler_invocation(TestCase *test_case) {
...@@ -2007,7 +2025,7 @@ static void run_test(TestCase *test_case) {...@@ -2007,7 +2025,7 @@ static void run_test(TestCase *test_case) {
2007 int return_code;2025 int return_code;
2008 os_exec_process(zig_exe, test_case->compiler_args, &return_code, &zig_stderr, &zig_stdout);2026 os_exec_process(zig_exe, test_case->compiler_args, &return_code, &zig_stderr, &zig_stdout);
20092027
2010 if (test_case->compile_errors.length) {2028 if (!test_case->is_parseh && test_case->compile_errors.length) {
2011 if (return_code) {2029 if (return_code) {
2012 for (int i = 0; i < test_case->compile_errors.length; i += 1) {2030 for (int i = 0; i < test_case->compile_errors.length; i += 1) {
2013 const char *err_text = test_case->compile_errors.at(i);2031 const char *err_text = test_case->compile_errors.at(i);
...@@ -2045,14 +2063,18 @@ static void run_test(TestCase *test_case) {...@@ -2045,14 +2063,18 @@ static void run_test(TestCase *test_case) {
2045 exit(1);2063 exit(1);
2046 }2064 }
20472065
2048 if (!strstr(buf_ptr(&zig_stdout), test_case->output)) {2066 for (int i = 0; i < test_case->compile_errors.length; i += 1) {
2049 printf("\n");2067 const char *output = test_case->compile_errors.at(i);
2050 printf("========= Expected this output: =========\n");2068
2051 printf("%s\n", test_case->output);2069 if (!strstr(buf_ptr(&zig_stdout), output)) {
2052 printf("================================================\n");2070 printf("\n");
2053 print_compiler_invocation(test_case);2071 printf("========= Expected this output: =========\n");
2054 printf("%s\n", buf_ptr(&zig_stdout));2072 printf("%s\n", output);
2055 exit(1);2073 printf("================================================\n");
2074 print_compiler_invocation(test_case);
2075 printf("%s\n", buf_ptr(&zig_stdout));
2076 exit(1);
2077 }
2056 }2078 }
2057 } else {2079 } else {
2058 Buf program_stderr = BUF_INIT;2080 Buf program_stderr = BUF_INIT;