Browse Source

new scheme for buffers

Roberto Ierusalimschy 25 years ago
parent
commit
787a78f83e
13 changed files with 376 additions and 211 deletions
  1. 93 4
      lauxlib.c
  2. 36 11
      lauxlib.h
  3. 3 2
      ldo.c
  4. 5 3
      lgc.c
  5. 53 34
      liolib.c
  6. 114 82
      llex.c
  7. 12 1
      lobject.c
  8. 2 1
      lobject.h
  9. 1 3
      lstate.c
  10. 1 3
      lstate.h
  11. 52 62
      lstrlib.c
  12. 2 2
      lundump.c
  13. 2 3
      lvm.c

+ 93 - 4
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.32 2000/08/29 14:33:31 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.33 2000/08/29 20:43:28 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -140,8 +140,97 @@ void luaL_chunkid (char *out, const char *source, int len) {
 }
 
 
-void luaL_filesource (char *out, const char *filename, int len) {
-  if (filename == NULL) filename = "(stdin)";
-  sprintf(out, "@%.*s", len-2, filename);  /* -2 for '@' and '\0' */
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#define buffempty(B)	((B)->p == (B)->buffer)
+#define bufflen(B)	((B)->p - (B)->buffer)
+#define bufffree(B)	((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
+
+#define LIMIT	(LUA_MINSTACK/2)
+
+
+static int emptybuffer (luaL_Buffer *B) {
+  size_t l = bufflen(B);
+  if (l == 0) return 0;  /* put nothing on stack */
+  else {
+    lua_pushlstring(B->L, B->buffer, l);
+    B->p = B->buffer;
+    B->level++;
+    return 1;
+  }
+}
+
+
+static void adjuststack (luaL_Buffer *B) {
+  if (B->level > 1) {
+    lua_State *L = B->L;
+    int toget = 1;  /* number of levels to concat */
+    size_t toplen = lua_strlen(L, -1);
+    do {
+      size_t l = lua_strlen(L, -(toget+1));
+      if (B->level - toget + 1 >= LIMIT || toplen > l) {
+        toplen += l;
+        toget++;
+      }
+      else break;
+    } while (toget < B->level);
+    if (toget >= 2) {
+      lua_concat(L, toget);
+      B->level = B->level - toget + 1;
+    }
+  }
+}
+
+
+char *luaL_prepbuffer (luaL_Buffer *B) {
+  if (emptybuffer(B))
+    adjuststack(B);
+  return B->buffer;
+}
+
+
+void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
+  while (l--)
+    luaL_putchar(B, *s++);
+}
+
+
+void luaL_pushresult (luaL_Buffer *B) {
+  emptybuffer(B);
+  if (B->level == 0)
+    lua_pushlstring(B->L, NULL, 0);
+  else if (B->level > 1)
+    lua_concat(B->L, B->level);
+  B->level = 1;
+}
+
+
+void luaL_addvalue (luaL_Buffer *B) {
+  lua_State *L = B->L;
+  size_t vl = lua_strlen(L, -1);
+  if (vl <= bufffree(B)) {  /* fit into buffer? */
+    memcpy(B->p, lua_tostring(L, -1), vl);  /* put it there */
+    B->p += vl;
+    lua_pop(L, 1);  /* remove from stack */
+  }
+  else {
+    if (emptybuffer(B))
+      lua_insert(L, -2);  /* put buffer before new value */
+    B->level++;  /* add new value into B stack */
+    adjuststack(B);
+  }
+}
+
+
+void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
+  B->L = L;
+  B->p = B->buffer;
+  B->level = 0;
 }
 
+/* }====================================================== */

+ 36 - 11
lauxlib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.21 2000/08/29 20:43:28 roberto Exp roberto $
+** $Id: lauxlib.h,v 1.22 2000/09/04 18:27:32 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -10,6 +10,7 @@
 
 
 #include <stddef.h>
+#include <stdio.h>
 
 #include "lua.h"
 
@@ -34,18 +35,8 @@ void luaL_checktype (lua_State *L, int narg, const char *tname);
 void luaL_verror (lua_State *L, const char *fmt, ...);
 int luaL_findstring (const char *name, const char *const list[]);
 void luaL_chunkid (char *out, const char *source, int len);
