static void read_string (LexState *LS, int del, SemInfo *seminfo) { lua_State *L = LS->L; size_t l = 0; checkbuffer(L, 10, l); save_and_next(L, LS, l); while (LS->current != del) { checkbuffer(L, 10, l); switch (LS->current) { case EOZ: case '\n': case '\r': save(L, '\0', l); luaX_error(LS, "unfinished string", TK_STRING); break; /* to avoid warnings */ case '\\': next(LS); /* do not save the '\' */ switch (LS->current) { case 'a': save(L, '\a', l); next(LS); break; case 'b': save(L, '\b', l); next(LS); break; case 'f': save(L, '\f', l); next(LS); break; case 'n': save(L, '\n', l); next(LS); break; case 'r': save(L, '\r', l); next(LS); break; case 't': save(L, '\t', l); next(LS); break; case 'v': save(L, '\v', l); next(LS); break; case '\n': save(L, '\n', l); inclinenumber(LS); if (LS->current == '\r') next(LS); break; case '\r': save(L, '\n', l); inclinenumber(LS); if (LS->current == '\n') next(LS); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int c = 0; int i = 0; do { c = 10*c + (LS->current-'0'); next(LS); } while (++i<3 && isdigit(LS->current)); if (c != (unsigned char)c) { save(L, '\0', l); luaX_error(LS, "escape sequence too large", TK_STRING); } save(L, c, l); break; } default: /* handles \\, \", \', and \? */ save_and_next(L, LS, l); } break; default: save_and_next(L, LS, l); } } save_and_next(L, LS, l); /* skip delimiter */ save(L, '\0', l); seminfo->ts = luaS_newlstr(L, L->Mbuffer+1, l-3); }
/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { int n = 1; pushstr(L, ""); for (;;) { const char *e = strchr(fmt, '%'); if (e == NULL) break; setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); incr_top(L); switch (*(e+1)) { case 's': { const char *s = va_arg(argp, char *); if (s == NULL) s = "(null)"; pushstr(L, s); break; } case 'c': { char buff[2]; buff[0] = cast(char, va_arg(argp, int)); buff[1] = '\0'; pushstr(L, buff); break; } case 'd': { setnvalue(L->top, cast_num(va_arg(argp, int))); incr_top(L); break; } case 'f': { setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); incr_top(L); break; } case 'p': { char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ sprintf(buff, "%p", va_arg(argp, void *)); pushstr(L, buff); break; } case '%': { pushstr(L, "%"); break; } default: { char buff[3]; buff[0] = '%'; buff[1] = *(e+1); buff[2] = '\0'; pushstr(L, buff); break; } } n += 2; fmt = e+2; } pushstr(L, fmt); luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); L->top -= n; return svalue(L->top - 1); }
static TaggedString *strconc (TaggedString *l, TaggedString *r) { size_t nl = l->u.s.len; size_t nr = r->u.s.len; char *buffer = luaL_openspace(nl+nr+1); memcpy(buffer, l->str, nl); memcpy(buffer+nl, r->str, nr); return luaS_newlstr(buffer, nl+nr); }
static TString *corename(lua_State *L, const TString *filename) { const char *fn = getstr(filename)+1; const char *s = strrchr(fn, '/'); s = s ? s + 1 : fn; while (*s == '.') s++; const char *e = strchr(s, '.'); int l = e ? e - s: strlen(s); return l ? luaS_newlstr (L, s, l) : luaS_new(L, fn); }
LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); luaC_checkGC(L); ts = luaS_newlstr(L, s, len); setsvalue2s(L, L->top, ts); api_incr_top(L); lua_unlock(L); return getstr(ts); }
/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { int n = 0; for (;;) { const char *e = strchr(fmt, '%'); if (e == NULL) break; setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); incr_top(L); switch (*(e+1)) { case 's': { const char *s = va_arg(argp, char *); if (s == NULL) s = "(null)"; pushstr(L, s, strlen(s)); break; } case 'c': { char buff; buff = cast(char, va_arg(argp, int)); pushstr(L, &buff, 1); break; } case 'd': { setnvalue(L->top, cast_num(va_arg(argp, int))); incr_top(L); break; } case 'f': { // Floats passed through ... are promoted to doubles... setnvalue(L->top, cast_num(va_arg(argp, double))); incr_top(L); break; } case 'p': { char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ int l = sprintf(buff, "%p", va_arg(argp, void *)); pushstr(L, buff, l); break; } case '%': { pushstr(L, "%", 1); break; } default: { luaG_runerror(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), *(e + 1)); } } n += 2; fmt = e+2; } pushstr(L, fmt, strlen(fmt)); if (n > 0) luaV_concat(L, n + 1); return svalue(L->top - 1); }
static void read_string (LexState *LS, int del, SemInfo *seminfo) { size_t l = 0; checkbuffer(LS, l); save_and_next(LS, l); while (LS->current != del) { checkbuffer(LS, l); switch (LS->current) { case EOZ: save(LS, '\0', l); luaX_lexerror(LS, "unfinished string", TK_EOS); break; /* to avoid warnings */ case '\n': save(LS, '\0', l); luaX_lexerror(LS, "unfinished string", TK_STRING); break; /* to avoid warnings */ case '\\': next(LS); /* do not save the `\' */ switch (LS->current) { case 'a': save(LS, '\a', l); next(LS); break; case 'b': save(LS, '\b', l); next(LS); break; case 'f': save(LS, '\f', l); next(LS); break; case 'n': save(LS, '\n', l); next(LS); break; case 'r': save(LS, '\r', l); next(LS); break; case 't': save(LS, '\t', l); next(LS); break; case 'v': save(LS, '\v', l); next(LS); break; case '\n': save(LS, '\n', l); inclinenumber(LS); break; case EOZ: break; /* will raise an error next loop */ default: { if (!isdigit(LS->current)) save_and_next(LS, l); /* handles \\, \", \', and \? */ else { /* \xxx */ int c = 0; int i = 0; do { c = 10*c + (LS->current-'0'); next(LS); } while (++i<3 && isdigit(LS->current)); if (c > UCHAR_MAX) { save(LS, '\0', l); luaX_lexerror(LS, "escape sequence too large", TK_STRING); } save(LS, c, l); } } } break; default: save_and_next(LS, l); } } save_and_next(LS, l); /* skip delimiter */ save(LS, '\0', l); seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3); }
int luaV_tostring (lua_State *L, StkId obj) { if (!ttisnumber(obj)) return 0; else { char s[LUAI_MAXNUMBER2STR]; lua_Number n = nvalue(obj); int l = lua_number2str(s, n); setsvalue2s(L, obj, luaS_newlstr(L, s, l)); return 1; } }
static void read_long_string (LexState *LS, SemInfo *seminfo) { lua_State *L = LS->L; int cont = 0; size_t l = 0; checkbuffer(L, 10, l); save(L, '[', l); /* save first '[' */ save_and_next(L, LS, l); /* pass the second '[' */ for (;;) { checkbuffer(L, 10, l); switch (LS->current) { case EOZ: save(L, '\0', l); if (seminfo) luaX_error(LS, "unfinished long string", TK_STRING); else luaX_error(LS, "unfinished comment", TK_EOS); break; /* to avoid warnings */ case '[': save_and_next(L, LS, l); if (LS->current == '[') { cont++; save_and_next(L, LS, l); } continue; case ']': save_and_next(L, LS, l); if (LS->current == ']') { if (cont == 0) goto endloop; cont--; save_and_next(L, LS, l); } continue; case '\n': save(L, '\n', l); inclinenumber(LS); if (LS->current == '\r') next(LS); continue; case '\r': save(L, '\n', l); inclinenumber(LS); if (LS->current == '\n') next(LS); continue; default: if (seminfo) /* no need to save complete comment */ save(L, LS->current, l); next(LS); } } endloop: save_and_next(L, LS, l); /* skip the second ']' */ save(L, '\0', l); if (seminfo) seminfo->ts = luaS_newlstr(L, L->Mbuffer+2, l-5); }
static TString *LoadString (LoadState *S) { size_t size = LoadByte(S); if (size == 0xFF) LoadVar(S, size); if (size == 0) return NULL; else { char *s = luaZ_openspace(S->L, S->b, --size); LoadVector(S, s, size); return luaS_newlstr(S->L, s, size); } }
static TString* LoadString (LoadState* S) { size_t size=LoadSize(S); if (size==0) return NULL; else { char* s=luaZ_openspace(S->L,S->b,size); ezread(S,s,size); return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } }
static TString* LoadString (lua_State* L, ZIO* Z, int swap) { size_t size=LoadSize(L,Z,swap); if (size==0) return NULL; else { char* s=luaO_openspace(L,size); LoadBlock(L,s,size,Z,0); return luaS_newlstr(L,s,size-1); /* remove trailing '\0' */ } }
static TString* LoadString(LoadState* S) { size_t size; LoadVar(S,size); if (size==0) return NULL; else { char* s=luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size*sizeof(char)); return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } }
int luaK_numberK (FuncState *fs, lua_Number r) { int n; lua_State *L = fs->ls->L; TValue o; setnvalue(&o, r); if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ /* use raw representation as key to avoid numeric problems */ setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); n = addk(fs, L->top - 1, &o); L->top--; } else n = addk(fs, &o, &o); /* regular case */ return n; }
static Proto *makefakeproto(lua_State *L, lu_byte nups) { Proto *p = luaF_newproto(L); p->sizelineinfo = 1; p->lineinfo = luaM_newvector(L, 1, int); p->lineinfo[0] = 1; p->sizecode = 1; p->code = luaM_newvector(L, 1, Instruction); p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); p->source = luaS_newlstr(L, "", 0); p->maxstacksize = 2; p->nups = nups; p->sizek = 0; p->sizep = 0; return p; }
static TString* LoadString(LoadState* S) { size_t size = 0; if ( sizeof(size_t) <= SIZE_T_PRECOMPILED_CHUNK ) LoadVar(S,size); else LoadMem(S,&size,1,SIZE_T_PRECOMPILED_CHUNK); if (size==0) return NULL; else { char* s=luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size); return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } }
static TString *LoadString (LoadState *S) { size_t size = LoadByte(S); if (size == 0xFF) LoadVar(S, size); if (size == 0) return NULL; else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ char buff[LUAI_MAXSHORTLEN]; LoadVector(S, buff, size); return luaS_newlstr(S->L, buff, size); } else { /* long string */ TString *ts = luaS_createlngstrobj(S->L, size); LoadVector(S, getstr(ts), size); /* load directly in final place */ return ts; } }
static void read_long_string (LexState *LS, SemInfo *seminfo) { int cont = 0; size_t l = 0; checkbuffer(LS, l); save(LS, '[', l); /* save first `[' */ save_and_next(LS, l); /* pass the second `[' */ if (LS->current == '\n') /* string starts with a newline? */ inclinenumber(LS); /* skip it */ for (;;) { checkbuffer(LS, l); switch (LS->current) { case EOZ: save(LS, '\0', l); luaX_lexerror(LS, (seminfo) ? "unfinished long string" : "unfinished long comment", TK_EOS); break; /* to avoid warnings */ case '[': save_and_next(LS, l); if (LS->current == '[') { cont++; save_and_next(LS, l); } continue; case ']': save_and_next(LS, l); if (LS->current == ']') { if (cont == 0) goto endloop; cont--; save_and_next(LS, l); } continue; case '\n': save(LS, '\n', l); inclinenumber(LS); if (!seminfo) l = 0; /* reset buffer to avoid wasting space */ continue; default: save_and_next(LS, l); } } endloop: save_and_next(LS, l); /* skip the second `]' */ save(LS, '\0', l); if (seminfo) seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5); }
void luaV_concat (lua_State *L, int total, int last) { lu_mem max_sizet = MAX_SIZET; if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit; do { /* Any call which does a memory allocation may trim the stack, invalidating top unless the stack is fixed duri ng the allocation */ StkId top = L->base + last + 1; fixedstack(L); int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { unfixedstack(L); if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) { /* restore 'top' pointer, since stack might have been reallocted */ top = L->base + last + 1; luaG_concaterror(L, top-2, top-1); } } else if (tsvalue(top-1)->len == 0) { /* second op is empty? */ (void)tostring(L, top - 2); /* result is first op (as string) */ } else { /* at least two string values; get as many as possible */ size_t tl = tsvalue(top-1)->len; char *buffer; int i; /* collect total length */ for (n = 1; n < total && tostring(L, top-n-1); n++) { size_t l = tsvalue(top-n-1)->len; if (l >= max_sizet - tl) luaG_runerror(L, "string length overflow"); tl += l; } G(L)->buff.n = tl; buffer = luaZ_openspace(L, &G(L)->buff, tl); tl = 0; for (i=n; i>0; i--) { /* concat all strings */ size_t l = tsvalue(top-i)->len; c_memcpy(buffer+tl, svalue(top-i), l); tl += l; } setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); luaZ_resetbuffer(&G(L)->buff); } total -= n-1; /* got `n' strings to create 1 new */ last -= n-1; unfixedstack(L); } while (total > 1); /* repeat until only 1 result left */ }
/* ** creates a new string and anchors it in scanner's table so that ** it will not be collected until the end of the compilation ** (by that time it should be anchored somewhere) */ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { lua_State *L = ls->L; TValue *o; /* entry for 'str' */ TString *ts = luaS_newlstr(L, str, l); /* create new string */ setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ o = luaH_set(L, ls->h, L->top - 1); if (ttisnil(o)) { /* not in use yet? */ /* boolean value does not need GC barrier; table has no metatable, so it does not need to invalidate cache */ setbvalue(o, 1); /* t[string] = true */ luaC_checkGC(L); } else { /* string already present */ ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ } L->top--; /* remove string from stack */ return ts; }
int luaV_tostring (lua_State *L, StkId obj) { if (!ttisnumber(obj)) return 0; else { char buff[MAXNUMBER2STR]; size_t len; if (ttisinteger(obj)) len = lua_integer2str(buff, ivalue(obj)); else { len = lua_number2str(buff, fltvalue(obj)); if (strspn(buff, "-0123456789") == len) { /* look like an integer? */ buff[len++] = '.'; /* add a '.0' */ buff[len++] = '0'; buff[len] = '\0'; } } setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); return 1; } }
static TString* LoadString(LoadState* S) { int32_t size; LoadVar(S,size); if (size==0) return NULL; else { char* s; if (!luaZ_direct_mode(S->Z)) { s = luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size); return luaS_newlstr(S->L,s,size-1); /* remove trailing zero */ } else { s = (char*)luaZ_get_crt_address(S->Z); LoadBlock(S,NULL,size); return luaS_newrolstr(S->L,s,size-1); } } }
void luaV_concat (lua_State *L, int total, int last) { do { StkId top = L->base + last + 1; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) luaG_concaterror(L, top-2, top-1); } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ (void)tostring(L, top - 2); /* result is first op (as string) */ else { /* at least two string values; get as many as possible */ size_t tl = tsvalue(top-1)->len; char *buffer; int i; /* collect total length */ for (n = 1; n < total && tostring(L, top-n-1); n++) { size_t l = tsvalue(top-n-1)->len; if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); tl += l; } buffer = luaZ_openspace(L, &G(L)->buff, tl); tl = 0; for (i=n; i>0; i--) /* concat all strings */ { size_t l = tsvalue(top-i)->len; memcpy(buffer+tl, svalue(top-i), l); tl += l; } setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); } total -= n-1; /* got `n' strings to create 1 new */ last -= n-1; } while (total > 1); /* repeat until only 1 result left */ }
void luaV_concat (lua_State *L, int total) { lua_assert(total >= 2); do { StkId top = L->top; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) luaG_concaterror(L, top-2, top-1); } else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ (void)tostring(L, top - 2); /* result is first operand */ else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { setsvalue2s(L, top-2, rawtsvalue(top-1)); /* result is second op. */ } else { /* at least two non-empty string values; get as many as possible */ size_t tl = tsvalue(top-1)->len; char *buffer; int i; /* collect total length */ for (i = 1; i < total && tostring(L, top-i-1); i++) { size_t l = tsvalue(top-i-1)->len; if (l >= (MAX_SIZET/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; } buffer = luaZ_openspace(L, &G(L)->buff, tl); tl = 0; n = i; do { /* concat all strings */ size_t l = tsvalue(top-i)->len; memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); tl += l; } while (--i > 0); setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); } total -= n-1; /* got 'n' strings to create 1 new */ L->top -= n-1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ }
/* ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. */ void luaV_concat (lua_State *L, int total) { lua_assert(total >= 2); do { StkId top = L->top; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); else if (isemptystr(top - 1)) /* second operand is empty? */ cast_void(tostring(L, top - 2)); /* result is first operand */ else if (isemptystr(top - 2)) { /* first operand is an empty string? */ setobjs2s(L, top - 2, top - 1); /* result is second op. */ } else { /* at least two non-empty string values; get as many as possible */ size_t tl = vslen(top - 1); TString *ts; /* collect total length and number of strings */ for (n = 1; n < total && tostring(L, top - n - 1); n++) { size_t l = vslen(top - n - 1); if (l >= (MAX_SIZE/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; } if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ char buff[LUAI_MAXSHORTLEN]; copy2buff(top, n, buff); /* copy strings to buffer */ ts = luaS_newlstr(L, buff, tl); } else { /* long string; copy strings directly to final result */ ts = luaS_createlngstrobj(L, tl); copy2buff(top, n, getstr(ts)); } setsvalue2s(L, top - n, ts); /* create result */ } total -= n-1; /* got 'n' strings to create 1 new */ L->top -= n-1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ }
static void pushstr (lua_State *L, const char *str, size_t l) { setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); }
TString *luaS_new (terra_State *L, const char *str) { return luaS_newlstr(L, str, strlen(str)); }
TaggedString *luaS_new (char *str) { return luaS_newlstr(str, strlen(str)); }
static void unpersistproto(int ref, UnpersistInfo *upi) { /* perms reftbl ... */ Proto *p; int i; int sizep, sizek; /* We have to be careful. The GC expects a lot out of protos. In * particular, we need to give the function a valid string for its * source, and valid code, even before we actually read in the real * code. */ TString *source = luaS_newlstr(upi->L, "", 0); p = luaF_newproto(upi->L); p->source = source; p->sizecode=1; p->code = luaM_newvector(upi->L, 1, Instruction); p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); p->maxstacksize = 2; p->sizek = 0; p->sizep = 0; pushproto(upi->L, p); /* perms reftbl ... proto */ /* We don't need to register early, since protos can never ever be * involved in cyclic references */ /* Read in constant references */ { verify(luaZ_read(&upi->zio, &sizek, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->k, 0, sizek, TObject); for(i=0; i<sizek; i++) { /* perms reftbl ... proto */ unpersist(upi); /* perms reftbl ... proto k */ setobj2s(&p->k[i], getobject(upi->L, -1)); p->sizek++; lua_pop(upi->L, 1); /* perms reftbl ... proto */ } /* perms reftbl ... proto */ } /* Read in sub-proto references */ { verify(luaZ_read(&upi->zio, &sizep, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->p, 0, sizep, Proto*); for(i=0; i<sizep; i++) { /* perms reftbl ... proto */ unpersist(upi); /* perms reftbl ... proto subproto */ p->p[i] = toproto(upi->L, -1); p->sizep++; lua_pop(upi->L, 1); /* perms reftbl ... proto */ } /* perms reftbl ... proto */ } /* Read in code */ { verify(luaZ_read(&upi->zio, &p->sizecode, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->code, 1, p->sizecode, Instruction); verify(luaZ_read(&upi->zio, p->code, sizeof(Instruction) * p->sizecode) == 0); } /* Read in misc values */ { verify(luaZ_read(&upi->zio, &p->nups, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->numparams, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->is_vararg, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->maxstacksize, sizeof(lu_byte)) == 0); } }
int luaX_lex (LexState *LS, SemInfo *seminfo) { for (;;) { switch (LS->current) { case '\n': { inclinenumber(LS); continue; } case '-': { next(LS); if (LS->current != '-') return '-'; /* else is a comment */ next(LS); if (LS->current == '[' && (next(LS), LS->current == '[')) read_long_string(LS, NULL); /* long comment */ else /* short comment */ while (LS->current != '\n' && LS->current != EOZ) next(LS); continue; } case '[': { next(LS); if (LS->current != '[') return '['; else { read_long_string(LS, seminfo); return TK_STRING; } } case '=': { next(LS); if (LS->current != '=') return '='; else { next(LS); return TK_EQ; } } case '<': { next(LS); if (LS->current == '<') { next(LS); return TK_SHL; } else if (LS->current != '=') return '<'; else { next(LS); return TK_LE; } } case '>': { next(LS); if (LS->current == '>') { next(LS); return TK_SHR; } else if (LS->current != '=') return '>'; else { next(LS); return TK_GE; } } case '~': { next(LS); if (LS->current != '=') return '~'; else { next(LS); return TK_NE; } } case '"': case '\'': { read_string(LS, LS->current, seminfo); return TK_STRING; } case '.': { next(LS); if (LS->current == '.') { next(LS); if (LS->current == '.') { next(LS); return TK_DOTS; /* ... */ } else return TK_CONCAT; /* .. */ } else if (!lex_isdigit(LS->current)) return '.'; else { return read_numeral(LS, 1, seminfo); } } case EOZ: { return TK_EOS; } default: { if (isspace(LS->current)) { next(LS); continue; } else if (lex_isdigit(LS->current)) { return (read_numeral(LS, 0, seminfo)); } else if (lex_isalpha(LS->current) || LS->current == '_') { char saveCh = 0; size_t l; TString *ts; if (LS->current == 'L') { next(LS); if (LS->current == '"') { read_wstring(LS, LS->current, seminfo); return TK_WSTRING; } saveCh = 'L'; } /* identifier or reserved word */ l = readname(LS, saveCh); ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l); if (ts->tsv.reserved > 0) /* reserved word? */ return ts->tsv.reserved - 1 + FIRST_RESERVED; seminfo->ts = ts; return TK_NAME; } else { int c = LS->current; if (iscntrl(c)) luaX_error(LS, "invalid control char", luaO_pushfstring(LS->L, "char(%d)", c)); next(LS); return c; /* single-char tokens (+ - / ...) */ } } } } }