Guest User

variadic.inc with mysql_format support

a guest
Mar 14th, 2016
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 13.31 KB | None | 0 0
  1. // Variadic functions in PAWN.
  2.  
  3. /*
  4.     native GetVariadicAddress(argument);
  5.     native GetVariadicString(address, dest[] = "", size = sizeof(dest));
  6.     native SetVariadicString(address, str[]);
  7.  
  8.     native PushArguments(start, end);
  9.     native VariadicFormat(output[], len, const str[], bool:pack = false);
  10.     native CallLocalVariadic(function[], const specifiers[]);
  11.     native CallRemoteVariadic(function[], const specifiers[]);
  12.  
  13.     native IsArgumentPacked(address);
  14.     native GetVariadicLength(address);
  15.     native UnpackArgument(address);
  16.  
  17.     native DeleteArgument(address);
  18.     native PopArguments();
  19. */
  20.  
  21. #define var%0(%1) \
  22.     variadic%0(%1)
  23.  
  24. #define variadic%0(%1) \
  25.     stock%0(%1, {Float,_}:...)
  26.  
  27. #define @variadic[%0] \
  28.     #VARIADIC_FORMAT_%0
  29.  
  30. #if !defined MAX_VARIADIC_STRING
  31.     #define MAX_VARIADIC_STRING (512)
  32. #endif
  33.  
  34. static stock
  35.     g_PushedAddress[24];
  36.  
  37. native org_format(output[], len, const str[], {Float,_}:...) = format;
  38. native org_mysql_format(connectionHandle, output[], len, const str[], {Float,_}:...) = mysql_format;
  39. native org_CallLocalFunction(func[], specifiers[], {Float,_}:...) = CallLocalFunction;
  40. native org_CallRemoteFunction(func[], specifiers[], {Float,_}:...) = CallRemoteFunction;
  41.  
  42. forward _variadic_fix_();
  43. public _variadic_fix_()
  44. {
  45.     strcat("", "");
  46.     strlen("");
  47.     strdel("", 0, 1);
  48.     strunpack("", "");
  49.     strpack("", "");
  50.     ispacked("");
  51.     memcpy("", "", 0, 0, 0);
  52.     CallLocalFunction("", "");
  53.     CallRemoteFunction("", "");
  54.  
  55.     format("", 1, "");
  56.     org_format("", 1, "");
  57.    
  58.     mysql_format(0, "", 1, "");
  59.     org_mysql_format(0, "", 1, "");
  60.    
  61.     org_CallLocalFunction("", "");
  62.     org_CallRemoteFunction("", "");
  63. }
  64.  
  65. stock GetVariadicAddress(argument)
  66. {
  67.     #emit LOAD.S.pri argument
  68.     #emit SHL.C.pri 2
  69.  
  70.     #emit LOAD.S.alt 0
  71.     #emit ADD
  72.  
  73.     #emit ADD.C 12
  74.     #emit LOAD.I
  75.  
  76.     #emit RETN
  77.  
  78.     return 0;
  79. }
  80.  
  81. stock GetVariadicString(address, dest[] = "", size = sizeof(dest))
  82. {
  83.     new string[MAX_VARIADIC_STRING];
  84.  
  85.     #emit LOAD.S.pri address
  86.     //#emit LOAD.I
  87.  
  88.     #emit PUSH.C 512
  89.     #emit PUSH.pri
  90.     #emit PUSH.adr string
  91.  
  92.     #emit PUSH.C 12
  93.     #emit SYSREQ.C strunpack
  94.  
  95.     #emit STACK 16
  96.  
  97.     if (numargs() > 1)
  98.     {
  99.         dest[0] = '\0';
  100.         strcat(dest, string, size);
  101.     }
  102.     return string;
  103. }
  104.  
  105. stock SetVariadicString(address, str[])
  106. {
  107.     new length = 0;
  108.  
  109.     #emit LOAD.S.pri address
  110.  
  111.     #emit PUSH.pri
  112.     #emit PUSH.C 4
  113.     #emit LOAD.S.pri length
  114.  
  115.     #emit SYSREQ.C strlen
  116.     #emit STOR.S.pri length
  117.  
  118.     #emit STACK 8
  119.  
  120.     if (length > 0)
  121.     {
  122.         #emit PUSH.adr length
  123.         #emit PUSH.C 0
  124.         #emit PUSH.S address
  125.  
  126.         #emit PUSH.C 12
  127.         #emit SYSREQ.C strdel
  128.  
  129.         #emit STACK 16
  130.     }
  131.     #emit PUSH.C 512
  132.     #emit PUSH.S str
  133.     #emit PUSH.S address
  134.  
  135.     #emit PUSH.C 12
  136.     #emit SYSREQ.C strcat
  137.  
  138.     #emit STACK 16
  139.     return 1;
  140. }
  141.  
  142. stock PushArguments(start, end)
  143. {
  144.     new idx, addr;
  145.  
  146.     for (new i = 0; i < sizeof(g_PushedAddress); i ++) {
  147.         g_PushedAddress[i] = -1;
  148.     }
  149.     while (start != end)
  150.     {
  151.         #emit LOAD.S.pri start
  152.         #emit SMUL.C 4
  153.  
  154.         #emit LOAD.S.alt 0
  155.         #emit ADD
  156.  
  157.         #emit ADD.C 12
  158.         #emit LOAD.I
  159.         #emit STOR.S.pri addr
  160.  
  161.         #emit CONST.pri g_PushedAddress
  162.         #emit LOAD.S.alt idx
  163.         #emit SHL.C.alt 2
  164.         #emit ADD
  165.         #emit LOAD.I
  166.         #emit LOAD.S.pri addr
  167.         #emit STOR.I
  168.  
  169.         idx++;
  170.         start++;
  171.     }
  172.     return 1;
  173. }
  174.  
  175. stock VariadicFormat(output[], len, const str[], bool:pack = false)
  176. {
  177.     new i, string[MAX_VARIADIC_STRING * 4], args = 12;
  178.  
  179.     for (i = sizeof(g_PushedAddress); --i >= 0; )
  180.     {
  181.         if (g_PushedAddress[i] != -1)
  182.         {
  183.             #emit CONST.pri g_PushedAddress
  184.             #emit LOAD.S.alt i
  185.             #emit SHL.C.alt 2
  186.             #emit ADD
  187.             #emit LOAD.I
  188.             #emit PUSH.pri
  189.  
  190.             args += 4;
  191.         }
  192.     }
  193.     #emit PUSH.S str
  194.     #emit PUSH.S len
  195.     #emit PUSH.adr string
  196.  
  197.     #emit PUSH.S args
  198.     #emit SYSREQ.C format
  199.  
  200.     #emit STACK 16
  201.  
  202.     for (i = 0; i < sizeof(g_PushedAddress); i ++)
  203.     {
  204.         if (g_PushedAddress[i] != -1)
  205.         {
  206.             #emit CONST.pri g_PushedAddress
  207.             #emit LOAD.S.alt i
  208.             #emit SHL.c.alt 2
  209.             #emit ADD
  210.             #emit LOAD.I
  211.             #emit CONST.pri 1
  212.             #emit NEG
  213.             #emit STOR.I
  214.             #emit STACK 4
  215.         }
  216.     }
  217.     if (pack || output[0] > 255) {
  218.         strpack(output, string, len);
  219.     }
  220.     else strcat((output[0] = '\0', output), string, len);
  221.     return 1;
  222. }
  223.  
  224. stock CallLocalVariadic(function[], const specifiers[])
  225. {
  226.     new i, args = 8;
  227.  
  228.     for (i = sizeof(g_PushedAddress); --i >= 0; )
  229.     {
  230.         if (g_PushedAddress[i] != -1)
  231.         {
  232.             #emit CONST.pri g_PushedAddress
  233.             #emit LOAD.S.alt i
  234.             #emit SHL.C.alt 2
  235.             #emit ADD
  236.             #emit LOAD.I
  237.             #emit PUSH.pri
  238.  
  239.             args += 4;
  240.         }
  241.     }
  242.     #emit PUSH.S specifiers
  243.     #emit PUSH.S function
  244.  
  245.     #emit PUSH.S args
  246.     #emit SYSREQ.C CallLocalFunction
  247.  
  248.     #emit STACK 12
  249.  
  250.     for (i = 0; i < sizeof(g_PushedAddress); i ++)
  251.     {
  252.         if (g_PushedAddress[i] != -1)
  253.         {
  254.             #emit CONST.pri g_PushedAddress
  255.             #emit LOAD.S.alt i
  256.             #emit SHL.c.alt 2
  257.             #emit ADD
  258.             #emit LOAD.I
  259.             #emit CONST.pri 1
  260.             #emit NEG
  261.             #emit STOR.I
  262.             #emit STACK 4
  263.         }
  264.     }
  265.     return 1;
  266. }
  267.  
  268. stock CallRemoteVariadic(function[], const specifiers[])
  269. {
  270.     new i, args = 8;
  271.  
  272.     for (i = sizeof(g_PushedAddress); --i >= 0; )
  273.     {
  274.         if (g_PushedAddress[i] != -1)
  275.         {
  276.             #emit CONST.pri g_PushedAddress
  277.             #emit LOAD.S.alt i
  278.             #emit SHL.C.alt 2
  279.             #emit ADD
  280.             #emit LOAD.I
  281.             #emit PUSH.pri
  282.  
  283.             args += 4;
  284.         }
  285.     }
  286.     #emit PUSH.S specifiers
  287.     #emit PUSH.S function
  288.  
  289.     #emit PUSH.S args
  290.     #emit SYSREQ.C CallRemoteFunction
  291.  
  292.     #emit STACK 12
  293.  
  294.     for (i = 0; i < sizeof(g_PushedAddress); i ++)
  295.     {
  296.         if (g_PushedAddress[i] != -1)
  297.         {
  298.             #emit CONST.pri g_PushedAddress
  299.             #emit LOAD.S.alt i
  300.             #emit SHL.c.alt 2
  301.             #emit ADD
  302.             #emit LOAD.I
  303.             #emit CONST.pri 1
  304.             #emit NEG
  305.             #emit STOR.I
  306.             #emit STACK 4
  307.         }
  308.     }
  309.     return 1;
  310. }
  311.  
  312. stock DeleteArgument(address)
  313. {
  314.     new length;
  315.  
  316.     #emit PUSH.S address
  317.     #emit PUSH.C 4
  318.  
  319.     #emit LOAD.S.pri length
  320.     #emit SYSREQ.C strlen
  321.  
  322.     #emit STOR.S.pri length
  323.     #emit STACK 8
  324.  
  325.     #emit PUSH.alt
  326.     #emit PUSH.C 0
  327.     #emit PUSH.S address
  328.     #emit PUSH.C 12
  329.  
  330.     #emit SYSREQ.C strdel
  331.     #emit STACK 16
  332.  
  333.     return 1;
  334. }
  335.  
  336. stock PopArguments()
  337. {
  338.     for (new i = 0; i < sizeof(g_PushedAddress); i ++) {
  339.         if (g_PushedAddress[i] != -1) g_PushedAddress[i] = -1;
  340.     }
  341.     return 1;
  342. }
  343.  
  344. stock IsArgumentPacked(address)
  345. {
  346.     new result;
  347.  
  348.     #emit PUSH.S address
  349.     #emit PUSH.C 4
  350.  
  351.     #emit LOAD.S.pri result
  352.     #emit SYSREQ.C ispacked
  353.  
  354.     #emit STOR.S.pri result
  355.     #emit STACK 8
  356.  
  357.     return result;
  358. }
  359.  
  360. stock GetVariadicLength(address)
  361. {
  362.     new length;
  363.  
  364.     #emit PUSH.S address
  365.     #emit PUSH.C 4
  366.  
  367.     #emit LOAD.S.pri length
  368.     #emit SYSREQ.C strlen
  369.  
  370.     #emit STOR.S.pri length
  371.     #emit STACK 8
  372.  
  373.     return length;
  374. }
  375.  
  376. stock var_Format(output[], len, const str[], {Float,_}:...)
  377. {
  378.     new
  379.         start,
  380.         end,
  381.         argument,
  382.         string[128],
  383.         args = numargs() * 4;
  384.  
  385.     GetVariadicString(GetVariadicAddress(3), string, sizeof(string));
  386.     if (!strfind(string, "VARIADIC_FORMAT_", false))
  387.     {
  388.         start = strval(string[16]);
  389.  
  390.         #emit LOAD.S.pri 0
  391.         #emit ADD.C 8
  392.  
  393.         #emit LOAD.I
  394.         #emit STOR.S.pri args
  395.  
  396.         argument = (args / 4);
  397.  
  398.         while (--argument >= start)
  399.         {
  400.             #emit LOAD.S.pri argument
  401.             #emit SMUL.C 4
  402.  
  403.             #emit LOAD.S.alt 0
  404.             #emit ADD
  405.  
  406.             #emit ADD.C 12
  407.             #emit LOAD.I
  408.             #emit PUSH.pri
  409.         }
  410.         #emit LOAD.S.pri args
  411.         #emit ADD.C 12
  412.         #emit STOR.S.pri args
  413.  
  414.         #emit PUSH.S str
  415.         #emit PUSH.S len
  416.         #emit PUSH.S output
  417.  
  418.         #emit PUSH.S args
  419.         #emit SYSREQ.C org_format
  420.  
  421.         #emit STACK 16
  422.  
  423.         for (argument = (args / 4) - 4; argument >= start; argument --)
  424.         {
  425.             #emit STACK 4
  426.         }
  427.     }
  428.     else
  429.     {
  430.         #emit ADDR.PRI str
  431.         #emit STOR.S.pri start
  432.  
  433.         for (end = start + (args - 12); end > start; end -= 4)
  434.         {
  435.             #emit LOAD.S.pri end
  436.             #emit LOAD.I
  437.             #emit PUSH.pri
  438.         }
  439.         #emit PUSH.S str
  440.         #emit PUSH.S len
  441.         #emit PUSH.S output
  442.  
  443.         #emit PUSH.S args
  444.         #emit SYSREQ.C org_format
  445.  
  446.         #emit STACK 16
  447.  
  448.         for (end = start + (args - 12); end > start; end -= 4)
  449.         {
  450.             #emit STACK 4
  451.         }
  452.     }
  453.     return 1;
  454. }
  455.  
  456. stock var_mysql_format(connectionHandle, output[], len, const str[], {Float,_}:...)
  457. {
  458.     new
  459.         start,
  460.         end,
  461.         argument,
  462.         string[128],
  463.         args = numargs() * 4;
  464.  
  465.     GetVariadicString(GetVariadicAddress(4), string, sizeof(string));
  466.     if (!strfind(string, "VARIADIC_FORMAT_", false))
  467.     {
  468.         start = strval(string[16]);
  469.  
  470.         #emit LOAD.S.pri 0
  471.         #emit ADD.C 8
  472.  
  473.         #emit LOAD.I
  474.         #emit STOR.S.pri args
  475.  
  476.         argument = (args / 4);
  477.  
  478.         while (--argument >= start)
  479.         {
  480.             #emit LOAD.S.pri argument
  481.             #emit SMUL.C 4
  482.  
  483.             #emit LOAD.S.alt 0
  484.             #emit ADD
  485.  
  486.             #emit ADD.C 12
  487.             #emit LOAD.I
  488.             #emit PUSH.pri
  489.         }
  490.         #emit LOAD.S.pri args
  491.         #emit ADD.C 16
  492.         #emit STOR.S.pri args
  493.  
  494.         #emit PUSH.S str
  495.         #emit PUSH.S len
  496.         #emit PUSH.S output
  497.         #emit PUSH.S connectionHandle
  498.  
  499.         #emit PUSH.S args
  500.         #emit SYSREQ.C org_mysql_format
  501.  
  502.         #emit STACK 20
  503.  
  504.         for (argument = (args / 4) - 5; argument >= start; argument--)
  505.         {
  506.             #emit STACK 4
  507.         }
  508.     }
  509.     else
  510.     {
  511.         #emit ADDR.PRI str
  512.         #emit STOR.S.pri start
  513.  
  514.         for (end = start + (args - 16); end > start; end -= 4)
  515.         {
  516.             #emit LOAD.S.pri end
  517.             #emit LOAD.I
  518.             #emit PUSH.pri
  519.         }
  520.  
  521.         #emit PUSH.S str
  522.         #emit PUSH.S len
  523.         #emit PUSH.S output
  524.         #emit PUSH.S connectionHandle
  525.  
  526.         #emit PUSH.S args
  527.         #emit SYSREQ.C org_mysql_format
  528.  
  529.         #emit STACK 20
  530.  
  531.         for (end = start + (args - 16); end > start; end -= 4)
  532.         {
  533.             #emit STACK 4
  534.         }
  535.     }
  536.     return 1;
  537. }
  538.  
  539. stock var_CallLocalFunction(func[], const specifiers[], {Float,_}:...)
  540. {
  541.     new
  542.         start,
  543.         end,
  544.         argument,
  545.         string[128],
  546.         args = numargs() * 4;
  547.  
  548.     GetVariadicString(GetVariadicAddress(2), string, sizeof(string));
  549.     if (!strfind(string, "VARIADIC_FORMAT_", false))
  550.     {
  551.         start = strval(string[16]);
  552.  
  553.         #emit LOAD.S.pri 0
  554.         #emit ADD.C 8
  555.  
  556.         #emit LOAD.I
  557.         #emit STOR.S.pri args
  558.  
  559.         argument = (args / 4);
  560.  
  561.         while (--argument >= start)
  562.         {
  563.             #emit LOAD.S.pri argument
  564.             #emit SMUL.C 4
  565.  
  566.             #emit LOAD.S.alt 0
  567.             #emit ADD
  568.  
  569.             #emit ADD.C 12
  570.             #emit LOAD.I
  571.             #emit PUSH.pri
  572.         }
  573.         #emit LOAD.S.pri args
  574.         #emit ADD.C 8
  575.         #emit STOR.S.pri args
  576.  
  577.         #emit PUSH.S specifiers
  578.         #emit PUSH.S func
  579.  
  580.         #emit PUSH.S args
  581.         #emit SYSREQ.C org_CallLocalFunction
  582.  
  583.         #emit STACK 12
  584.  
  585.         for (argument = (args / 4) - 3; argument >= start; argument --)
  586.         {
  587.             #emit STACK 4
  588.         }
  589.     }
  590.     else
  591.     {
  592.         #emit ADDR.PRI specifiers
  593.         #emit STOR.S.pri start
  594.  
  595.         for (end = start + (args - 8); end > start; end -= 4)
  596.         {
  597.             #emit LOAD.S.pri end
  598.             #emit LOAD.I
  599.             #emit PUSH.pri
  600.         }
  601.         #emit PUSH.S specifiers
  602.         #emit PUSH.S func
  603.  
  604.         #emit PUSH.S args
  605.         #emit SYSREQ.C org_CallLocalFunction
  606.  
  607.         #emit STACK 12
  608.  
  609.         for (end = start + (args - 8); end > start; end -= 4)
  610.         {
  611.             #emit STACK 4
  612.         }
  613.     }
  614.     return 1;
  615. }
  616.  
  617. stock var_CallRemoteFunction(func[], const specifiers[], {Float,_}:...)
  618. {
  619.     new
  620.         start,
  621.         end,
  622.         argument,
  623.         string[128],
  624.         args = numargs() * 4;
  625.  
  626.     GetVariadicString(GetVariadicAddress(2), string, sizeof(string));
  627.     if (!strfind(string, "VARIADIC_FORMAT_", false))
  628.     {
  629.         start = strval(string[16]);
  630.  
  631.         #emit LOAD.S.pri 0
  632.         #emit ADD.C 8
  633.  
  634.         #emit LOAD.I
  635.         #emit STOR.S.pri args
  636.  
  637.         argument = (args / 4);
  638.  
  639.         while (--argument >= start)
  640.         {
  641.             #emit LOAD.S.pri argument
  642.             #emit SMUL.C 4
  643.  
  644.             #emit LOAD.S.alt 0
  645.             #emit ADD
  646.  
  647.             #emit ADD.C 12
  648.             #emit LOAD.I
  649.             #emit PUSH.pri
  650.         }
  651.         #emit LOAD.S.pri args
  652.         #emit ADD.C 8
  653.         #emit STOR.S.pri args
  654.  
  655.         #emit PUSH.S specifiers
  656.         #emit PUSH.S func
  657.  
  658.         #emit PUSH.S args
  659.         #emit SYSREQ.C org_CallRemoteFunction
  660.  
  661.         #emit STACK 12
  662.  
  663.         for (argument = (args / 4) - 3; argument >= start; argument --)
  664.         {
  665.             #emit STACK 4
  666.         }
  667.     }
  668.     else
  669.     {
  670.         #emit ADDR.PRI specifiers
  671.         #emit STOR.S.pri start
  672.  
  673.         for (end = start + (args - 8); end > start; end -= 4)
  674.         {
  675.             #emit LOAD.S.pri end
  676.             #emit LOAD.I
  677.             #emit PUSH.pri
  678.         }
  679.         #emit PUSH.S specifiers
  680.         #emit PUSH.S func
  681.  
  682.         #emit PUSH.S args
  683.         #emit SYSREQ.C org_CallRemoteFunction
  684.  
  685.         #emit STACK 12
  686.  
  687.         for (end = start + (args - 8); end > start; end -= 4)
  688.         {
  689.             #emit STACK 4
  690.         }
  691.     }
  692.     return 1;
  693. }
  694.  
  695. #if defined _ALS_format
  696.     #undef format
  697. #else
  698.     #define _ALS_format
  699. #endif
  700.  
  701. #if defined _ALS_mysql_format
  702.     #undef mysql_format
  703. #else
  704.     #define _ALS_mysql_format
  705. #endif
  706.  
  707. #if defined _ALS_CallLocalFunction
  708.     #undef CallLocalFunction
  709. #else
  710.     #define _ALS_CallLocalFunction
  711. #endif
  712.  
  713. #if defined _ALS_CallRemoteFunction
  714.     #undef CallRemoteFunction
  715. #else
  716.     #define _ALS_CallRemoteFunction
  717. #endif
  718.  
  719. #define format(%0) \
  720.     (var_Format(%0))
  721.    
  722. #define format(%0) \
  723.     (var_mysql_format(%0))
  724.  
  725. #define CallLocalFunction(%0) \
  726.     (var_CallLocalFunction(%0))
  727.  
  728. #define CallRemoteFunction(%0) \
  729.     (var_CallRemoteFunction(%0))
Advertisement
Add Comment
Please, Sign In to add comment