y_amx.inc 34 KB

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