| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361 |
- /**--------------------------------------------------------------------------**\
- ===============================
- y_scripting - Access amx data
- ===============================
- Description:
- Allows a script access to information about itself, such as function names.
- This can be used for a range of things, including automatic callback hooking
- and testing.
- Legal:
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is the YSI AMX include.
-
- The Initial Developer of the Original Code is Alex "Y_Less" Cole.
- Portions created by the Initial Developer are Copyright (C) 2011
- the Initial Developer. All Rights Reserved.
-
- Contributors:
- ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
-
- Thanks:
- JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
- ZeeX - Very productive conversations.
- koolk - IsPlayerinAreaEx code.
- TheAlpha - Danish translation.
- breadfish - German translation.
- Fireburn - Dutch translation.
- yom - French translation.
- 50p - Polish translation.
- Zamaroht - Spanish translation.
- Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
- for me to strive to better.
- Pixels^ - Running XScripters where the idea was born.
- Matite - Pestering me to release it and using it.
-
- Very special thanks to:
- Thiadmer - PAWN, whose limits continue to amaze me!
- Kye/Kalcor - SA:MP.
- SA:MP Team past, present and future - SA:MP.
-
- Version:
- 1.0
- Changelog:
- 13/11/13:
- Simplified the main macros to work across multiple lines.
- 06/08/10:
- First version
- \**--------------------------------------------------------------------------**/
- #if defined _INC_y_amx
- #endinput
- #endif
- #define _INC_y_amx
- // I debated porting this over to use ZeeX's advanced AMX system, but there's no
- // point - this is stable and works well. Doing so would mean testing that all
- // the code that uses this file still operates corectly given how differently
- // the two systems do things. I fully admit that his is FAR more general but
- // there are legacy libraries to consider.
- #include "..\YSI_Internal\y_version"
- #include "..\YSI_Server\y_scriptinit"
- #include "..\YSI_Core\y_debug"
- #include "..\YSI_Internal\y_natives"
- #include "..\amx\asm"
- #include "..\amx\disasm"
- #include "..\amx\frame_info"
- #define AMX_FastString(%1,%2,%3,%4) \
- (((%1) << 0) | ((%2) << 8) | ((%3) << 16) | ((%4) << 24))
- #define AMX_MEMORY_TRACE_0 0xAABBCCDD
- #define AMX_MEMORY_TRACE_1 0xDDCCBBAA
- #define AMX_MEMORY_TRACE_2 0x12345678
- #define AMX_MEMORY_TRACE_3 0x87654321
- stock
- AMX_HEADER_SIZE,
- AMX_HEADER_MAGIC,
- AMX_HEADER_FILE_VERSION,
- AMX_HEADER_AMX_VERSION,
- AMX_HEADER_FLAGS,
- AMX_HEADER_DEFSIZE,
- // These are not as they appear in the AMX - they are relative to the dat
- // pointer so that they can be directly manipulated.
- AMX_HEADER_COD,
- AMX_HEADER_DAT,
- AMX_HEADER_HEA,
- AMX_HEADER_STP,
- AMX_HEADER_CIP,
- AMX_HEADER_PUBLICS,
- AMX_HEADER_NATIVES,
- AMX_HEADER_LIBRARIES,
- AMX_HEADER_PUBVARS,
- AMX_HEADER_TAGS,
- AMX_HEADER_NAMETABLE,
- //E_AMX_HEADER_OVERLAYS,
- AMX_REAL_ADDRESS,
- AMX_BASE_ADDRESS,
- AMX_REAL_DATA;
- enum E_AMX_TABLE
- {
- AMX_TABLE_PUBLICS,
- AMX_TABLE_NATIVES,
- AMX_TABLE_LIBRARIES,
- AMX_TABLE_PUBVARS,
- AMX_TABLE_TAGS
- }
- // This is based on the AMX version used in SA:MP - it DOES NOT match the code
- // found in the PAWN documentation as that's for a later version.
- public OnScriptInit()
- {
- new
- addr,
- data;
- #emit LCTRL 1
- #emit STOR.S.pri addr
- // Invert to get the prefix offset relative to the data.
- // Get all the script data.
- addr = -addr;
- // Now read in all the data.
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_SIZE = data;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_MAGIC = data & 0xFFFF;
- AMX_HEADER_FILE_VERSION = data >>> 16 & 0xFF;
- AMX_HEADER_AMX_VERSION = data >>> 24;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_FLAGS = data & 0xFFFF;
- AMX_HEADER_DEFSIZE = data >>> 16;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_COD = data;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- //dat = data;
- AMX_HEADER_DAT = 0;
- AMX_BASE_ADDRESS = -data;
- AMX_HEADER_COD += AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_HEA = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_STP = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_CIP = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_PUBLICS = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_NATIVES = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_LIBRARIES = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_PUBVARS = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_TAGS = data + AMX_BASE_ADDRESS;
- addr += 4;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- AMX_HEADER_NAMETABLE = data + AMX_BASE_ADDRESS;
- // Now find the AMX's base address in global memory. This is VERY handy to
- // have for more advanced functionality (none of which actually exists yet).
- AMX_REAL_ADDRESS = AMX_GetGlobal();
- AMX_REAL_DATA = AMX_REAL_ADDRESS - AMX_BASE_ADDRESS;
- // Call next ALS callback.
- #if defined YSI_LOCK_MODE
- GetServerVarAsString(YSI_gLockData, YSI_gLockData[5], sizeof (YSI_gLockData) - 5);
- #endif
- #if defined AMX_OnScriptInit
- AMX_OnScriptInit();
- #endif
- return 1;
- }
- #undef OnScriptInit
- #define OnScriptInit AMX_OnScriptInit
- #if defined AMX_OnScriptInit
- forward AMX_OnScriptInit();
- #endif
- stock AMX_GetGlobalAddress(...)
- {
- new
- addr;
- // addr = numargs();
- #emit LOAD.S.pri 8
- #emit STOR.S.pri addr
- if (addr >= 4)
- {
- // getargptr(0);
- #emit LOAD.S.pri 12
- #emit LOAD.alt AMX_REAL_DATA
- #emit ADD
- #emit STACK 4
- #emit RETN
- }
- return 0;
- }
- stock AMX_GetRelativeAddress(...)
- {
- new
- addr;
- // addr = numargs();
- #emit LOAD.S.pri 8
- #emit STOR.S.pri addr
- if (addr >= 4)
- {
- // getargptr(0);
- #emit LOAD.S.pri 12
- #emit STACK 4
- #emit RETN
- }
- return 0;
- }
- static AMX_GetGlobal()
- {
- new
- addr = -1;
- // Get the return address.
- #emit LOAD.S.pri 4
- #emit ADD.C 0xFFFFFFFC
- #emit LOAD.alt AMX_HEADER_COD
- #emit ADD
- #emit STOR.S.pri addr
- // Get the data 4 bytes before the return address.
- #emit LREF.S.alt addr
- #emit CONST.pri AMX_GetGlobal
- #emit SUB.alt
- #emit LOAD.alt AMX_HEADER_COD
- #emit SUB
- #emit LOAD.alt AMX_BASE_ADDRESS
- #emit ADD
- // Return
- #emit STACK 4
- #emit RETN
- // Find base address, not cod address (both operands relative to DAT.
- return 0;
- }
- stock AMX_TraceCode(pattern[], &addrRet, &dataRet, size = sizeof (pattern))
- {
- new
- addr = AMX_HEADER_COD + addrRet,
- data,
- i;
- while (addr < AMX_HEADER_DAT)
- {
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- if (data == pattern[i])
- {
- ++i;
- addr += 4;
- if (i == size)
- {
- addrRet = addr - i * 4 - AMX_HEADER_COD;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- dataRet = data;
- return 1;
- }
- }
- else if (i)
- {
- addr -= i * 4 - 4;
- i = 0;
- }
- else
- {
- addr += 4;
- }
- }
- return 0;
- }
- stock AMX_TraceMemory(pattern[], &addrRet, &dataRet, size = sizeof (pattern))
- {
- new
- addr = AMX_HEADER_DAT + addrRet,
- data,
- i;
- while (addr < AMX_HEADER_HEA)
- {
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- if (data == pattern[i])
- {
- ++i;
- addr += 4;
- if (i == size)
- {
- addrRet = addr - i * 4 - AMX_HEADER_DAT;
- #emit LREF.S.pri addr
- #emit STOR.S.pri data
- dataRet = data;
- return 1;
- }
- }
- else if (i)
- {
- addr -= i * 4 - 4;
- i = 0;
- }
- else
- {
- addr += 4;
- }
- }
- return 0;
- }
- stock AMX_GetBaseCount(E_AMX_TABLE:table, &base, &count)
- {
- P:7("AMX_GetBaseCount called: %i, %i, %i", _:table, base, count);
- switch (table)
- {
- case AMX_TABLE_PUBLICS:
- {
- base = AMX_HEADER_PUBLICS;
- count = (AMX_HEADER_NATIVES - AMX_HEADER_PUBLICS) / 8;
- }
- case AMX_TABLE_NATIVES:
- {
- base = AMX_HEADER_NATIVES;
- count = (AMX_HEADER_LIBRARIES - AMX_HEADER_NATIVES) / 8;
- }
- case AMX_TABLE_LIBRARIES:
- {
- base = AMX_HEADER_LIBRARIES;
- count = (AMX_HEADER_PUBVARS - AMX_HEADER_LIBRARIES) / 8;
- }
- case AMX_TABLE_PUBVARS:
- {
- base = AMX_HEADER_PUBVARS;
- count = (AMX_HEADER_TAGS - AMX_HEADER_PUBVARS) / 8;
- }
- case AMX_TABLE_TAGS:
- {
- base = AMX_HEADER_TAGS;
- count = (AMX_HEADER_NAMETABLE - AMX_HEADER_TAGS) / 8;
- }
- default:
- {
- base = 0;
- count = 0;
- }
- }
- }
- #define AMX_GetPublicEntry( AMX_GetEntry(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeEntry( AMX_GetEntry(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryEntry( AMX_GetEntry(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarEntry( AMX_GetEntry(AMX_TABLE_PUBVARS,
- #define AMX_GetTagEntry( AMX_GetEntry(AMX_TABLE_TAGS,
- stock AMX_GetEntry(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "", const bool:exact = false)
- {
- P:7("AMX_GetEntry called: %i, %i, %i, \"%s\", %i", _:table, idx, buffer, pattern, exact);
- new
- base,
- count;
- AMX_GetBaseCount(table, base, count);
- if (idx < count)
- {
- if (pattern[0] == '\0')
- {
- buffer = idx * 8 + base;
- return idx + 1;
- }
- else
- {
- new
- addr,
- pos = idx * 8 + base + 4,
- str[32];
- do
- {
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- AMX_ReadString(AMX_BASE_ADDRESS + addr, str);
- ++idx;
- if (exact ? (str{0} && !strcmp(str, pattern)) : (strfind(str, pattern) != -1))
- {
- buffer = pos - 4;
- return idx;
- }
- pos += 8;
- }
- while (idx < count);
- }
- }
- return 0;
- }
- #define AMX_GetPublicEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_TAGS,
- stock AMX_GetEntryPrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
- {
- P:7("AMX_GetEntryPrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
- new
- base,
- count;
- AMX_GetBaseCount(table, base, count);
- if (idx < count)
- {
- new
- addr,
- pos = idx * 8 + base + 4;
- do
- {
- // Get the address of the string.
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- // Get the 4 bytes 5 bytes before this position.
- addr += AMX_BASE_ADDRESS;
- #emit LREF.S.pri addr
- #emit STOR.S.pri addr
- ++idx;
- if (addr == pattern)
- {
- buffer = pos - 4;
- return idx;
- }
- pos += 8;
- }
- while (idx < count);
- }
- return 0;
- }
- #define AMX_GetPublicEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_TAGS,
- stock AMX_GetEntrySuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
- {
- P:7("AMX_GetEntrySuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
- new
- base,
- count;
- AMX_GetBaseCount(table, base, count);
- if (idx < --count)
- {
- new
- addr,
- pos = idx * 8 + base + 12;
- do
- {
- // Get the address of the string.
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- // Get the 4 bytes 5 bytes before this position.
- addr += AMX_BASE_ADDRESS - 5;
- #emit LREF.S.pri addr
- #emit STOR.S.pri addr
- ++idx;
- if (addr == pattern)
- {
- buffer = pos - 12;
- return idx;
- }
- pos += 8;
- }
- while (idx < count);
- }
- if (idx == count)
- {
- // Do the final one, this is more of an issue!
- new
- addr,
- ch,
- pos = idx * 8 + base + 4;
- // Get the address of the string.
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- addr += AMX_BASE_ADDRESS;
- for ( ; ; )
- {
- // Find the end of the string.
- #emit LREF.S.pri addr
- #emit STOR.S.pri ch
- if (ch & 0x000000FF)
- {
- if (ch & 0x0000FF00)
- {
- if (ch & 0x00FF0000)
- {
- if (ch & 0xFF000000)
- {
- addr += 4;
- continue;
- }
- else addr -= 1;
- }
- else addr -= 2;
- }
- else addr -= 3;
- }
- else addr -= 4;
- break;
- }
- #emit LREF.S.pri addr
- #emit STOR.S.pri ch
- ++idx;
- if (ch == pattern)
- {
- buffer = pos - 4;
- return idx;
- }
- }
- return 0;
- }
- #define AMX_GetPublicName( AMX_GetName(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeName( AMX_GetName(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryName( AMX_GetName(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarName( AMX_GetName(AMX_TABLE_PUBVARS,
- #define AMX_GetTagName( AMX_GetName(AMX_TABLE_TAGS,
- stock AMX_GetName(E_AMX_TABLE:table, idx, buffer[32], const pattern[] = "", const bool:exact = false)
- {
- P:7("AMX_GetName called: %i, %i, \"%s\", \"%s\"", _:table, idx, buffer, pattern);
- new
- base,
- count;
- AMX_GetBaseCount(table, base, count);
- if (idx < count)
- {
- if (pattern[0] == '\0')
- {
- new
- addr,
- pos = idx * 8 + base + 4;
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
- ++idx;
- //buffer = idx * 8 + base;
- return idx;
- }
- else
- {
- new
- addr,
- pos = idx * 8 + base + 4;
- do
- {
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
- ++idx;
- if (exact ? (!strcmp(buffer, pattern)) : (strfind(buffer, pattern) != -1))//if (strfind(buffer, pattern) != -1)
- {
- //buffer = idx * 8 + base;
- return idx;
- }
- pos += 8;
- }
- while (idx < count);
- }
- }
- return 0;
- }
- #define AMX_GetPublicNamePrefix( AMX_GetNamePrefix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeNamePrefix( AMX_GetNamePrefix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryNamePrefix( AMX_GetNamePrefix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarNamePrefix( AMX_GetNamePrefix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagNamePrefix( AMX_GetNamePrefix(AMX_TABLE_TAGS,
- stock AMX_GetNamePrefix(E_AMX_TABLE:table, idx, buffer[32], pattern)
- {
- P:7("AMX_GetNamePrefix called: %i, %i, \"%s\", %i", _:table, idx, buffer, pattern);
- new
- base,
- count;
- AMX_GetBaseCount(table, base, count);
- if (idx < count)
- {
- new
- addr,
- pos = idx * 8 + base + 4;
- do
- {
- // Get the address of the string.
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- // Get the 4 bytes 5 bytes before this position.
- addr += AMX_BASE_ADDRESS;
- #emit LREF.S.pri addr
- #emit STOR.S.pri addr
- ++idx;
- if (addr == pattern)
- {
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
- return idx;
- }
- pos += 8;
- }
- while (idx < count);
- }
- return 0;
- }
- #define AMX_GetPublicNameSuffix( AMX_GetNameSuffix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeNameSuffix( AMX_GetNameSuffix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryNameSuffix( AMX_GetNameSuffix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarNameSuffix( AMX_GetNameSuffix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagNameSuffix( AMX_GetNameSuffix(AMX_TABLE_TAGS,
- stock AMX_GetNameSuffix(E_AMX_TABLE:table, idx, buffer[32], pattern)
- {
- P:7("AMX_GetNameSuffix called: %i, %i, \"%s\", %i", _:table, idx, buffer, pattern);
- new
- base,
- count;
- AMX_GetBaseCount(table, base, count);
- if (idx < --count)
- {
- new
- addr,
- pos = idx * 8 + base + 12;
- do
- {
- // Get the address of the string.
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- // Get the 4 bytes 5 bytes before this position.
- addr += AMX_BASE_ADDRESS - 5;
- #emit LREF.S.pri addr
- #emit STOR.S.pri addr
- ++idx;
- if (addr == pattern)
- {
- //buffer = pos - 12;
- pos -= 8;
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- //addr += AMX_BASE_ADDRESS;
- AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
- return idx;
- }
- pos += 8;
- }
- while (idx < count);
- }
- if (idx == count)
- {
- // Do the final one, this is more of an issue!
- new
- addr,
- ch,
- pos = idx * 8 + base + 4;
- // Get the address of the string.
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- addr += AMX_BASE_ADDRESS;
- for ( ; ; )
- {
- // Find the end of the string.
- #emit LREF.S.pri addr
- #emit STOR.S.pri ch
- if (ch & 0x000000FF)
- {
- if (ch & 0x0000FF00)
- {
- if (ch & 0x00FF0000)
- {
- if (ch & 0xFF000000)
- {
- addr += 4;
- continue;
- }
- else addr -= 1;
- }
- else addr -= 2;
- }
- else addr -= 3;
- }
- else addr -= 4;
- break;
- }
- #emit LREF.S.pri addr
- #emit STOR.S.pri ch
- ++idx;
- if (ch == pattern)
- {
- #emit LREF.S.pri pos
- #emit STOR.S.pri addr
- AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
- return idx;
- }
- }
- return 0;
- }
- #define AMX_GetPublicPointer( AMX_GetPointer(AMX_TABLE_PUBLICS,
- #define AMX_GetNativePointer( AMX_GetPointer(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryPointer( AMX_GetPointer(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarPointer( AMX_GetPointer(AMX_TABLE_PUBVARS,
- #define AMX_GetTagPointer( AMX_GetPointer(AMX_TABLE_TAGS,
- stock AMX_GetPointer(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "", const bool:exact = false)
- {
- P:7("AMX_GetPointer called: %i, %i, %i, \"%s\", %i", _:table, idx, buffer, pattern, exact);
- new
- pointer;
- idx = AMX_GetEntry(table, idx, pointer, pattern, exact);
- if (idx)
- {
- #emit LREF.S.pri pointer
- #emit SREF.S.pri buffer
- }
- return idx;
- }
- #define AMX_GetPublicPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativePointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_TAGS,
- stock AMX_GetPointerPrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
- {
- P:7("AMX_GetPointerPrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
- new
- pointer;
- idx = AMX_GetEntryPrefix(table, idx, pointer, pattern);
- if (idx)
- {
- #emit LREF.S.pri pointer
- #emit SREF.S.pri buffer
- }
- return idx;
- }
- #define AMX_GetPublicPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativePointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_TAGS,
- stock AMX_GetPointerSuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
- {
- P:7("AMX_GetPointerSuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
- new
- pointer;
- idx = AMX_GetEntrySuffix(table, idx, pointer, pattern);
- if (idx)
- {
- #emit LREF.S.pri pointer
- #emit SREF.S.pri buffer
- }
- return idx;
- }
- #define AMX_GetPublicValue( AMX_GetValue(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeValue( AMX_GetValue(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryValue( AMX_GetValue(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarValue( AMX_GetValue(AMX_TABLE_PUBVARS,
- #define AMX_GetTagValue( AMX_GetValue(AMX_TABLE_TAGS,
- stock AMX_GetValue(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "", const bool:exact = false)
- {
- P:7("AMX_GetValue called: %i, %i, %i, \"%s\", %i", _:table, idx, buffer, pattern, exact);
- new
- pointer;
- idx = AMX_GetPointer(table, idx, pointer, pattern, exact);
- if (idx)
- {
- #emit LREF.S.pri pointer
- #emit SREF.S.pri buffer
- }
- return idx;
- }
- #define AMX_GetPublicValuePrefix( AMX_GetValuePrefix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeValuePrefix( AMX_GetValuePrefix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryValuePrefix( AMX_GetValuePrefix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarValuePrefix( AMX_GetValuePrefix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagValuePrefix( AMX_GetValuePrefix(AMX_TABLE_TAGS,
- stock AMX_GetValuePrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
- {
- P:7("AMX_GetValuePrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
- new
- pointer;
- idx = AMX_GetPointerPrefix(table, idx, pointer, pattern);
- if (idx)
- {
- #emit LREF.S.pri pointer
- #emit SREF.S.pri buffer
- }
- return idx;
- }
- #define AMX_GetPublicValueSuffix( AMX_GetValueSuffix(AMX_TABLE_PUBLICS,
- #define AMX_GetNativeValueSuffix( AMX_GetValueSuffix(AMX_TABLE_NATIVES,
- #define AMX_GetLibraryValueSuffix( AMX_GetValueSuffix(AMX_TABLE_LIBRARIES,
- #define AMX_GetPubvarValueSuffix( AMX_GetValueSuffix(AMX_TABLE_PUBVARS,
- #define AMX_GetTagValueSuffix( AMX_GetValueSuffix(AMX_TABLE_TAGS,
- stock AMX_GetValueSuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
- {
- P:7("AMX_GetValueSuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
- new
- pointer;
- idx = AMX_GetPointerSuffix(table, idx, pointer, pattern);
- if (idx)
- {
- #emit LREF.S.pri pointer
- #emit SREF.S.pri buffer
- }
- return idx;
- }
- /*enum e_AMX_HEADER_TYPE (<<= 1)
- {
- e_AMX_HEADER_TYPE_NONE = 0,
- e_AMX_HEADER_TYPE_PUBLIC = 1,
- e_AMX_HEADER_TYPE_NATIVE,
- e_AMX_HEADER_TYPE_LIBRARY,
- e_AMX_HEADER_TYPE_PUBVAR,
- e_AMX_HEADER_TYPE_TAG
- }
- enum E_AMX_HEADER
- {
- e_AMX_HEADER_TYPE:E_AMX_HEADER_TYPE, // Public, native, tag, etc.
- E_AMX_HEADER_ENTRY,
- E_AMX_HEADER_PTR,
- // For variables, this is their value. For publics and natives, this is
- // their table index (used by "funcidx" and "SYSREQ.C" respectively).
- E_AMX_HEADER_VALUE,
- E_AMX_HEADER_NAME[32 char]
- }
- stock AMX_GetEntryData(entry, ret[E_AMX_HEADER])
- {
- if ((ret[e_AMX_HEADER_TYPE] = AMX_GetEntryType(entry)))
- {
-
- }
- }*/
- stock AMX_GetEntryPointer(entry)
- {
- #emit LREF.S.pri entry
- #emit RETN
- return 0; // Make the compiler happy.
- }
- /*stock bool:AMX_GetData(const name[], ret[E_AMX_HEADER], e_AMX_HEADER_TYPE:type = e_AMX_HEADER_TYPE_NONE)
- {
- new
- entry;
- switch (type)
- {
- case e_AMX_HEADER_TYPE_NONE :
- {
- if (AMX_GetEntry(AMX_TABLE_PUBLICS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBLIC ;
- if (AMX_GetEntry(AMX_TABLE_NATIVES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_NATIVE ;
- if (AMX_GetEntry(AMX_TABLE_LIBRARIES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_LIBRARY;
- if (AMX_GetEntry(AMX_TABLE_PUBVARS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBVAR ;
- if (AMX_GetEntry(AMX_TABLE_TAGS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_TAG ;
- }
- case e_AMX_HEADER_TYPE_PUBLIC : AMX_GetEntry(AMX_TABLE_PUBLICS, 0, entry, name);
- case e_AMX_HEADER_TYPE_NATIVE : AMX_GetEntry(AMX_TABLE_NATIVES, 0, entry, name);
- case e_AMX_HEADER_TYPE_LIBRARY: AMX_GetEntry(AMX_TABLE_LIBRARIES, 0, entry, name);
- case e_AMX_HEADER_TYPE_PUBVAR : AMX_GetEntry(AMX_TABLE_PUBVARS, 0, entry, name);
- case e_AMX_HEADER_TYPE_TAG : AMX_GetEntry(AMX_TABLE_TAGS, 0, entry, name);
- }
- strpack(ret[E_AMX_HEADER_NAME], name),
- ret[E_AMX_HEADER_TYPE] = type;
- new
- ptr;
- #emit LREF.S.pri entry
- #emit SREF.S.pri ptr
- switch (type)
- {
- case e_AMX_HEADER_TYPE_PUBLIC :
- {
- // Has a pointer.
- return
- ret[E_AMX_HEADER_ENTRY] = entry,
- ret[E_AMX_HEADER_PTR] = ptr,
- ret[E_AMX_HEADER_VALUE] = AMX_GetPublicIndexFromEntry(entry);
- }
- case e_AMX_HEADER_TYPE_NATIVE :
- {
- // Has a pointer.
- return
- ret[E_AMX_HEADER_ENTRY] = entry,
- ret[E_AMX_HEADER_PTR] = ptr,
- ret[E_AMX_HEADER_VALUE] = AMX_GetNativeIndexFromEntry(entry);
- }
- case e_AMX_HEADER_TYPE_LIBRARY:
- {
- }
- case e_AMX_HEADER_TYPE_PUBVAR :
- {
- }
- case e_AMX_HEADER_TYPE_TAG :
- {
- }
- }
- // Multiple matches found, or none.
- return
- ret[E_AMX_HEADER_INDEX] = -1,
- ret[E_AMX_HEADER_PTR] = 0,
- ret[E_AMX_HEADER_VALUE] = cellmin;
- }*/
- stock AMX_GetEntryFromNativeIndex(index)
- {
- return (index * 8) + AMX_HEADER_NATIVES;
- }
- stock AMX_GetEntryFromPublicIndex(index)
- {
- // An index is an offset in to their own table.
- return (index * 8) + AMX_HEADER_PUBLICS;
- }
- stock AMX_GetNativeIndexFromEntry(entry)
- {
- return (entry - AMX_HEADER_NATIVES) / 8;
- }
- stock AMX_GetPublicIndexFromEntry(entry)
- {
- return (entry - AMX_HEADER_PUBLICS) / 8;
- }
- /*stock AMX_GetEntryType(entry)
- {
- if (AMX_HEADER_PUBLICS <= entry < AMX_HEADER_NATIVES) return e_AMX_HEADER_TYPE_PUBLIC;
- else if (AMX_HEADER_NATIVES <= entry < AMX_HEADER_LIBRARIES) return e_AMX_HEADER_TYPE_NATIVE;
- else if (AMX_HEADER_LIBRARIES <= entry < AMX_HEADER_PUBVARS) return e_AMX_HEADER_TYPE_LIBRARY;
- else if (AMX_HEADER_PUBVARS <= entry < AMX_HEADER_TAGS) return e_AMX_HEADER_TYPE_PUBVAR;
- else if (AMX_HEADER_TAGS <= entry < AMX_HEADER_NAMETABLE) return e_AMX_HEADER_TYPE_TAG;
- return e_AMX_HEADER_TYPE_NONE;
- }
- stock e_AMX_HEADER_TYPE:AMX_GetType(const name[])
- {
- new
- e_AMX_HEADER_TYPE:type = e_AMX_HEADER_TYPE_NONE,
- entry;
- if (AMX_GetEntry(AMX_TABLE_PUBLICS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBLIC ;
- if (AMX_GetEntry(AMX_TABLE_NATIVES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_NATIVE ;
- if (AMX_GetEntry(AMX_TABLE_LIBRARIES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_LIBRARY;
- if (AMX_GetEntry(AMX_TABLE_PUBVARS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBVAR ;
- if (AMX_GetEntry(AMX_TABLE_TAGS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_TAG ;
- return type;
- }*/
- stock AMX_ReadString(addr, str[], len = sizeof (str))
- {
- new
- buffer,
- idx;
- do
- {
- // Read 4 bytes.
- #emit LREF.S.pri addr
- #emit STOR.S.pri buffer
- // Write PACKED strings.
- buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000) | (buffer << 24);
- str[idx] = buffer;
- if (!(buffer & 0x000000FF && buffer & 0x0000FF00 && buffer & 0x00FF0000 && buffer & 0xFF000000))
- {
- return;
- }
- addr += 4;
- }
- while (++idx < len);
- }
- stock AMX_ReadUnpackedString(addr, str[], len = sizeof (str))
- {
- new
- buffer = 1;
- while (buffer && len--);
- {
- // Read 4 bytes.
- #emit LREF.S.pri addr
- #emit STOR.S.pri buffer
- #emit SREF.S.pri str
- #emit LOAD.S.pri str
- #emit ADD.C 4
- #emit STOR.S.pri str
- addr += 4;
- }
- }
- stock AMX_WriteString(addr, const str[], len = sizeof (str))
- {
- new
- old,
- buffer,
- idx;
- do
- {
- buffer = str[idx];
- P:7("AMX_WriteString: Writing %04x%04x", buffer >>> 16, buffer & 0xFFFF);
- if (!(buffer & 0xFF000000))
- {
- #emit LREF.S.pri addr
- #emit CONST.alt 0xFFFFFF00
- #emit AND
- #emit SREF.S.pri addr
- return;
- }
- else if (!(buffer & 0x00FF0000))
- {
- // This:
- // '\0', '1'.
- // Becomes:
- // '1', '\0', ???, ???.
- #emit LREF.S.pri addr
- #emit STOR.S.pri old
- buffer = (old & 0xFFFF0000) | (buffer >>> 24);
- #emit LOAD.S.pri buffer
- #emit SREF.S.pri addr
- return;
- }
- else if (!(buffer & 0x0000FF00))
- {
- // This:
- // '\0', '2', '1'.
- // Becomes:
- // '1', '2', '\0', ???.
- #emit LREF.S.pri addr
- #emit STOR.S.pri old
- buffer = (old & 0xFF000000) | (buffer >>> 24) | (buffer >> 8 & 0x0000FF00);
- #emit LOAD.S.pri buffer
- #emit SREF.S.pri addr
- return;
- }
- else if (!(buffer & 0x000000FF))
- {
- // This:
- // '\0', '3', '2', '1'.
- // Becomes:
- // '1', '2', '3', '\0'.
- // Write 3 bytes.
- buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000);
- #emit LOAD.S.pri buffer
- #emit SREF.S.pri addr
- return;
- }
- else
- {
- // Write 4 bytes.
- buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000) | (buffer << 24);
- #emit LOAD.S.pri buffer
- #emit SREF.S.pri addr
- addr += 4;
- }
- }
- while (++idx < len);
- }
- stock AMX_Read(addr)
- {
- // This is now, AFAIK, the first ever self-inlining function!
- static
- sFrame;
- // Get the current stack pointer.
- #emit LCTRL 4
- #emit ADD.C 12
- // Get the previous frame pointer.
- #emit LOAD.S.alt 0
- #emit SUB
- #emit STOR.pri sFrame
- P:7("AMX_Read called: %i %d", addr, sFrame);
- new
- start = GetCurrentFrameReturn() - 16,
- ctx2[DisasmContext];
- DisasmInit(ctx2, start, start + 16);
- if (!DisasmDecodeInsn(ctx2) || DisasmGetOpcode(ctx2) != OP_PUSH_C || DisasmGetOperand(ctx2) != 4)
- {
- P:W("Couldn't rewrite \"AMX_Read\" call");
- return AMX_RawRead(addr);
- }
- new
- ctx[AsmContext];
- AsmInitPtr(ctx, start + AMX_HEADER_COD, 16);
- // This is the actual code. The standard function call puts the variable to
- // read from on to the stack, so use that as a frame offset and call "LREF"
- // on that stack value. Then remove it from the stack and skip the next
- // cell - since we are replacing 4 cells with just 3.
- @emit LREF.S.pri sFrame
- @emit POP.alt
- @emit NOP
- return AMX_RawRead(addr);
- }
- stock AMX_Write(addr, value)
- {
- P:7("AMX_Write called: %i, %i", addr, value);
- #emit LOAD.S.pri value
- #emit SREF.S.pri addr
- }
- stock AMX_RawRead(addr)
- {
- P:7("AMX_RawRead called: %i", addr);
- #emit LREF.S.pri addr
- #emit RETN
- return 0;
- }
- stock AMX_RawWrite(addr, value)
- {
- P:7("AMX_RawWrite called: %i, %i", addr, value);
- #emit LOAD.S.pri value
- #emit SREF.S.pri addr
- }
- stock AMX_ReadArray(addr, dest[], len = sizeof (dest))
- {
- // I tried to use memcpy, I couldn't get it to work, even when exactly
- // replicating compiler generated code...
- while (len--)
- {
- // Load the address possibly outside "dat". Can't be done using only
- // "pri"/"alt" as it relies on "LREF.S" explicitly.
- #emit LREF.S.pri addr
- #emit SREF.S.pri dest
- #emit LOAD.S.pri addr
- #emit ADD.C 4
- #emit STOR.S.pri addr
- #emit LOAD.S.pri dest
- #emit ADD.C 4
- #emit STOR.S.pri dest
- }
- }
- stock AMX_WriteArray(addr, const src[], len = sizeof (src))
- {
- while (len--)
- {
- #emit DEC.pri
- // Read the data.
- #emit LREF.S.pri dest
- #emit SREF.S.pri addr
- #emit LOAD.S.pri addr
- #emit ADD.C 4
- #emit STOR.S.pri addr
- #emit LOAD.S.pri dest
- #emit ADD.C 4
- #emit STOR.S.pri dest
- }
- }
- stock AMX_CodToDat(ptr)
- {
- // Convert a pointer in to the code segment in to a data offset.
- return ptr + AMX_HEADER_COD;
- }
- #define _A<%0> (_:H_Re(%0,0))
- // Do the next character test as this one failed.
- #define H_Se(%0,%1,%3) H_Ne%1(%0,%3)
- // End of string test failed.
- #define H_Ee(%0,%3) @E_:H_Se(%0,_,%3)
- // Do the single addition.
- #define H_De(%0,%1,%3) (_:H_Re(%0,%3+8))|%1<<%3
- // Recurse through the string.
- #define H_Re(%0,%3) he:H_Ee(%0,%3)
- // Test for the end of a string (4 characters only).
- #define he:H_Ee(%0,0+8+8+8+8) 0
- // Test for the current character.
- #define @E_:H_Se(_%0,%1,%3) H_De(%0,95,%3)
- #define @E@:H_Se(@%0,%1,%3) H_De(%0,64,%3)
- #define @Ey:H_Se(y%0,%1,%3) H_De(%0,121,%3)
- #define @Ea:H_Se(a%0,%1,%3) H_De(%0,97,%3)
- #define @Eb:H_Se(b%0,%1,%3) H_De(%0,98,%3)
- #define @Ec:H_Se(c%0,%1,%3) H_De(%0,99,%3)
- #define @Ed:H_Se(d%0,%1,%3) H_De(%0,100,%3)
- #define @Ee:H_Se(e%0,%1,%3) H_De(%0,101,%3)
- #define @Ef:H_Se(f%0,%1,%3) H_De(%0,102,%3)
- #define @Eg:H_Se(g%0,%1,%3) H_De(%0,103,%3)
- #define @Eh:H_Se(h%0,%1,%3) H_De(%0,104,%3)
- #define @Ei:H_Se(i%0,%1,%3) H_De(%0,105,%3)
- #define @Ej:H_Se(j%0,%1,%3) H_De(%0,106,%3)
- #define @Ek:H_Se(k%0,%1,%3) H_De(%0,107,%3)
- #define @El:H_Se(l%0,%1,%3) H_De(%0,108,%3)
- #define @Em:H_Se(m%0,%1,%3) H_De(%0,109,%3)
- #define @En:H_Se(n%0,%1,%3) H_De(%0,110,%3)
- #define @Eo:H_Se(o%0,%1,%3) H_De(%0,111,%3)
- #define @Ep:H_Se(p%0,%1,%3) H_De(%0,112,%3)
- #define @Eq:H_Se(q%0,%1,%3) H_De(%0,113,%3)
- #define @Er:H_Se(r%0,%1,%3) H_De(%0,114,%3)
- #define @Es:H_Se(s%0,%1,%3) H_De(%0,115,%3)
- #define @Et:H_Se(t%0,%1,%3) H_De(%0,116,%3)
- #define @Eu:H_Se(u%0,%1,%3) H_De(%0,117,%3)
- #define @Ev:H_Se(v%0,%1,%3) H_De(%0,118,%3)
- #define @Ew:H_Se(w%0,%1,%3) H_De(%0,119,%3)
- #define @Ex:H_Se(x%0,%1,%3) H_De(%0,120,%3)
- #define @Ez:H_Se(z%0,%1,%3) H_De(%0,122,%3)
- #define @EA:H_Se(A%0,%1,%3) H_De(%0,65,%3)
- #define @EB:H_Se(B%0,%1,%3) H_De(%0,66,%3)
- #define @EC:H_Se(C%0,%1,%3) H_De(%0,67,%3)
- #define @ED:H_Se(D%0,%1,%3) H_De(%0,68,%3)
- #define @EE:H_Se(E%0,%1,%3) H_De(%0,69,%3)
- #define @EF:H_Se(F%0,%1,%3) H_De(%0,70,%3)
- #define @EG:H_Se(G%0,%1,%3) H_De(%0,71,%3)
- #define @EH:H_Se(H%0,%1,%3) H_De(%0,72,%3)
- #define @EI:H_Se(I%0,%1,%3) H_De(%0,73,%3)
- #define @EJ:H_Se(J%0,%1,%3) H_De(%0,74,%3)
- #define @EK:H_Se(K%0,%1,%3) H_De(%0,75,%3)
- #define @EL:H_Se(L%0,%1,%3) H_De(%0,76,%3)
- #define @EM:H_Se(M%0,%1,%3) H_De(%0,77,%3)
- #define @EN:H_Se(N%0,%1,%3) H_De(%0,78,%3)
- #define @EO:H_Se(O%0,%1,%3) H_De(%0,79,%3)
- #define @EP:H_Se(P%0,%1,%3) H_De(%0,80,%3)
- #define @EQ:H_Se(Q%0,%1,%3) H_De(%0,81,%3)
- #define @ER:H_Se(R%0,%1,%3) H_De(%0,82,%3)
- #define @ES:H_Se(S%0,%1,%3) H_De(%0,83,%3)
- #define @ET:H_Se(T%0,%1,%3) H_De(%0,84,%3)
- #define @EU:H_Se(U%0,%1,%3) H_De(%0,85,%3)
- #define @EV:H_Se(V%0,%1,%3) H_De(%0,86,%3)
- #define @EW:H_Se(W%0,%1,%3) H_De(%0,87,%3)
- #define @EX:H_Se(X%0,%1,%3) H_De(%0,88,%3)
- #define @EY:H_Se(Y%0,%1,%3) H_De(%0,89,%3)
- #define @EZ:H_Se(Z%0,%1,%3) H_De(%0,90,%3)
- #define @E0:H_Se(0%0,%1,%3) H_De(%0,48,%3)
- #define @E1:H_Se(1%0,%1,%3) H_De(%0,49,%3)
- #define @E2:H_Se(2%0,%1,%3) H_De(%0,50,%3)
- #define @E3:H_Se(3%0,%1,%3) H_De(%0,51,%3)
- #define @E4:H_Se(4%0,%1,%3) H_De(%0,52,%3)
- #define @E5:H_Se(5%0,%1,%3) H_De(%0,53,%3)
- #define @E6:H_Se(6%0,%1,%3) H_De(%0,54,%3)
- #define @E7:H_Se(7%0,%1,%3) H_De(%0,55,%3)
- #define @E8:H_Se(8%0,%1,%3) H_De(%0,56,%3)
- #define @E9:H_Se(9%0,%1,%3) H_De(%0,57,%3)
- // Find the next character to test.
- #define H_Ne_(%0,%3) @E@:H_Se(%0,@,%3)
- #define H_Ne@(%0,%3) @Ey:H_Se(%0,y,%3)
- #define H_Ney(%0,%3) @Ea:H_Se(%0,a,%3)
- #define H_Nea(%0,%3) @Eb:H_Se(%0,b,%3)
- #define H_Neb(%0,%3) @Ec:H_Se(%0,c,%3)
- #define H_Nec(%0,%3) @Ed:H_Se(%0,d,%3)
- #define H_Ned(%0,%3) @Ee:H_Se(%0,e,%3)
- #define H_Nee(%0,%3) @Ef:H_Se(%0,f,%3)
- #define H_Nef(%0,%3) @Eg:H_Se(%0,g,%3)
- #define H_Neg(%0,%3) @Eh:H_Se(%0,h,%3)
- #define H_Neh(%0,%3) @Ei:H_Se(%0,i,%3)
- #define H_Nei(%0,%3) @Ej:H_Se(%0,j,%3)
- #define H_Nej(%0,%3) @Ek:H_Se(%0,k,%3)
- #define H_Nek(%0,%3) @El:H_Se(%0,l,%3)
- #define H_Nel(%0,%3) @Em:H_Se(%0,m,%3)
- #define H_Nem(%0,%3) @En:H_Se(%0,n,%3)
- #define H_Nen(%0,%3) @Eo:H_Se(%0,o,%3)
- #define H_Neo(%0,%3) @Ep:H_Se(%0,p,%3)
- #define H_Nep(%0,%3) @Eq:H_Se(%0,q,%3)
- #define H_Neq(%0,%3) @Er:H_Se(%0,r,%3)
- #define H_Ner(%0,%3) @Es:H_Se(%0,s,%3)
- #define H_Nes(%0,%3) @Et:H_Se(%0,t,%3)
- #define H_Net(%0,%3) @Eu:H_Se(%0,u,%3)
- #define H_Neu(%0,%3) @Ev:H_Se(%0,v,%3)
- #define H_Nev(%0,%3) @Ew:H_Se(%0,w,%3)
- #define H_New(%0,%3) @Ex:H_Se(%0,x,%3)
- #define H_Nex(%0,%3) @Ez:H_Se(%0,z,%3)
- #define H_Nez(%0,%3) @EA:H_Se(%0,A,%3)
- #define H_NeA(%0,%3) @EB:H_Se(%0,B,%3)
- #define H_NeB(%0,%3) @EC:H_Se(%0,C,%3)
- #define H_NeC(%0,%3) @ED:H_Se(%0,D,%3)
- #define H_NeD(%0,%3) @EE:H_Se(%0,E,%3)
- #define H_NeE(%0,%3) @EF:H_Se(%0,F,%3)
- #define H_NeF(%0,%3) @EG:H_Se(%0,G,%3)
- #define H_NeG(%0,%3) @EH:H_Se(%0,H,%3)
- #define H_NeH(%0,%3) @EI:H_Se(%0,I,%3)
- #define H_NeI(%0,%3) @EJ:H_Se(%0,J,%3)
- #define H_NeJ(%0,%3) @EK:H_Se(%0,K,%3)
- #define H_NeK(%0,%3) @EL:H_Se(%0,L,%3)
- #define H_NeL(%0,%3) @EM:H_Se(%0,M,%3)
- #define H_NeM(%0,%3) @EN:H_Se(%0,N,%3)
- #define H_NeN(%0,%3) @EO:H_Se(%0,O,%3)
- #define H_NeO(%0,%3) @EP:H_Se(%0,P,%3)
- #define H_NeP(%0,%3) @EQ:H_Se(%0,Q,%3)
- #define H_NeQ(%0,%3) @ER:H_Se(%0,R,%3)
- #define H_NeR(%0,%3) @ES:H_Se(%0,S,%3)
- #define H_NeS(%0,%3) @ET:H_Se(%0,T,%3)
- #define H_NeT(%0,%3) @EU:H_Se(%0,U,%3)
- #define H_NeU(%0,%3) @EV:H_Se(%0,V,%3)
- #define H_NeV(%0,%3) @EW:H_Se(%0,W,%3)
- #define H_NeW(%0,%3) @EX:H_Se(%0,X,%3)
- #define H_NeX(%0,%3) @EY:H_Se(%0,Y,%3)
- #define H_NeY(%0,%3) @EZ:H_Se(%0,Z,%3)
- #define H_NeZ(%0,%3) @E0:H_Se(%0,0,%3)
- #define H_Ne0(%0,%3) @E1:H_Se(%0,1,%3)
- #define H_Ne1(%0,%3) @E2:H_Se(%0,2,%3)
- #define H_Ne2(%0,%3) @E3:H_Se(%0,3,%3)
- #define H_Ne3(%0,%3) @E4:H_Se(%0,4,%3)
- #define H_Ne4(%0,%3) @E5:H_Se(%0,5,%3)
- #define H_Ne5(%0,%3) @E6:H_Se(%0,6,%3)
- #define H_Ne6(%0,%3) @E7:H_Se(%0,7,%3)
- #define H_Ne7(%0,%3) @E8:H_Se(%0,8,%3)
- #define H_Ne8(%0,%3) @E9:H_Se(%0,9,%3)
- #define H_Ne9(%0,%3) ()
|