static void str_gsub (void) { int32 srcl; const char *src = luaL_check_lstr(1, &srcl); const char *p = luaL_check_string(2); lua_Object newp = lua_getparam(3); int32 max_s = (int32)luaL_opt_number(4, srcl+1); int32 anchor = (*p == '^') ? (p++, 1) : 0; int32 n = 0; struct Capture cap; luaL_arg_check(lua_isstring(newp) || lua_isfunction(newp), 3, "string or function expected"); luaL_resetbuffer(); cap.src_end = src+srcl; while (n < max_s) { const char *e; cap.level = 0; e = match(src, p, &cap); if (e) { n++; add_s(newp, &cap); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ else if (src < cap.src_end) luaL_addchar(*src++); else break; if (anchor) break; } addnchar(src, cap.src_end-src); closeandpush(); lua_pushnumber(n); /* number of substitutions */ }
static void io_read() { int32 arg = FIRSTARG; LuaFile *f = (LuaFile *)getfileparam(FINPUT, &arg); char *buff; const char *p = luaL_opt_string(arg, "[^\n]*{\n}"); int inskip = 0; // to control {skips} int c = NEED_OTHER; luaL_resetbuffer(); while (*p) { if (*p == '{') { inskip++; p++; } else if (*p == '}') { if (inskip == 0) lua_error("unbalanced braces in read pattern"); inskip--; p++; } else { const char *ep; // get what is next int m; // match result if (c == NEED_OTHER) { char z; if (f->read(&z, 1) != 1) c = EOF; else c = z; } m = luaI_singlematch((c == EOF) ? 0 : (char)c, p, &ep); if (m) { if (inskip == 0) luaL_addchar(c); c = NEED_OTHER; } switch (*ep) { case '*': // repetition if (!m) p = ep + 1; // else stay in (repeat) the same item break; case '?': // optional p = ep + 1; // continues reading the pattern break; default: if (m) p = ep; // continues reading the pattern else goto break_while; // pattern fails } } } break_while: if (c >= 0) // not EOF nor NEED_OTHER? f->seek(-1, SEEK_CUR); luaL_addchar(0); buff = luaL_buffer(); if (*buff != 0 || *p == 0) // read something or did not fail? lua_pushstring(buff); }
static void str_format (void) { int32 arg = 1; const char *strfrmt = luaL_check_string(arg); struct Capture cap; cap.src_end = strfrmt+strlen(strfrmt)+1; luaL_resetbuffer(); while (*strfrmt) { if (*strfrmt != '%') luaL_addchar(*strfrmt++); else if (*++strfrmt == '%') luaL_addchar(*strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* store the format ('%...') */ char *buff; const char *initf = strfrmt; form[0] = '%'; cap.level = 0; if (isdigit((byte)initf[0]) && initf[1] == '$') { arg = initf[0] - '0'; initf += 2; /* skip the 'n$' */ } arg++; strfrmt = match(initf, "[-+ #0]*(%d*)%.?(%d*)", &cap); if (cap.capture[0].len > 2 || cap.capture[1].len > 2) /* < 100? */ lua_error("invalid format (width or precision too long)"); strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ form[strfrmt-initf+2] = 0; buff = luaL_openspace(1000); /* to store the formatted value */ switch (*strfrmt++) { case 'q': luaI_addquoted(luaL_check_string(arg)); continue; case 's': { const char *s = luaL_check_string(arg); buff = luaL_openspace(strlen(s)); sprintf(buff, form, s); break; } case 'c': case 'd': case 'i': sprintf(buff, form, (int)luaL_check_number(arg)); break; case 'o': case 'u': case 'x': case 'X': sprintf(buff, form, (unsigned int)luaL_check_number(arg)); break; case 'e': case 'E': case 'f': case 'g': case 'G': sprintf(buff, form, luaL_check_number(arg)); break; default: /* also treat cases 'pnLlh' */ lua_error("invalid option in `format'"); } luaL_addsize(strlen(buff)); } } closeandpush(); /* push the result */ }
static void str_char (void) { int32 i = 0; luaL_resetbuffer(); while (lua_getparam(++i) != LUA_NOOBJECT) { double c = luaL_check_number(i); luaL_arg_check((byte)c == c, i, "invalid value"); luaL_addchar((int32)c); } closeandpush(); }
static void str_rep (void) { int32 l; const char *s = luaL_check_lstr(1, &l); int32 n = (int32)luaL_check_number(2); luaL_resetbuffer(); while (n-- > 0) addnchar(s, l); closeandpush(); }
static void str_upper (void) { int32 l; int32 i; const char *s = luaL_check_lstr(1, &l); luaL_resetbuffer(); for (i=0; i<l; i++) luaL_addchar(toupper((byte)(s[i]))); closeandpush(); }
void luaX_setinput (LexState *LS, ZIO *z) { LS->current = '\n'; LS->linenumber = 0; LS->iflevel = 0; LS->ifstate[0].skip = 0; LS->ifstate[0].elsepart = 1; /* to avoid a free $else */ LS->lex_z = z; LS->fs = NULL; firstline(LS); luaL_resetbuffer(); }
void luaX_setinput(ZIO *z) { LexState *LS = lua_state->lexstate; LS->current = '\n'; LS->linelasttoken = 0; LS->linenumber = 0; LS->iflevel = 0; LS->ifstate[0].skip = 0; LS->ifstate[0].elsepart = 1; // to avoid a free $else LS->lex_z = z; firstline(LS); luaL_resetbuffer(); }
static void io_read (void) { int arg = FIRSTARG; FILE *f = getfileparam(FINPUT, &arg); char *buff; char *p = luaL_opt_string(arg, "[^\n]*{\n}"); int inskip = 0; /* to control {skips} */ int c = NEED_OTHER; luaL_resetbuffer(); while (*p) { if (*p == '{') { inskip++; p++; } else if (*p == '}') { if (inskip == 0) lua_error("unbalanced braces in read pattern"); inskip--; p++; } else { char *ep; /* get what is next */ int m; /* match result */ if (c == NEED_OTHER) c = getc(f); m = luaI_singlematch((c == EOF) ? 0 : (char)c, p, &ep); if (m) { if (inskip == 0) luaL_addchar(c); c = NEED_OTHER; } switch (*ep) { case '*': /* repetition */ if (!m) p = ep+1; /* else stay in (repeat) the same item */ break; case '?': /* optional */ p = ep+1; /* continues reading the pattern */ break; default: if (m) p = ep; /* continues reading the pattern */ else goto break_while; /* pattern fails */ } } } break_while: if (c >= 0) /* not EOF nor NEED_OTHER? */ ungetc(c, f); luaL_addchar(0); buff = luaL_buffer(); if (*buff != 0 || *p == 0) /* read something or did not fail? */ lua_pushstring(buff); }
int luaX_lex (LexState *LS) { luaL_resetbuffer(); for (;;) { switch (LS->current) { case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */ next(LS); continue; case '\n': inclinenumber(LS); continue; case '-': save_and_next(LS); if (LS->current != '-') return '-'; do { next(LS); } while (LS->current != '\n' && LS->current != EOZ); luaL_resetbuffer(); continue; case '[': save_and_next(LS); if (LS->current != '[') return '['; else { save_and_next(LS); /* pass the second '[' */ return read_long_string(LS); } case '=': save_and_next(LS); if (LS->current != '=') return '='; else { save_and_next(LS); return EQ; } case '<': save_and_next(LS); if (LS->current != '=') return '<'; else { save_and_next(LS); return LE; } case '>': save_and_next(LS); if (LS->current != '=') return '>'; else { save_and_next(LS); return GE; } case '~': save_and_next(LS); if (LS->current != '=') return '~'; else { save_and_next(LS); return NE; } case '"': case '\'': { int del = LS->current; save_and_next(LS); while (LS->current != del) { switch (LS->current) { case EOZ: case '\n': luaX_error(LS, "unfinished string"); return EOS; /* to avoid warnings */ case '\\': next(LS); /* do not save the '\' */ switch (LS->current) { case 'a': save('\a'); next(LS); break; case 'b': save('\b'); next(LS); break; case 'f': save('\f'); next(LS); break; case 'n': save('\n'); next(LS); break; case 'r': save('\r'); next(LS); break; case 't': save('\t'); next(LS); break; case 'v': save('\v'); next(LS); break; case '\n': save('\n'); inclinenumber(LS); break; default : { if (isdigit(LS->current)) { 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) luaX_error(LS, "escape sequence too large"); save(c); } else { /* handles \, ", ', and ? */ save(LS->current); next(LS); } break; } } break; default: save_and_next(LS); } } save_and_next(LS); /* skip delimiter */ LS->seminfo.ts = luaS_newlstr(L->Mbuffer+(L->Mbuffbase+1), L->Mbuffnext-L->Mbuffbase-2); return STRING; } case '.': save_and_next(LS); if (LS->current == '.') { save_and_next(LS); if (LS->current == '.') { save_and_next(LS); return DOTS; /* ... */ } else return CONC; /* .. */ } else if (!isdigit(LS->current)) return '.'; goto fraction; /* LS->current is a digit: goes through to number */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { save_and_next(LS); } while (isdigit(LS->current)); if (LS->current == '.') { save_and_next(LS); if (LS->current == '.') { save('.'); luaX_error(LS, "ambiguous syntax (decimal point x string concatenation)"); } } fraction: while (isdigit(LS->current)) save_and_next(LS); if (toupper(LS->current) == 'E') { save_and_next(LS); /* read 'E' */ save_and_next(LS); /* read '+', '-' or first digit */ while (isdigit(LS->current)) save_and_next(LS); } save('\0'); LS->seminfo.r = luaO_str2d(L->Mbuffer+L->Mbuffbase); if (LS->seminfo.r < 0) luaX_error(LS, "invalid numeric format"); return NUMBER; case EOZ: if (LS->iflevel > 0) luaX_error(LS, "input ends inside a $if"); return EOS; default: if (LS->current != '_' && !isalpha(LS->current)) { int c = LS->current; if (iscntrl(c)) luaX_invalidchar(LS, c); save_and_next(LS); return c; } else { /* identifier or reserved word */ TaggedString *ts; do { save_and_next(LS); } while (isalnum(LS->current) || LS->current == '_'); save('\0'); ts = luaS_new(L->Mbuffer+L->Mbuffbase); if (ts->head.marked >= FIRST_RESERVED) return ts->head.marked; /* reserved word */ LS->seminfo.ts = ts; return NAME; } } } }
int32 luaY_lex(YYSTYPE *l) { LexState *LS = lua_state->lexstate; double a; luaL_resetbuffer(); if (lua_debug) luaY_codedebugline(LS->linelasttoken); LS->linelasttoken = LS->linenumber; while (1) { switch (LS->current) { case ' ': case '\t': case '\r': // CR: to avoid problems with DOS next(LS); continue; case '\n': inclinenumber(LS); LS->linelasttoken = LS->linenumber; continue; case '-': save_and_next(LS); if (LS->current != '-') return '-'; do { next(LS); } while (LS->current != '\n' && LS->current != EOZ); luaL_resetbuffer(); continue; case '[': save_and_next(LS); if (LS->current != '[') return '['; else { save_and_next(LS); // pass the second '[' return read_long_string(LS, l); } case '=': save_and_next(LS); if (LS->current != '=') return '='; else { save_and_next(LS); return EQ; } case '<': save_and_next(LS); if (LS->current != '=') return '<'; else { save_and_next(LS); return LE; } case '>': save_and_next(LS); if (LS->current != '=') return '>'; else { save_and_next(LS); return GE; } case '~': save_and_next(LS); if (LS->current != '=') return '~'; else { save_and_next(LS); return NE; } case '"': case '\'': { int32 del = LS->current; save_and_next(LS); while (LS->current != del) { switch (LS->current) { case EOZ: case '\n': save(0); return WRONGTOKEN; case '\\': next(LS); // do not save the '\' switch (LS->current) { case 'n': save('\n'); next(LS); break; case 't': save('\t'); next(LS); break; case 'r': save('\r'); next(LS); break; case '\n': save('\n'); inclinenumber(LS); break; default : save_and_next(LS); break; } break; default: save_and_next(LS); } } next(LS); // skip delimiter save(0); l->pTStr = luaS_new(Mbuffbase + 1); Mbuffer[Mbuffnext - 1] = del; // restore delimiter return STRING; } case '.': save_and_next(LS); if (LS->current == '.') { save_and_next(LS); if (LS->current == '.') { save_and_next(LS); return DOTS; // ... } else return CONC; // .. } else if (!Common::isDigit(LS->current)) return '.'; // LS->current is a digit: goes through to number/ a = 0.0; goto fraction; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': a = 0.0; do { a = 10.0 * a + (LS->current - '0'); save_and_next(LS); } while (Common::isDigit(LS->current)); if (LS->current == '.') { save_and_next(LS); if (LS->current == '.') { save(0); luaY_error("ambiguous syntax (decimal point x string concatenation)"); } } fraction: { double da = 0.1; while (Common::isDigit(LS->current)) { a += (LS->current - '0') * da; da /= 10.0; save_and_next(LS); } if (toupper(LS->current) == 'E') { int32 e = 0; int32 neg; double ea; save_and_next(LS); neg = (LS->current == '-'); if (LS->current == '+' || LS->current == '-') save_and_next(LS); if (!Common::isDigit(LS->current)) { save(0); return WRONGTOKEN; } do { e = 10 * e + (LS->current - '0'); save_and_next(LS); } while (Common::isDigit(LS->current)); for (ea = neg ? 0.1 : 10.0; e > 0; e >>= 1) { if (e & 1) a *= ea; ea *= ea; } } l->vReal = a; return NUMBER; } case EOZ: save(0); if (LS->iflevel > 0) luaY_syntaxerror("input ends inside a $if", ""); return 0; default: if (LS->current != '_' && !Common::isAlpha(LS->current)) { int32 c = LS->current; save_and_next(LS); return c; } else { // identifier or reserved word TaggedString *ts; do { save_and_next(LS); } while (Common::isAlnum(LS->current) || LS->current == '_'); save(0); ts = luaS_new(Mbuffbase); if (ts->head.marked >= 255) return ts->head.marked; // reserved word l->pTStr = ts; return NAME; } } }