Browse Source

use of different buffers for scanner and concatenation

Roberto Ierusalimschy 23 years ago
parent
commit
b3d0682fb9
15 changed files with 136 additions and 110 deletions
  1. 5 2
      ldo.c
  2. 4 6
      lgc.c
  3. 63 66
      llex.c
  4. 3 2
      llex.h
  5. 7 1
      llimits.h
  6. 1 10
      lobject.c
  7. 1 3
      lobject.h
  8. 3 2
      lparser.c
  9. 2 2
      lparser.h
  10. 3 4
      lstate.c
  11. 3 3
      lstate.h
  12. 2 2
      lundump.c
  13. 2 2
      lvm.c
  14. 13 2
      lzio.c
  15. 24 3
      lzio.h

+ 5 - 2
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.193 2002/08/30 19:09:21 roberto Exp roberto $
+** $Id: ldo.c,v 1.194 2002/09/02 20:00:41 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -420,12 +420,13 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
 */
 struct SParser {  /* data to `f_parser' */
   ZIO *z;
+  Mbuffer buff;  /* buffer to be used by the scanner */
   int bin;
 };
 
 static void f_parser (lua_State *L, void *ud) {
   struct SParser *p = cast(struct SParser *, ud);
-  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
+  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z, &p->buff);
   Closure *cl = luaF_newLclosure(L, 0, gt(L));
   cl->l.p = tf;
   setclvalue(L->top, cl);
@@ -439,11 +440,13 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
   int status;
   ptrdiff_t oldtopr = savestack(L, L->top);  /* save current top */
   p.z = z; p.bin = bin;
+  luaZ_initbuffer(L, &p.buff);
   /* before parsing, give a (good) chance to GC */
   if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
     luaC_collectgarbage(L);
   old_blocks = G(L)->nblocks;
   status = luaD_rawrunprotected(L, f_parser, &p);
+  luaZ_freebuffer(L, &p.buff);
   if (status == 0) {
     /* add new memory to threshold (as it probably will stay) */
     lua_assert(G(L)->nblocks >= old_blocks);

+ 4 - 6
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.150 2002/09/05 19:57:40 roberto Exp roberto $
+** $Id: lgc.c,v 1.151 2002/09/19 19:54:22 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -332,17 +332,15 @@ static void sweepstrings (lua_State *L, int all) {
 }
 
 
-#define MINBUFFER	256
 static void checkSizes (lua_State *L) {
   /* check size of string hash */
   if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
       G(L)->strt.size > MINSTRTABSIZE*2)
     luaS_resize(L, G(L)->strt.size/2);  /* table is too big */
   /* check size of buffer */
-  if (G(L)->Mbuffsize > MINBUFFER*2) {  /* is buffer too big? */
-    size_t newsize = G(L)->Mbuffsize/2;  /* still larger than MINBUFFER */
-    luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, newsize, char);
-    G(L)->Mbuffsize = newsize;
+  if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */
+    size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
+    luaZ_resizebuffer(L, &G(L)->buff, newsize);
   }
 }
 

+ 63 - 66
llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 1.111 2002/09/05 19:45:42 roberto Exp roberto $
+** $Id: llex.c,v 1.112 2002/09/19 13:03:53 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -100,7 +100,7 @@ static void luaX_lexerror (LexState *ls, const char *s, int token) {
   if (token == TK_EOS)
     luaX_error(ls, s, luaX_token2str(ls, token));
   else
-    luaX_error(ls, s, cast(char *, G(ls->L)->Mbuffer));
+    luaX_error(ls, s, luaZ_buffer(ls->buff));
 }
 
 
