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.c152
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. */
38int 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. */
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. */ 107/* Save character in buffer. */
100static LJ_AINLINE void cp_save(CPState *cp, CPChar c) 108static 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)
177static CPToken cp_ident(CPState *cp) 182static 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. */
297static CPToken cp_next_(CPState *cp) 302static 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)
398static void cp_cleanup(CPState *cp) 402static 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. */
959static void cp_decl_reset(CPDecl *decl) 961static 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)
1741static void cp_pragma(CPState *cp, BCLine pragmaline) 1753static 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. */
1788static 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. */
1777static void cp_decl_multi(CPState *cp) 1798static 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. */