Y_Less

y_amx

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