diff options
Diffstat (limited to 'src/lj_cparse.c')
| -rw-r--r-- | src/lj_cparse.c | 178 |
1 files changed, 107 insertions, 71 deletions
diff --git a/src/lj_cparse.c b/src/lj_cparse.c index f5c93d2e..a1361a12 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,30 @@ | |||
| 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 | #ifdef LUA_USE_ASSERT | ||
| 32 | #define lj_assertCP(c, ...) (lj_assertG_(G(cp->L), (c), __VA_ARGS__)) | ||
| 33 | #else | ||
| 34 | #define lj_assertCP(c, ...) ((void)cp) | ||
| 35 | #endif | ||
| 36 | |||
| 37 | /* -- Miscellaneous ------------------------------------------------------- */ | ||
| 38 | |||
| 39 | /* Match string against a C literal. */ | ||
| 40 | #define cp_str_is(str, k) \ | ||
| 41 | ((str)->len == sizeof(k)-1 && !memcmp(strdata(str), k, sizeof(k)-1)) | ||
| 42 | |||
| 43 | /* Check string against a linear list of matches. */ | ||
| 44 | int lj_cparse_case(GCstr *str, const char *match) | ||
| 45 | { | ||
| 46 | MSize len; | ||
| 47 | int n; | ||
| 48 | for (n = 0; (len = (MSize)*match++); n++, match += len) { | ||
| 49 | if (str->len == len && !memcmp(match, strdata(str), len)) | ||
| 50 | return n; | ||
| 51 | } | ||
| 52 | return -1; | ||
| 53 | } | ||
| 54 | |||
| 30 | /* -- C lexer ------------------------------------------------------------- */ | 55 | /* -- C lexer ------------------------------------------------------------- */ |
| 31 | 56 | ||
| 32 | /* C lexer token names. */ | 57 | /* C lexer token names. */ |
| @@ -42,13 +67,13 @@ LJ_NORET static void cp_err(CPState *cp, ErrMsg em); | |||
| 42 | 67 | ||
| 43 | static const char *cp_tok2str(CPState *cp, CPToken tok) | 68 | static const char *cp_tok2str(CPState *cp, CPToken tok) |
| 44 | { | 69 | { |
| 45 | lua_assert(tok < CTOK_FIRSTDECL); | 70 | lj_assertCP(tok < CTOK_FIRSTDECL, "bad CPToken %d", tok); |
| 46 | if (tok > CTOK_OFS) | 71 | if (tok > CTOK_OFS) |
| 47 | return ctoknames[tok-CTOK_OFS-1]; | 72 | return ctoknames[tok-CTOK_OFS-1]; |
| 48 | else if (!lj_char_iscntrl(tok)) | 73 | else if (!lj_char_iscntrl(tok)) |
| 49 | return lj_str_pushf(cp->L, "%c", tok); | 74 | return lj_strfmt_pushf(cp->L, "%c", tok); |
| 50 | else | 75 | else |
| 51 | return lj_str_pushf(cp->L, "char(%d)", tok); | 76 | return lj_strfmt_pushf(cp->L, "char(%d)", tok); |
| 52 | } | 77 | } |
| 53 | 78 | ||
| 54 | /* End-of-line? */ | 79 | /* End-of-line? */ |
| @@ -85,24 +110,10 @@ static LJ_NOINLINE CPChar cp_get_bs(CPState *cp) | |||
| 85 | return cp_get(cp); | 110 | return cp_get(cp); |
| 86 | } | 111 | } |
| 87 | 112 | ||
| 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. */ | 113 | /* Save character in buffer. */ |
| 100 | static LJ_AINLINE void cp_save(CPState *cp, CPChar c) | 114 | static LJ_AINLINE void cp_save(CPState *cp, CPChar c) |
| 101 | { | 115 | { |
| 102 | if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz)) | 116 | lj_buf_putb(&cp->sb, c); |
| 103 | cp_save_grow(cp, c); | ||
| 104 | else | ||
| 105 | cp->sb.buf[cp->sb.n++] = (char)c; | ||
| 106 | } | 117 | } |
| 107 | 118 | ||
| 108 | /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ | 119 | /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ |
| @@ -122,20 +133,20 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...) | |||
| 122 | tokstr = NULL; | 133 | tokstr = NULL; |
| 123 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || | 134 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || |
| 124 | tok >= CTOK_FIRSTDECL) { | 135 | tok >= CTOK_FIRSTDECL) { |
| 125 | if (cp->sb.n == 0) cp_save(cp, '$'); | 136 | if (cp->sb.w == cp->sb.b) cp_save(cp, '$'); |
| 126 | cp_save(cp, '\0'); | 137 | cp_save(cp, '\0'); |
| 127 | tokstr = cp->sb.buf; | 138 | tokstr = cp->sb.b; |
| 128 | } else { | 139 | } else { |
| 129 | tokstr = cp_tok2str(cp, tok); | 140 | tokstr = cp_tok2str(cp, tok); |
| 130 | } | 141 | } |
| 131 | L = cp->L; | 142 | L = cp->L; |
| 132 | va_start(argp, em); | 143 | va_start(argp, em); |
| 133 | msg = lj_str_pushvf(L, err2msg(em), argp); | 144 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
| 134 | va_end(argp); | 145 | va_end(argp); |
| 135 | if (tokstr) | 146 | if (tokstr) |
| 136 | msg = lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr); | 147 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr); |
| 137 | if (cp->linenumber > 1) | 148 | if (cp->linenumber > 1) |
| 138 | msg = lj_str_pushf(L, "%s at line %d", msg, cp->linenumber); | 149 | msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber); |
| 139 | lj_err_callermsg(L, msg); | 150 | lj_err_callermsg(L, msg); |
| 140 | } | 151 | } |
| 141 | 152 | ||
| @@ -164,7 +175,8 @@ static CPToken cp_number(CPState *cp) | |||
| 164 | TValue o; | 175 | TValue o; |
| 165 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); | 176 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); |
| 166 | cp_save(cp, '\0'); | 177 | cp_save(cp, '\0'); |
| 167 | fmt = lj_strscan_scan((const uint8_t *)cp->sb.buf, &o, STRSCAN_OPT_C); | 178 | fmt = lj_strscan_scan((const uint8_t *)(cp->sb.b), sbuflen(&cp->sb)-1, |
| 179 | &o, STRSCAN_OPT_C); | ||
| 168 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; | 180 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; |
| 169 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; | 181 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; |
| 170 | else if (!(cp->mode & CPARSE_MODE_SKIP)) | 182 | else if (!(cp->mode & CPARSE_MODE_SKIP)) |
| @@ -177,7 +189,7 @@ static CPToken cp_number(CPState *cp) | |||
| 177 | static CPToken cp_ident(CPState *cp) | 189 | static CPToken cp_ident(CPState *cp) |
| 178 | { | 190 | { |
| 179 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); | 191 | 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); | 192 | cp->str = lj_buf_str(cp->L, &cp->sb); |
| 181 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); | 193 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); |
| 182 | if (ctype_type(cp->ct->info) == CT_KW) | 194 | if (ctype_type(cp->ct->info) == CT_KW) |
| 183 | return ctype_cid(cp->ct->info); | 195 | return ctype_cid(cp->ct->info); |
| @@ -263,11 +275,11 @@ static CPToken cp_string(CPState *cp) | |||
| 263 | } | 275 | } |
| 264 | cp_get(cp); | 276 | cp_get(cp); |
| 265 | if (delim == '"') { | 277 | if (delim == '"') { |
| 266 | cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n); | 278 | cp->str = lj_buf_str(cp->L, &cp->sb); |
| 267 | return CTOK_STRING; | 279 | return CTOK_STRING; |
| 268 | } else { | 280 | } else { |
| 269 | if (cp->sb.n != 1) cp_err_token(cp, '\''); | 281 | if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\''); |
| 270 | cp->val.i32 = (int32_t)(char)cp->sb.buf[0]; | 282 | cp->val.i32 = (int32_t)(char)*cp->sb.b; |
| 271 | cp->val.id = CTID_INT32; | 283 | cp->val.id = CTID_INT32; |
| 272 | return CTOK_INTEGER; | 284 | return CTOK_INTEGER; |
| 273 | } | 285 | } |
| @@ -296,7 +308,7 @@ static void cp_comment_cpp(CPState *cp) | |||
| 296 | /* Lexical scanner for C. Only a minimal subset is implemented. */ | 308 | /* Lexical scanner for C. Only a minimal subset is implemented. */ |
| 297 | static CPToken cp_next_(CPState *cp) | 309 | static CPToken cp_next_(CPState *cp) |
| 298 | { | 310 | { |
| 299 | lj_str_resetbuf(&cp->sb); | 311 | lj_buf_reset(&cp->sb); |
| 300 | for (;;) { | 312 | for (;;) { |
| 301 | if (lj_char_isident(cp->c)) | 313 | if (lj_char_isident(cp->c)) |
| 302 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); | 314 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); |
| @@ -385,9 +397,8 @@ static void cp_init(CPState *cp) | |||
| 385 | cp->depth = 0; | 397 | cp->depth = 0; |
| 386 | cp->curpack = 0; | 398 | cp->curpack = 0; |
| 387 | cp->packstack[0] = 255; | 399 | cp->packstack[0] = 255; |
| 388 | lj_str_initbuf(&cp->sb); | 400 | lj_buf_init(cp->L, &cp->sb); |
| 389 | lj_str_resizebuf(cp->L, &cp->sb, LJ_MIN_SBUF); | 401 | lj_assertCP(cp->p != NULL, "uninitialized cp->p"); |
| 390 | lua_assert(cp->p != NULL); | ||
| 391 | cp_get(cp); /* Read-ahead first char. */ | 402 | cp_get(cp); /* Read-ahead first char. */ |
| 392 | cp->tok = 0; | 403 | cp->tok = 0; |
| 393 | cp->tmask = CPNS_DEFAULT; | 404 | cp->tmask = CPNS_DEFAULT; |
| @@ -398,7 +409,7 @@ static void cp_init(CPState *cp) | |||
| 398 | static void cp_cleanup(CPState *cp) | 409 | static void cp_cleanup(CPState *cp) |
| 399 | { | 410 | { |
| 400 | global_State *g = G(cp->L); | 411 | global_State *g = G(cp->L); |
| 401 | lj_str_freebuf(g, &cp->sb); | 412 | lj_buf_free(g, &cp->sb); |
| 402 | } | 413 | } |
| 403 | 414 | ||
| 404 | /* Check and consume optional token. */ | 415 | /* Check and consume optional token. */ |
| @@ -848,12 +859,13 @@ static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl) | |||
| 848 | /* The cid is already part of info for copies of pointers/functions. */ | 859 | /* The cid is already part of info for copies of pointers/functions. */ |
| 849 | idx = ct->next; | 860 | idx = ct->next; |
| 850 | if (ctype_istypedef(info)) { | 861 | if (ctype_istypedef(info)) { |
| 851 | lua_assert(id == 0); | 862 | lj_assertCP(id == 0, "typedef not at toplevel"); |
| 852 | id = ctype_cid(info); | 863 | id = ctype_cid(info); |
| 853 | /* Always refetch info/size, since struct/enum may have been completed. */ | 864 | /* Always refetch info/size, since struct/enum may have been completed. */ |
| 854 | cinfo = ctype_get(cp->cts, id)->info; | 865 | cinfo = ctype_get(cp->cts, id)->info; |
| 855 | csize = ctype_get(cp->cts, id)->size; | 866 | csize = ctype_get(cp->cts, id)->size; |
| 856 | lua_assert(ctype_isstruct(cinfo) || ctype_isenum(cinfo)); | 867 | lj_assertCP(ctype_isstruct(cinfo) || ctype_isenum(cinfo), |
| 868 | "typedef of bad type"); | ||
| 857 | } else if (ctype_isfunc(info)) { /* Intern function. */ | 869 | } else if (ctype_isfunc(info)) { /* Intern function. */ |
| 858 | CType *fct; | 870 | CType *fct; |
| 859 | CTypeID fid; | 871 | CTypeID fid; |
| @@ -886,7 +898,7 @@ static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl) | |||
| 886 | /* Inherit csize/cinfo from original type. */ | 898 | /* Inherit csize/cinfo from original type. */ |
| 887 | } else { | 899 | } else { |
| 888 | if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */ | 900 | if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */ |
| 889 | lua_assert(id == 0); | 901 | lj_assertCP(id == 0, "number not at toplevel"); |
| 890 | if (!(info & CTF_BOOL)) { | 902 | if (!(info & CTF_BOOL)) { |
| 891 | CTSize msize = ctype_msizeP(decl->attr); | 903 | CTSize msize = ctype_msizeP(decl->attr); |
| 892 | CTSize vsize = ctype_vsizeP(decl->attr); | 904 | CTSize vsize = ctype_vsizeP(decl->attr); |
| @@ -941,7 +953,7 @@ static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl) | |||
| 941 | info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN); | 953 | info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN); |
| 942 | info |= (cinfo & CTF_QUAL); /* Inherit qual. */ | 954 | info |= (cinfo & CTF_QUAL); /* Inherit qual. */ |
| 943 | } else { | 955 | } else { |
| 944 | lua_assert(ctype_isvoid(info)); | 956 | lj_assertCP(ctype_isvoid(info), "bad ctype %08x", info); |
| 945 | } | 957 | } |
| 946 | csize = size; | 958 | csize = size; |
| 947 | cinfo = info+id; | 959 | cinfo = info+id; |
| @@ -953,8 +965,6 @@ static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl) | |||
| 953 | 965 | ||
| 954 | /* -- C declaration parser ------------------------------------------------ */ | 966 | /* -- C declaration parser ------------------------------------------------ */ |
| 955 | 967 | ||
| 956 | #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be) | ||
| 957 | |||
| 958 | /* Reset declaration state to declaration specifier. */ | 968 | /* Reset declaration state to declaration specifier. */ |
| 959 | static void cp_decl_reset(CPDecl *decl) | 969 | static void cp_decl_reset(CPDecl *decl) |
| 960 | { | 970 | { |
| @@ -1031,7 +1041,7 @@ static void cp_decl_asm(CPState *cp, CPDecl *decl) | |||
| 1031 | if (cp->tok == CTOK_STRING) { | 1041 | if (cp->tok == CTOK_STRING) { |
| 1032 | GCstr *str = cp->str; | 1042 | GCstr *str = cp->str; |
| 1033 | while (cp_next(cp) == CTOK_STRING) { | 1043 | while (cp_next(cp) == CTOK_STRING) { |
| 1034 | lj_str_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); | 1044 | lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); |
| 1035 | cp->L->top--; | 1045 | cp->L->top--; |
| 1036 | str = strV(cp->L->top); | 1046 | str = strV(cp->L->top); |
| 1037 | } | 1047 | } |
| @@ -1083,44 +1093,57 @@ static void cp_decl_gccattribute(CPState *cp, CPDecl *decl) | |||
| 1083 | if (cp->tok == CTOK_IDENT) { | 1093 | if (cp->tok == CTOK_IDENT) { |
| 1084 | GCstr *attrstr = cp->str; | 1094 | GCstr *attrstr = cp->str; |
| 1085 | cp_next(cp); | 1095 | cp_next(cp); |
| 1086 | switch (attrstr->hash) { | 1096 | switch (lj_cparse_case(attrstr, |
| 1087 | case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */ | 1097 | "\007aligned" "\013__aligned__" |
| 1098 | "\006packed" "\012__packed__" | ||
| 1099 | "\004mode" "\010__mode__" | ||
| 1100 | "\013vector_size" "\017__vector_size__" | ||
| 1101 | #if LJ_TARGET_X86 | ||
| 1102 | "\007regparm" "\013__regparm__" | ||
| 1103 | "\005cdecl" "\011__cdecl__" | ||
| 1104 | "\010thiscall" "\014__thiscall__" | ||
| 1105 | "\010fastcall" "\014__fastcall__" | ||
| 1106 | "\007stdcall" "\013__stdcall__" | ||
| 1107 | "\012sseregparm" "\016__sseregparm__" | ||
| 1108 | #endif | ||
| 1109 | )) { | ||
| 1110 | case 0: case 1: /* aligned */ | ||
| 1088 | cp_decl_align(cp, decl); | 1111 | cp_decl_align(cp, decl); |
| 1089 | break; | 1112 | break; |
| 1090 | case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */ | 1113 | case 2: case 3: /* packed */ |
| 1091 | decl->attr |= CTFP_PACKED; | 1114 | decl->attr |= CTFP_PACKED; |
| 1092 | break; | 1115 | break; |
| 1093 | case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */ | 1116 | case 4: case 5: /* mode */ |
| 1094 | cp_decl_mode(cp, decl); | 1117 | cp_decl_mode(cp, decl); |
| 1095 | break; | 1118 | break; |
| 1096 | case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */ | 1119 | case 6: case 7: /* vector_size */ |
| 1097 | { | 1120 | { |
| 1098 | CTSize vsize = cp_decl_sizeattr(cp); | 1121 | CTSize vsize = cp_decl_sizeattr(cp); |
| 1099 | if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize)); | 1122 | if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize)); |
| 1100 | } | 1123 | } |
| 1101 | break; | 1124 | break; |
| 1102 | #if LJ_TARGET_X86 | 1125 | #if LJ_TARGET_X86 |
| 1103 | case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */ | 1126 | case 8: case 9: /* regparm */ |
| 1104 | CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp)); | 1127 | CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp)); |
| 1105 | decl->fattr |= CTFP_CCONV; | 1128 | decl->fattr |= CTFP_CCONV; |
| 1106 | break; | 1129 | break; |
| 1107 | case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */ | 1130 | case 10: case 11: /* cdecl */ |
| 1108 | CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL); | 1131 | CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL); |
| 1109 | decl->fattr |= CTFP_CCONV; | 1132 | decl->fattr |= CTFP_CCONV; |
| 1110 | break; | 1133 | break; |
| 1111 | case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */ | 1134 | case 12: case 13: /* thiscall */ |
| 1112 | CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL); | 1135 | CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL); |
| 1113 | decl->fattr |= CTFP_CCONV; | 1136 | decl->fattr |= CTFP_CCONV; |
| 1114 | break; | 1137 | break; |
| 1115 | case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */ | 1138 | case 14: case 15: /* fastcall */ |
| 1116 | CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL); | 1139 | CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL); |
| 1117 | decl->fattr |= CTFP_CCONV; | 1140 | decl->fattr |= CTFP_CCONV; |
| 1118 | break; | 1141 | break; |
| 1119 | case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */ | 1142 | case 16: case 17: /* stdcall */ |
| 1120 | CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL); | 1143 | CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL); |
| 1121 | decl->fattr |= CTFP_CCONV; | 1144 | decl->fattr |= CTFP_CCONV; |
| 1122 | break; | 1145 | break; |
| 1123 | case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */ | 1146 | case 18: case 19: /* sseregparm */ |
| 1124 | decl->fattr |= CTF_SSEREGPARM; | 1147 | decl->fattr |= CTF_SSEREGPARM; |
| 1125 | decl->fattr |= CTFP_CCONV; | 1148 | decl->fattr |= CTFP_CCONV; |
| 1126 | break; | 1149 | break; |
| @@ -1152,16 +1175,13 @@ static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl) | |||
| 1152 | while (cp->tok == CTOK_IDENT) { | 1175 | while (cp->tok == CTOK_IDENT) { |
| 1153 | GCstr *attrstr = cp->str; | 1176 | GCstr *attrstr = cp->str; |
| 1154 | cp_next(cp); | 1177 | cp_next(cp); |
| 1155 | switch (attrstr->hash) { | 1178 | if (cp_str_is(attrstr, "align")) { |
| 1156 | case H_(bc2395fa,98f267f8): /* align */ | ||
| 1157 | cp_decl_align(cp, decl); | 1179 | cp_decl_align(cp, decl); |
| 1158 | break; | 1180 | } else { /* Ignore all other attributes. */ |
| 1159 | default: /* Ignore all other attributes. */ | ||
| 1160 | if (cp_opt(cp, '(')) { | 1181 | if (cp_opt(cp, '(')) { |
| 1161 | while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp); | 1182 | while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp); |
| 1162 | cp_check(cp, ')'); | 1183 | cp_check(cp, ')'); |
| 1163 | } | 1184 | } |
| 1164 | break; | ||
| 1165 | } | 1185 | } |
| 1166 | } | 1186 | } |
| 1167 | cp_check(cp, ')'); | 1187 | cp_check(cp, ')'); |
| @@ -1574,7 +1594,7 @@ end_decl: | |||
| 1574 | cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC); | 1594 | cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC); |
| 1575 | sz = sizeof(int); | 1595 | sz = sizeof(int); |
| 1576 | } | 1596 | } |
| 1577 | lua_assert(sz != 0); | 1597 | lj_assertCP(sz != 0, "basic ctype with zero size"); |
| 1578 | info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */ | 1598 | info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */ |
| 1579 | info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */ | 1599 | info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */ |
| 1580 | cp_push(decl, info, sz); | 1600 | cp_push(decl, info, sz); |
| @@ -1743,19 +1763,18 @@ static CTypeID cp_decl_abstract(CPState *cp) | |||
| 1743 | static void cp_pragma(CPState *cp, BCLine pragmaline) | 1763 | static void cp_pragma(CPState *cp, BCLine pragmaline) |
| 1744 | { | 1764 | { |
| 1745 | cp_next(cp); | 1765 | cp_next(cp); |
| 1746 | if (cp->tok == CTOK_IDENT && | 1766 | if (cp->tok == CTOK_IDENT && cp_str_is(cp->str, "pack")) { |
| 1747 | cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */ | ||
| 1748 | cp_next(cp); | 1767 | cp_next(cp); |
| 1749 | cp_check(cp, '('); | 1768 | cp_check(cp, '('); |
| 1750 | if (cp->tok == CTOK_IDENT) { | 1769 | if (cp->tok == CTOK_IDENT) { |
| 1751 | if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */ | 1770 | if (cp_str_is(cp->str, "push")) { |
| 1752 | if (cp->curpack < CPARSE_MAX_PACKSTACK-1) { | 1771 | if (cp->curpack < CPARSE_MAX_PACKSTACK-1) { |
| 1753 | cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack]; | 1772 | cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack]; |
| 1754 | cp->curpack++; | 1773 | cp->curpack++; |
| 1755 | } else { | 1774 | } else { |
| 1756 | cp_errmsg(cp, cp->tok, LJ_ERR_XLEVELS); | 1775 | cp_errmsg(cp, cp->tok, LJ_ERR_XLEVELS); |
| 1757 | } | 1776 | } |
| 1758 | } else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */ | 1777 | } else if (cp_str_is(cp->str, "pop")) { |
| 1759 | if (cp->curpack > 0) cp->curpack--; | 1778 | if (cp->curpack > 0) cp->curpack--; |
| 1760 | } else { | 1779 | } else { |
| 1761 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); | 1780 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); |
| @@ -1777,6 +1796,16 @@ static void cp_pragma(CPState *cp, BCLine pragmaline) | |||
| 1777 | } | 1796 | } |
| 1778 | } | 1797 | } |
| 1779 | 1798 | ||
| 1799 | /* Handle line number. */ | ||
| 1800 | static void cp_line(CPState *cp, BCLine hashline) | ||
| 1801 | { | ||
| 1802 | BCLine newline = cp->val.u32; | ||
| 1803 | /* TODO: Handle file name and include it in error messages. */ | ||
| 1804 | while (cp->tok != CTOK_EOF && cp->linenumber == hashline) | ||
| 1805 | cp_next(cp); | ||
| 1806 | cp->linenumber = newline; | ||
| 1807 | } | ||
| 1808 | |||
| 1780 | /* Parse multiple C declarations of types or extern identifiers. */ | 1809 | /* Parse multiple C declarations of types or extern identifiers. */ |
| 1781 | static void cp_decl_multi(CPState *cp) | 1810 | static void cp_decl_multi(CPState *cp) |
| 1782 | { | 1811 | { |
| @@ -1789,12 +1818,21 @@ static void cp_decl_multi(CPState *cp) | |||
| 1789 | continue; | 1818 | continue; |
| 1790 | } | 1819 | } |
| 1791 | if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ | 1820 | if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */ |
| 1792 | BCLine pragmaline = cp->linenumber; | 1821 | BCLine hashline = cp->linenumber; |
| 1793 | if (!(cp_next(cp) == CTOK_IDENT && | 1822 | CPToken tok = cp_next(cp); |
| 1794 | cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */ | 1823 | if (tok == CTOK_INTEGER) { |
| 1824 | cp_line(cp, hashline); | ||
| 1825 | continue; | ||
| 1826 | } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "line")) { | ||
| 1827 | if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok); | ||
| 1828 | cp_line(cp, hashline); | ||
| 1829 | continue; | ||
| 1830 | } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "pragma")) { | ||
| 1831 | cp_pragma(cp, hashline); | ||
| 1832 | continue; | ||
| 1833 | } else { | ||
| 1795 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); | 1834 | cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL); |
| 1796 | cp_pragma(cp, pragmaline); | 1835 | } |
| 1797 | continue; | ||
| 1798 | } | 1836 | } |
| 1799 | scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); | 1837 | scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC); |
| 1800 | if ((cp->tok == ';' || cp->tok == CTOK_EOF) && | 1838 | if ((cp->tok == ';' || cp->tok == CTOK_EOF) && |
| @@ -1818,7 +1856,7 @@ static void cp_decl_multi(CPState *cp) | |||
| 1818 | /* Treat both static and extern function declarations as extern. */ | 1856 | /* Treat both static and extern function declarations as extern. */ |
| 1819 | ct = ctype_get(cp->cts, ctypeid); | 1857 | ct = ctype_get(cp->cts, ctypeid); |
| 1820 | /* We always get new anonymous functions (typedefs are copied). */ | 1858 | /* We always get new anonymous functions (typedefs are copied). */ |
| 1821 | lua_assert(gcref(ct->name) == NULL); | 1859 | lj_assertCP(gcref(ct->name) == NULL, "unexpected named function"); |
| 1822 | id = ctypeid; /* Just name it. */ | 1860 | id = ctypeid; /* Just name it. */ |
| 1823 | } else if ((scl & CDF_STATIC)) { /* Accept static constants. */ | 1861 | } else if ((scl & CDF_STATIC)) { /* Accept static constants. */ |
| 1824 | id = cp_decl_constinit(cp, &ct, ctypeid); | 1862 | id = cp_decl_constinit(cp, &ct, ctypeid); |
| @@ -1860,8 +1898,6 @@ static void cp_decl_single(CPState *cp) | |||
| 1860 | if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF); | 1898 | if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF); |
| 1861 | } | 1899 | } |
| 1862 | 1900 | ||
| 1863 | #undef H_ | ||
| 1864 | |||
| 1865 | /* ------------------------------------------------------------------------ */ | 1901 | /* ------------------------------------------------------------------------ */ |
| 1866 | 1902 | ||
| 1867 | /* Protected callback for C parser. */ | 1903 | /* Protected callback for C parser. */ |
| @@ -1877,7 +1913,7 @@ static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud) | |||
| 1877 | cp_decl_single(cp); | 1913 | cp_decl_single(cp); |
| 1878 | if (cp->param && cp->param != cp->L->top) | 1914 | if (cp->param && cp->param != cp->L->top) |
| 1879 | cp_err(cp, LJ_ERR_FFI_NUMPARAM); | 1915 | cp_err(cp, LJ_ERR_FFI_NUMPARAM); |
| 1880 | lua_assert(cp->depth == 0); | 1916 | lj_assertCP(cp->depth == 0, "unbalanced cparser declaration depth"); |
| 1881 | return NULL; | 1917 | return NULL; |
| 1882 | } | 1918 | } |
| 1883 | 1919 | ||
