diff options
Diffstat (limited to 'src/lj_lex.c')
-rw-r--r-- | src/lj_lex.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/src/lj_lex.c b/src/lj_lex.c index a115b79a..01e5ce57 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c | |||
@@ -13,6 +13,12 @@ | |||
13 | #include "lj_gc.h" | 13 | #include "lj_gc.h" |
14 | #include "lj_err.h" | 14 | #include "lj_err.h" |
15 | #include "lj_str.h" | 15 | #include "lj_str.h" |
16 | #if LJ_HASFFI | ||
17 | #include "lj_tab.h" | ||
18 | #include "lj_ctype.h" | ||
19 | #include "lj_cdata.h" | ||
20 | #include "lualib.h" | ||
21 | #endif | ||
16 | #include "lj_lex.h" | 22 | #include "lj_lex.h" |
17 | #include "lj_parse.h" | 23 | #include "lj_parse.h" |
18 | #include "lj_char.h" | 24 | #include "lj_char.h" |
@@ -77,7 +83,64 @@ static void inclinenumber(LexState *ls) | |||
77 | 83 | ||
78 | /* -- Scanner for terminals ----------------------------------------------- */ | 84 | /* -- Scanner for terminals ----------------------------------------------- */ |
79 | 85 | ||
80 | static void read_numeral(LexState *ls, TValue *tv) | 86 | #if LJ_HASFFI |
87 | /* Load FFI library on-demand. Needed if we create cdata objects. */ | ||
88 | static void lex_loadffi(lua_State *L) | ||
89 | { | ||
90 | cTValue *tmp; | ||
91 | luaopen_ffi(L); | ||
92 | tmp = lj_tab_getstr(tabV(registry(L)), lj_str_newlit(L, "_LOADED")); | ||
93 | if (tmp && tvistab(tmp)) { | ||
94 | GCtab *t = tabV(tmp); | ||
95 | copyTV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "ffi")), L->top-1); | ||
96 | lj_gc_anybarriert(L, t); | ||
97 | } | ||
98 | L->top--; | ||
99 | } | ||
100 | |||
101 | /* Parse 64 bit integer. */ | ||
102 | static int lex_number64(LexState *ls, TValue *tv) | ||
103 | { | ||
104 | uint64_t n = 0; | ||
105 | uint8_t *p = (uint8_t *)ls->sb.buf; | ||
106 | CTypeID id = CTID_INT64; | ||
107 | GCcdata *cd; | ||
108 | int numl = 0; | ||
109 | if (p[0] == '0' && (p[1] & ~0x20) == 'X') { /* Hexadecimal. */ | ||
110 | p += 2; | ||
111 | if (!lj_char_isxdigit(*p)) return 0; | ||
112 | do { | ||
113 | n = n*16 + (*p & 15); | ||
114 | if (!lj_char_isdigit(*p)) n += 9; | ||
115 | p++; | ||
116 | } while (lj_char_isxdigit(*p)); | ||
117 | } else { /* Decimal. */ | ||
118 | if (!lj_char_isdigit(*p)) return 0; | ||
119 | do { | ||
120 | n = n*10 + (*p - '0'); | ||
121 | p++; | ||
122 | } while (lj_char_isdigit(*p)); | ||
123 | } | ||
124 | for (;;) { /* Parse suffixes. */ | ||
125 | if ((*p & ~0x20) == 'U') | ||
126 | id = CTID_UINT64; | ||
127 | else if ((*p & ~0x20) == 'L') | ||
128 | numl++; | ||
129 | else | ||
130 | break; | ||
131 | p++; | ||
132 | } | ||
133 | if (numl != 2 || *p != '\0') return 0; | ||
134 | /* Return cdata holding a 64 bit integer. */ | ||
135 | cd = lj_cdata_new_(ls->L, id, 8); | ||
136 | *(uint64_t *)cdataptr(cd) = n; | ||
137 | lj_parse_keepcdata(ls, tv, cd); | ||
138 | return 1; /* Ok. */ | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | /* Parse a number literal. */ | ||
143 | static void lex_number(LexState *ls, TValue *tv) | ||
81 | { | 144 | { |
82 | int c; | 145 | int c; |
83 | lua_assert(lj_char_isdigit(ls->current)); | 146 | lua_assert(lj_char_isdigit(ls->current)); |
@@ -87,9 +150,31 @@ static void read_numeral(LexState *ls, TValue *tv) | |||
87 | } while (lj_char_isident(ls->current) || ls->current == '.' || | 150 | } while (lj_char_isident(ls->current) || ls->current == '.' || |
88 | ((ls->current == '-' || ls->current == '+') && | 151 | ((ls->current == '-' || ls->current == '+') && |
89 | ((c & ~0x20) == 'E' || (c & ~0x20) == 'P'))); | 152 | ((c & ~0x20) == 'E' || (c & ~0x20) == 'P'))); |
153 | #if LJ_HASFFI | ||
154 | c &= ~0x20; | ||
155 | if ((c == 'I' || c == 'L' || c == 'U') && !ctype_ctsG(G(ls->L))) | ||
156 | lex_loadffi(ls->L); | ||
157 | if (c == 'I') /* Parse imaginary part of complex number. */ | ||
158 | ls->sb.n--; | ||
159 | #endif | ||
90 | save(ls, '\0'); | 160 | save(ls, '\0'); |
91 | if (!lj_str_numconv(ls->sb.buf, tv)) | 161 | #if LJ_HASFFI |
92 | lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); | 162 | if ((c == 'L' || c == 'U') && lex_number64(ls, tv)) { /* Parse 64 bit int. */ |
163 | return; | ||
164 | } else | ||
165 | #endif | ||
166 | if (lj_str_numconv(ls->sb.buf, tv)) { | ||
167 | #if LJ_HASFFI | ||
168 | if (c == 'I') { /* Return cdata holding a complex number. */ | ||
169 | GCcdata *cd = lj_cdata_new_(ls->L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); | ||
170 | ((double *)cdataptr(cd))[0] = 0; | ||
171 | ((double *)cdataptr(cd))[1] = tv->n; | ||
172 | lj_parse_keepcdata(ls, tv, cd); | ||
173 | } | ||
174 | #endif | ||
175 | return; | ||
176 | } | ||
177 | lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); | ||
93 | } | 178 | } |
94 | 179 | ||
95 | static int skip_sep(LexState *ls) | 180 | static int skip_sep(LexState *ls) |
@@ -224,7 +309,7 @@ static int llex(LexState *ls, TValue *tv) | |||
224 | if (lj_char_isident(ls->current)) { | 309 | if (lj_char_isident(ls->current)) { |
225 | GCstr *s; | 310 | GCstr *s; |
226 | if (lj_char_isdigit(ls->current)) { /* Numeric literal. */ | 311 | if (lj_char_isdigit(ls->current)) { /* Numeric literal. */ |
227 | read_numeral(ls, tv); | 312 | lex_number(ls, tv); |
228 | return TK_number; | 313 | return TK_number; |
229 | } | 314 | } |
230 | /* Identifier or reserved word. */ | 315 | /* Identifier or reserved word. */ |
@@ -306,7 +391,7 @@ static int llex(LexState *ls, TValue *tv) | |||
306 | } else if (!lj_char_isdigit(ls->current)) { | 391 | } else if (!lj_char_isdigit(ls->current)) { |
307 | return '.'; | 392 | return '.'; |
308 | } else { | 393 | } else { |
309 | read_numeral(ls, tv); | 394 | lex_number(ls, tv); |
310 | return TK_number; | 395 | return TK_number; |
311 | } | 396 | } |
312 | case END_OF_STREAM: | 397 | case END_OF_STREAM: |