Advertisement
Guest User

y_amx

a guest
Nov 27th, 2012
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.05 KB | None | 0 0
  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.  
  12. The contents of this file are subject to the Mozilla Public License Version
  13. 1.1 (the "License"); you may not use this file except in compliance with
  14. the License. You may obtain a copy of the License at
  15. http://www.mozilla.org/MPL/
  16.  
  17. Software distributed under the License is distributed on an "AS IS" basis,
  18. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  19. for the specific language governing rights and limitations under the
  20. License.
  21.  
  22. The Original Code is the YSI AMX include.
  23.  
  24. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  25. Portions created by the Initial Developer are Copyright (C) 2011
  26. the Initial Developer. All Rights Reserved.
  27.  
  28. Contributors:
  29. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  30.  
  31. Thanks:
  32. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  33. ZeeX - Very productive conversations.
  34. koolk - IsPlayerinAreaEx code.
  35. TheAlpha - Danish translation.
  36. breadfish - German translation.
  37. Fireburn - Dutch translation.
  38. yom - French translation.
  39. 50p - Polish translation.
  40. Zamaroht - Spanish translation.
  41. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  42. for me to strive to better.
  43. Pixels^ - Running XScripters where the idea was born.
  44. Matite - Pestering me to release it and using it.
  45.  
  46. Very special thanks to:
  47. Thiadmer - PAWN, whose limits continue to amaze me!
  48. Kye/Kalcor - SA:MP.
  49. SA:MP Team past, present and future - SA:MP.
  50.  
  51. Version:
  52. 1.0
  53. Changelog:
  54. 06/08/10:
  55. First version
  56. \*----------------------------------------------------------------------------*/
  57.  
  58. #include "internal\y_version"
  59.  
  60. #include "y_scriptinit"
  61. //#include "internal\y_funcinc"
  62. #include "y_debug"
  63. #include "internal\y_natives"
  64.  
  65. #define AMX_FastString(%1,%2,%3,%4) \
  66. (((%1) << 0) | ((%2) << 8) | ((%3) << 16) | ((%4) << 24))
  67.  
  68. #define AMX_MEMORY_TRACE_0 0xAABBCCDD
  69. #define AMX_MEMORY_TRACE_1 0xDDCCBBAA
  70. #define AMX_MEMORY_TRACE_2 0x12345678
  71. #define AMX_MEMORY_TRACE_3 0x87654321
  72.  
  73. stock
  74. AMX_HEADER_SIZE,
  75. AMX_HEADER_MAGIC,
  76. AMX_HEADER_FILE_VERSION,
  77. AMX_HEADER_AMX_VERSION,
  78. AMX_HEADER_FLAGS,
  79. AMX_HEADER_DEFSIZE,
  80. // These are not as they appear in the AMX - they are relative to the dat
  81. // pointer so that they can be directly manipulated.
  82. AMX_HEADER_COD,
  83. AMX_HEADER_DAT,
  84. AMX_HEADER_HEA,
  85. AMX_HEADER_STP,
  86. AMX_HEADER_CIP,
  87. AMX_HEADER_PUBLICS,
  88. AMX_HEADER_NATIVES,
  89. AMX_HEADER_LIBRARIES,
  90. AMX_HEADER_PUBVARS,
  91. AMX_HEADER_TAGS,
  92. AMX_HEADER_NAMETABLE,
  93. //E_AMX_HEADER_OVERLAYS,
  94. AMX_REAL_ADDRESS,
  95. AMX_BASE_ADDRESS,
  96. AMX_REAL_DATA;
  97.  
  98. enum E_AMX_TABLE
  99. {
  100. AMX_TABLE_PUBLICS,
  101. AMX_TABLE_NATIVES,
  102. AMX_TABLE_LIBRARIES,
  103. AMX_TABLE_PUBVARS,
  104. AMX_TABLE_TAGS
  105. }
  106.  
  107. // This is based on the AMX version used in SA:MP - it DOES NOT match the code
  108. // found in the PAWN documentation as that's for a later version.
  109. #define AMX_NOP 000
  110. #define AMX_LOAD_PRI 001
  111. #define AMX_LOAD_ALT 002
  112. #define AMX_PUSH_C 039
  113. #define AMX_CALL 049
  114. #define AMX_STACK 044
  115.  
  116. forward _@_y_amx_inc_@_();
  117. public _@_y_amx_inc_@_()
  118. {
  119. // This function call is VERY important - it exists but it never used, so
  120. // can be found in memory, and it also appears in code before the constant
  121. // offset is ever used in #emit code.
  122. AMX_TraceFunc(AMX_MEMORY_TRACE_0, AMX_MEMORY_TRACE_1, AMX_MEMORY_TRACE_2, AMX_MEMORY_TRACE_3);
  123. }
  124.  
  125. static stock AMX_TraceFunc(b0, b1, b2, b3)
  126. {
  127. // This function is only called to anchor the AMX in memory.
  128. #pragma unused b0, b1, b2, b3
  129. return 0;
  130. }
  131.  
  132. public OnScriptInit()
  133. {
  134. new
  135. addr,
  136. data,
  137. dat;
  138. #emit LCTRL 1
  139. #emit STOR.S.pri addr
  140. // Invert to get the prefix offset relative to the data.
  141. // Get all the script data.
  142. addr = -addr;
  143. // Now read in all the data.
  144. #emit LREF.S.pri addr
  145. #emit STOR.S.pri data
  146. AMX_HEADER_SIZE = data;
  147. addr += 4;
  148. #emit LREF.S.pri addr
  149. #emit STOR.S.pri data
  150. AMX_HEADER_MAGIC = data & 0xFFFF;
  151. AMX_HEADER_FILE_VERSION = data >>> 16 & 0xFF;
  152. AMX_HEADER_AMX_VERSION = data >>> 24;
  153. addr += 4;
  154. #emit LREF.S.pri addr
  155. #emit STOR.S.pri data
  156. AMX_HEADER_FLAGS = data & 0xFFFF;
  157. AMX_HEADER_DEFSIZE = data >>> 16;
  158. addr += 4;
  159. #emit LREF.S.pri addr
  160. #emit STOR.S.pri data
  161. AMX_HEADER_COD = data;
  162. addr += 4;
  163. #emit LREF.S.pri addr
  164. #emit STOR.S.pri data
  165. dat = data;
  166. AMX_HEADER_DAT = 0;
  167. AMX_BASE_ADDRESS = -dat;
  168. AMX_HEADER_COD -= dat;
  169. addr += 4;
  170. #emit LREF.S.pri addr
  171. #emit STOR.S.pri data
  172. AMX_HEADER_HEA = data - dat;
  173. addr += 4;
  174. #emit LREF.S.pri addr
  175. #emit STOR.S.pri data
  176. AMX_HEADER_STP = data - dat;
  177. addr += 4;
  178. #emit LREF.S.pri addr
  179. #emit STOR.S.pri data
  180. AMX_HEADER_CIP = data - dat;
  181. addr += 4;
  182. #emit LREF.S.pri addr
  183. #emit STOR.S.pri data
  184. AMX_HEADER_PUBLICS = data - dat;
  185. addr += 4;
  186. #emit LREF.S.pri addr
  187. #emit STOR.S.pri data
  188. AMX_HEADER_NATIVES = data - dat;
  189. addr += 4;
  190. #emit LREF.S.pri addr
  191. #emit STOR.S.pri data
  192. AMX_HEADER_LIBRARIES = data - dat;
  193. addr += 4;
  194. #emit LREF.S.pri addr
  195. #emit STOR.S.pri data
  196. AMX_HEADER_PUBVARS = data - dat;
  197. addr += 4;
  198. #emit LREF.S.pri addr
  199. #emit STOR.S.pri data
  200. AMX_HEADER_TAGS = data - dat;
  201. addr += 4;
  202. #emit LREF.S.pri addr
  203. #emit STOR.S.pri data
  204. AMX_HEADER_NAMETABLE = data - dat;
  205. // Now find the AMX's base address in global memory. This is VERY handy to
  206. // have for more advanced functionality (none of which actually exists yet).
  207. /*addr = 0;
  208. data = 0;
  209. new
  210. func;
  211. static
  212. sSearch[] =
  213. {
  214. AMX_PUSH_C, AMX_MEMORY_TRACE_3,
  215. AMX_PUSH_C, AMX_MEMORY_TRACE_2,
  216. AMX_PUSH_C, AMX_MEMORY_TRACE_1,
  217. AMX_PUSH_C, AMX_MEMORY_TRACE_0,
  218. AMX_PUSH_C, 0x10,
  219. AMX_CALL
  220. };
  221. #emit CONST.pri AMX_TraceFunc
  222. #emit STOR.S.pri func
  223. if (AMX_TraceCode(sSearch, addr, data))
  224. {
  225. AMX_REAL_ADDRESS = data - func - (AMX_HEADER_COD - AMX_BASE_ADDRESS);
  226. addr += 4;
  227. if (AMX_TraceCode(sSearch, addr, data))
  228. {
  229. P:E("Multiple y_amx tracers found!");
  230. }
  231. }
  232. else
  233. {
  234. P:E("y_amx tracer not found!");
  235. }*/
  236. AMX_REAL_ADDRESS = AMX_GetGlobal();
  237. AMX_REAL_DATA = AMX_REAL_ADDRESS - AMX_BASE_ADDRESS;
  238. // Call next ALS callback.
  239. #if defined YSI_LOCK_MODE
  240. GetServerVarAsString(YSI_gLockData, YSI_gLockData[5], sizeof (YSI_gLockData) - 5);
  241. #endif
  242. CallLocalFunction("AMX_OnScriptInit", "");
  243. }
  244.  
  245. stock AMX_GetGlobalAddress(...)
  246. {
  247. new
  248. addr;
  249. // addr = numargs();
  250. #emit LOAD.S.pri 8
  251. #emit STOR.S.pri addr
  252. if (addr >= 4)
  253. {
  254. // getargptr(0);
  255. #emit LOAD.S.pri 12
  256. #emit LOAD.alt AMX_REAL_DATA
  257. #emit ADD
  258. #emit STACK 4
  259. #emit RETN
  260. }
  261. return 0;
  262. }
  263.  
  264. stock AMX_GetRelativeAddress(...)
  265. {
  266. new
  267. addr;
  268. // addr = numargs();
  269. #emit LOAD.S.pri 8
  270. #emit STOR.S.pri addr
  271. if (addr >= 4)
  272. {
  273. // getargptr(0);
  274. #emit LOAD.S.pri 12
  275. #emit STACK 4
  276. #emit RETN
  277. }
  278. return 0;
  279. }
  280.  
  281. static AMX_GetGlobal()
  282. {
  283. new
  284. addr = -1;
  285. // Get the return address.
  286. #emit LOAD.S.pri 4
  287. #emit ADD.C 0xFFFFFFFC
  288. #emit LOAD.alt AMX_HEADER_COD
  289. #emit ADD
  290. #emit STOR.S.pri addr
  291. // Get the data 4 bytes before the return address.
  292. #emit LREF.S.alt addr
  293. #emit CONST.pri AMX_GetGlobal
  294. #emit SUB.alt
  295. #emit LOAD.alt AMX_HEADER_COD
  296. #emit SUB
  297. #emit LOAD.alt AMX_BASE_ADDRESS
  298. #emit ADD
  299. // Return
  300. #emit STACK 4
  301. #emit RETN
  302. // Find base address, not cod address (both operands relative to DAT.
  303. return 0;
  304. }
  305.  
  306. #undef OnScriptInit
  307. #define OnScriptInit AMX_OnScriptInit
  308. forward OnScriptInit();
  309.  
  310. stock AMX_TraceCode(pattern[], &addrRet, &dataRet, size = sizeof (pattern))
  311. {
  312. new
  313. addr = AMX_HEADER_COD + addrRet,
  314. data,
  315. i;
  316. while (addr < AMX_HEADER_DAT)
  317. {
  318. #emit LREF.S.pri addr
  319. #emit STOR.S.pri data
  320. if (data == pattern[i])
  321. {
  322. ++i;
  323. addr += 4;
  324. if (i == size)
  325. {
  326. addrRet = addr - i * 4 - AMX_HEADER_COD;
  327. #emit LREF.S.pri addr
  328. #emit STOR.S.pri data
  329. dataRet = data;
  330. return 1;
  331. }
  332. }
  333. else if (i)
  334. {
  335. addr -= i * 4 - 4;
  336. i = 0;
  337. }
  338. else
  339. {
  340. addr += 4;
  341. }
  342. }
  343. return 0;
  344. }
  345.  
  346. stock AMX_TraceMemory(pattern[], &addrRet, &dataRet, size = sizeof (pattern))
  347. {
  348. new
  349. addr = AMX_HEADER_DAT + addrRet,
  350. data,
  351. i;
  352. while (addr < AMX_HEADER_HEA)
  353. {
  354. #emit LREF.S.pri addr
  355. #emit STOR.S.pri data
  356. if (data == pattern[i])
  357. {
  358. ++i;
  359. addr += 4;
  360. if (i == size)
  361. {
  362. addrRet = addr - i * 4 - AMX_HEADER_DAT;
  363. #emit LREF.S.pri addr
  364. #emit STOR.S.pri data
  365. dataRet = data;
  366. return 1;
  367. }
  368. }
  369. else if (i)
  370. {
  371. addr -= i * 4 - 4;
  372. i = 0;
  373. }
  374. else
  375. {
  376. addr += 4;
  377. }
  378. }
  379. return 0;
  380. }
  381.  
  382. stock AMX_GetBaseCount(E_AMX_TABLE:table, &base, &count)
  383. {
  384. P:5("AMX_GetBaseCount called: %i, %i, %i", _:table, base, count);
  385. switch (table)
  386. {
  387. case AMX_TABLE_PUBLICS:
  388. {
  389. base = AMX_HEADER_PUBLICS;
  390. count = (AMX_HEADER_NATIVES - base) / 8;
  391. }
  392. case AMX_TABLE_NATIVES:
  393. {
  394. base = AMX_HEADER_NATIVES;
  395. count = (AMX_HEADER_LIBRARIES - base) / 8;
  396. }
  397. case AMX_TABLE_LIBRARIES:
  398. {
  399. base = AMX_HEADER_LIBRARIES;
  400. count = (AMX_HEADER_PUBVARS - base) / 8;
  401. }
  402. case AMX_TABLE_PUBVARS:
  403. {
  404. base = AMX_HEADER_PUBVARS;
  405. count = (AMX_HEADER_TAGS - base) / 8;
  406. }
  407. case AMX_TABLE_TAGS:
  408. {
  409. base = AMX_HEADER_TAGS;
  410. count = (AMX_HEADER_NAMETABLE - base) / 8;
  411. }
  412. default:
  413. {
  414. base = 0;
  415. count = 0;
  416. }
  417. }
  418. }
  419.  
  420. #define AMX_GetPublicEntry(%0) AMX_GetEntry(AMX_TABLE_PUBLICS,%0)
  421. #define AMX_GetNativeEntry(%0) AMX_GetEntry(AMX_TABLE_NATIVES,%0)
  422. #define AMX_GetLibraryEntry(%0) AMX_GetEntry(AMX_TABLE_LIBRARIES,%0)
  423. #define AMX_GetPubvarEntry(%0) AMX_GetEntry(AMX_TABLE_PUBVARS,%0)
  424. #define AMX_GetTagEntry(%0) AMX_GetEntry(AMX_TABLE_TAGS,%0)
  425.  
  426. stock AMX_GetEntry(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "")
  427. {
  428. P:5("AMX_GetEntry called: %i, %i, %i, \"%s\"", _:table, idx, buffer, pattern);
  429. new
  430. base,
  431. count;
  432. if (table == AMX_TABLE_PUBLICS && idx == 0)
  433. {
  434. // Special case where we can use native functions.
  435. idx = funcidx(pattern);
  436. if (idx == -1)
  437. {
  438. idx = 0;
  439. }
  440. else
  441. {
  442. buffer = idx * 8 + AMX_HEADER_PUBLICS;
  443. return idx + 1;
  444. }
  445. }
  446. AMX_GetBaseCount(table, base, count);
  447. if (idx < count)
  448. {
  449. if (pattern[0] == '\0')
  450. {
  451. buffer = idx * 8 + base;
  452. return idx + 1;
  453. }
  454. else
  455. {
  456. new
  457. addr,
  458. pos = idx * 8 + base + 4,
  459. str[32];
  460. do
  461. {
  462. #emit LREF.S.pri pos
  463. #emit STOR.S.pri addr
  464. AMX_ReadString(AMX_BASE_ADDRESS + addr, str);
  465. ++idx;
  466. if (strfind(str, pattern) != -1)
  467. {
  468. buffer = pos - 4;
  469. return idx;
  470. }
  471. pos += 8;
  472. }
  473. while (idx < count);
  474. }
  475. }
  476. return 0;
  477. }
  478.  
  479. #define AMX_GetPublicEntryPrefix(%0) AMX_GetEntryPrefix(AMX_TABLE_PUBLICS,%0)
  480. #define AMX_GetNativeEntryPrefix(%0) AMX_GetEntryPrefix(AMX_TABLE_NATIVES,%0)
  481. #define AMX_GetLibraryEntryPrefix(%0) AMX_GetEntryPrefix(AMX_TABLE_LIBRARIES,%0)
  482. #define AMX_GetPubvarEntryPrefix(%0) AMX_GetEntryPrefix(AMX_TABLE_PUBVARS,%0)
  483. #define AMX_GetTagEntryPrefix(%0) AMX_GetEntryPrefix(AMX_TABLE_TAGS,%0)
  484.  
  485. stock AMX_GetEntryPrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
  486. {
  487. P:5("AMX_GetEntryPrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  488. new
  489. base,
  490. count;
  491. AMX_GetBaseCount(table, base, count);
  492. if (idx < count)
  493. {
  494. new
  495. addr,
  496. pos = idx * 8 + base + 4;
  497. do
  498. {
  499. // Get the address of the string.
  500. #emit LREF.S.pri pos
  501. #emit STOR.S.pri addr
  502. // Get the 4 bytes 5 bytes before this position.
  503. addr += AMX_BASE_ADDRESS;
  504. #emit LREF.S.pri addr
  505. #emit STOR.S.pri addr
  506. ++idx;
  507. if (addr == pattern)
  508. {
  509. buffer = pos - 4;
  510. return idx;
  511. }
  512. pos += 8;
  513. }
  514. while (idx < count);
  515. }
  516. return 0;
  517. }
  518.  
  519. #define AMX_GetPublicEntrySuffix(%0) AMX_GetEntrySuffix(AMX_TABLE_PUBLICS,%0)
  520. #define AMX_GetNativeEntrySuffix(%0) AMX_GetEntrySuffix(AMX_TABLE_NATIVES,%0)
  521. #define AMX_GetLibraryEntrySuffix(%0) AMX_GetEntrySuffix(AMX_TABLE_LIBRARIES,%0)
  522. #define AMX_GetPubvarEntrySuffix(%0) AMX_GetEntrySuffix(AMX_TABLE_PUBVARS,%0)
  523. #define AMX_GetTagEntrySuffix(%0) AMX_GetEntrySuffix(AMX_TABLE_TAGS,%0)
  524.  
  525. stock AMX_GetEntrySuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
  526. {
  527. P:5("AMX_GetEntrySuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  528. new
  529. base,
  530. count;
  531. AMX_GetBaseCount(table, base, count);
  532. if (idx < --count)
  533. {
  534. new
  535. addr,
  536. pos = idx * 8 + base + 12;
  537. do
  538. {
  539. // Get the address of the string.
  540. #emit LREF.S.pri pos
  541. #emit STOR.S.pri addr
  542. // Get the 4 bytes 5 bytes before this position.
  543. addr += AMX_BASE_ADDRESS - 5;
  544. #emit LREF.S.pri addr
  545. #emit STOR.S.pri addr
  546. ++idx;
  547. if (addr == pattern)
  548. {
  549. buffer = pos - 12;
  550. return idx;
  551. }
  552. pos += 8;
  553. }
  554. while (idx < count);
  555. }
  556. if (idx == count)
  557. {
  558. // Do the final one, this is more of an issue!
  559. new
  560. addr,
  561. ch,
  562. pos = idx * 8 + base + 4;
  563. // Get the address of the string.
  564. #emit LREF.S.pri pos
  565. #emit STOR.S.pri addr
  566. addr += AMX_BASE_ADDRESS;
  567. for ( ; ; )
  568. {
  569. // Find the end of the string.
  570. #emit LREF.S.pri addr
  571. #emit STOR.S.pri ch
  572. if (ch & 0x000000FF)
  573. {
  574. if (ch & 0x0000FF00)
  575. {
  576. if (ch & 0x00FF0000)
  577. {
  578. if (ch & 0xFF000000)
  579. {
  580. addr += 4;
  581. continue;
  582. }
  583. else addr -= 1;
  584. }
  585. else addr -= 2;
  586. }
  587. else addr -= 3;
  588. }
  589. else addr -= 4;
  590. break;
  591. }
  592. #emit LREF.S.pri addr
  593. #emit STOR.S.pri ch
  594. ++idx;
  595. if (ch == pattern)
  596. {
  597. buffer = pos - 4;
  598. return idx;
  599. }
  600. }
  601. return 0;
  602. }
  603.  
  604. #define AMX_GetPublicName(%0) AMX_GetName(AMX_TABLE_PUBLICS,%0)
  605. #define AMX_GetNativeName(%0) AMX_GetName(AMX_TABLE_NATIVES,%0)
  606. #define AMX_GetLibraryName(%0) AMX_GetName(AMX_TABLE_LIBRARIES,%0)
  607. #define AMX_GetPubvarName(%0) AMX_GetName(AMX_TABLE_PUBVARS,%0)
  608. #define AMX_GetTagName(%0) AMX_GetName(AMX_TABLE_TAGS,%0)
  609.  
  610. stock AMX_GetName(E_AMX_TABLE:table, idx, buffer[32], const pattern[] = "")
  611. {
  612. P:5("AMX_GetName called: %i, %i, \"%s\", \"%s\"", _:table, idx, buffer, pattern);
  613. new
  614. base,
  615. count;
  616. AMX_GetBaseCount(table, base, count);
  617. if (idx < count)
  618. {
  619. if (pattern[0] == '\0')
  620. {
  621. new
  622. addr,
  623. pos = idx * 8 + base + 4;
  624. #emit LREF.S.pri pos
  625. #emit STOR.S.pri addr
  626. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  627. ++idx;
  628. //buffer = idx * 8 + base;
  629. return idx;
  630. }
  631. else
  632. {
  633. new
  634. addr,
  635. pos = idx * 8 + base + 4;
  636. do
  637. {
  638. #emit LREF.S.pri pos
  639. #emit STOR.S.pri addr
  640. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  641. ++idx;
  642. if (strfind(buffer, pattern) != -1)
  643. {
  644. //buffer = idx * 8 + base;
  645. return idx;
  646. }
  647. pos += 8;
  648. }
  649. while (idx < count);
  650. }
  651. }
  652. return 0;
  653. }
  654.  
  655. #define AMX_GetPublicNamePrefix(%0) AMX_GetNamePrefix(AMX_TABLE_PUBLICS,%0)
  656. #define AMX_GetNativeNamePrefix(%0) AMX_GetNamePrefix(AMX_TABLE_NATIVES,%0)
  657. #define AMX_GetLibraryNamePrefix(%0) AMX_GetNamePrefix(AMX_TABLE_LIBRARIES,%0)
  658. #define AMX_GetPubvarNamePrefix(%0) AMX_GetNamePrefix(AMX_TABLE_PUBVARS,%0)
  659. #define AMX_GetTagNamePrefix(%0) AMX_GetNamePrefix(AMX_TABLE_TAGS,%0)
  660.  
  661. stock AMX_GetNamePrefix(E_AMX_TABLE:table, idx, buffer[32], pattern)
  662. {
  663. P:5("AMX_GetNamePrefix called: %i, %i, \"%s\", %i", _:table, idx, buffer, pattern);
  664. new
  665. base,
  666. count;
  667. AMX_GetBaseCount(table, base, count);
  668. if (idx < count)
  669. {
  670. new
  671. addr,
  672. pos = idx * 8 + base + 4;
  673. do
  674. {
  675. // Get the address of the string.
  676. #emit LREF.S.pri pos
  677. #emit STOR.S.pri addr
  678. // Get the 4 bytes 5 bytes before this position.
  679. addr += AMX_BASE_ADDRESS;
  680. #emit LREF.S.pri addr
  681. #emit STOR.S.pri addr
  682. ++idx;
  683. if (addr == pattern)
  684. {
  685. #emit LREF.S.pri pos
  686. #emit STOR.S.pri addr
  687. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  688. return idx;
  689. }
  690. pos += 8;
  691. }
  692. while (idx < count);
  693. }
  694. return 0;
  695. }
  696.  
  697. #define AMX_GetPublicNameSuffix(%0) AMX_GetNameSuffix(AMX_TABLE_PUBLICS,%0)
  698. #define AMX_GetNativeNameSuffix(%0) AMX_GetNameSuffix(AMX_TABLE_NATIVES,%0)
  699. #define AMX_GetLibraryNameSuffix(%0) AMX_GetNameSuffix(AMX_TABLE_LIBRARIES,%0)
  700. #define AMX_GetPubvarNameSuffix(%0) AMX_GetNameSuffix(AMX_TABLE_PUBVARS,%0)
  701. #define AMX_GetTagNameSuffix(%0) AMX_GetNameSuffix(AMX_TABLE_TAGS,%0)
  702.  
  703. stock AMX_GetNameSuffix(E_AMX_TABLE:table, idx, buffer[32], pattern)
  704. {
  705. P:5("AMX_GetNameSuffix called: %i, %i, \"%s\", %i", _:table, idx, buffer, pattern);
  706. new
  707. base,
  708. count;
  709. AMX_GetBaseCount(table, base, count);
  710. if (idx < --count)
  711. {
  712. new
  713. addr,
  714. pos = idx * 8 + base + 12;
  715. do
  716. {
  717. // Get the address of the string.
  718. #emit LREF.S.pri pos
  719. #emit STOR.S.pri addr
  720. // Get the 4 bytes 5 bytes before this position.
  721. addr += AMX_BASE_ADDRESS - 5;
  722. #emit LREF.S.pri addr
  723. #emit STOR.S.pri addr
  724. ++idx;
  725. if (addr == pattern)
  726. {
  727. //buffer = pos - 12;
  728. pos -= 8;
  729. #emit LREF.S.pri pos
  730. #emit STOR.S.pri addr
  731. //addr += AMX_BASE_ADDRESS;
  732. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  733. return idx;
  734. }
  735. pos += 8;
  736. }
  737. while (idx < count);
  738. }
  739. if (idx == count)
  740. {
  741. // Do the final one, this is more of an issue!
  742. new
  743. addr,
  744. ch,
  745. pos = idx * 8 + base + 4;
  746. // Get the address of the string.
  747. #emit LREF.S.pri pos
  748. #emit STOR.S.pri addr
  749. addr += AMX_BASE_ADDRESS;
  750. for ( ; ; )
  751. {
  752. // Find the end of the string.
  753. #emit LREF.S.pri addr
  754. #emit STOR.S.pri ch
  755. if (ch & 0x000000FF)
  756. {
  757. if (ch & 0x0000FF00)
  758. {
  759. if (ch & 0x00FF0000)
  760. {
  761. if (ch & 0xFF000000)
  762. {
  763. addr += 4;
  764. continue;
  765. }
  766. else addr -= 1;
  767. }
  768. else addr -= 2;
  769. }
  770. else addr -= 3;
  771. }
  772. else addr -= 4;
  773. break;
  774. }
  775. #emit LREF.S.pri addr
  776. #emit STOR.S.pri ch
  777. ++idx;
  778. if (ch == pattern)
  779. {
  780. #emit LREF.S.pri pos
  781. #emit STOR.S.pri addr
  782. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  783. return idx;
  784. }
  785. }
  786. return 0;
  787. }
  788.  
  789. #define AMX_GetPublicPointer(%0) AMX_GetPointer(AMX_TABLE_PUBLICS,%0)
  790. #define AMX_GetNativePointer(%0) AMX_GetPointer(AMX_TABLE_NATIVES,%0)
  791. #define AMX_GetLibraryPointer(%0) AMX_GetPointer(AMX_TABLE_LIBRARIES,%0)
  792. #define AMX_GetPubvarPointer(%0) AMX_GetPointer(AMX_TABLE_PUBVARS,%0)
  793. #define AMX_GetTagPointer(%0) AMX_GetPointer(AMX_TABLE_TAGS,%0)
  794.  
  795. stock AMX_GetPointer(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "")
  796. {
  797. P:5("AMX_GetPointer called: %i, %i, %i, \"%s\"", _:table, idx, buffer, pattern);
  798. new
  799. pointer;
  800. idx = AMX_GetEntry(table, idx, pointer, pattern);
  801. if (idx)
  802. {
  803. #emit LREF.S.pri pointer
  804. #emit SREF.S.pri buffer
  805. }
  806. return idx;
  807. }
  808.  
  809. #define AMX_GetPublicPointerPrefix(%0) AMX_GetPointerPrefix(AMX_TABLE_PUBLICS,%0)
  810. #define AMX_GetNativePointerPrefix(%0) AMX_GetPointerPrefix(AMX_TABLE_NATIVES,%0)
  811. #define AMX_GetLibraryPointerPrefix(%0) AMX_GetPointerPrefix(AMX_TABLE_LIBRARIES,%0)
  812. #define AMX_GetPubvarPointerPrefix(%0) AMX_GetPointerPrefix(AMX_TABLE_PUBVARS,%0)
  813. #define AMX_GetTagPointerPrefix(%0) AMX_GetPointerPrefix(AMX_TABLE_TAGS,%0)
  814.  
  815. stock AMX_GetPointerPrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
  816. {
  817. P:5("AMX_GetPointerPrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  818. new
  819. pointer;
  820. idx = AMX_GetEntryPrefix(table, idx, pointer, pattern);
  821. if (idx)
  822. {
  823. #emit LREF.S.pri pointer
  824. #emit SREF.S.pri buffer
  825. }
  826. return idx;
  827. }
  828.  
  829. #define AMX_GetPublicPointerSuffix(%0) AMX_GetPointerSuffix(AMX_TABLE_PUBLICS,%0)
  830. #define AMX_GetNativePointerSuffix(%0) AMX_GetPointerSuffix(AMX_TABLE_NATIVES,%0)
  831. #define AMX_GetLibraryPointerSuffix(%0) AMX_GetPointerSuffix(AMX_TABLE_LIBRARIES,%0)
  832. #define AMX_GetPubvarPointerSuffix(%0) AMX_GetPointerSuffix(AMX_TABLE_PUBVARS,%0)
  833. #define AMX_GetTagPointerSuffix(%0) AMX_GetPointerSuffix(AMX_TABLE_TAGS,%0)
  834.  
  835. stock AMX_GetPointerSuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
  836. {
  837. P:5("AMX_GetPointerSuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  838. new
  839. pointer;
  840. idx = AMX_GetEntrySuffix(table, idx, pointer, pattern);
  841. if (idx)
  842. {
  843. #emit LREF.S.pri pointer
  844. #emit SREF.S.pri buffer
  845. }
  846. return idx;
  847. }
  848.  
  849. #define AMX_GetPublicValue(%0) AMX_GetValue(AMX_TABLE_PUBLICS,%0)
  850. #define AMX_GetNativeValue(%0) AMX_GetValue(AMX_TABLE_NATIVES,%0)
  851. #define AMX_GetLibraryValue(%0) AMX_GetValue(AMX_TABLE_LIBRARIES,%0)
  852. #define AMX_GetPubvarValue(%0) AMX_GetValue(AMX_TABLE_PUBVARS,%0)
  853. #define AMX_GetTagValue(%0) AMX_GetValue(AMX_TABLE_TAGS,%0)
  854.  
  855. stock AMX_GetValue(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "")
  856. {
  857. P:5("AMX_GetValue called: %i, %i, %i, \"%s\"", _:table, idx, buffer, pattern);
  858. new
  859. pointer;
  860. idx = AMX_GetPointer(table, idx, pointer, pattern);
  861. if (idx)
  862. {
  863. #emit LREF.S.pri pointer
  864. #emit SREF.S.pri buffer
  865. }
  866. return idx;
  867. }
  868.  
  869. #define AMX_GetPublicValuePrefix(%0) AMX_GetValuePrefix(AMX_TABLE_PUBLICS,%0)
  870. #define AMX_GetNativeValuePrefix(%0) AMX_GetValuePrefix(AMX_TABLE_NATIVES,%0)
  871. #define AMX_GetLibraryValuePrefix(%0) AMX_GetValuePrefix(AMX_TABLE_LIBRARIES,%0)
  872. #define AMX_GetPubvarValuePrefix(%0) AMX_GetValuePrefix(AMX_TABLE_PUBVARS,%0)
  873. #define AMX_GetTagValuePrefix(%0) AMX_GetValuePrefix(AMX_TABLE_TAGS,%0)
  874.  
  875. stock AMX_GetValuePrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
  876. {
  877. P:5("AMX_GetValuePrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  878. new
  879. pointer;
  880. idx = AMX_GetPointerPrefix(table, idx, pointer, pattern);
  881. if (idx)
  882. {
  883. #emit LREF.S.pri pointer
  884. #emit SREF.S.pri buffer
  885. }
  886. return idx;
  887. }
  888.  
  889. #define AMX_GetPublicValueSuffix(%0) AMX_GetValueSuffix(AMX_TABLE_PUBLICS,%0)
  890. #define AMX_GetNativeValueSuffix(%0) AMX_GetValueSuffix(AMX_TABLE_NATIVES,%0)
  891. #define AMX_GetLibraryValueSuffix(%0) AMX_GetValueSuffix(AMX_TABLE_LIBRARIES,%0)
  892. #define AMX_GetPubvarValueSuffix(%0) AMX_GetValueSuffix(AMX_TABLE_PUBVARS,%0)
  893. #define AMX_GetTagValueSuffix(%0) AMX_GetValueSuffix(AMX_TABLE_TAGS,%0)
  894.  
  895. stock AMX_GetValueSuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
  896. {
  897. P:5("AMX_GetValueSuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  898. new
  899. pointer;
  900. idx = AMX_GetPointerSuffix(table, idx, pointer, pattern);
  901. if (idx)
  902. {
  903. #emit LREF.S.pri pointer
  904. #emit SREF.S.pri buffer
  905. }
  906. return idx;
  907. }
  908.  
  909. stock AMX_ReadString(addr, str[], len = sizeof (str))
  910. {
  911. new
  912. buffer,
  913. idx;
  914. do
  915. {
  916. // Read 4 bytes.
  917. #emit LREF.S.pri addr
  918. #emit STOR.S.pri buffer
  919. // Write PACKED strings.
  920. buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000) | (buffer << 24);
  921. str[idx] = buffer;
  922. if (!(buffer & 0x000000FF && buffer & 0x0000FF00 && buffer & 0x00FF0000 && buffer & 0xFF000000))
  923. {
  924. return;
  925. }
  926. addr += 4;
  927. }
  928. while (++idx < len);
  929. }
  930.  
  931. stock AMX_WriteString(addr, const str[], len = sizeof (str))
  932. {
  933. new
  934. buffer,
  935. idx;
  936. do
  937. {
  938. // Write PACKED strings.
  939. buffer = str[idx];
  940. buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000) | (buffer << 24);
  941. // Write 4 bytes.
  942. #emit LOAD.S.pri buffer
  943. #emit SREF.S.pri addr
  944. if (!(buffer & 0x000000FF && buffer & 0x0000FF00 && buffer & 0x00FF0000 && buffer & 0xFF000000))
  945. {
  946. return;
  947. }
  948. addr += 4;
  949. }
  950. while (++idx < len);
  951. }
  952.  
  953. stock AMX_Read(addr)
  954. {
  955. P:5("AMX_Read called: %i", addr);
  956. /*new
  957. ret;
  958. #emit LREF.S.pri addr
  959. #emit STOR.S.pri ret
  960. return ret;*/
  961. #emit LREF.S.pri addr
  962. #emit RETN
  963. return 0;
  964. // It's a shame about the compiler here - this should be a 1 line function:
  965. //
  966. // #emit LREF.S.pri addr
  967. //
  968. // pri is the return value of a function so the data will already be in the
  969. // correct place, but the compiler will detect the lack of a return call.
  970. // Now fixed!
  971. }
  972.  
  973. stock AMX_Write(addr, value)
  974. {
  975. P:5("AMX_Write called: %i, %i", addr, value);
  976. #emit LOAD.S.pri value
  977. #emit SREF.S.pri addr
  978. }
  979.  
  980. stock AMX_ReadArray(addr, dest[], len = sizeof (dest))
  981. {
  982. // I tried to use memcpy, I couldn't get it to work, even when exactly
  983. // replicating compiler generated code...
  984. //while (len--)
  985. #emit LOAD.S.pri len
  986. #emit JZER AMX_ReadArray_done
  987. // if (len)
  988. AMX_ReadArray_loop:
  989. {
  990. // --len
  991. #emit DEC.pri
  992. // Load the address possibly outside "dat". Can't be done using only
  993. // "pri"/"alt" as it relies on "LREF.S" explicitly.
  994. #emit LREF.S.alt addr
  995. #emit SREF.S.alt dest
  996. #emit LOAD.S.alt addr
  997. #emit ADD.C 4
  998. #emit STOR.S.alt addr
  999. #emit LOAD.S.alt dest
  1000. #emit ADD.C 4
  1001. #emit STOR.S.alt dest
  1002. // while (len != 0)
  1003. #emit JNZ AMX_ReadArray_loop
  1004. }
  1005. AMX_ReadArray_done:
  1006. // ret;
  1007. /*while (len--)
  1008. {
  1009. #emit LREF.S.pri addr
  1010. #emit SREF.S.pri dest
  1011. #emit LOAD.S.pri addr
  1012. #emit ADD.C 4
  1013. #emit STOR.S.pri addr
  1014. #emit LOAD.S.pri dest
  1015. #emit ADD.C 4
  1016. #emit STOR.S.pri dest
  1017. }*/
  1018. // ret;
  1019. //#emit LREF.S.pri addr
  1020. //#emit STOR.S.pri ret
  1021. //return ret;
  1022. /*#emit push.adr len
  1023. #emit push.adr dest
  1024. #emit push.adr addr
  1025. #emit push.c 0x175c
  1026. #emit push.c 10
  1027. #emit sysreq.c printf
  1028. #emit stack 14
  1029. //printf("1 %d %d %d", addr, dest, len);
  1030. new src[32];
  1031.  
  1032. printf("1 %d %d %d", addr, dest, len);
  1033. #emit BREAK
  1034. #emit PUSH.S len
  1035. #emit LOAD.S.pri len
  1036. #emit SMUL.C 4
  1037. #emit PUSH.pri
  1038. #emit PUSH.C 0
  1039. #emit PUSH.adr src
  1040. #emit PUSH.S dest
  1041. #emit PUSH.C 20
  1042. #emit SYSREQ.C memcpy
  1043. #emit STACK 24*/
  1044. //#emit LOAD.S.pri addr
  1045. //#emit LOAD.S.alt dest
  1046. //#emit
  1047. // It's a shame about the compiler here - this should be a 1 line function:
  1048. //
  1049. // #emit LREF.S.pri addr
  1050. //
  1051. // pri is the return value of a function so the data will already be in the
  1052. // correct place, but the compiler will detect the lack of a return call.
  1053. return;
  1054. }
  1055.  
  1056. stock AMX_WriteArray(addr, const src[], len = sizeof (src))
  1057. {
  1058. #emit LOAD.S.pri len
  1059. #emit JZER AMX_WriteArray_done
  1060. // if (len)
  1061. AMX_WriteArray_loop:
  1062. {
  1063. // --len
  1064. #emit DEC.pri
  1065. // Read the data.
  1066. #emit LREF.S.alt dest
  1067. #emit SREF.S.alt addr
  1068. #emit LOAD.S.alt addr
  1069. #emit ADD.C 4
  1070. #emit STOR.S.alt addr
  1071. #emit LOAD.S.alt dest
  1072. #emit ADD.C 4
  1073. #emit STOR.S.alt dest
  1074. // while (len != 0)
  1075. #emit JNZ AMX_WriteArray_loop
  1076. }
  1077. AMX_WriteArray_done:
  1078. return;
  1079. }
  1080.  
  1081. /*#endinput
  1082.  
  1083. #define AMX_GetPublicsCount() ((AMX_HEADER_NATIVES-AMX_HEADER_PUBLICS)/8)
  1084.  
  1085. #define AMX_GetNativesCount() ((AMX_HEADER_NATIVES-AMX_HEADER_PUBLICS)/8)
  1086.  
  1087. #define AMX_GetPublicFast(%0) AMX_GetNamePrefix(AMX_PUBLICS,%0)
  1088.  
  1089. #define AMX_GetPublicSuffix(%0) AMX_GetNameSuffix(AMX_PUBLICS,%0)
  1090.  
  1091. #define AMX_GetPubvarSuffix(%0) AMX_GetNameSuffix(AMX_PUBVARS,%0)
  1092.  
  1093. #define AMX_GetNativeFast(%0) AMX_GetNamePrefix(AMX_NATIVES,%0)
  1094.  
  1095. #define AMX_GetPublic(%0) AMX_GetName(AMX_PUBLICS,%0)
  1096.  
  1097. #define AMX_GetNative(%0) AMX_GetName(AMX_NATIVES,%0)
  1098.  
  1099. stock AMX_GetPublicPointer(name[])
  1100. {
  1101. P:5("AMX_GetPublicPointer called: \"%s\"", name);
  1102. new
  1103. p;
  1104. AMX_GetPointer(AMX_PUBLICS, 0, p, name);
  1105. return p;
  1106. }
  1107.  
  1108. //#define AMX_GetPointerSuffix(idx, &func, search)
  1109.  
  1110. #define AMX_RedirectPublic(name[], pointer)
  1111.  
  1112. #define AMX_GetPublicVariable(name[])
  1113.  
  1114. #define AMX_SetPublicVariable(name[], value)*/
  1115.  
  1116. //#define _A<%0> (_:H_Xe:H_Ye:H_Ze(%0))
  1117. #define _A<%0> (_:H_Re(%0,0))
  1118.  
  1119. //#define H_Xe:H_Ye:H_Ze(@y%0) (31040|(_:H_Re(%0,0+8+8)))
  1120. //#define H_Ye:H_Ze(_y%0) (31071|(_:H_Re(%0,0+8+8)))
  1121. //#define H_Ze(%0) H_Re(%0,0)
  1122.  
  1123. // Do the next character test as this one failed.
  1124. #define H_Se(%0,%1,%3) H_Ne%1(%0,%3)
  1125. // End of string test failed.
  1126. #define H_Ee(%0,%3) @E_:H_Se(%0,_,%3)
  1127. // Do the single addition.
  1128. #define H_De(%0,%1,%3) (_:H_Re(%0,%3+8))|%1<<%3
  1129. // Recurse through the string.
  1130. #define H_Re(%0,%3) he:H_Ee(%0,%3)
  1131. // Test for the end of a string (4 characters only).
  1132. #define he:H_Ee(%0,0+8+8+8+8) 0
  1133. // Find the length of a string at compile time.
  1134. //#define LEN(%0,%3) _:(H_R(%0,%3),%3)
  1135.  
  1136. // Test for the current character.
  1137.  
  1138. #define @E_:H_Se(_%0,%1,%3) H_De(%0,95,%3)
  1139. #define @E@:H_Se(@%0,%1,%3) H_De(%0,64,%3)
  1140. #define @Ey:H_Se(y%0,%1,%3) H_De(%0,121,%3)
  1141.  
  1142. #define @Ea:H_Se(a%0,%1,%3) H_De(%0,97,%3)
  1143. #define @Eb:H_Se(b%0,%1,%3) H_De(%0,98,%3)
  1144. #define @Ec:H_Se(c%0,%1,%3) H_De(%0,99,%3)
  1145. #define @Ed:H_Se(d%0,%1,%3) H_De(%0,100,%3)
  1146. #define @Ee:H_Se(e%0,%1,%3) H_De(%0,101,%3)
  1147. #define @Ef:H_Se(f%0,%1,%3) H_De(%0,102,%3)
  1148. #define @Eg:H_Se(g%0,%1,%3) H_De(%0,103,%3)
  1149. #define @Eh:H_Se(h%0,%1,%3) H_De(%0,104,%3)
  1150. #define @Ei:H_Se(i%0,%1,%3) H_De(%0,105,%3)
  1151. #define @Ej:H_Se(j%0,%1,%3) H_De(%0,106,%3)
  1152. #define @Ek:H_Se(k%0,%1,%3) H_De(%0,107,%3)
  1153. #define @El:H_Se(l%0,%1,%3) H_De(%0,108,%3)
  1154. #define @Em:H_Se(m%0,%1,%3) H_De(%0,109,%3)
  1155. #define @En:H_Se(n%0,%1,%3) H_De(%0,110,%3)
  1156. #define @Eo:H_Se(o%0,%1,%3) H_De(%0,111,%3)
  1157. #define @Ep:H_Se(p%0,%1,%3) H_De(%0,112,%3)
  1158. #define @Eq:H_Se(q%0,%1,%3) H_De(%0,113,%3)
  1159. #define @Er:H_Se(r%0,%1,%3) H_De(%0,114,%3)
  1160. #define @Es:H_Se(s%0,%1,%3) H_De(%0,115,%3)
  1161. #define @Et:H_Se(t%0,%1,%3) H_De(%0,116,%3)
  1162. #define @Eu:H_Se(u%0,%1,%3) H_De(%0,117,%3)
  1163. #define @Ev:H_Se(v%0,%1,%3) H_De(%0,118,%3)
  1164. #define @Ew:H_Se(w%0,%1,%3) H_De(%0,119,%3)
  1165. #define @Ex:H_Se(x%0,%1,%3) H_De(%0,120,%3)
  1166. #define @Ez:H_Se(z%0,%1,%3) H_De(%0,122,%3)
  1167.  
  1168. #define @EA:H_Se(A%0,%1,%3) H_De(%0,65,%3)
  1169. #define @EB:H_Se(B%0,%1,%3) H_De(%0,66,%3)
  1170. #define @EC:H_Se(C%0,%1,%3) H_De(%0,67,%3)
  1171. #define @ED:H_Se(D%0,%1,%3) H_De(%0,68,%3)
  1172. #define @EE:H_Se(E%0,%1,%3) H_De(%0,69,%3)
  1173. #define @EF:H_Se(F%0,%1,%3) H_De(%0,70,%3)
  1174. #define @EG:H_Se(G%0,%1,%3) H_De(%0,71,%3)
  1175. #define @EH:H_Se(H%0,%1,%3) H_De(%0,72,%3)
  1176. #define @EI:H_Se(I%0,%1,%3) H_De(%0,73,%3)
  1177. #define @EJ:H_Se(J%0,%1,%3) H_De(%0,74,%3)
  1178. #define @EK:H_Se(K%0,%1,%3) H_De(%0,75,%3)
  1179. #define @EL:H_Se(L%0,%1,%3) H_De(%0,76,%3)
  1180. #define @EM:H_Se(M%0,%1,%3) H_De(%0,77,%3)
  1181. #define @EN:H_Se(N%0,%1,%3) H_De(%0,78,%3)
  1182. #define @EO:H_Se(O%0,%1,%3) H_De(%0,79,%3)
  1183. #define @EP:H_Se(P%0,%1,%3) H_De(%0,80,%3)
  1184. #define @EQ:H_Se(Q%0,%1,%3) H_De(%0,81,%3)
  1185. #define @ER:H_Se(R%0,%1,%3) H_De(%0,82,%3)
  1186. #define @ES:H_Se(S%0,%1,%3) H_De(%0,83,%3)
  1187. #define @ET:H_Se(T%0,%1,%3) H_De(%0,84,%3)
  1188. #define @EU:H_Se(U%0,%1,%3) H_De(%0,85,%3)
  1189. #define @EV:H_Se(V%0,%1,%3) H_De(%0,86,%3)
  1190. #define @EW:H_Se(W%0,%1,%3) H_De(%0,87,%3)
  1191. #define @EX:H_Se(X%0,%1,%3) H_De(%0,88,%3)
  1192. #define @EY:H_Se(Y%0,%1,%3) H_De(%0,89,%3)
  1193. #define @EZ:H_Se(Z%0,%1,%3) H_De(%0,90,%3)
  1194.  
  1195. #define @E0:H_Se(0%0,%1,%3) H_De(%0,48,%3)
  1196. #define @E1:H_Se(1%0,%1,%3) H_De(%0,49,%3)
  1197. #define @E2:H_Se(2%0,%1,%3) H_De(%0,50,%3)
  1198. #define @E3:H_Se(3%0,%1,%3) H_De(%0,51,%3)
  1199. #define @E4:H_Se(4%0,%1,%3) H_De(%0,52,%3)
  1200. #define @E5:H_Se(5%0,%1,%3) H_De(%0,53,%3)
  1201. #define @E6:H_Se(6%0,%1,%3) H_De(%0,54,%3)
  1202. #define @E7:H_Se(7%0,%1,%3) H_De(%0,55,%3)
  1203. #define @E8:H_Se(8%0,%1,%3) H_De(%0,56,%3)
  1204. #define @E9:H_Se(9%0,%1,%3) H_De(%0,57,%3)
  1205.  
  1206. // Find the next character to test.
  1207. #define H_Ne_(%0,%3) @E@:H_Se(%0,@,%3)
  1208. #define H_Ne@(%0,%3) @Ey:H_Se(%0,y,%3)
  1209. #define H_Ney(%0,%3) @Ea:H_Se(%0,a,%3)
  1210.  
  1211. #define H_Nea(%0,%3) @Eb:H_Se(%0,b,%3)
  1212. #define H_Neb(%0,%3) @Ec:H_Se(%0,c,%3)
  1213. #define H_Nec(%0,%3) @Ed:H_Se(%0,d,%3)
  1214. #define H_Ned(%0,%3) @Ee:H_Se(%0,e,%3)
  1215. #define H_Nee(%0,%3) @Ef:H_Se(%0,f,%3)
  1216. #define H_Nef(%0,%3) @Eg:H_Se(%0,g,%3)
  1217. #define H_Neg(%0,%3) @Eh:H_Se(%0,h,%3)
  1218. #define H_Neh(%0,%3) @Ei:H_Se(%0,i,%3)
  1219. #define H_Nei(%0,%3) @Ej:H_Se(%0,j,%3)
  1220. #define H_Nej(%0,%3) @Ek:H_Se(%0,k,%3)
  1221. #define H_Nek(%0,%3) @El:H_Se(%0,l,%3)
  1222. #define H_Nel(%0,%3) @Em:H_Se(%0,m,%3)
  1223. #define H_Nem(%0,%3) @En:H_Se(%0,n,%3)
  1224. #define H_Nen(%0,%3) @Eo:H_Se(%0,o,%3)
  1225. #define H_Neo(%0,%3) @Ep:H_Se(%0,p,%3)
  1226. #define H_Nep(%0,%3) @Eq:H_Se(%0,q,%3)
  1227. #define H_Neq(%0,%3) @Er:H_Se(%0,r,%3)
  1228. #define H_Ner(%0,%3) @Es:H_Se(%0,s,%3)
  1229. #define H_Nes(%0,%3) @Et:H_Se(%0,t,%3)
  1230. #define H_Net(%0,%3) @Eu:H_Se(%0,u,%3)
  1231. #define H_Neu(%0,%3) @Ev:H_Se(%0,v,%3)
  1232. #define H_Nev(%0,%3) @Ew:H_Se(%0,w,%3)
  1233. #define H_New(%0,%3) @Ex:H_Se(%0,x,%3)
  1234. #define H_Nex(%0,%3) @Ez:H_Se(%0,z,%3)
  1235. #define H_Nez(%0,%3) @EA:H_Se(%0,A,%3)
  1236.  
  1237. #define H_NeA(%0,%3) @EB:H_Se(%0,B,%3)
  1238. #define H_NeB(%0,%3) @EC:H_Se(%0,C,%3)
  1239. #define H_NeC(%0,%3) @ED:H_Se(%0,D,%3)
  1240. #define H_NeD(%0,%3) @EE:H_Se(%0,E,%3)
  1241. #define H_NeE(%0,%3) @EF:H_Se(%0,F,%3)
  1242. #define H_NeF(%0,%3) @EG:H_Se(%0,G,%3)
  1243. #define H_NeG(%0,%3) @EH:H_Se(%0,H,%3)
  1244. #define H_NeH(%0,%3) @EI:H_Se(%0,I,%3)
  1245. #define H_NeI(%0,%3) @EJ:H_Se(%0,J,%3)
  1246. #define H_NeJ(%0,%3) @EK:H_Se(%0,K,%3)
  1247. #define H_NeK(%0,%3) @EL:H_Se(%0,L,%3)
  1248. #define H_NeL(%0,%3) @EM:H_Se(%0,M,%3)
  1249. #define H_NeM(%0,%3) @EN:H_Se(%0,N,%3)
  1250. #define H_NeN(%0,%3) @EO:H_Se(%0,O,%3)
  1251. #define H_NeO(%0,%3) @EP:H_Se(%0,P,%3)
  1252. #define H_NeP(%0,%3) @EQ:H_Se(%0,Q,%3)
  1253. #define H_NeQ(%0,%3) @ER:H_Se(%0,R,%3)
  1254. #define H_NeR(%0,%3) @ES:H_Se(%0,S,%3)
  1255. #define H_NeS(%0,%3) @ET:H_Se(%0,T,%3)
  1256. #define H_NeT(%0,%3) @EU:H_Se(%0,U,%3)
  1257. #define H_NeU(%0,%3) @EV:H_Se(%0,V,%3)
  1258. #define H_NeV(%0,%3) @EW:H_Se(%0,W,%3)
  1259. #define H_NeW(%0,%3) @EX:H_Se(%0,X,%3)
  1260. #define H_NeX(%0,%3) @EY:H_Se(%0,Y,%3)
  1261. #define H_NeY(%0,%3) @EZ:H_Se(%0,Z,%3)
  1262. #define H_NeZ(%0,%3) @E0:H_Se(%0,0,%3)
  1263.  
  1264. #define H_Ne0(%0,%3) @E1:H_Se(%0,1,%3)
  1265. #define H_Ne1(%0,%3) @E2:H_Se(%0,2,%3)
  1266. #define H_Ne2(%0,%3) @E3:H_Se(%0,3,%3)
  1267. #define H_Ne3(%0,%3) @E4:H_Se(%0,4,%3)
  1268. #define H_Ne4(%0,%3) @E5:H_Se(%0,5,%3)
  1269. #define H_Ne5(%0,%3) @E6:H_Se(%0,6,%3)
  1270. #define H_Ne6(%0,%3) @E7:H_Se(%0,7,%3)
  1271. #define H_Ne7(%0,%3) @E8:H_Se(%0,8,%3)
  1272. #define H_Ne8(%0,%3) @E9:H_Se(%0,9,%3)
  1273. #define H_Ne9(%0,%3) ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement