diff options
Diffstat (limited to 'src/lj_cparse.c')
-rw-r--r-- | src/lj_cparse.c | 152 |
1 files changed, 90 insertions, 62 deletions
diff --git a/src/lj_cparse.c b/src/lj_cparse.c index 50bb76ad..70b82af3 100644 --- a/src/lj_cparse.c +++ b/src/lj_cparse.c | |||
@@ -9,13 +9,14 @@ | |||
9 | 9 | ||
10 | #include "lj_gc.h" | 10 | #include "lj_gc.h" |
11 | #include "lj_err.h" | 11 | #include "lj_err.h" |
12 | #include "lj_str.h" | 12 | #include "lj_buf.h" |
13 | #include "lj_ctype.h" | 13 | #include "lj_ctype.h" |
14 | #include "lj_cparse.h" | 14 | #include "lj_cparse.h" |
15 | #include "lj_frame.h" | 15 | #include "lj_frame.h" |
16 | #include "lj_vm.h" | 16 | #include "lj_vm.h" |
17 | #include "lj_char.h" | 17 | #include "lj_char.h" |
18 | #include "lj_strscan.h" | 18 | #include "lj_strscan.h" |
19 | #include "lj_strfmt.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | ** Important note: this is NOT a validating C parser! This is a minimal | 22 | ** Important note: this is NOT a validating C parser! This is a minimal |
@@ -27,6 +28,24 @@ | |||
27 | ** If in doubt, please check the input against your favorite C compiler. | 28 | ** If in doubt, please check the input against your favorite C compiler. |
28 | */ | 29 | */ |
29 | 30 | ||
31 | /* -- Miscellaneous ------------------------------------------------------- */ | ||
32 | |||
33 | /* Match string against a C literal. */ | ||
34 | #define cp_str_is(str, k) \ | ||
35 | ((str)->len == sizeof(k)-1 && !memcmp(strdata(str), k, sizeof(k)-1)) | ||
36 | |||
37 | /* Check string against a linear list of matches. */ | ||
38 | int lj_cparse_case(GCstr *str, const char *match) | ||
39 | { | ||
40 | MSize len; | ||
41 | int n; | ||
42 | for (n = 0; (len = (MSize)*match++); n++, match += len) { | ||
43 | if (str->len == len && !memcmp(match, strdata(str), len)) | ||
44 | return n; | ||
45 | } | ||
46 | return -1; | ||
47 | } | ||
48 | |||
30 | /* -- C lexer ------------------------------------------------------------- */ | 49 | /* -- C lexer ------------------------------------------------------------- */ |
31 | 50 | ||
32 | /* C lexer token names. */ | 51 | /* C lexer token names. */ |
@@ -46,9 +65,9 @@ static const char *cp_tok2str(CPState *cp, CPToken tok) | |||
46 | if (tok > CTOK_OFS) | 65 | if (tok > CTOK_OFS) |
47 | return ctoknames[tok-CTOK_OFS-1]; | 66 | return ctoknames[tok-CTOK_OFS-1]; |
48 | else if (!lj_char_iscntrl(tok)) | 67 | else if (!lj_char_iscntrl(tok)) |
49 | return lj_str_pushf(cp->L, "%c", tok); | 68 | return lj_strfmt_pushf(cp->L, "%c", tok); |
50 | else | 69 | else |
51 | return lj_str_pushf(cp->L, "char(%d)", tok); | 70 | return lj_strfmt_pushf(cp->L, "char(%d)", tok); |
52 | } | 71 | } |
53 | 72 | ||
54 | /* End-of-line? */ | 73 | /* End-of-line? */ |
@@ -85,24 +104,10 @@ static LJ_NOINLINE CPChar cp_get_bs(CPState *cp) | |||
85 | return cp_get(cp); | 104 | return cp_get(cp); |
86 | } | 105 | } |
87 | 106 | ||
88 | /* Grow save buffer. */ | ||
89 | static LJ_NOINLINE void cp_save_grow(CPState *cp, CPChar c) | ||
90 | { | ||
91 | MSize newsize; | ||
92 | if (cp->sb.sz >= CPARSE_MAX_BUF/2) | ||
93 | cp_err(cp, LJ_ERR_XELEM); | ||
94 | newsize = cp->sb.sz * 2; | ||
95 | lj_str_resizebuf(cp->L, &cp->sb, newsize); | ||
96 | cp->sb.buf[cp->sb.n++] = (char)c; | ||
97 | } | ||
98 | |||
99 | /* Save character in buffer. */ | 107 | /* Save character in buffer. */ |
100 | static LJ_AINLINE void cp_save(CPState *cp, CPChar c) | 108 | static LJ_AINLINE void cp_save(CPState *cp, CPChar c) |
101 | { | 109 | { |
102 | if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz)) | 110 | lj_buf_putb(&cp->sb, c); |
103 | cp_save_grow(cp, c); | ||
104 | else | ||
105 | cp->sb.buf[cp->sb.n++] = (char)c; | ||
106 | } | 111 | } |
107 | 112 | ||
108 | /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ | 113 | /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ |
@@ -122,20 +127,20 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...) | |||
122 | tokstr = NULL; | 127 | tokstr = NULL; |
123 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || | 128 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || |
124 | tok >= CTOK_FIRSTDECL) { | 129 | tok >= CTOK_FIRSTDECL) { |
125 | if (cp->sb.n == 0) cp_save(cp, '$'); | 130 | if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$'); |
126 | cp_save(cp, '\0'); | 131 | cp_save(cp, '\0'); |
127 | tokstr = cp->sb.buf; | 132 | tokstr = sbufB(&cp->sb); |
128 | } else { | 133 | } else { |
129 | tokstr = cp_tok2str(cp, tok); | 134 | tokstr = cp_tok2str(cp, tok); |
130 | } | 135 | } |
131 | L = cp->L; | 136 | L = cp->L; |
132 | va_start(argp, em); | 137 | va_start(argp, em); |
133 | msg = lj_str_pushvf(L, err2msg(em), argp); | 138 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
134 | va_end(argp); | 139 | va_end(argp); |
135 | if (tokstr) | 140 | if (tokstr) |
136 | msg = lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr); | 141 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr); |
137 | if (cp->linenumber > 1) | 142 | if (cp->linenumber > 1) |
138 | msg = lj_str_pushf(L, "%s at line %d", msg, cp->linenumber); | 143 | msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber); |
139 | lj_err_callermsg(L, msg); | 144 | lj_err_callermsg(L, msg); |
140 | } | 145 | } |
141 | 146 | ||
@@ -164,7 +169,7 @@ static CPToken cp_number(CPState *cp) | |||
164 | TValue o; | 169 | TValue o; |
165 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); | 170 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); |
166 | cp_save(cp, '\0'); | 171 | cp_save(cp, '\0'); |
167 | fmt = lj_strscan_scan((const uint8_t *)cp->sb.buf, &o, STRSCAN_OPT_C); | 172 | fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), &o, STRSCAN_OPT_C); |
168 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; | 173 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; |
169 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; | 174 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; |
170 | else if (!(cp->mode & CPARSE_MODE_SKIP)) | 175 | else if (!(cp->mode & CPARSE_MODE_SKIP)) |
@@ -177,7 +182,7 @@ static CPToken cp_number(CPState *cp) | |||
177 | static CPToken cp_ident(CPState *cp) | 182 | static CPToken cp_ident(CPState *cp) |
178 | { | 183 | { |
179 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); | 184 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); |
180 | cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n); | 185 | cp->str = lj_buf_str(cp->L, &cp->sb); |
181 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); | 186 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); |
182 | if (ctype_type(cp->ct->info) == CT_KW) | 187 | if (ctype_type(cp->ct->info) == CT_KW) |
183 | return ctype_cid(cp->ct->info); | 188 | return ctype_cid(cp->ct->info); |
@@ -263,11 +268,11 @@ static CPToken cp_string(CPState *cp) | |||
263 | } | 268 | } |
264 | cp_get(cp); | 269 | cp_get(cp); |
265 | if (delim == '"') { | 270 | if (delim == '"') { |
266 | cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n); | 271 | cp->str = lj_buf_str(cp->L, &cp->sb); |
267 | return CTOK_STRING; | 272 | return CTOK_STRING; |
268 | } else { | 273 | } else { |
269 | if (cp->sb.n != 1) cp_err_token(cp, '\''); | 274 | if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\''); |
270 | cp->val.i32 = (int32_t)(char)cp->sb.buf[0]; | 275 | cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb); |
271 | cp->val.id = CTID_INT32; | 276 | cp->val.id = CTID_INT32; |
272 | return CTOK_INTEGER; | 277 | return CTOK_INTEGER; |
273 | } | 278 | } |
@@ -296,7 +301,7 @@ static void cp_comment_cpp(CPState *cp) | |||
296 | /* Lexical scanner for C. Only a minimal subset is implemented. */ | 301 | /* Lexical scanner for C. Only a minimal subset is implemented. */ |
297 | static CPToken cp_next_(CPState *cp) | 302 | static CPToken cp_next_(CPState *cp) |
298 | { | 303 | { |
299 | lj_str_resetbuf(&cp->sb); | 304 | lj_buf_reset(&cp->sb); |
300 | for (;;) { | 305 | for (;;) { |
301 | if (lj_char_isident(cp->c)) | 306 | if (lj_char_isident(cp->c)) |
302 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); | 307 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); |
@@ -385,8 +390,7 @@ static void cp_init(CPState *cp) | |||
385 | cp->depth = 0; | 390 | cp->depth = 0; |
386 | cp->curpack = 0; | 391 | cp->curpack = 0; |
387 | cp->packstack[0] = 255; | 392 | cp->packstack[0] = 255; |
388 | lj_str_initbuf(&cp->sb); | 393 | lj_buf_init(cp->L, &cp->sb); |
389 | lj_str_resizebuf(cp->L, &cp->sb, LJ_MIN_SBUF); | ||
390 | lua_assert(cp->p != NULL); | 394 | lua_assert(cp->p != NULL); |
391 | cp_get(cp); /* Read-ahead first char. */ | 395 | cp_get(cp); /* Read-ahead first char. */ |
392 | cp->tok = 0; | 396 | cp->tok = 0; |
@@ -398,7 +402,7 @@ static void cp_init(CPState *cp) | |||
398 | static void cp_cleanup(CPState *cp) | 402 | static void cp_cleanup(CPState *cp) |
399 | { | 403 | { |
400 | global_State *g = G(cp->L); | 404 | global_State *g = G(cp->L); |
401 | lj_str_freebuf(g, &cp->sb); | 405 | lj_buf_free(g, &cp->sb); |
402 | } | 406 | } |
403 | 407 | ||
404 | /* Check and consume optional token. */ | 408 | /* Check and consume optional token. */ |
@@ -953,8 +957,6 @@ static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl) | |||
953 | 957 | ||
954 | /* -- C declaration parser ------------------------------------------------ */ | 958 | /* -- C declaration parser ------------------------------------------------ */ |
955 | 959 | ||
956 | #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be) | ||
957 | |||
958 | /* Reset declaration state to declaration specifier. */ | 960 | /* Reset declaration state to declaration specifier. */ |
959 | static void cp_decl_reset(CPDecl *decl) | 961 | static void cp_decl_reset(CPDecl *decl) |
960 | { | 962 | { |
@@ -1031,7 +1033,7 @@ static void cp_decl_asm(CPState *cp, CPDecl *decl) | |||
1031 | if (cp->tok == CTOK_STRING) { | 1033 | if (cp->tok == CTOK_STRING) { |
1032 | GCstr *str = cp->str; | 1034 | GCstr *str = cp->str; |
1033 | while (cp_next(cp) == CTOK_STRING) { | 1035 | while (cp_next(cp) == CTOK_STRING) { |
1034 | lj_str_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); | 1036 | lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); |
1035 | cp->L->top--; | 1037 | cp->L->top--; |
1036 | str = strV(cp->L->top); | 1038 | str = strV(cp->L->top); |
1037 | } | 1039 | } |
@@ -1083,44 +1085,57 @@ static void cp_decl_gccattribute(CPState *cp, CPDecl *decl) | |||
1083 | if (cp->tok == CTOK_IDENT) { | 1085 | if (cp->tok == CTOK_IDENT) { |
1084 | GCstr *attrstr = cp->str; | 1086 | GCstr *attrstr = cp->str; |
1085 | cp_next(cp); | 1087 | cp_next(cp); |
1086 | switch (attrstr->hash) { | 1088 | switch (lj_cparse_case(attrstr, |
1087 | case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */ | 1089 | "\007aligned" "\013__aligned__" |
1090 | "\006packed" "\012__packed__" | ||
1091 | "\004mode" "\010__mode__" | ||
1092 | "\013vector_size" "\017__vector_size__" | ||
1093 | #if LJ_TARGET_X86 | ||
1094 | "\007regparm" "\013__regparm__" | ||
1095 | "\005cdecl" "\011__cdecl__" | ||
1096 | "\010thiscall" "\014__thiscall__" | ||
1097 | "\010fastcall" "\014__fastcall__" | ||
1098 | "\007stdcall" "\013__stdcall__" | ||
1099 | "\012sseregparm" "\016__sseregparm__" | ||
1100 | #endif | ||
1101 | )) { | ||
1102 | case 0: case 1: /* aligned */ | ||
1088 | cp_decl_align(cp, decl); | 1103 | cp_decl_align(cp, decl); |
1089 | break; | 1104 | break; |
1090 | case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */ | 1105 | case 2: case 3: /* packed */ |
1091 | decl->attr |= CTFP_PACKED; | 1106 | decl->attr |= CTFP_PACKED; |
1092 | break; | 1107 | break; |
1093 | case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */ | 1108 | case 4: case 5: /* mode */ |
1094 | cp_decl_mode(cp, decl); | 1109 | cp_decl_mode(cp, decl); |
1095 | break; | 1110 | break; |
1096 | case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */ | 1111 | case 6: case 7: /* vector_size */ |
1097 | { | 1112 | { |
1098 | CTSize vsize = cp_decl_sizeattr(cp); | 1113 | CTSize vsize = cp_decl_sizeattr(cp); |
1099 | if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize)); | 1114 | if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize)); |
1100 | } | 1115 | } |
1101 | break; | 1116 | break; |
1102 | #if LJ_TARGET_X86 | 1117 | #if LJ_TARGET_X86 |
1103 | case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */ | 1118 | case 8: case 9: /* regparm */ |
1104 | CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp)); | 1119 | CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp)); |
1105 | decl->fattr |= CTFP_CCONV; | 1120 | decl->fattr |= CTFP_CCONV; |
1106 | break; | 1121 | break; |
1107 | case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */ | 1122 | case 10: case 11: /* cdecl */ |
1108 | CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL); | 1123 | CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL); |
1109 | decl->fattr |= CTFP_CCONV; | 1124 | decl->fattr |= CTFP_CCONV; |
1110 | break; | 1125 | break; |
1111 | case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */ | 1126 | case 12: case 13: /* thiscall */ |
1112 | CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL); | 1127 | CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL); |
1113 | decl->fattr |= CTFP_CCONV; | 1128 | decl->fattr |= CTFP_CCONV; |
1114 | break; | 1129 | break; |
1115 | case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */ | 1130 | case 14: case 15: /* fastcall */ |
1116 | CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL); | 1131 | CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL); |
1117 | decl->fattr |= CTFP_CCONV; | 1132 | decl->fattr |= CTFP_CCONV; |
1118 | break; | 1133 | break; |
1119 | case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */ | 1134 | case 16: case 17: /* stdcall */ |
1120 | CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL); | 1135 | CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL); |
1121 | decl->fattr |= CTFP_CCONV; | 1136 | decl->fattr |= CTFP_CCONV; |
1122 | break; | 1137 | break; |
1123 | case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */ | 1138 | case 18: case 19: /* sseregparm */ |
1124 | decl->fattr |= CTF_SSEREGPARM; | 1139 | decl->fattr |= CTF_SSEREGPARM; |
1125 | decl->fattr |= CTFP_CCONV; | 1140 | decl->fattr |= CTFP_CCONV; |
1126 | break; | 1141 | break; |
@@ -1152,16 +1167,13 @@ static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl) | |||
1152 | while (cp->tok == CTOK_IDENT) { | 1167 | while (cp->tok == CTOK_IDENT) { |
1153 | GCstr *attrstr = cp->str; | 1168 | GCstr *attrstr = cp->str; |
1154 | cp_next(cp); | 1169 | cp_next(cp); |
1155 | switch (attrstr->hash) { | 1170 | if (cp_str_is(attrstr, "align")) { |
1156 | case H_(bc2395fa,98f267f8): /* align */ | ||
1157 | cp_decl_align(cp, decl); | 1171 | cp_decl_align(cp, decl); |
1158 | break; | 1172 | } else { /* Ignore all other attributes. */ |
1159 | default: /* Ignore all other attributes. */ | ||
1160 | if (cp_opt(cp, '(')) { | 1173 | if (cp_opt(cp, '(')) { |
1161 | while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp); | 1174 | while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp); |
1162 | cp_check(cp, ')'); | 1175 | cp_check(cp, ')'); |
1163 | } | 1176 | } |
1164 | break; | ||
1165 | } | 1177 | } |
1166 | } | 1178 | } |
1167 | cp_check(cp, ')'); | 1179 | cp_check(cp, ')'); |
@@ -1741,17 +1753,16 @@ static CTypeID cp_decl_abstract(CPState *cp) | |||
1741 | static void cp_pragma(CPState *cp, BCLine pragmaline) | 1753 | static void cp_pragma(CPState *cp, BCLine pragmaline) |
1742 | { | 1754 | { |
1743 | cp_next(cp); | 1755 | cp_next(cp); |
1744 | if (cp->tok == CTOK_IDENT && | 1756 | if (cp->tok == CTOK_IDENT && cp_str_is(cp->str, "pack")) { |
1745 | cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */ | ||
1746 | cp_next(cp); | 1757 | cp_next(cp); |
1747 | cp_check(cp, '('); | 1758 | cp_check(cp, '('); |
1748 | if (cp->tok == CTOK_IDENT) { | 1759 | if (cp->tok == CTOK_IDENT) { |
1749 | if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */ | 1760 | if (cp_str_is(cp->str, "push")) { |
1750 | if (cp->curpack < CPARSE_MAX_PACKSTACK) { | 1761 | if (cp->curpack < CPARSE_MAX_PACKSTACK) { |
1751 | cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack]; | 1762 | cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack]; |
1752 | cp->curpack++; | 1763 | cp->curpack++; |
1753 | } | 1764 | } |
1754 | } else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */ | 1765 | } else if (cp_str_is(cp->str, "pop")) { |
1755 | if (cp->curpack > 0) cp->curpack--; | 1766 | if (cp->curpack > 0) cp->curpack--; |
1756 | } else { | 1767 | } else { |
1757 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); | 1768 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); |
@@ -1773,6 +1784,16 @@ static void cp_pragma(CPState *cp, BCLine pragmaline) | |||
1773 | } | 1784 | } |
1774 | } | 1785 | } |
1775 | 1786 | ||
1787 | /* Handle line number. */ | ||
1788 | static void cp_line(CPState *cp, BCLine hashline) | ||
1789 | { | ||
1790 | BCLine newline = cp->val.u32; | ||
1791 | /* TODO: Handle file name and include it in error messages. */ | ||
1792 | while (cp->tok != CTOK_EOF && cp->linenumber == hashline) | ||
1793 | cp_next(cp); | ||
1794 | cp->linenumber = newline; | ||
1795 | } | ||
1796 | |||
1776 | /* Parse multiple C declarations of types or extern identifiers. */ | 1797 | /* Parse multiple C declarations of types or extern identifiers. */ |
1777 | static void cp_decl_multi(CPState *cp) | 1798 | static void cp_decl_multi(CPState *cp) |
1778 | { | 1799 | { |
@@ -1785,12 +1806,21 @@ static void cp_decl_multi(CPState *cp) | |||
1785 | continue; | 1806 | continue; |
1786 | } | 1807 | } |
1787 | if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ | 1808 | if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ |
1788 | BCLine pragmaline = cp->linenumber; | 1809 | BCLine hashline = cp->linenumber; |
1789 | if (!(cp_next(cp) == CTOK_IDENT && | 1810 | CPToken tok = cp_next(cp); |
1790 | cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */ | 1811 | if (tok == CTOK_INTEGER) { |
1812 | cp_line(cp, hashline); | ||
1813 | continue; | ||
1814 | } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "line")) { | ||
1815 | if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok); | ||
1816 | cp_line(cp, hashline); | ||
1817 | continue; | ||
1818 | } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "pragma")) { | ||
1819 | cp_pragma(cp, hashline); | ||
1820 | continue; | ||
1821 | } else { | ||
1791 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); | 1822 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); |
1792 | cp_pragma(cp, pragmaline); | 1823 | } |
1793 | continue; | ||
1794 | } | 1824 | } |
1795 | scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); | 1825 | scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); |
1796 | if ((cp->tok == ';' || cp->tok == CTOK_EOF) && | 1826 | if ((cp->tok == ';' || cp->tok == CTOK_EOF) && |
@@ -1856,8 +1886,6 @@ static void cp_decl_single(CPState *cp) | |||
1856 | if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF); | 1886 | if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF); |
1857 | } | 1887 | } |
1858 | 1888 | ||
1859 | #undef H_ | ||
1860 | |||
1861 | /* ------------------------------------------------------------------------ */ | 1889 | /* ------------------------------------------------------------------------ */ |
1862 | 1890 | ||
1863 | /* Protected callback for C parser. */ | 1891 | /* Protected callback for C parser. */ |