aboutsummaryrefslogtreecommitdiff
path: root/src/lj_cparse.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-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 5b359306..7ec4a5ee 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);
@@ -380,8 +367,7 @@ static void cp_init(CPState *cp)
380 cp->depth = 0; 367 cp->depth = 0;
381 cp->curpack = 0; 368 cp->curpack = 0;
382 cp->packstack[0] = 255; 369 cp->packstack[0] = 255;
383 lj_str_initbuf(&cp->sb); 370 lj_buf_init(cp->L, &cp->sb);
384 lj_str_resizebuf(cp->L, &cp->sb, LJ_MIN_SBUF);
385 lua_assert(cp->p != NULL); 371 lua_assert(cp->p != NULL);
386 cp_get(cp); /* Read-ahead first char. */ 372 cp_get(cp); /* Read-ahead first char. */
387 cp->tok = 0; 373 cp->tok = 0;
@@ -393,7 +379,7 @@ static void cp_init(CPState *cp)
393static void cp_cleanup(CPState *cp) 379static void cp_cleanup(CPState *cp)
394{ 380{
395 global_State *g = G(cp->L); 381 global_State *g = G(cp->L);
396 lj_str_freebuf(g, &cp->sb); 382 lj_buf_free(g, &cp->sb);
397} 383}
398 384
399/* Check and consume optional token. */ 385/* Check and consume optional token. */
@@ -1016,7 +1002,7 @@ static void cp_decl_asm(CPState *cp, CPDecl *decl)
1016 if (cp->tok == CTOK_STRING) { 1002 if (cp->tok == CTOK_STRING) {
1017 GCstr *str = cp->str; 1003 GCstr *str = cp->str;
1018 while (cp_next(cp) == CTOK_STRING) { 1004 while (cp_next(cp) == CTOK_STRING) {
1019 lj_str_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); 1005 lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str));
1020 cp->L->top--; 1006 cp->L->top--;
1021 str = strV(cp->L->top); 1007 str = strV(cp->L->top);
1022 } 1008 }
@@ -1758,6 +1744,16 @@ static void cp_pragma(CPState *cp, BCLine pragmaline)
1758 } 1744 }
1759} 1745}
1760 1746
1747/* Handle line number. */
1748static void cp_line(CPState *cp, BCLine hashline)
1749{
1750 BCLine newline = cp->val.u32;
1751 /* TODO: Handle file name and include it in error messages. */
1752 while (cp->tok != CTOK_EOF && cp->linenumber == hashline)
1753 cp_next(cp);
1754 cp->linenumber = newline;
1755}
1756
1761/* Parse multiple C declarations of types or extern identifiers. */ 1757/* Parse multiple C declarations of types or extern identifiers. */
1762static void cp_decl_multi(CPState *cp) 1758static void cp_decl_multi(CPState *cp)
1763{ 1759{
@@ -1770,12 +1766,23 @@ static void cp_decl_multi(CPState *cp)
1770 continue; 1766 continue;
1771 } 1767 }
1772 if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ 1768 if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */
1773 BCLine pragmaline = cp->linenumber; 1769 BCLine hashline = cp->linenumber;
1774 if (!(cp_next(cp) == CTOK_IDENT && 1770 CPToken tok = cp_next(cp);
1775 cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */ 1771 if (tok == CTOK_INTEGER) {
1772 cp_line(cp, hashline);
1773 continue;
1774 } else if (tok == CTOK_IDENT &&
1775 cp->str->hash == H_(187aab88,fcb60b42)) { /* line */
1776 if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok);
1777 cp_line(cp, hashline);
1778 continue;
1779 } else if (tok == CTOK_IDENT &&
1780 cp->str->hash == H_(f5e6b4f8,1d509107)) { /* pragma */
1781 cp_pragma(cp, hashline);
1782 continue;
1783 } else {
1776 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); 1784 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1777 cp_pragma(cp, pragmaline); 1785 }
1778 continue;
1779 } 1786 }
1780 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); 1787 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
1781 if ((cp->tok == ';' || cp->tok == CTOK_EOF) && 1788 if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&