Commit 373785ae8d

jean-dao <pfudke@gmail.com>
2017-09-10 22:35:56
c macros: support hex chars (#459)
* c macros: remove add_char redundancies * c macros: support hex chars * c macros: add test for hex chars
1 parent 4f44d49
src/c_tokenizer.cpp
@@ -598,7 +598,8 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
                         ctok->octal_index = 1;
                         break;
                     case 'x':
-                        zig_panic("TODO hex");
+                        ctok->state = CTokStateStrHex;
+                        ctok->cur_char = 0;
                         break;
                     case 'u':
                         zig_panic("TODO unicode");
@@ -610,6 +611,54 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
                         return mark_error(ctok);
                 }
                 break;
+            case CTokStateStrHex: {
+                uint8_t value = 0;
+                switch (*c) {
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                        value = *c - '0';
+                        break;
+                    case 'a':
+                    case 'b':
+                    case 'c':
+                    case 'd':
+                    case 'e':
+                    case 'f':
+                        value = (*c - 'a') + 10;
+                        break;
+                    case 'A':
+                    case 'B':
+                    case 'C':
+                    case 'D':
+                    case 'E':
+                    case 'F':
+                        value = (*c - 'A') + 10;
+                        break;
+                    default:
+                        c -= 1;
+                        add_char(ctok, ctok->cur_char);
+                        continue;
+                }
+                // TODO @mul_with_overflow
+                if (((long)ctok->cur_char) * 16 >= 256) {
+                    zig_panic("TODO str hex mul overflow");
+                }
+                ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)16);
+                // TODO @add_with_overflow
+                if (((long)ctok->cur_char) + (long)(value) >= 256) {
+                    zig_panic("TODO str hex add overflow");
+                }
+                ctok->cur_char = (uint8_t)(ctok->cur_char + value);
+                break;
+            }
             case CTokStateStrOctal:
                 switch (*c) {
                     case '0':
@@ -632,28 +681,12 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
                         ctok->cur_char = (uint8_t)(ctok->cur_char + (uint8_t)(*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();
-                            }
+                            add_char(ctok, ctok->cur_char);
                         }
                         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();
-                        }
+                        add_char(ctok, ctok->cur_char);
                         continue;
                 }
                 break;
@@ -748,6 +781,7 @@ found_end_of_macro:
         case CTokStateString:
         case CTokStateExpSign:
         case CTokStateFloatExpFirst:
+        case CTokStateStrHex:
         case CTokStateStrOctal:
             return mark_error(ctok);
     }
src/c_tokenizer.hpp
@@ -68,6 +68,7 @@ enum CTokState {
     CTokStateExpSign,
     CTokStateFloatExp,
     CTokStateFloatExpFirst,
+    CTokStateStrHex,
     CTokStateStrOctal,
     CTokStateNumLitIntSuffixU,
     CTokStateNumLitIntSuffixL,
test/parsec.zig
@@ -285,6 +285,18 @@ pub fn addCases(cases: &tests.ParseCContext) {
         \\pub const @"comptime" = struct_comptime;
     );
 
+    cases.add("macro defines string literal with hex",
+        \\#define FOO "aoeu\xab derp"
+        \\#define FOO2 "aoeu\x0007a derp"
+        \\#define FOO_CHAR '\xfF'
+    ,
+        \\pub const FOO = c"aoeu\xab derp";
+    ,
+        \\pub const FOO2 = c"aoeuz derp";
+    ,
+        \\pub const FOO_CHAR = 255;
+    );
+
     cases.add("macro defines string literal with octal",
         \\#define FOO "aoeu\023 derp"
         \\#define FOO2 "aoeu\0234 derp"