NCDModule.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /**
  2. * @file NCDModule.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdarg.h>
  30. #include <string.h>
  31. #include <stddef.h>
  32. #include <inttypes.h>
  33. #include <limits.h>
  34. #include <misc/offset.h>
  35. #include <ncd/NCDModule.h>
  36. #include <ncd/static_strings.h>
  37. #define STATE_DEAD 0
  38. #define STATE_DOWN_CLEAN 1
  39. #define STATE_UP 2
  40. #define STATE_DOWN_UNCLEAN 3
  41. #define STATE_DYING 4
  42. #define PROCESS_STATE_INIT 0
  43. #define PROCESS_STATE_DOWN 1
  44. #define PROCESS_STATE_UP 2
  45. #define PROCESS_STATE_DOWN_WAITING 3
  46. #define PROCESS_STATE_TERMINATING 4
  47. #define PROCESS_STATE_TERMINATED 5
  48. static int object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
  49. static int object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
  50. static int process_args_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
  51. static int process_arg_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
  52. static void frontend_event (NCDModuleInst *n, int event)
  53. {
  54. n->params->func_event(n, event);
  55. }
  56. static void inst_assert_backend (NCDModuleInst *n)
  57. {
  58. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  59. n->state == STATE_UP ||
  60. n->state == STATE_DYING)
  61. }
  62. static void set_process_state (NCDModuleProcess *p, int state)
  63. {
  64. #ifndef NDEBUG
  65. p->state = state;
  66. #endif
  67. }
  68. static NCDObject persistent_obj_retobj (NCDPersistentObj const *pobj)
  69. {
  70. NCDModuleInst *n = UPPER_OBJECT(pobj, NCDModuleInst, pobj);
  71. return NCDModuleInst_Object(n);
  72. }
  73. void NCDModuleInst_Init (NCDModuleInst *n, const struct NCDInterpModule *m, void *method_context, NCDValRef args, const struct NCDModuleInst_params *params)
  74. {
  75. ASSERT(m)
  76. ASSERT(m->module.func_new2)
  77. ASSERT(m->module.alloc_size >= 0)
  78. ASSERT(m->base_type_id >= 0)
  79. ASSERT(m->group)
  80. ASSERT(n->mem)
  81. ASSERT(NCDVal_IsList(args))
  82. ASSERT(params)
  83. ASSERT(params->func_event)
  84. ASSERT(params->func_getobj)
  85. ASSERT(params->logfunc)
  86. ASSERT(params->iparams)
  87. ASSERT(params->iparams->func_initprocess)
  88. ASSERT(params->iparams->func_interp_exit)
  89. ASSERT(params->iparams->func_interp_getargs)
  90. ASSERT(params->iparams->func_interp_getretrytime)
  91. // init arguments
  92. n->m = m;
  93. n->params = params;
  94. // set initial state
  95. n->state = STATE_DOWN_CLEAN;
  96. // give NCDModuleInst to methods, not mem
  97. n->pass_mem_to_methods = 0;
  98. // init persistent object interface
  99. NCDPersistentObj_Init(&n->pobj, persistent_obj_retobj);
  100. DebugObject_Init(&n->d_obj);
  101. struct NCDModuleInst_new_params new_params;
  102. new_params.method_user = method_context;
  103. new_params.args = args;
  104. n->m->module.func_new2(n->mem, n, &new_params);
  105. }
  106. void NCDModuleInst_Free (NCDModuleInst *n)
  107. {
  108. DebugObject_Free(&n->d_obj);
  109. ASSERT(n->state == STATE_DEAD)
  110. // free persistent object interface
  111. NCDPersistentObj_Free(&n->pobj);
  112. }
  113. void NCDModuleInst_Die (NCDModuleInst *n)
  114. {
  115. DebugObject_Access(&n->d_obj);
  116. ASSERT(n->state == STATE_UP || n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN)
  117. n->state = STATE_DYING;
  118. if (!n->m->module.func_die) {
  119. NCDModuleInst_Backend_Dead(n);
  120. return;
  121. }
  122. n->m->module.func_die(n->mem);
  123. return;
  124. }
  125. int NCDModuleInst_TryFree (NCDModuleInst *n)
  126. {
  127. DebugObject_Access(&n->d_obj);
  128. ASSERT(n->state == STATE_UP || n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN)
  129. if (n->m->module.func_die) {
  130. return 0;
  131. }
  132. DebugObject_Free(&n->d_obj);
  133. // free persistent object interface
  134. NCDPersistentObj_Free(&n->pobj);
  135. return 1;
  136. }
  137. void NCDModuleInst_Clean (NCDModuleInst *n)
  138. {
  139. DebugObject_Access(&n->d_obj);
  140. ASSERT(n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN)
  141. if (n->state == STATE_DOWN_UNCLEAN) {
  142. n->state = STATE_DOWN_CLEAN;
  143. if (n->m->module.func_clean) {
  144. n->m->module.func_clean(n->mem);
  145. return;
  146. }
  147. }
  148. }
  149. NCDObject NCDModuleInst_Object (NCDModuleInst *n)
  150. {
  151. DebugObject_Access(&n->d_obj);
  152. ASSERT(n->m->base_type_id >= 0)
  153. void *method_user = (n->pass_mem_to_methods ? n->mem : n);
  154. return NCDObject_BuildFull(n->m->base_type_id, n, 0, method_user, object_func_getvar, object_func_getobj, &n->pobj);
  155. }
  156. void NCDModuleInst_Backend_PassMemToMethods (NCDModuleInst *n)
  157. {
  158. DebugObject_Access(&n->d_obj);
  159. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  160. n->state == STATE_UP ||
  161. n->state == STATE_DYING)
  162. n->pass_mem_to_methods = 1;
  163. }
  164. static int can_resolve (NCDModuleInst *n)
  165. {
  166. switch (n->state) {
  167. case STATE_UP:
  168. return 1;
  169. case STATE_DOWN_CLEAN:
  170. case STATE_DOWN_UNCLEAN:
  171. return !!(n->m->module.flags & NCDMODULE_FLAG_CAN_RESOLVE_WHEN_DOWN);
  172. default:
  173. return 0;
  174. }
  175. }
  176. static int object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
  177. {
  178. NCDModuleInst *n = NCDObject_DataPtr(obj);
  179. DebugObject_Access(&n->d_obj);
  180. if ((!n->m->module.func_getvar && !n->m->module.func_getvar2) || !can_resolve(n)) {
  181. return 0;
  182. }
  183. int res;
  184. if (n->m->module.func_getvar2) {
  185. res = n->m->module.func_getvar2(n->mem, name, mem, out_value);
  186. } else {
  187. if (NCDStringIndex_HasNulls(n->params->iparams->string_index, name)) {
  188. return 0;
  189. }
  190. const char *name_str = NCDStringIndex_Value(n->params->iparams->string_index, name);
  191. res = n->m->module.func_getvar(n->mem, name_str, mem, out_value);
  192. }
  193. ASSERT(res == 0 || res == 1)
  194. ASSERT(res == 0 || (NCDVal_Assert(*out_value), 1))
  195. return res;
  196. }
  197. static int object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
  198. {
  199. NCDModuleInst *n = NCDObject_DataPtr(obj);
  200. DebugObject_Access(&n->d_obj);
  201. if (!n->m->module.func_getobj || !can_resolve(n)) {
  202. return 0;
  203. }
  204. int res = n->m->module.func_getobj(n->mem, name, out_object);
  205. ASSERT(res == 0 || res == 1)
  206. return res;
  207. }
  208. void * NCDModuleInst_Backend_GetUser (NCDModuleInst *n)
  209. {
  210. DebugObject_Access(&n->d_obj);
  211. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  212. n->state == STATE_UP ||
  213. n->state == STATE_DYING)
  214. return n->mem;
  215. }
  216. void NCDModuleInst_Backend_Up (NCDModuleInst *n)
  217. {
  218. DebugObject_Access(&n->d_obj);
  219. ASSERT(n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN)
  220. n->state = STATE_UP;
  221. frontend_event(n, NCDMODULE_EVENT_UP);
  222. }
  223. void NCDModuleInst_Backend_Down (NCDModuleInst *n)
  224. {
  225. DebugObject_Access(&n->d_obj);
  226. ASSERT(n->state == STATE_UP)
  227. n->state = STATE_DOWN_UNCLEAN;
  228. frontend_event(n, NCDMODULE_EVENT_DOWN);
  229. }
  230. void NCDModuleInst_Backend_DownUp (NCDModuleInst *n)
  231. {
  232. DebugObject_Access(&n->d_obj);
  233. ASSERT(n->state == STATE_UP)
  234. frontend_event(n, NCDMODULE_EVENT_DOWNUP);
  235. }
  236. void NCDModuleInst_Backend_Dead (NCDModuleInst *n)
  237. {
  238. DebugObject_Access(&n->d_obj);
  239. ASSERT(n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN ||
  240. n->state == STATE_UP || n->state == STATE_DYING)
  241. n->state = STATE_DEAD;
  242. frontend_event(n, NCDMODULE_EVENT_DEAD);
  243. return;
  244. }
  245. void NCDModuleInst_Backend_DeadError (NCDModuleInst *n)
  246. {
  247. DebugObject_Access(&n->d_obj);
  248. ASSERT(n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN ||
  249. n->state == STATE_UP || n->state == STATE_DYING)
  250. n->state = STATE_DEAD;
  251. frontend_event(n, NCDMODULE_EVENT_DEADERROR);
  252. return;
  253. }
  254. int NCDModuleInst_Backend_GetObj (NCDModuleInst *n, NCD_string_id_t name, NCDObject *out_object)
  255. {
  256. DebugObject_Access(&n->d_obj);
  257. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  258. n->state == STATE_UP ||
  259. n->state == STATE_DYING)
  260. ASSERT(out_object)
  261. int res = n->params->func_getobj(n, name, out_object);
  262. ASSERT(res == 0 || res == 1)
  263. return res;
  264. }
  265. void NCDModuleInst_Backend_Log (NCDModuleInst *n, int channel, int level, const char *fmt, ...)
  266. {
  267. DebugObject_Access(&n->d_obj);
  268. va_list vl;
  269. va_start(vl, fmt);
  270. BLog_LogViaFuncVarArg(n->params->logfunc, n, channel, level, fmt, vl);
  271. va_end(vl);
  272. }
  273. void NCDModuleInst_Backend_LogVarArg (NCDModuleInst *n, int channel, int level, const char *fmt, va_list vl)
  274. {
  275. DebugObject_Access(&n->d_obj);
  276. BLog_LogViaFuncVarArg(n->params->logfunc, n, channel, level, fmt, vl);
  277. }
  278. BLogContext NCDModuleInst_Backend_LogContext (NCDModuleInst *n)
  279. {
  280. DebugObject_Access(&n->d_obj);
  281. return BLog_MakeContext(n->params->logfunc, n);
  282. }
  283. void NCDModuleInst_Backend_InterpExit (NCDModuleInst *n, int exit_code)
  284. {
  285. DebugObject_Access(&n->d_obj);
  286. inst_assert_backend(n);
  287. n->params->iparams->func_interp_exit(n->params->iparams->user, exit_code);
  288. }
  289. int NCDModuleInst_Backend_InterpGetArgs (NCDModuleInst *n, NCDValMem *mem, NCDValRef *out_value)
  290. {
  291. DebugObject_Access(&n->d_obj);
  292. inst_assert_backend(n);
  293. ASSERT(mem)
  294. ASSERT(out_value)
  295. int res = n->params->iparams->func_interp_getargs(n->params->iparams->user, mem, out_value);
  296. ASSERT(res == 0 || res == 1)
  297. ASSERT(res == 0 || (NCDVal_Assert(*out_value), 1))
  298. return res;
  299. }
  300. btime_t NCDModuleInst_Backend_InterpGetRetryTime (NCDModuleInst *n)
  301. {
  302. DebugObject_Access(&n->d_obj);
  303. inst_assert_backend(n);
  304. return n->params->iparams->func_interp_getretrytime(n->params->iparams->user);
  305. }
  306. int NCDModuleInst_Backend_InterpLoadGroup (NCDModuleInst *n, const struct NCDModuleGroup *group)
  307. {
  308. DebugObject_Access(&n->d_obj);
  309. inst_assert_backend(n);
  310. ASSERT(group)
  311. return n->params->iparams->func_loadgroup(n->params->iparams->user, group);
  312. }
  313. int NCDModuleProcess_InitId (NCDModuleProcess *o, NCDModuleInst *n, NCD_string_id_t template_name, NCDValRef args, NCDModuleProcess_handler_event handler_event)
  314. {
  315. DebugObject_Access(&n->d_obj);
  316. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  317. n->state == STATE_UP ||
  318. n->state == STATE_DYING)
  319. ASSERT(template_name >= 0)
  320. ASSERT(NCDVal_IsInvalid(args) || NCDVal_IsList(args))
  321. ASSERT(handler_event)
  322. // init arguments
  323. o->args = args;
  324. o->handler_event = handler_event;
  325. // set no special functions
  326. o->func_getspecialobj = NULL;
  327. // set state
  328. set_process_state(o, PROCESS_STATE_INIT);
  329. #ifndef NDEBUG
  330. // clear interp functions so we can assert they were set
  331. o->interp_func_event = NULL;
  332. o->interp_func_getobj = NULL;
  333. #endif
  334. // init interpreter part
  335. if (!(n->params->iparams->func_initprocess(n->params->iparams->user, o, template_name))) {
  336. goto fail1;
  337. }
  338. ASSERT(o->interp_func_event)
  339. ASSERT(o->interp_func_getobj)
  340. // set state
  341. set_process_state(o, PROCESS_STATE_DOWN);
  342. DebugObject_Init(&o->d_obj);
  343. return 1;
  344. fail1:
  345. return 0;
  346. }
  347. int NCDModuleProcess_InitValue (NCDModuleProcess *o, NCDModuleInst *n, NCDValRef template_name, NCDValRef args, NCDModuleProcess_handler_event handler_event)
  348. {
  349. DebugObject_Access(&n->d_obj);
  350. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  351. n->state == STATE_UP ||
  352. n->state == STATE_DYING)
  353. ASSERT(NCDVal_IsString(template_name))
  354. ASSERT(NCDVal_IsInvalid(args) || NCDVal_IsList(args))
  355. ASSERT(handler_event)
  356. NCD_string_id_t template_name_id;
  357. if (NCDVal_IsIdString(template_name)) {
  358. template_name_id = NCDVal_IdStringId(template_name);
  359. } else {
  360. template_name_id = NCDStringIndex_GetBin(n->params->iparams->string_index, NCDVal_StringData(template_name), NCDVal_StringLength(template_name));
  361. if (template_name_id < 0) {
  362. BLog(BLOG_ERROR, "NCDStringIndex_GetBin failed");
  363. return 0;
  364. }
  365. }
  366. return NCDModuleProcess_InitId(o, n, template_name_id, args, handler_event);
  367. }
  368. void NCDModuleProcess_Free (NCDModuleProcess *o)
  369. {
  370. DebugObject_Free(&o->d_obj);
  371. ASSERT(o->state == PROCESS_STATE_TERMINATED)
  372. }
  373. void NCDModuleProcess_AssertFree (NCDModuleProcess *o)
  374. {
  375. DebugObject_Access(&o->d_obj);
  376. ASSERT(o->state == PROCESS_STATE_TERMINATED)
  377. }
  378. void NCDModuleProcess_SetSpecialFuncs (NCDModuleProcess *o, NCDModuleProcess_func_getspecialobj func_getspecialobj)
  379. {
  380. DebugObject_Access(&o->d_obj);
  381. o->func_getspecialobj = func_getspecialobj;
  382. }
  383. void NCDModuleProcess_Continue (NCDModuleProcess *o)
  384. {
  385. DebugObject_Access(&o->d_obj);
  386. ASSERT(o->state == PROCESS_STATE_DOWN_WAITING)
  387. set_process_state(o, PROCESS_STATE_DOWN);
  388. o->interp_func_event(o->interp_user, NCDMODULEPROCESS_INTERP_EVENT_CONTINUE);
  389. }
  390. void NCDModuleProcess_Terminate (NCDModuleProcess *o)
  391. {
  392. DebugObject_Access(&o->d_obj);
  393. ASSERT(o->state == PROCESS_STATE_DOWN || o->state == PROCESS_STATE_UP ||
  394. o->state == PROCESS_STATE_DOWN_WAITING)
  395. set_process_state(o, PROCESS_STATE_TERMINATING);
  396. o->interp_func_event(o->interp_user, NCDMODULEPROCESS_INTERP_EVENT_TERMINATE);
  397. }
  398. int NCDModuleProcess_GetObj (NCDModuleProcess *o, NCD_string_id_t name, NCDObject *out_object)
  399. {
  400. DebugObject_Access(&o->d_obj);
  401. ASSERT(o->state != PROCESS_STATE_INIT)
  402. ASSERT(o->state != PROCESS_STATE_TERMINATED)
  403. ASSERT(out_object)
  404. int res = o->interp_func_getobj(o->interp_user, name, out_object);
  405. ASSERT(res == 0 || res == 1)
  406. return res;
  407. }
  408. static void process_assert_interp (NCDModuleProcess *o)
  409. {
  410. // assert that the interpreter knows about the object, and we're not in init
  411. ASSERT(o->state == PROCESS_STATE_DOWN || o->state == PROCESS_STATE_UP ||
  412. o->state == PROCESS_STATE_DOWN_WAITING || o->state == PROCESS_STATE_TERMINATING)
  413. }
  414. void NCDModuleProcess_Interp_SetHandlers (NCDModuleProcess *o, void *interp_user,
  415. NCDModuleProcess_interp_func_event interp_func_event,
  416. NCDModuleProcess_interp_func_getobj interp_func_getobj)
  417. {
  418. ASSERT(o->state == PROCESS_STATE_INIT)
  419. ASSERT(interp_func_event)
  420. ASSERT(interp_func_getobj)
  421. o->interp_user = interp_user;
  422. o->interp_func_event = interp_func_event;
  423. o->interp_func_getobj = interp_func_getobj;
  424. }
  425. void NCDModuleProcess_Interp_Up (NCDModuleProcess *o)
  426. {
  427. DebugObject_Access(&o->d_obj);
  428. process_assert_interp(o);
  429. ASSERT(o->state == PROCESS_STATE_DOWN)
  430. set_process_state(o, PROCESS_STATE_UP);
  431. o->handler_event(o, NCDMODULEPROCESS_EVENT_UP);
  432. return;
  433. }
  434. void NCDModuleProcess_Interp_Down (NCDModuleProcess *o)
  435. {
  436. DebugObject_Access(&o->d_obj);
  437. process_assert_interp(o);
  438. ASSERT(o->state == PROCESS_STATE_UP)
  439. set_process_state(o, PROCESS_STATE_DOWN_WAITING);
  440. o->handler_event(o, NCDMODULEPROCESS_EVENT_DOWN);
  441. return;
  442. }
  443. void NCDModuleProcess_Interp_Terminated (NCDModuleProcess *o)
  444. {
  445. DebugObject_Access(&o->d_obj);
  446. process_assert_interp(o);
  447. ASSERT(o->state == PROCESS_STATE_TERMINATING)
  448. set_process_state(o, PROCESS_STATE_TERMINATED);
  449. o->handler_event(o, NCDMODULEPROCESS_EVENT_TERMINATED);
  450. return;
  451. }
  452. int NCDModuleProcess_Interp_GetSpecialObj (NCDModuleProcess *o, NCD_string_id_t name, NCDObject *out_object)
  453. {
  454. DebugObject_Access(&o->d_obj);
  455. process_assert_interp(o);
  456. ASSERT(out_object)
  457. if (!NCDVal_IsInvalid(o->args)) {
  458. if (name == NCD_STRING_ARGS) {
  459. *out_object = NCDObject_Build(-1, o, process_args_object_func_getvar, NCDObject_no_getobj);
  460. return 1;
  461. }
  462. if (name >= NCD_STRING_ARG0 && name <= NCD_STRING_ARG19) {
  463. int num = name - NCD_STRING_ARG0;
  464. if (num < NCDVal_ListCount(o->args)) {
  465. *out_object = NCDObject_BuildFull(-1, o, num, NULL, process_arg_object_func_getvar, NCDObject_no_getobj, NULL);
  466. return 1;
  467. }
  468. }
  469. }
  470. if (!o->func_getspecialobj) {
  471. return 0;
  472. }
  473. int res = o->func_getspecialobj(o, name, out_object);
  474. ASSERT(res == 0 || res == 1)
  475. return res;
  476. }
  477. int NCDCall_DoIt (
  478. struct NCDCall_interp_shared const *interp_shared, void *interp_user,
  479. struct NCDInterpFunction const *interp_function,
  480. size_t arg_count, NCDValMem *res_mem, NCDValRef *res_out
  481. )
  482. {
  483. NCDValRef res = NCDVal_NewInvalid();
  484. NCDCall call;
  485. call.interp_shared = interp_shared;
  486. call.interp_user = interp_user;
  487. call.interp_function = interp_function;
  488. call.arg_count = arg_count;
  489. call.res_mem = res_mem;
  490. call.out_ref = &res;
  491. interp_function->function.func_eval(call);
  492. if (NCDVal_IsInvalid(res)) {
  493. return 0;
  494. }
  495. *res_out = res;
  496. return 1;
  497. }
  498. struct NCDInterpFunction const * NCDCall_InterpFunction (NCDCall const *o)
  499. {
  500. return o->interp_function;
  501. }
  502. struct NCDModuleInst_iparams const * NCDCall_Iparams (NCDCall const *o)
  503. {
  504. return o->interp_shared->iparams;
  505. }
  506. size_t NCDCall_ArgCount (NCDCall const *o)
  507. {
  508. return o->arg_count;
  509. }
  510. NCDValRef NCDCall_EvalArg (NCDCall const *o, size_t index, NCDValMem *mem)
  511. {
  512. ASSERT(index < o->arg_count)
  513. ASSERT(mem)
  514. NCDValRef res;
  515. int eval_res = o->interp_shared->func_eval_arg(o->interp_user, index, mem, &res);
  516. ASSERT(eval_res == 0 || eval_res == 1)
  517. ASSERT(eval_res == 0 || (NCDVal_Assert(res), 1))
  518. if (!eval_res) {
  519. res = NCDVal_NewInvalid();
  520. }
  521. return res;
  522. }
  523. NCDValMem * NCDCall_ResMem (NCDCall const *o)
  524. {
  525. return o->res_mem;
  526. }
  527. void NCDCall_SetResult (NCDCall const *o, NCDValRef ref)
  528. {
  529. *o->out_ref = ref;
  530. }
  531. BLogContext NCDCall_LogContext (NCDCall const *o)
  532. {
  533. return BLog_MakeContext(o->interp_shared->logfunc, o->interp_user);
  534. }
  535. static int process_args_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
  536. {
  537. NCDModuleProcess *o = NCDObject_DataPtr(obj);
  538. DebugObject_Access(&o->d_obj);
  539. process_assert_interp(o);
  540. ASSERT(!NCDVal_IsInvalid(o->args))
  541. if (name != NCD_STRING_EMPTY) {
  542. return 0;
  543. }
  544. *out_value = NCDVal_NewCopy(mem, o->args);
  545. if (NCDVal_IsInvalid(*out_value)) {
  546. BLog_LogToChannel(BLOG_CHANNEL_NCDModuleProcess, BLOG_ERROR, "NCDVal_NewCopy failed");
  547. }
  548. return 1;
  549. }
  550. static int process_arg_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
  551. {
  552. NCDModuleProcess *o = NCDObject_DataPtr(obj);
  553. DebugObject_Access(&o->d_obj);
  554. process_assert_interp(o);
  555. ASSERT(!NCDVal_IsInvalid(o->args))
  556. if (name != NCD_STRING_EMPTY) {
  557. return 0;
  558. }
  559. *out_value = NCDVal_NewCopy(mem, NCDVal_ListGet(o->args, NCDObject_DataInt(obj)));
  560. if (NCDVal_IsInvalid(*out_value)) {
  561. BLog_LogToChannel(BLOG_CHANNEL_NCDModuleProcess, BLOG_ERROR, "NCDVal_NewCopy failed");
  562. }
  563. return 1;
  564. }