diff options
Diffstat (limited to 'src/lj_cparse.c')
-rw-r--r-- | src/lj_cparse.c | 83 |
1 files changed, 45 insertions, 38 deletions
diff --git a/src/lj_cparse.c b/src/lj_cparse.c index f111537d..19f632ff 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 |
@@ -46,9 +47,9 @@ static const char *cp_tok2str(CPState *cp, CPToken tok) | |||
46 | if (tok > CTOK_OFS) | 47 | if (tok > CTOK_OFS) |
47 | return ctoknames[tok-CTOK_OFS-1]; | 48 | return ctoknames[tok-CTOK_OFS-1]; |
48 | else if (!lj_char_iscntrl(tok)) | 49 | else if (!lj_char_iscntrl(tok)) |
49 | return lj_str_pushf(cp->L, "%c", tok); | 50 | return lj_strfmt_pushf(cp->L, "%c", tok); |
50 | else | 51 | else |
51 | return lj_str_pushf(cp->L, "char(%d)", tok); | 52 | return lj_strfmt_pushf(cp->L, "char(%d)", tok); |
52 | } | 53 | } |
53 | 54 | ||
54 | /* End-of-line? */ | 55 | /* End-of-line? */ |
@@ -85,24 +86,10 @@ static LJ_NOINLINE CPChar cp_get_bs(CPState *cp) | |||
85 | return cp_get(cp); | 86 | return cp_get(cp); |
86 | } | 87 | } |
87 | 88 | ||
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. */ | 89 | /* Save character in buffer. */ |
100 | static LJ_AINLINE void cp_save(CPState *cp, CPChar c) | 90 | static LJ_AINLINE void cp_save(CPState *cp, CPChar c) |
101 | { | 91 | { |
102 | if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz)) | 92 | lj_buf_putb(&cp->sb, c); |
103 | cp_save_grow(cp, c); | ||
104 | else | ||
105 | cp->sb.buf[cp->sb.n++] = (char)c; | ||
106 | } | 93 | } |
107 | 94 | ||
108 | /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ | 95 | /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ |
@@ -122,20 +109,20 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...) | |||
122 | tokstr = NULL; | 109 | tokstr = NULL; |
123 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || | 110 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || |
124 | tok >= CTOK_FIRSTDECL) { | 111 | tok >= CTOK_FIRSTDECL) { |
125 | if (cp->sb.n == 0) cp_save(cp, '$'); | 112 | if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$'); |
126 | cp_save(cp, '\0'); | 113 | cp_save(cp, '\0'); |
127 | tokstr = cp->sb.buf; | 114 | tokstr = sbufB(&cp->sb); |
128 | } else { | 115 | } else { |
129 | tokstr = cp_tok2str(cp, tok); | 116 | tokstr = cp_tok2str(cp, tok); |
130 | } | 117 | } |
131 | L = cp->L; | 118 | L = cp->L; |
132 | va_start(argp, em); | 119 | va_start(argp, em); |
133 | msg = lj_str_pushvf(L, err2msg(em), argp); | 120 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
134 | va_end(argp); | 121 | va_end(argp); |
135 | if (tokstr) | 122 | if (tokstr) |
136 | msg = lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr); | 123 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr); |
137 | if (cp->linenumber > 1) | 124 | if (cp->linenumber > 1) |
138 | msg = lj_str_pushf(L, "%s at line %d", msg, cp->linenumber); | 125 | msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber); |
139 | lj_err_callermsg(L, msg); | 126 | lj_err_callermsg(L, msg); |
140 | } | 127 | } |
141 | 128 | ||
@@ -164,7 +151,7 @@ static CPToken cp_number(CPState *cp) | |||
164 | TValue o; | 151 | TValue o; |
165 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); | 152 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); |
166 | cp_save(cp, '\0'); | 153 | cp_save(cp, '\0'); |
167 | fmt = lj_strscan_scan((const uint8_t *)cp->sb.buf, &o, STRSCAN_OPT_C); | 154 | fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), &o, STRSCAN_OPT_C); |
168 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; | 155 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; |
169 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; | 156 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; |
170 | else if (!(cp->mode & CPARSE_MODE_SKIP)) | 157 | else if (!(cp->mode & CPARSE_MODE_SKIP)) |
@@ -177,7 +164,7 @@ static CPToken cp_number(CPState *cp) | |||
177 | static CPToken cp_ident(CPState *cp) | 164 | static CPToken cp_ident(CPState *cp) |
178 | { | 165 | { |
179 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); | 166 | 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); | 167 | cp->str = lj_buf_str(cp->L, &cp->sb); |
181 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); | 168 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); |
182 | if (ctype_type(cp->ct->info) == CT_KW) | 169 | if (ctype_type(cp->ct->info) == CT_KW) |
183 | return ctype_cid(cp->ct->info); | 170 | return ctype_cid(cp->ct->info); |
@@ -263,11 +250,11 @@ static CPToken cp_string(CPState *cp) | |||
263 | } | 250 | } |
264 | cp_get(cp); | 251 | cp_get(cp); |
265 | if (delim == '"') { | 252 | if (delim == '"') { |
266 | cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n); | 253 | cp->str = lj_buf_str(cp->L, &cp->sb); |
267 | return CTOK_STRING; | 254 | return CTOK_STRING; |
268 | } else { | 255 | } else { |
269 | if (cp->sb.n != 1) cp_err_token(cp, '\''); | 256 | if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\''); |
270 | cp->val.i32 = (int32_t)(char)cp->sb.buf[0]; | 257 | cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb); |
271 | cp->val.id = CTID_INT32; | 258 | cp->val.id = CTID_INT32; |
272 | return CTOK_INTEGER; | 259 | return CTOK_INTEGER; |
273 | } | 260 | } |
@@ -296,7 +283,7 @@ static void cp_comment_cpp(CPState *cp) | |||
296 | /* Lexical scanner for C. Only a minimal subset is implemented. */ | 283 | /* Lexical scanner for C. Only a minimal subset is implemented. */ |
297 | static CPToken cp_next_(CPState *cp) | 284 | static CPToken cp_next_(CPState *cp) |
298 | { | 285 | { |
299 | lj_str_resetbuf(&cp->sb); | 286 | lj_buf_reset(&cp->sb); |
300 | for (;;) { | 287 | for (;;) { |
301 | if (lj_char_isident(cp->c)) | 288 | if (lj_char_isident(cp->c)) |
302 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); | 289 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); |
@@ -385,8 +372,7 @@ static void cp_init(CPState *cp) | |||
385 | cp->depth = 0; | 372 | cp->depth = 0; |
386 | cp->curpack = 0; | 373 | cp->curpack = 0; |
387 | cp->packstack[0] = 255; | 374 | cp->packstack[0] = 255; |
388 | lj_str_initbuf(&cp->sb); | 375 | lj_buf_init(cp->L, &cp->sb); |
389 | lj_str_resizebuf(cp->L, &cp->sb, LJ_MIN_SBUF); | ||
390 | lua_assert(cp->p != NULL); | 376 | lua_assert(cp->p != NULL); |
391 | cp_get(cp); /* Read-ahead first char. */ | 377 | cp_get(cp); /* Read-ahead first char. */ |
392 | cp->tok = 0; | 378 | cp->tok = 0; |
@@ -398,7 +384,7 @@ static void cp_init(CPState *cp) | |||
398 | static void cp_cleanup(CPState *cp) | 384 | static void cp_cleanup(CPState *cp) |
399 | { | 385 | { |
400 | global_State *g = G(cp->L); | 386 | global_State *g = G(cp->L); |
401 | lj_str_freebuf(g, &cp->sb); | 387 | lj_buf_free(g, &cp->sb); |
402 | } | 388 | } |
403 | 389 | ||
404 | /* Check and consume optional token. */ | 390 | /* Check and consume optional token. */ |
@@ -1031,7 +1017,7 @@ static void cp_decl_asm(CPState *cp, CPDecl *decl) | |||
1031 | if (cp->tok == CTOK_STRING) { | 1017 | if (cp->tok == CTOK_STRING) { |
1032 | GCstr *str = cp->str; | 1018 | GCstr *str = cp->str; |
1033 | while (cp_next(cp) == CTOK_STRING) { | 1019 | while (cp_next(cp) == CTOK_STRING) { |
1034 | lj_str_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); | 1020 | lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); |
1035 | cp->L->top--; | 1021 | cp->L->top--; |
1036 | str = strV(cp->L->top); | 1022 | str = strV(cp->L->top); |
1037 | } | 1023 | } |
@@ -1773,6 +1759,16 @@ static void cp_pragma(CPState *cp, BCLine pragmaline) | |||
1773 | } | 1759 | } |
1774 | } | 1760 | } |
1775 | 1761 | ||
1762 | /* Handle line number. */ | ||
1763 | static void cp_line(CPState *cp, BCLine hashline) | ||
1764 | { | ||
1765 | BCLine newline = cp->val.u32; | ||
1766 | /* TODO: Handle file name and include it in error messages. */ | ||
1767 | while (cp->tok != CTOK_EOF && cp->linenumber == hashline) | ||
1768 | cp_next(cp); | ||
1769 | cp->linenumber = newline; | ||
1770 | } | ||
1771 | |||
1776 | /* Parse multiple C declarations of types or extern identifiers. */ | 1772 | /* Parse multiple C declarations of types or extern identifiers. */ |
1777 | static void cp_decl_multi(CPState *cp) | 1773 | static void cp_decl_multi(CPState *cp) |
1778 | { | 1774 | { |
@@ -1785,12 +1781,23 @@ static void cp_decl_multi(CPState *cp) | |||
1785 | continue; | 1781 | continue; |
1786 | } | 1782 | } |
1787 | if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ | 1783 | if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ |
1788 | BCLine pragmaline = cp->linenumber; | 1784 | BCLine hashline = cp->linenumber; |
1789 | if (!(cp_next(cp) == CTOK_IDENT && | 1785 | CPToken tok = cp_next(cp); |
1790 | cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */ | 1786 | if (tok == CTOK_INTEGER) { |
1787 | cp_line(cp, hashline); | ||
1788 | continue; | ||
1789 | } else if (tok == CTOK_IDENT && | ||
1790 | cp->str->hash == H_(187aab88,fcb60b42)) { /* line */ | ||
1791 | if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok); | ||
1792 | cp_line(cp, hashline); | ||
1793 | continue; | ||
1794 | } else if (tok == CTOK_IDENT && | ||
1795 | cp->str->hash == H_(f5e6b4f8,1d509107)) { /* pragma */ | ||
1796 | cp_pragma(cp, hashline); | ||
1797 | continue; | ||
1798 | } else { | ||
1791 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); | 1799 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); |
1792 | cp_pragma(cp, pragmaline); | 1800 | } |
1793 | continue; | ||
1794 | } | 1801 | } |
1795 | scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); | 1802 | scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); |
1796 | if ((cp->tok == ';' || cp->tok == CTOK_EOF) && | 1803 | if ((cp->tok == ';' || cp->tok == CTOK_EOF) && |