kustom.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // Kustom
  2. #include "SDK/amx/amx.h"
  3. #include "sscanf.h"
  4. #include "utils.h"
  5. #include "data.h"
  6. #include "specifiers.h"
  7. #include <stdio.h>
  8. extern logprintf_t
  9. logprintf;
  10. extern int
  11. gOptions;
  12. bool
  13. DoK(AMX * amx, char ** defaults, char ** input, cell * cptr, bool optional)
  14. {
  15. // First, get the type of the array.
  16. char *
  17. type = GetMultiType(defaults);
  18. if (!type)
  19. {
  20. return false;
  21. }
  22. if (optional)
  23. {
  24. // Optional parameters - just collect the data for
  25. // now and use it later.
  26. char *
  27. opts = 0;
  28. if (**defaults == '(')
  29. {
  30. ++(*defaults);
  31. SkipWhitespace(defaults);
  32. // Got the start of the values.
  33. opts = *defaults;
  34. // Skip the defaults for now, we don't know the length yet.
  35. bool
  36. escape = false;
  37. while (**defaults && (escape || **defaults != ')'))
  38. {
  39. if (**defaults == '\\')
  40. {
  41. escape = !escape;
  42. }
  43. else
  44. {
  45. escape = false;
  46. }
  47. ++(*defaults);
  48. }
  49. if (**defaults)
  50. {
  51. if (opts == *defaults)
  52. {
  53. // No defaults found.
  54. logprintf("sscanf warning: Empty default values.");
  55. opts = 0;
  56. }
  57. // Found a valid end. Make it null for
  58. // later array getting (easy to detect a
  59. // null end and we'll never need to
  60. // backtrack to here in the specifiers).
  61. **defaults = '\0';
  62. ++(*defaults);
  63. }
  64. else
  65. {
  66. logprintf("sscanf warning: Unclosed default value.");
  67. }
  68. /*if (optional)
  69. {
  70. // Optional parameters are always separated by commans, not
  71. // whatever the coder may choose.
  72. TempDelimiter(",)");
  73. // We need to copy the old save value for optional parts. If
  74. // we don't and save gets set to false in the middle of the
  75. // enum then when the code is called for a second time for the
  76. // real values then save will already be false and they won't
  77. // get saved.
  78. switch (DoEnumValues(type, &opts, cptr, true))
  79. {
  80. case SSCANF_TRUE_RETURN:
  81. break;
  82. case SSCANF_CONT_RETURN:
  83. logprintf("sscanf error: Insufficient default values.");
  84. // FALLTHROUGH
  85. default:
  86. RestoreDelimiter();
  87. return false;
  88. }
  89. RestoreDelimiter();
  90. }*/
  91. }
  92. else
  93. {
  94. logprintf("sscanf warning: No default value found.");
  95. }
  96. if (!input || IsStringEnd(**input))
  97. {
  98. if (cptr)
  99. {
  100. if (opts)
  101. {
  102. if (gOptions & 16)
  103. {
  104. char
  105. func[32];
  106. int
  107. idx;
  108. sprintf(func, "sscanf_%s", type);
  109. if (amx_FindPublic(amx, func, &idx))
  110. {
  111. logprintf("sscanf warning: Could not find function SSCANF:%s.", type);
  112. }
  113. else
  114. {
  115. cell
  116. ret,
  117. addr;
  118. amx_PushString(amx, &addr, 0, opts, 0, 0);
  119. amx_Exec(amx, &ret, idx);
  120. amx_Release(amx, addr);
  121. *cptr = ret;
  122. return true;
  123. }
  124. }
  125. else
  126. {
  127. *cptr = (cell)GetNumber(&opts);
  128. return true;
  129. }
  130. }
  131. *cptr = 0;
  132. }
  133. return true;
  134. }
  135. }
  136. else if (!input || IsStringEnd(**input))
  137. {
  138. return false;
  139. }
  140. char
  141. func[32];
  142. int
  143. idx;
  144. sprintf(func, "sscanf_%s", type);
  145. if (amx_FindPublic(amx, func, &idx))
  146. {
  147. logprintf("sscanf warning: Could not find function SSCANF:%s.", type);
  148. }
  149. else
  150. {
  151. char
  152. * string = *input,
  153. * outp = string,
  154. * start = string;
  155. if (IsDefaultDelimiter())
  156. {
  157. while (!IsWhitespace(*string))
  158. {
  159. if (*string == '\\')
  160. {
  161. if (IsEnd(*(string + 1)))
  162. {
  163. ++string;
  164. break;
  165. }
  166. if (*(string + 1) == '\\' || IsWhitespace(*(string + 1)))
  167. {
  168. ++string;
  169. }
  170. }
  171. if (outp != string)
  172. {
  173. *outp = *string;
  174. }
  175. ++outp;
  176. ++string;
  177. }
  178. }
  179. else
  180. {
  181. // Just a single word. Note that if your delimiter is a backslash
  182. // you can't escape it - this is not a bug, just don't try use it as
  183. // a delimiter and still expect to be able to use it in a string. I
  184. // suppose that technically you could see this as a bug, but I
  185. // choose to call it an undesirable feature (no-one has complained).
  186. while (!IsEnd(*string) && !IsDelimiter(*string))
  187. {
  188. if (*string == '\\')
  189. {
  190. if (IsEnd(*(string + 1)))
  191. {
  192. ++string;
  193. break;
  194. }
  195. // Escape spaces, backspace and delimiters - this code
  196. // is context independent so you can use a string with
  197. // or without a delimiter and can still escape spaces.
  198. if (*(string + 1) == '\\' || IsSpacer(*(string + 1)))
  199. {
  200. ++string;
  201. }
  202. }
  203. if (outp != string)
  204. {
  205. *outp = *string;
  206. }
  207. ++outp;
  208. ++string;
  209. }
  210. }
  211. if (!IsEnd(*string))
  212. {
  213. // Skip the final character.
  214. *input = string + 1;
  215. }
  216. else
  217. {
  218. // Save the return.
  219. *input = string;
  220. }
  221. // Add a null terminator.
  222. *outp = '\0';
  223. cell
  224. ret,
  225. addr;
  226. amx_PushString(amx, &addr, 0, start, 0, 0);
  227. amx_Exec(amx, &ret, idx);
  228. amx_Release(amx, addr);
  229. if (cptr) *cptr = ret;
  230. }
  231. return true;
  232. }