xref: /freebsd/sys/contrib/openzfs/module/lua/llex.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1*61145dc2SMartin Matuska // SPDX-License-Identifier: MIT
2eda14cbcSMatt Macy /*
3eda14cbcSMatt Macy ** $Id: llex.c,v 2.63.1.3 2015/02/09 17:56:34 roberto Exp $
4eda14cbcSMatt Macy ** Lexical Analyzer
5eda14cbcSMatt Macy ** See Copyright Notice in lua.h
6eda14cbcSMatt Macy */
7eda14cbcSMatt Macy 
8eda14cbcSMatt Macy #define llex_c
9eda14cbcSMatt Macy #define LUA_CORE
10eda14cbcSMatt Macy 
11eda14cbcSMatt Macy #include <sys/lua/lua.h>
12eda14cbcSMatt Macy 
13eda14cbcSMatt Macy #include "lctype.h"
14eda14cbcSMatt Macy #include "ldo.h"
15eda14cbcSMatt Macy #include "llex.h"
16eda14cbcSMatt Macy #include "lobject.h"
17eda14cbcSMatt Macy #include "lparser.h"
18eda14cbcSMatt Macy #include "lstate.h"
19eda14cbcSMatt Macy #include "lstring.h"
20eda14cbcSMatt Macy #include "ltable.h"
21eda14cbcSMatt Macy #include "lzio.h"
22eda14cbcSMatt Macy 
23eda14cbcSMatt Macy 
24eda14cbcSMatt Macy 
25eda14cbcSMatt Macy #define next(ls) (ls->current = zgetc(ls->z))
26eda14cbcSMatt Macy 
27eda14cbcSMatt Macy 
28eda14cbcSMatt Macy 
29eda14cbcSMatt Macy #define currIsNewline(ls)	(ls->current == '\n' || ls->current == '\r')
30eda14cbcSMatt Macy 
31eda14cbcSMatt Macy 
32eda14cbcSMatt Macy /* ORDER RESERVED */
33eda14cbcSMatt Macy static const char *const luaX_tokens [] = {
34eda14cbcSMatt Macy     "and", "break", "do", "else", "elseif",
35eda14cbcSMatt Macy     "end", "false", "for", "function", "goto", "if",
36eda14cbcSMatt Macy     "in", "local", "nil", "not", "or", "repeat",
37eda14cbcSMatt Macy     "return", "then", "true", "until", "while",
38eda14cbcSMatt Macy     "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
39eda14cbcSMatt Macy     "<number>", "<name>", "<string>"
40eda14cbcSMatt Macy };
41eda14cbcSMatt Macy 
42eda14cbcSMatt Macy 
43eda14cbcSMatt Macy #define save_and_next(ls) (save(ls, ls->current), next(ls))
44eda14cbcSMatt Macy 
45eda14cbcSMatt Macy 
46eda14cbcSMatt Macy static l_noret lexerror (LexState *ls, const char *msg, int token);
47eda14cbcSMatt Macy 
48eda14cbcSMatt Macy 
save(LexState * ls,int c)49eda14cbcSMatt Macy static void save (LexState *ls, int c) {
50eda14cbcSMatt Macy   Mbuffer *b = ls->buff;
51eda14cbcSMatt Macy   if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
52eda14cbcSMatt Macy     size_t newsize;
53eda14cbcSMatt Macy     if (luaZ_sizebuffer(b) >= MAX_SIZET/2)
54eda14cbcSMatt Macy       lexerror(ls, "lexical element too long", 0);
55eda14cbcSMatt Macy     newsize = luaZ_sizebuffer(b) * 2;
56eda14cbcSMatt Macy     luaZ_resizebuffer(ls->L, b, newsize);
57eda14cbcSMatt Macy   }
58eda14cbcSMatt Macy   b->buffer[luaZ_bufflen(b)++] = cast(char, c);
59eda14cbcSMatt Macy }
60eda14cbcSMatt Macy 
61eda14cbcSMatt Macy 
luaX_init(lua_State * L)62eda14cbcSMatt Macy void luaX_init (lua_State *L) {
63eda14cbcSMatt Macy   int i;
64eda14cbcSMatt Macy   for (i=0; i<NUM_RESERVED; i++) {
65eda14cbcSMatt Macy     TString *ts = luaS_new(L, luaX_tokens[i]);
66eda14cbcSMatt Macy     luaS_fix(ts);  /* reserved words are never collected */
67eda14cbcSMatt Macy     ts->tsv.extra = cast_byte(i+1);  /* reserved word */
68eda14cbcSMatt Macy   }
69eda14cbcSMatt Macy }
70eda14cbcSMatt Macy 
71eda14cbcSMatt Macy 
luaX_token2str(LexState * ls,int token)72eda14cbcSMatt Macy const char *luaX_token2str (LexState *ls, int token) {
73eda14cbcSMatt Macy   if (token < FIRST_RESERVED) {  /* single-byte symbols? */
74eda14cbcSMatt Macy     lua_assert(token == cast(unsigned char, token));
75eda14cbcSMatt Macy     return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) :
76eda14cbcSMatt Macy                               luaO_pushfstring(ls->L, "char(%d)", token);
77eda14cbcSMatt Macy   }
78eda14cbcSMatt Macy   else {
79eda14cbcSMatt Macy     const char *s = luaX_tokens[token - FIRST_RESERVED];
80eda14cbcSMatt Macy     if (token < TK_EOS)  /* fixed format (symbols and reserved words)? */
81eda14cbcSMatt Macy       return luaO_pushfstring(ls->L, LUA_QS, s);
82eda14cbcSMatt Macy     else  /* names, strings, and numerals */
83eda14cbcSMatt Macy       return s;
84eda14cbcSMatt Macy   }
85eda14cbcSMatt Macy }
86eda14cbcSMatt Macy 
87eda14cbcSMatt Macy 
txtToken(LexState * ls,int token)88eda14cbcSMatt Macy static const char *txtToken (LexState *ls, int token) {
89eda14cbcSMatt Macy   switch (token) {
90eda14cbcSMatt Macy     case TK_NAME:
91eda14cbcSMatt Macy     case TK_STRING:
92eda14cbcSMatt Macy     case TK_NUMBER:
93eda14cbcSMatt Macy       save(ls, '\0');
94eda14cbcSMatt Macy       return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff));
95eda14cbcSMatt Macy     default:
96eda14cbcSMatt Macy       return luaX_token2str(ls, token);
97eda14cbcSMatt Macy   }
98eda14cbcSMatt Macy }
99eda14cbcSMatt Macy 
100eda14cbcSMatt Macy 
lexerror(LexState * ls,const char * msg,int token)101eda14cbcSMatt Macy static l_noret lexerror (LexState *ls, const char *msg, int token) {
102eda14cbcSMatt Macy   char buff[LUA_IDSIZE];
103eda14cbcSMatt Macy   luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE);
104eda14cbcSMatt Macy   msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
105eda14cbcSMatt Macy   if (token)
106eda14cbcSMatt Macy     luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
107eda14cbcSMatt Macy   luaD_throw(ls->L, LUA_ERRSYNTAX);
108eda14cbcSMatt Macy }
109eda14cbcSMatt Macy 
110eda14cbcSMatt Macy 
luaX_syntaxerror(LexState * ls,const char * msg)111eda14cbcSMatt Macy l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
112eda14cbcSMatt Macy   lexerror(ls, msg, ls->t.token);
113eda14cbcSMatt Macy }
114eda14cbcSMatt Macy 
115eda14cbcSMatt Macy 
116eda14cbcSMatt Macy /*
117eda14cbcSMatt Macy ** creates a new string and anchors it in function's table so that
118eda14cbcSMatt Macy ** it will not be collected until the end of the function's compilation
119eda14cbcSMatt Macy ** (by that time it should be anchored in function's prototype)
120eda14cbcSMatt Macy */
luaX_newstring(LexState * ls,const char * str,size_t l)121eda14cbcSMatt Macy TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
122eda14cbcSMatt Macy   lua_State *L = ls->L;
123eda14cbcSMatt Macy   TValue *o;  /* entry for `str' */
124eda14cbcSMatt Macy   TString *ts = luaS_newlstr(L, str, l);  /* create new string */
125eda14cbcSMatt Macy   setsvalue2s(L, L->top++, ts);  /* temporarily anchor it in stack */
126eda14cbcSMatt Macy   o = luaH_set(L, ls->fs->h, L->top - 1);
127eda14cbcSMatt Macy   if (ttisnil(o)) {  /* not in use yet? (see 'addK') */
128eda14cbcSMatt Macy     /* boolean value does not need GC barrier;
129eda14cbcSMatt Macy        table has no metatable, so it does not need to invalidate cache */
130eda14cbcSMatt Macy     setbvalue(o, 1);  /* t[string] = true */
131eda14cbcSMatt Macy     luaC_checkGC(L);
132eda14cbcSMatt Macy   }
133eda14cbcSMatt Macy   else {  /* string already present */
134eda14cbcSMatt Macy     ts = rawtsvalue(keyfromval(o));  /* re-use value previously stored */
135eda14cbcSMatt Macy   }
136eda14cbcSMatt Macy   L->top--;  /* remove string from stack */
137eda14cbcSMatt Macy   return ts;
138eda14cbcSMatt Macy }
139eda14cbcSMatt Macy 
140eda14cbcSMatt Macy 
141eda14cbcSMatt Macy /*
142eda14cbcSMatt Macy ** increment line number and skips newline sequence (any of
143eda14cbcSMatt Macy ** \n, \r, \n\r, or \r\n)
144eda14cbcSMatt Macy */
inclinenumber(LexState * ls)145eda14cbcSMatt Macy static void inclinenumber (LexState *ls) {
146eda14cbcSMatt Macy   int old = ls->current;
147eda14cbcSMatt Macy   lua_assert(currIsNewline(ls));
148eda14cbcSMatt Macy   next(ls);  /* skip `\n' or `\r' */
149eda14cbcSMatt Macy   if (currIsNewline(ls) && ls->current != old)
150eda14cbcSMatt Macy     next(ls);  /* skip `\n\r' or `\r\n' */
151eda14cbcSMatt Macy   if (++ls->linenumber >= MAX_INT)
152eda14cbcSMatt Macy     lexerror(ls, "chunk has too many lines", 0);
153eda14cbcSMatt Macy }
154eda14cbcSMatt Macy 
155eda14cbcSMatt Macy 
luaX_setinput(lua_State * L,LexState * ls,ZIO * z,TString * source,int firstchar)156eda14cbcSMatt Macy void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
157eda14cbcSMatt Macy                     int firstchar) {
158eda14cbcSMatt Macy   ls->decpoint = '.';
159eda14cbcSMatt Macy   ls->L = L;
160eda14cbcSMatt Macy   ls->current = firstchar;
161eda14cbcSMatt Macy   ls->lookahead.token = TK_EOS;  /* no look-ahead token */
162eda14cbcSMatt Macy   ls->z = z;
163eda14cbcSMatt Macy   ls->fs = NULL;
164eda14cbcSMatt Macy   ls->linenumber = 1;
165eda14cbcSMatt Macy   ls->lastline = 1;
166eda14cbcSMatt Macy   ls->source = source;
167eda14cbcSMatt Macy   ls->envn = luaS_new(L, LUA_ENV);  /* create env name */
168eda14cbcSMatt Macy   luaS_fix(ls->envn);  /* never collect this name */
169eda14cbcSMatt Macy   luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */
170eda14cbcSMatt Macy }
171eda14cbcSMatt Macy 
172eda14cbcSMatt Macy 
173eda14cbcSMatt Macy 
174eda14cbcSMatt Macy /*
175eda14cbcSMatt Macy ** =======================================================
176eda14cbcSMatt Macy ** LEXICAL ANALYZER
177eda14cbcSMatt Macy ** =======================================================
178eda14cbcSMatt Macy */
179eda14cbcSMatt Macy 
180eda14cbcSMatt Macy 
181eda14cbcSMatt Macy 
check_next(LexState * ls,const char * set)182eda14cbcSMatt Macy static int check_next (LexState *ls, const char *set) {
183eda14cbcSMatt Macy   if (ls->current == '\0' || !strchr(set, ls->current))
184eda14cbcSMatt Macy     return 0;
185eda14cbcSMatt Macy   save_and_next(ls);
186eda14cbcSMatt Macy   return 1;
187eda14cbcSMatt Macy }
188eda14cbcSMatt Macy 
189eda14cbcSMatt Macy 
190eda14cbcSMatt Macy /*
191eda14cbcSMatt Macy ** change all characters 'from' in buffer to 'to'
192eda14cbcSMatt Macy */
buffreplace(LexState * ls,char from,char to)193eda14cbcSMatt Macy static void buffreplace (LexState *ls, char from, char to) {
194eda14cbcSMatt Macy   size_t n = luaZ_bufflen(ls->buff);
195eda14cbcSMatt Macy   char *p = luaZ_buffer(ls->buff);
196eda14cbcSMatt Macy   while (n--)
197eda14cbcSMatt Macy     if (p[n] == from) p[n] = to;
198eda14cbcSMatt Macy }
199eda14cbcSMatt Macy 
200eda14cbcSMatt Macy 
201eda14cbcSMatt Macy #if !defined(getlocaledecpoint)
202eda14cbcSMatt Macy #define getlocaledecpoint()	(localeconv()->decimal_point[0])
203eda14cbcSMatt Macy #endif
204eda14cbcSMatt Macy 
205eda14cbcSMatt Macy 
206eda14cbcSMatt Macy #define buff2d(b,e)	luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e)
207eda14cbcSMatt Macy 
208eda14cbcSMatt Macy /*
209eda14cbcSMatt Macy ** in case of format error, try to change decimal point separator to
210eda14cbcSMatt Macy ** the one defined in the current locale and check again
211eda14cbcSMatt Macy */
trydecpoint(LexState * ls,SemInfo * seminfo)212eda14cbcSMatt Macy static void trydecpoint (LexState *ls, SemInfo *seminfo) {
213eda14cbcSMatt Macy   char old = ls->decpoint;
214eda14cbcSMatt Macy   ls->decpoint = getlocaledecpoint();
215eda14cbcSMatt Macy   buffreplace(ls, old, ls->decpoint);  /* try new decimal separator */
216eda14cbcSMatt Macy   if (!buff2d(ls->buff, &seminfo->r)) {
217eda14cbcSMatt Macy     /* format error with correct decimal point: no more options */
218eda14cbcSMatt Macy     buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
219eda14cbcSMatt Macy     lexerror(ls, "malformed number", TK_NUMBER);
220eda14cbcSMatt Macy   }
221eda14cbcSMatt Macy }
222eda14cbcSMatt Macy 
223eda14cbcSMatt Macy 
224eda14cbcSMatt Macy /* LUA_NUMBER */
225eda14cbcSMatt Macy /*
226eda14cbcSMatt Macy ** this function is quite liberal in what it accepts, as 'luaO_str2d'
227eda14cbcSMatt Macy ** will reject ill-formed numerals.
228eda14cbcSMatt Macy */
read_numeral(LexState * ls,SemInfo * seminfo)229eda14cbcSMatt Macy static void read_numeral (LexState *ls, SemInfo *seminfo) {
230eda14cbcSMatt Macy   const char *expo = "Ee";
231eda14cbcSMatt Macy   int first = ls->current;
232eda14cbcSMatt Macy   lua_assert(lisdigit(ls->current));
233eda14cbcSMatt Macy   save_and_next(ls);
234eda14cbcSMatt Macy   if (first == '0' && check_next(ls, "Xx"))  /* hexadecimal? */
235eda14cbcSMatt Macy     expo = "Pp";
236eda14cbcSMatt Macy   for (;;) {
237eda14cbcSMatt Macy     if (check_next(ls, expo))  /* exponent part? */
238eda14cbcSMatt Macy       (void) check_next(ls, "+-");  /* optional exponent sign */
239eda14cbcSMatt Macy     if (lisxdigit(ls->current) || ls->current == '.')
240eda14cbcSMatt Macy       save_and_next(ls);
241eda14cbcSMatt Macy     else  break;
242eda14cbcSMatt Macy   }
243eda14cbcSMatt Macy   save(ls, '\0');
244eda14cbcSMatt Macy   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
245eda14cbcSMatt Macy   if (!buff2d(ls->buff, &seminfo->r))  /* format error? */
246eda14cbcSMatt Macy     trydecpoint(ls, seminfo); /* try to update decimal point separator */
247eda14cbcSMatt Macy }
248eda14cbcSMatt Macy 
249eda14cbcSMatt Macy 
250eda14cbcSMatt Macy /*
251eda14cbcSMatt Macy ** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
252eda14cbcSMatt Macy ** -1 if sequence is malformed
253eda14cbcSMatt Macy */
skip_sep(LexState * ls)254eda14cbcSMatt Macy static int skip_sep (LexState *ls) {
255eda14cbcSMatt Macy   int count = 0;
256eda14cbcSMatt Macy   int s = ls->current;
257eda14cbcSMatt Macy   lua_assert(s == '[' || s == ']');
258eda14cbcSMatt Macy   save_and_next(ls);
259eda14cbcSMatt Macy   while (ls->current == '=') {
260eda14cbcSMatt Macy     save_and_next(ls);
261eda14cbcSMatt Macy     count++;
262eda14cbcSMatt Macy   }
263eda14cbcSMatt Macy   return (ls->current == s) ? count : (-count) - 1;
264eda14cbcSMatt Macy }
265eda14cbcSMatt Macy 
266eda14cbcSMatt Macy 
read_long_string(LexState * ls,SemInfo * seminfo,int sep)267eda14cbcSMatt Macy static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
268eda14cbcSMatt Macy   save_and_next(ls);  /* skip 2nd `[' */
269eda14cbcSMatt Macy   if (currIsNewline(ls))  /* string starts with a newline? */
270eda14cbcSMatt Macy     inclinenumber(ls);  /* skip it */
271eda14cbcSMatt Macy   for (;;) {
272eda14cbcSMatt Macy     switch (ls->current) {
273eda14cbcSMatt Macy       case EOZ:
274eda14cbcSMatt Macy         lexerror(ls, (seminfo) ? "unfinished long string" :
275eda14cbcSMatt Macy                                  "unfinished long comment", TK_EOS);
276eda14cbcSMatt Macy         break;  /* to avoid warnings */
277eda14cbcSMatt Macy       case ']': {
278eda14cbcSMatt Macy         if (skip_sep(ls) == sep) {
279eda14cbcSMatt Macy           save_and_next(ls);  /* skip 2nd `]' */
280eda14cbcSMatt Macy           goto endloop;
281eda14cbcSMatt Macy         }
282eda14cbcSMatt Macy         break;
283eda14cbcSMatt Macy       }
284eda14cbcSMatt Macy       case '\n': case '\r': {
285eda14cbcSMatt Macy         save(ls, '\n');
286eda14cbcSMatt Macy         inclinenumber(ls);
287eda14cbcSMatt Macy         if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */
288eda14cbcSMatt Macy         break;
289eda14cbcSMatt Macy       }
290eda14cbcSMatt Macy       default: {
291eda14cbcSMatt Macy         if (seminfo) save_and_next(ls);
292eda14cbcSMatt Macy         else next(ls);
293eda14cbcSMatt Macy       }
294eda14cbcSMatt Macy     }
295eda14cbcSMatt Macy   } endloop:
296eda14cbcSMatt Macy   if (seminfo)
297eda14cbcSMatt Macy     seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
298eda14cbcSMatt Macy                                      luaZ_bufflen(ls->buff) - 2*(2 + sep));
299eda14cbcSMatt Macy }
300eda14cbcSMatt Macy 
301eda14cbcSMatt Macy 
escerror(LexState * ls,int * c,int n,const char * msg)302eda14cbcSMatt Macy static void escerror (LexState *ls, int *c, int n, const char *msg) {
303eda14cbcSMatt Macy   int i;
304eda14cbcSMatt Macy   luaZ_resetbuffer(ls->buff);  /* prepare error message */
305eda14cbcSMatt Macy   save(ls, '\\');
306eda14cbcSMatt Macy   for (i = 0; i < n && c[i] != EOZ; i++)
307eda14cbcSMatt Macy     save(ls, c[i]);
308eda14cbcSMatt Macy   lexerror(ls, msg, TK_STRING);
309eda14cbcSMatt Macy }
310eda14cbcSMatt Macy 
311eda14cbcSMatt Macy 
readhexaesc(LexState * ls)312eda14cbcSMatt Macy static int readhexaesc (LexState *ls) {
313eda14cbcSMatt Macy   int c[3], i;  /* keep input for error message */
314eda14cbcSMatt Macy   int r = 0;  /* result accumulator */
315eda14cbcSMatt Macy   c[0] = 'x';  /* for error message */
316eda14cbcSMatt Macy   for (i = 1; i < 3; i++) {  /* read two hexadecimal digits */
317eda14cbcSMatt Macy     c[i] = next(ls);
318eda14cbcSMatt Macy     if (!lisxdigit(c[i]))
319eda14cbcSMatt Macy       escerror(ls, c, i + 1, "hexadecimal digit expected");
320eda14cbcSMatt Macy     r = (r << 4) + luaO_hexavalue(c[i]);
321eda14cbcSMatt Macy   }
322eda14cbcSMatt Macy   return r;
323eda14cbcSMatt Macy }
324eda14cbcSMatt Macy 
325eda14cbcSMatt Macy 
readdecesc(LexState * ls)326eda14cbcSMatt Macy static int readdecesc (LexState *ls) {
327eda14cbcSMatt Macy   int c[3], i;
328eda14cbcSMatt Macy   int r = 0;  /* result accumulator */
329eda14cbcSMatt Macy   for (i = 0; i < 3 && lisdigit(ls->current); i++) {  /* read up to 3 digits */
330eda14cbcSMatt Macy     c[i] = ls->current;
331eda14cbcSMatt Macy     r = 10*r + c[i] - '0';
332eda14cbcSMatt Macy     next(ls);
333eda14cbcSMatt Macy   }
334eda14cbcSMatt Macy   if (r > UCHAR_MAX)
335eda14cbcSMatt Macy     escerror(ls, c, i, "decimal escape too large");
336eda14cbcSMatt Macy   return r;
337eda14cbcSMatt Macy }
338eda14cbcSMatt Macy 
339eda14cbcSMatt Macy 
read_string(LexState * ls,int del,SemInfo * seminfo)340eda14cbcSMatt Macy static void read_string (LexState *ls, int del, SemInfo *seminfo) {
341eda14cbcSMatt Macy   save_and_next(ls);  /* keep delimiter (for error messages) */
342eda14cbcSMatt Macy   while (ls->current != del) {
343eda14cbcSMatt Macy     switch (ls->current) {
344eda14cbcSMatt Macy       case EOZ:
345eda14cbcSMatt Macy         lexerror(ls, "unfinished string", TK_EOS);
346eda14cbcSMatt Macy         break;  /* to avoid warnings */
347eda14cbcSMatt Macy       case '\n':
348eda14cbcSMatt Macy       case '\r':
349eda14cbcSMatt Macy         lexerror(ls, "unfinished string", TK_STRING);
350eda14cbcSMatt Macy         break;  /* to avoid warnings */
351eda14cbcSMatt Macy       case '\\': {  /* escape sequences */
352eda14cbcSMatt Macy         int c;  /* final character to be saved */
353eda14cbcSMatt Macy         next(ls);  /* do not save the `\' */
354eda14cbcSMatt Macy         switch (ls->current) {
355eda14cbcSMatt Macy           case 'a': c = '\a'; goto read_save;
356eda14cbcSMatt Macy           case 'b': c = '\b'; goto read_save;
357eda14cbcSMatt Macy           case 'f': c = '\f'; goto read_save;
358eda14cbcSMatt Macy           case 'n': c = '\n'; goto read_save;
359eda14cbcSMatt Macy           case 'r': c = '\r'; goto read_save;
360eda14cbcSMatt Macy           case 't': c = '\t'; goto read_save;
361eda14cbcSMatt Macy           case 'v': c = '\v'; goto read_save;
362eda14cbcSMatt Macy           case 'x': c = readhexaesc(ls); goto read_save;
363eda14cbcSMatt Macy           case '\n': case '\r':
364eda14cbcSMatt Macy             inclinenumber(ls); c = '\n'; goto only_save;
365eda14cbcSMatt Macy           case '\\': case '\"': case '\'':
366eda14cbcSMatt Macy             c = ls->current; goto read_save;
367eda14cbcSMatt Macy           case EOZ: goto no_save;  /* will raise an error next loop */
368eda14cbcSMatt Macy           case 'z': {  /* zap following span of spaces */
369eda14cbcSMatt Macy             next(ls);  /* skip the 'z' */
370eda14cbcSMatt Macy             while (lisspace(ls->current)) {
371eda14cbcSMatt Macy               if (currIsNewline(ls)) inclinenumber(ls);
372eda14cbcSMatt Macy               else next(ls);
373eda14cbcSMatt Macy             }
374eda14cbcSMatt Macy             goto no_save;
375eda14cbcSMatt Macy           }
376eda14cbcSMatt Macy           default: {
377eda14cbcSMatt Macy             if (!lisdigit(ls->current))
378eda14cbcSMatt Macy               escerror(ls, &ls->current, 1, "invalid escape sequence");
379eda14cbcSMatt Macy             /* digital escape \ddd */
380eda14cbcSMatt Macy             c = readdecesc(ls);
381eda14cbcSMatt Macy             goto only_save;
382eda14cbcSMatt Macy           }
383eda14cbcSMatt Macy         }
384eda14cbcSMatt Macy        read_save: next(ls);  /* read next character */
385eda14cbcSMatt Macy        only_save: save(ls, c);  /* save 'c' */
386eda14cbcSMatt Macy        no_save: break;
387eda14cbcSMatt Macy       }
388eda14cbcSMatt Macy       default:
389eda14cbcSMatt Macy         save_and_next(ls);
390eda14cbcSMatt Macy     }
391eda14cbcSMatt Macy   }
392eda14cbcSMatt Macy   save_and_next(ls);  /* skip delimiter */
393eda14cbcSMatt Macy   seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
394eda14cbcSMatt Macy                                    luaZ_bufflen(ls->buff) - 2);
395eda14cbcSMatt Macy }
396eda14cbcSMatt Macy 
397eda14cbcSMatt Macy 
llex(LexState * ls,SemInfo * seminfo)398eda14cbcSMatt Macy static int llex (LexState *ls, SemInfo *seminfo) {
399eda14cbcSMatt Macy   luaZ_resetbuffer(ls->buff);
400eda14cbcSMatt Macy   for (;;) {
401eda14cbcSMatt Macy     switch (ls->current) {
402eda14cbcSMatt Macy       case '\n': case '\r': {  /* line breaks */
403eda14cbcSMatt Macy         inclinenumber(ls);
404eda14cbcSMatt Macy         break;
405eda14cbcSMatt Macy       }
406eda14cbcSMatt Macy       case ' ': case '\f': case '\t': case '\v': {  /* spaces */
407eda14cbcSMatt Macy         next(ls);
408eda14cbcSMatt Macy         break;
409eda14cbcSMatt Macy       }
410eda14cbcSMatt Macy       case '-': {  /* '-' or '--' (comment) */
411eda14cbcSMatt Macy         next(ls);
412eda14cbcSMatt Macy         if (ls->current != '-') return '-';
413eda14cbcSMatt Macy         /* else is a comment */
414eda14cbcSMatt Macy         next(ls);
415eda14cbcSMatt Macy         if (ls->current == '[') {  /* long comment? */
416eda14cbcSMatt Macy           int sep = skip_sep(ls);
417eda14cbcSMatt Macy           luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */
418eda14cbcSMatt Macy           if (sep >= 0) {
419eda14cbcSMatt Macy             read_long_string(ls, NULL, sep);  /* skip long comment */
420eda14cbcSMatt Macy             luaZ_resetbuffer(ls->buff);  /* previous call may dirty the buff. */
421eda14cbcSMatt Macy             break;
422eda14cbcSMatt Macy           }
423eda14cbcSMatt Macy         }
424eda14cbcSMatt Macy         /* else short comment */
425eda14cbcSMatt Macy         while (!currIsNewline(ls) && ls->current != EOZ)
426eda14cbcSMatt Macy           next(ls);  /* skip until end of line (or end of file) */
427eda14cbcSMatt Macy         break;
428eda14cbcSMatt Macy       }
429eda14cbcSMatt Macy       case '[': {  /* long string or simply '[' */
430eda14cbcSMatt Macy         int sep = skip_sep(ls);
431eda14cbcSMatt Macy         if (sep >= 0) {
432eda14cbcSMatt Macy           read_long_string(ls, seminfo, sep);
433eda14cbcSMatt Macy           return TK_STRING;
434eda14cbcSMatt Macy         } else if (sep == -1) {
435eda14cbcSMatt Macy 		return '[';
436eda14cbcSMatt Macy         } else {
437eda14cbcSMatt Macy 		lexerror(ls, "invalid long string delimiter", TK_STRING);
438eda14cbcSMatt Macy 		break;
439eda14cbcSMatt Macy 	}
440eda14cbcSMatt Macy       }
441eda14cbcSMatt Macy       case '=': {
442eda14cbcSMatt Macy         next(ls);
443eda14cbcSMatt Macy         if (ls->current != '=') return '=';
444eda14cbcSMatt Macy         else { next(ls); return TK_EQ; }
445eda14cbcSMatt Macy       }
446eda14cbcSMatt Macy       case '<': {
447eda14cbcSMatt Macy         next(ls);
448eda14cbcSMatt Macy         if (ls->current != '=') return '<';
449eda14cbcSMatt Macy         else { next(ls); return TK_LE; }
450eda14cbcSMatt Macy       }
451eda14cbcSMatt Macy       case '>': {
452eda14cbcSMatt Macy         next(ls);
453eda14cbcSMatt Macy         if (ls->current != '=') return '>';
454eda14cbcSMatt Macy         else { next(ls); return TK_GE; }
455eda14cbcSMatt Macy       }
456eda14cbcSMatt Macy       case '~': {
457eda14cbcSMatt Macy         next(ls);
458eda14cbcSMatt Macy         if (ls->current != '=') return '~';
459eda14cbcSMatt Macy         else { next(ls); return TK_NE; }
460eda14cbcSMatt Macy       }
461eda14cbcSMatt Macy       case ':': {
462eda14cbcSMatt Macy         next(ls);
463eda14cbcSMatt Macy         if (ls->current != ':') return ':';
464eda14cbcSMatt Macy         else { next(ls); return TK_DBCOLON; }
465eda14cbcSMatt Macy       }
466eda14cbcSMatt Macy       case '"': case '\'': {  /* short literal strings */
467eda14cbcSMatt Macy         read_string(ls, ls->current, seminfo);
468eda14cbcSMatt Macy         return TK_STRING;
469eda14cbcSMatt Macy       }
470eda14cbcSMatt Macy       case '.': {  /* '.', '..', '...', or number */
471eda14cbcSMatt Macy         save_and_next(ls);
472eda14cbcSMatt Macy         if (check_next(ls, ".")) {
473eda14cbcSMatt Macy           if (check_next(ls, "."))
474eda14cbcSMatt Macy             return TK_DOTS;   /* '...' */
475eda14cbcSMatt Macy           else return TK_CONCAT;   /* '..' */
476eda14cbcSMatt Macy         }
477eda14cbcSMatt Macy         else if (!lisdigit(ls->current)) return '.';
478eda14cbcSMatt Macy         /* else go through */
479eda14cbcSMatt Macy       }
480c03c5b1cSMartin Matuska         zfs_fallthrough;
481eda14cbcSMatt Macy       case '0': case '1': case '2': case '3': case '4':
482eda14cbcSMatt Macy       case '5': case '6': case '7': case '8': case '9': {
483eda14cbcSMatt Macy         read_numeral(ls, seminfo);
484eda14cbcSMatt Macy         return TK_NUMBER;
485eda14cbcSMatt Macy       }
486eda14cbcSMatt Macy       case EOZ: {
487eda14cbcSMatt Macy         return TK_EOS;
488eda14cbcSMatt Macy       }
489eda14cbcSMatt Macy       default: {
490eda14cbcSMatt Macy         if (lislalpha(ls->current)) {  /* identifier or reserved word? */
491eda14cbcSMatt Macy           TString *ts;
492eda14cbcSMatt Macy           do {
493eda14cbcSMatt Macy             save_and_next(ls);
494eda14cbcSMatt Macy           } while (lislalnum(ls->current));
495eda14cbcSMatt Macy           ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
496eda14cbcSMatt Macy                                   luaZ_bufflen(ls->buff));
497eda14cbcSMatt Macy           seminfo->ts = ts;
498eda14cbcSMatt Macy           if (isreserved(ts))  /* reserved word? */
499eda14cbcSMatt Macy             return ts->tsv.extra - 1 + FIRST_RESERVED;
500eda14cbcSMatt Macy           else {
501eda14cbcSMatt Macy             return TK_NAME;
502eda14cbcSMatt Macy           }
503eda14cbcSMatt Macy         }
504eda14cbcSMatt Macy         else {  /* single-char tokens (+ - / ...) */
505eda14cbcSMatt Macy           int c = ls->current;
506eda14cbcSMatt Macy           next(ls);
507eda14cbcSMatt Macy           return c;
508eda14cbcSMatt Macy         }
509eda14cbcSMatt Macy       }
510eda14cbcSMatt Macy     }
511eda14cbcSMatt Macy   }
512eda14cbcSMatt Macy }
513eda14cbcSMatt Macy 
514eda14cbcSMatt Macy 
luaX_next(LexState * ls)515eda14cbcSMatt Macy void luaX_next (LexState *ls) {
516eda14cbcSMatt Macy   ls->lastline = ls->linenumber;
517eda14cbcSMatt Macy   if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */
518eda14cbcSMatt Macy     ls->t = ls->lookahead;  /* use this one */
519eda14cbcSMatt Macy     ls->lookahead.token = TK_EOS;  /* and discharge it */
520eda14cbcSMatt Macy   }
521eda14cbcSMatt Macy   else
522eda14cbcSMatt Macy     ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */
523eda14cbcSMatt Macy }
524eda14cbcSMatt Macy 
525eda14cbcSMatt Macy 
luaX_lookahead(LexState * ls)526eda14cbcSMatt Macy int luaX_lookahead (LexState *ls) {
527eda14cbcSMatt Macy   lua_assert(ls->lookahead.token == TK_EOS);
528eda14cbcSMatt Macy   ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
529eda14cbcSMatt Macy   return ls->lookahead.token;
530eda14cbcSMatt Macy }
531