aboutsummaryrefslogtreecommitdiff
path: root/src/lj_cparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_cparse.c')
-rw-r--r--src/lj_cparse.c83
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. */
89static 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. */
100static LJ_AINLINE void cp_save(CPState *cp, CPChar c) 90static 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)
177static CPToken cp_ident(CPState *cp) 164static 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. */
297static CPToken cp_next_(CPState *cp) 284static 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)
398static void cp_cleanup(CPState *cp) 384static 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. */
1763static 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. */
1777static void cp_decl_multi(CPState *cp) 1773static 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) &&