list.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2019 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. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  19. ******************************************************************************/
  20. /******************************************************************************
  21. * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t *
  22. * *
  23. * coded by Igor van den Hoven 2004 *
  24. ******************************************************************************/
  25. #include "tintin.h"
  26. #define DO_ARRAY(array) struct session *array (struct session *ses, struct listnode *list, char *arg, char *var, char *arg1, char *arg2)
  27. extern DO_ARRAY(array_add);
  28. extern DO_ARRAY(array_clear);
  29. extern DO_ARRAY(array_collapse);
  30. extern DO_ARRAY(array_copy);
  31. extern DO_ARRAY(array_create);
  32. extern DO_ARRAY(array_delete);
  33. extern DO_ARRAY(array_explode);
  34. extern DO_ARRAY(array_filter);
  35. extern DO_ARRAY(array_find);
  36. extern DO_ARRAY(array_get);
  37. extern DO_ARRAY(array_indexate);
  38. extern DO_ARRAY(array_insert);
  39. extern DO_ARRAY(array_numerate);
  40. extern DO_ARRAY(array_order);
  41. extern DO_ARRAY(array_reverse);
  42. extern DO_ARRAY(array_refine);
  43. extern DO_ARRAY(array_set);
  44. extern DO_ARRAY(array_shuffle);
  45. extern DO_ARRAY(array_simplify);
  46. extern DO_ARRAY(array_size);
  47. extern DO_ARRAY(array_sort);
  48. extern DO_ARRAY(array_swap);
  49. extern DO_ARRAY(array_tokenize);
  50. typedef struct session *ARRAY(struct session *ses, struct listnode *list, char *arg, char *var, char *arg1, char *arg2);
  51. struct array_type
  52. {
  53. char * name;
  54. ARRAY * fun;
  55. char * desc;
  56. };
  57. struct array_type array_table[] =
  58. {
  59. { "ADD", array_add, "Add items to a list" },
  60. { "CLEAR", array_clear, "Clear a list" },
  61. { "CLR", array_clear, NULL },
  62. { "COLLAPSE", array_collapse, "Collapse the list into a variable" },
  63. { "COPY", array_copy, "Copy a list to a list" },
  64. { "CREATE", array_create, "Create a list with given items" },
  65. { "DELETE", array_delete, "Delete a list item with given index" },
  66. { "EXPLODE", array_explode, "Explode the variable into a list" },
  67. { "FILTER", array_filter, "Filter a list with given regex" },
  68. { "FIND", array_find, "Find a list item with given regex" },
  69. { "FND", array_find, NULL },
  70. { "GET", array_get, "Retrieve a list item with given index" },
  71. { "INDEXATE", array_indexate, "Indexate a list table for sorting" },
  72. { "INSERT", array_insert, "Insert an item at given index" },
  73. { "NUMERATE", array_numerate, "Turn a table into a list" },
  74. { "ORDER", array_order, "Sort a list table numerically" },
  75. { "LENGTH", array_size, NULL },
  76. { "REFINE", array_refine, "Filter a list with given math" },
  77. { "REVERSE", array_reverse, "Sort a list table in reverse order" },
  78. { "SET", array_set, "Change a list item at given index" },
  79. { "SHUFFLE", array_shuffle, "Sort a list table in random order" },
  80. { "SIMPLIFY", array_simplify, "Turn a list table into a simple list" },
  81. { "SIZE", array_size, NULL },
  82. { "SORT", array_sort, "Sort a list table alphabetically" },
  83. { "SRT", array_sort, NULL },
  84. { "SWAP", array_swap, "Swap two list items" },
  85. { "TOKENIZE", array_tokenize, "Create a list with given characters" },
  86. { "", NULL, "" }
  87. };
  88. DO_COMMAND(do_list)
  89. {
  90. struct listnode *node;
  91. int index, cnt;
  92. arg = sub_arg_in_braces(ses, arg, arg1, GET_NST, SUB_VAR|SUB_FUN);
  93. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  94. if (*arg1 == 0)
  95. {
  96. tintin_header(ses, 80, " LIST OPTIONS ");
  97. for (index = 0 ; *array_table[index].fun ; index++)
  98. {
  99. if (array_table[index].desc && *array_table[index].name)
  100. {
  101. tintin_printf2(ses, " [%-24s] %s", array_table[index].name, array_table[index].desc);
  102. }
  103. }
  104. tintin_header(ses, 80, "");
  105. }
  106. else if (*arg2 == 0)
  107. {
  108. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST <VARIABLE> <OPTION> <ARGUMENT>");
  109. }
  110. else
  111. {
  112. for (cnt = 0 ; *array_table[cnt].name ; cnt++)
  113. {
  114. if (is_abbrev(arg2, array_table[cnt].name))
  115. {
  116. break;
  117. }
  118. }
  119. if (*array_table[cnt].name == 0)
  120. {
  121. show_error(ses, LIST_VARIABLE, "#ERROR: #LIST {%s} {%s}: INVALID LIST OPTION.", arg1, arg2);
  122. return ses;
  123. }
  124. if (!valid_variable(ses, arg1))
  125. {
  126. show_error(ses, LIST_VARIABLE, "#ERROR: #LIST {%s} {%s}: INVALID VARIABLE NAME.", arg1, arg2);
  127. return ses;
  128. }
  129. if ((node = search_nest_node_ses(ses, arg1)) == NULL)
  130. {
  131. node = set_nest_node_ses(ses, arg1, "");
  132. }
  133. array_table[cnt].fun(ses, node, arg, arg1, arg2, arg3);
  134. }
  135. return ses;
  136. }
  137. int get_list_index(struct session *ses, struct listroot *root, char *arg)
  138. {
  139. int toi;
  140. toi = get_number(ses, arg);
  141. if (toi > 0)
  142. {
  143. if (toi <= root->used)
  144. {
  145. return toi - 1;
  146. }
  147. return -1;
  148. }
  149. if (toi < 0)
  150. {
  151. if (root->used + toi >= 0)
  152. {
  153. return root->used + toi;
  154. }
  155. return -1;
  156. }
  157. return -1;
  158. }
  159. DO_ARRAY(array_add)
  160. {
  161. char *str;
  162. int index;
  163. if (list->root == NULL)
  164. {
  165. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  166. }
  167. if (list->root->used)
  168. {
  169. int numerate = atoi(list->root->list[0]->arg1) == 1 && atoi(list->root->list[list->root->used - 1]->arg1) == list->root->used;
  170. if (numerate == 0)
  171. {
  172. for (index = 0 ; index < list->root->used ; index++)
  173. {
  174. if (atoi(list->root->list[index]->arg1) != index + 1)
  175. {
  176. break;
  177. }
  178. }
  179. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} ADD: INVALID LIST. INDEX %d IS SET TO {%s}.", var, index + 1, list->root->list[index]->arg1);
  180. return ses;
  181. }
  182. }
  183. index = list->root->used + 1;
  184. while (*arg)
  185. {
  186. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  187. str = arg1;
  188. while (*str)
  189. {
  190. str = get_arg_in_braces(ses, str, arg2, GET_ALL);
  191. set_nest_node(list->root, ntos(index++), "%s", arg2);
  192. if (*str == COMMAND_SEPARATOR)
  193. {
  194. str++;
  195. }
  196. }
  197. if (*arg == COMMAND_SEPARATOR)
  198. {
  199. arg++;
  200. }
  201. }
  202. return ses;
  203. }
  204. DO_ARRAY(array_clear)
  205. {
  206. if (list->root)
  207. {
  208. free_list(list->root);
  209. list->root = NULL;
  210. }
  211. set_nest_node_ses(ses, var, "");
  212. return ses;
  213. }
  214. DO_ARRAY(array_collapse)
  215. {
  216. int index;
  217. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN|SUB_ESC);
  218. if (list->root)
  219. {
  220. if (list->root->used)
  221. {
  222. str_cpy(&list->arg2, list->root->list[0]->arg2);
  223. }
  224. for (index = 1 ; index < list->root->used ; index++)
  225. {
  226. str_cat(&list->arg2, arg1);
  227. str_cat(&list->arg2, list->root->list[index]->arg2);
  228. }
  229. free_list(list->root);
  230. list->root = NULL;
  231. }
  232. return ses;
  233. }
  234. DO_ARRAY(array_copy)
  235. {
  236. struct listnode *from;
  237. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  238. if (*arg1 == 0)
  239. {
  240. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {%s} COPY <VARIABLE>.", var);
  241. return ses;
  242. }
  243. if ((from = search_nest_node_ses(ses, arg1)) == NULL)
  244. {
  245. show_error(ses, LIST_VARIABLE, "#LIST COPY: VARIABLE {%s} NOT FOUND.", arg1);
  246. return ses;
  247. }
  248. if (!strcmp(var, arg1))
  249. {
  250. return ses;
  251. }
  252. str_cpy(&list->arg2, from->arg2);
  253. str_cpy(&list->arg3, from->arg3);
  254. str_cpy(&list->arg4, from->arg4);
  255. if (list->root)
  256. {
  257. free_list(list->root);
  258. list->root = NULL;
  259. }
  260. copy_nest_node(ses->list[LIST_VARIABLE], list, from);
  261. return ses;
  262. }
  263. DO_ARRAY(array_create)
  264. {
  265. char *buf, *str;
  266. int index = 1;
  267. buf = str_alloc_stack(0);
  268. substitute(ses, arg, buf, SUB_VAR|SUB_FUN);
  269. arg = buf;
  270. if (*arg == 0)
  271. {
  272. set_nest_node_ses(ses, arg1, "");
  273. return ses;
  274. }
  275. if (list->root)
  276. {
  277. free_list(list->root);
  278. }
  279. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  280. while (*arg)
  281. {
  282. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  283. str = arg1;
  284. while (*str)
  285. {
  286. str = get_arg_in_braces(ses, str, arg2, GET_ALL);
  287. set_nest_node(list->root, ntos(index++), "%s", arg2);
  288. if (*str == COMMAND_SEPARATOR)
  289. {
  290. *str = ' ';
  291. // str++;
  292. }
  293. }
  294. if (*arg == COMMAND_SEPARATOR)
  295. {
  296. *arg = ' ';
  297. // arg++;
  298. }
  299. }
  300. return ses;
  301. }
  302. DO_ARRAY(array_delete)
  303. {
  304. int index, cnt, loop;
  305. if (list->root)
  306. {
  307. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  308. arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
  309. index = get_list_index(ses, list->root, arg1);
  310. if (*arg2)
  311. {
  312. loop = URANGE(1, (int) get_number(ses, arg2), list->root->used - index);
  313. }
  314. else
  315. {
  316. loop = 1;
  317. }
  318. if (index == -1)
  319. {
  320. show_error(ses, LIST_VARIABLE, "#LIST {%s} DELETE: INVALID INDEX {%s}.", var, arg1);
  321. return ses;
  322. }
  323. for (cnt = index + loop ; cnt < list->root->used ; cnt++)
  324. {
  325. str_cpy_printf(&list->root->list[cnt]->arg1, "%d", cnt + 1 - loop);
  326. }
  327. while (loop--)
  328. {
  329. delete_index_list(list->root, index);
  330. }
  331. if (list->root->used == 0)
  332. {
  333. array_clear(ses, list, arg, var, arg1, arg2);
  334. }
  335. }
  336. else
  337. {
  338. show_error(ses, LIST_VARIABLE, "#LIST DELETE: VARIABLE {%s} IS NOT A LIST.", var);
  339. }
  340. return ses;
  341. }
  342. DO_ARRAY(array_explode)
  343. {
  344. char *str;
  345. int index = 1;
  346. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN|SUB_ESC);
  347. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  348. if (*arg1 == 0)
  349. {
  350. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {%s} EXPLODE <SEPARATOR>", var);
  351. return ses;
  352. }
  353. if (list->root)
  354. {
  355. if (*arg2 == 0)
  356. {
  357. show_error(ses, LIST_VARIABLE, "#LIST {%s} EXPLODE: VARIABLE {%s} IS ALREADY A LIST.", var, var);
  358. return ses;
  359. }
  360. free_list(list->root);
  361. list->root = NULL;
  362. }
  363. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  364. if (*arg2)
  365. {
  366. str_cpy(&list->arg2, arg2);
  367. }
  368. arg = list->arg2;
  369. while (1)
  370. {
  371. str = strstr(arg, arg1);
  372. if (str == NULL)
  373. {
  374. if (*arg)
  375. {
  376. set_nest_node(list->root, ntos(index++), "%s", arg);
  377. }
  378. break;
  379. }
  380. *str = 0;
  381. set_nest_node(list->root, ntos(index++), "%s", arg);
  382. arg = str + strlen(arg1);
  383. }
  384. return ses;
  385. }
  386. DO_ARRAY(array_filter)
  387. {
  388. int index;
  389. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  390. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  391. if (*arg1 == 0 && *arg2 == 0)
  392. {
  393. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST <VARIABLE> FILTER <KEEP> [REMOVE]");
  394. return ses;
  395. }
  396. if (list->root && list->root->used)
  397. {
  398. int numerate = atoi(list->root->list[0]->arg1) == 1 && atoi(list->root->list[list->root->used - 1]->arg1) == list->root->used;
  399. int found = 0;
  400. if (*arg1)
  401. {
  402. for (index = 0 ; index < list->root->used ; index++)
  403. {
  404. if (!match(ses, list->root->list[index]->arg2, arg1, SUB_NONE))
  405. {
  406. delete_index_list(list->root, index--);
  407. found = 1;
  408. }
  409. }
  410. }
  411. if (*arg2)
  412. {
  413. for (index = 0 ; index < list->root->used ; index++)
  414. {
  415. if (match(ses, list->root->list[index]->arg2, arg2, SUB_NONE))
  416. {
  417. delete_index_list(list->root, index--);
  418. found = 1;
  419. }
  420. }
  421. }
  422. if (found && list->root->used == 0)
  423. {
  424. array_clear(ses, list, arg, var, arg1, arg2);
  425. }
  426. else if (found && numerate)
  427. {
  428. array_numerate(ses, list, arg, var, arg1, arg2);
  429. }
  430. }
  431. return ses;
  432. }
  433. DO_ARRAY(array_find)
  434. {
  435. int index;
  436. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  437. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  438. if (*arg2 == 0)
  439. {
  440. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST <VARIABLE> FIND <TEXT> <VARIABLE>");
  441. return ses;
  442. }
  443. if (list->root)
  444. {
  445. for (index = 0 ; index < list->root->used ; index++)
  446. {
  447. if (match(ses, list->root->list[index]->arg2, arg1, SUB_NONE))
  448. {
  449. set_nest_node_ses(ses, arg2, "%d", index + 1);
  450. return ses;
  451. }
  452. }
  453. }
  454. set_nest_node_ses(ses, arg2, "0");
  455. return ses;
  456. }
  457. DO_ARRAY(array_get)
  458. {
  459. int index;
  460. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  461. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  462. if (*arg2 == 0)
  463. {
  464. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST <VARIABLE> GET <INDEX> <VARIABLE>");
  465. return ses;
  466. }
  467. if (list->root)
  468. {
  469. index = get_list_index(ses, list->root, arg1);
  470. if (index != -1)
  471. {
  472. set_nest_node_ses(ses, arg2, "%s", list->root->list[index]->arg2);
  473. return ses;
  474. }
  475. }
  476. set_nest_node_ses(ses, arg2, "0");
  477. return ses;
  478. }
  479. DO_ARRAY(array_indexate)
  480. {
  481. int cnt, index;
  482. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  483. if (list->root == NULL || list->root->used == 0 || list->root->list[0]->root == NULL)
  484. {
  485. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: NOT AN INDEXABLE LIST TABLE.", var);
  486. return ses;
  487. }
  488. if (*arg1 == 0)
  489. {
  490. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  491. {
  492. if (list->root->list[cnt]->root)
  493. {
  494. str_cpy(&list->root->list[cnt]->arg2, list->root->list[cnt]->arg1);
  495. }
  496. else
  497. {
  498. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: ABORTED DUE TO INVALID INDEX {%s}.", var, list->root->list[cnt]->arg1);
  499. break;
  500. }
  501. }
  502. return ses;
  503. }
  504. #if 1
  505. if (list->root->used)
  506. {
  507. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  508. {
  509. if (list->root->list[cnt]->root == NULL)
  510. {
  511. show_error(ses, LIST_COMMAND, "#ERROR: #LIST %s[%s] INDEXATE: FAILED TO FIND NEST {%s}.", var, list->root->list[cnt]->arg1, arg1);
  512. return ses;
  513. }
  514. index = search_index_list(list->root->list[cnt]->root, arg1, "");
  515. if (index == -1)
  516. {
  517. show_error(ses, LIST_COMMAND, "#ERROR: #LIST %s[%s] INDEXATE: FAILED TO FIND NEST {%s}.", var, list->root->list[cnt]->arg1, arg1);
  518. return ses;
  519. }
  520. str_cpy(&list->root->list[cnt]->arg2, list->root->list[cnt]->root->list[index]->arg2);
  521. }
  522. }
  523. #else
  524. if (list->root->used)
  525. {
  526. int index = search_index_list(list->root->list[0]->root, arg1, "");
  527. if (index == -1)
  528. {
  529. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: FAILED TO FIND NEST {%s}.", var, arg1);
  530. return ses;
  531. }
  532. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  533. {
  534. if (list->root->list[cnt]->root && list->root->list[cnt]->root->used > index)
  535. {
  536. str_cpy(&list->root->list[cnt]->arg2, list->root->list[cnt]->root->list[index]->arg2);
  537. }
  538. else
  539. {
  540. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: ABORTED DUE TO INVALID INDEX {%s}.", var, list->root->list[cnt]->arg1);
  541. break;
  542. }
  543. }
  544. }
  545. #endif
  546. return ses;
  547. }
  548. DO_ARRAY(array_insert)
  549. {
  550. int cnt, toi, index;
  551. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  552. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  553. if (list->root == NULL)
  554. {
  555. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  556. }
  557. toi = get_number(ses, arg1);
  558. if (toi == 0)
  559. {
  560. show_error(ses, LIST_VARIABLE, "#LIST INSERT: INVALID INDEX {%s}.", arg1);
  561. return ses;
  562. }
  563. index = get_list_index(ses, list->root, arg1);
  564. if (index == -1 || toi < 0)
  565. {
  566. index++;
  567. }
  568. for (cnt = index ; cnt < list->root->used ; cnt++)
  569. {
  570. str_cpy_printf(&list->root->list[cnt]->arg1, "%d", cnt + 2);
  571. }
  572. set_nest_node(list->root, ntos(index + 1), "%s", arg2);
  573. return ses;
  574. }
  575. DO_ARRAY(array_numerate)
  576. {
  577. int index;
  578. if (list->root == NULL)
  579. {
  580. show_error(ses, LIST_VARIABLE, "#LIST {%s} NUMERATE: VARIABLE IS NOT A TABLE.", var);
  581. return ses;
  582. }
  583. for (index = 0 ; index < list->root->used ; index++)
  584. {
  585. str_cpy_printf(&list->root->list[index]->arg1, "%d", index + 1);
  586. }
  587. return ses;
  588. }
  589. DO_ARRAY(array_order)
  590. {
  591. int cnt, val, len;
  592. char **arg2_buffer;
  593. array_add(ses, list, arg, var, arg1, arg2);
  594. if (list->root->used > 1)
  595. {
  596. /* if (*list->root->list[0]->arg2 == 0)
  597. {
  598. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} ORDER: LIST IS NOT INDEXED.", var);
  599. return ses;
  600. }
  601. */
  602. if (list->root->list[0]->root)
  603. {
  604. struct listroot **root_buffer;
  605. root_buffer = malloc(list->root->used * sizeof(struct listroot *));
  606. arg2_buffer = malloc(list->root->used * sizeof(char *));
  607. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  608. {
  609. len = str_len(list->root->list[cnt]->arg2);
  610. root_buffer[cnt] = list->root->list[cnt]->root;
  611. arg2_buffer[cnt] = list->root->list[cnt]->arg2;
  612. str_resize(&arg2_buffer[cnt], 10);
  613. sprintf(arg2_buffer[cnt] + len + 1, "%x", cnt);
  614. }
  615. quadsort(arg2_buffer, list->root->used, sizeof(char *), cmp_num);
  616. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  617. {
  618. val = hex_number_32bit(arg2_buffer[cnt] + str_len(arg2_buffer[cnt]) + 1);
  619. list->root->list[cnt]->root = root_buffer[val];
  620. list->root->list[cnt]->arg2 = arg2_buffer[cnt];
  621. }
  622. free(arg2_buffer);
  623. free(root_buffer);
  624. }
  625. else
  626. {
  627. arg2_buffer = malloc(list->root->used * sizeof(char *));
  628. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  629. {
  630. arg2_buffer[cnt] = list->root->list[cnt]->arg2;
  631. }
  632. quadsort(arg2_buffer, list->root->used, sizeof(char *), cmp_num);
  633. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  634. {
  635. list->root->list[cnt]->arg2 = arg2_buffer[cnt];
  636. }
  637. free(arg2_buffer);
  638. }
  639. }
  640. return ses;
  641. }
  642. DO_ARRAY(array_refine)
  643. {
  644. char arg3[BUFFER_SIZE];
  645. int index;
  646. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  647. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  648. if (*arg1 == 0 && *arg2 == 0)
  649. {
  650. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST <VARIABLE> REFINE <KEEP> [REMOVE]");
  651. return ses;
  652. }
  653. if (list->root && list->root->used)
  654. {
  655. int numerate = atoi(list->root->list[0]->arg1) == 1 && atoi(list->root->list[list->root->used - 1]->arg1) == list->root->used;
  656. int found = 0;
  657. if (*arg1)
  658. {
  659. for (index = 0 ; index < list->root->used ; index++)
  660. {
  661. RESTRING(gtd->cmds[0], list->root->list[index]->arg2);
  662. substitute(ses, arg1, arg3, SUB_CMD);
  663. if (!get_number(ses, arg3))
  664. {
  665. delete_index_list(list->root, index--);
  666. found = 1;
  667. }
  668. }
  669. }
  670. if (*arg2)
  671. {
  672. for (index = 0 ; index < list->root->used ; index++)
  673. {
  674. RESTRING(gtd->cmds[0], list->root->list[index]->arg2);
  675. substitute(ses, arg2, arg3, SUB_CMD);
  676. // printf("debug: (%s) (%d)\n", arg3, (int) get_number(ses, arg3));
  677. if (get_number(ses, arg3))
  678. {
  679. delete_index_list(list->root, index--);
  680. found = 1;
  681. }
  682. }
  683. }
  684. if (found && list->root->used == 0)
  685. {
  686. array_clear(ses, list, arg, var, arg1, arg2);
  687. }
  688. else if (found && numerate)
  689. {
  690. array_numerate(ses, list, arg, var, arg1, arg2);
  691. }
  692. }
  693. return ses;
  694. }
  695. DO_ARRAY(array_reverse)
  696. {
  697. struct listroot *toor;
  698. char *swap;
  699. int cnt, rev;
  700. array_add(ses, list, arg, var, arg1, arg2);
  701. for (cnt = 0 ; cnt < list->root->used / 2 ; cnt++)
  702. {
  703. rev = list->root->used - 1 - cnt;
  704. swap = list->root->list[cnt]->arg2;
  705. list->root->list[cnt]->arg2 = list->root->list[rev]->arg2;
  706. list->root->list[rev]->arg2 = swap;
  707. toor = list->root->list[cnt]->root;
  708. list->root->list[cnt]->root = list->root->list[rev]->root;
  709. list->root->list[rev]->root = toor;
  710. }
  711. return ses;
  712. }
  713. DO_ARRAY(array_simplify)
  714. {
  715. char *str;
  716. int index;
  717. array_add(ses, list, arg, var, arg1, arg2);
  718. str = str_alloc_stack(0);
  719. if (list->root)
  720. {
  721. if (list->root->used)
  722. {
  723. str_cpy(&str, list->root->list[0]->arg2);
  724. }
  725. for (index = 1 ; index < list->root->used ; index++)
  726. {
  727. str_cat_printf(&str, ";%s", list->root->list[index]->arg2);
  728. }
  729. set_nest_node_ses(ses, var, "%s", str);
  730. return ses;
  731. }
  732. else
  733. {
  734. show_error(ses, LIST_VARIABLE, "#LIST SIMPLIFY: VARIABLE {%s} IS NOT A LIST.", list->arg1);
  735. }
  736. return ses;
  737. }
  738. DO_ARRAY(array_size)
  739. {
  740. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  741. if (*arg1 == 0)
  742. {
  743. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST <VARIABLE> SIZE <VARIABLE>");
  744. return ses;
  745. }
  746. if (list->root)
  747. {
  748. set_nest_node_ses(ses, arg1, "%d", list->root->used);
  749. }
  750. else
  751. {
  752. set_nest_node_ses(ses, arg1, "0");
  753. }
  754. return ses;
  755. }
  756. DO_ARRAY(array_set)
  757. {
  758. int index;
  759. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  760. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  761. if (list->root)
  762. {
  763. index = get_list_index(ses, list->root, arg1);
  764. if (index == -1)
  765. {
  766. show_error(ses, LIST_VARIABLE, "#LIST {%s} SET: INVALID INDEX {%s}.", var, arg1);
  767. return ses;
  768. }
  769. set_nest_node(list->root, list->root->list[index]->arg1, "%s", arg2);
  770. // str_cpy(&list->root->list[index]->arg2, arg2);
  771. return ses;
  772. }
  773. show_error(ses, LIST_VARIABLE, "#LIST SET: VARIABLE {%s} IS NOT A LIST.", var);
  774. return ses;
  775. }
  776. DO_ARRAY(array_shuffle)
  777. {
  778. struct listroot *toor;
  779. char *swap;
  780. int cnt, rnd;
  781. array_add(ses, list, arg, var, arg1, arg2);
  782. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  783. {
  784. rnd = generate_rand(ses) % list->root->used;
  785. swap = list->root->list[cnt]->arg2;
  786. list->root->list[cnt]->arg2 = list->root->list[rnd]->arg2;
  787. list->root->list[rnd]->arg2 = swap;
  788. toor = list->root->list[cnt]->root;
  789. list->root->list[cnt]->root = list->root->list[rnd]->root;
  790. list->root->list[rnd]->root = toor;
  791. }
  792. return ses;
  793. }
  794. DO_ARRAY(array_sort)
  795. {
  796. int cnt, val, len;
  797. char **arg2_buffer;
  798. array_add(ses, list, arg, var, arg1, arg2);
  799. if (list->root->used > 1)
  800. {
  801. if (*list->root->list[0]->arg2 == 0)
  802. {
  803. show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} SORT: LIST IS NOT INDEXED.", var);
  804. return ses;
  805. }
  806. if (list->root->list[0]->root)
  807. {
  808. struct listroot **root_buffer;
  809. root_buffer = malloc(list->root->used * sizeof(struct listroot *));
  810. arg2_buffer = malloc(list->root->used * sizeof(char *));
  811. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  812. {
  813. len = str_len(list->root->list[cnt]->arg2);
  814. root_buffer[cnt] = list->root->list[cnt]->root;
  815. arg2_buffer[cnt] = list->root->list[cnt]->arg2;
  816. str_resize(&arg2_buffer[cnt], 10);
  817. sprintf(arg2_buffer[cnt] + len + 1, "%x", cnt);
  818. }
  819. quadsort(arg2_buffer, list->root->used, sizeof(char *), cmp_str);
  820. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  821. {
  822. val = hex_number_32bit(arg2_buffer[cnt] + str_len(arg2_buffer[cnt]) + 1);
  823. list->root->list[cnt]->root = root_buffer[val];
  824. list->root->list[cnt]->arg2 = arg2_buffer[cnt];
  825. }
  826. free(arg2_buffer);
  827. free(root_buffer);
  828. }
  829. else
  830. {
  831. arg2_buffer = malloc(list->root->used * sizeof(char *));
  832. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  833. {
  834. arg2_buffer[cnt] = list->root->list[cnt]->arg2;
  835. }
  836. quadsort(arg2_buffer, list->root->used, sizeof(char *), cmp_str);
  837. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  838. {
  839. list->root->list[cnt]->arg2 = arg2_buffer[cnt];
  840. }
  841. free(arg2_buffer);
  842. }
  843. }
  844. return ses;
  845. }
  846. DO_ARRAY(array_swap)
  847. {
  848. char *swap;
  849. int index1, index2;
  850. struct listroot *toor;
  851. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  852. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  853. if (list->root)
  854. {
  855. index1 = get_list_index(ses, list->root, arg1);
  856. index2 = get_list_index(ses, list->root, arg2);
  857. if (index1 == -1 || index2 == -1)
  858. {
  859. show_error(ses, LIST_VARIABLE, "#LIST {%s} SWAP: INVALID INDEX {%s} {%s}.", var, arg1, arg2);
  860. return ses;
  861. }
  862. swap = list->root->list[index1]->arg2; list->root->list[index1]->arg2 = list->root->list[index2]->arg2; list->root->list[index2]->arg2 = swap;
  863. toor = list->root->list[index1]->root; list->root->list[index1]->root = list->root->list[index2]->root; list->root->list[index2]->root = toor;
  864. return ses;
  865. }
  866. show_error(ses, LIST_VARIABLE, "#LIST SWAP: VARIABLE {%s} IS NOT A LIST.", var);
  867. return ses;
  868. }
  869. DO_ARRAY(array_tokenize)
  870. {
  871. char *buf;
  872. int index = 1, i;
  873. buf = str_alloc_stack(0);
  874. substitute(ses, arg, buf, SUB_VAR|SUB_FUN);
  875. arg = buf;
  876. if (list->root)
  877. {
  878. free_list(list->root);
  879. }
  880. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  881. while (*arg)
  882. {
  883. arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
  884. i = 0;
  885. while (arg1[i] != 0)
  886. {
  887. if (arg1[i] == '{')
  888. {
  889. strcpy(arg2, "\\x7B"); i++;
  890. }
  891. else if (arg1[i] == '}')
  892. {
  893. strcpy(arg2, "\\x7D"); i++;
  894. }
  895. else if (arg1[i] == '\\' && arg1[i+1] == 'x' && is_hex(arg1[i+2]) && is_hex(arg1[i+3]))
  896. {
  897. i += sprintf(arg2, "%.4s", &arg1[i]);
  898. }
  899. else if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, &arg1[i]))
  900. {
  901. i += sprintf(arg2, "%.*s", get_euc_size(ses, &arg1[i]), &arg1[i]);
  902. }
  903. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&arg1[i]))
  904. {
  905. i += sprintf(arg2, "%.*s", get_utf8_size(&arg1[i]), &arg1[i]);
  906. }
  907. else
  908. {
  909. i += sprintf(arg2, "%c", arg1[i]);
  910. }
  911. set_nest_node(list->root, ntos(index++), "%s", arg2);
  912. }
  913. if (*arg == COMMAND_SEPARATOR)
  914. {
  915. arg++;
  916. }
  917. }
  918. return ses;
  919. }