@@ -138,146 +138,143 @@ 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, len)	\
-    if (((len)+10)*sizeof(char) > G(L)->Mbuffsize) \
-      luaO_openspace(L, (len)+EXTRABUFF)
+#define EXTRABUFF	32
+#define checkbuffer(LS, len)	\
+    if (((len)+3)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
+      luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
 
-#define save(L, c, l)	(cast(char *, G(L)->Mbuffer)[l++] = cast(char, c))
-#define save_and_next(L, LS, l)  (save(L, LS->current, l), next(LS))
+#define save(LS, c, l) \
+	(cast(char *, luaZ_buffer((LS)->buff))[l++] = cast(char, c))
+#define save_and_next(LS, l)  (save(LS, LS->current, l), next(LS))
 
 
 static size_t readname (LexState *LS) {
-  lua_State *L = LS->L;
   size_t l = 0;
-  checkbuffer(L, l);
+  checkbuffer(LS, l);
   do {
-    checkbuffer(L, l);
-    save_and_next(L, LS, l);
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
   } while (isalnum(LS->current) || LS->current == '_');
-  save(L, '\0', l);
+  save(LS, '\0', l);
   return l-1;
 }
 
 
 /* LUA_NUMBER */
 static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
-  lua_State *L = LS->L;
   size_t l = 0;
-  checkbuffer(L, l);
-  if (comma) save(L, '.', l);
+  checkbuffer(LS, l);
+  if (comma) save(LS, '.', l);
   while (isdigit(LS->current)) {
-    checkbuffer(L, l);
-    save_and_next(L, LS, l);
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
   }
   if (LS->current == '.') {
-    save_and_next(L, LS, l);
+    save_and_next(LS, l);
     if (LS->current == '.') {
-      save_and_next(L, LS, l);
-      save(L, '\0', l);
+      save_and_next(LS, l);
+      save(LS, '\0', l);
       luaX_lexerror(LS,
                  "ambiguous syntax (decimal point x string concatenation)",
                  TK_NUMBER);
     }
   }
   while (isdigit(LS->current)) {
-    checkbuffer(L, l);
-    save_and_next(L, LS, l);
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
   }
   if (LS->current == 'e' || LS->current == 'E') {
-    save_and_next(L, LS, l);  /* read `E' */
+    save_and_next(LS, l);  /* read `E' */
     if (LS->current == '+' || LS->current == '-')
-      save_and_next(L, LS, l);  /* optional exponent sign */
+      save_and_next(LS, l);  /* optional exponent sign */
     while (isdigit(LS->current)) {
-      checkbuffer(L, l);
-      save_and_next(L, LS, l);
+      checkbuffer(LS, l);
+      save_and_next(LS, l);
     }
   }
-  save(L, '\0', l);
-  if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
+  save(LS, '\0', l);
+  if (!luaO_str2d(cast(char *, luaZ_buffer(LS->buff)), &seminfo->r))
     luaX_lexerror(LS, "malformed number", TK_NUMBER);
 }
 
 
 static void read_long_string (LexState *LS, SemInfo *seminfo) {
-  lua_State *L = LS->L;
   int cont = 0;
   size_t l = 0;
-  checkbuffer(L, l);
-  save(L, '[', l);  /* save first `[' */
-  save_and_next(L, LS, l);  /* pass the second `[' */
+  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(L, l);
+    checkbuffer(LS, l);
     switch (LS->current) {
       case EOZ:
-        save(L, '\0', l);
+        save(LS, '\0', l);
         luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
                                    "unfinished long comment", TK_EOS);
         break;  /* to avoid warnings */
       case '[':
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
         if (LS->current == '[') {
           cont++;
-          save_and_next(L, LS, l);
+          save_and_next(LS, l);
         }
         continue;
       case ']':
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
         if (LS->current == ']') {
           if (cont == 0) goto endloop;
           cont--;
-          save_and_next(L, LS, l);
+          save_and_next(LS, l);
         }
         continue;
       case '\n':
-        save(L, '\n', l);
+        save(LS, '\n', l);
         inclinenumber(LS);
         if (!seminfo) l = 0;  /* reset buffer to avoid wasting space */
         continue;
       default:
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
     }
   } endloop:
-  save_and_next(L, LS, l);  /* skip the second `]' */
-  save(L, '\0', l);
+  save_and_next(LS, l);  /* skip the second `]' */
+  save(LS, '\0', l);
   if (seminfo)
-    seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+2, l-5);
+    seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
 }
 
 
 static void read_string (LexState *LS, int del, SemInfo *seminfo) {
-  lua_State *L = LS->L;
   size_t l = 0;
-  checkbuffer(L, l);
-  save_and_next(L, LS, l);
+  checkbuffer(LS, l);
+  save_and_next(LS, l);
   while (LS->current != del) {
-    checkbuffer(L, l);
+    checkbuffer(LS, l);
     switch (LS->current) {
       case EOZ:
-        save(L, '\0', l);
+        save(LS, '\0', l);
         luaX_lexerror(LS, "unfinished string", TK_EOS);
         break;  /* to avoid warnings */
       case '\n':
-        save(L, '\0', l);
+        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(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 '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(L, LS, l);  /* handles \\, \", \', and \? */
+              save_and_next(LS, l);  /* handles \\, \", \', and \? */
             else {  /* \xxx */
               int c = 0;
               int i = 0;
@@ -286,21 +283,21 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
                 next(LS);
               } while (++i<3 && isdigit(LS->current));
               if (c > UCHAR_MAX) {
-                save(L, '\0', l);
+                save(LS, '\0', l);
                 luaX_lexerror(LS, "escape sequence too large", TK_STRING);
               }
-              save(L, c, l);
+              save(LS, c, l);
             }
           }
         }
         break;
       default:
-        save_and_next(L, LS, l);
+        save_and_next(LS, l);
     }
   }
