1
0

y_scripting.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /*----------------------------------------------------------------------------*-
  2. ===============================
  3. y_scripting - Access amx data
  4. ===============================
  5. Description:
  6. Allows a script access to information about itself, such as function names.
  7. This can be used for a range of things, including automatic callback hooking
  8. and testing.
  9. Legal:
  10. Version: MPL 1.1
  11. The contents of this file are subject to the Mozilla Public License Version
  12. 1.1 (the "License"); you may not use this file except in compliance with
  13. the License. You may obtain a copy of the License at
  14. http://www.mozilla.org/MPL/
  15. Software distributed under the License is distributed on an "AS IS" basis,
  16. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  17. for the specific language governing rights and limitations under the
  18. License.
  19. The Original Code is the SA:MP script information include.
  20. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  21. Portions created by the Initial Developer are Copyright (C) 2008
  22. the Initial Developer. All Rights Reserved.
  23. Contributors:
  24. ZeeX, koolk
  25. Thanks:
  26. Peter, Cam - Support.
  27. ZeeX - Very productive conversations.
  28. koolk - IsPlayerinAreaEx code.
  29. TheAlpha - Danish translation.
  30. breadfish - German translation.
  31. Fireburn - Dutch translation.
  32. yom - French translation.
  33. 50p - Polish translation.
  34. Zamaroht - Spanish translation.
  35. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  36. for me to strive to better.
  37. Pixels^ - Running XScripters where the idea was born.
  38. Matite - Pestering me to release it and using it.
  39. Very special thanks to:
  40. Thiadmer - PAWN.
  41. Kye/Kalcor - SA:MP.
  42. SA:MP Team past, present and future - SA:MP.
  43. Version:
  44. 1.0
  45. Changelog:
  46. 06/08/10:
  47. First version
  48. -*----------------------------------------------------------------------------*/
  49. #include <YSI\internal\y_version>
  50. #include <YSI\internal\y_funcinc>
  51. #define Scripting_FastString(%1,%2,%3,%4) \
  52. (((%1) << 0) | ((%2) << 8) | ((%3) << 16) | ((%4) << 24))
  53. static stock Scripting_GetBase()
  54. {
  55. static
  56. s_addr;
  57. if (!s_addr)
  58. {
  59. // Get the data offset.
  60. #emit LCTRL 1
  61. #emit STOR.pri s_addr
  62. // Invert to get the prefix offset relative to the data.
  63. s_addr = -s_addr;
  64. }
  65. return s_addr;
  66. }
  67. static stock Scripting_GetPublics()
  68. {
  69. static
  70. s_addr;
  71. if (!s_addr)
  72. {
  73. new
  74. addr;// = Scripting_GetBase();
  75. // Get the data offset.
  76. #emit LCTRL 1
  77. #emit STOR.S.pri addr
  78. // Invert to get the prefix offset relative to the data.
  79. addr = -addr;
  80. // Get the pointer to the publics.
  81. addr += 32;
  82. #emit LREF.S.pri addr
  83. #emit STOR.pri s_addr
  84. // Adjust to get the relative offset.
  85. s_addr = s_addr + addr - 32;
  86. }
  87. return s_addr;
  88. }
  89. static stock Scripting_GetNatives()
  90. {
  91. static
  92. s_addr;
  93. if (!s_addr)
  94. {
  95. new
  96. addr;// = Scripting_GetBase();
  97. // Get the data offset.
  98. #emit LCTRL 1
  99. #emit STOR.S.pri addr
  100. // Invert to get the prefix offset relative to the data.
  101. addr = -addr;
  102. // Get the pointer to the publics.
  103. addr += 36;
  104. #emit LREF.S.pri addr
  105. #emit STOR.pri s_addr
  106. // Adjust to get the relative offset.
  107. s_addr = s_addr + addr - 36;
  108. }
  109. return s_addr;
  110. }
  111. static stock Scripting_GetLibraries()
  112. {
  113. static
  114. s_addr;
  115. if (!s_addr)
  116. {
  117. new
  118. addr;// = Scripting_GetBase();
  119. // Get the data offset.
  120. #emit LCTRL 1
  121. #emit STOR.S.pri addr
  122. // Invert to get the prefix offset relative to the data.
  123. addr = -addr;
  124. // Get the pointer to the publics.
  125. addr += 40;
  126. #emit LREF.S.pri addr
  127. #emit STOR.pri s_addr
  128. // Adjust to get the relative offset.
  129. s_addr = s_addr + addr - 40;
  130. }
  131. return s_addr;
  132. }
  133. static stock Scripting_GetString(addr)
  134. {
  135. new
  136. str[32],
  137. buffer,
  138. ch,
  139. idx;
  140. do
  141. {
  142. // Read 4 bytes.
  143. #emit LREF.S.pri addr
  144. #emit STOR.S.pri buffer
  145. // Write a character to the buffer.
  146. ch = buffer & 0xFF;
  147. str[idx++] = ch;
  148. // Check for the end of the string.
  149. if (!ch) break;
  150. // Write a character to the buffer.
  151. ch = buffer >> 8 & 0xFF;
  152. str[idx++] = ch;
  153. // Check for the end of the string.
  154. if (!ch) break;
  155. // Write a character to the buffer.
  156. ch = buffer >> 16 & 0xFF;
  157. str[idx++] = ch;
  158. // Check for the end of the string.
  159. if (!ch) break;
  160. // Write a character to the buffer.
  161. ch = buffer >>> 24;
  162. str[idx++] = ch;
  163. // Check for the end of the string.
  164. if (!ch) break;
  165. // Get the next address.
  166. addr += 4;
  167. }
  168. while (idx < 32);
  169. return str;
  170. }
  171. static stock Scripting_GetStringFast(addr, buffer)
  172. {
  173. new
  174. str[32],
  175. ch,
  176. idx;
  177. do
  178. {
  179. // Write a character to the buffer.
  180. ch = buffer & 0xFF;
  181. str[idx++] = ch;
  182. // Check for the end of the string.
  183. if (!ch) break;
  184. // Write a character to the buffer.
  185. ch = buffer >> 8 & 0xFF;
  186. str[idx++] = ch;
  187. // Check for the end of the string.
  188. if (!ch) break;
  189. // Write a character to the buffer.
  190. ch = buffer >> 16 & 0xFF;
  191. str[idx++] = ch;
  192. // Check for the end of the string.
  193. if (!ch) break;
  194. // Write a character to the buffer.
  195. ch = buffer >>> 24;
  196. str[idx++] = ch;
  197. // Check for the end of the string.
  198. if (!ch) break;
  199. // Get the next address.
  200. addr += 4;
  201. // Read 4 bytes.
  202. #emit LREF.S.pri addr
  203. #emit STOR.S.pri buffer
  204. }
  205. while (idx < 32);
  206. return str;
  207. }
  208. /*----------------------------------------------------------------------------*-
  209. Function:
  210. Scripting_GetPublicsCount
  211. Params:
  212. -
  213. Return:
  214. Number of public functions in a script.
  215. Notes:
  216. -
  217. native Scripting_GetPublicsCount();
  218. -*----------------------------------------------------------------------------*/
  219. stock Scripting_GetPublicsCount()
  220. {
  221. static
  222. s_count;
  223. if (!s_count)
  224. {
  225. // Get the difference in pointers.
  226. s_count = (Scripting_GetNatives() - Scripting_GetPublics()) / 8;
  227. }
  228. return s_count;
  229. }
  230. /*----------------------------------------------------------------------------*-
  231. Function:
  232. Scripting_GetNativesCount
  233. Params:
  234. -
  235. Return:
  236. Number of native functions in a script.
  237. Notes:
  238. -
  239. native Scripting_GetNativesCount();
  240. -*----------------------------------------------------------------------------*/
  241. stock Scripting_GetNativesCount()
  242. {
  243. static
  244. s_count;
  245. if (!s_count)
  246. {
  247. // Get the difference in pointers.
  248. s_count = (Scripting_GetLibraries() - Scripting_GetNatives()) / 8;
  249. }
  250. return s_count;
  251. }
  252. /*----------------------------------------------------------------------------*-
  253. Function:
  254. Scripting_GetPublicFast
  255. Params:
  256. idx - Index of the public to start at.
  257. buffer[32] - Buffer to store the name in.
  258. search - Pattern matching parameter.
  259. Return:
  260. Index of next public.
  261. Notes:
  262. Gets a string starting with a known 4 character sequence.
  263. native Scripting_GetPublicFast(idx, buffer[32], search);
  264. -*----------------------------------------------------------------------------*/
  265. stock Scripting_GetPublicFast(idx, buffer[32], search)
  266. {
  267. new
  268. count = Scripting_GetPublicsCount(),
  269. base = Scripting_GetBase(),
  270. pos = idx * 8 + 4 + Scripting_GetPublics(),
  271. addr;
  272. while (idx < count)
  273. {
  274. // Get the offset in the public records.
  275. // Get the pointer to the string.
  276. //pos += publics;
  277. // Get the address of the string.
  278. #emit LREF.S.pri pos
  279. #emit STOR.S.pri addr
  280. //printf("%s", Scripting_GetString(Scripting_GetBase() + pos));
  281. //new
  282. // str[32] = Scripting_GetString(base + pos));
  283. ++idx;
  284. addr += base;
  285. new
  286. chars;
  287. #emit LREF.S.pri addr
  288. #emit STOR.S.pri chars
  289. if (chars == search)
  290. {
  291. buffer = Scripting_GetStringFast(addr, chars);
  292. return idx;
  293. }
  294. pos += 8;
  295. }
  296. buffer[0] = '\0';
  297. return 0;
  298. }
  299. /*----------------------------------------------------------------------------*-
  300. Function:
  301. Scripting_GetPublicSuffix
  302. Params:
  303. idx - Index of the public to start at.
  304. buffer[32] - Buffer to store the name in.
  305. search - Pattern matching parameter.
  306. Return:
  307. Index of next public.
  308. Notes:
  309. Gets a string ending with a known 4 character sequence.
  310. native Scripting_GetPublicFast(idx, buffer[32], search);
  311. -*----------------------------------------------------------------------------*/
  312. stock Scripting_GetPublicSuffix(idx, buffer[32], search)
  313. {
  314. new
  315. count = Scripting_GetPublicsCount(),
  316. base = Scripting_GetBase(),
  317. // Add 12 to get the pointer to the next string.
  318. pos = idx * 8 + 12 + Scripting_GetPublics(),
  319. addr;
  320. // This code will actually spill in to the natives record, but that's fine.
  321. while (idx < count)
  322. {
  323. // Get the address of the string.
  324. #emit LREF.S.pri pos
  325. #emit STOR.S.pri addr
  326. ++idx;
  327. addr = addr + base - 5;
  328. //addr
  329. #emit LREF.S.pri addr
  330. #emit STOR.S.pri addr
  331. if (addr == search)
  332. {
  333. pos -= 8;
  334. #emit LREF.S.pri pos
  335. #emit STOR.S.pri addr
  336. addr += base;
  337. buffer = Scripting_GetString(addr);
  338. return idx;
  339. }
  340. pos += 8;
  341. }
  342. buffer[0] = '\0';
  343. return 0;
  344. }
  345. /*----------------------------------------------------------------------------*-
  346. Function:
  347. Scripting_GetNativeFast
  348. Params:
  349. idx - Index of the native to get.
  350. buffer[32] - Buffer to store the name in.
  351. search - Pattern matching parameter.
  352. Return:
  353. Index of next native.
  354. Notes:
  355. -
  356. native Scripting_GetNativeFast(idx, buffer[32], search);
  357. -*----------------------------------------------------------------------------*/
  358. stock Scripting_GetNativeFast(idx, buffer[32], search)
  359. {
  360. new
  361. count = Scripting_GetNativesCount(),
  362. base = Scripting_GetBase(),
  363. pos = idx * 8 + 4 + Scripting_GetNatives()
  364. addr;
  365. while (idx < count)
  366. {
  367. // Get the offset in the public records.
  368. new
  369. // Get the pointer to the string.
  370. //pos += publics;
  371. // Get the address of the string.
  372. #emit LREF.S.pri pos
  373. #emit STOR.S.pri addr
  374. //printf("%s", Scripting_GetString(Scripting_GetBase() + pos));
  375. //new
  376. // str[32] = Scripting_GetString(base + pos));
  377. ++idx;
  378. addr += base;
  379. new
  380. chars;
  381. #emit LREF.S.pri addr
  382. #emit STOR.S.pri chars
  383. if (chars == search)
  384. {
  385. buffer = Scripting_GetStringFast(addr, chars);
  386. return idx;
  387. }
  388. pos += 8;
  389. }
  390. buffer[0] = '\0';
  391. return 0;
  392. }
  393. /*----------------------------------------------------------------------------*-
  394. Function:
  395. Scripting_GetPublic
  396. Params:
  397. idx - Index of the public to get.
  398. buffer[32] - Buffer to store the name in.
  399. search[] - Optional pattern matching parameter.
  400. Return:
  401. Index of next public.
  402. Notes:
  403. -
  404. native Scripting_GetPublic(idx, buffer[32], search[] = "");
  405. -*----------------------------------------------------------------------------*/
  406. stock Scripting_GetPublic(idx, buffer[32], search[] = "")
  407. {
  408. new
  409. count = Scripting_GetPublicsCount(),
  410. base = Scripting_GetBase(),
  411. pos = idx * 8 + 4 + Scripting_GetPublics(),
  412. addr;
  413. while (idx < count)
  414. {
  415. // Get the offset in the public records.
  416. // Get the pointer to the string.
  417. //pos += publics;
  418. // Get the address of the string.
  419. #emit LREF.S.pri pos
  420. #emit STOR.S.pri addr
  421. //printf("%s", Scripting_GetString(Scripting_GetBase() + pos));
  422. //new
  423. // str[32] = Scripting_GetString(base + pos));
  424. ++idx;
  425. buffer = Scripting_GetString(base + addr);
  426. if (search[0] == '\0' || strfind(buffer, search) != -1)
  427. {
  428. return idx;
  429. }
  430. pos += 8;
  431. }
  432. buffer[0] = '\0';
  433. return 0;
  434. }
  435. /*----------------------------------------------------------------------------*-
  436. Function:
  437. Scripting_GetNative
  438. Params:
  439. idx - Index of the native to get.
  440. buffer[32] - Buffer to store the name in.
  441. search[] - Optional pattern matching parameter.
  442. Return:
  443. Index of next native.
  444. Notes:
  445. -
  446. native Scripting_GetNative(idx, buffer[32], search[] = "");
  447. -*----------------------------------------------------------------------------*/
  448. stock Scripting_GetNative(idx, buffer[32], search[] = "")
  449. {
  450. new
  451. count = Scripting_GetNativesCount(),
  452. base = Scripting_GetBase(),
  453. pos = idx * 8 + 4 + Scripting_GetNatives(),
  454. addr;
  455. while (idx < count)
  456. {
  457. // Get the offset in the public records.
  458. // Get the pointer to the string.
  459. //pos += publics;
  460. // Get the address of the string.
  461. #emit LREF.S.pri pos
  462. #emit STOR.S.pri addr
  463. //printf("%s", Scripting_GetString(Scripting_GetBase() + pos));
  464. //new
  465. // str[32] = Scripting_GetString(base + pos));
  466. ++idx;
  467. buffer = Scripting_GetString(base + addr);
  468. if (search[0] == '\0' || strfind(buffer, search) != -1)
  469. {
  470. return idx;
  471. }
  472. pos += 8;
  473. }
  474. buffer[0] = '\0';
  475. return 0;
  476. }
  477. static stock Scripting_CompareString(str[], addr)
  478. {
  479. new
  480. buffer,
  481. ch,
  482. idx;
  483. do
  484. {
  485. // Read 4 bytes.
  486. #emit LREF.S.pri addr
  487. #emit STOR.S.pri buffer
  488. ch = buffer & 0xFF;
  489. if (ch != str[idx++]) return false;
  490. if (!ch) break;
  491. ch = buffer >> 8 & 0xFF;
  492. if (ch != str[idx++]) return false;
  493. if (!ch) break;
  494. ch = buffer >> 16 & 0xFF;
  495. if (ch != str[idx++]) return false;
  496. if (!ch) break;
  497. ch = buffer >>> 24;
  498. if (ch != str[idx++]) return false;
  499. if (!ch) break;
  500. addr += 4;
  501. }
  502. while (idx < 32);
  503. return true;
  504. }
  505. /*----------------------------------------------------------------------------*-
  506. Function:
  507. Scripting_GetPublicPointer
  508. Params:
  509. name[] - Name of the function to get the pointer for.
  510. Return:
  511. Pointer or -1.
  512. Notes:
  513. -
  514. native Scripting_GetPublicPointer(name[]);
  515. -*----------------------------------------------------------------------------*/
  516. stock Scripting_GetPublicPointer(name[])
  517. {
  518. new
  519. count = Scripting_GetPublicsCount(),
  520. base = Scripting_GetBase(),
  521. pos = 4 + Scripting_GetPublics(),
  522. addr;
  523. while (count--)
  524. {
  525. // Get the offset in the public records.
  526. // Get the pointer to the string.
  527. //pos += publics;
  528. // Get the address of the string.
  529. #emit LREF.S.pri pos
  530. #emit STOR.S.pri addr
  531. //printf("%s", Scripting_GetString(Scripting_GetBase() + pos));
  532. //new
  533. // str[32] = Scripting_GetString(base + pos));
  534. if (Scripting_CompareString(name, base + addr))
  535. {
  536. //pos = idx * 8 + publics;
  537. pos -= 4;
  538. // Get the pointer to the string.
  539. //pos += publics;
  540. // Get the address of the string.
  541. #emit LREF.S.pri pos
  542. #emit STOR.S.pri addr
  543. // It doesn't really matter what this is relative to, as long as the
  544. // usage in code is consistent.
  545. return addr;
  546. }
  547. pos += 8;
  548. }
  549. return -1;
  550. }
  551. /*----------------------------------------------------------------------------*-
  552. Function:
  553. Scripting_RedirectPublic
  554. Params:
  555. name[] - Name of the function to move.
  556. pointer - Where to move it to.
  557. Return:
  558. -
  559. Notes:
  560. -
  561. native Scripting_RedirectPublic(name[], pointer);
  562. -*----------------------------------------------------------------------------*/
  563. stock Scripting_RedirectPublic(name[], pointer)
  564. {
  565. new
  566. count = Scripting_GetPublicsCount(),
  567. base = Scripting_GetBase(),
  568. pos = 4 + Scripting_GetPublics(),
  569. addr;
  570. while (count--)
  571. {
  572. // Get the offset in the public records.
  573. // Get the pointer to the string.
  574. //pos += publics;
  575. // Get the address of the string.
  576. #emit LREF.S.pri pos
  577. #emit STOR.S.pri addr
  578. //printf("%s", Scripting_GetString(Scripting_GetBase() + pos));
  579. //new
  580. // str[32] = Scripting_GetString(base + pos));
  581. if (Scripting_CompareString(name, base + addr))
  582. {
  583. //pos = idx * 8 + publics;
  584. pos -= 4;
  585. // Get the pointer to the string.
  586. //pos += publics;
  587. // Get the address of the string.
  588. #emit LOAD.S.pri pointer
  589. #emit SREF.S.pri pos
  590. // It doesn't really matter what this is relative to, as long as the
  591. // usage in code is consistent.
  592. return;
  593. }
  594. pos += 8;
  595. }
  596. }