1
0

y_amx.inc 34 KB

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