-void luaL_filesource (char *out, const char *filename, int len);
 
 
-char *luaL_openspace (lua_State *L, size_t size);
-void luaL_resetbuffer (lua_State *L);
-void luaL_addchar (lua_State *L, int c);
-size_t luaL_getsize (lua_State *L);
-void luaL_addsize (lua_State *L, size_t n);
-size_t luaL_newbuffer (lua_State *L, size_t size);
-void luaL_oldbuffer (lua_State *L, size_t old);
-char *luaL_buffer (lua_State *L);
-
 
 /*
 ** ===============================================================
@@ -64,5 +55,39 @@ char *luaL_buffer (lua_State *L);
 #define luaL_openl(L,a)		luaL_openlib(L, a, (sizeof(a)/sizeof(a[0])))
 
 
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#define LUAL_BUFFERSIZE	  BUFSIZ
+
+
+typedef struct luaL_Buffer {
+  char *p;			/* current position in buffer */
+  int level;
+  lua_State *L;
+  char buffer[LUAL_BUFFERSIZE];
+} luaL_Buffer;
+
+#define luaL_putchar(B,c) \
+  ((void)((B)->p < &(B)->buffer[LUAL_BUFFERSIZE] || luaL_prepbuffer(B)), \
+   (*(B)->p++ = (char)(c)))
+
+#define luaL_addsize(B,n)	((B)->p += (n))
+
+void luaL_buffinit (lua_State *L, luaL_Buffer *B);
+char *luaL_prepbuffer (luaL_Buffer *B);
+void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
+void luaL_addvalue (luaL_Buffer *B);
+void luaL_pushresult (luaL_Buffer *B);
+
+
+/* }====================================================== */
+
+
 #endif
 
+

