- initial import of revision 374 from cnc
[apt.git] / lua / lapi.c
1 /*
2 ** $Id: lapi.c,v 1.235 2003/04/07 14:36:08 roberto Exp $
3 ** Lua API
4 ** See Copyright Notice in lua.h
5 */
6
7
8 #include <assert.h>
9 #include <string.h>
10
11 #define lapi_c
12
13 #include "lua.h"
14
15 #include "lapi.h"
16 #include "ldebug.h"
17 #include "ldo.h"
18 #include "lfunc.h"
19 #include "lgc.h"
20 #include "lmem.h"
21 #include "lobject.h"
22 #include "lstate.h"
23 #include "lstring.h"
24 #include "ltable.h"
25 #include "ltm.h"
26 #include "lundump.h"
27 #include "lvm.h"
28
29
30 const char lua_ident[] =
31   "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
32   "$Authors: " LUA_AUTHORS " $\n"
33   "$URL: www.lua.org $\n";
34
35
36
37 #ifndef api_check
38 #define api_check(L, o)         /*{ assert(o); }*/
39 #endif
40
41 #define api_checknelems(L, n)   api_check(L, (n) <= (L->top - L->base))
42
43 #define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
44
45
46
47
48 static TObject *negindex (lua_State *L, int idx) {
49   if (idx > LUA_REGISTRYINDEX) {
50     api_check(L, idx != 0 && -idx <= L->top - L->base);
51     return L->top+idx;
52   }
53   else switch (idx) {  /* pseudo-indices */
54     case LUA_REGISTRYINDEX: return registry(L);
55     case LUA_GLOBALSINDEX: return gt(L);
56     default: {
57       TObject *func = (L->base - 1);
58       idx = LUA_GLOBALSINDEX - idx;
59       lua_assert(iscfunction(func));
60       return (idx <= clvalue(func)->c.nupvalues)
61                 ? &clvalue(func)->c.upvalue[idx-1]
62                 : NULL;
63     }
64   }
65 }
66
67
68 static TObject *luaA_index (lua_State *L, int idx) {
69   if (idx > 0) {
70     api_check(L, idx <= L->top - L->base);
71     return L->base + idx - 1;
72   }
73   else {
74     TObject *o = negindex(L, idx);
75     api_check(L, o != NULL);
76     return o;
77   }
78 }
79
80
81 static TObject *luaA_indexAcceptable (lua_State *L, int idx) {
82   if (idx > 0) {
83     TObject *o = L->base+(idx-1);
84     api_check(L, idx <= L->stack_last - L->base);
85     if (o >= L->top) return NULL;
86     else return o;
87   }
88   else
89     return negindex(L, idx);
90 }
91
92
93 void luaA_pushobject (lua_State *L, const TObject *o) {
94   setobj2s(L->top, o);
95   incr_top(L);
96 }
97
98
99 LUA_API int lua_checkstack (lua_State *L, int size) {
100   int res;
101   lua_lock(L);
102   if ((L->top - L->base + size) > LUA_MAXCSTACK)
103     res = 0;  /* stack overflow */
104   else {
105     luaD_checkstack(L, size);
106     if (L->ci->top < L->top + size)
107       L->ci->top = L->top + size;
108     res = 1;
109   }
110   lua_unlock(L);
111   return res;
112 }
113
114
115 LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
116   int i;
117   lua_lock(to);
118   api_checknelems(from, n);
119   from->top -= n;
120   for (i = 0; i < n; i++) {
121     setobj2s(to->top, from->top + i);
122     api_incr_top(to);
123   }
124   lua_unlock(to);
125 }
126
127
128 LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
129   lua_CFunction old;
130   lua_lock(L);
131   old = G(L)->panic;
132   G(L)->panic = panicf;
133   lua_unlock(L);
134   return old;
135 }
136
137
138 LUA_API lua_State *lua_newthread (lua_State *L) {
139   lua_State *L1;
140   lua_lock(L);
141   luaC_checkGC(L);
142   L1 = luaE_newthread(L);
143   setthvalue(L->top, L1);
144   api_incr_top(L);
145   lua_unlock(L);
146   lua_userstateopen(L1);
147   return L1;
148 }
149
150
151
152 /*
153 ** basic stack manipulation
154 */
155
156
157 LUA_API int lua_gettop (lua_State *L) {
158   return (L->top - L->base);
159 }
160
161
162 LUA_API void lua_settop (lua_State *L, int idx) {
163   lua_lock(L);
164   if (idx >= 0) {
165     api_check(L, idx <= L->stack_last - L->base);
166     while (L->top < L->base + idx)
167       setnilvalue(L->top++);
168     L->top = L->base + idx;
169   }
170   else {
171     api_check(L, -(idx+1) <= (L->top - L->base));
172     L->top += idx+1;  /* `subtract' index (index is negative) */
173   }
174   lua_unlock(L);
175 }
176
177
178 LUA_API void lua_remove (lua_State *L, int idx) {
179   StkId p;
180   lua_lock(L);
181   p = luaA_index(L, idx);
182   while (++p < L->top) setobjs2s(p-1, p);
183   L->top--;
184   lua_unlock(L);
185 }
186
187
188 LUA_API void lua_insert (lua_State *L, int idx) {
189   StkId p;
190   StkId q;
191   lua_lock(L);
192   p = luaA_index(L, idx);
193   for (q = L->top; q>p; q--) setobjs2s(q, q-1);
194   setobjs2s(p, L->top);
195   lua_unlock(L);
196 }
197
198
199 LUA_API void lua_replace (lua_State *L, int idx) {
200   lua_lock(L);
201   api_checknelems(L, 1);
202   setobj(luaA_index(L, idx), L->top - 1);  /* write barrier */
203   L->top--;
204   lua_unlock(L);
205 }
206
207
208 LUA_API void lua_pushvalue (lua_State *L, int idx) {
209   lua_lock(L);
210   setobj2s(L->top, luaA_index(L, idx));
211   api_incr_top(L);
212   lua_unlock(L);
213 }
214
215
216
217 /*
218 ** access functions (stack -> C)
219 */
220
221
222 LUA_API int lua_type (lua_State *L, int idx) {
223   StkId o = luaA_indexAcceptable(L, idx);
224   return (o == NULL) ? LUA_TNONE : ttype(o);
225 }
226
227
228 LUA_API const char *lua_typename (lua_State *L, int t) {
229   UNUSED(L);
230   return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
231 }
232
233
234 LUA_API int lua_iscfunction (lua_State *L, int idx) {
235   StkId o = luaA_indexAcceptable(L, idx);
236   return (o == NULL) ? 0 : iscfunction(o);
237 }
238
239
240 LUA_API int lua_isnumber (lua_State *L, int idx) {
241   TObject n;
242   const TObject *o = luaA_indexAcceptable(L, idx);
243   return (o != NULL && tonumber(o, &n));
244 }
245
246
247 LUA_API int lua_isstring (lua_State *L, int idx) {
248   int t = lua_type(L, idx);
249   return (t == LUA_TSTRING || t == LUA_TNUMBER);
250 }
251
252
253 LUA_API int lua_isuserdata (lua_State *L, int idx) {
254   const TObject *o = luaA_indexAcceptable(L, idx);
255   return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
256 }
257
258
259 LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
260   StkId o1 = luaA_indexAcceptable(L, index1);
261   StkId o2 = luaA_indexAcceptable(L, index2);
262   return (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
263                                     : luaO_rawequalObj(o1, o2);
264 }
265
266
267 LUA_API int lua_equal (lua_State *L, int index1, int index2) {
268   StkId o1, o2;
269   int i;
270   lua_lock(L);  /* may call tag method */
271   o1 = luaA_indexAcceptable(L, index1);
272   o2 = luaA_indexAcceptable(L, index2);
273   i = (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
274                                  : equalobj(L, o1, o2);
275   lua_unlock(L);
276   return i;
277 }
278
279
280 LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
281   StkId o1, o2;
282   int i;
283   lua_lock(L);  /* may call tag method */
284   o1 = luaA_indexAcceptable(L, index1);
285   o2 = luaA_indexAcceptable(L, index2);
286   i = (o1 == NULL || o2 == NULL) ? 0  /* index out-of-range */
287                                  : luaV_lessthan(L, o1, o2);
288   lua_unlock(L);
289   return i;
290 }
291
292
293
294 LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
295   TObject n;
296   const TObject *o = luaA_indexAcceptable(L, idx);
297   if (o != NULL && tonumber(o, &n))
298     return nvalue(o);
299   else
300     return 0;
301 }
302
303
304 LUA_API int lua_toboolean (lua_State *L, int idx) {
305   const TObject *o = luaA_indexAcceptable(L, idx);
306   return (o != NULL) && !l_isfalse(o);
307 }
308
309
310 LUA_API const char *lua_tostring (lua_State *L, int idx) {
311   StkId o = luaA_indexAcceptable(L, idx);
312   if (o == NULL)
313     return NULL;
314   else if (ttisstring(o))
315     return svalue(o);
316   else {
317     const char *s;
318     lua_lock(L);  /* `luaV_tostring' may create a new string */
319     s = (luaV_tostring(L, o) ? svalue(o) : NULL);
320     luaC_checkGC(L);
321     lua_unlock(L);
322     return s;
323   }
324 }
325
326
327 LUA_API size_t lua_strlen (lua_State *L, int idx) {
328   StkId o = luaA_indexAcceptable(L, idx);
329   if (o == NULL)
330     return 0;
331   else if (ttisstring(o))
332     return tsvalue(o)->tsv.len;
333   else {
334     size_t l;
335     lua_lock(L);  /* `luaV_tostring' may create a new string */
336     l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0);
337     lua_unlock(L);
338     return l;
339   }
340 }
341
342
343 LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
344   StkId o = luaA_indexAcceptable(L, idx);
345   return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
346 }
347
348
349 LUA_API void *lua_touserdata (lua_State *L, int idx) {
350   StkId o = luaA_indexAcceptable(L, idx);
351   if (o == NULL) return NULL;
352   switch (ttype(o)) {
353     case LUA_TUSERDATA: return (uvalue(o) + 1);
354     case LUA_TLIGHTUSERDATA: return pvalue(o);
355     default: return NULL;
356   }
357 }
358
359
360 LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
361   StkId o = luaA_indexAcceptable(L, idx);
362   return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
363 }
364
365
366 LUA_API const void *lua_topointer (lua_State *L, int idx) {
367   StkId o = luaA_indexAcceptable(L, idx);
368   if (o == NULL) return NULL;
369   else {
370     switch (ttype(o)) {
371       case LUA_TTABLE: return hvalue(o);
372       case LUA_TFUNCTION: return clvalue(o);
373       case LUA_TTHREAD: return thvalue(o);
374       case LUA_TUSERDATA:
375       case LUA_TLIGHTUSERDATA:
376         return lua_touserdata(L, idx);
377       default: return NULL;
378     }
379   }
380 }
381
382
383
384 /*
385 ** push functions (C -> stack)
386 */
387
388
389 LUA_API void lua_pushnil (lua_State *L) {
390   lua_lock(L);
391   setnilvalue(L->top);
392   api_incr_top(L);
393   lua_unlock(L);
394 }
395
396
397 LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
398   lua_lock(L);
399   setnvalue(L->top, n);
400   api_incr_top(L);
401   lua_unlock(L);
402 }
403
404
405 LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
406   lua_lock(L);
407   luaC_checkGC(L);
408   setsvalue2s(L->top, luaS_newlstr(L, s, len));
409   api_incr_top(L);
410   lua_unlock(L);
411 }
412
413
414 LUA_API void lua_pushstring (lua_State *L, const char *s) {
415   if (s == NULL)
416     lua_pushnil(L);
417   else
418     lua_pushlstring(L, s, strlen(s));
419 }
420
421
422 LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
423                                       va_list argp) {
424   const char *ret;
425   lua_lock(L);
426   luaC_checkGC(L);
427   ret = luaO_pushvfstring(L, fmt, argp);
428   lua_unlock(L);
429   return ret;
430 }
431
432
433 LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
434   const char *ret;
435   va_list argp;
436   lua_lock(L);
437   luaC_checkGC(L);
438   va_start(argp, fmt);
439   ret = luaO_pushvfstring(L, fmt, argp);
440   va_end(argp);
441   lua_unlock(L);
442   return ret;
443 }
444
445
446 LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
447   Closure *cl;
448   lua_lock(L);
449   luaC_checkGC(L);
450   api_checknelems(L, n);
451   cl = luaF_newCclosure(L, n);
452   cl->c.f = fn;
453   L->top -= n;
454   while (n--)
455     setobj2n(&cl->c.upvalue[n], L->top+n);
456   setclvalue(L->top, cl);
457   api_incr_top(L);
458   lua_unlock(L);
459 }
460
461
462 LUA_API void lua_pushboolean (lua_State *L, int b) {
463   lua_lock(L);
464   setbvalue(L->top, (b != 0));  /* ensure that true is 1 */
465   api_incr_top(L);
466   lua_unlock(L);
467 }
468
469
470 LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
471   lua_lock(L);
472   setpvalue(L->top, p);
473   api_incr_top(L);
474   lua_unlock(L);
475 }
476
477
478
479 /*
480 ** get functions (Lua -> stack)
481 */
482
483
484 LUA_API void lua_gettable (lua_State *L, int idx) {
485   StkId t;
486   lua_lock(L);
487   t = luaA_index(L, idx);
488   setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
489   lua_unlock(L);
490 }
491
492
493 LUA_API void lua_rawget (lua_State *L, int idx) {
494   StkId t;
495   lua_lock(L);
496   t = luaA_index(L, idx);
497   api_check(L, ttistable(t));
498   setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
499   lua_unlock(L);
500 }
501
502
503 LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
504   StkId o;
505   lua_lock(L);
506   o = luaA_index(L, idx);
507   api_check(L, ttistable(o));
508   setobj2s(L->top, luaH_getnum(hvalue(o), n));
509   api_incr_top(L);
510   lua_unlock(L);
511 }
512
513
514 LUA_API void lua_newtable (lua_State *L) {
515   lua_lock(L);
516   luaC_checkGC(L);
517   sethvalue(L->top, luaH_new(L, 0, 0));
518   api_incr_top(L);
519   lua_unlock(L);
520 }
521
522
523 LUA_API int lua_getmetatable (lua_State *L, int objindex) {
524   const TObject *obj;
525   Table *mt = NULL;
526   int res;
527   lua_lock(L);
528   obj = luaA_indexAcceptable(L, objindex);
529   if (obj != NULL) {
530     switch (ttype(obj)) {
531       case LUA_TTABLE:
532         mt = hvalue(obj)->metatable;
533         break;
534       case LUA_TUSERDATA:
535         mt = uvalue(obj)->uv.metatable;
536         break;
537     }
538   }
539   if (mt == NULL || mt == hvalue(defaultmeta(L)))
540     res = 0;
541   else {
542     sethvalue(L->top, mt);
543     api_incr_top(L);
544     res = 1;
545   }
546   lua_unlock(L);
547   return res;
548 }
549
550
551 LUA_API void lua_getfenv (lua_State *L, int idx) {
552   StkId o;
553   lua_lock(L);
554   o = luaA_index(L, idx);
555   setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
556   api_incr_top(L);
557   lua_unlock(L);
558 }
559
560
561 /*
562 ** set functions (stack -> Lua)
563 */
564
565
566 LUA_API void lua_settable (lua_State *L, int idx) {
567   StkId t;
568   lua_lock(L);
569   api_checknelems(L, 2);
570   t = luaA_index(L, idx);
571   luaV_settable(L, t, L->top - 2, L->top - 1);
572   L->top -= 2;  /* pop index and value */
573   lua_unlock(L);
574 }
575
576
577 LUA_API void lua_rawset (lua_State *L, int idx) {
578   StkId t;
579   lua_lock(L);
580   api_checknelems(L, 2);
581   t = luaA_index(L, idx);
582   api_check(L, ttistable(t));
583   setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1);  /* write barrier */
584   L->top -= 2;
585   lua_unlock(L);
586 }
587
588
589 LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
590   StkId o;
591   lua_lock(L);
592   api_checknelems(L, 1);
593   o = luaA_index(L, idx);
594   api_check(L, ttistable(o));
595   setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1);  /* write barrier */
596   L->top--;
597   lua_unlock(L);
598 }
599
600
601 LUA_API int lua_setmetatable (lua_State *L, int objindex) {
602   TObject *obj, *mt;
603   int res = 1;
604   lua_lock(L);
605   api_checknelems(L, 1);
606   obj = luaA_index(L, objindex);
607   mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L);
608   api_check(L, ttistable(mt));
609   switch (ttype(obj)) {
610     case LUA_TTABLE: {
611       hvalue(obj)->metatable = hvalue(mt);  /* write barrier */
612       break;
613     }
614     case LUA_TUSERDATA: {
615       uvalue(obj)->uv.metatable = hvalue(mt);  /* write barrier */
616       break;
617     }
618     default: {
619       res = 0;  /* cannot set */
620       break;
621     }
622   }
623   L->top--;
624   lua_unlock(L);
625   return res;
626 }
627
628
629 LUA_API int lua_setfenv (lua_State *L, int idx) {
630   StkId o;
631   int res = 0;
632   lua_lock(L);
633   api_checknelems(L, 1);
634   o = luaA_index(L, idx);
635   L->top--;
636   api_check(L, ttistable(L->top));
637   if (isLfunction(o)) {
638     res = 1;
639     clvalue(o)->l.g = *(L->top);
640   }
641   lua_unlock(L);
642   return res;
643 }
644
645
646 /*
647 ** `load' and `call' functions (run Lua code)
648 */
649
650 LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
651   StkId func;
652   lua_lock(L);
653   api_checknelems(L, nargs+1);
654   func = L->top - (nargs+1);
655   luaD_call(L, func, nresults);
656   lua_unlock(L);
657 }
658
659
660
661 /*
662 ** Execute a protected call.
663 */
664 struct CallS {  /* data to `f_call' */
665   StkId func;
666   int nresults;
667 };
668
669
670 static void f_call (lua_State *L, void *ud) {
671   struct CallS *c = cast(struct CallS *, ud);
672   luaD_call(L, c->func, c->nresults);
673 }
674
675
676
677 LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
678   struct CallS c;
679   int status;
680   ptrdiff_t func;
681   lua_lock(L);
682   func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
683   c.func = L->top - (nargs+1);  /* function to be called */
684   c.nresults = nresults;
685   status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
686   lua_unlock(L);
687   return status;
688 }
689
690
691 /*
692 ** Execute a protected C call.
693 */
694 struct CCallS {  /* data to `f_Ccall' */
695   lua_CFunction func;
696   void *ud;
697 };
698
699
700 static void f_Ccall (lua_State *L, void *ud) {
701   struct CCallS *c = cast(struct CCallS *, ud);
702   Closure *cl;
703   cl = luaF_newCclosure(L, 0);
704   cl->c.f = c->func;
705   setclvalue(L->top, cl);  /* push function */
706   incr_top(L);
707   setpvalue(L->top, c->ud);  /* push only argument */
708   incr_top(L);
709   luaD_call(L, L->top - 2, 0);
710 }
711
712
713 LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
714   struct CCallS c;
715   int status;
716   lua_lock(L);
717   c.func = func;
718   c.ud = ud;
719   status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
720   lua_unlock(L);
721   return status;
722 }
723
724
725 LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
726                       const char *chunkname) {
727   ZIO z;
728   int status;
729   int c;
730   lua_lock(L);
731   if (!chunkname) chunkname = "?";
732   luaZ_init(&z, reader, data, chunkname);
733   c = luaZ_lookahead(&z);
734   status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]));
735   lua_unlock(L);
736   return status;
737 }
738
739
740 LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
741   int status;
742   TObject *o;
743   lua_lock(L);
744   api_checknelems(L, 1);
745   o = L->top - 1;
746   if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
747     luaU_dump(L, clvalue(o)->l.p, writer, data);
748     status = 1;
749   }
750   else
751     status = 0;
752   lua_unlock(L);
753   return status;
754 }
755
756
757 /*
758 ** Garbage-collection functions
759 */
760
761 /* GC values are expressed in Kbytes: #bytes/2^10 */
762 #define GCscalel(x)             ((x)>>10)
763 #define GCscale(x)              (cast(int, GCscalel(x)))
764 #define GCunscale(x)            (cast(lu_mem, x)<<10)
765
766 LUA_API int lua_getgcthreshold (lua_State *L) {
767   int threshold;
768   lua_lock(L);
769   threshold = GCscale(G(L)->GCthreshold);
770   lua_unlock(L);
771   return threshold;
772 }
773
774 LUA_API int lua_getgccount (lua_State *L) {
775   int count;
776   lua_lock(L);
777   count = GCscale(G(L)->nblocks);
778   lua_unlock(L);
779   return count;
780 }
781
782 LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
783   lua_lock(L);
784   if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
785     G(L)->GCthreshold = MAX_LUMEM;
786   else
787     G(L)->GCthreshold = GCunscale(newthreshold);
788   luaC_checkGC(L);
789   lua_unlock(L);
790 }
791
792
793 /*
794 ** miscellaneous functions
795 */
796
797
798 LUA_API const char *lua_version (void) {
799   return LUA_VERSION;
800 }
801
802
803 LUA_API int lua_error (lua_State *L) {
804   lua_lock(L);
805   api_checknelems(L, 1);
806   luaG_errormsg(L);
807   lua_unlock(L);
808   return 0;  /* to avoid warnings */
809 }
810
811
812 LUA_API int lua_next (lua_State *L, int idx) {
813   StkId t;
814   int more;
815   lua_lock(L);
816   t = luaA_index(L, idx);
817   api_check(L, ttistable(t));
818   more = luaH_next(L, hvalue(t), L->top - 1);
819   if (more) {
820     api_incr_top(L);
821   }
822   else  /* no more elements */
823     L->top -= 1;  /* remove key */
824   lua_unlock(L);
825   return more;
826 }
827
828
829 LUA_API void lua_concat (lua_State *L, int n) {
830   lua_lock(L);
831   luaC_checkGC(L);
832   api_checknelems(L, n);
833   if (n >= 2) {
834     luaV_concat(L, n, L->top - L->base - 1);
835     L->top -= (n-1);
836   }
837   else if (n == 0) {  /* push empty string */
838     setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
839     api_incr_top(L);
840   }
841   /* else n == 1; nothing to do */
842   lua_unlock(L);
843 }
844
845
846 LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
847   Udata *u;
848   lua_lock(L);
849   luaC_checkGC(L);
850   u = luaS_newudata(L, size);
851   setuvalue(L->top, u);
852   api_incr_top(L);
853   lua_unlock(L);
854   return u + 1;
855 }
856
857
858 LUA_API int lua_pushupvalues (lua_State *L) {
859   Closure *func;
860   int n, i;
861   lua_lock(L);
862   api_check(L, iscfunction(L->base - 1));
863   func = clvalue(L->base - 1);
864   n = func->c.nupvalues;
865   luaD_checkstack(L, n + LUA_MINSTACK);
866   for (i=0; i<n; i++) {
867     setobj2s(L->top, &func->c.upvalue[i]);
868     L->top++;
869   }
870   lua_unlock(L);
871   return n;
872 }
873
874
875 static const char *aux_upvalue (lua_State *L, int funcindex, int n,
876                                 TObject **val) {
877   Closure *f;
878   StkId fi = luaA_index(L, funcindex);
879   if (!ttisfunction(fi)) return NULL;
880   f = clvalue(fi);
881   if (f->c.isC) {
882     if (n > f->c.nupvalues) return NULL;
883     *val = &f->c.upvalue[n-1];
884     return "";
885   }
886   else {
887     Proto *p = f->l.p;
888     if (n > p->sizeupvalues) return NULL;
889     *val = f->l.upvals[n-1]->v;
890     return getstr(p->upvalues[n-1]);
891   }
892 }
893
894
895 LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
896   const char *name;
897   TObject *val;
898   lua_lock(L);
899   name = aux_upvalue(L, funcindex, n, &val);
900   if (name) {
901     setobj2s(L->top, val);
902     api_incr_top(L);
903   }
904   lua_unlock(L);
905   return name;
906 }
907
908
909 LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
910   const char *name;
911   TObject *val;
912   lua_lock(L);
913   api_checknelems(L, 1);
914   name = aux_upvalue(L, funcindex, n, &val);
915   if (name) {
916     L->top--;
917     setobj(val, L->top);  /* write barrier */
918   }
919   lua_unlock(L);
920   return name;
921 }
922