1 /*@-bounds -realcompare -sizeoftype @*/
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 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);
105 if (lua_islightuserdata(L, -1))
106 ret = lua_touserdata(L, -1);
112 void *rpmluaGetData(rpmlua lua, const char *key)
114 return getdata(lua->L, key);
117 void rpmluaSetPrintBuffer(rpmlua lua, int flag)
119 lua->storeprint = flag;
121 lua->printbuf = NULL;
122 lua->printbufsize = 0;
125 const char *rpmluaGetPrintBuffer(rpmlua lua)
127 return lua->printbuf;
130 static int pushvar(lua_State *L, rpmluavType type, void *value)
139 lua_pushstring(L, *((char **)value));
142 lua_pushnumber(L, *((double *)value));
151 void rpmluaSetVar(rpmlua lua, rpmluav var)
153 lua_State *L = lua->L;
154 if (var->listmode && lua->pushsize > 0) {
155 if (var->keyType != RPMLUAV_NUMBER || var->key.num == (double)0) {
156 var->keyType = RPMLUAV_NUMBER;
157 var->key.num = (double) luaL_getn(L, -1);
161 if (!var->listmode || lua->pushsize > 0) {
162 if (lua->pushsize == 0)
163 lua_pushvalue(L, LUA_GLOBALSINDEX);
164 if (pushvar(L, var->keyType, &var->key) != -1) {
165 if (pushvar(L, var->valueType, &var->value) != -1)
170 if (lua->pushsize == 0)
175 static void popvar(lua_State *L, rpmluavType *type, void *value)
176 /*@modifies L, *type, *value @*/
178 switch (lua_type(L, -1)) {
180 *type = RPMLUAV_STRING;
181 /*@-observertrans -dependenttrans @*/
182 *((const char **)value) = lua_tostring(L, -1);
183 /*@=observertrans =dependenttrans @*/
186 *type = RPMLUAV_NUMBER;
187 *((double *)value) = lua_tonumber(L, -1);
191 *((void **)value) = NULL;
197 void rpmluaGetVar(rpmlua lua, rpmluav var)
199 lua_State *L = lua->L;
200 if (!var->listmode) {
201 if (lua->pushsize == 0)
202 lua_pushvalue(L, LUA_GLOBALSINDEX);
203 if (pushvar(L, var->keyType, &var->key) != -1) {
205 popvar(L, &var->valueType, &var->value);
207 if (lua->pushsize == 0)
209 } else if (lua->pushsize > 0) {
210 (void) pushvar(L, var->keyType, &var->key);
211 if (lua_next(L, -2) != 0)
212 popvar(L, &var->valueType, &var->value);
216 #define FINDKEY_RETURN 0
217 #define FINDKEY_CREATE 1
218 #define FINDKEY_REMOVE 2
219 static int findkey(lua_State *L, int oper, const char *key, va_list va)
225 (void) vsnprintf(buf, BUFSIZ, key, va);
227 lua_pushvalue(L, LUA_GLOBALSINDEX);
229 if (*e == '\0' || *e == '.') {
231 lua_pushlstring(L, s, e-s);
238 /*@switchbreak@*/ break;
244 /*@switchbreak@*/ break;
247 if (!lua_istable(L, -1)) {
250 lua_pushlstring(L, s, e-s);
251 lua_pushvalue(L, -2);
255 /*@switchbreak@*/ break;
260 if (!lua_istable(L, -1)) {
273 void rpmluaDelVar(rpmlua lua, const char *key, ...)
277 (void) findkey(lua->L, FINDKEY_REMOVE, key, va);
281 int rpmluaVarExists(rpmlua lua, const char *key, ...)
286 if (findkey(lua->L, FINDKEY_RETURN, key, va) == 0) {
287 if (!lua_isnil(lua->L, -1))
295 void rpmluaPushTable(rpmlua lua, const char *key, ...)
299 (void) findkey(lua->L, FINDKEY_CREATE, key, va);
304 void rpmluaPop(rpmlua lua)
306 assert(lua->pushsize > 0);
311 rpmluav rpmluavNew(void)
313 rpmluav var = (rpmluav) xcalloc(1, sizeof(*var));
317 void *rpmluavFree(rpmluav var)
323 void rpmluavSetListMode(rpmluav var, int flag)
325 var->listmode = flag;
326 var->keyType = RPMLUAV_NIL;
329 void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
332 /*@-assignexpose -branchstate -temptrans @*/
335 var->key.num = *((double *)value);
338 var->key.str = (char *)value;
343 /*@=assignexpose =branchstate =temptrans @*/
346 void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
348 var->valueType = type;
349 /*@-assignexpose -branchstate -temptrans @*/
352 var->value.num = *((const double *)value);
355 var->value.str = (const char *)value;
360 /*@=assignexpose =branchstate =temptrans @*/
363 void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
365 *type = var->keyType;
367 switch (var->keyType) {
369 *((double **)value) = &var->key.num;
372 *((const char **)value) = var->key.str;
380 void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
382 *type = var->valueType;
384 switch (var->valueType) {
386 *((double **)value) = &var->value.num;
389 *((const char **)value) = var->value.str;
397 void rpmluavSetKeyNum(rpmluav var, double value)
399 rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
402 void rpmluavSetValueNum(rpmluav var, double value)
404 rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
407 double rpmluavGetKeyNum(rpmluav var)
411 rpmluavGetKey(var, &type, &value);
412 if (type == RPMLUAV_NUMBER)
413 return *((double *)value);
417 double rpmluavGetValueNum(rpmluav var)
421 rpmluavGetValue(var, &type, &value);
422 if (type == RPMLUAV_NUMBER)
423 return *((double *)value);
427 int rpmluavKeyIsNum(rpmluav var)
429 return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
432 int rpmluavValueIsNum(rpmluav var)
434 return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
437 int rpmluaCheckScript(rpmlua lua, const char *script, const char *name)
439 lua_State *L = lua->L;
445 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
446 rpmError(RPMERR_SCRIPT,
447 _("invalid syntax in lua scriptlet: %s\n"),
448 lua_tostring(L, -1));
451 lua_pop(L, 1); /* Error or chunk. */
455 int rpmluaRunScript(rpmlua lua, const char *script, const char *name)
457 lua_State *L = lua->L;
463 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
464 rpmError(RPMERR_SCRIPT, _("invalid syntax in lua script: %s\n"),
465 lua_tostring(L, -1));
468 } else if (lua_pcall(L, 0, 0, 0) != 0) {
469 rpmError(RPMERR_SCRIPT, _("lua script failed: %s\n"),
470 lua_tostring(L, -1));
478 static int rpmluaReadline(lua_State *L, const char *prompt)
479 /*@globals fileSystem @*/
480 /*@modifies L, fileSystem @*/
482 static char buffer[1024];
484 (void) fputs(prompt, stdout);
485 (void) fflush(stdout);
487 if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
488 return 0; /* read fails */
490 lua_pushstring(L, buffer);
496 static void _rpmluaInteractive(lua_State *L)
497 /*@globals fileSystem @*/
498 /*@modifies L, fileSystem @*/
500 (void) fputs("\n", stdout);
501 printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
505 if (rpmluaReadline(L, "> ") == 0)
507 if (lua_tostring(L, -1)[0] == '=') {
509 (void) lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
515 rc = luaL_loadbuffer(L, lua_tostring(L, -1),
516 lua_strlen(L, -1), "<lua>");
518 if (rc == LUA_ERRSYNTAX &&
519 strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
520 if (rpmluaReadline(L, ">> ") == 0)
521 /*@innerbreak@*/ break;
522 lua_remove(L, -2); /* Remove error */
524 /*@innercontinue@*/ continue;
526 /*@innerbreak@*/ break;
529 rc = lua_pcall(L, 0, 0, 0);
531 fprintf(stderr, "%s\n", lua_tostring(L, -1));
534 lua_pop(L, 1); /* Remove line */
536 (void) fputs("\n", stdout);
539 void rpmluaInteractive(rpmlua lua)
541 _rpmluaInteractive(lua->L);
544 /* ------------------------------------------------------------------ */
547 static int rpm_expand(lua_State *L)
548 /*@globals rpmGlobalMacroContext, h_errno @*/
549 /*@modifies L, rpmGlobalMacroContext @*/
551 const char *str = luaL_checkstring(L, 1);
552 lua_pushstring(L, rpmExpand(str, NULL));
556 static int rpm_define(lua_State *L)
557 /*@globals rpmGlobalMacroContext, h_errno @*/
558 /*@modifies L, rpmGlobalMacroContext @*/
560 const char *str = luaL_checkstring(L, 1);
561 (void) rpmDefineMacro(NULL, str, 0);
565 static int rpm_interactive(lua_State *L)
566 /*@globals fileSystem @*/
567 /*@modifies L, fileSystem @*/
569 _rpmluaInteractive(L);
573 /* Based on luaB_print. */
574 static int rpm_print (lua_State *L)
575 /*@globals fileSystem @*/
576 /*@modifies L, fileSystem @*/
578 rpmlua lua = (rpmlua)getdata(L, "lua");
579 int n = lua_gettop(L); /* number of arguments */
582 lua_getglobal(L, "tostring");
583 for (i = 1; i <= n; i++) {
585 lua_pushvalue(L, -1); /* function to be called */
586 lua_pushvalue(L, i); /* value to print */
588 s = lua_tostring(L, -1); /* get result */
590 return luaL_error(L, "`tostring' must return a string to `print'");
591 if (lua->storeprint) {
592 int sl = lua_strlen(L, -1);
593 if (lua->printbufused+sl+1 > lua->printbufsize) {
594 lua->printbufsize += sl+512;
595 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
598 lua->printbuf[lua->printbufused++] = '\t';
599 memcpy(lua->printbuf+lua->printbufused, s, sl+1);
600 lua->printbufused += sl;
603 (void) fputs("\t", stdout);
604 (void) fputs(s, stdout);
606 lua_pop(L, 1); /* pop result */
609 if (!lua->storeprint) {
610 (void) fputs("\n", stdout);
612 if (lua->printbufused+1 >= lua->printbufsize) {
613 lua->printbufsize += 512;
614 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
616 lua->printbuf[lua->printbufused++] = '\n';
617 lua->printbuf[lua->printbufused] = '\0';
623 /*@observer@*/ /*@unchecked@*/
624 static const luaL_reg rpmlib[] = {
625 {"expand", rpm_expand},
626 {"define", rpm_define},
627 {"interactive", rpm_interactive},
632 static int luaopen_rpm(lua_State *L)
635 lua_pushvalue(L, LUA_GLOBALSINDEX);
636 luaL_openlib(L, "rpm", rpmlib, 0);
639 /*@=bounds =realcompare =sizeoftype @*/