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