array.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /*
  2. * Version: MPL 1.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the sscanf 2.0 SA:MP plugin.
  15. *
  16. * The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  17. * Portions created by the Initial Developer are Copyright (C) 2010
  18. * the Initial Developer. All Rights Reserved.
  19. *
  20. * Contributor(s):
  21. *
  22. * Special Thanks to:
  23. *
  24. * SA:MP Team past, present and future
  25. */
  26. #include <stdio.h>
  27. #include "SDK/amx/amx.h"
  28. #include "utils.h"
  29. #include "specifiers.h"
  30. #include "data.h"
  31. #include "sscanf.h"
  32. extern logprintf_t
  33. logprintf;
  34. #define SAVE_VALUE(m) \
  35. if (cptr) \
  36. *cptr++ = m
  37. #define SAVE_VALUE_F(m) \
  38. if (cptr) { \
  39. float f = (float)m; \
  40. *cptr++ = amx_ftoc(f); }
  41. #define UPDATE_VALUES(m) \
  42. if (defaults) { \
  43. if (count) { \
  44. diff.c = m - last.c; \
  45. last.c = m; \
  46. } else { \
  47. last.c = m; \
  48. diff.c = 0; } } \
  49. SkipOneSpacer(&string); \
  50. ++count
  51. #define UPDATE_VALUES_F(m) \
  52. if (defaults) { \
  53. if (count) { \
  54. diff.d = m - last.d; \
  55. last.d = m; \
  56. } else { \
  57. last.d = m; \
  58. diff.d = 0; } } \
  59. SkipOneSpacer(&string); \
  60. ++count
  61. #define DO_LOOP(n) \
  62. count < length && *string && Do##n(&string, &b)
  63. // Macros for the regular values.
  64. #define DO(m,n) \
  65. {m b; \
  66. while (DO_LOOP(n)) { \
  67. SAVE_VALUE((cell)b); \
  68. UPDATE_VALUES((cell)b); } } \
  69. break;
  70. #define DOV(m,n) \
  71. {m b; \
  72. while (count < length && *string) { \
  73. Do##n(&string, &b); \
  74. SAVE_VALUE((cell)b); \
  75. UPDATE_VALUES((cell)b); } } \
  76. break;
  77. #define DOF(m,n) \
  78. {m b; \
  79. while (DO_LOOP(n)) { \
  80. SAVE_VALUE_F(b) \
  81. UPDATE_VALUES_F(b); } } \
  82. break;
  83. #define OPTIONAL_INVALID \
  84. logprintf("sscanf warning: Optional types invalid in array specifiers, consider using 'A'.")
  85. #define DX(m,n) \
  86. OPTIONAL_INVALID;
  87. #define DXF(m,n) \
  88. OPTIONAL_INVALID;
  89. void
  90. GetJaggedSlot(cell *, int, int, int, cell **, int *);
  91. bool
  92. DoK(AMX * amx, char ** defaults, char ** input, cell * cptr, bool optional);
  93. extern AMX *
  94. g_aCurAMX;
  95. extern int
  96. gOptions;
  97. union update_u
  98. {
  99. cell
  100. c;
  101. double
  102. d;
  103. };
  104. int
  105. DoArrayValues(char * type, char ** input, cell * cptr, int length, bool defaults, bool wholeString)
  106. {
  107. int
  108. count = 0;
  109. union update_u
  110. last,
  111. diff;
  112. last.d = 0;
  113. diff.d = 0;
  114. char *
  115. string = *input;
  116. switch (*type++)
  117. {
  118. // Copied directly from the main loop, just with different macros.
  119. case 'L':
  120. DX(bool, L)
  121. // FALLTHROUGH
  122. case 'l':
  123. {
  124. // The only custom code here. If the result is either "true"
  125. // or "false" it makes no sense to alternate in defaults as we
  126. // will just end up with larger values of true.
  127. bool
  128. b;
  129. while (count < length && *string)
  130. {
  131. DoL(&string, &b);
  132. SAVE_VALUE((cell)b);
  133. if (defaults)
  134. {
  135. last.c = (cell)b;
  136. }
  137. SkipOneSpacer(&string);
  138. ++count;
  139. }
  140. }
  141. break;
  142. case 'B':
  143. DX(int, B)
  144. // FALLTHROUGH
  145. case 'b':
  146. DO(int, B)
  147. case 'N':
  148. DX(int, N)
  149. // FALLTHROUGH
  150. case 'n':
  151. DO(int, N)
  152. case 'C':
  153. DX(char, C)
  154. // FALLTHROUGH
  155. case 'c':
  156. DO(char, C)
  157. case 'I':
  158. case 'D':
  159. DX(int, I)
  160. // FALLTHROUGH
  161. case 'i':
  162. case 'd':
  163. DO(int, I)
  164. case 'H':
  165. case 'X':
  166. DX(int, H)
  167. // FALLTHROUGH
  168. case 'h':
  169. case 'x':
  170. DO(int, H)
  171. case 'O':
  172. DX(int, O)
  173. // FALLTHROUGH
  174. case 'o':
  175. DO(int, O)
  176. case 'F':
  177. DXF(double, F)
  178. // FALLTHROUGH
  179. case 'f':
  180. DOF(double, F)
  181. case 'G':
  182. DXF(double, G)
  183. // FALLTHROUGH
  184. case 'g':
  185. {
  186. double
  187. b;
  188. while (DO_LOOP(G))
  189. {
  190. float
  191. f = (float)b;
  192. if (cptr)
  193. {
  194. *cptr++ = amx_ftoc(f);
  195. }
  196. if (defaults)
  197. {
  198. switch (amx_ftoc(f))
  199. {
  200. default:
  201. if (count)
  202. {
  203. diff.d = b - last.d;
  204. last.d = b;
  205. break;
  206. }
  207. // FALLTHROUGH
  208. case FLOAT_NEG_INFINITY:
  209. case FLOAT_INFINITY:
  210. case FLOAT_NAN:
  211. case FLOAT_NAN_E:
  212. last.d = b;
  213. diff.d = 0;
  214. break;
  215. }
  216. }
  217. SkipOneSpacer(&string);
  218. ++count;
  219. }
  220. }
  221. break;
  222. case 'U':
  223. DX(int, U)
  224. // FALLTHROUGH
  225. case 'u':
  226. if (*type == '[')
  227. {
  228. logprintf("sscanf warning: User arrays are not supported in arrays.");
  229. }
  230. if (defaults)
  231. {
  232. if (gOptions & 1)
  233. {
  234. int
  235. b;
  236. while (count < length && *string)
  237. {
  238. DoU(&string, &b, 0);
  239. SAVE_VALUE((cell)b);
  240. last.c = b;
  241. diff.c = 0;
  242. SkipOneSpacer(&string);
  243. ++count;
  244. }
  245. }
  246. else
  247. {
  248. int
  249. b;
  250. while (count < length && *string)
  251. {
  252. DoI(&string, &b);
  253. SAVE_VALUE((cell)b);
  254. last.c = b;
  255. diff.c = 0;
  256. SkipOneSpacer(&string);
  257. ++count;
  258. }
  259. }
  260. }
  261. else
  262. #define DoU(m,n) DoU(m,n,0)
  263. {
  264. DOV(int, U)
  265. }
  266. #undef DoU
  267. break;
  268. case 'Q':
  269. DX(int, Q)
  270. // FALLTHROUGH
  271. case 'q':
  272. if (*type == '[')
  273. {
  274. logprintf("sscanf warning: User arrays are not supported in arrays.");
  275. }
  276. if (defaults)
  277. {
  278. if (gOptions & 1)
  279. {
  280. int
  281. b;
  282. while (count < length && *string)
  283. {
  284. DoQ(&string, &b, 0);
  285. SAVE_VALUE((cell)b);
  286. last.c = b;
  287. diff.c = 0;
  288. SkipOneSpacer(&string);
  289. ++count;
  290. }
  291. }
  292. else
  293. {
  294. int
  295. b;
  296. while (count < length && *string)
  297. {
  298. DoI(&string, &b);
  299. SAVE_VALUE((cell)b);
  300. last.c = b;
  301. diff.c = 0;
  302. SkipOneSpacer(&string);
  303. ++count;
  304. }
  305. }
  306. }
  307. else
  308. #define DoQ(m,n) DoQ(m,n,0)
  309. {
  310. DOV(int, Q)
  311. }
  312. #undef DoQ
  313. break;
  314. case 'R':
  315. DX(int, R)
  316. // FALLTHROUGH
  317. case 'r':
  318. if (*type == '[')
  319. {
  320. logprintf("sscanf warning: User arrays are not supported in arrays.");
  321. }
  322. if (defaults)
  323. {
  324. if (gOptions & 1)
  325. {
  326. int
  327. b;
  328. while (count < length && *string)
  329. {
  330. DoR(&string, &b, 0);
  331. SAVE_VALUE((cell)b);
  332. last.c = b;
  333. diff.c = 0;
  334. SkipOneSpacer(&string);
  335. ++count;
  336. }
  337. }
  338. else
  339. {
  340. int
  341. b;
  342. while (count < length && *string)
  343. {
  344. DoI(&string, &b);
  345. SAVE_VALUE((cell)b);
  346. last.c = b;
  347. diff.c = 0;
  348. SkipOneSpacer(&string);
  349. ++count;
  350. }
  351. }
  352. }
  353. else
  354. #define DoR(m,n) DoR(m,n,0)
  355. {
  356. DOV(int, R)
  357. }
  358. #undef DoR
  359. break;
  360. case 'A':
  361. case 'a':
  362. logprintf("sscanf error: Multi-dimensional arrays are not supported.");
  363. return SSCANF_FAIL_RETURN;
  364. case '\'':
  365. logprintf("sscanf error: Search strings are not supported in arrays.");
  366. return SSCANF_FAIL_RETURN;
  367. case 'P':
  368. case 'p':
  369. logprintf("sscanf error: Delimiters are not supported in arrays.");
  370. return SSCANF_FAIL_RETURN;
  371. case '?':
  372. logprintf("sscanf error: Options are not supported in arrays.");
  373. return SSCANF_FAIL_RETURN;
  374. case 'K':
  375. DX(double, K)
  376. // FALLTHROUGH
  377. case 'k':
  378. //DOF(double, K)
  379. if (defaults)
  380. {
  381. if (DoK(g_aCurAMX, &type, &string, cptr, false) && cptr)
  382. {
  383. while (++count < length)
  384. {
  385. *(cptr + 1) = *cptr;
  386. ++cptr;
  387. }
  388. }
  389. }
  390. else
  391. {
  392. char *
  393. f = type;
  394. while (count < length && *string && DoK(g_aCurAMX, &f, &string, cptr, false))
  395. {
  396. if (cptr) ++cptr;
  397. SkipOneSpacer(&string);
  398. ++count;
  399. *(f - 1) = '>';
  400. f = type;
  401. }
  402. }
  403. break;
  404. case 's':
  405. //logprintf("sscanf error: Strings are not supported in arrays.");
  406. // Now they are (or rather, now I would like them to be, I've not
  407. // actually WRITTEN the code yet...).
  408. // This code has to read the memory pointed to by "cptr", which for
  409. // a multi-dimensional array points to the array header and from
  410. // which we can actually read the array lengths. Note that this
  411. // actually means that we don't need to include the string length in
  412. // the array specifier, and can thus support jagged arrays!
  413. if (defaults)
  414. {
  415. //char *
  416. // lt = type + 1;
  417. int
  418. nl = GetLength(&type, false),
  419. sl;
  420. char *
  421. dest;
  422. // Parse the default string.
  423. DoS(&string, &dest, 0x7FFFFFFF, true);
  424. if (cptr)
  425. {
  426. cell *
  427. sptr;
  428. // Send the string to PAWN.
  429. while (count < length)
  430. {
  431. // Get the true address as offset from the array
  432. // base address, and its length.
  433. GetJaggedSlot(cptr, length, nl, count, &sptr, &sl);
  434. amx_SetString(sptr, dest, 0, 0, sl);
  435. ++count;
  436. }
  437. }
  438. break;
  439. }
  440. else
  441. {
  442. // Get the length.
  443. //char *
  444. // lt = type;
  445. int
  446. nl = GetLength(&type, false),
  447. sl;
  448. char *
  449. dest;
  450. while (count < length && *string)
  451. {
  452. if (cptr)
  453. {
  454. cell *
  455. sptr;
  456. // Get the true address as offset from the array
  457. // base address, and its length.
  458. GetJaggedSlot(cptr, length, nl, count, &sptr, &sl);
  459. //printf("%d %d\n", nl, sl);
  460. //printf("%d %d %d", cptr, sptr, sl);
  461. DoS(&string, &dest, sl, wholeString && count == length - 1);
  462. amx_SetString(sptr, dest, 0, 0, sl);
  463. }
  464. else
  465. {
  466. DoS(&string, &dest, 0x7FFFFFFF, wholeString && count == length - 1);
  467. }
  468. SkipOneSpacer(&string);
  469. ++count;
  470. }
  471. break;
  472. }
  473. //return SSCANF_FAIL_RETURN;
  474. case '{':
  475. case '}':
  476. logprintf("sscanf error: Quiet sections are not supported in arrays.");
  477. return SSCANF_FAIL_RETURN;
  478. default:
  479. logprintf("sscanf error: Unknown format specifier '%c'.", *(type - 1));
  480. return SSCANF_FAIL_RETURN;
  481. }
  482. // Save the end of the string.
  483. *input = string;
  484. if (defaults)
  485. {
  486. if (count < length)
  487. {
  488. if (*string)
  489. {
  490. // Error in format specifier.
  491. logprintf("sscanf warning: Invalid values in array defaults.");
  492. }
  493. else
  494. {
  495. switch (*(type - 1))
  496. {
  497. case 'F':
  498. case 'f':
  499. case 'G':
  500. case 'g':
  501. // Float type.
  502. do
  503. {
  504. last.d += diff.d;
  505. SAVE_VALUE_F(last.d);
  506. ++count;
  507. }
  508. while (count < length);
  509. break;
  510. case 'K':
  511. case 'k':
  512. case 's':
  513. // There is no "progression" in optional strings - you
  514. // specify one and JUST one!
  515. break;
  516. default:
  517. do
  518. {
  519. // Other type.
  520. while (count < length)
  521. {
  522. last.c += diff.c;
  523. SAVE_VALUE(last.c);
  524. ++count;
  525. }
  526. }
  527. while (count < length);
  528. break;
  529. }
  530. }
  531. }
  532. else if (*string)
  533. {
  534. logprintf("sscanf warning: Excess array defaults found.");
  535. }
  536. }
  537. else
  538. {
  539. if (count < length)
  540. {
  541. if (*string)
  542. {
  543. // Invalid value entered.
  544. return SSCANF_FAIL_RETURN;
  545. }
  546. else
  547. {
  548. // Ran out of values - check if this is an optional array at a
  549. // higher level.
  550. return SSCANF_CONT_RETURN;
  551. }
  552. }
  553. }
  554. return SSCANF_TRUE_RETURN;
  555. }
  556. bool
  557. DoA(char ** defaults, char ** input, cell * cptr, bool optional)
  558. {
  559. // First, get the type of the array.
  560. bool
  561. escape = false;
  562. char
  563. * type = GetMultiType(defaults),
  564. * opts = 0;
  565. if (!type) return false;
  566. switch (*type)
  567. {
  568. case 'Z':
  569. // Don't even THINK about using "Z" - you will get THREE error
  570. // messages telling you off, "z" will give you 2, and "S" just 1.
  571. logprintf("sscanf warning: 'Z' doesn't exist - that would be an optional, deprecated optional string!.");
  572. // FALLTHROUGH
  573. case 'z':
  574. logprintf("sscanf warning: 'z' is deprecated, consider using 'S' instead.");
  575. // FALLTHROUGH
  576. case 'S':
  577. OPTIONAL_INVALID;
  578. *type = 's';
  579. break;
  580. }
  581. if (optional)
  582. {
  583. // Optional parameters - just collect the data for
  584. // now and use it later.
  585. if (**defaults == '(')
  586. {
  587. // Find the end of the options. Based on
  588. // SkipDefaultEx, but saving the start point.
  589. ++(*defaults);
  590. SkipWhitespace(defaults);
  591. // Got the start of the values.
  592. opts = *defaults;
  593. // Skip the defaults for now, we don't know the length yet.
  594. //while (**defaults) // && **defaults != ')')
  595. for ( ; ; )
  596. {
  597. switch (**defaults)
  598. {
  599. case '\0':
  600. goto DoA_after_loop;
  601. case '\\':
  602. escape = !escape;
  603. break;
  604. case ')':
  605. if (!escape)
  606. {
  607. // End the loop after ")" if it isn't escaped.
  608. goto DoA_after_loop;
  609. }
  610. // FALLTHROUGH.
  611. default:
  612. escape = false;
  613. break;
  614. }
  615. // Don't need to check for escaped ")"s here as you can't have
  616. // arrays of strings, which is the only place that would be.
  617. // Only now we do...
  618. ++(*defaults);
  619. }
  620. DoA_after_loop:
  621. if (**defaults)
  622. {
  623. if (opts == *defaults && *type != 's')
  624. {
  625. // No defaults found.
  626. logprintf("sscanf warning: Empty default values.");
  627. optional = false;
  628. }
  629. // Found a valid end. Make it null for
  630. // later array getting (easy to detect a
  631. // null end and we'll never need to
  632. // backtrack to here in the specifiers).
  633. **defaults = '\0';
  634. ++(*defaults);
  635. }
  636. else
  637. {
  638. logprintf("sscanf warning: Unclosed default value.");
  639. }
  640. }
  641. else
  642. {
  643. logprintf("sscanf warning: No default value found.");
  644. optional = false;
  645. }
  646. }
  647. // GetLength has "true" as arrays, being new, MUST have lengths.
  648. int
  649. length = GetLength(defaults, true);
  650. if (length)
  651. {
  652. // Got the length of the array, it's all good.
  653. if (optional)
  654. {
  655. // Optional parameters are always separated by commans, not
  656. // whatever the coder may choose.
  657. if (*type == 's') TempDelimiter(")");
  658. else TempDelimiter(",)");
  659. if (DoArrayValues(type, &opts, cptr, length, true, false) == SSCANF_FAIL_RETURN)
  660. {
  661. RestoreDelimiter();
  662. return false;
  663. }
  664. RestoreDelimiter();
  665. }
  666. if (input)
  667. {
  668. switch (DoArrayValues(type, input, cptr, length, false, *type == 's' && (IsEnd(**defaults) || (!cptr && **defaults == '}' && IsEnd(*(*defaults + 1))))))
  669. {
  670. case SSCANF_CONT_RETURN:
  671. if (optional)
  672. {
  673. return true;
  674. }
  675. else
  676. {
  677. return false;
  678. }
  679. case SSCANF_TRUE_RETURN:
  680. return true;
  681. default:
  682. return false;
  683. }
  684. }
  685. else
  686. {
  687. return true;
  688. }
  689. }
  690. // Default fail - only gets here if there is no length.
  691. return false;
  692. }