data.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2020 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  18. ******************************************************************************/
  19. /******************************************************************************
  20. * T I N T I N + + *
  21. * *
  22. * coded by Igor van den Hoven 2004 *
  23. ******************************************************************************/
  24. #include "tintin.h"
  25. #include <limits.h>
  26. extern char **environ;
  27. struct listroot *init_list(struct session *ses, int type, int size)
  28. {
  29. struct listroot *listhead;
  30. if ((listhead = (struct listroot *) calloc(1, sizeof(struct listroot))) == NULL)
  31. {
  32. syserr_fatal(-1, "init_list: calloc");
  33. }
  34. listhead->ses = ses;
  35. listhead->list = (struct listnode **) calloc(size, sizeof(struct listnode *));
  36. listhead->size = size;
  37. listhead->type = type;
  38. listhead->flags = list_table[type].flags;
  39. return listhead;
  40. }
  41. void kill_list(struct listroot *root)
  42. {
  43. while (root->used)
  44. {
  45. delete_index_list(root, root->used - 1);
  46. }
  47. root->update = 0;
  48. }
  49. void free_list(struct listroot *root)
  50. {
  51. kill_list(root);
  52. free(root->list);
  53. free(root);
  54. }
  55. struct listroot *copy_list(struct session *ses, struct listroot *sourcelist, int type)
  56. {
  57. int i;
  58. struct listnode *node;
  59. push_call("copy_list(%p,%p,%s)",ses,sourcelist,list_table[type].name);
  60. ses->list[type] = init_list(ses, type, sourcelist->size);
  61. if (HAS_BIT(sourcelist->flags, LIST_FLAG_INHERIT))
  62. {
  63. for (i = 0 ; i < sourcelist->used ; i++)
  64. {
  65. node = (struct listnode *) calloc(1, sizeof(struct listnode));
  66. node->arg1 = str_dup_clone(sourcelist->list[i]->arg1);
  67. node->arg2 = str_dup_clone(sourcelist->list[i]->arg2);
  68. node->arg3 = str_dup_clone(sourcelist->list[i]->arg3);
  69. node->arg4 = str_dup_clone(sourcelist->list[i]->arg4);
  70. node->shots = sourcelist->list[i]->shots;
  71. node->group = strdup(sourcelist->list[i]->group);
  72. switch (type)
  73. {
  74. case LIST_ALIAS:
  75. node->regex = tintin_regexp_compile(ses, node, node->arg1, PCRE_ANCHORED);
  76. break;
  77. case LIST_ACTION:
  78. case LIST_GAG:
  79. case LIST_HIGHLIGHT:
  80. case LIST_PROMPT:
  81. case LIST_SUBSTITUTE:
  82. node->regex = tintin_regexp_compile(ses, node, node->arg1, 0);
  83. break;
  84. case LIST_BUTTON:
  85. case LIST_EVENT:
  86. // case LIST_TICKER:
  87. case LIST_PATHDIR:
  88. node->val64 = sourcelist->list[i]->val64;
  89. break;
  90. case LIST_VARIABLE:
  91. copy_nest_node(ses->list[type], node, sourcelist->list[i]);
  92. break;
  93. case LIST_TICKER:
  94. node->val64 = gtd->utime + (long long) (tintoi(node->arg3) * 1000000.0);
  95. if (node->val64 < gtd->utime_next_tick)
  96. {
  97. gtd->utime_next_tick = node->val64;
  98. }
  99. break;
  100. default:
  101. if (sourcelist->list[i]->val64)
  102. {
  103. printf("copy_list: unhandled val64 (%d).\n", type);
  104. }
  105. break;
  106. }
  107. ses->list[type]->list[i] = node;
  108. }
  109. ses->list[type]->used = sourcelist->used;
  110. }
  111. ses->list[type]->flags = sourcelist->flags;
  112. pop_call();
  113. return ses->list[type];
  114. }
  115. struct listnode *create_node_list(struct listroot *root, char *arg1, char *arg2, char *arg3, char *arg4)
  116. {
  117. struct listnode *node;
  118. node = (struct listnode *) calloc(1, sizeof(struct listnode));
  119. if (list_table[root->type].priority_arg == 3 && *arg3 == 0)
  120. {
  121. strcpy(arg3, "5");
  122. }
  123. if (HAS_BIT(root->flags, LIST_FLAG_NEST) && *arg1 == '\\')
  124. {
  125. node->arg1 = str_dup(arg1+1);
  126. }
  127. else
  128. {
  129. node->arg1 = str_dup(arg1);
  130. }
  131. node->arg2 = str_dup(arg2);
  132. node->arg3 = str_dup(arg3);
  133. node->arg4 = str_dup(arg4);
  134. // printf("debug: %p [%p] (%d) (%s) (%s)\n", root, root->ses, root->type, node->arg1, node->arg3);
  135. if (gtd->level->shots)
  136. {
  137. node->shots = gtd->level->mshot;
  138. }
  139. node->group = HAS_BIT(root->flags, LIST_FLAG_CLASS) ? strdup(root->ses->group) : strdup("");
  140. switch (root->type)
  141. {
  142. case LIST_ALIAS:
  143. node->regex = tintin_regexp_compile(root->ses, node, node->arg1, PCRE_ANCHORED);
  144. break;
  145. case LIST_ACTION:
  146. case LIST_GAG:
  147. case LIST_HIGHLIGHT:
  148. case LIST_PROMPT:
  149. case LIST_SUBSTITUTE:
  150. node->regex = tintin_regexp_compile(root->ses, node, node->arg1, 0);
  151. break;
  152. case LIST_DELAY:
  153. node->val64 = (long long) tintoi(node->arg1);
  154. if (node->val64 < gtd->utime_next_delay)
  155. {
  156. gtd->utime_next_delay = node->val64;
  157. }
  158. break;
  159. case LIST_TICKER:
  160. node->val64 = gtd->utime + (long long) (tintoi(arg3) * 1000000.0);
  161. if (node->val64 < gtd->utime_next_tick)
  162. {
  163. gtd->utime_next_tick = node->val64;
  164. }
  165. break;
  166. }
  167. return insert_node_list(root, node);
  168. }
  169. struct listnode *insert_node_list(struct listroot *root, struct listnode *node)
  170. {
  171. int index;
  172. index = locate_index_list(root, node->arg1, node->arg3);
  173. return insert_index_list(root, node, index);
  174. }
  175. struct listnode *update_node_list(struct listroot *root, char *arg1, char *arg2, char *arg3, char *arg4)
  176. {
  177. int index;
  178. struct listnode *node;
  179. index = search_index_list(root, arg1, NULL);
  180. if (index != -1)
  181. {
  182. node = root->list[index];
  183. if (gtd->level->shots)
  184. {
  185. node->shots = gtd->level->mshot;
  186. }
  187. if (strcmp(node->arg2, arg2) != 0)
  188. {
  189. str_cpy(&node->arg2, arg2);
  190. }
  191. switch (root->type)
  192. {
  193. case LIST_TICKER:
  194. node->val64 = gtd->utime + (long long) tintoi(arg3) * 1000000;
  195. if (node->val64 < gtd->utime_next_tick)
  196. {
  197. gtd->utime_next_tick = node->val64;
  198. }
  199. break;
  200. }
  201. if (list_table[root->type].priority_arg == 3 && *arg3 == 0)
  202. {
  203. strcpy(arg3, "5");
  204. }
  205. if (list_table[root->type].mode != SORT_PRIORITY)
  206. {
  207. if (strcmp(node->arg3, arg3) != 0)
  208. {
  209. str_cpy(&node->arg3, arg3);
  210. }
  211. }
  212. if (strcmp(node->arg4, arg4) != 0)
  213. {
  214. str_cpy(&node->arg4, arg4);
  215. }
  216. switch (list_table[root->type].mode)
  217. {
  218. case SORT_PRIORITY:
  219. if (strcmp(node->arg3, arg3))
  220. {
  221. remove_index_list(root, index);
  222. str_cpy(&node->arg3, arg3);
  223. insert_node_list(root, node);
  224. }
  225. break;
  226. case SORT_APPEND:
  227. remove_index_list(root, index);
  228. insert_node_list(root, node);
  229. break;
  230. case SORT_ALPHA:
  231. case SORT_ALNUM:
  232. case SORT_STABLE:
  233. break;
  234. default:
  235. tintin_printf2(root->ses, "#BUG: update_node_list: unknown sort: %d", list_table[root->type].mode);
  236. break;
  237. }
  238. return node;
  239. }
  240. else
  241. {
  242. return create_node_list(root, arg1, arg2, arg3, arg4);
  243. }
  244. }
  245. struct listnode *insert_index_list(struct listroot *root, struct listnode *node, int index)
  246. {
  247. root->used++;
  248. if (root->used == root->size)
  249. {
  250. root->size *= 2;
  251. root->list = (struct listnode **) realloc(root->list, (root->size) * sizeof(struct listnode *));
  252. }
  253. if (index + 1 < root->used)
  254. {
  255. memmove(&root->list[index + 1], &root->list[index], (root->used - index) * sizeof(struct listnode *));
  256. }
  257. root->list[index] = node;
  258. return node;
  259. }
  260. void remove_node_list(struct session *ses, int type, struct listnode *node)
  261. {
  262. int index = search_index_list(ses->list[type], node->arg1, node->arg3);
  263. remove_index_list(ses->list[type], index);
  264. }
  265. void remove_index_list(struct listroot *root, int index)
  266. {
  267. if (index <= root->update)
  268. {
  269. root->update--;
  270. }
  271. memmove(&root->list[index], &root->list[index + 1], (root->used - index) * sizeof(struct listnode *));
  272. root->used--;
  273. return;
  274. }
  275. void delete_node_list(struct session *ses, int type, struct listnode *node)
  276. {
  277. int index = search_index_list(ses->list[type], node->arg1, node->arg3);
  278. delete_index_list(ses->list[type], index);
  279. }
  280. void delete_index_list(struct listroot *root, int index)
  281. {
  282. struct listnode *node = root->list[index];
  283. if (HAS_BIT(list_table[root->type].flags, LIST_FLAG_REGEX))
  284. {
  285. if (node->regex)
  286. {
  287. free(node->regex);
  288. }
  289. }
  290. switch (root->type)
  291. {
  292. case LIST_TERRAIN:
  293. delete_room_data(node->room);
  294. free(node->room);
  295. break;
  296. case LIST_CLASS:
  297. if (node->data)
  298. {
  299. free(node->data);
  300. }
  301. break;
  302. case LIST_EVENT:
  303. event_table[node->val32[0]].level--;
  304. break;
  305. }
  306. remove_index_list(root, index);
  307. // dispose in memory update for one shot handling
  308. insert_index_list(gtd->dispose_list, node, gtd->dispose_list->used);
  309. }
  310. void dispose_node(struct listnode *node)
  311. {
  312. if (node->root)
  313. {
  314. free_list(node->root);
  315. }
  316. str_free(node->arg1);
  317. str_free(node->arg2);
  318. str_free(node->arg3);
  319. str_free(node->arg4);
  320. free(node->group);
  321. free(node);
  322. }
  323. struct listnode *search_node_list(struct listroot *root, char *text)
  324. {
  325. int index;
  326. push_call("search_node_list(%p,%p)",root,text);
  327. switch (list_table[root->type].mode)
  328. {
  329. case SORT_ALPHA:
  330. case SORT_STABLE:
  331. index = bsearch_alpha_list(root, text, 0);
  332. break;
  333. case SORT_ALNUM:
  334. index = bsearch_alnum_list(root, text, 0);
  335. break;
  336. default:
  337. index = nsearch_list(root, text);
  338. break;
  339. }
  340. if (index != -1)
  341. {
  342. pop_call();
  343. return root->list[index];
  344. }
  345. pop_call();
  346. return NULL;
  347. }
  348. int search_index_list(struct listroot *root, char *text, char *priority)
  349. {
  350. switch (list_table[root->type].mode)
  351. {
  352. case SORT_ALPHA:
  353. case SORT_STABLE:
  354. return bsearch_alpha_list(root, text, 0);
  355. case SORT_ALNUM:
  356. return bsearch_alnum_list(root, text, 0);
  357. case SORT_PRIORITY:
  358. if (priority)
  359. {
  360. bsearch_priority_list(root, text, priority, 0);
  361. }
  362. break;
  363. }
  364. return nsearch_list(root, text);
  365. }
  366. /*
  367. Return insertion index.
  368. */
  369. int locate_index_list(struct listroot *root, char *text, char *priority)
  370. {
  371. switch (list_table[root->type].mode)
  372. {
  373. case SORT_ALPHA:
  374. return bsearch_alpha_list(root, text, SEEK_REPLACE);
  375. case SORT_STABLE:
  376. return bsearch_alpha_list(root, text, SEEK_APPEND);
  377. case SORT_ALNUM:
  378. return bsearch_alnum_list(root, text, SEEK_REPLACE);
  379. case SORT_PRIORITY:
  380. return bsearch_priority_list(root, text, priority, SEEK_REPLACE);
  381. default:
  382. return root->used;
  383. }
  384. }
  385. int bsearch_alpha_list(struct listroot *root, char *text, int seek)
  386. {
  387. int bot, mid, top;
  388. if (root->used == 0)
  389. {
  390. return seek ? 0 : -1;
  391. }
  392. bot = 0;
  393. top = root->used;
  394. if (HAS_BIT(root->flags, LIST_FLAG_CASE))
  395. {
  396. while (top > 1)
  397. {
  398. mid = top / 2;
  399. if (strcasecmp(text, root->list[bot + mid]->arg1) >= 0)
  400. {
  401. bot += mid;
  402. }
  403. top -= mid;
  404. }
  405. if (strcasecmp(text, root->list[bot]->arg1) == 0)
  406. {
  407. return bot + (seek == SEEK_APPEND);
  408. }
  409. if (seek)
  410. {
  411. return bot + (strcasecmp(text, root->list[bot]->arg1) > 0);
  412. }
  413. return -1;
  414. }
  415. while (top > 1)
  416. {
  417. mid = top / 2;
  418. if (strcmp(text, root->list[bot + mid]->arg1) >= 0)
  419. {
  420. bot += mid;
  421. }
  422. top -= mid;
  423. }
  424. if (strcmp(text, root->list[bot]->arg1) == 0)
  425. {
  426. return bot + (seek == SEEK_APPEND);
  427. }
  428. if (seek)
  429. {
  430. return bot + (strcmp(text, root->list[bot]->arg1) > 0);
  431. }
  432. return -1;
  433. }
  434. /*
  435. int bsearch_alpha_list(struct listroot *root, char *text, int seek)
  436. {
  437. int bot, top, val, srt;
  438. bot = 0;
  439. top = root->used - 1;
  440. val = top;
  441. while (bot <= top)
  442. {
  443. srt = strcmp(text, root->list[val]->arg1);
  444. if (srt == 0)
  445. {
  446. return val;
  447. }
  448. if (srt < 0)
  449. {
  450. top = val - 1;
  451. }
  452. else
  453. {
  454. bot = val + 1;
  455. }
  456. val = bot + (top - bot) / 2;
  457. }
  458. if (seek)
  459. {
  460. return UMAX(0, val);
  461. }
  462. return -1;
  463. }
  464. */
  465. int bsearch_alnum_list(struct listroot *root, char *text, int seek)
  466. {
  467. long double toi, toj;
  468. int bot, top, val, noi, noj, srt;
  469. push_call("bsearch_alpha_list(%p,%p,%d)",root,text,seek);
  470. if (seek == 0 && HAS_BIT(root->flags, LIST_FLAG_NEST))
  471. {
  472. switch (*text)
  473. {
  474. case '+':
  475. toi = get_number(root->ses, text);
  476. if (seek == 0)
  477. {
  478. if (toi > 0 && toi <= root->used)
  479. {
  480. pop_call();
  481. return toi - 1;
  482. }
  483. }
  484. else
  485. {
  486. if (toi >= 0 && toi <= root->used)
  487. {
  488. pop_call();
  489. return UMAX(0, toi - 1);
  490. }
  491. }
  492. break;
  493. case '-':
  494. toi = get_number(root->ses, text);
  495. if (toi < 0 && root->used + toi >= 0)
  496. {
  497. pop_call();
  498. return root->used + toi;
  499. }
  500. break;
  501. case '\\':
  502. text++;
  503. break;
  504. }
  505. }
  506. bot = 0;
  507. top = root->used - 1;
  508. val = top;
  509. noi = is_number(text);
  510. toi = noi ? tintoi(text) : 0;
  511. while (bot <= top)
  512. {
  513. noj = is_number(root->list[val]->arg1);
  514. toj = noj ? tintoi(root->list[val]->arg1) : 0;
  515. if (noi)
  516. {
  517. srt = !noj ? 1 : (toi < toj) ? -1 : (toi > toj) ? 1 : 0;
  518. }
  519. else if (noj)
  520. {
  521. srt = -1;
  522. }
  523. else
  524. {
  525. srt = strcmp(text, root->list[val]->arg1);
  526. }
  527. if (srt == 0)
  528. {
  529. pop_call();
  530. return val;
  531. }
  532. if (srt < 0)
  533. {
  534. top = val - 1;
  535. }
  536. else
  537. {
  538. bot = val + 1;
  539. }
  540. val = bot + (top - bot) / 2;
  541. }
  542. if (seek)
  543. {
  544. pop_call();
  545. return UMAX(0, val);
  546. }
  547. pop_call();
  548. return -1;
  549. }
  550. /*
  551. Binary search on priorially and alphabetically sorted list
  552. */
  553. int bsearch_priority_list(struct listroot *root, char *text, char *priority, int seek)
  554. {
  555. int bot, top, val;
  556. long double prt, srt;
  557. bot = 0;
  558. top = root->used - 1;
  559. val = top;
  560. prt = tintoi(priority);
  561. while (bot <= top)
  562. {
  563. srt = tintoi(root->list[val]->arg3);
  564. if (srt == prt)
  565. {
  566. srt = strcmp(text, root->list[val]->arg1);
  567. if (srt == 0)
  568. {
  569. return val;
  570. }
  571. if (srt < 0)
  572. {
  573. top = val - 1;
  574. }
  575. else
  576. {
  577. bot = val + 1;
  578. }
  579. }
  580. else
  581. {
  582. if (prt < srt)
  583. {
  584. top = val - 1;
  585. }
  586. else
  587. {
  588. bot = val + 1;
  589. }
  590. }
  591. val = bot + (top - bot) / 2;
  592. }
  593. if (seek)
  594. {
  595. return UMAX(0, val);
  596. }
  597. else
  598. {
  599. return -1;
  600. }
  601. }
  602. /*
  603. Linear search
  604. */
  605. int nsearch_list(struct listroot *root, char *text)
  606. {
  607. int i;
  608. for (i = 0 ; i < root->used ; i++)
  609. {
  610. if (!strcmp(text, root->list[i]->arg1))
  611. {
  612. return i;
  613. }
  614. }
  615. return -1;
  616. }
  617. /*
  618. show content of a node on screen
  619. */
  620. void show_node(struct listroot *root, struct listnode *node, int level)
  621. {
  622. char *str_arg2;
  623. push_call("show_node(%p,%p,%d)",root,node,level);
  624. str_arg2 = str_alloc_stack(0);
  625. show_nest_node(node, &str_arg2, TRUE);
  626. switch (list_table[root->type].args)
  627. {
  628. case 4:
  629. tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2, node->arg3, node->arg4);
  630. break;
  631. case 3:
  632. if (list_table[root->type].priority_arg == 3 && !strcmp(node->arg3, "5"))
  633. {
  634. tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2);
  635. }
  636. else
  637. {
  638. tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2, node->arg3);
  639. }
  640. break;
  641. case 2:
  642. tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2);
  643. break;
  644. case 1:
  645. tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1);
  646. break;
  647. }
  648. pop_call();
  649. return;
  650. }
  651. /*
  652. list content of a list on screen
  653. */
  654. void show_list(struct listroot *root, int level)
  655. {
  656. int i;
  657. if (root == root->ses->list[root->type])
  658. {
  659. tintin_header(root->ses, 80, " %s ", list_table[root->type].name_multi);
  660. }
  661. for (i = 0 ; i < root->used ; i++)
  662. {
  663. show_node(root, root->list[i], level);
  664. }
  665. }
  666. int show_node_with_wild(struct session *ses, char *text, struct listroot *root)
  667. {
  668. struct listnode *node;
  669. int index, found = FALSE;
  670. push_call("show_node_with_wild(%p,%p,%p)",ses,text,root);
  671. switch (list_table[root->type].mode)
  672. {
  673. case SORT_ALPHA:
  674. case SORT_STABLE:
  675. index = bsearch_alpha_list(root, text, 0);
  676. break;
  677. case SORT_ALNUM:
  678. index = bsearch_alnum_list(root, text, 0);
  679. break;
  680. default:
  681. index = nsearch_list(root, text);
  682. break;
  683. }
  684. if (index != -1)
  685. {
  686. node = root->list[index];
  687. if (list_table[root->type].script_arg == 2)
  688. {
  689. if (list_table[root->type].args == 2)
  690. {
  691. tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
  692. }
  693. else if (list_table[root->type].args == 3)
  694. {
  695. if (list_table[root->type].priority_arg == 3)
  696. {
  697. if (!strcmp(node->arg3, "5"))
  698. {
  699. tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
  700. }
  701. else
  702. {
  703. tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
  704. }
  705. }
  706. else
  707. {
  708. tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
  709. }
  710. }
  711. }
  712. else
  713. {
  714. show_node(root, node, 0);
  715. }
  716. switch(root->type)
  717. {
  718. // case LIST_EVENT:
  719. // case LIST_FUNCTION:
  720. // case LIST_MACRO:
  721. // tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
  722. // break;
  723. // case LIST_ACTION:
  724. // case LIST_ALIAS:
  725. // case LIST_BUTTON:
  726. // if (!strcmp(node->arg3, "5"))
  727. // {
  728. // tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
  729. // }
  730. // else
  731. // {
  732. // tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
  733. // }
  734. // break;
  735. // case LIST_DELAY:
  736. // case LIST_TICKER:
  737. // tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
  738. // break;
  739. // default:
  740. // show_node(root, node, 0);
  741. // break;
  742. }
  743. pop_call();
  744. return TRUE;
  745. }
  746. for (index = 0 ; index < root->used ; index++)
  747. {
  748. if (match(ses, root->list[index]->arg1, text, SUB_VAR|SUB_FUN))
  749. {
  750. show_node(root, root->list[index], 0);
  751. found = TRUE;
  752. }
  753. }
  754. pop_call();
  755. return found;
  756. }
  757. int delete_node_with_wild(struct session *ses, int type, char *text)
  758. {
  759. struct listroot *root = ses->list[type];
  760. struct listnode *node;
  761. char arg1[BUFFER_SIZE];
  762. int index, found = FALSE;
  763. sub_arg_in_braces(ses, text, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  764. switch (list_table[type].mode)
  765. {
  766. case SORT_ALPHA:
  767. case SORT_STABLE:
  768. index = bsearch_alpha_list(root, arg1, 0);
  769. break;
  770. case SORT_ALNUM:
  771. index = bsearch_alnum_list(root, arg1, 0);
  772. break;
  773. default:
  774. index = nsearch_list(root, arg1);
  775. break;
  776. }
  777. if (index != -1)
  778. {
  779. node = root->list[index];
  780. show_message(ses, type, "#OK. {%s} IS NO LONGER %s %s.", node->arg1, (*list_table[type].name == 'A' || *list_table[type].name == 'E') ? "AN" : "A", list_table[type].name);
  781. delete_index_list(root, index);
  782. return TRUE;
  783. }
  784. for (index = root->used - 1 ; index >= 0 ; index--)
  785. {
  786. if (match(ses, root->list[index]->arg1, arg1, SUB_VAR|SUB_FUN))
  787. {
  788. show_message(ses, type, "#OK. {%s} IS NO LONGER %s %s.", root->list[index]->arg1, is_vowel(list_table[type].name) ? "AN" : "A", list_table[type].name);
  789. delete_index_list(root, index);
  790. found = TRUE;
  791. }
  792. }
  793. if (found == 0)
  794. {
  795. show_message(ses, type, "#KILL: NO MATCHES FOUND FOR %s {%s}.", list_table[type].name, arg1);
  796. return FALSE;
  797. }
  798. return TRUE;
  799. }
  800. DO_COMMAND(do_killall)
  801. {
  802. tintin_printf2(ses, "\e[1;31m#NOTICE: PLEASE CHANGE #KILLALL TO #KILL ALL.");
  803. do_kill(ses, arg, arg1, arg2, arg3, arg4);
  804. return ses;
  805. }
  806. DO_COMMAND(do_kill)
  807. {
  808. int index;
  809. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  810. get_arg_in_braces(ses, arg, arg2, GET_ALL);
  811. if (*arg1 == 0 || !strcasecmp(arg1, "ALL"))
  812. {
  813. for (index = 0 ; index < LIST_MAX ; index++)
  814. {
  815. if (index == LIST_PATHDIR)
  816. {
  817. continue;
  818. }
  819. if (!HAS_BIT(ses->list[index]->flags, LIST_FLAG_HIDE))
  820. {
  821. kill_list(ses->list[index]);
  822. }
  823. }
  824. show_message(ses, LIST_COMMAND, "#KILL - ALL LISTS CLEARED.");
  825. return ses;
  826. }
  827. for (index = 0 ; index < LIST_MAX ; index++)
  828. {
  829. if (!is_abbrev(arg1, list_table[index].name) && !is_abbrev(arg1, list_table[index].name_multi))
  830. {
  831. continue;
  832. }
  833. if (*arg2 == 0 || !strcasecmp(arg2, "ALL"))
  834. {
  835. kill_list(ses->list[index]);
  836. show_message(ses, LIST_COMMAND, "#OK: #%s LIST CLEARED.", list_table[index].name);
  837. }
  838. else
  839. {
  840. delete_node_with_wild(ses, index, arg);
  841. }
  842. break;
  843. }
  844. if (index == LIST_MAX)
  845. {
  846. show_error(ses, LIST_COMMAND, "#ERROR: #KILL {%s} {%s} - NO MATCH FOUND.", arg1, arg2);
  847. }
  848. return ses;
  849. }
  850. DO_COMMAND(do_message)
  851. {
  852. int index, found = FALSE;
  853. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  854. arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
  855. if (*arg1 == 0)
  856. {
  857. tintin_header(ses, 80, " MESSAGES ");
  858. for (index = 0 ; index < LIST_MAX ; index++)
  859. {
  860. if (!HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  861. {
  862. tintin_printf2(ses, " %-20s %3s", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF");
  863. }
  864. }
  865. tintin_header(ses, 80, "");
  866. }
  867. else
  868. {
  869. for (index = found = 0 ; index < LIST_MAX ; index++)
  870. {
  871. if (HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  872. {
  873. continue;
  874. }
  875. if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
  876. {
  877. continue;
  878. }
  879. if (*arg2 == 0)
  880. {
  881. TOG_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE);
  882. }
  883. else if (is_abbrev(arg2, "ON"))
  884. {
  885. SET_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE);
  886. }
  887. else if (is_abbrev(arg2, "OFF"))
  888. {
  889. DEL_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE);
  890. }
  891. else
  892. {
  893. show_error(ses, LIST_COMMAND, "#SYNTAX: #MESSAGE {%s} [ON|OFF]", arg1);
  894. return ses;
  895. }
  896. show_message(ses, LIST_COMMAND, "#OK: #MESSAGE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF");
  897. found = TRUE;
  898. }
  899. if (found == FALSE)
  900. {
  901. show_error(ses, LIST_COMMAND, "#ERROR: #MESSAGE {%s} - NO MATCH FOUND.", arg1);
  902. }
  903. }
  904. return ses;
  905. }
  906. DO_COMMAND(do_ignore)
  907. {
  908. int index, found = FALSE;
  909. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  910. arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
  911. if (*arg1 == 0)
  912. {
  913. tintin_header(ses, 80, " IGNORES ");
  914. for (index = 0 ; index < LIST_MAX ; index++)
  915. {
  916. if (!HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  917. {
  918. tintin_printf2(ses, " %-20s %3s", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF");
  919. }
  920. }
  921. tintin_header(ses, 80, "");
  922. }
  923. else
  924. {
  925. for (index = found = 0 ; index < LIST_MAX ; index++)
  926. {
  927. if (HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  928. {
  929. continue;
  930. }
  931. if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
  932. {
  933. continue;
  934. }
  935. if (*arg2 == 0)
  936. {
  937. TOG_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE);
  938. }
  939. else if (is_abbrev(arg2, "ON"))
  940. {
  941. SET_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE);
  942. }
  943. else if (is_abbrev(arg2, "OFF"))
  944. {
  945. DEL_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE);
  946. }
  947. else
  948. {
  949. show_error(ses, LIST_COMMAND, "#SYNTAX: #IGNORE {%s} [ON|OFF]", arg1);
  950. return ses;
  951. }
  952. show_message(ses, LIST_COMMAND, "#OK: #IGNORE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF");
  953. found = TRUE;
  954. }
  955. if (found == FALSE)
  956. {
  957. show_error(ses, LIST_COMMAND, "#ERROR: #IGNORE {%s} - NO MATCH FOUND.", arg1);
  958. }
  959. }
  960. return ses;
  961. }
  962. DO_COMMAND(do_debug)
  963. {
  964. int index, found = FALSE;
  965. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  966. arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
  967. if (*arg1 == 0)
  968. {
  969. tintin_header(ses, 80, " DEBUGS ");
  970. for (index = 0 ; index < LIST_MAX ; index++)
  971. {
  972. if (!HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  973. {
  974. tintin_printf2(ses, " %-20s %3s", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF");
  975. }
  976. }
  977. tintin_header(ses, 80, "");
  978. }
  979. else
  980. {
  981. for (index = found = 0 ; index < LIST_MAX ; index++)
  982. {
  983. if (HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  984. {
  985. continue;
  986. }
  987. if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
  988. {
  989. continue;
  990. }
  991. if (*arg2 == 0)
  992. {
  993. TOG_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG);
  994. }
  995. else if (is_abbrev(arg2, "ON"))
  996. {
  997. SET_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG);
  998. }
  999. else if (is_abbrev(arg2, "OFF"))
  1000. {
  1001. DEL_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG);
  1002. DEL_BIT(ses->list[index]->flags, LIST_FLAG_LOG);
  1003. }
  1004. else if (is_abbrev(arg2, "LOG"))
  1005. {
  1006. SET_BIT(ses->list[index]->flags, LIST_FLAG_LOG);
  1007. }
  1008. else
  1009. {
  1010. show_error(ses, LIST_COMMAND, "#SYNTAX: #DEBUG {%s} [ON|OFF|LOG]", arg1);
  1011. return ses;
  1012. }
  1013. show_message(ses, LIST_COMMAND, "#OK: #DEBUG STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, is_abbrev(arg2, "LOG") ? "LOG" : HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF");
  1014. found = TRUE;
  1015. }
  1016. if (found == FALSE)
  1017. {
  1018. show_error(ses, LIST_COMMAND, "#DEBUG {%s} - NO MATCH FOUND.", arg1);
  1019. }
  1020. }
  1021. return ses;
  1022. }
  1023. DO_COMMAND(do_info)
  1024. {
  1025. char name[BUFFER_SIZE];
  1026. int cnt, index, found = FALSE;
  1027. struct listroot *root;
  1028. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  1029. arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
  1030. if (*arg1 == 0)
  1031. {
  1032. tintin_header(ses, 80, " INFORMATION ");
  1033. for (index = 0 ; index < LIST_MAX ; index++)
  1034. {
  1035. if (!HAS_BIT(ses->list[index]->flags, LIST_FLAG_HIDE))
  1036. {
  1037. tintin_printf2(ses, "%-15s %5d IGNORE %3s MESSAGE %3s INFO %3s DEBUG %3s%s",
  1038. list_table[index].name_multi,
  1039. ses->list[index]->used,
  1040. HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF",
  1041. HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF",
  1042. HAS_BIT(ses->list[index]->flags, LIST_FLAG_INFO) ? "ON" : "OFF",
  1043. HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF",
  1044. HAS_BIT(ses->list[index]->flags, LIST_FLAG_LOG) ? " LOG" : "");
  1045. }
  1046. }
  1047. tintin_header(ses, 80, "");
  1048. }
  1049. else
  1050. {
  1051. for (index = found = 0 ; index < LIST_MAX ; index++)
  1052. {
  1053. if (HAS_BIT(list_table[index].flags, LIST_FLAG_HIDE))
  1054. {
  1055. continue;
  1056. }
  1057. if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
  1058. {
  1059. continue;
  1060. }
  1061. if (*arg2 == 0)
  1062. {
  1063. TOG_BIT(ses->list[index]->flags, LIST_FLAG_INFO);
  1064. }
  1065. else if (is_abbrev(arg2, "ON"))
  1066. {
  1067. SET_BIT(ses->list[index]->flags, LIST_FLAG_INFO);
  1068. }
  1069. else if (is_abbrev(arg2, "OFF"))
  1070. {
  1071. DEL_BIT(ses->list[index]->flags, LIST_FLAG_INFO);
  1072. }
  1073. else
  1074. {
  1075. root = ses->list[index];
  1076. if (is_abbrev(arg2, "LIST"))
  1077. {
  1078. for (cnt = 0 ; cnt < root->used ; cnt++)
  1079. {
  1080. tintin_printf2(ses, "#INFO %s %4d {arg1}{%s} {arg2}{%s} {arg3}{%s} {arg4}{%s} {class}{%s} {shots}{%u}", list_table[index].name_multi, cnt+1, root->list[cnt]->arg1, root->list[cnt]->arg2, root->list[cnt]->arg3, root->list[cnt]->arg4, root->list[cnt]->group, root->list[cnt]->shots);
  1081. }
  1082. }
  1083. else if (is_abbrev(arg2, "SAVE"))
  1084. {
  1085. sprintf(name, "info[%s]", list_table[index].name_multi);
  1086. set_nest_node_ses(ses, name, "");
  1087. for (cnt = 0 ; cnt < root->used ; cnt++)
  1088. {
  1089. sprintf(name, "info[%s][%d]", list_table[index].name_multi, cnt + 1);
  1090. set_nest_node_ses(ses, name, "{arg1}{%s}{arg2}{%s}{arg3}{%s}{arg4}{%s}{class}{%s}{nest}{%d}{shots}{%u}", root->list[cnt]->arg1, root->list[cnt]->arg2, root->list[cnt]->arg3, root->list[cnt]->arg4, root->list[cnt]->group, root->list[cnt]->root ? root->list[cnt]->root->used : 0, root->list[cnt]->shots);
  1091. }
  1092. show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[%s]}", list_table[index].name_multi);
  1093. }
  1094. else
  1095. {
  1096. show_error(ses, LIST_COMMAND, "#SYNTAX: #INFO {%s} [ON|OFF|LIST|SAVE|SYSTEM]", arg1);
  1097. }
  1098. return ses;
  1099. }
  1100. show_message(ses, LIST_COMMAND, "#OK: #INFO STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_INFO) ? "ON" : "OFF");
  1101. if (strcasecmp(arg1, "ALL"))
  1102. {
  1103. return ses;
  1104. }
  1105. found = TRUE;
  1106. }
  1107. if (found)
  1108. {
  1109. return ses;
  1110. }
  1111. *gtd->is_result = 0;
  1112. switch (*arg1 % 32)
  1113. {
  1114. case CTRL_A:
  1115. if (is_abbrev(arg1, "ARGUMENTS"))
  1116. {
  1117. if (is_abbrev(arg2, "SAVE"))
  1118. {
  1119. set_nest_node_ses(ses, "info[ARGUMENTS]", "");
  1120. for (index = 0 ; index < gtd->varc ; index++)
  1121. {
  1122. add_nest_node_ses(ses, "info[ARGUMENTS]", "{%d}{%s}", index, gtd->vars[index]);
  1123. }
  1124. }
  1125. else
  1126. {
  1127. for (index = 0 ; index < gtd->varc ; index++)
  1128. {
  1129. tintin_printf2(ses, "#INFO ARGUMENTS: %2d: %s", index, gtd->vars[index]);
  1130. }
  1131. }
  1132. }
  1133. break;
  1134. case CTRL_B:
  1135. if (is_abbrev(arg1, "BIG5TOUTF8"))
  1136. {
  1137. big5toutf8_info(ses);
  1138. }
  1139. break;
  1140. case CTRL_C:
  1141. if (is_abbrev(arg1, "CPU"))
  1142. {
  1143. show_cpu(ses);
  1144. }
  1145. break;
  1146. case CTRL_D:
  1147. if (is_abbrev(arg1, "DAEMON"))
  1148. {
  1149. if (is_abbrev(arg2, "SAVE"))
  1150. {
  1151. sprintf(name, "info[DAEMON]");
  1152. set_nest_node_ses(ses, name, "{DETACH_FILE}{%s}{ATTACH_FILE}{%s}", gtd->detach_port > 0 ? gtd->detach_file : "", gtd->attach_sock > 0 ? gtd->attach_file : "");
  1153. show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
  1154. }
  1155. else
  1156. {
  1157. tintin_printf2(ses, "#INFO DAEMON: DETACH UID = %d", gtd->detach_info.uid);
  1158. tintin_printf2(ses, "#INFO DAEMON: DETACH GID = %d", gtd->detach_info.gid);
  1159. tintin_printf2(ses, "#INFO DAEMON: DETACH PID = %d", gtd->detach_info.pid);
  1160. tintin_printf2(ses, "#INFO DAEMON: DETACH_SOCK = %d", gtd->detach_sock);
  1161. tintin_printf2(ses, "#INFO DAEMON: DETACH_PORT = %d", gtd->detach_port);
  1162. tintin_printf2(ses, "#INFO DAEMON: DETACH_FILE = %s", gtd->detach_port ? gtd->detach_file : "");
  1163. tintin_printf2(ses, "#INFO DAEMON: ATTACH_SOCK = %d", gtd->attach_sock);
  1164. tintin_printf2(ses, "#INFO DAEMON: ATTACH_FILE = %s", gtd->attach_sock ? gtd->attach_file : "");
  1165. }
  1166. }
  1167. break;
  1168. case CTRL_E:
  1169. if (is_abbrev(arg1, "ENVIRON"))
  1170. {
  1171. char **env, *sep;
  1172. if (is_abbrev(arg2, "SAVE"))
  1173. {
  1174. set_nest_node_ses(ses, "info[ENVIRON]", "");
  1175. for (env = environ ; *env ; env++)
  1176. {
  1177. sep = strchr(*env, '=');
  1178. *sep = 0;
  1179. add_nest_node_ses(ses, "info[ENVIRON]", "{%s}{%s}", *env, sep + 1);
  1180. *sep = '=';
  1181. }
  1182. }
  1183. else
  1184. {
  1185. for (env = environ ; *env ; env++)
  1186. {
  1187. tintin_printf2(ses, "%s", *env);
  1188. }
  1189. }
  1190. }
  1191. break;
  1192. case CTRL_I:
  1193. if (is_abbrev(arg1, "INPUT"))
  1194. {
  1195. if (is_abbrev(arg2, "SAVE"))
  1196. {
  1197. set_nest_node_ses(ses, "info[INPUT]", "{BUFFER}{%s}", gtd->ses->input->buf);
  1198. add_nest_node_ses(ses, "info[INPUT]", "{CUT}{%s}", gtd->ses->input->cut);
  1199. add_nest_node_ses(ses, "info[INPUT]", "{COL}{%d}", inputline_cur_col());
  1200. add_nest_node_ses(ses, "info[INPUT]", "{HEIGHT}{%d}", inputline_max_row());
  1201. add_nest_node_ses(ses, "info[INPUT]", "{LENGTH}{%d}", inputline_cur_str_len());
  1202. add_nest_node_ses(ses, "info[INPUT]", "{NAME}{%s}", gtd->ses->input->line_name);
  1203. add_nest_node_ses(ses, "info[INPUT]", "{OFFSET}{%d}", inputline_cur_off());
  1204. add_nest_node_ses(ses, "info[INPUT]", "{ROW}{%d}", inputline_cur_row());
  1205. add_nest_node_ses(ses, "info[INPUT]", "{WIDTH}{%d}", inputline_max_str_len());
  1206. }
  1207. else
  1208. {
  1209. tintin_printf2(ses, "#INFO INPUT: BUFFER: %s", gtd->ses->input->buf);
  1210. tintin_printf2(ses, "#INFO INPUT: CUT: %s", gtd->ses->input->cut);
  1211. tintin_printf2(ses, "#INFO INPUT: COL: %d", inputline_cur_col());
  1212. tintin_printf2(ses, "#INFO INPUT: HEIGHT: %d", inputline_max_row());
  1213. tintin_printf2(ses, "#INFO INPUT: LENGTH: %d", inputline_cur_str_len());
  1214. tintin_printf2(ses, "#INFO INPUT: NAME: %s", gtd->ses->input->line_name);
  1215. tintin_printf2(ses, "#INFO INPUT: OFFSET: %d", inputline_cur_off());
  1216. tintin_printf2(ses, "#INFO INPUT: ROW: %d", inputline_cur_row());
  1217. tintin_printf2(ses, "#INFO INPUT: WIDTH: %d", inputline_max_str_len());
  1218. }
  1219. }
  1220. break;
  1221. case CTRL_M:
  1222. if (is_abbrev(arg1, "MATCHES"))
  1223. {
  1224. if (is_abbrev(arg2, "SAVE"))
  1225. {
  1226. set_nest_node_ses(ses, "info[MATCHES]", "");
  1227. for (index = 0 ; index < gtd->cmdc ; index++)
  1228. {
  1229. add_nest_node_ses(ses, "info[MATCHES]", "{%d}{%s}", index, gtd->cmds[index]);
  1230. }
  1231. }
  1232. else
  1233. {
  1234. for (index = 0 ; index < gtd->cmdc ; index++)
  1235. {
  1236. tintin_printf2(ses, "#INFO MATCHES: %2d: %s", index, gtd->cmds[index]);
  1237. }
  1238. }
  1239. }
  1240. else if (is_abbrev(arg1, "MCCP"))
  1241. {
  1242. if (ses->mccp2)
  1243. {
  1244. tintin_printf2(ses, "#INFO MCCP2: TOTAL IN: %9u TOTAL OUT: %9u PERCENT: %3d", ses->mccp2->total_in, ses->mccp2->total_out, ses->mccp2->total_out ? 100 * ses->mccp2->total_in / ses->mccp2->total_out : 0);
  1245. }
  1246. if (ses->mccp3)
  1247. {
  1248. tintin_printf2(ses, "#INFO MCCP3: TOTAL IN: %9u TOTAL OUT: %9u PERCENT: %3d", ses->mccp3->total_in, ses->mccp3->total_out, ses->mccp3->total_in ? 100 * ses->mccp3->total_out / ses->mccp3->total_in : 0);
  1249. }
  1250. }
  1251. else if (is_abbrev(arg1, "MEMORY"))
  1252. {
  1253. struct str_data *str_ptr;
  1254. long long quan, used, max;
  1255. max = 0;
  1256. quan = 0;
  1257. used = 0;
  1258. for (index = 0 ; index < gtd->memory->stack_cap ; index++)
  1259. {
  1260. max++;
  1261. quan += gtd->memory->stack[index]->max;
  1262. used += gtd->memory->stack[index]->len;
  1263. }
  1264. tintin_printf2(ses, "#INFO MEMORY: STACK SIZE: %d", quan);
  1265. tintin_printf2(ses, "#INFO MEMORY: STACK MAX: %d", gtd->memory->stack_max);
  1266. tintin_printf2(ses, "#INFO MEMORY: STACK CAP: %d", gtd->memory->stack_cap);
  1267. tintin_printf2(ses, "#INFO MEMORY: STACK LEN: %d", gtd->memory->stack_len);
  1268. tintin_printf2(ses, "");
  1269. max = 0;
  1270. quan = 0;
  1271. used = 0;
  1272. for (index = 0 ; index < gtd->memory->list_len ; index++)
  1273. {
  1274. str_ptr = gtd->memory->list[index];
  1275. if (str_ptr->max != NAME_SIZE + 1 && strlen(get_str_str(str_ptr)) != str_ptr->len)
  1276. {
  1277. tintin_printf2(ses, "#ERROR: index %d len = %d/%d max = %d flags = %d (%s)", index, strlen(get_str_str(str_ptr)), str_ptr->len, str_ptr->max, str_ptr->flags, get_str_str(str_ptr));
  1278. }
  1279. if (!HAS_BIT(str_ptr->flags, STR_FLAG_FREE))
  1280. {
  1281. max++;
  1282. quan += str_ptr->max;
  1283. used += str_ptr->len;
  1284. }
  1285. }
  1286. tintin_printf2(ses, "#INFO MEMORY: ALLOC SIZE: %d", quan);
  1287. tintin_printf2(ses, "#INFO MEMORY: ALLOC USED: %d", used);
  1288. tintin_printf2(ses, "#INFO MEMORY: ALLOC MAX: %d", gtd->memory->list_max);
  1289. tintin_printf2(ses, "#INFO MEMORY: ALLOC LEN: %d", gtd->memory->list_len);
  1290. tintin_printf2(ses, "");
  1291. quan = 0;
  1292. used = 0;
  1293. for (index = 0 ; index < gtd->memory->free_len ; index++)
  1294. {
  1295. str_ptr = gtd->memory->list[gtd->memory->free[index]];
  1296. if (HAS_BIT(str_ptr->flags, STR_FLAG_FREE))
  1297. {
  1298. quan += str_ptr->max;
  1299. used += str_ptr->len;
  1300. }
  1301. else
  1302. {
  1303. tintin_printf2(ses, "error: found freed memory not marked as free.");
  1304. }
  1305. }
  1306. tintin_printf2(ses, "#INFO MEMORY: FREED SIZE: %d", quan);
  1307. tintin_printf2(ses, "#INFO MEMORY: FREED MAX: %d", gtd->memory->free_max);
  1308. tintin_printf2(ses, "#INFO MEMORY: FREED LEN: %d", gtd->memory->free_len);
  1309. tintin_printf2(ses, "");
  1310. quan = 0;
  1311. used = 0;
  1312. for (index = 0 ; index < gtd->memory->debug_len ; index++)
  1313. {
  1314. quan += NAME_SIZE;
  1315. }
  1316. tintin_printf2(ses, "#INFO MEMORY: DEBUG SIZE: %d", quan);
  1317. tintin_printf2(ses, "#INFO MEMORY: DEBUG MAX: %d", gtd->memory->debug_max);
  1318. tintin_printf2(ses, "#INFO MEMORY: DEBUG LEN: %d", gtd->memory->debug_len);
  1319. }
  1320. break;
  1321. case CTRL_S:
  1322. if (is_abbrev(arg1, "SESSION"))
  1323. {
  1324. if (is_abbrev(arg2, "SAVE"))
  1325. {
  1326. set_nest_node_ses(ses, "info[SESSION]", "{NAME}{%s}", ses->name);
  1327. add_nest_node_ses(ses, "info[SESSION]", "{ACTIVE}{%d}", gtd->ses == ses);
  1328. add_nest_node_ses(ses, "info[SESSION]", "{CLASS}{%s}", ses->group);
  1329. add_nest_node_ses(ses, "info[SESSION]", "{CREATED}{%d}", ses->created);
  1330. add_nest_node_ses(ses, "info[SESSION]", "{HOST} {%s}", ses->session_host);
  1331. add_nest_node_ses(ses, "info[SESSION]", "{IP} {%s}", ses->session_ip);
  1332. add_nest_node_ses(ses, "info[SESSION]", "{PORT} {%s}", ses->session_port);
  1333. show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SESSION]}");
  1334. }
  1335. else
  1336. {
  1337. tintin_printf2(ses, "{NAME}{%s}", ses->name);
  1338. tintin_printf2(ses, "{ACTIVE}{%d}", gtd->ses == ses);
  1339. tintin_printf2(ses, "{CLASS}{%s}", ses->group);
  1340. tintin_printf2(ses, "{CREATED}{%d}", ses->created);
  1341. tintin_printf2(ses, "{HOST} {%s}", ses->session_host);
  1342. tintin_printf2(ses, "{IP} {%s}", ses->session_ip);
  1343. tintin_printf2(ses, "{PORT} {%s}", ses->session_port);
  1344. }
  1345. }
  1346. else if (is_abbrev(arg1, "SESSIONS"))
  1347. {
  1348. struct session *sesptr;
  1349. if (is_abbrev(arg2, "SAVE"))
  1350. {
  1351. set_nest_node_ses(ses, "info[SESSIONS]", "");
  1352. for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
  1353. {
  1354. sprintf(name, "info[SESSIONS][%s]", sesptr->name);
  1355. add_nest_node_ses(ses, name, "{NAME}{%s}", sesptr->name);
  1356. add_nest_node_ses(ses, name, "{ACTIVE}{%d}", gtd->ses == sesptr);
  1357. add_nest_node_ses(ses, name, "{CLASS}{%s}", sesptr->group);
  1358. add_nest_node_ses(ses, name, "{CREATED}{%d}", sesptr->created);
  1359. add_nest_node_ses(ses, name, "{HOST} {%s}", sesptr->session_host);
  1360. add_nest_node_ses(ses, name, "{IP} {%s}", sesptr->session_ip);
  1361. add_nest_node_ses(ses, name, "{PORT} {%s}", sesptr->session_port);
  1362. }
  1363. show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SESSIONS]}");
  1364. }
  1365. else
  1366. {
  1367. for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
  1368. {
  1369. tintin_printf2(ses, "{%s}{NAME}{%s}", sesptr->name, sesptr->name);
  1370. tintin_printf2(ses, "{%s}{ACTIVE}{%d}", sesptr->name, gtd->ses == sesptr);
  1371. tintin_printf2(ses, "{%s}{CLASS}{%s}", sesptr->name, sesptr->group);
  1372. tintin_printf2(ses, "{%s}{CREATED}{%d}", sesptr->name, sesptr->created);
  1373. tintin_printf2(ses, "{%s}{HOST} {%s}", sesptr->name, sesptr->session_host);
  1374. tintin_printf2(ses, "{%s}{IP} {%s}", sesptr->name, sesptr->session_ip);
  1375. tintin_printf2(ses, "{%s}{PORT} {%s}", sesptr->name, sesptr->session_port);
  1376. }
  1377. }
  1378. }
  1379. else if (is_abbrev(arg1, "STACK"))
  1380. {
  1381. dump_stack();
  1382. }
  1383. else if (is_abbrev(arg1, "SYSTEM"))
  1384. {
  1385. char cwd[PATH_MAX];
  1386. if (getcwd(cwd, PATH_MAX) == NULL)
  1387. {
  1388. syserr_printf(ses, "do_info: getcwd:");
  1389. cwd[0] = 0;
  1390. }
  1391. if (is_abbrev(arg2, "SAVE"))
  1392. {
  1393. sprintf(name, "info[SYSTEM]");
  1394. set_nest_node_ses(ses, name, "{CLIENT_NAME}{%s}{CLIENT_VERSION}{%s}", CLIENT_NAME, CLIENT_VERSION);
  1395. add_nest_node_ses(ses, name, "{CWD}{%s}{EXEC}{%s}{HOME}{%s}{LANG}{%s}{OS}{%s}{PID}{%d}{TERM}{%s}{TINTIN}{%s}", cwd, gtd->system->exec, gtd->system->home, gtd->system->lang, gtd->system->os, getpid(), gtd->system->term, gtd->system->tt_dir);
  1396. add_nest_node_ses(ses, name, "{DETACH_FILE}{%s}{ATTACH_FILE}{%s}", gtd->detach_port > 0 ? gtd->detach_file : "", gtd->attach_sock > 0 ? gtd->attach_file : "");
  1397. show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
  1398. }
  1399. else
  1400. {
  1401. tintin_printf2(ses, "#INFO SYSTEM: CLIENT_NAME = %s", CLIENT_NAME);
  1402. tintin_printf2(ses, "#INFO SYSTEM: CLIENT_VERSION = %s", CLIENT_VERSION);
  1403. tintin_printf2(ses, "#INFO SYSTEM: CWD = %s", cwd);
  1404. tintin_printf2(ses, "#INFO SYSTEM: EXEC = %s", gtd->system->exec);
  1405. tintin_printf2(ses, "#INFO SYSTEM: HOME = %s", gtd->system->home);
  1406. tintin_printf2(ses, "#INFO SYSTEM: LANG = %s", gtd->system->lang);
  1407. tintin_printf2(ses, "#INFO SYSTEM: OS = %s", gtd->system->os);
  1408. tintin_printf2(ses, "#INFO SYSTEM: PID = %d", getpid());
  1409. tintin_printf2(ses, "#INFO SYSTEM: TERM = %s", gtd->system->term);
  1410. tintin_printf2(ses, "#INFO SYSTEM: TINTIN = %s", gtd->system->tt_dir);
  1411. }
  1412. }
  1413. break;
  1414. case CTRL_T:
  1415. if (is_abbrev(arg1, "TOKENIZER"))
  1416. {
  1417. int index = URANGE(0, gtd->script_index + atoi(arg2), gtd->script_index);
  1418. struct scriptroot *root = gtd->script_stack[index];
  1419. tintin_printf2(ses, "#INFO TOKENIZER: SCRIPT_INDEX = %d", index);
  1420. tintin_printf2(ses, "#INFO TOKENIZER: SESSION_NAME = %s", root->ses->name);
  1421. tintin_printf2(ses, "#INFO TOKENIZER: LIST_TYPE = %s", list_table[root->list].name);
  1422. tintin_printf2(ses, "#INFO TOKENIZER: LOCAL_VARS = %d", root->local->used);
  1423. tintin_printf2(ses, "#INFO TOKENIZER: SCRIPT =\n%s", view_script(ses, root));
  1424. }
  1425. break;
  1426. case CTRL_U:
  1427. if (is_abbrev(arg1, "UNICODE"))
  1428. {
  1429. int size, width, index;
  1430. size = get_utf8_size(arg2);
  1431. get_utf8_width(arg2, &width, NULL);
  1432. get_utf8_index(arg2, &index);
  1433. tintin_printf2(ses, "#INFO UNICODE: %s: is_utf8_head = %d (%s)", arg2, is_utf8_head(arg2), is_utf8_head(arg2) ? "true" : "false");
  1434. tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_size = %d", arg2, size);
  1435. tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_width = %d", arg2, width);
  1436. tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_index = %d (decimal)", arg2, index);
  1437. tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_index = %x (hexadecimal)", arg2, index);
  1438. }
  1439. else if (is_abbrev(arg1, "UTF8TOBIG5"))
  1440. {
  1441. utf8tobig5_info(ses);
  1442. }
  1443. break;
  1444. }
  1445. if (*gtd->is_result == 0)
  1446. {
  1447. show_error(ses, LIST_COMMAND, "#INFO {%s} - NO MATCH FOUND.", arg1);
  1448. }
  1449. }
  1450. return ses;
  1451. }