-  save_and_next(L, LS, l);  /* skip delimiter */
-  save(L, '\0', l);
-  seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+1, l-3);
+  save_and_next(LS, l);  /* skip delimiter */
+  save(LS, '\0', l);
+  seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
 }
 
 
@@ -388,7 +385,7 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
         else if (isalpha(LS->current) || LS->current == '_') {
           /* identifier or reserved word */
           size_t l = readname(LS);
-          TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
+          TString *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;

+ 3 - 2
llex.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.43 2002/05/07 17:36:56 roberto Exp roberto $
+** $Id: llex.h,v 1.44 2002/09/03 11:57:38 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -56,7 +56,8 @@ typedef struct LexState {
   Token lookahead;  /* look ahead token */
   struct FuncState *fs;  /* `FuncState' is private to the parser */
   struct lua_State *L;
-  struct zio *z;  /* input stream */
+  ZIO *z;  /* input stream */
+  Mbuffer *buff;  /* buffer for tokens */
   TString *source;  /* current source name */
 } LexState;
 

+ 7 - 1
llimits.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.44 2002/06/13 13:45:31 roberto Exp roberto $
+** $Id: llimits.h,v 1.45 2002/07/08 20:22:08 roberto Exp roberto $
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
@@ -150,4 +150,10 @@ typedef unsigned long Instruction;
 #endif
 
 
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER	32
+#endif
+
+
 #endif

+ 1 - 10
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 1.88 2002/09/19 13:03:53 roberto Exp roberto $
+** $Id: lobject.c,v 1.89 2002/10/04 14:31:03 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -73,15 +73,6 @@ int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
 }
 
 
