aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-03-06 13:54:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-03-06 13:54:42 -0300
commit88a2023c3285c4514519158fba90e644fc6ffca3 (patch)
treeda6611257545c486ff856dd48d66d94e056f3d66
parent5ef1989c4b05aff8362a7ea6ba62aad76d4a040d (diff)
downloadlua-88a2023c3285c4514519158fba90e644fc6ffca3.tar.gz
lua-88a2023c3285c4514519158fba90e644fc6ffca3.tar.bz2
lua-88a2023c3285c4514519158fba90e644fc6ffca3.zip
support for strings with '\0'
-rw-r--r--lapi.c30
-rw-r--r--lauxlib.c9
-rw-r--r--lauxlib.h9
-rw-r--r--lbuffer.c6
-rw-r--r--lbuiltin.c25
-rw-r--r--lgc.c6
-rw-r--r--liolib.c30
-rw-r--r--llex.c6
-rw-r--r--lobject.h9
-rw-r--r--lstring.c116
-rw-r--r--lstring.h3
-rw-r--r--lstrlib.c98
-rw-r--r--lua.h4
-rw-r--r--lvm.c41
14 files changed, 236 insertions, 156 deletions
diff --git a/lapi.c b/lapi.c
index 8528dd65..5f1a81ba 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.20 1998/01/27 19:13:45 roberto Exp roberto $ 2** $Id: lapi.c,v 1.21 1998/02/12 19:23:32 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -219,7 +219,7 @@ lua_Object lua_getglobal (char *name)
219lua_Object lua_rawgetglobal (char *name) 219lua_Object lua_rawgetglobal (char *name)
220{ 220{
221 TaggedString *ts = luaS_new(name); 221 TaggedString *ts = luaS_new(name);
222 return put_luaObject(&ts->u.globalval); 222 return put_luaObject(&ts->u.s.globalval);
223} 223}
224 224
225 225
@@ -293,6 +293,14 @@ char *lua_getstring (lua_Object object)
293 else return (svalue(Address(object))); 293 else return (svalue(Address(object)));
294} 294}
295 295
296long lua_getstrlen (lua_Object object)
297{
298 luaC_checkGC(); /* "tostring" may create a new string */
299 if (object == LUA_NOOBJECT || tostring(Address(object)))
300 return 0L;
301 else return (tsvalue(Address(object))->u.s.len);
302}
303
296void *lua_getuserdata (lua_Object object) 304void *lua_getuserdata (lua_Object object)
297{ 305{
298 if (object == LUA_NOOBJECT || ttype(Address(object)) != LUA_T_USERDATA) 306 if (object == LUA_NOOBJECT || ttype(Address(object)) != LUA_T_USERDATA)
@@ -321,18 +329,22 @@ void lua_pushnumber (double n)
321 incr_top; 329 incr_top;
322} 330}
323 331
324void lua_pushstring (char *s) 332void lua_pushlstr (char *s, long len)
325{ 333{
326 if (s == NULL) 334 tsvalue(L->stack.top) = luaS_newlstr(s, len);
327 ttype(L->stack.top) = LUA_T_NIL; 335 ttype(L->stack.top) = LUA_T_STRING;
328 else {
329 tsvalue(L->stack.top) = luaS_new(s);
330 ttype(L->stack.top) = LUA_T_STRING;
331 }
332 incr_top; 336 incr_top;
333 luaC_checkGC(); 337 luaC_checkGC();
334} 338}
335 339
340void lua_pushstring (char *s)
341{
342 if (s == NULL)
343 lua_pushnil();
344 else
345 lua_pushlstr(s, strlen(s));
346}
347
336void lua_pushCclosure (lua_CFunction fn, int n) 348void lua_pushCclosure (lua_CFunction fn, int n)
337{ 349{
338 if (fn == NULL) 350 if (fn == NULL)
diff --git a/lauxlib.c b/lauxlib.c
index 6de9c2bf..f94c9836 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.8 1998/01/09 15:06:07 roberto Exp $ 2** $Id: lauxlib.c,v 1.8 1998/01/09 15:09:53 roberto Exp roberto $
3** Auxiliar functions for building Lua libraries 3** Auxiliar functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -31,17 +31,18 @@ void luaL_argerror (int numarg, char *extramsg)
31 numarg, funcname, extramsg); 31 numarg, funcname, extramsg);
32} 32}
33 33
34char *luaL_check_string (int numArg) 34char *luaL_check_lstr (int numArg, long *len)
35{ 35{
36 lua_Object o = lua_getparam(numArg); 36 lua_Object o = lua_getparam(numArg);
37 luaL_arg_check(lua_isstring(o), numArg, "string expected"); 37 luaL_arg_check(lua_isstring(o), numArg, "string expected");
38 if (len) *len = lua_getstrlen(o);
38 return lua_getstring(o); 39 return lua_getstring(o);
39} 40}
40 41
41char *luaL_opt_string (int numArg, char *def) 42char *luaL_opt_lstr (int numArg, char *def, long *len)
42{ 43{
43 return (lua_getparam(numArg) == LUA_NOOBJECT) ? def : 44 return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
44 luaL_check_string(numArg); 45 luaL_check_lstr(numArg, len);
45} 46}
46 47
47double luaL_check_number (int numArg) 48double luaL_check_number (int numArg)
diff --git a/lauxlib.h b/lauxlib.h
index 4fe65c99..0e150d25 100644
--- a/lauxlib.h
+++ b/lauxlib.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.h,v 1.5 1997/12/17 20:48:58 roberto Exp roberto $ 2** $Id: lauxlib.h,v 1.6 1998/01/09 15:06:07 roberto Exp roberto $
3** Auxiliar functions for building Lua libraries 3** Auxiliar functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -23,8 +23,10 @@ struct luaL_reg {
23 23
24void luaL_openlib (struct luaL_reg *l, int n); 24void luaL_openlib (struct luaL_reg *l, int n);
25void luaL_argerror (int numarg, char *extramsg); 25void luaL_argerror (int numarg, char *extramsg);
26char *luaL_check_string (int numArg); 26#define luaL_check_string(n) (luaL_check_lstr((n), NULL))
27char *luaL_opt_string (int numArg, char *def); 27char *luaL_check_lstr (int numArg, long *len);
28#define luaL_opt_string(n, d) (luaL_opt_lstr((n), (d), NULL))
29char *luaL_opt_lstr (int numArg, char *def, long *len);
28double luaL_check_number (int numArg); 30double luaL_check_number (int numArg);
29double luaL_opt_number (int numArg, double def); 31double luaL_opt_number (int numArg, double def);
30lua_Object luaL_functionarg (int arg); 32lua_Object luaL_functionarg (int arg);
@@ -34,6 +36,7 @@ void luaL_verror (char *fmt, ...);
34char *luaL_openspace (int size); 36char *luaL_openspace (int size);
35void luaL_resetbuffer (void); 37void luaL_resetbuffer (void);
36void luaL_addchar (int c); 38void luaL_addchar (int c);
39int luaL_getsize (void);
37void luaL_addsize (int n); 40void luaL_addsize (int n);
38int luaL_newbuffer (int size); 41int luaL_newbuffer (int size);
39void luaL_oldbuffer (int old); 42void luaL_oldbuffer (int old);
diff --git a/lbuffer.c b/lbuffer.c
index 04820736..d5aa8c98 100644
--- a/lbuffer.c
+++ b/lbuffer.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: $ 2** $Id: lbuffer.c,v 1.1 1997/12/23 19:24:36 roberto Exp roberto $
3** Auxiliar functions for building Lua libraries 3** Auxiliar functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -57,6 +57,10 @@ void luaL_addsize (int n)
57 L->Mbuffnext += n; 57 L->Mbuffnext += n;
58} 58}
59 59
60int luaL_getsize (void)
61{
62 return L->Mbuffnext-(L->Mbuffbase-L->Mbuffer);
63}
60 64
61int luaL_newbuffer (int size) 65int luaL_newbuffer (int size)
62{ 66{
diff --git a/lbuiltin.c b/lbuiltin.c
index 1d26b86e..683bbd9b 100644
--- a/lbuiltin.c
+++ b/lbuiltin.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbuiltin.c,v 1.24 1998/02/12 19:23:32 roberto Exp roberto $ 2** $Id: lbuiltin.c,v 1.25 1998/02/12 19:27:10 roberto Exp roberto $
3** Built-in functions 3** Built-in functions
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -47,11 +47,11 @@ static void nextvar (void)
47 luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected"); 47 luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected");
48 g = (TaggedString *)g->head.next; 48 g = (TaggedString *)g->head.next;
49 } 49 }
50 while (g && g->u.globalval.ttype == LUA_T_NIL) /* skip globals with nil */ 50 while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */
51 g = (TaggedString *)g->head.next; 51 g = (TaggedString *)g->head.next;
52 if (g) { 52 if (g) {
53 pushstring(g); 53 pushstring(g);
54 luaA_pushobject(&g->u.globalval); 54 luaA_pushobject(&g->u.s.globalval);
55 } 55 }
56} 56}
57 57
@@ -65,12 +65,12 @@ static void foreachvar (void)
65 L->stack.top++; 65 L->stack.top++;
66 for (g = L->rootglobal.next; g; g = g->next) { 66 for (g = L->rootglobal.next; g; g = g->next) {
67 TaggedString *s = (TaggedString *)g; 67 TaggedString *s = (TaggedString *)g;
68 if (s->u.globalval.ttype != LUA_T_NIL) { 68 if (s->u.s.globalval.ttype != LUA_T_NIL) {
69 ttype(L->stack.stack+name) = LUA_T_STRING; 69 ttype(L->stack.stack+name) = LUA_T_STRING;
70 tsvalue(L->stack.stack+name) = s; /* keep s on stack to avoid GC */ 70 tsvalue(L->stack.stack+name) = s; /* keep s on stack to avoid GC */
71 luaA_pushobject(&f); 71 luaA_pushobject(&f);
72 pushstring(s); 72 pushstring(s);
73 luaA_pushobject(&s->u.globalval); 73 luaA_pushobject(&s->u.s.globalval);
74 luaD_call((L->stack.top-L->stack.stack)-2, 1); 74 luaD_call((L->stack.top-L->stack.stack)-2, 1);
75 if (ttype(L->stack.top-1) != LUA_T_NIL) 75 if (ttype(L->stack.top-1) != LUA_T_NIL)
76 return; 76 return;
@@ -331,22 +331,17 @@ static void copytagmethods (void)
331 331
332static void rawgettable (void) 332static void rawgettable (void)
333{ 333{
334 lua_Object t = luaL_nonnullarg(1); 334 lua_pushobject(luaL_nonnullarg(1));
335 lua_Object i = luaL_nonnullarg(2); 335 lua_pushobject(luaL_nonnullarg(2));
336 lua_pushobject(t);
337 lua_pushobject(i);
338 lua_pushobject(lua_rawgettable()); 336 lua_pushobject(lua_rawgettable());
339} 337}
340 338
341 339
342static void rawsettable (void) 340static void rawsettable (void)
343{ 341{
344 lua_Object t = luaL_nonnullarg(1); 342 lua_pushobject(luaL_nonnullarg(1));
345 lua_Object i = luaL_nonnullarg(2); 343 lua_pushobject(luaL_nonnullarg(2));
346 lua_Object v = luaL_nonnullarg(3); 344 lua_pushobject(luaL_nonnullarg(3));
347 lua_pushobject(t);
348 lua_pushobject(i);
349 lua_pushobject(v);
350 lua_rawsettable(); 345 lua_rawsettable();
351} 346}
352 347
diff --git a/lgc.c b/lgc.c
index 21550bb7..14b6bceb 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.15 1998/01/09 14:44:55 roberto Exp roberto $ 2** $Id: lgc.c,v 1.16 1998/01/19 19:49:22 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -213,8 +213,8 @@ static void globalmark (void)
213{ 213{
214 TaggedString *g; 214 TaggedString *g;
215 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) 215 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next)
216 if (g->u.globalval.ttype != LUA_T_NIL) { 216 if (g->u.s.globalval.ttype != LUA_T_NIL) {
217 markobject(&g->u.globalval); 217 markobject(&g->u.s.globalval);
218 strmark(g); /* cannot collect non nil global variables */ 218 strmark(g); /* cannot collect non nil global variables */
219 } 219 }
220} 220}
diff --git a/liolib.c b/liolib.c
index 9ed3e8d8..260625bb 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: liolib.c,v 1.13 1997/12/26 18:38:16 roberto Exp roberto $ 2** $Id: liolib.c,v 1.14 1998/01/07 16:26:48 roberto Exp roberto $
3** Standard I/O (and system) library 3** Standard I/O (and system) library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -184,7 +184,7 @@ static void io_read (void)
184{ 184{
185 int arg = FIRSTARG; 185 int arg = FIRSTARG;
186 FILE *f = getfileparam(FINPUT, &arg); 186 FILE *f = getfileparam(FINPUT, &arg);
187 char *buff; 187 int l;
188 char *p = luaL_opt_string(arg, "[^\n]*{\n}"); 188 char *p = luaL_opt_string(arg, "[^\n]*{\n}");
189 int inskip = 0; /* to control {skips} */ 189 int inskip = 0; /* to control {skips} */
190 int c = NEED_OTHER; 190 int c = NEED_OTHER;
@@ -204,10 +204,16 @@ static void io_read (void)
204 char *ep; /* get what is next */ 204 char *ep; /* get what is next */
205 int m; /* match result */ 205 int m; /* match result */
206 if (c == NEED_OTHER) c = getc(f); 206 if (c == NEED_OTHER) c = getc(f);
207 m = luaI_singlematch((c == EOF) ? 0 : (char)c, p, &ep); 207 if (c == EOF) {
208 if (m) { 208 luaI_singlematch(0, p, &ep); /* to set "ep" */
209 if (inskip == 0) luaL_addchar(c); 209 m = 0;
210 c = NEED_OTHER; 210 }
211 else {
212 m = luaI_singlematch((char)c, p, &ep);
213 if (m) {
214 if (inskip == 0) luaL_addchar(c);
215 c = NEED_OTHER;
216 }
211 } 217 }
212 switch (*ep) { 218 switch (*ep) {
213 case '*': /* repetition */ 219 case '*': /* repetition */
@@ -225,10 +231,9 @@ static void io_read (void)
225 } break_while: 231 } break_while:
226 if (c >= 0) /* not EOF nor NEED_OTHER? */ 232 if (c >= 0) /* not EOF nor NEED_OTHER? */
227 ungetc(c, f); 233 ungetc(c, f);
228 luaL_addchar(0); 234 l = luaL_getsize();
229 buff = luaL_buffer(); 235 if (l > 0 || *p == 0) /* read something or did not fail? */
230 if (*buff != 0 || *p == 0) /* read something or did not fail? */ 236 lua_pushlstr(luaL_buffer(), l);
231 lua_pushstring(buff);
232} 237}
233 238
234 239
@@ -238,8 +243,9 @@ static void io_write (void)
238 FILE *f = getfileparam(FOUTPUT, &arg); 243 FILE *f = getfileparam(FOUTPUT, &arg);
239 int status = 1; 244 int status = 1;
240 char *s; 245 char *s;
241 while ((s = luaL_opt_string(arg++, NULL)) != NULL) 246 long l;
242 status = status && (fputs(s, f) != EOF); 247 while ((s = luaL_opt_lstr(arg++, NULL, &l)) != NULL)
248 status = status && (fwrite(s, 1, l, f) == l);
243 pushresult(status); 249 pushresult(status);
244} 250}
245 251
diff --git a/llex.c b/llex.c
index ef023c3f..5cc90045 100644
--- a/llex.c
+++ b/llex.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llex.c,v 1.14 1998/01/19 20:18:02 roberto Exp roberto $ 2** $Id: llex.c,v 1.15 1998/02/11 20:56:46 roberto Exp roberto $
3** Lexical Analizer 3** Lexical Analizer
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -358,8 +358,8 @@ int luaY_lex (YYSTYPE *l)
358 } 358 }
359 } 359 }
360 next(LS); /* skip delimiter */ 360 next(LS); /* skip delimiter */
361 save(0); 361 l->pTStr = luaS_newlstr(L->Mbuffbase+1,
362 l->pTStr = luaS_new(L->Mbuffbase+1); 362 L->Mbuffnext-((L->Mbuffbase+1)-L->Mbuffer));
363 L->Mbuffer[L->Mbuffnext-1] = del; /* restore delimiter */ 363 L->Mbuffer[L->Mbuffnext-1] = del; /* restore delimiter */
364 return STRING; 364 return STRING;
365 } 365 }
diff --git a/lobject.h b/lobject.h
index 9e1f94d5..9177f03c 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.15 1998/01/14 13:48:28 roberto Exp roberto $ 2** $Id: lobject.h,v 1.16 1998/01/19 19:49:22 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -95,10 +95,13 @@ typedef struct GCnode {
95 95
96typedef struct TaggedString { 96typedef struct TaggedString {
97 GCnode head; 97 GCnode head;
98 int constindex; /* hint to reuse constants (= -1 if this is a userdata) */
99 unsigned long hash; 98 unsigned long hash;
99 int constindex; /* hint to reuse constants (= -1 if this is a userdata) */
100 union { 100 union {
101 TObject globalval; 101 struct {
102 TObject globalval;
103 long len; /* if this is a string, here is its length */
104 } s;
102 struct { 105 struct {
103 int tag; 106 int tag;
104 void *v; /* if this is a userdata, here is its value */ 107 void *v; /* if this is a userdata, here is its value */
diff --git a/lstring.c b/lstring.c
index a6e0ca4e..f18d2ff2 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.c,v 1.10 1998/01/13 18:06:27 roberto Exp roberto $ 2** $Id: lstring.c,v 1.11 1998/01/28 16:50:33 roberto Exp roberto $
3** String table (keeps all strings handled by Lua) 3** String table (keeps all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -21,7 +21,8 @@
21 21
22 22
23 23
24static TaggedString EMPTY = {{NULL, 2}, 0, 0L, {{LUA_T_NIL, {NULL}}}, {0}}; 24static TaggedString EMPTY = {{NULL, 2}, 0L, 0,
25 {{{LUA_T_NIL, {NULL}}, 0L}}, {0}};
25 26
26 27
27void luaS_init (void) 28void luaS_init (void)
@@ -36,20 +37,14 @@ void luaS_init (void)
36} 37}
37 38
38 39
39static unsigned long hash (char *s, int tag) 40static unsigned long hash_s (char *s, long l)
40{ 41{
41 unsigned long h; 42 unsigned long h = 0;
42 if (tag != LUA_T_STRING) 43 while (l--)
43 h = (unsigned long)s; 44 h = ((h<<5)-h)^(unsigned char)*(s++);
44 else {
45 h = 0;
46 while (*s)
47 h = ((h<<5)-h)^(unsigned char)*(s++);
48 }
49 return h; 45 return h;
50} 46}
51 47
52
53static int newsize (stringtable *tb) 48static int newsize (stringtable *tb)
54{ 49{
55 int size = tb->size; 50 int size = tb->size;
@@ -91,34 +86,67 @@ static void grow (stringtable *tb)
91} 86}
92 87
93 88
94static TaggedString *newone (char *buff, int tag, unsigned long h) 89static TaggedString *newone_s (char *str, long l, unsigned long h)
95{ 90{
96 TaggedString *ts; 91 TaggedString *ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l);
97 if (tag == LUA_T_STRING) { 92 memcpy(ts->str, str, l);
98 long l = strlen(buff); 93 ts->str[l] = 0; /* ending 0 */
99 ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l); 94 ts->u.s.globalval.ttype = LUA_T_NIL; /* initialize global value */
100 strcpy(ts->str, buff); 95 ts->u.s.len = l;
101 ts->u.globalval.ttype = LUA_T_NIL; /* initialize global value */ 96 ts->constindex = 0;
102 ts->constindex = 0; 97 L->nblocks += gcsizestring(l);
103 L->nblocks += gcsizestring(l);
104 }
105 else {
106 ts = luaM_new(TaggedString);
107 ts->u.d.v = buff;
108 ts->u.d.tag = tag == LUA_ANYTAG ? 0 : tag;
109 ts->constindex = -1; /* tag -> this is a userdata */
110 L->nblocks++;
111 }
112 ts->head.marked = 0; 98 ts->head.marked = 0;
113 ts->head.next = (GCnode *)ts; /* signal it is in no list */ 99 ts->head.next = (GCnode *)ts; /* signal it is in no list */
114 ts->hash = h; 100 ts->hash = h;
115 return ts; 101 return ts;
116} 102}
117 103
118static TaggedString *insert (char *buff, int tag, stringtable *tb) 104static TaggedString *newone_u (char *buff, int tag, unsigned long h)
105{
106 TaggedString *ts = luaM_new(TaggedString);
107 ts->u.d.v = buff;
108 ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
109 ts->constindex = -1; /* tag -> this is a userdata */
110 L->nblocks++;
111 ts->head.marked = 0;
112 ts->head.next = (GCnode *)ts; /* signal it is in no list */
113 ts->hash = h;
114 return ts;
115}
116
117static TaggedString *insert_s (char *str, long l, stringtable *tb)
118{
119 TaggedString *ts;
120 unsigned long h = hash_s(str, l);
121 int size = tb->size;
122 int i;
123 int j = -1;
124 if ((long)tb->nuse*3 >= (long)size*2) {
125 grow(tb);
126 size = tb->size;
127 }
128 for (i = h%size; (ts = tb->hash[i]) != NULL; ) {
129 if (ts == &EMPTY)
130 j = i;
131 else if (ts->constindex >= 0 &&
132 ts->u.s.len == l &&
133 (memcmp(str, ts->str, l) == 0))
134 return ts;
135 if (++i == size) i=0;
136 }
137 /* not found */
138 if (j != -1) /* is there an EMPTY space? */
139 i = j;
140 else
141 tb->nuse++;
142 ts = tb->hash[i] = newone_s(str, l, h);
143 return ts;
144}
145
146static TaggedString *insert_u (void *buff, int tag, stringtable *tb)
119{ 147{
120 TaggedString *ts; 148 TaggedString *ts;
121 unsigned long h = hash(buff, tag); 149 unsigned long h = (unsigned long)buff;
122 int size = tb->size; 150 int size = tb->size;
123 int i; 151 int i;
124 int j = -1; 152 int j = -1;
@@ -129,9 +157,9 @@ static TaggedString *insert (char *buff, int tag, stringtable *tb)
129 for (i = h%size; (ts = tb->hash[i]) != NULL; ) { 157 for (i = h%size; (ts = tb->hash[i]) != NULL; ) {
130 if (ts == &EMPTY) 158 if (ts == &EMPTY)
131 j = i; 159 j = i;
132 else if ((ts->constindex >= 0) ? /* is a string? */ 160 else if (ts->constindex < 0 && /* is a udata? */
133 (tag == LUA_T_STRING && (strcmp(buff, ts->str) == 0)) : 161 (tag == ts->u.d.tag || tag == LUA_ANYTAG) &&
134 ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v)) 162 buff == ts->u.d.v)
135 return ts; 163 return ts;
136 if (++i == size) i=0; 164 if (++i == size) i=0;
137 } 165 }
@@ -140,18 +168,24 @@ static TaggedString *insert (char *buff, int tag, stringtable *tb)
140 i = j; 168 i = j;
141 else 169 else
142 tb->nuse++; 170 tb->nuse++;
143 ts = tb->hash[i] = newone(buff, tag, h); 171 ts = tb->hash[i] = newone_u(buff, tag, h);
144 return ts; 172 return ts;
145} 173}
146 174
147TaggedString *luaS_createudata (void *udata, int tag) 175TaggedString *luaS_createudata (void *udata, int tag)
148{ 176{
149 return insert(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]); 177 return insert_u(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]);
178}
179
180TaggedString *luaS_newlstr (char *str, long l)
181{
182 int i = (l==0)?0:(unsigned char)str[0];
183 return insert_s(str, l, &L->string_root[i%NUM_HASHS]);
150} 184}
151 185
152TaggedString *luaS_new (char *str) 186TaggedString *luaS_new (char *str)
153{ 187{
154 return insert(str, LUA_T_STRING, &L->string_root[(unsigned)str[0]%NUM_HASHS]); 188 return luaS_newlstr(str, strlen(str));
155} 189}
156 190
157TaggedString *luaS_newfixedstring (char *str) 191TaggedString *luaS_newfixedstring (char *str)
@@ -167,7 +201,7 @@ void luaS_free (TaggedString *l)
167{ 201{
168 while (l) { 202 while (l) {
169 TaggedString *next = (TaggedString *)l->head.next; 203 TaggedString *next = (TaggedString *)l->head.next;
170 L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(strlen(l->str)); 204 L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len);
171 luaM_free(l); 205 luaM_free(l);
172 l = next; 206 l = next;
173 } 207 }
@@ -253,7 +287,7 @@ void luaS_freeall (void)
253 287
254void luaS_rawsetglobal (TaggedString *ts, TObject *newval) 288void luaS_rawsetglobal (TaggedString *ts, TObject *newval)
255{ 289{
256 ts->u.globalval = *newval; 290 ts->u.s.globalval = *newval;
257 if (ts->head.next == (GCnode *)ts) { /* is not in list? */ 291 if (ts->head.next == (GCnode *)ts) { /* is not in list? */
258 ts->head.next = L->rootglobal.next; 292 ts->head.next = L->rootglobal.next;
259 L->rootglobal.next = (GCnode *)ts; 293 L->rootglobal.next = (GCnode *)ts;
@@ -265,7 +299,7 @@ char *luaS_travsymbol (int (*fn)(TObject *))
265{ 299{
266 TaggedString *g; 300 TaggedString *g;
267 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) 301 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next)
268 if (fn(&g->u.globalval)) 302 if (fn(&g->u.s.globalval))
269 return g->str; 303 return g->str;
270 return NULL; 304 return NULL;
271} 305}
@@ -274,6 +308,6 @@ char *luaS_travsymbol (int (*fn)(TObject *))
274int luaS_globaldefined (char *name) 308int luaS_globaldefined (char *name)
275{ 309{
276 TaggedString *ts = luaS_new(name); 310 TaggedString *ts = luaS_new(name);
277 return ts->u.globalval.ttype != LUA_T_NIL; 311 return ts->u.s.globalval.ttype != LUA_T_NIL;
278} 312}
279 313
diff --git a/lstring.h b/lstring.h
index 5f8d01f4..82cdbabb 100644
--- a/lstring.h
+++ b/lstring.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.h,v 1.5 1997/11/26 18:53:45 roberto Exp roberto $ 2** $Id: lstring.h,v 1.6 1997/12/01 20:31:25 roberto Exp roberto $
3** String table (keep all strings handled by Lua) 3** String table (keep all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -15,6 +15,7 @@ void luaS_init (void);
15TaggedString *luaS_createudata (void *udata, int tag); 15TaggedString *luaS_createudata (void *udata, int tag);
16TaggedString *luaS_collector (void); 16TaggedString *luaS_collector (void);
17void luaS_free (TaggedString *l); 17void luaS_free (TaggedString *l);
18TaggedString *luaS_newlstr (char *str, long l);
18TaggedString *luaS_new (char *str); 19TaggedString *luaS_new (char *str);
19TaggedString *luaS_newfixedstring (char *str); 20TaggedString *luaS_newfixedstring (char *str);
20void luaS_rawsetglobal (TaggedString *ts, TObject *newval); 21void luaS_rawsetglobal (TaggedString *ts, TObject *newval);
diff --git a/lstrlib.c b/lstrlib.c
index a1b061ed..8ddf6428 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.7 1998/01/09 14:57:43 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.8 1998/01/27 19:11:36 roberto Exp roberto $
3** Standard library for strings and pattern-matching 3** Standard library for strings and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -19,83 +19,86 @@
19static void addnchar (char *s, int n) 19static void addnchar (char *s, int n)
20{ 20{
21 char *b = luaL_openspace(n); 21 char *b = luaL_openspace(n);
22 strncpy(b, s, n); 22 memcpy(b, s, n);
23 luaL_addsize(n); 23 luaL_addsize(n);
24} 24}
25 25
26 26
27static void addstr (char *s) 27static void str_len (void)
28{ 28{
29 addnchar(s, strlen(s)); 29 long l;
30 luaL_check_lstr(1, &l);
31 lua_pushnumber(l);
30} 32}
31 33
32 34
33static void str_len (void) 35static void closeandpush (void)
34{ 36{
35 lua_pushnumber(strlen(luaL_check_string(1))); 37 lua_pushlstr(luaL_buffer(), luaL_getsize());
36} 38}
37 39
38 40
39static void closeandpush (void) 41static long posrelat (long pos, long len)
40{ 42{
41 luaL_addchar(0); 43 /* relative string position: negative means back from end */
42 lua_pushstring(luaL_buffer()); 44 return (pos>=0) ? pos : len+pos+1;
43} 45}
44 46
45 47
46static void str_sub (void) 48static void str_sub (void)
47{ 49{
48 char *s = luaL_check_string(1); 50 long l;
49 long l = strlen(s); 51 char *s = luaL_check_lstr(1, &l);
50 long start = (long)luaL_check_number(2); 52 long start = posrelat(luaL_check_number(2), l);
51 long end = (long)luaL_opt_number(3, -1); 53 long end = posrelat(luaL_opt_number(3, -1), l);
52 if (start < 0) start = l+start+1; 54 if (1 <= start && start <= end && end <= l)
53 if (end < 0) end = l+end+1; 55 lua_pushlstr(s+start-1, end-start+1);
54 if (1 <= start && start <= end && end <= l) {
55 luaL_resetbuffer();
56 addnchar(s+start-1, end-start+1);
57 closeandpush();
58 }
59 else lua_pushstring(""); 56 else lua_pushstring("");
60} 57}
61 58
62 59
63static void str_lower (void) 60static void str_lower (void)
64{ 61{
65 char *s; 62 long l;
63 int i;
64 char *s = luaL_check_lstr(1, &l);
66 luaL_resetbuffer(); 65 luaL_resetbuffer();
67 for (s = luaL_check_string(1); *s; s++) 66 for (i=0; i<l; i++)
68 luaL_addchar(tolower((unsigned char)*s)); 67 luaL_addchar(tolower((unsigned char)(s[i])));
69 closeandpush(); 68 closeandpush();
70} 69}
71 70
72 71
73static void str_upper (void) 72static void str_upper (void)
74{ 73{
75 char *s; 74 long l;
75 int i;
76 char *s = luaL_check_lstr(1, &l);
76 luaL_resetbuffer(); 77 luaL_resetbuffer();
77 for (s = luaL_check_string(1); *s; s++) 78 for (i=0; i<l; i++)
78 luaL_addchar(toupper((unsigned char)*s)); 79 luaL_addchar(toupper((unsigned char)(s[i])));
79 closeandpush(); 80 closeandpush();
80} 81}
81 82
82static void str_rep (void) 83static void str_rep (void)
83{ 84{
84 char *s = luaL_check_string(1); 85 long l;
86 char *s = luaL_check_lstr(1, &l);
85 int n = (int)luaL_check_number(2); 87 int n = (int)luaL_check_number(2);
86 luaL_resetbuffer(); 88 luaL_resetbuffer();
87 while (n-- > 0) 89 while (n-- > 0)
88 addstr(s); 90 addnchar(s, l);
89 closeandpush(); 91 closeandpush();
90} 92}
91 93
92 94
93static void str_ascii (void) 95static void str_ascii (void)
94{ 96{
95 char *s = luaL_check_string(1); 97 long l;
96 long pos = (long)luaL_opt_number(2, 1) - 1; 98 char *s = luaL_check_lstr(1, &l);
97 luaL_arg_check(0<=pos && pos<strlen(s), 2, "out of range"); 99 long pos = posrelat(luaL_opt_number(2, 1), l);
98 lua_pushnumber((unsigned char)s[pos]); 100 luaL_arg_check(0<pos && pos<=l, 2, "out of range");
101 lua_pushnumber((unsigned char)s[pos-1]);
99} 102}
100 103
101 104
@@ -124,14 +127,8 @@ struct Capture {
124static void push_captures (struct Capture *cap) 127static void push_captures (struct Capture *cap)
125{ 128{
126 int i; 129 int i;
127 for (i=0; i<cap->level; i++) { 130 for (i=0; i<cap->level; i++)
128 int l = cap->capture[i].len; 131 lua_pushlstr(cap->capture[i].init, cap->capture[i].len);
129 char *buff = luaL_openspace(l+1);
130 if (l == -1) lua_error("unfinished capture");
131 strncpy(buff, cap->capture[i].init, l);
132 buff[l] = 0;
133 lua_pushstring(buff);
134 }
135} 132}
136 133
137 134
@@ -163,7 +160,6 @@ static char *bracket_end (char *p)
163static int matchclass (int c, int cl) 160static int matchclass (int c, int cl)
164{ 161{
165 int res; 162 int res;
166 if (c == 0) return 0;
167 switch (tolower((unsigned char)cl)) { 163 switch (tolower((unsigned char)cl)) {
168 case 'w' : res = isalnum((unsigned char)c); break; 164 case 'w' : res = isalnum((unsigned char)c); break;
169 case 'd' : res = isdigit((unsigned char)c); break; 165 case 'd' : res = isdigit((unsigned char)c); break;
@@ -184,7 +180,7 @@ int luaI_singlematch (int c, char *p, char **ep)
184 switch (*p) { 180 switch (*p) {
185 case '.': 181 case '.':
186 *ep = p+1; 182 *ep = p+1;
187 return (c != 0); 183 return 1;
188 case '\0': 184 case '\0':
189 *ep = p; 185 *ep = p;
190 return 0; 186 return 0;
@@ -198,7 +194,6 @@ int luaI_singlematch (int c, char *p, char **ep)
198 int sig = *(p+1) == '^' ? (p++, 0) : 1; 194 int sig = *(p+1) == '^' ? (p++, 0) : 1;
199 if (end == NULL) lua_error("incorrect pattern (missing `]')"); 195 if (end == NULL) lua_error("incorrect pattern (missing `]')");
200 *ep = end+1; 196 *ep = end+1;
201 if (c == 0) return 0;
202 while (++p < end) { 197 while (++p < end) {
203 if (*p == ESC) { 198 if (*p == ESC) {
204 if (((p+1) < end) && matchclass(c, *++p)) return sig; 199 if (((p+1) < end) && matchclass(c, *++p)) return sig;
@@ -254,7 +249,8 @@ static char *matchitem (char *s, char *p, struct Capture *cap, char **ep)
254 } 249 }
255 else p--; /* and go through */ 250 else p--; /* and go through */
256 } 251 }
257 return (luaI_singlematch(*s, p, ep) ? s+1 : NULL); 252 /* "luaI_singlematch" sets "ep" (so must be called even when *s == 0) */
253 return (luaI_singlematch(*s, p, ep) && *s) ? s+1 : NULL;
258} 254}
259 255
260 256
@@ -322,10 +318,11 @@ static char *match (char *s, char *p, struct Capture *cap)
322 318
323static void str_find (void) 319static void str_find (void)
324{ 320{
325 char *s = luaL_check_string(1); 321 long l;
322 char *s = luaL_check_lstr(1, &l);
326 char *p = luaL_check_string(2); 323 char *p = luaL_check_string(2);
327 long init = (long)luaL_opt_number(3, 1) - 1; 324 long init = posrelat(luaL_opt_number(3, 1), l) - 1;
328 luaL_arg_check(0 <= init && init <= strlen(s), 3, "out of range"); 325 luaL_arg_check(0 <= init && init <= l, 3, "out of range");
329 if (lua_getparam(4) != LUA_NOOBJECT || 326 if (lua_getparam(4) != LUA_NOOBJECT ||
330 strpbrk(p, SPECIALS) == NULL) { /* no special caracters? */ 327 strpbrk(p, SPECIALS) == NULL) { /* no special caracters? */
331 char *s2 = strstr(s+init, p); 328 char *s2 = strstr(s+init, p);
@@ -381,7 +378,10 @@ static void add_s (lua_Object newp, struct Capture *cap)
381 lua_error(NULL); 378 lua_error(NULL);
382 } 379 }
383 res = lua_getresult(1); 380 res = lua_getresult(1);
384 addstr(lua_isstring(res) ? lua_getstring(res) : ""); 381 if (lua_isstring(res))
382 addnchar(lua_getstring(res), lua_getstrlen(res));
383 else
384 addnchar(NULL, 0);
385 lua_endblock(); 385 lua_endblock();
386 } 386 }
387 else luaL_arg_check(0, 3, "string or function expected"); 387 else luaL_arg_check(0, 3, "string or function expected");
@@ -413,7 +413,7 @@ static void str_gsub (void)
413 else break; 413 else break;
414 if (anchor) break; 414 if (anchor) break;
415 } 415 }
416 addstr(src); 416 addnchar(src, strlen(src));
417 closeandpush(); 417 closeandpush();
418 lua_pushnumber(n); /* number of substitutions */ 418 lua_pushnumber(n); /* number of substitutions */
419} 419}
diff --git a/lua.h b/lua.h
index 4e11f987..90661078 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.14 1998/01/07 16:26:48 roberto Exp roberto $ 2** $Id: lua.h,v 1.15 1998/02/12 19:23:32 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil 4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
5** e-mail: lua@tecgraf.puc-rio.br 5** e-mail: lua@tecgraf.puc-rio.br
@@ -90,12 +90,14 @@ int lua_isfunction (lua_Object object);
90 90
91double lua_getnumber (lua_Object object); 91double lua_getnumber (lua_Object object);
92char *lua_getstring (lua_Object object); 92char *lua_getstring (lua_Object object);
93long lua_getstrlen (lua_Object object);
93lua_CFunction lua_getcfunction (lua_Object object); 94lua_CFunction lua_getcfunction (lua_Object object);
94void *lua_getuserdata (lua_Object object); 95void *lua_getuserdata (lua_Object object);
95 96
96 97
97void lua_pushnil (void); 98void lua_pushnil (void);
98void lua_pushnumber (double n); 99void lua_pushnumber (double n);
100void lua_pushlstr (char *s, long len);
99void lua_pushstring (char *s); 101void lua_pushstring (char *s);
100void lua_pushCclosure (lua_CFunction fn, int n); 102void lua_pushCclosure (lua_CFunction fn, int n);
101void lua_pushusertag (void *u, int tag); 103void lua_pushusertag (void *u, int tag);
diff --git a/lvm.c b/lvm.c
index 0119bd12..dba91979 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.22 1998/01/12 13:35:37 roberto Exp roberto $ 2** $Id: lvm.c,v 1.23 1998/01/14 13:49:15 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -37,13 +37,14 @@
37 37
38 38
39 39
40static TaggedString *strconc (char *l, char *r) 40static TaggedString *strconc (TaggedString *l, TaggedString *r)
41{ 41{
42 size_t nl = strlen(l); 42 size_t nl = l->u.s.len;
43 char *buffer = luaL_openspace(nl+strlen(r)+1); 43 size_t nr = r->u.s.len;
44 strcpy(buffer, l); 44 char *buffer = luaL_openspace(nl+nr+1);
45 strcpy(buffer+nl, r); 45 memcpy(buffer, l->str, nl);
46 return luaS_new(buffer); 46 memcpy(buffer+nl, r->str, nr);
47 return luaS_newlstr(buffer, nl+nr);
47} 48}
48 49
49 50
@@ -167,7 +168,7 @@ void luaV_settable (TObject *t, int mode)
167void luaV_getglobal (TaggedString *ts) 168void luaV_getglobal (TaggedString *ts)
168{ 169{
169 /* WARNING: caller must assure stack space */ 170 /* WARNING: caller must assure stack space */
170 TObject *value = &ts->u.globalval; 171 TObject *value = &ts->u.s.globalval;
171 TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL); 172 TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL);
172 if (ttype(im) == LUA_T_NIL) { /* default behavior */ 173 if (ttype(im) == LUA_T_NIL) { /* default behavior */
173 *L->stack.top++ = *value; 174 *L->stack.top++ = *value;
@@ -185,7 +186,7 @@ void luaV_getglobal (TaggedString *ts)
185 186
186void luaV_setglobal (TaggedString *ts) 187void luaV_setglobal (TaggedString *ts)
187{ 188{
188 TObject *oldvalue = &ts->u.globalval; 189 TObject *oldvalue = &ts->u.s.globalval;
189 TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL); 190 TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
190 if (ttype(im) == LUA_T_NIL) /* default behavior */ 191 if (ttype(im) == LUA_T_NIL) /* default behavior */
191 luaS_rawsetglobal(ts, --L->stack.top); 192 luaS_rawsetglobal(ts, --L->stack.top);
@@ -224,6 +225,23 @@ static void call_arith (IMS event)
224} 225}
225 226
226 227
228static int strcomp (char *l, long ll, char *r, long lr)
229{
230 for (;;) {
231 long temp = strcoll(l, r);
232 if (temp != 0) return temp;
233 /* strings are equal up to a '\0' */
234 temp = strlen(l); /* index of first '\0' in both strings */
235 if (temp == ll) /* l is finished? */
236 return (temp == lr) ? 0 : -1; /* l is equal or smaller than r */
237 else if (temp == lr) /* r is finished? */
238 return 1; /* l is greater than r (because l is not finished) */
239 /* both strings longer than temp; go on comparing (after the '\0') */
240 temp++;
241 l += temp; ll -= temp; r += temp; lr -= temp;
242 }
243}
244
227static void comparison (lua_Type ttype_less, lua_Type ttype_equal, 245static void comparison (lua_Type ttype_less, lua_Type ttype_equal,
228 lua_Type ttype_great, IMS op) 246 lua_Type ttype_great, IMS op)
229{ 247{
@@ -234,7 +252,8 @@ static void comparison (lua_Type ttype_less, lua_Type ttype_equal,
234 if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER) 252 if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER)
235 result = (nvalue(l) < nvalue(r)) ? -1 : (nvalue(l) == nvalue(r)) ? 0 : 1; 253 result = (nvalue(l) < nvalue(r)) ? -1 : (nvalue(l) == nvalue(r)) ? 0 : 1;
236 else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING) 254 else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING)
237 result = strcoll(svalue(l), svalue(r)); 255 result = strcomp(svalue(l), tsvalue(l)->u.s.len,
256 svalue(r), tsvalue(r)->u.s.len);
238 else { 257 else {
239 call_binTM(op, "unexpected type in comparison"); 258 call_binTM(op, "unexpected type in comparison");
240 return; 259 return;
@@ -582,7 +601,7 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base)
582 if (tostring(l) || tostring(r)) 601 if (tostring(l) || tostring(r))
583 call_binTM(IM_CONCAT, "unexpected type for concatenation"); 602 call_binTM(IM_CONCAT, "unexpected type for concatenation");
584 else { 603 else {
585 tsvalue(l) = strconc(svalue(l), svalue(r)); 604 tsvalue(l) = strconc(tsvalue(l), tsvalue(r));
586 --S->top; 605 --S->top;
587 } 606 }
588 luaC_checkGC(); 607 luaC_checkGC();