1 /*
2 ** $Id: lapi.c,v 1.2 2002/07/12 07:49:04 jcatki Exp $
3 ** Lua API
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #include <string.h>
9 
10 #include "lua.h"
11 
12 #include "lapi.h"
13 #include "ldo.h"
14 #include "lfunc.h"
15 #include "lgc.h"
16 #include "lmem.h"
17 #include "lobject.h"
18 #include "lstate.h"
19 #include "lstring.h"
20 #include "ltable.h"
21 #include "ltm.h"
22 #include "lvm.h"
23 
24 
25 const char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
26                                "$Authors: " LUA_AUTHORS " $";
27 
28 
29 
30 #define Index(L,i)	((i) >= 0 ? (L->Cbase+((i)-1)) : (L->top+(i)))
31 
32 #define api_incr_top(L)	incr_top
33 
34 
35 
36 
luaA_index(lua_State * L,int index)37 TObject *luaA_index (lua_State *L, int index) {
38   return Index(L, index);
39 }
40 
41 
luaA_indexAcceptable(lua_State * L,int index)42 static TObject *luaA_indexAcceptable (lua_State *L, int index) {
43   if (index >= 0) {
44     TObject *o = L->Cbase+(index-1);
45     if (o >= L->top) return NULL;
46     else return o;
47   }
48   else return L->top+index;
49 }
50 
51 
luaA_pushobject(lua_State * L,const TObject * o)52 void luaA_pushobject (lua_State *L, const TObject *o) {
53   *L->top = *o;
54   incr_top;
55 }
56 
lua_stackspace(lua_State * L)57 LUA_API int lua_stackspace (lua_State *L) {
58   return (L->stack_last - L->top);
59 }
60 
61 
62 
63 /*
64 ** basic stack manipulation
65 */
66 
67 
lua_gettop(lua_State * L)68 LUA_API int lua_gettop (lua_State *L) {
69   return (L->top - L->Cbase);
70 }
71 
72 
lua_settop(lua_State * L,int index)73 LUA_API void lua_settop (lua_State *L, int index) {
74   if (index >= 0)
75     luaD_adjusttop(L, L->Cbase, index);
76   else
77     L->top = L->top+index+1;  /* index is negative */
78 }
79 
80 
lua_remove(lua_State * L,int index)81 LUA_API void lua_remove (lua_State *L, int index) {
82   StkId p = luaA_index(L, index);
83   while (++p < L->top) *(p-1) = *p;
84   L->top--;
85 }
86 
87 
lua_insert(lua_State * L,int index)88 LUA_API void lua_insert (lua_State *L, int index) {
89   StkId p = luaA_index(L, index);
90   StkId q;
91   for (q = L->top; q>p; q--)
92     *q = *(q-1);
93   *p = *L->top;
94 }
95 
96 
lua_pushvalue(lua_State * L,int index)97 LUA_API void lua_pushvalue (lua_State *L, int index) {
98   *L->top = *luaA_index(L, index);
99   api_incr_top(L);
100 }
101 
102 
103 
104 /*
105 ** access functions (stack -> C)
106 */
107 
108 
lua_type(lua_State * L,int index)109 LUA_API int lua_type (lua_State *L, int index) {
110   StkId o = luaA_indexAcceptable(L, index);
111   return (o == NULL) ? LUA_TNONE : ttype(o);
112 }
113 
lua_typename(lua_State * L,int t)114 LUA_API const char *lua_typename (lua_State *L, int t) {
115   UNUSED(L);
116   return (t == LUA_TNONE) ? "no value" : luaO_typenames[t];
117 }
118 
119 
lua_iscfunction(lua_State * L,int index)120 LUA_API int lua_iscfunction (lua_State *L, int index) {
121   StkId o = luaA_indexAcceptable(L, index);
122   return (o == NULL) ? 0 : iscfunction(o);
123 }
124 
lua_isnumber(lua_State * L,int index)125 LUA_API int lua_isnumber (lua_State *L, int index) {
126   TObject *o = luaA_indexAcceptable(L, index);
127   return (o == NULL) ? 0 : (tonumber(o) == 0);
128 }
129 
lua_isstring(lua_State * L,int index)130 LUA_API int lua_isstring (lua_State *L, int index) {
131   int t = lua_type(L, index);
132   return (t == LUA_TSTRING || t == LUA_TNUMBER);
133 }
134 
135 
lua_tag(lua_State * L,int index)136 LUA_API int lua_tag (lua_State *L, int index) {
137   StkId o = luaA_indexAcceptable(L, index);
138   return (o == NULL) ? LUA_NOTAG : luaT_tag(o);
139 }
140 
lua_equal(lua_State * L,int index1,int index2)141 LUA_API int lua_equal (lua_State *L, int index1, int index2) {
142   StkId o1 = luaA_indexAcceptable(L, index1);
143   StkId o2 = luaA_indexAcceptable(L, index2);
144   if (o1 == NULL || o2 == NULL) return 0;  /* index out-of-range */
145   else return luaO_equalObj(o1, o2);
146 }
147 
lua_lessthan(lua_State * L,int index1,int index2)148 LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
149   StkId o1 = luaA_indexAcceptable(L, index1);
150   StkId o2 = luaA_indexAcceptable(L, index2);
151   if (o1 == NULL || o2 == NULL) return 0;  /* index out-of-range */
152   else return luaV_lessthan(L, o1, o2, L->top);
153 }
154 
155 
156 
lua_tonumber(lua_State * L,int index)157 LUA_API double lua_tonumber (lua_State *L, int index) {
158   StkId o = luaA_indexAcceptable(L, index);
159   return (o == NULL || tonumber(o)) ? 0 : nvalue(o);
160 }
161 
lua_tostring(lua_State * L,int index)162 LUA_API const char *lua_tostring (lua_State *L, int index) {
163   StkId o = luaA_indexAcceptable(L, index);
164   return (o == NULL || tostring(L, o)) ? NULL : svalue(o);
165 }
166 
lua_strlen(lua_State * L,int index)167 LUA_API size_t lua_strlen (lua_State *L, int index) {
168   StkId o = luaA_indexAcceptable(L, index);
169   return (o == NULL || tostring(L, o)) ? 0 : tsvalue(o)->len;
170 }
171 
lua_tocfunction(lua_State * L,int index)172 LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) {
173   StkId o = luaA_indexAcceptable(L, index);
174   return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->f.c;
175 }
176 
lua_touserdata(lua_State * L,int index)177 LUA_API void *lua_touserdata (lua_State *L, int index) {
178   StkId o = luaA_indexAcceptable(L, index);
179   return (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL :
180                                                     tsvalue(o)->u.d.value;
181 }
182 
lua_topointer(lua_State * L,int index)183 LUA_API const void *lua_topointer (lua_State *L, int index) {
184   StkId o = luaA_indexAcceptable(L, index);
185   if (o == NULL) return NULL;
186   switch (ttype(o)) {
187     case LUA_TTABLE:
188       return hvalue(o);
189     case LUA_TFUNCTION:
190       return clvalue(o);
191     default: return NULL;
192   }
193 }
194 
195 
196 
197 /*
198 ** push functions (C -> stack)
199 */
200 
201 
lua_pushnil(lua_State * L)202 LUA_API void lua_pushnil (lua_State *L) {
203   ttype(L->top) = LUA_TNIL;
204   api_incr_top(L);
205 }
206 
207 
lua_pushnumber(lua_State * L,double n)208 LUA_API void lua_pushnumber (lua_State *L, double n) {
209   nvalue(L->top) = n;
210   ttype(L->top) = LUA_TNUMBER;
211   api_incr_top(L);
212 }
213 
214 
lua_pushlstring(lua_State * L,const char * s,size_t len)215 LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
216   tsvalue(L->top) = luaS_newlstr(L, s, len);
217   ttype(L->top) = LUA_TSTRING;
218   api_incr_top(L);
219 }
220 
221 
lua_pushstring(lua_State * L,const char * s)222 LUA_API void lua_pushstring (lua_State *L, const char *s) {
223   if (s == NULL)
224     lua_pushnil(L);
225   else
226     lua_pushlstring(L, s, strlen(s));
227 }
228 
229 
lua_pushcclosure(lua_State * L,lua_CFunction fn,int n)230 LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
231   luaV_Cclosure(L, fn, n);
232 }
233 
234 
lua_pushusertag(lua_State * L,void * u,int tag)235 LUA_API void lua_pushusertag (lua_State *L, void *u, int tag) {
236   /* ORDER LUA_T */
237   if (!(tag == LUA_ANYTAG || tag == LUA_TUSERDATA || validtag(tag)))
238     luaO_verror(L, "invalid tag for a userdata (%d)", tag);
239   tsvalue(L->top) = luaS_createudata(L, u, tag);
240   ttype(L->top) = LUA_TUSERDATA;
241   api_incr_top(L);
242 }
243 
244 
245 
246 /*
247 ** get functions (Lua -> stack)
248 */
249 
250 
lua_getglobal(lua_State * L,const char * name)251 LUA_API void lua_getglobal (lua_State *L, const char *name) {
252   StkId top = L->top;
253   *top = *luaV_getglobal(L, luaS_new(L, name));
254   L->top = top;
255   api_incr_top(L);
256 }
257 
258 
lua_gettable(lua_State * L,int index)259 LUA_API void lua_gettable (lua_State *L, int index) {
260   StkId t = Index(L, index);
261   StkId top = L->top;
262   *(top-1) = *luaV_gettable(L, t);
263   L->top = top;  /* tag method may change top */
264 }
265 
266 
lua_rawget(lua_State * L,int index)267 LUA_API void lua_rawget (lua_State *L, int index) {
268   StkId t = Index(L, index);
269   LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected");
270   *(L->top - 1) = *luaH_get(L, hvalue(t), L->top - 1);
271 }
272 
273 
lua_rawgeti(lua_State * L,int index,int n)274 LUA_API void lua_rawgeti (lua_State *L, int index, int n) {
275   StkId o = Index(L, index);
276   LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected");
277   *L->top = *luaH_getnum(hvalue(o), n);
278   api_incr_top(L);
279 }
280 
281 
lua_getglobals(lua_State * L)282 LUA_API void lua_getglobals (lua_State *L) {
283   hvalue(L->top) = L->gt;
284   ttype(L->top) = LUA_TTABLE;
285   api_incr_top(L);
286 }
287 
288 
lua_getref(lua_State * L,int ref)289 LUA_API int lua_getref (lua_State *L, int ref) {
290   if (ref == LUA_REFNIL)
291     ttype(L->top) = LUA_TNIL;
292   else if (0 <= ref && ref < L->refSize &&
293           (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
294     *L->top = L->refArray[ref].o;
295   else
296     return 0;
297   api_incr_top(L);
298   return 1;
299 }
300 
301 
lua_newtable(lua_State * L)302 LUA_API void lua_newtable (lua_State *L) {
303   hvalue(L->top) = luaH_new(L, 0);
304   ttype(L->top) = LUA_TTABLE;
305   api_incr_top(L);
306 }
307 
308 
309 
310 /*
311 ** set functions (stack -> Lua)
312 */
313 
314 
lua_setglobal(lua_State * L,const char * name)315 LUA_API void lua_setglobal (lua_State *L, const char *name) {
316   StkId top = L->top;
317   luaV_setglobal(L, luaS_new(L, name));
318   L->top = top-1;  /* remove element from the top */
319 }
320 
321 
lua_settable(lua_State * L,int index)322 LUA_API void lua_settable (lua_State *L, int index) {
323   StkId t = Index(L, index);
324   StkId top = L->top;
325   luaV_settable(L, t, top-2);
326   L->top = top-2;  /* pop index and value */
327 }
328 
329 
lua_rawset(lua_State * L,int index)330 LUA_API void lua_rawset (lua_State *L, int index) {
331   StkId t = Index(L, index);
332   LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected");
333   *luaH_set(L, hvalue(t), L->top-2) = *(L->top-1);
334   L->top -= 2;
335 }
336 
337 
lua_rawseti(lua_State * L,int index,int n)338 LUA_API void lua_rawseti (lua_State *L, int index, int n) {
339   StkId o = Index(L, index);
340   LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected");
341   *luaH_setint(L, hvalue(o), n) = *(L->top-1);
342   L->top--;
343 }
344 
345 
lua_setglobals(lua_State * L)346 LUA_API void lua_setglobals (lua_State *L) {
347   StkId newtable = --L->top;
348   LUA_ASSERT(ttype(newtable) == LUA_TTABLE, "table expected");
349   L->gt = hvalue(newtable);
350 }
351 
352 
lua_ref(lua_State * L,int lock)353 LUA_API int lua_ref (lua_State *L,  int lock) {
354   int ref;
355   if (ttype(L->top-1) == LUA_TNIL)
356     ref = LUA_REFNIL;
357   else {
358     if (L->refFree != NONEXT) {  /* is there a free place? */
359       ref = L->refFree;
360       L->refFree = L->refArray[ref].st;
361     }
362     else {  /* no more free places */
363       luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref,
364                       "reference table overflow", MAX_INT);
365       L->nblocks += sizeof(struct Ref);
366       ref = L->refSize++;
367     }
368     L->refArray[ref].o = *(L->top-1);
369     L->refArray[ref].st = lock ? LOCK : HOLD;
370   }
371   L->top--;
372   return ref;
373 }
374 
375 
376 /*
377 ** "do" functions (run Lua code)
378 ** (most of them are in ldo.c)
379 */
380 
lua_rawcall(lua_State * L,int nargs,int nresults)381 LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) {
382   luaD_call(L, L->top-(nargs+1), nresults);
383 }
384 
385 
386 /*
387 ** Garbage-collection functions
388 */
389 
390 /* GC values are expressed in Kbytes: #bytes/2^10 */
391 #define GCscale(x)		((int)((x)>>10))
392 #define GCunscale(x)		((unsigned long)(x)<<10)
393 
lua_getgcthreshold(lua_State * L)394 LUA_API int lua_getgcthreshold (lua_State *L) {
395   return GCscale(L->GCthreshold);
396 }
397 
lua_getgccount(lua_State * L)398 LUA_API int lua_getgccount (lua_State *L) {
399   return GCscale(L->nblocks);
400 }
401 
lua_setgcthreshold(lua_State * L,int newthreshold)402 LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
403   if (newthreshold > GCscale(ULONG_MAX))
404     L->GCthreshold = ULONG_MAX;
405   else
406     L->GCthreshold = GCunscale(newthreshold);
407   luaC_checkGC(L);
408 }
409 
410 
411 /*
412 ** miscellaneous functions
413 */
414 
lua_settag(lua_State * L,int tag)415 LUA_API void lua_settag (lua_State *L, int tag) {
416   luaT_realtag(L, tag);
417   switch (ttype(L->top-1)) {
418     case LUA_TTABLE:
419       hvalue(L->top-1)->htag = tag;
420       break;
421     case LUA_TUSERDATA:
422       tsvalue(L->top-1)->u.d.tag = tag;
423       break;
424     default:
425       luaO_verror(L, "cannot change the tag of a %.20s",
426                   luaO_typename(L->top-1));
427   }
428 }
429 
430 
lua_unref(lua_State * L,int ref)431 LUA_API void lua_unref (lua_State *L, int ref) {
432   if (ref >= 0) {
433     LUA_ASSERT(ref < L->refSize && L->refArray[ref].st < 0, "invalid ref");
434     L->refArray[ref].st = L->refFree;
435     L->refFree = ref;
436   }
437 }
438 
439 
lua_next(lua_State * L,int index)440 LUA_API int lua_next (lua_State *L, int index) {
441   StkId t = luaA_index(L, index);
442   Node *n;
443   LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected");
444   n = luaH_next(L, hvalue(t), luaA_index(L, -1));
445   if (n) {
446     *(L->top-1) = *key(n);
447     *L->top = *val(n);
448     api_incr_top(L);
449     return 1;
450   }
451   else {  /* no more elements */
452     L->top -= 1;  /* remove key */
453     return 0;
454   }
455 }
456 
457 
lua_getn(lua_State * L,int index)458 LUA_API int lua_getn (lua_State *L, int index) {
459   Hash *h = hvalue(luaA_index(L, index));
460   const TObject *value = luaH_getstr(h, luaS_new(L, "n"));  /* value = h.n */
461   if (ttype(value) == LUA_TNUMBER)
462     return (int)nvalue(value);
463   else {
464     Number max = 0;
465     int i = h->size;
466     Node *n = h->node;
467     while (i--) {
468       if (ttype(key(n)) == LUA_TNUMBER &&
469           ttype(val(n)) != LUA_TNIL &&
470           nvalue(key(n)) > max)
471         max = nvalue(key(n));
472       n++;
473     }
474     return (int)max;
475   }
476 }
477 
478 
lua_concat(lua_State * L,int n)479 LUA_API void lua_concat (lua_State *L, int n) {
480   StkId top = L->top;
481   luaV_strconc(L, n, top);
482   L->top = top-(n-1);
483   luaC_checkGC(L);
484 }
485 
486 
lua_newuserdata(lua_State * L,size_t size)487 LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
488   TString *ts = luaS_newudata(L, (size==0) ? 1 : size, NULL);
489   tsvalue(L->top) = ts;
490   ttype(L->top) = LUA_TUSERDATA;
491   api_incr_top(L);
492   return ts->u.d.value;
493 }
494 
495