17 #define _RPMLUA_INTERNAL
22 #if !defined(HAVE_VSNPRINTF)
23 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
24 const char * fmt, va_list ap)
26 return vsprintf(buf, fmt, ap);
30 static int luaopen_rpm(lua_State *L)
32 static int rpm_print(lua_State *L)
33 /*@globals fileSystem @*/
34 /*@modifies L, fileSystem @*/;
38 rpmlua lua = (rpmlua) xcalloc(1, sizeof(*lua));
39 lua_State *L = lua_open();
41 /*@observer@*/ /*@unchecked@*/
42 static const luaL_reg lualibs[] = {
43 {"base", luaopen_base},
44 {"table", luaopen_table},
46 {"string", luaopen_string},
47 {"debug", luaopen_debug},
48 {"loadlib", luaopen_loadlib},
49 {"posix", luaopen_posix},
54 /*@observer@*/ /*@unchecked@*/
55 static const luaL_reg *lib = lualibs;
59 for (; lib->name; lib++) {
63 lua_pushliteral(L, "LUA_PATH");
64 lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua");
65 lua_rawset(L, LUA_GLOBALSINDEX);
66 lua_pushliteral(L, "print");
67 lua_pushcfunction(L, rpm_print);
68 lua_rawset(L, LUA_GLOBALSINDEX);
69 rpmluaSetData(lua, "lua", lua);
73 void *rpmluaFree(rpmlua lua)
76 if (lua->L) lua_close(lua->L);
83 void rpmluaSetData(rpmlua lua, const char *key, const void *data)
85 lua_State *L = lua->L;
86 lua_pushliteral(L, "rpm_");
87 lua_pushstring(L, key);
92 lua_pushlightuserdata(L, (void *)data);
93 lua_rawset(L, LUA_REGISTRYINDEX);
96 static void *getdata(lua_State *L, const char *key)
100 lua_pushliteral(L, "rpm_");
101 lua_pushstring(L, key);
103 lua_rawget(L, LUA_REGISTRYINDEX);
104 if (lua_islightuserdata(L, -1))
105 ret = lua_touserdata(L, -1);
110 void *rpmluaGetData(rpmlua lua, const char *key)
112 return getdata(lua->L, key);
115 void rpmluaSetPrintBuffer(rpmlua lua, int flag)
117 lua->storeprint = flag;
119 lua->printbuf = NULL;
120 lua->printbufsize = 0;
123 const char *rpmluaGetPrintBuffer(rpmlua lua)
125 return lua->printbuf;
128 static int pushvar(lua_State *L, rpmluavType type, void *value)
137 lua_pushstring(L, *((char **)value));
140 lua_pushnumber(L, *((double *)value));
149 void rpmluaSetVar(rpmlua lua, rpmluav var)
151 lua_State *L = lua->L;
152 if (var->listmode && lua->pushsize > 0) {
153 if (var->keyType != RPMLUAV_NUMBER || var->key.num == 0) {
154 var->keyType = RPMLUAV_NUMBER;
155 var->key.num = luaL_getn(L, -1);
159 if (!var->listmode || lua->pushsize > 0) {
160 if (lua->pushsize == 0)
161 lua_pushvalue(L, LUA_GLOBALSINDEX);
162 if (pushvar(L, var->keyType, &var->key) != -1) {
163 if (pushvar(L, var->valueType, &var->value) != -1)
168 if (lua->pushsize == 0)
173 static void popvar(lua_State *L, rpmluavType *type, void *value)
174 /*@modifies L, *type, *value @*/
176 switch (lua_type(L, -1)) {
178 *type = RPMLUAV_STRING;
179 *((const char **)value) = lua_tostring(L, -1);
182 *type = RPMLUAV_NUMBER;
183 *((double *)value) = lua_tonumber(L, -1);
187 *((void **)value) = NULL;
193 void rpmluaGetVar(rpmlua lua, rpmluav var)
195 lua_State *L = lua->L;
196 if (!var->listmode) {
197 if (lua->pushsize == 0)
198 lua_pushvalue(L, LUA_GLOBALSINDEX);
199 if (pushvar(L, var->keyType, &var->key) != -1) {
201 popvar(L, &var->valueType, &var->value);
203 if (lua->pushsize == 0)
205 } else if (lua->pushsize > 0) {
206 pushvar(L, var->keyType, &var->key);
207 if (lua_next(L, -2) != 0)
208 popvar(L, &var->valueType, &var->value);
212 #define FINDKEY_RETURN 0
213 #define FINDKEY_CREATE 1
214 #define FINDKEY_REMOVE 2
215 static int findkey(lua_State *L, int oper, const char *key, va_list va)
221 vsnprintf(buf, BUFSIZ, key, va);
223 lua_pushvalue(L, LUA_GLOBALSINDEX);
225 if (*e == '\0' || *e == '.') {
227 lua_pushlstring(L, s, e-s);
234 /*@switchbreak@*/ break;
240 /*@switchbreak@*/ break;
243 if (!lua_istable(L, -1)) {
246 lua_pushlstring(L, s, e-s);
247 lua_pushvalue(L, -2);
251 /*@switchbreak@*/ break;
256 if (!lua_istable(L, -1)) {
269 void rpmluaDelVar(rpmlua lua, const char *key, ...)
273 findkey(lua->L, FINDKEY_REMOVE, key, va);
277 int rpmluaVarExists(rpmlua lua, const char *key, ...)
282 if (findkey(lua->L, FINDKEY_RETURN, key, va) == 0) {
283 if (!lua_isnil(lua->L, -1))
291 void rpmluaPushTable(rpmlua lua, const char *key, ...)
295 findkey(lua->L, FINDKEY_CREATE, key, va);
300 void rpmluaPop(rpmlua lua)
302 assert(lua->pushsize > 0);
307 rpmluav rpmluavNew(void)
309 rpmluav var = (rpmluav) xcalloc(1, sizeof(*var));
313 void *rpmluavFree(rpmluav var)
319 void rpmluavSetListMode(rpmluav var, int flag)
321 var->listmode = flag;
322 var->keyType = RPMLUAV_NIL;
325 void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
330 var->key.num = *((double *)value);
333 var->key.str = (char *)value;
340 void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
342 var->valueType = type;
345 var->value.num = *((const double *)value);
348 var->value.str = (const char *)value;
355 void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
357 *type = var->keyType;
358 switch (var->keyType) {
360 *((double **)value) = &var->key.num;
363 *((const char **)value) = var->key.str;
370 void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
372 *type = var->valueType;
373 switch (var->valueType) {
375 *((double **)value) = &var->value.num;
378 *((const char **)value) = var->value.str;
385 void rpmluavSetKeyNum(rpmluav var, double value)
387 rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
390 void rpmluavSetValueNum(rpmluav var, double value)
392 rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
395 double rpmluavGetKeyNum(rpmluav var)
399 rpmluavGetKey(var, &type, &value);
400 if (type == RPMLUAV_NUMBER)
401 return *((double *)value);
405 double rpmluavGetValueNum(rpmluav var)
409 rpmluavGetValue(var, &type, &value);
410 if (type == RPMLUAV_NUMBER)
411 return *((double *)value);
415 int rpmluavKeyIsNum(rpmluav var)
417 return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
420 int rpmluavValueIsNum(rpmluav var)
422 return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
425 int rpmluaCheckScript(rpmlua lua, const char *script, const char *name)
427 lua_State *L = lua->L;
431 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
432 rpmError(RPMERR_SCRIPT,
433 _("invalid syntax in lua scriptlet: %s\n"),
434 lua_tostring(L, -1));
437 lua_pop(L, 1); /* Error or chunk. */
441 int rpmluaRunScript(rpmlua lua, const char *script, const char *name)
443 lua_State *L = lua->L;
447 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
448 rpmError(RPMERR_SCRIPT, _("invalid syntax in lua script: %s\n"),
449 lua_tostring(L, -1));
452 } else if (lua_pcall(L, 0, 0, 0) != 0) {
453 rpmError(RPMERR_SCRIPT, _("lua script failed: %s\n"),
454 lua_tostring(L, -1));
462 static int rpmluaReadline(lua_State *L, const char *prompt)
463 /*@globals fileSystem @*/
464 /*@modifies L, fileSystem @*/
466 static char buffer[1024];
468 fputs(prompt, stdout);
471 if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
472 return 0; /* read fails */
474 lua_pushstring(L, buffer);
480 static void _rpmluaInteractive(lua_State *L)
481 /*@globals fileSystem @*/
482 /*@modifies L, fileSystem @*/
485 printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
489 if (rpmluaReadline(L, "> ") == 0)
491 if (lua_tostring(L, -1)[0] == '=') {
492 lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
496 rc = luaL_loadbuffer(L, lua_tostring(L, -1),
497 lua_strlen(L, -1), "<lua>");
498 if (rc == LUA_ERRSYNTAX &&
499 strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
500 if (rpmluaReadline(L, ">> ") == 0)
501 /*@innerbreak@*/ break;
502 lua_remove(L, -2); /* Remove error */
504 /*@innercontinue@*/ continue;
506 /*@innerbreak@*/ break;
509 rc = lua_pcall(L, 0, 0, 0);
511 fprintf(stderr, "%s\n", lua_tostring(L, -1));
514 lua_pop(L, 1); /* Remove line */
519 void rpmluaInteractive(rpmlua lua)
521 _rpmluaInteractive(lua->L);
524 /* ------------------------------------------------------------------ */
527 static int rpm_expand(lua_State *L)
528 /*@globals rpmGlobalMacroContext, h_errno @*/
529 /*@modifies L, rpmGlobalMacroContext @*/
531 const char *str = luaL_checkstring(L, 1);
532 lua_pushstring(L, rpmExpand(str, NULL));
536 static int rpm_define(lua_State *L)
537 /*@globals rpmGlobalMacroContext, h_errno @*/
538 /*@modifies L, rpmGlobalMacroContext @*/
540 const char *str = luaL_checkstring(L, 1);
541 rpmDefineMacro(NULL, str, 0);
545 static int rpm_interactive(lua_State *L)
546 /*@globals fileSystem @*/
547 /*@modifies L, fileSystem @*/
549 _rpmluaInteractive(L);
553 /* Based on luaB_print. */
554 static int rpm_print (lua_State *L)
555 /*@globals fileSystem @*/
556 /*@modifies L, fileSystem @*/
558 rpmlua lua = (rpmlua)getdata(L, "lua");
559 int n = lua_gettop(L); /* number of arguments */
562 lua_getglobal(L, "tostring");
563 for (i = 1; i <= n; i++) {
565 lua_pushvalue(L, -1); /* function to be called */
566 lua_pushvalue(L, i); /* value to print */
568 s = lua_tostring(L, -1); /* get result */
570 return luaL_error(L, "`tostring' must return a string to `print'");
571 if (lua->storeprint) {
572 int sl = lua_strlen(L, -1);
573 if (lua->printbufused+sl+1 > lua->printbufsize) {
574 lua->printbufsize += sl+512;
575 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
578 lua->printbuf[lua->printbufused++] = '\t';
579 memcpy(lua->printbuf+lua->printbufused, s, sl+1);
580 lua->printbufused += sl;
586 lua_pop(L, 1); /* pop result */
589 if (!lua->storeprint) {
592 if (lua->printbufused+1 >= lua->printbufsize) {
593 lua->printbufsize += 512;
594 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
596 lua->printbuf[lua->printbufused++] = '\n';
597 lua->printbuf[lua->printbufused] = '\0';
603 /*@observer@*/ /*@unchecked@*/
604 static const luaL_reg rpmlib[] = {
605 {"expand", rpm_expand},
606 {"define", rpm_define},
607 {"interactive", rpm_interactive},
612 static int luaopen_rpm(lua_State *L)
615 lua_pushvalue(L, LUA_GLOBALSINDEX);
616 luaL_openlib(L, "rpm", rpmlib, 0);