parse.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  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 Peter Unold 1992 *
  24. * recoded by Igor van den Hoven 2005 *
  25. ******************************************************************************/
  26. #include "tintin.h"
  27. // whether str1 is an abbreviation of str2
  28. int case_table[256] =
  29. {
  30. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  31. 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  32. 95, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  33. 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  34. 64,
  35. 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
  36. 91, 92, 93, 94,
  37. 95, 96,
  38. 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
  39. 123, 124, 125, 126, 127,
  40. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
  41. 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
  42. 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
  43. 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
  44. 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
  45. 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
  46. 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  47. 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
  48. };
  49. int is_abbrev(char *str1, char *str2)
  50. {
  51. if (*str1 == 0)
  52. {
  53. return false;
  54. }
  55. if (*str2 == 0)
  56. {
  57. tintin_printf2(gtd->ses, "\e[1;31mis_abbrev(%s,%s)", str1, str2);
  58. dump_stack();
  59. return false;
  60. }
  61. while (true)
  62. {
  63. if (*str1 == 0)
  64. {
  65. return true;
  66. }
  67. if (case_table[(int) *str1] != case_table[(int) *str2])
  68. {
  69. return false;
  70. }
  71. str1++;
  72. str2++;
  73. }
  74. }
  75. void filename_string(char *input, char *output)
  76. {
  77. while (*input)
  78. {
  79. *output++ = (char) case_table[(int) *input++];
  80. }
  81. *output = 0;
  82. }
  83. int is_suffix(char *str1, char *str2)
  84. {
  85. int len1, len2;
  86. len1 = strlen(str1);
  87. len2 = strlen(str2);
  88. if (len1 >= len2)
  89. {
  90. if (is_abbrev(str1 + len1 - len2, str2))
  91. {
  92. return TRUE;
  93. }
  94. }
  95. return FALSE;
  96. }
  97. struct session *parse_input(struct session *ses, char *input)
  98. {
  99. char *line;
  100. push_call("parse_input(%s,%s)",ses->name,input);
  101. if (*input == 0)
  102. {
  103. write_mud(ses, input, SUB_EOL);
  104. pop_call();
  105. return ses;
  106. }
  107. if (VERBATIM(ses))
  108. {
  109. line = (char *) malloc(BUFFER_SIZE);
  110. strcpy(line, input);
  111. if (check_all_aliases(ses, line))
  112. {
  113. ses = script_driver(ses, LIST_ALIAS, line);
  114. }
  115. else
  116. {
  117. write_mud(ses, line, SUB_EOL);
  118. }
  119. free(line);
  120. pop_call();
  121. return ses;
  122. }
  123. if (*input == gtd->verbatim_char)
  124. {
  125. write_mud(ses, input+1, SUB_EOL);
  126. pop_call();
  127. return ses;
  128. }
  129. line = (char *) malloc(BUFFER_SIZE);
  130. while (*input)
  131. {
  132. input = space_out(input);
  133. input = get_arg_all(ses, input, line, GET_ONE);
  134. if (parse_command(ses, line))
  135. {
  136. ses = script_driver(ses, LIST_COMMAND, line);
  137. }
  138. else if (check_all_aliases(ses, line))
  139. {
  140. ses = script_driver(ses, LIST_ALIAS, line);
  141. }
  142. else if (HAS_BIT(ses->flags, SES_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
  143. {
  144. process_speedwalk(ses, line);
  145. }
  146. else
  147. {
  148. write_mud(ses, line, SUB_VAR|SUB_FUN|SUB_ESC|SUB_EOL);
  149. }
  150. if (*input == COMMAND_SEPARATOR)
  151. {
  152. input++;
  153. }
  154. }
  155. free(line);
  156. pop_call();
  157. return ses;
  158. }
  159. /*
  160. Deal with variables and functions used as commands.
  161. */
  162. struct session *parse_command(struct session *ses, char *input)
  163. {
  164. char *arg, line[BUFFER_SIZE], cmd1[BUFFER_SIZE], cmd2[BUFFER_SIZE];
  165. push_call("parse_command(%p,%p)",ses,input);
  166. arg = get_arg_stop_spaces(ses, input, cmd1, GET_ONE);
  167. substitute(ses, cmd1, cmd2, SUB_VAR|SUB_FUN);
  168. if (!strcmp(cmd1, cmd2))
  169. {
  170. pop_call();
  171. return NULL;
  172. }
  173. sprintf(line, "%s%s%s", cmd2, *arg ? " " : "", arg);
  174. strcpy(input, line);
  175. pop_call();
  176. return ses;
  177. }
  178. int is_speedwalk(struct session *ses, char *input)
  179. {
  180. int flag = FALSE;
  181. while (*input)
  182. {
  183. switch (*input)
  184. {
  185. case 'n':
  186. case 'e':
  187. case 's':
  188. case 'w':
  189. case 'u':
  190. case 'd':
  191. flag = TRUE;
  192. break;
  193. case '0':
  194. case '1':
  195. case '2':
  196. case '3':
  197. case '4':
  198. case '5':
  199. case '6':
  200. case '7':
  201. case '8':
  202. case '9':
  203. flag = FALSE;
  204. break;
  205. default:
  206. return FALSE;
  207. }
  208. input++;
  209. }
  210. return flag;
  211. }
  212. void process_speedwalk(struct session *ses, char *input)
  213. {
  214. char dir[2];
  215. int cnt, i;
  216. for (dir[1] = 0 ; *input ; input++)
  217. {
  218. if (isdigit((int) *input))
  219. {
  220. sscanf(input, "%d%c", &cnt, dir);
  221. for (i = 0 ; i < cnt ; i++)
  222. {
  223. write_mud(ses, dir, SUB_EOL);
  224. }
  225. while (*input != dir[0])
  226. {
  227. input++;
  228. }
  229. }
  230. else
  231. {
  232. dir[0] = *input;
  233. write_mud(ses, dir, SUB_EOL);
  234. }
  235. }
  236. return;
  237. }
  238. /*
  239. Deals with all # stuff
  240. */
  241. struct session *parse_tintin_command(struct session *ses, char *input)
  242. {
  243. char line[BUFFER_SIZE];
  244. struct session *sesptr;
  245. input = get_arg_stop_spaces(ses, input, line, GET_ONE);
  246. substitute(ses, line, line, SUB_VAR|SUB_FUN);
  247. if (is_number(line))
  248. {
  249. int cnt = atoi(line);
  250. input = get_arg_in_braces(ses, input, line, GET_ALL);
  251. while (cnt-- > 0)
  252. {
  253. ses = script_driver(ses, LIST_COMMAND, line);
  254. }
  255. return ses;
  256. }
  257. sesptr = find_session(line);
  258. if (sesptr)
  259. {
  260. if (*input)
  261. {
  262. input = get_arg_in_braces(ses, input, line, GET_ALL);
  263. substitute(ses, line, line, SUB_VAR|SUB_FUN);
  264. script_driver(sesptr, LIST_COMMAND, line);
  265. return ses;
  266. }
  267. else
  268. {
  269. return activate_session(sesptr);
  270. }
  271. }
  272. tintin_printf2(ses, "#ERROR: #UNKNOWN TINTIN-COMMAND '%s'.", line);
  273. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 1, "UNKNOWN COMMAND", line);
  274. return ses;
  275. }
  276. /*
  277. get all arguments - only check for unescaped command separators
  278. */
  279. char *get_arg_all(struct session *ses, char *string, char *result, int verbatim)
  280. {
  281. char *pto, *pti;
  282. int nest = 0;
  283. pti = string;
  284. pto = result;
  285. if (*pti == gtd->verbatim_char)
  286. {
  287. while (*pti)
  288. {
  289. *pto++ = *pti++;
  290. }
  291. *pto = 0;
  292. return pti;
  293. }
  294. while (*pti)
  295. {
  296. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  297. {
  298. *pto++ = *pti++;
  299. *pto++ = *pti++;
  300. continue;
  301. }
  302. if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
  303. {
  304. *pto++ = *pti++;
  305. }
  306. else if (*pti == COMMAND_SEPARATOR && nest == 0 && !verbatim)
  307. {
  308. break;
  309. }
  310. else if (*pti == DEFAULT_OPEN)
  311. {
  312. nest++;
  313. }
  314. else if (*pti == DEFAULT_CLOSE)
  315. {
  316. nest--;
  317. }
  318. *pto++ = *pti++;
  319. if (pto - result >= BUFFER_SIZE - 3)
  320. {
  321. tintin_printf2(ses, "#ERROR: INPUT BUFFER OVERFLOW.");
  322. pto--;
  323. break;
  324. }
  325. }
  326. *pto = '\0';
  327. return pti;
  328. }
  329. /*
  330. Braces are stripped in braced arguments leaving all else as is.
  331. */
  332. char *get_arg_in_braces(struct session *ses, char *string, char *result, int flag)
  333. {
  334. char *pti, *pto;
  335. int nest = 1;
  336. pti = space_out(string);
  337. pto = result;
  338. if (*pti != DEFAULT_OPEN)
  339. {
  340. if (!HAS_BIT(flag, GET_ALL))
  341. {
  342. pti = get_arg_stop_spaces(ses, pti, result, flag);
  343. }
  344. else
  345. {
  346. pti = get_arg_with_spaces(ses, pti, result, flag);
  347. }
  348. return pti;
  349. }
  350. pti++;
  351. while (*pti)
  352. {
  353. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  354. {
  355. *pto++ = *pti++;
  356. *pto++ = *pti++;
  357. continue;
  358. }
  359. if (*pti == DEFAULT_OPEN)
  360. {
  361. nest++;
  362. }
  363. else if (*pti == DEFAULT_CLOSE)
  364. {
  365. nest--;
  366. if (nest == 0)
  367. {
  368. break;
  369. }
  370. }
  371. *pto++ = *pti++;
  372. }
  373. if (*pti == 0)
  374. {
  375. tintin_printf2(ses, "#ERROR: GET BRACED ARGUMENT: UNMATCHED BRACE.");
  376. }
  377. else
  378. {
  379. pti++;
  380. }
  381. *pto = '\0';
  382. return pti;
  383. }
  384. char *sub_arg_in_braces(struct session *ses, char *string, char *result, int flag, int sub)
  385. {
  386. char *buffer = str_alloc(UMAX(strlen(string), BUFFER_SIZE));
  387. string = get_arg_in_braces(ses, string, buffer, flag);
  388. substitute(ses, buffer, result, sub);
  389. str_free(buffer);
  390. return string;
  391. }
  392. /*
  393. get all arguments
  394. */
  395. char *get_arg_with_spaces(struct session *ses, char *string, char *result, int flag)
  396. {
  397. char *pto, *pti;
  398. int nest = 0;
  399. pti = space_out(string);
  400. pto = result;
  401. while (*pti)
  402. {
  403. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  404. {
  405. *pto++ = *pti++;
  406. *pto++ = *pti++;
  407. continue;
  408. }
  409. if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
  410. {
  411. *pto++ = *pti++;
  412. }
  413. else if (*pti == COMMAND_SEPARATOR && nest == 0)
  414. {
  415. break;
  416. }
  417. else if (*pti == DEFAULT_OPEN)
  418. {
  419. nest++;
  420. }
  421. else if (*pti == DEFAULT_CLOSE)
  422. {
  423. nest--;
  424. }
  425. *pto++ = *pti++;
  426. }
  427. *pto = '\0';
  428. return pti;
  429. }
  430. /*
  431. get one arg, stop at spaces
  432. */
  433. char *get_arg_stop_spaces(struct session *ses, char *string, char *result, int flag)
  434. {
  435. char *pto, *pti;
  436. int nest = 0;
  437. pti = space_out(string);
  438. pto = result;
  439. while (*pti)
  440. {
  441. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  442. {
  443. *pto++ = *pti++;
  444. *pto++ = *pti++;
  445. continue;
  446. }
  447. if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
  448. {
  449. *pto++ = *pti++;
  450. }
  451. else if (*pti == COMMAND_SEPARATOR && nest == 0)
  452. {
  453. break;
  454. }
  455. else if (isspace((int) *pti) && nest == 0)
  456. {
  457. pti++;
  458. break;
  459. }
  460. else if (*pti == DEFAULT_OPEN)
  461. {
  462. nest++;
  463. }
  464. else if (*pti == '[' && HAS_BIT(flag, GET_NST))
  465. {
  466. nest++;
  467. }
  468. else if (*pti == DEFAULT_CLOSE)
  469. {
  470. nest--;
  471. }
  472. else if (*pti == ']' && HAS_BIT(flag, GET_NST))
  473. {
  474. nest--;
  475. }
  476. *pto++ = *pti++;
  477. }
  478. *pto = '\0';
  479. return pti;
  480. }
  481. /*
  482. advance ptr to next none-space
  483. */
  484. char *space_out(char *string)
  485. {
  486. while (isspace((int) *string))
  487. {
  488. string++;
  489. }
  490. return string;
  491. }
  492. /*
  493. For variable handling
  494. */
  495. char *get_arg_to_brackets(struct session *ses, char *string, char *result)
  496. {
  497. char *pti, *pto, *ptii, *ptoo;
  498. int nest1 = 0, nest2 = 0, nest3 = 0;
  499. pti = space_out(string);
  500. pto = result;
  501. ptii = ptoo = NULL;
  502. while (*pti)
  503. {
  504. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  505. {
  506. *pto++ = *pti++;
  507. *pto++ = *pti++;
  508. continue;
  509. }
  510. if (*pti == '[')
  511. {
  512. nest2++;
  513. if (nest1 == 0 && ptii == NULL)
  514. {
  515. ptii = pti;
  516. ptoo = pto;
  517. }
  518. }
  519. else if (*pti == ']')
  520. {
  521. if (nest2)
  522. {
  523. nest2--;
  524. }
  525. else
  526. {
  527. nest3 = 1;
  528. }
  529. if (*(pti+1) == 0 && ptii && nest1 == 0 && nest2 == 0 && nest3 == 0)
  530. {
  531. *ptoo = 0;
  532. return ptii;
  533. }
  534. }
  535. else if (*pti == DEFAULT_OPEN)
  536. {
  537. nest1++;
  538. }
  539. else if (*pti == DEFAULT_CLOSE)
  540. {
  541. nest1--;
  542. }
  543. *pto++ = *pti++;
  544. }
  545. *pto = 0;
  546. return pti;
  547. }
  548. char *get_arg_at_brackets(struct session *ses, char *string, char *result)
  549. {
  550. char *pti, *pto;
  551. int nest = 0;
  552. pti = string;
  553. pto = result;
  554. if (*pti != '[')
  555. {
  556. *pto = 0;
  557. return pti;
  558. }
  559. while (*pti)
  560. {
  561. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  562. {
  563. *pto++ = *pti++;
  564. *pto++ = *pti++;
  565. continue;
  566. }
  567. if (*pti == '[')
  568. {
  569. nest++;
  570. }
  571. else if (*pti == ']')
  572. {
  573. if (nest)
  574. {
  575. nest--;
  576. }
  577. else
  578. {
  579. break;
  580. }
  581. }
  582. else if (nest == 0)
  583. {
  584. break;
  585. }
  586. *pto++ = *pti++;
  587. }
  588. if (nest)
  589. {
  590. tintin_printf2(NULL, "#ERROR: GET BRACKETED VARIABLE: UNMATCHED BRACKET.");
  591. }
  592. *pto = 0;
  593. return pti;
  594. }
  595. char *get_arg_in_brackets(struct session *ses, char *string, char *result)
  596. {
  597. char *pti, *pto;
  598. int nest = 1;
  599. pti = string;
  600. pto = result;
  601. if (*pti != '[')
  602. {
  603. *pto = 0;
  604. return pti;
  605. }
  606. pti++;
  607. while (*pti)
  608. {
  609. if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
  610. {
  611. *pto++ = *pti++;
  612. *pto++ = *pti++;
  613. continue;
  614. }
  615. if (*pti == '[')
  616. {
  617. nest++;
  618. }
  619. else if (*pti == ']')
  620. {
  621. nest--;
  622. if (nest == 0)
  623. {
  624. break;
  625. }
  626. }
  627. *pto++ = *pti++;
  628. }
  629. if (*pti == 0)
  630. {
  631. tintin_printf2(NULL, "#ERROR: GET BRACKETED ARGUMENT: UNMATCHED BRACKET.");
  632. }
  633. else
  634. {
  635. pti++;
  636. }
  637. *pto = 0;
  638. return pti;
  639. }
  640. /*
  641. send command to the mud
  642. */
  643. void write_mud(struct session *ses, char *command, int flags)
  644. {
  645. char output[BUFFER_SIZE];
  646. int size;
  647. size = substitute(ses, command, output, flags);
  648. if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
  649. {
  650. if (ses->map == NULL || ses->map->nofollow == 0)
  651. {
  652. check_append_path(ses, command, NULL, 1);
  653. }
  654. }
  655. if (ses->map && ses->map->in_room && ses->map->nofollow == 0)
  656. {
  657. if (follow_map(ses, command))
  658. {
  659. return;
  660. }
  661. }
  662. write_line_mud(ses, output, size);
  663. }
  664. /*
  665. Check line for triggers
  666. */
  667. void do_one_line(char *line, struct session *ses)
  668. {
  669. char strip[BUFFER_SIZE];
  670. push_call("[%s] do_one_line(%s)",ses->name,line);
  671. if (gtd->ignore_level)
  672. {
  673. pop_call();
  674. return;
  675. }
  676. strip_vt102_codes(line, strip);
  677. if (!HAS_BIT(ses->list[LIST_ACTION]->flags, LIST_FLAG_IGNORE))
  678. {
  679. check_all_actions(ses, line, strip);
  680. }
  681. if (!HAS_BIT(ses->list[LIST_PROMPT]->flags, LIST_FLAG_IGNORE))
  682. {
  683. check_all_prompts(ses, line, strip);
  684. }
  685. if (!HAS_BIT(ses->list[LIST_GAG]->flags, LIST_FLAG_IGNORE))
  686. {
  687. check_all_gags(ses, line, strip);
  688. }
  689. if (!HAS_BIT(ses->list[LIST_SUBSTITUTE]->flags, LIST_FLAG_IGNORE))
  690. {
  691. check_all_substitutions(ses, line, strip);
  692. }
  693. if (!HAS_BIT(ses->list[LIST_HIGHLIGHT]->flags, LIST_FLAG_IGNORE))
  694. {
  695. check_all_highlights(ses, line, strip);
  696. }
  697. if (HAS_BIT(ses->flags, SES_FLAG_LOGNEXT))
  698. {
  699. logit(ses, line, ses->lognext_file, TRUE);
  700. DEL_BIT(ses->flags, SES_FLAG_LOGNEXT);
  701. }
  702. pop_call();
  703. return;
  704. }