1 /*
2 ** $Id: lauxlib.c,v 1.1 2002/02/14 10:46:59 jcatki Exp $
3 ** Auxiliary functions for building Lua libraries
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 /* This file uses only the official API of Lua.
13 ** Any function declared here could be written as an application function.
14 ** With care, these functions can be used by other libraries.
15 */
16 
17 #include "lua.h"
18 
19 #include "lauxlib.h"
20 #include "luadebug.h"
21 
22 
23 
luaL_findstring(const char * name,const char * const list[])24 LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
25   int i;
26   for (i=0; list[i]; i++)
27     if (strcmp(list[i], name) == 0)
28       return i;
29   return -1;  /* name not found */
30 }
31 
luaL_argerror(lua_State * L,int narg,const char * extramsg)32 LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) {
33   lua_Debug ar;
34   lua_getstack(L, 0, &ar);
35   lua_getinfo(L, "n", &ar);
36   if (ar.name == NULL)
37     ar.name = "?";
38   luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)",
39               narg, ar.name, extramsg);
40 }
41 
42 
type_error(lua_State * L,int narg,int t)43 static void type_error (lua_State *L, int narg, int t) {
44   char buff[50];
45   sprintf(buff, "%.8s expected, got %.8s", lua_typename(L, t),
46                                            lua_typename(L, lua_type(L, narg)));
47   luaL_argerror(L, narg, buff);
48 }
49 
50 
luaL_checkstack(lua_State * L,int space,const char * mes)51 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
52   if (space > lua_stackspace(L))
53     luaL_verror(L, "stack overflow (%.30s)", mes);
54 }
55 
56 
luaL_checktype(lua_State * L,int narg,int t)57 LUALIB_API void luaL_checktype(lua_State *L, int narg, int t) {
58   if (lua_type(L, narg) != t)
59     type_error(L, narg, t);
60 }
61 
62 
luaL_checkany(lua_State * L,int narg)63 LUALIB_API void luaL_checkany (lua_State *L, int narg) {
64   if (lua_type(L, narg) == LUA_TNONE)
65     luaL_argerror(L, narg, "value expected");
66 }
67 
68 
luaL_check_lstr(lua_State * L,int narg,size_t * len)69 LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) {
70   const char *s = lua_tostring(L, narg);
71   if (!s) type_error(L, narg, LUA_TSTRING);
72   if (len) *len = lua_strlen(L, narg);
73   return s;
74 }
75 
76 
luaL_opt_lstr(lua_State * L,int narg,const char * def,size_t * len)77 LUALIB_API const char *luaL_opt_lstr (lua_State *L, int narg, const char *def, size_t *len) {
78   if (lua_isnull(L, narg)) {
79     if (len)
80       *len = (def ? strlen(def) : 0);
81     return def;
82   }
83   else return luaL_check_lstr(L, narg, len);
84 }
85 
86 
luaL_check_number(lua_State * L,int narg)87 LUALIB_API double luaL_check_number (lua_State *L, int narg) {
88   double d = lua_tonumber(L, narg);
89   if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
90     type_error(L, narg, LUA_TNUMBER);
91   return d;
92 }
93 
94 
luaL_opt_number(lua_State * L,int narg,double def)95 LUALIB_API double luaL_opt_number (lua_State *L, int narg, double def) {
96   if (lua_isnull(L, narg)) return def;
97   else return luaL_check_number(L, narg);
98 }
99 
100 
luaL_openlib(lua_State * L,const struct luaL_reg * l,int n)101 LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n) {
102   int i;
103   for (i=0; i<n; i++)
104     lua_register(L, l[i].name, l[i].func);
105 }
106 
107 
luaL_verror(lua_State * L,const char * fmt,...)108 LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...) {
109   char buff[500];
110   va_list argp;
111   va_start(argp, fmt);
112   vsprintf(buff, fmt, argp);
113   va_end(argp);
114   lua_error(L, buff);
115 }
116 
117 
118 /*
119 ** {======================================================
120 ** Generic Buffer manipulation
121 ** =======================================================
122 */
123 
124 
125 #define buffempty(B)	((B)->p == (B)->buffer)
126 #define bufflen(B)	((B)->p - (B)->buffer)
127 #define bufffree(B)	((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
128 
129 #define LIMIT	(LUA_MINSTACK/2)
130 
131 
emptybuffer(luaL_Buffer * B)132 static int emptybuffer (luaL_Buffer *B) {
133   size_t l = bufflen(B);
134   if (l == 0) return 0;  /* put nothing on stack */
135   else {
136     lua_pushlstring(B->L, B->buffer, l);
137     B->p = B->buffer;
138     B->level++;
139     return 1;
140   }
141 }
142 
143 
adjuststack(luaL_Buffer * B)144 static void adjuststack (luaL_Buffer *B) {
145   if (B->level > 1) {
146     lua_State *L = B->L;
147     int toget = 1;  /* number of levels to concat */
148     size_t toplen = lua_strlen(L, -1);
149     do {
150       size_t l = lua_strlen(L, -(toget+1));
151       if (B->level - toget + 1 >= LIMIT || toplen > l) {
152         toplen += l;
153         toget++;
154       }
155       else break;
156     } while (toget < B->level);
157     if (toget >= 2) {
158       lua_concat(L, toget);
159       B->level = B->level - toget + 1;
160     }
161   }
162 }
163 
164 
luaL_prepbuffer(luaL_Buffer * B)165 LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
166   if (emptybuffer(B))
167     adjuststack(B);
168   return B->buffer;
169 }
170 
171 
luaL_addlstring(luaL_Buffer * B,const char * s,size_t l)172 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
173   while (l--)
174     luaL_putchar(B, *s++);
175 }
176 
177 
luaL_addstring(luaL_Buffer * B,const char * s)178 LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
179   luaL_addlstring(B, s, strlen(s));
180 }
181 
182 
luaL_pushresult(luaL_Buffer * B)183 LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
184   emptybuffer(B);
185   if (B->level == 0)
186     lua_pushlstring(B->L, NULL, 0);
187   else if (B->level > 1)
188     lua_concat(B->L, B->level);
189   B->level = 1;
190 }
191 
192 
luaL_addvalue(luaL_Buffer * B)193 LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
194   lua_State *L = B->L;
195   size_t vl = lua_strlen(L, -1);
196   if (vl <= bufffree(B)) {  /* fit into buffer? */
197     memcpy(B->p, lua_tostring(L, -1), vl);  /* put it there */
198     B->p += vl;
199     lua_pop(L, 1);  /* remove from stack */
200   }
201   else {
202     if (emptybuffer(B))
203       lua_insert(L, -2);  /* put buffer before new value */
204     B->level++;  /* add new value into B stack */
205     adjuststack(B);
206   }
207 }
208 
209 
luaL_buffinit(lua_State * L,luaL_Buffer * B)210 LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
211   B->L = L;
212   B->p = B->buffer;
213   B->level = 0;
214 }
215 
216 /* }====================================================== */
217