NCDModule.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  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).ptr;
  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. void NCDModuleRef_Init (NCDModuleRef *o, NCDModuleInst *inst)
  314. {
  315. ASSERT(!inst->pass_mem_to_methods)
  316. NCDObject obj = NCDModuleInst_Object(inst);
  317. NCDObjRef_Init(&o->objref, NCDObject_Pobj(&obj));
  318. DebugObject_Init(&o->d_obj);
  319. }
  320. void NCDModuleRef_Free (NCDModuleRef *o)
  321. {
  322. DebugObject_Free(&o->d_obj);
  323. NCDObjRef_Free(&o->objref);
  324. }
  325. NCDModuleInst * NCDModuleRef_Deref (NCDModuleRef *o)
  326. {
  327. DebugObject_Access(&o->d_obj);
  328. NCDModuleInst *res = NULL;
  329. NCDObject obj;
  330. if (NCDObjRef_Deref(&o->objref, &obj)) {
  331. res = NCDObject_MethodUser(&obj);
  332. }
  333. return res;
  334. }
  335. int NCDModuleProcess_InitId (NCDModuleProcess *o, NCDModuleInst *n, NCD_string_id_t template_name, NCDValRef args, NCDModuleProcess_handler_event handler_event)
  336. {
  337. DebugObject_Access(&n->d_obj);
  338. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  339. n->state == STATE_UP ||
  340. n->state == STATE_DYING)
  341. ASSERT(template_name >= 0)
  342. ASSERT(NCDVal_IsInvalid(args) || NCDVal_IsList(args))
  343. ASSERT(handler_event)
  344. // init arguments
  345. o->args = args;
  346. o->handler_event = handler_event;
  347. // set no special functions
  348. o->func_getspecialobj = NULL;
  349. // set state
  350. set_process_state(o, PROCESS_STATE_INIT);
  351. #ifndef NDEBUG
  352. // clear interp functions so we can assert they were set
  353. o->interp_func_event = NULL;
  354. o->interp_func_getobj = NULL;
  355. #endif
  356. // init interpreter part
  357. if (!(n->params->iparams->func_initprocess(n->params->iparams->user, o, template_name))) {
  358. goto fail1;
  359. }
  360. ASSERT(o->interp_func_event)
  361. ASSERT(o->interp_func_getobj)
  362. // set state
  363. set_process_state(o, PROCESS_STATE_DOWN);
  364. DebugObject_Init(&o->d_obj);
  365. return 1;
  366. fail1:
  367. return 0;
  368. }
  369. int NCDModuleProcess_InitValue (NCDModuleProcess *o, NCDModuleInst *n, NCDValRef template_name, NCDValRef args, NCDModuleProcess_handler_event handler_event)
  370. {
  371. DebugObject_Access(&n->d_obj);
  372. ASSERT(n->state == STATE_DOWN_UNCLEAN || n->state == STATE_DOWN_CLEAN ||
  373. n->state == STATE_UP ||
  374. n->state == STATE_DYING)
  375. ASSERT(NCDVal_IsString(template_name))
  376. ASSERT(NCDVal_IsInvalid(args) || NCDVal_IsList(args))
  377. ASSERT(handler_event)
  378. NCD_string_id_t template_name_id;
  379. if (NCDVal_IsIdString(template_name)) {
  380. template_name_id = NCDVal_IdStringId(template_name);
  381. } else {
  382. template_name_id = NCDStringIndex_GetBinMr(n->params->iparams->string_index, NCDVal_StringMemRef(template_name));
  383. if (template_name_id < 0) {
  384. BLog(BLOG_ERROR, "NCDStringIndex_GetBin failed");
  385. return 0;
  386. }
  387. }
  388. return NCDModuleProcess_InitId(o, n, template_name_id, args, handler_event);
  389. }
  390. void NCDModuleProcess_Free (NCDModuleProcess *o)
  391. {
  392. DebugObject_Free(&o->d_obj);
  393. ASSERT(o->state == PROCESS_STATE_TERMINATED)
  394. }
  395. void NCDModuleProcess_AssertFree (NCDModuleProcess *o)
  396. {
  397. DebugObject_Access(&o->d_obj);
  398. ASSERT(o->state == PROCESS_STATE_TERMINATED)
  399. }
  400. void NCDModuleProcess_SetSpecialFuncs (NCDModuleProcess *o, NCDModuleProcess_func_getspecialobj func_getspecialobj)
  401. {
  402. DebugObject_Access(&o->d_obj);
  403. o->func_getspecialobj = func_getspecialobj;
  404. }
  405. void NCDModuleProcess_Continue (NCDModuleProcess *o)
  406. {
  407. DebugObject_Access(&o->d_obj);
  408. ASSERT(o->state == PROCESS_STATE_DOWN_WAITING)
  409. set_process_state(o, PROCESS_STATE_DOWN);
  410. o->interp_func_event(o->interp_user, NCDMODULEPROCESS_INTERP_EVENT_CONTINUE);
  411. }
  412. void NCDModuleProcess_Terminate (NCDModuleProcess *o)
  413. {
  414. DebugObject_Access(&o->d_obj);
  415. ASSERT(o->state == PROCESS_STATE_DOWN || o->state == PROCESS_STATE_UP ||
  416. o->state == PROCESS_STATE_DOWN_WAITING)
  417. set_process_state(o, PROCESS_STATE_TERMINATING);
  418. o->interp_func_event(o->interp_user, NCDMODULEPROCESS_INTERP_EVENT_TERMINATE);
  419. }
  420. int NCDModuleProcess_GetObj (NCDModuleProcess *o, NCD_string_id_t name, NCDObject *out_object)
  421. {
  422. DebugObject_Access(&o->d_obj);
  423. ASSERT(o->state != PROCESS_STATE_INIT)
  424. ASSERT(o->state != PROCESS_STATE_TERMINATED)
  425. ASSERT(out_object)
  426. int res = o->interp_func_getobj(o->interp_user, name, out_object);
  427. ASSERT(res == 0 || res == 1)
  428. return res;
  429. }
  430. static void process_assert_interp (NCDModuleProcess *o)
  431. {
  432. // assert that the interpreter knows about the object, and we're not in init
  433. ASSERT(o->state == PROCESS_STATE_DOWN || o->state == PROCESS_STATE_UP ||
  434. o->state == PROCESS_STATE_DOWN_WAITING || o->state == PROCESS_STATE_TERMINATING)
  435. }
  436. void NCDModuleProcess_Interp_SetHandlers (NCDModuleProcess *o, void *interp_user,
  437. NCDModuleProcess_interp_func_event interp_func_event,
  438. NCDModuleProcess_interp_func_getobj interp_func_getobj)
  439. {
  440. ASSERT(o->state == PROCESS_STATE_INIT)
  441. ASSERT(interp_func_event)
  442. ASSERT(interp_func_getobj)
  443. o->interp_user = interp_user;
  444. o->interp_func_event = interp_func_event;
  445. o->interp_func_getobj = interp_func_getobj;
  446. }
  447. void NCDModuleProcess_Interp_Up (NCDModuleProcess *o)
  448. {
  449. DebugObject_Access(&o->d_obj);
  450. process_assert_interp(o);
  451. ASSERT(o->state == PROCESS_STATE_DOWN)
  452. set_process_state(o, PROCESS_STATE_UP);
  453. o->handler_event(o, NCDMODULEPROCESS_EVENT_UP);
  454. return;
  455. }
  456. void NCDModuleProcess_Interp_Down (NCDModuleProcess *o)
  457. {
  458. DebugObject_Access(&o->d_obj);
  459. process_assert_interp(o);
  460. ASSERT(o->state == PROCESS_STATE_UP)
  461. set_process_state(o, PROCESS_STATE_DOWN_WAITING);
  462. o->handler_event(o, NCDMODULEPROCESS_EVENT_DOWN);
  463. return;
  464. }
  465. void NCDModuleProcess_Interp_Terminated (NCDModuleProcess *o)
  466. {
  467. DebugObject_Access(&o->d_obj);
  468. process_assert_interp(o);
  469. ASSERT(o->state == PROCESS_STATE_TERMINATING)
  470. set_process_state(o, PROCESS_STATE_TERMINATED);
  471. o->handler_event(o, NCDMODULEPROCESS_EVENT_TERMINATED);
  472. return;
  473. }
  474. int NCDModuleProcess_Interp_GetSpecialObj (NCDModuleProcess *o, NCD_string_id_t name, NCDObject *out_object)
  475. {
  476. DebugObject_Access(&o->d_obj);
  477. process_assert_interp(o);
  478. ASSERT(out_object)
  479. if (!NCDVal_IsInvalid(o->args)) {
  480. if (name == NCD_STRING_ARGS) {
  481. *out_object = NCDObject_Build(-1, o, process_args_object_func_getvar, NCDObject_no_getobj);
  482. return 1;
  483. }
  484. if (name >= NCD_STRING_ARG0 && name <= NCD_STRING_ARG19) {
  485. int num = name - NCD_STRING_ARG0;
  486. if (num < NCDVal_ListCount(o->args)) {
  487. *out_object = NCDObject_BuildFull(-1, o, num, NULL, process_arg_object_func_getvar, NCDObject_no_getobj, NULL);
  488. return 1;
  489. }
  490. }
  491. }
  492. if (!o->func_getspecialobj) {
  493. return 0;
  494. }
  495. int res = o->func_getspecialobj(o, name, out_object);
  496. ASSERT(res == 0 || res == 1)
  497. return res;
  498. }
  499. int NCDCall_DoIt (
  500. struct NCDCall_interp_shared const *interp_shared, void *interp_user,
  501. struct NCDInterpFunction const *interp_function,
  502. size_t arg_count, NCDValMem *res_mem, NCDValRef *res_out
  503. )
  504. {
  505. NCDValRef res = NCDVal_NewInvalid();
  506. NCDCall call;
  507. call.interp_shared = interp_shared;
  508. call.interp_user = interp_user;
  509. call.interp_function = interp_function;
  510. call.arg_count = arg_count;
  511. call.res_mem = res_mem;
  512. call.out_ref = &res;
  513. interp_function->function.func_eval(call);
  514. if (NCDVal_IsInvalid(res)) {
  515. return 0;
  516. }
  517. *res_out = res;
  518. return 1;
  519. }
  520. struct NCDInterpFunction const * NCDCall_InterpFunction (NCDCall const *o)
  521. {
  522. return o->interp_function;
  523. }
  524. struct NCDModuleInst_iparams const * NCDCall_Iparams (NCDCall const *o)
  525. {
  526. return o->interp_shared->iparams;
  527. }
  528. size_t NCDCall_ArgCount (NCDCall const *o)
  529. {
  530. return o->arg_count;
  531. }
  532. NCDValRef NCDCall_EvalArg (NCDCall const *o, size_t index, NCDValMem *mem)
  533. {
  534. ASSERT(index < o->arg_count)
  535. ASSERT(mem)
  536. NCDValRef res;
  537. int eval_res = o->interp_shared->func_eval_arg(o->interp_user, index, mem, &res);
  538. ASSERT(eval_res == 0 || eval_res == 1)
  539. ASSERT(eval_res == 0 || (NCDVal_Assert(res), 1))
  540. if (!eval_res) {
  541. res = NCDVal_NewInvalid();
  542. }
  543. return res;
  544. }
  545. NCDValMem * NCDCall_ResMem (NCDCall const *o)
  546. {
  547. return o->res_mem;
  548. }
  549. void NCDCall_SetResult (NCDCall const *o, NCDValRef ref)
  550. {
  551. *o->out_ref = ref;
  552. }
  553. BLogContext NCDCall_LogContext (NCDCall const *o)
  554. {
  555. return BLog_MakeContext(o->interp_shared->logfunc, o->interp_user);
  556. }
  557. static int process_args_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
  558. {
  559. NCDModuleProcess *o = NCDObject_DataPtr(obj);
  560. DebugObject_Access(&o->d_obj);
  561. process_assert_interp(o);
  562. ASSERT(!NCDVal_IsInvalid(o->args))
  563. if (name != NCD_STRING_EMPTY) {
  564. return 0;
  565. }
  566. *out_value = NCDVal_NewCopy(mem, o->args);
  567. if (NCDVal_IsInvalid(*out_value)) {
  568. BLog_LogToChannel(BLOG_CHANNEL_NCDModuleProcess, BLOG_ERROR, "NCDVal_NewCopy failed");
  569. }
  570. return 1;
  571. }
  572. static int process_arg_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
  573. {
  574. NCDModuleProcess *o = NCDObject_DataPtr(obj);
  575. DebugObject_Access(&o->d_obj);
  576. process_assert_interp(o);
  577. ASSERT(!NCDVal_IsInvalid(o->args))
  578. if (name != NCD_STRING_EMPTY) {
  579. return 0;
  580. }
  581. *out_value = NCDVal_NewCopy(mem, NCDVal_ListGet(o->args, NCDObject_DataInt(obj)));
  582. if (NCDVal_IsInvalid(*out_value)) {
  583. BLog_LogToChannel(BLOG_CHANNEL_NCDModuleProcess, BLOG_ERROR, "NCDVal_NewCopy failed");
  584. }
  585. return 1;
  586. }