+ 3 - 2
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.92 2000/08/31 13:31:44 roberto Exp roberto $
+** $Id: ldo.c,v 1.93 2000/09/04 18:52:51 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -293,7 +293,8 @@ static int parse_file (lua_State *L, const char *filename) {
   int c;    /* look ahead char */
   FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
   if (f == NULL) return LUA_ERRFILE;  /* unable to open file */
-  luaL_filesource(source, filename, sizeof(source));
+  if (filename == NULL) filename = "(stdin)";
+  sprintf(source, "@%.*s", (int)sizeof(source)-2, filename);
   c = fgetc(f);
   ungetc(c, f);
   bin = (c == ID_CHUNK);

+ 5 - 3
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.63 2000/08/22 17:44:17 roberto Exp roberto $
+** $Id: lgc.c,v 1.64 2000/08/28 17:57:04 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -333,6 +333,8 @@ void luaC_collect (lua_State *L, int all) {
 }
 
 
+#define MINBUFFER	256
+
 long lua_collectgarbage (lua_State *L, long limit) {
   unsigned long recovered = L->nblocks;  /* to subtract `nblocks' after gc */
   markall(L);
@@ -340,8 +342,8 @@ long lua_collectgarbage (lua_State *L, long limit) {
   luaC_collect(L, 0);
   recovered = recovered - L->nblocks;
   L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
-  if (L->Mbuffsize > L->Mbuffnext*4) {  /* is buffer too big? */
-    L->Mbuffsize /= 2;  /* still larger than Mbuffnext*2 */
+  if (L->Mbuffsize > MINBUFFER*2) {  /* is buffer too big? */
+    L->Mbuffsize /= 2;  /* still larger than MINBUFFER */
     luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char);
   }
   callgcTM(L, &luaO_nilobject);

+ 53 - 34
liolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 1.76 2000/08/31 20:23:40 roberto Exp roberto $
+** $Id: liolib.c,v 1.77 2000/09/05 19:33:32 roberto Exp $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -263,7 +263,7 @@ static int read_pattern (lua_State *L, FILE *f, const char *p) {
         if (c == NEED_OTHER) c = getc(f);
         m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
         if (m) {
-          if (!inskip) luaL_addchar(L, c);
+          if (!inskip) luaL_putchar(L, c);
           c = NEED_OTHER;
         }
         switch (*ep) {
@@ -274,7 +274,7 @@ static int read_pattern (lua_State *L, FILE *f, const char *p) {
             while (m) {  /* reads the same item until it fails */
               c = getc(f);
               m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
-              if (m && !inskip) luaL_addchar(L, c);
+              if (m && !inskip) luaL_putchar(L, c);
             }
             /* go through to continue reading the pattern */
           case '?':  /* optional */
@@ -308,53 +308,74 @@ static int read_number (lua_State *L, FILE *f) {
 }
 
 
-static void read_word (lua_State *L, FILE *f) {
+static int read_word (lua_State *L, FILE *f) {
   int c;
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
   do { c = fgetc(f); } while (isspace(c));  /* skip spaces */
   while (c != EOF && !isspace(c)) {
-    luaL_addchar(L, c);
+    luaL_putchar(&b, c);
     c = fgetc(f);
   }
   ungetc(c, f);
+  luaL_pushresult(&b);  /* close buffer */
+  return (lua_strlen(L, 1) > 0);
 }
 
 
-#define HUNK_LINE	256
-#define HUNK_FILE	BUFSIZ
-
 static int read_line (lua_State *L, FILE *f) {
-  int n;
-  char *b;
+  int n = 0;
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
   for (;;) {
-    b = luaL_openspace(L, HUNK_LINE);
-    if (!fgets(b, HUNK_LINE, f)) return 0;  /* read fails */
-    n = strlen(b);
-    if (b[n-1] != '\n')
-      luaL_addsize(L, n); 
+    char *p = luaL_prepbuffer(&b);
+    if (!fgets(p, LUAL_BUFFERSIZE, f))  /* read fails? */
+      break;
+    n = strlen(p);
+    if (p[n-1] != '\n')
+      luaL_addsize(&b, n); 
     else {
-      luaL_addsize(L, n-1);  /* do not add the `\n' */
+      luaL_addsize(&b, n-1);  /* do not add the `\n' */
       break;
     }
   }
-  return 1;
+  luaL_pushresult(&b);  /* close buffer */
+  return (n > 0);  /* read something? */
 }
 
 
 static void read_file (lua_State *L, FILE *f) {
-  size_t n;
-  do {
-    char *b = luaL_openspace(L, HUNK_FILE);
-    n = fread(b, sizeof(char), HUNK_FILE, f);
-    luaL_addsize(L, n);
-  } while (n==HUNK_FILE);
+  size_t len = 0;
+  size_t size = BUFSIZ;
+  char *buffer = NULL;
+  for (;;) {
+    buffer = (char *)realloc(buffer, size);
+    if (buffer == NULL)
+      lua_error(L, "not enough memory to read a file");
+    len += fread(buffer+len, sizeof(char), size-len, f);
+    if (len < size) break;  /* did not read all it could */
+    size *= 2;
+  }
+  lua_pushlstring(L, buffer, len);
+  free(buffer);
 }
 
 
 static int read_chars (lua_State *L, FILE *f, size_t n) {
-  char *b = luaL_openspace(L, n);
-  size_t n1 = fread(b, sizeof(char), n, f);
-  luaL_addsize(L, n1);
-  return (n == n1);
+  char *buffer;
+  size_t n1;
+  char statbuff[BUFSIZ];
+  if (n <= BUFSIZ)
+    buffer = statbuff;
+  else {
+    buffer = (char  *)malloc(n);
+    if (buffer == NULL)
+      lua_error(L, "not enough memory to read a file");
+  }
+  n1 = fread(buffer, sizeof(char), n, f);
+  lua_pushlstring(L, buffer, n1);
+  if (buffer != statbuff) free(buffer);
+  return (n1 > 0 || n == 0);
 }
 
 
@@ -375,9 +396,7 @@ static int io_read (lua_State *L) {
   else
     luaL_checkstack(L, lastarg-firstarg+1, "too many arguments");
   for (n = firstarg; n<=lastarg; n++) {
-    size_t l;
     int success;
-    luaL_resetbuffer(L);
     if (lua_isnumber(L, n))
       success = read_chars(L, f, (size_t)lua_tonumber(L, n));
     else {
@@ -397,8 +416,7 @@ static int io_read (lua_State *L) {
             success = 1; /* always success */
             break;
           case 'w':  /* word */
-            read_word(L, f);
-            success = 0;  /* must read something to succeed */
+            success = read_word(L, f);
             break;
           default:
             luaL_argerror(L, n, "invalid format");
@@ -406,9 +424,10 @@ static int io_read (lua_State *L) {
         }
       }
     }
-    l = luaL_getsize(L);
-    if (!success && l==0) break;  /* read fails */
-    lua_pushlstring(L, luaL_buffer(L), l);
+    if (!success) {
+      lua_pop(L, 1);  /* remove last result */
+      break;  /* read fails */
+    }
   } endloop:
   return n - firstarg;
 }

+ 114 - 82
llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 1.67 2000/08/09 19:16:57 roberto Exp roberto $
+** $Id: llex.c,v 1.68 2000/08/22 20:07:56 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -27,9 +27,6 @@
 #define next(LS) (LS->current = zgetc(LS->z))
 
 
-#define save(L, c)	luaL_addchar(L, c)
-#define save_and_next(L, LS)  (save(L, LS->current), next(LS))
-
 
 /* ORDER RESERVED */
 static const char *const token2string [] = {
@@ -70,10 +67,8 @@ void luaX_syntaxerror (LexState *ls, const char *s, const char *token) {
 void luaX_error (LexState *ls, const char *s, int token) {
   char buff[TOKEN_LEN];
   luaX_token2str(token, buff);
-  if (buff[0] == '\0') {
-    save(ls->L, '\0');
-    luaX_syntaxerror(ls, s, luaL_buffer(ls->L));
-  }
+  if (buff[0] == '\0')
+    luaX_syntaxerror(ls, s, ls->L->Mbuffer);
   else
     luaX_syntaxerror(ls, s, buff);
 }
@@ -96,16 +91,6 @@ static void luaX_invalidchar (LexState *ls, int c) {
 }
 
 
-static const char *readname (lua_State *L, LexState *LS) {
-  luaL_resetbuffer(L);
-  do {
-    save_and_next(L, LS);
-  } while (isalnum(LS->current) || LS->current == '_');
-  save(L, '\0');
-  return L->Mbuffer+L->Mbuffbase;
-}
-
-
 static void inclinenumber (LexState *LS) {
   next(LS);  /* skip '\n' */
   ++LS->linenumber;
@@ -138,61 +123,133 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
 */
 
 
+/* use Mbuffer to store names, literal strings and numbers */
+
+#define EXTRABUFF	128
+#define checkbuffer(L, n, len)	if ((len)+(n) > L->Mbuffsize) \
+                                  luaO_openspace(L, (len)+(n)+EXTRABUFF)
+
+#define save(L, c, l)	(L->Mbuffer[l++] = (char)c)
+#define save_and_next(L, LS, l)  (save(L, LS->current, l), next(LS))
+
 
-static void read_long_string (lua_State *L, LexState *LS) {
+static const char *readname (LexState *LS) {
+  lua_State *L = LS->L;
+  size_t l = 0;
+  checkbuffer(L, 10, l);
+  do {
+    checkbuffer(L, 10, l);
+    save_and_next(L, LS, l);
+  } while (isalnum(LS->current) || LS->current == '_');
+  save(L, '\0', l);
+  return L->Mbuffer;
+}
+
+
+/* LUA_NUMBER */
+static void read_number (LexState *LS, int comma) {
+  lua_State *L = LS->L;
+  size_t l = 0;
+  checkbuffer(L, 10, l);
+  if (comma) save(L, '.', l);
+  while (isdigit(LS->current)) {
+    checkbuffer(L, 10, l);
+    save_and_next(L, LS, l);
+  }
+  if (LS->current == '.') {
+    save_and_next(L, LS, l);
+    if (LS->current == '.') {
+      save_and_next(L, LS, l);
+      save(L, '\0', l);
+      luaX_error(LS, "ambiguous syntax"
+           " (decimal point x string concatenation)", TK_NUMBER);
+    }
+  }
+  while (isdigit(LS->current)) {
+    checkbuffer(L, 10, l);
+    save_and_next(L, LS, l);
+  }
+  if (LS->current == 'e' || LS->current == 'E') {
+    save_and_next(L, LS, l);  /* read 'E' */
+    if (LS->current == '+' || LS->current == '-')
+      save_and_next(L, LS, l);  /* optional exponent sign */
+    while (isdigit(LS->current)) {
+      checkbuffer(L, 10, l);
+      save_and_next(L, LS, l);
+    }
+  }
+  save(L, '\0', l);
+  if (!luaO_str2d(L->Mbuffer, &LS->t.seminfo.r))
+    luaX_error(LS, "malformed number", TK_NUMBER);
+}
+
+
+static void read_long_string (LexState *LS) {
+  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);
         luaX_error(LS, "unfinished long string", TK_STRING);
         break;  /* to avoid warnings */
       case '[':
-        save_and_next(L, LS);
+        save_and_next(L, LS, l);
         if (LS->current == '[') {
           cont++;
-          save_and_next(L, LS);
+          save_and_next(L, LS, l);
         }
         continue;
       case ']':
-        save_and_next(L, LS);
+        save_and_next(L, LS, l);
         if (LS->current == ']') {
           if (cont == 0) goto endloop;
           cont--;
-          save_and_next(L, LS);
+          save_and_next(L, LS, l);
         }
         continue;
       case '\n':
-        save(L, '\n');
+        save(L, '\n', l);
         inclinenumber(LS);
         continue;
       default:
-        save_and_next(L, LS);
+        save_and_next(L, LS, l);
     }
   } endloop:
-  save_and_next(L, LS);  /* skip the second ']' */
-  LS->t.seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+2),
-                          L->Mbuffnext-L->Mbuffbase-4);
+  save_and_next(L, LS, l);  /* skip the second ']' */
+  save(L, '\0', l);
+  LS->t.seminfo.ts = luaS_newlstr(L, L->Mbuffer+2, l-5);
 }
 
 
-static void read_string (lua_State *L, LexState *LS, int del) {
-  save_and_next(L, LS);
+static void read_string (LexState *LS, int del) {
+  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':
+        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'); next(LS); break;
-          case 'b': save(L, '\b'); next(LS); break;
-          case 'f': save(L, '\f'); next(LS); break;
-          case 'n': save(L, '\n'); next(LS); break;
-          case 'r': save(L, '\r'); next(LS); break;
-          case 't': save(L, '\t'); next(LS); break;
-          case 'v': save(L, '\v'); next(LS); break;
-          case '\n': save(L, '\n'); inclinenumber(LS); break;
+          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); break;
           case '0': case '1': case '2': case '3': case '4':
           case '5': case '6': case '7': case '8': case '9': {
             int c = 0;
@@ -201,28 +258,28 @@ static void read_string (lua_State *L, LexState *LS, int del) {
               c = 10*c + (LS->current-'0');
               next(LS);
             } while (++i<3 && isdigit(LS->current));
-            if (c != (unsigned char)c)
+            if (c != (unsigned char)c) {
+              save(L, '\0', l);
               luaX_error(LS, "escape sequence too large", TK_STRING);
-            save(L, c);
+            }
+            save(L, c, l);
             break;
           }
           default:  /* handles \\, \", \', and \? */
-            save(L, LS->current);
-            next(LS);
+            save_and_next(L, LS, l);
         }
         break;
       default:
-        save_and_next(L, LS);
+        save_and_next(L, LS, l);
     }
   }
-  save_and_next(L, LS);  /* skip delimiter */
-  LS->t.seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1),
-                          L->Mbuffnext-L->Mbuffbase-2);
+  save_and_next(L, LS, l);  /* skip delimiter */
+  save(L, '\0', l);
+  LS->t.seminfo.ts = luaS_newlstr(L, L->Mbuffer+1, l-3);
 }
 
 
 int luaX_lex (LexState *LS) {
-  lua_State *L = LS->L;
   for (;;) {
     switch (LS->current) {
 
@@ -245,12 +302,10 @@ int luaX_lex (LexState *LS) {
         continue;
 
       case '[':
-        luaL_resetbuffer(L);
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current != '[') return '[';
         else {
-          save_and_next(L, LS);  /* pass the second '[' */
-          read_long_string(L, LS);
+          read_long_string(LS);
           return TK_STRING;
         }
 
@@ -276,13 +331,11 @@ int luaX_lex (LexState *LS) {
 
       case '"':
       case '\'':
-        luaL_resetbuffer(L);
-        read_string(L, LS, LS->current);
+        read_string(LS, LS->current);
         return TK_STRING;
 
       case '.':
-        luaL_resetbuffer(L);
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current == '.') {
           next(LS);
           if (LS->current == '.') {
@@ -292,35 +345,14 @@ int luaX_lex (LexState *LS) {
           else return TK_CONCAT;   /* .. */
         }
         else if (!isdigit(LS->current)) return '.';
-        else goto fraction;  /* LS->current is a digit */
+        else {
+          read_number(LS, 1);
+          return TK_NUMBER;
+        }
 
       case '0': case '1': case '2': case '3': case '4':
       case '5': case '6': case '7': case '8': case '9':
-        luaL_resetbuffer(L);
-        do {
-          save_and_next(L, LS);
-        } while (isdigit(LS->current));
-        if (LS->current == '.') {
-          save_and_next(L, LS);
-          if (LS->current == '.') {
-            save(L, '.');
-            luaX_error(LS, "ambiguous syntax"
-                       " (decimal point x string concatenation)", TK_NUMBER);
-          }
-        }
-      fraction:  /* LUA_NUMBER */
-        while (isdigit(LS->current))
-          save_and_next(L, LS);
-        if (LS->current == 'e' || LS->current == 'E') {
-          save_and_next(L, LS);  /* read 'E' */
-          if (LS->current == '+' || LS->current == '-')
-            save_and_next(L, LS);  /* optional exponent sign */
-          while (isdigit(LS->current))
-            save_and_next(L, LS);
-        }
-        save(L, '\0');
-        if (!luaO_str2d(L->Mbuffer+L->Mbuffbase, &LS->t.seminfo.r))
-          luaX_error(LS, "malformed number", TK_NUMBER);
+        read_number(LS, 0);
         return TK_NUMBER;
 
       case EOZ:
@@ -337,7 +369,7 @@ int luaX_lex (LexState *LS) {
           return c;
         }
         tname: {  /* identifier or reserved word */
-          TString *ts = luaS_new(L, readname(L, LS));
+          TString *ts = luaS_new(LS->L, readname(LS));
           if (ts->marked >= RESERVEDMARK)  /* reserved word? */
             return ts->marked-RESERVEDMARK+FIRST_RESERVED;
           LS->t.seminfo.ts = ts;

+ 12 - 1
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 1.44 2000/08/09 19:16:57 roberto Exp roberto $
+** $Id: lobject.c,v 1.45 2000/08/11 16:17:28 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -9,7 +9,9 @@
 
 #include "lua.h"
 
+#include "lmem.h"
 #include "lobject.h"
+#include "lstate.h"
 
 
 /*
@@ -53,6 +55,15 @@ int luaO_equalObj (const TObject *t1, const TObject *t2) {
 }
 
 
+char *luaO_openspace (lua_State *L, size_t n) {
+  if (n > L->Mbuffsize) {
+    luaM_reallocvector(L, L->Mbuffer, n, char);
+    L->Mbuffsize = n;
+  }
+  return L->Mbuffer;
+}
+
+
 static double expten (unsigned int e) {
   double exp = 10.0;
   double res = 1.0;

+ 2 - 1
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.73 2000/08/21 14:34:43 roberto Exp roberto $
+** $Id: lobject.h,v 1.74 2000/08/22 17:44:17 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -193,6 +193,7 @@ extern const TObject luaO_nilobject;
 #define luaO_typename(o)        luaO_typenames[ttype(o)]
 
 lint32 luaO_power2 (lint32 n);
+char *luaO_openspace (lua_State *L, size_t n);
 
 int luaO_equalObj (const TObject *t1, const TObject *t2);
 int luaO_str2d (const char *s, Number *result);

+ 1 - 3
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.35 2000/08/31 13:30:39 roberto Exp roberto $
+** $Id: lstate.c,v 1.36 2000/09/05 19:33:32 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -35,9 +35,7 @@ lua_State *lua_newstate (int stacksize) {
   L->strt.hash = NULL;
   L->udt.hash = NULL;
   L->Mbuffer = NULL;
-  L->Mbuffbase = 0;
   L->Mbuffsize = 0;
-  L->Mbuffnext = 0;
   L->rootproto = NULL;
   L->rootcl = NULL;
   L->roottable = NULL;

+ 1 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.36 2000/08/08 20:42:07 roberto Exp roberto $
+** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -61,9 +61,7 @@ struct lua_State {
   StkId Cbase;  /* base for current C function */
   struct lua_longjmp *errorJmp;  /* current error recover point */
   char *Mbuffer;  /* global buffer */
-  size_t Mbuffbase;  /* current first position of Mbuffer */
   size_t Mbuffsize;  /* size of Mbuffer */
-  size_t Mbuffnext;  /* next position to fill in Mbuffer */
   /* global state */
   Proto *rootproto;  /* list of all prototypes */
   Closure *rootcl;  /* list of all closures */

+ 52 - 62
lstrlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.50 2000/08/31 20:23:40 roberto Exp roberto $
+** $Id: lstrlib.c,v 1.51 2000/09/05 19:33:32 roberto Exp $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */
@@ -18,13 +18,6 @@
 
 
 
-static void addnchar (lua_State *L, const char *s, size_t n) {
-  char *b = luaL_openspace(L, n);
-  memcpy(b, s, n);
-  luaL_addsize(L, n);
-}
-
-
 static int str_len (lua_State *L) {
   size_t l;
   luaL_check_lstr(L, 1, &l);
@@ -33,11 +26,6 @@ static int str_len (lua_State *L) {
 }
 
 
-static void closeandpush (lua_State *L) {
-  lua_pushlstring(L, luaL_buffer(L), luaL_getsize(L));
-}
-
-
 static long posrelat (long pos, size_t len) {
   /* relative string position: negative means back from end */
   return (pos>=0) ? pos : (long)len+pos+1;
@@ -61,11 +49,12 @@ static int str_sub (lua_State *L) {
 static int str_lower (lua_State *L) {
   size_t l;
   size_t i;
+  luaL_Buffer b;
   const char *s = luaL_check_lstr(L, 1, &l);
-  luaL_resetbuffer(L);
+  luaL_buffinit(L, &b);
   for (i=0; i<l; i++)
-    luaL_addchar(L, tolower((unsigned char)(s[i])));
-  closeandpush(L);
+    luaL_putchar(&b, tolower((unsigned char)(s[i])));
+  luaL_pushresult(&b);
   return 1;
 }
 
@@ -73,22 +62,24 @@ static int str_lower (lua_State *L) {
 static int str_upper (lua_State *L) {
   size_t l;
   size_t i;
+  luaL_Buffer b;
   const char *s = luaL_check_lstr(L, 1, &l);
-  luaL_resetbuffer(L);
+  luaL_buffinit(L, &b);
   for (i=0; i<l; i++)
-    luaL_addchar(L, toupper((unsigned char)(s[i])));
-  closeandpush(L);
+    luaL_putchar(&b, toupper((unsigned char)(s[i])));
+  luaL_pushresult(&b);
   return 1;
 }
 
 static int str_rep (lua_State *L) {
   size_t l;
+  luaL_Buffer b;
   const char *s = luaL_check_lstr(L, 1, &l);
   int n = luaL_check_int(L, 2);
-  luaL_resetbuffer(L);
+  luaL_buffinit(L, &b);
   while (n-- > 0)
-    addnchar(L, s, l);
-  closeandpush(L);
+    luaL_addlstring(&b, s, l);
+  luaL_pushresult(&b);
   return 1;
 }
 
@@ -106,13 +97,14 @@ static int str_byte (lua_State *L) {
 static int str_char (lua_State *L) {
   int n = lua_gettop(L);  /* number of arguments */
   int i;
-  luaL_resetbuffer(L);
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
   for (i=1; i<=n; i++) {
     int c = luaL_check_int(L, i);
     luaL_arg_check(L, (unsigned char)c == c, i, "invalid value");
-    luaL_addchar(L, (unsigned char)c);
+    luaL_putchar(&b, (unsigned char)c);
   }
-  closeandpush(L);
+  luaL_pushresult(&b);
   return 1;
 }
 
@@ -445,43 +437,37 @@ static int str_find (lua_State *L) {
 }
 
 
-static void add_s (lua_State *L, struct Capture *cap) {
+static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) {
   if (lua_isstring(L, 3)) {
     const char *news = lua_tostring(L, 3);
     size_t l = lua_strlen(L, 3);
     size_t i;
     for (i=0; i<l; i++) {
       if (news[i] != ESC)
-        luaL_addchar(L, news[i]);
+        luaL_putchar(b, news[i]);
       else {
         i++;  /* skip ESC */
         if (!isdigit((unsigned char)news[i]))
-          luaL_addchar(L, news[i]);
+          luaL_putchar(b, news[i]);
         else {
           int level = check_capture(L, news[i], cap);
-          addnchar(L, cap->capture[level].init, cap->capture[level].len);
+          luaL_addlstring(b, cap->capture[level].init, cap->capture[level].len);
         }
       }
     }
   }
   else {  /* is a function */
     int status;
-    size_t oldbuff;
     int n;
-    const char *s;
     lua_pushvalue(L, 3);
     n = push_captures(L, cap);
-    /* function may use buffer, so save it and create a new one */
-    oldbuff = luaL_newbuffer(L, 0);
     status = lua_call(L, n, 1);
-    /* restore old buffer */
-    luaL_oldbuffer(L, oldbuff);
     if (status != 0)
-      lua_error(L, NULL);
-    s = lua_tostring(L, -1);
-    if (s)
-      addnchar(L, lua_tostring(L, -1), lua_strlen(L, -1));
-    lua_pop(L, 1);  /* pop function result */
+      lua_error(L, NULL);  /* propagate error */
+    if (lua_isstring(L, -1))
+      luaL_addvalue(b);  /* add return to accumulated result */
+    else
+      lua_pop(L, 1);  /* function result is not a string: pop it */
   }
 }
 
@@ -494,10 +480,11 @@ static int str_gsub (lua_State *L) {
   int anchor = (*p == '^') ? (p++, 1) : 0;
   int n = 0;
   struct Capture cap;
+  luaL_Buffer b;
   luaL_arg_check(L,
     lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
     3, "string or function expected");
-  luaL_resetbuffer(L);
+  luaL_buffinit(L, &b);
   cap.src_end = src+srcl;
   while (n < max_s) {
     const char *e;
@@ -505,17 +492,17 @@ static int str_gsub (lua_State *L) {
     e = match(L, src, p, &cap);
     if (e) {
       n++;
-      add_s(L, &cap);
+      add_s(L, &b, &cap);
     }
     if (e && e>src) /* non empty match? */
       src = e;  /* skip it */
     else if (src < cap.src_end)
-      luaL_addchar(L, *src++);
+      luaL_putchar(&b, *src++);
     else break;
     if (anchor) break;
   }
-  addnchar(L, src, cap.src_end-src);
-  closeandpush(L);
+  luaL_addlstring(&b, src, cap.src_end-src);
+  luaL_pushresult(&b);
   lua_pushnumber(L, n);  /* number of substitutions */
   return 2;
 }
@@ -523,40 +510,43 @@ static int str_gsub (lua_State *L) {
 /* }====================================================== */
 
 
-static void luaI_addquoted (lua_State *L, int arg) {
+static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
   size_t l;
   const char *s = luaL_check_lstr(L, arg, &l);
-  luaL_addchar(L, '"');
+  luaL_putchar(b, '"');
   while (l--) {
     switch (*s) {
       case '"':  case '\\':  case '\n':
-        luaL_addchar(L, '\\');
-        luaL_addchar(L, *s);
+        luaL_putchar(b, '\\');
+        luaL_putchar(b, *s);
         break;
-      case '\0': addnchar(L, "\\000", 4); break;
-      default: luaL_addchar(L, *s);
+      case '\0': luaL_addlstring(b, "\\000", 4); break;
+      default: luaL_putchar(b, *s);
     }
     s++;
   }
-  luaL_addchar(L, '"');
+  luaL_putchar(b, '"');
 }
 
+/* maximum size of each formated item (> len(format('%99.99f', -1e308))) */
+#define MAX_ITEM	512
 /* maximum size of each format specification (such as '%-099.99d') */
-#define MAX_FORMAT 20  /* arbitrary limit */
+#define MAX_FORMAT	20
 
 static int str_format (lua_State *L) {
   int arg = 1;
   const char *strfrmt = luaL_check_string(L, arg);
-  luaL_resetbuffer(L);
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
   while (*strfrmt) {
     if (*strfrmt != '%')
-      luaL_addchar(L, *strfrmt++);
+      luaL_putchar(&b, *strfrmt++);
     else if (*++strfrmt == '%')
-      luaL_addchar(L, *strfrmt++);  /* %% */
+      luaL_putchar(&b, *strfrmt++);  /* %% */
     else { /* format item */
       struct Capture cap;
       char form[MAX_FORMAT];  /* to store the format ('%...') */
-      char *buff;  /* to store the formatted item */
+      char buff[MAX_ITEM];  /* to store the formatted item */
       const char *initf = strfrmt;
       form[0] = '%';
       if (isdigit((unsigned char)*initf) && *(initf+1) == '$') {
@@ -572,7 +562,6 @@ static int str_format (lua_State *L) {
         lua_error(L, "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(L, 512);  /* 512 > len(format('%99.99f', -1e308)) */
       switch (*strfrmt++) {
         case 'c':  case 'd':  case 'i':
           sprintf(buff, form, luaL_check_int(L, arg));
@@ -584,7 +573,7 @@ static int str_format (lua_State *L) {
           sprintf(buff, form, luaL_check_number(L, arg));
           break;
         case 'q':
-          luaI_addquoted(L, arg);
+          luaI_addquoted(L, &b, arg);
           continue;  /* skip the "addsize" at the end */
         case 's': {
           size_t l;
@@ -592,7 +581,8 @@ static int str_format (lua_State *L) {
           if (cap.capture[1].len == 0 && l >= 100) {
             /* no precision and string is too long to be formatted;
                keep original string */
-            addnchar(L, s, l);
+            lua_pushvalue(L, arg);
+            luaL_addvalue(&b);
             continue;  /* skip the "addsize" at the end */
           }
           else {
@@ -603,10 +593,10 @@ static int str_format (lua_State *L) {
         default:  /* also treat cases 'pnLlh' */
           lua_error(L, "invalid option in `format'");
       }
-      luaL_addsize(L, strlen(buff));
+      luaL_addlstring(&b, buff, strlen(buff));
     }
   }
-  closeandpush(L);  /* push the result */
+  luaL_pushresult(&b);
   return 1;
 }
 

+ 2 - 2
lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.29 2000/06/28 14:12:55 lhf Exp lhf $
+** $Id: lundump.c,v 1.27 2000/09/04 18:53:41 roberto Exp roberto $
 ** load bytecodes from files
 ** See Copyright Notice in lua.h
 */
@@ -86,7 +86,7 @@ static TString* LoadString (lua_State* L, ZIO* Z, int swap)
   return NULL;
  else
  {
-  char* s=luaL_openspace(L,size);
+  char* s=luaO_openspace(L,size);
   LoadBlock(L,s,size,Z);
   return luaS_newlstr(L,s,size-1);	/* remove trailing '\0' */
  }

+ 2 - 3
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.133 2000/08/31 21:02:55 roberto Exp roberto $
+** $Id: lvm.c,v 1.134 2000/09/05 19:33:32 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -12,7 +12,6 @@
 #include "lua.h"
 
 #include "lapi.h"
-#include "lauxlib.h"
 #include "ldebug.h"
 #include "ldo.h"
 #include "lfunc.h"
@@ -300,7 +299,7 @@ void luaV_strconc (lua_State *L, int total, StkId top) {
         n++;
       }
       if (tl > MAX_SIZET) lua_error(L, "string size overflow");
-      buffer = luaL_openspace(L, tl);
+      buffer = luaO_openspace(L, tl);
       tl = 0;
       for (i=n; i>0; i--) {  /* concat all strings */
         size_t l = tsvalue(top-i)->u.s.len;