-char *luaO_openspace (lua_State *L, size_t n) {
-  if (n > G(L)->Mbuffsize) {
-    luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, n, char);
-    G(L)->Mbuffsize = n;
-  }
-  return G(L)->Mbuffer;
-}
-
-
 int luaO_str2d (const char *s, lua_Number *result) {
   char *endptr;
   lua_Number res = lua_str2number(s, &endptr);

+ 1 - 3
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.145 2002/09/02 19:54:49 roberto Exp roberto $
+** $Id: lobject.h,v 1.146 2002/09/19 13:03:53 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -316,8 +316,6 @@ extern const TObject luaO_nilobject;
 int luaO_log2 (unsigned int x);
 
 
-char *luaO_openspace (lua_State *L, size_t n);
-
 int luaO_rawequalObj (const TObject *t1, const TObject *t2);
 int luaO_str2d (const char *s, lua_Number *result);
 

+ 3 - 2
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.193 2002/08/22 19:51:08 roberto Exp roberto $
+** $Id: lparser.c,v 1.194 2002/08/30 19:09:21 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -351,9 +351,10 @@ static void close_func (LexState *ls) {
 }
 
 
-Proto *luaY_parser (lua_State *L, ZIO *z) {
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
   struct LexState lexstate;
   struct FuncState funcstate;
+  lexstate.buff = buff;
   luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
   open_func(&lexstate, &funcstate);
   next(&lexstate);  /* read first token */

+ 2 - 2
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
+** $Id: lparser.h,v 1.44 2002/05/14 17:52:22 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -65,7 +65,7 @@ typedef struct FuncState {
 } FuncState;
 
 
-Proto *luaY_parser (lua_State *L, ZIO *z);
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
 
 
 #endif

+ 3 - 4
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.104 2002/08/16 20:00:28 roberto Exp roberto $
+** $Id: lstate.c,v 1.105 2002/08/30 19:09:21 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -61,8 +61,7 @@ static void f_luaopen (lua_State *L, void *ud) {
   G(L)->strt.size = 0;
   G(L)->strt.nuse = 0;
   G(L)->strt.hash = NULL;
-  G(L)->Mbuffer = NULL;
-  G(L)->Mbuffsize = 0;
+  luaZ_initbuffer(L, &G(L)->buff);
   G(L)->panic = &default_panic;
   G(L)->rootgc = NULL;
   G(L)->rootudata = NULL;
@@ -160,7 +159,7 @@ static void close_state (lua_State *L) {
     lua_assert(G(L)->rootgc == NULL);
     lua_assert(G(L)->rootudata == NULL);
     luaS_freeall(L);
-    luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
+    luaZ_freebuffer(L, &G(L)->buff);
     luaM_freelem(NULL, L->l_G);
   }
   luaE_closethread(NULL, L);

+ 3 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.95 2002/08/30 19:09:21 roberto Exp roberto $
+** $Id: lstate.h,v 1.96 2002/09/19 13:03:53 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -11,6 +11,7 @@
 
 #include "lobject.h"
 #include "ltm.h"
+#include "lzio.h"
 
 
 /*
@@ -124,8 +125,7 @@ typedef struct global_State {
   GCObject *rootgc;  /* list of (almost) all collectable objects */
   GCObject *rootudata;   /* (separated) list of all userdata */
   GCObject *tmudata;  /* list of userdata to be GC */
-  char *Mbuffer;  /* global buffer */
-  size_t Mbuffsize;  /* size of Mbuffer */
+  Mbuffer buff;  /* temporary buffer for string concatentation */
   lu_mem GCthreshold;
   lu_mem nblocks;  /* number of `bytes' currently allocated */
   lua_CFunction panic;  /* to be called in unprotected errors */

+ 2 - 2
lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.52 2002/08/12 13:37:19 roberto Exp roberto $
+** $Id: lundump.c,v 1.53 2002/09/19 13:03:53 roberto Exp roberto $
 ** load pre-compiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -99,7 +99,7 @@ static TString* LoadString (LoadState* S)
   return NULL;
  else
  {
-  char* s=luaO_openspace(S->L,size);
+  char* s=luaZ_openspace(S->L,&G(S->L)->buff,size);
   ezread(S,s,size);
   return luaS_newlstr(S->L,s,size-1);	/* remove trailing '\0' */
  }

+ 2 - 2
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.255 2002/09/19 13:03:53 roberto Exp roberto $
+** $Id: lvm.c,v 1.256 2002/09/19 20:12:47 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -303,7 +303,7 @@ void luaV_concat (lua_State *L, int total, int last) {
         n++;
       }
       if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
-      buffer = luaO_openspace(L, 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)->tsv.len;

+ 13 - 2
lzio.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.c,v 1.20 2002/08/05 18:45:02 roberto Exp roberto $
+** $Id: lzio.c,v 1.21 2002/08/06 17:26:45 roberto Exp roberto $
 ** a generic input stream interface
 ** See Copyright Notice in lua.h
 */
@@ -10,10 +10,10 @@
 #include "lua.h"
 
 #include "llimits.h"
+#include "lmem.h"
 #include "lzio.h"
 
 
-
 int luaZ_fill (ZIO *z) {
   size_t size;
   const char *buff = z->reader(NULL, z->data, &size);
@@ -66,3 +66,14 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
   return 0;
 }
 
+/* ------------------------------------------------------------------------ */
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+  if (n > buff->buffsize) {
+    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+    luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
+    buff->buffsize = n;
+  }
+  return buff->buffer;
+}
+
+

+ 24 - 3
lzio.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.h,v 1.12 2002/06/06 12:40:22 roberto Exp roberto $
+** $Id: lzio.h,v 1.13 2002/08/05 18:45:02 roberto Exp roberto $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
@@ -13,7 +13,7 @@
 
 #define EOZ	(-1)			/* end of stream */
 
-typedef struct zio ZIO;
+typedef struct Zio ZIO;
 
 #define zgetc(z)  (((z)->n--)>0 ? \
 			cast(int, cast(unsigned char, *(z)->p++)) : \
@@ -26,9 +26,30 @@ size_t luaZ_read (ZIO* z, void* b, size_t n);	/* read next n bytes */
 int luaZ_lookahead (ZIO *z);
 
 
+
+typedef struct Mbuffer {
+  char *buffer;
+  size_t buffsize;
+} Mbuffer;
+
+
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
+
+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define luaZ_sizebuffer(buff)	((buff)->buffsize)
+#define luaZ_buffer(buff)	((buff)->buffer)
+
+#define luaZ_resizebuffer(L, buff, size) \
+	(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+	(buff)->buffsize = size)
+
+#define luaZ_freebuffer(L, buff)	luaZ_resizebuffer(L, buff, 0)
+
+
 /* --------- Private Part ------------------ */
 
-struct zio {
+struct Zio {
   size_t n;			/* bytes still unread */
   const char *p;		/* current position in buffer */
   lua_Chunkreader reader;