diff options
Diffstat (limited to 'src/lj_lex.c')
-rw-r--r-- | src/lj_lex.c | 110 |
1 files changed, 31 insertions, 79 deletions
diff --git a/src/lj_lex.c b/src/lj_lex.c index 669d2dfe..55e2bea1 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "lj_lex.h" | 23 | #include "lj_lex.h" |
24 | #include "lj_parse.h" | 24 | #include "lj_parse.h" |
25 | #include "lj_char.h" | 25 | #include "lj_char.h" |
26 | #include "lj_strscan.h" | ||
26 | 27 | ||
27 | /* Lua lexer token names. */ | 28 | /* Lua lexer token names. */ |
28 | static const char *const tokennames[] = { | 29 | static const char *const tokennames[] = { |
@@ -84,100 +85,51 @@ static void inclinenumber(LexState *ls) | |||
84 | 85 | ||
85 | /* -- Scanner for terminals ----------------------------------------------- */ | 86 | /* -- Scanner for terminals ----------------------------------------------- */ |
86 | 87 | ||
87 | #if LJ_HASFFI | ||
88 | /* Load FFI library on-demand. Needed if we create cdata objects. */ | ||
89 | static void lex_loadffi(lua_State *L) | ||
90 | { | ||
91 | ptrdiff_t oldtop = savestack(L, L->top); | ||
92 | luaopen_ffi(L); | ||
93 | L->top = restorestack(L, oldtop); | ||
94 | } | ||
95 | |||
96 | /* Parse 64 bit integer. */ | ||
97 | static int lex_number64(LexState *ls, TValue *tv) | ||
98 | { | ||
99 | uint64_t n = 0; | ||
100 | uint8_t *p = (uint8_t *)ls->sb.buf; | ||
101 | CTypeID id = CTID_INT64; | ||
102 | GCcdata *cd; | ||
103 | int numl = 0; | ||
104 | if (p[0] == '0' && (p[1] & ~0x20) == 'X') { /* Hexadecimal. */ | ||
105 | p += 2; | ||
106 | if (!lj_char_isxdigit(*p)) return 0; | ||
107 | do { | ||
108 | n = n*16 + (*p & 15); | ||
109 | if (!lj_char_isdigit(*p)) n += 9; | ||
110 | p++; | ||
111 | } while (lj_char_isxdigit(*p)); | ||
112 | } else { /* Decimal. */ | ||
113 | if (!lj_char_isdigit(*p)) return 0; | ||
114 | do { | ||
115 | n = n*10 + (*p - '0'); | ||
116 | p++; | ||
117 | } while (lj_char_isdigit(*p)); | ||
118 | } | ||
119 | for (;;) { /* Parse suffixes. */ | ||
120 | if ((*p & ~0x20) == 'U') | ||
121 | id = CTID_UINT64; | ||
122 | else if ((*p & ~0x20) == 'L') | ||
123 | numl++; | ||
124 | else | ||
125 | break; | ||
126 | p++; | ||
127 | } | ||
128 | if (numl != 2 || *p != '\0') return 0; | ||
129 | /* Return cdata holding a 64 bit integer. */ | ||
130 | cd = lj_cdata_new_(ls->L, id, 8); | ||
131 | *(uint64_t *)cdataptr(cd) = n; | ||
132 | lj_parse_keepcdata(ls, tv, cd); | ||
133 | return 1; /* Ok. */ | ||
134 | } | ||
135 | #endif | ||
136 | |||
137 | /* Parse a number literal. */ | 88 | /* Parse a number literal. */ |
138 | static void lex_number(LexState *ls, TValue *tv) | 89 | static void lex_number(LexState *ls, TValue *tv) |
139 | { | 90 | { |
140 | int c, xp = 'E'; | 91 | StrScanFmt fmt; |
92 | int c, xp = 'e'; | ||
141 | lua_assert(lj_char_isdigit(ls->current)); | 93 | lua_assert(lj_char_isdigit(ls->current)); |
142 | if ((c = ls->current) == '0') { | 94 | if ((c = ls->current) == '0') { |
143 | save_and_next(ls); | 95 | save_and_next(ls); |
144 | if ((ls->current & ~0x20) == 'X') xp = 'P'; | 96 | if ((ls->current | 0x20) == 'x') xp = 'p'; |
145 | } | 97 | } |
146 | while (lj_char_isident(ls->current) || ls->current == '.' || | 98 | while (lj_char_isident(ls->current) || ls->current == '.' || |
147 | ((ls->current == '-' || ls->current == '+') && (c & ~0x20) == xp)) { | 99 | ((ls->current == '-' || ls->current == '+') && (c | 0x20) == xp)) { |
148 | c = ls->current; | 100 | c = ls->current; |
149 | save_and_next(ls); | 101 | save_and_next(ls); |
150 | } | 102 | } |
151 | #if LJ_HASFFI | ||
152 | c &= ~0x20; | ||
153 | if ((c == 'I' || c == 'L' || c == 'U') && !ctype_ctsG(G(ls->L))) | ||
154 | lex_loadffi(ls->L); | ||
155 | if (c == 'I') /* Parse imaginary part of complex number. */ | ||
156 | ls->sb.n--; | ||
157 | #endif | ||
158 | save(ls, '\0'); | 103 | save(ls, '\0'); |
159 | #if LJ_HASFFI | 104 | fmt = lj_strscan_scan((const uint8_t *)ls->sb.buf, tv, |
160 | if ((c == 'L' || c == 'U') && lex_number64(ls, tv)) { /* Parse 64 bit int. */ | 105 | (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) | |
161 | return; | 106 | (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0)); |
162 | } else | 107 | if (LJ_DUALNUM && fmt == STRSCAN_INT) { |
163 | #endif | 108 | setitype(tv, LJ_TISNUM); |
164 | if (lj_str_numconv(ls->sb.buf, tv)) { | 109 | } else if (fmt == STRSCAN_NUM) { |
165 | #if LJ_HASFFI | 110 | /* Already in correct format. */ |
166 | if (c == 'I') { /* Return cdata holding a complex number. */ | 111 | } else if (LJ_HASFFI && fmt != STRSCAN_ERROR) { |
167 | GCcdata *cd = lj_cdata_new_(ls->L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); | 112 | lua_State *L = ls->L; |
168 | ((double *)cdataptr(cd))[0] = 0; | 113 | GCcdata *cd; |
169 | ((double *)cdataptr(cd))[1] = numberVnum(tv); | 114 | lua_assert(fmt == STRSCAN_I64 || fmt == STRSCAN_U64 || fmt == STRSCAN_IMAG); |
170 | lj_parse_keepcdata(ls, tv, cd); | 115 | if (!ctype_ctsG(G(L))) { |
116 | ptrdiff_t oldtop = savestack(L, L->top); | ||
117 | luaopen_ffi(L); /* Load FFI library on-demand. */ | ||
118 | L->top = restorestack(L, oldtop); | ||
171 | } | 119 | } |
172 | #endif | 120 | if (fmt == STRSCAN_IMAG) { |
173 | if (LJ_DUALNUM && tvisnum(tv)) { | 121 | cd = lj_cdata_new_(L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); |
174 | int32_t k = lj_num2int(numV(tv)); | 122 | ((double *)cdataptr(cd))[0] = 0; |
175 | if ((lua_Number)k == numV(tv)) /* -0 cannot end up here. */ | 123 | ((double *)cdataptr(cd))[1] = numV(tv); |
176 | setintV(tv, k); | 124 | } else { |
125 | cd = lj_cdata_new_(L, fmt==STRSCAN_I64 ? CTID_INT64 : CTID_UINT64, 8); | ||
126 | *(uint64_t *)cdataptr(cd) = tv->u64; | ||
177 | } | 127 | } |
178 | return; | 128 | lj_parse_keepcdata(ls, tv, cd); |
129 | } else { | ||
130 | lua_assert(fmt == STRSCAN_ERROR); | ||
131 | lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); | ||
179 | } | 132 | } |
180 | lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); | ||
181 | } | 133 | } |
182 | 134 | ||
183 | static int skip_sep(LexState *ls) | 135 | static int skip_sep(LexState *ls) |