bcread_error(ls, LJ_ERR_BCBAD);
do {
const char *buf;
- size_t size;
- if (ls->n) { /* Copy remainder to buffer. */
- if (ls->sb.n) { /* Move down in buffer. */
- lua_assert(ls->p + ls->n == ls->sb.buf + ls->sb.n);
- if (ls->n != ls->sb.n)
- memmove(ls->sb.buf, ls->p, ls->n);
+ size_t sz;
+ char *p = sbufB(&ls->sb);
+ MSize n = (MSize)(ls->pe - ls->p);
+ if (n) { /* Copy remainder to buffer. */
+ if (sbuflen(&ls->sb)) { /* Move down in buffer. */
+ lua_assert(ls->pe == sbufP(&ls->sb));
+ if (ls->p != p) memmove(p, ls->p, n);
} else { /* Copy from buffer provided by reader. */
- bcread_resize(ls, len);
- memcpy(ls->sb.buf, ls->p, ls->n);
+ p = lj_buf_need(&ls->sb, len);
+ memcpy(p, ls->p, n);
}
- ls->p = ls->sb.buf;
+ ls->p = p;
+ ls->pe = p + n;
}
- ls->sb.n = ls->n;
- buf = ls->rfunc(ls->L, ls->rdata, &size); /* Get more data from reader. */
- if (buf == NULL || size == 0) { /* EOF? */
+ setsbufP(&ls->sb, p + n);
+ buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */
+ if (buf == NULL || sz == 0) { /* EOF? */
if (need) bcread_error(ls, LJ_ERR_BCBAD);
- ls->current = -1; /* Only bad if we get called again. */
+ ls->c = -1; /* Only bad if we get called again. */
break;
}
- if (size >= LJ_MAX_MEM - ls->sb.n) lj_err_mem(ls->L);
- if (ls->sb.n) { /* Append to buffer. */
- MSize n = ls->sb.n + (MSize)size;
- bcread_resize(ls, n < len ? len : n);
- memcpy(ls->sb.buf + ls->sb.n, buf, size);
- ls->n = ls->sb.n = n;
- ls->p = ls->sb.buf;
++ if (sz >= LJ_MAX_BUF - n) lj_err_mem(ls->L);
+ if (n) { /* Append to buffer. */
+ n += (MSize)sz;
+ p = lj_buf_need(&ls->sb, n < len ? len : n);
+ memcpy(sbufP(&ls->sb), buf, sz);
+ setsbufP(&ls->sb, p + n);
+ ls->p = p;
+ ls->pe = p + n;
} else { /* Return buffer provided by reader. */
- ls->n = (MSize)size;
ls->p = buf;
+ ls->pe = buf + sz;
}
- } while (ls->p + len > ls->pe);
- } while (ls->n < len);
++ } while ((MSize)(ls->pe - ls->p) < len);
}
/* Need a certain number of bytes. */
static LJ_AINLINE void bcread_need(LexState *ls, MSize len)
{
- if (LJ_UNLIKELY(ls->p + len > ls->pe))
- if (LJ_UNLIKELY(ls->n < len))
++ if (LJ_UNLIKELY((MSize)(ls->pe - ls->p) < len))
bcread_fill(ls, len, 1);
}
/* Want to read up to a certain number of bytes, but may need less. */
static LJ_AINLINE void bcread_want(LexState *ls, MSize len)
{
- if (LJ_UNLIKELY(ls->p + len > ls->pe))
- if (LJ_UNLIKELY(ls->n < len))
++ if (LJ_UNLIKELY((MSize)(ls->pe - ls->p) < len))
bcread_fill(ls, len, 0);
}
setprotoV(L, L->top, pt);
incr_top(L);
}
- if ((int32_t)(2*(uint32_t)(ls->pe - ls->p)) > 0 ||
- L->top-1 != bcread_oldtop(L, ls))
- if ((ls->n && !ls->endmark) || L->top-1 != bcread_oldtop(L, ls))
++ if ((ls->pe != ls->p && !ls->endmark) || L->top-1 != bcread_oldtop(L, ls))
bcread_error(ls, LJ_ERR_BCBAD);
/* Pop off last prototype. */
L->top--;
/* -- Buffer handling ----------------------------------------------------- */
-#define char2int(c) ((int)(uint8_t)(c))
-#define next(ls) \
- (ls->current = (ls->n--) > 0 ? char2int(*ls->p++) : fillbuf(ls))
-#define save_and_next(ls) (save(ls, ls->current), next(ls))
-#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
-#define END_OF_STREAM (-1)
+#define LEX_EOF (-1)
+#define lex_iseol(ls) (ls->c == '\n' || ls->c == '\r')
-static int fillbuf(LexState *ls)
+/* Get more input from reader. */
+static LJ_NOINLINE LexChar lex_more(LexState *ls)
{
size_t sz;
- const char *buf = ls->rfunc(ls->L, ls->rdata, &sz);
- if (buf == NULL || sz == 0) return END_OF_STREAM;
- if (sz >= LJ_MAX_MEM) {
+ const char *p = ls->rfunc(ls->L, ls->rdata, &sz);
+ if (p == NULL || sz == 0) return LEX_EOF;
++ if (sz >= LJ_MAX_BUF) {
+ if (sz != ~(size_t)0) lj_err_mem(ls->L);
++ sz = ~(uintptr_t)0 - (uintptr_t)p;
+ ls->endmark = 1;
+ }
- ls->n = (MSize)sz - 1;
- ls->p = buf;
- return char2int(*(ls->p++));
+ ls->pe = p + sz;
+ ls->p = p + 1;
+ return (LexChar)(uint8_t)p[0];
}
-static LJ_NOINLINE void save_grow(LexState *ls, int c)
+/* Get next character. */
+static LJ_AINLINE LexChar lex_next(LexState *ls)
{
- MSize newsize;
- if (ls->sb.sz >= LJ_MAX_STR/2)
- lj_lex_error(ls, 0, LJ_ERR_XELEM);
- newsize = ls->sb.sz * 2;
- lj_str_resizebuf(ls->L, &ls->sb, newsize);
- ls->sb.buf[ls->sb.n++] = (char)c;
+ return (ls->c = ls->p < ls->pe ? (LexChar)(uint8_t)*ls->p++ : lex_more(ls));
}
-static LJ_AINLINE void save(LexState *ls, int c)
+/* Save character. */
+static LJ_AINLINE void lex_save(LexState *ls, LexChar c)
{
- if (LJ_UNLIKELY(ls->sb.n + 1 > ls->sb.sz))
- save_grow(ls, c);
- else
- ls->sb.buf[ls->sb.n++] = (char)c;
+ lj_buf_putb(&ls->sb, c);
}
-static void inclinenumber(LexState *ls)
+/* Save previous character and get next character. */
+static LJ_AINLINE LexChar lex_savenext(LexState *ls)
{
- int old = ls->current;
- lua_assert(currIsNewline(ls));
- next(ls); /* skip `\n' or `\r' */
- if (currIsNewline(ls) && ls->current != old)
- next(ls); /* skip `\n\r' or `\r\n' */
+ lex_save(ls, ls->c);
+ return lex_next(ls);
+}
+
+/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
+static void lex_newline(LexState *ls)
+{
+ LexChar old = ls->c;
+ lua_assert(lex_iseol(ls));
+ lex_next(ls); /* Skip "\n" or "\r". */
+ if (lex_iseol(ls) && ls->c != old) lex_next(ls); /* Skip "\n\r" or "\r\n". */
if (++ls->linenumber >= LJ_MAX_LINE)
- lj_lex_error(ls, ls->token, LJ_ERR_XLINES);
+ lj_lex_error(ls, ls->tok, LJ_ERR_XLINES);
}
/* -- Scanner for terminals ----------------------------------------------- */
ls->lookahead = TK_eof; /* No look-ahead token. */
ls->linenumber = 1;
ls->lastline = 1;
- lj_str_resizebuf(ls->L, &ls->sb, LJ_MIN_SBUF);
- next(ls); /* Read-ahead first char. */
- if (ls->current == 0xef && ls->n >= 2 && char2int(ls->p[0]) == 0xbb &&
- char2int(ls->p[1]) == 0xbf) { /* Skip UTF-8 BOM (if buffered). */
- ls->n -= 2;
+ ls->endmark = 0;
+ lex_next(ls); /* Read-ahead first char. */
+ if (ls->c == 0xef && ls->p + 2 <= ls->pe && (uint8_t)ls->p[0] == 0xbb &&
+ (uint8_t)ls->p[1] == 0xbf) { /* Skip UTF-8 BOM (if buffered). */
ls->p += 2;
- next(ls);
+ lex_next(ls);
header = 1;
}
- if (ls->current == '#') { /* Skip POSIX #! header line. */
+ if (ls->c == '#') { /* Skip POSIX #! header line. */
do {
- next(ls);
- if (ls->current == END_OF_STREAM) return 0;
- } while (!currIsNewline(ls));
- inclinenumber(ls);
+ lex_next(ls);
+ if (ls->c == LEX_EOF) return 0;
+ } while (!lex_iseol(ls));
+ lex_newline(ls);
header = 1;
}
- if (ls->current == LUA_SIGNATURE[0]) { /* Bytecode dump. */
+ if (ls->c == LUA_SIGNATURE[0]) { /* Bytecode dump. */
if (header) {
/*
** Loading bytecode with an extra header is disabled for security