37 // ok |
37 // ok |
38 return ud; |
38 return ud; |
39 } |
39 } |
40 |
40 |
41 /** |
41 /** |
|
42 * Convenience function to create a new metatable for a type, a userdata for that type, and register it as a global |
|
43 */ |
|
44 static void* lua_obj_create_global_type (lua_State *L, const char *type_name, const struct luaL_Reg methods[], const char *global_name, size_t size) |
|
45 { |
|
46 // allocate the global object |
|
47 void *obj = lua_newuserdata(L, size); |
|
48 |
|
49 // create the type metatable |
|
50 lua_obj_create_type(L, type_name, methods); |
|
51 |
|
52 // set the userdata's metatable |
|
53 lua_setmetatable(L, -2); |
|
54 |
|
55 // store it as a global |
|
56 lua_setglobal(L, global_name); |
|
57 |
|
58 // ok |
|
59 return obj; |
|
60 } |
|
61 |
|
62 /** |
42 * Convenience function to get a userdata with the given type metatable name as the first argument for a function |
63 * Convenience function to get a userdata with the given type metatable name as the first argument for a function |
43 */ |
64 */ |
44 static void* lua_obj_get_obj (lua_State *L, const char *func, const char *name) |
65 static void* lua_obj_get_obj (lua_State *L, const char *func, const char *name) |
45 { |
66 { |
46 void *ud; |
67 void *ud; |
47 |
68 |
48 // validate the userdata arg |
69 // validate the userdata arg |
49 if ((ud = luaL_checkudata(L, 1, name)) == NULL) { |
70 if ((ud = luaL_checkudata(L, 1, name)) == NULL) { |
50 luaL_error(L, "bad type argument to %s: `%s` expected", func, name); |
71 luaL_error(L, "bad type argument to %s: `%s` expected", func, name); |
|
72 |
|
73 // XXX: needs a __noreturn__ attribute |
|
74 return NULL; |
51 |
75 |
52 } else { |
76 } else { |
53 // ok |
77 // ok |
54 return ud; |
78 return ud; |
55 |
79 |
309 { "quit", &lua_client_quit }, |
333 { "quit", &lua_client_quit }, |
310 { NULL, NULL } |
334 { NULL, NULL } |
311 }; |
335 }; |
312 |
336 |
313 /** |
337 /** |
314 * Initializes a lua_irc_client wrapper for the given client in the give lua state. This registers a set of globals for |
338 * Initialize the evirc.client type for lua_client, and registers an instance bound to the given irc_client at |
315 * 'client' and 'networks'. |
339 * 'client'. |
316 */ |
340 */ |
317 static void lua_client_init (lua_State *L, struct irc_client *client) |
341 static void lua_client_init (lua_State *L, struct irc_client *client) |
318 { |
342 { |
319 // allocate the global "client" object |
343 // allocate the global "client" object |
320 struct lua_client *lua_client = lua_newuserdata(L, sizeof(*lua_client)); |
344 struct lua_client *lua_client = lua_obj_create_global_type(L, "evirc.client", lua_client_methods, "client", sizeof(*lua_client)); |
321 |
345 |
322 // create the type metatable |
|
323 lua_obj_create_type(L, "evirc.client", lua_client_methods); |
|
324 |
|
325 // set the client userdata's metatable |
|
326 lua_setmetatable(L, -2); |
|
327 |
|
328 // initialize it |
346 // initialize it |
329 lua_client->client = client; |
347 lua_client->client = client; |
330 |
348 } |
331 // store it as a global |
349 |
332 lua_setglobal(L, "client"); |
350 /** |
|
351 * Wrapper for module |
|
352 */ |
|
353 struct lua_module { |
|
354 struct module *module; |
|
355 }; |
|
356 |
|
357 /** |
|
358 * Create a lua_module userdata from the given module and push it onto the stack, returning 1. |
|
359 */ |
|
360 static int lua_module_create (lua_State *L, struct module *module) |
|
361 { |
|
362 // create the new obj |
|
363 struct lua_module *lua_module = lua_obj_create_obj(L, "spbot.module", sizeof(*lua_module)); |
|
364 |
|
365 // initialize |
|
366 lua_module->module = module; |
|
367 |
|
368 // ok |
|
369 return 1; |
|
370 } |
|
371 |
|
372 static int lua_module_conf (lua_State *L) |
|
373 { |
|
374 struct lua_module *lua_module = lua_obj_get_obj(L, __func__, "spbot.module"); |
|
375 const struct config_option *option; |
|
376 struct config_value value; |
|
377 struct error_info err; |
|
378 |
|
379 // XXX: come up with some better way... |
|
380 struct nexus *nexus = lua_module->module->modules->nexus; |
|
381 |
|
382 // the config name |
|
383 const char *conf_name = luaL_checkstring(L, 2); |
|
384 |
|
385 // the config value |
|
386 // XXX: support lua_chan |
|
387 const char *conf_value = luaL_checkstring(L, 3); |
|
388 |
|
389 // mutable version of the conf_value |
|
390 char conf_value_buf[strlen(conf_value) + 1]; |
|
391 strcpy(conf_value_buf, conf_value); |
|
392 |
|
393 // look it up |
|
394 if ((option = module_conf_lookup(lua_module->module, conf_name, &err)) == NULL) |
|
395 return luaL_error(L, "module_conf_lookup: %s/%s: %s", module_name(lua_module->module), conf_name, error_msg(&err)); |
|
396 |
|
397 // parse it |
|
398 if (config_parse(option, nexus, &value, conf_value_buf, &err)) |
|
399 return luaL_error(L, "config_parse: %s/%s: %s", option->name, conf_value_buf, error_msg(&err)); |
|
400 |
|
401 // apply it |
|
402 if (module_conf(lua_module->module, option, &value, &err)) |
|
403 return luaL_error(L, "module_conf: %s/%s/%s: %s", module_name(lua_module->module), option->name, conf_value_buf, error_msg(&err)); |
|
404 |
|
405 // ok |
|
406 return 0; |
|
407 } |
|
408 |
|
409 static const struct luaL_Reg lua_module_methods[] = { |
|
410 { "conf", &lua_module_conf }, |
|
411 { NULL, NULL } |
|
412 }; |
|
413 |
|
414 /** |
|
415 * Initialize the lua_module object type |
|
416 */ |
|
417 static void lua_module_init (lua_State *L) |
|
418 { |
|
419 lua_obj_create_type(L, "spbot.module", lua_module_methods); |
|
420 } |
|
421 |
|
422 /** |
|
423 * Wrapper for modules |
|
424 */ |
|
425 struct lua_modules { |
|
426 struct modules *modules; |
|
427 }; |
|
428 |
|
429 static int lua_modules_load (lua_State *L) |
|
430 { |
|
431 struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules"); |
|
432 struct module *module; |
|
433 struct module_info info; |
|
434 struct error_info err; |
|
435 |
|
436 // the module name/path |
|
437 info.name = luaL_checkstring(L, 2); |
|
438 info.path = luaL_checkstring(L, 3); |
|
439 |
|
440 // load |
|
441 if (module_load(lua_modules->modules, &module, &info, &err)) |
|
442 return luaL_error(L, "module_load: %s/%s: %s", info.name, info.path, error_msg(&err)); |
|
443 |
|
444 // wrap |
|
445 return lua_module_create(L, module); |
|
446 } |
|
447 |
|
448 static int lua_modules_module (lua_State *L) |
|
449 { |
|
450 struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules"); |
|
451 struct module *module; |
|
452 |
|
453 // the module name |
|
454 const char *name = luaL_checkstring(L, 2); |
|
455 |
|
456 // look it up |
|
457 if ((module = module_get(lua_modules->modules, name)) == NULL) |
|
458 return luaL_error(L, "module_get: %s: no such module", name); |
|
459 |
|
460 // wrap |
|
461 return lua_module_create(L, module); |
|
462 } |
|
463 |
|
464 static const struct luaL_Reg lua_modules_methods[] = { |
|
465 { "load", &lua_modules_load }, |
|
466 { "module", &lua_modules_module }, |
|
467 { NULL, NULL } |
|
468 }; |
|
469 |
|
470 /** |
|
471 * Initialize the spbot.modules type for lua_modules, and registers an instance bound to the given modules list at |
|
472 * 'modules'. |
|
473 */ |
|
474 static void lua_modules_init (lua_State *L, struct modules *modules) |
|
475 { |
|
476 // allocate the global "modules" object |
|
477 struct lua_modules *lua_modules = lua_obj_create_global_type(L, "spbot.modules", lua_modules_methods, "modules", sizeof(*lua_modules)); |
|
478 |
|
479 // initialize it |
|
480 lua_modules->modules = modules; |
|
481 } |
|
482 |
|
483 /** |
|
484 * Wrapper for nexus |
|
485 */ |
|
486 struct lua_nexus { |
|
487 struct nexus *nexus; |
|
488 }; |
|
489 |
|
490 static int lua_nexus_shutdown (lua_State *L) |
|
491 { |
|
492 struct lua_nexus *lua_nexus = lua_obj_get_obj(L, __func__, "spbot.nexus"); |
|
493 |
|
494 // just shut it down |
|
495 nexus_shutdown(lua_nexus->nexus); |
|
496 |
|
497 return 0; |
|
498 } |
|
499 |
|
500 static const struct luaL_Reg lua_nexus_methods[] = { |
|
501 { "shutdown", &lua_nexus_shutdown }, |
|
502 { NULL, NULL } |
|
503 }; |
|
504 |
|
505 /** |
|
506 * Initialize the spbot.nexus type for lua_nexus, and registers an instance bound to the given nexus list at |
|
507 * 'nexus'. |
|
508 */ |
|
509 static void lua_nexus_init (lua_State *L, struct nexus *nexus) |
|
510 { |
|
511 // allocate the global "nexus" object |
|
512 struct lua_nexus *lua_nexus = lua_obj_create_global_type(L, "spbot.nexus", lua_nexus_methods, "nexus", sizeof(*lua_nexus)); |
|
513 |
|
514 // initialize it |
|
515 lua_nexus->nexus = nexus; |
333 } |
516 } |
334 |
517 |
335 /** |
518 /** |
336 * Set up the lua state in protected mode |
519 * Set up the lua state in protected mode |
337 */ |
520 */ |