Advertisement
Belgica

Untitled

Oct 2nd, 2016
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 5.32 KB | None | 0 0
  1. stock formatex(szOutput[], iLength = sizeof(szOutput), const szFormatString[], {FORMAT_TAGS}:...) {
  2.     static
  3.              s_szBuffer[FORMAT_BUFFER_SIZE],
  4.         bool:s_bIsInCustomSpecifier = false
  5.     ;
  6.    
  7.     // If formatex is called inside a custom specifier, the original "format" will be used
  8.     // to prevent having s_szBuffer overwritten. Specifiers shouldn't depend on other specifiers, anyway.
  9.     if (s_bIsInCustomSpecifier) {
  10.         new
  11.             iNumArgs,
  12.             i
  13.         ;
  14.        
  15.         #emit LOAD.S.pri  8
  16.         #emit STOR.S.pri  iNumArgs
  17.         #emit SHR.C.pri   2
  18.         #emit STOR.S.pri  i
  19.  
  20.         while (--i >= 0) {
  21.             #emit LOAD.S.pri  i
  22.             #emit SHL.C.pri   2
  23.             #emit ADD.C       12
  24.             #emit MOVE.alt
  25.             #emit LCTRL       5
  26.             #emit ADD
  27.             #emit LOAD.I
  28.             #emit PUSH.pri
  29.         }
  30.        
  31.         #emit LOAD.S.pri  iNumArgs
  32.         #emit PUSH.pri
  33.         #emit MOVE.alt
  34.         #emit SYSREQ.C    format
  35.         #emit CONST.pri   4
  36.         #emit ADD
  37.         #emit MOVE.alt
  38.         #emit LCTRL       4
  39.         #emit ADD
  40.         #emit SCTRL       4
  41.     } else {
  42.         new
  43.             iPos = -1,
  44.             iArg = 12 + (3 * 4),
  45.             iArgCount,
  46.             iAddress,
  47.             iArgValue,
  48.             aiArgs[128],
  49.             i
  50.         ;
  51.    
  52.         if (!gs_bIsInitialized)
  53.             InitializeFormatSpecifiers();
  54.    
  55.         iLength = min(FORMAT_BUFFER_SIZE, iLength);
  56.    
  57.         s_szBuffer[0] = 0;
  58.    
  59.         strunpack(s_szBuffer, szFormatString);
  60.        
  61.         while (-1 != (iPos = strfind(s_szBuffer, !"%", _, ++iPos))) {
  62.             while (s_szBuffer[++iPos]) {
  63.                 // Look for custom formats
  64.                 if (1 <= s_szBuffer[iPos] < sizeof(gs_CustomFormatFunctions) && gs_CustomFormatFunctions[s_szBuffer[iPos]] != -1) {
  65.                     new
  66.                         iFunc = gs_CustomFormatFunctions[s_szBuffer[iPos]]
  67.                     ;
  68.                
  69.                     static
  70.                         s_szCustomFormatBuffer[FORMAT_CUSTOM_SPEC_BUFFER_SIZE]
  71.                     ;
  72.                
  73.                     strdel(s_szBuffer, iPos - 1, iPos + 1);
  74.                
  75.                     s_szCustomFormatBuffer[0] = 0;
  76.                
  77.                     #emit LCTRL       5
  78.                     #emit LOAD.S.alt  iArg
  79.                     #emit ADD
  80.                     #emit LOAD.I
  81.                     #emit MOVE.alt
  82.                     #emit LOAD.I
  83.                     #emit PUSH.pri
  84.                     #emit PUSH.alt
  85.                
  86.                     iArg += 4;
  87.                    
  88.                     s_bIsInCustomSpecifier = true;
  89.                
  90.                     #emit PUSH.C      s_szCustomFormatBuffer
  91.                     #emit PUSH.C      12
  92.                     #emit LCTRL       6
  93.                     #emit ADD.C       28
  94.                     #emit PUSH.pri
  95.                     #emit LOAD.S.pri  iFunc
  96.                     #emit SCTRL       6
  97.                    
  98.                     s_bIsInCustomSpecifier = false;
  99.                
  100.                     strins(s_szBuffer, s_szCustomFormatBuffer, iPos - 1);
  101.                
  102.                     break;
  103.                 }
  104.            
  105.                 switch (s_szBuffer[iPos]) {
  106.                     // Handled by the original format function
  107.                     case '*', 'i', 'd', 'x', 'h', 'c', 's', 'f', 'b', 'q': {
  108.                         // Get the argument address and save it for later
  109.                         #emit LCTRL        5
  110.                         #emit LOAD.S.alt  iArg
  111.                         #emit ADD
  112.                         #emit LOAD.I
  113.                         #emit STOR.S.pri  iAddress
  114.                         #emit MOVE.pri
  115.                         #emit ADD.C       4
  116.                         #emit STOR.S.pri  iArg
  117.                    
  118.                         aiArgs[iArgCount++] = iAddress;
  119.                    
  120.                         if (s_szBuffer[iPos] == '*')
  121.                             continue;
  122.                    
  123.                         break;
  124.                     }
  125.                
  126.                     // Unsigned numbers
  127.                     case 'u': {
  128.                         new
  129.                             szBuffer[11]
  130.                         ;
  131.                    
  132.                         #emit LCTRL       5
  133.                         #emit LOAD.S.alt  iArg
  134.                         #emit ADD
  135.                         #emit LOAD.I
  136.                         #emit LOAD.I
  137.                         #emit STOR.S.pri  iArgValue
  138.                         #emit MOVE.pri
  139.                         #emit ADD.C       4
  140.                         #emit STOR.S.pri  iArg
  141.                    
  142.                         strdel(s_szBuffer, iPos - 1, iPos + 1);
  143.                    
  144.                         if (!iArgValue) {
  145.                             strins(s_szBuffer, "0", iPos - 1);
  146.                         } else {
  147.                             new
  148.                                 j = sizeof(szBuffer) - 1
  149.                             ;
  150.                        
  151.                             while (iArgValue) {
  152.                                 // szBuffer[--i]
  153.                                 #emit ADDR.alt    szBuffer  // alt = *szBuffer
  154.                                 #emit LOAD.S.pri  j         // pri = i
  155.                                 #emit DEC.pri               // pri -= 1
  156.                                 #emit STOR.S.pri  j         // i = pri
  157.                                 #emit IDXADDR               // pri = alt + i * 4
  158.                                 #emit PUSH.pri              // Store pri for later
  159.  
  160.                                 // Now do an unsigned divide on uValue then use both the quotient and remainder!
  161.                                 #emit LOAD.S.pri  iArgValue // pri = uValue
  162.                                 #emit CONST.alt   10
  163.                                 #emit UDIV                  // pri = uValue / 10; alt = uValue % 10
  164.                                 #emit STOR.S.pri  iArgValue // uValue = pri
  165.                                 #emit CONST.pri   '0'
  166.                                 #emit ADD                   // pri = '0' + (uValue % 10)
  167.                                 #emit POP.alt               // alt = szBuffer[i]
  168.                                 #emit STOR.I                // szBuffer[i] = pri
  169.                             }
  170.                        
  171.                             strins(s_szBuffer, szBuffer[j], iPos - 1);
  172.                         }
  173.                     }
  174.                
  175.                     case '0' .. '9', ' ', '.':
  176.                         continue;
  177.                
  178.                     case '%':
  179.                         break;
  180.            
  181.                     default: {
  182.                         break;
  183.                     }
  184.                 }
  185.             }
  186.         }
  187.    
  188.         i = iArgCount;
  189.    
  190.         // Push the arguments we stored above
  191.         while (--i >= 0) {
  192.             #emit ADDR.alt    aiArgs
  193.             #emit LOAD.S.pri  i
  194.             #emit LIDX
  195.             #emit PUSH.pri
  196.             #emit STOR.S.pri iAddress
  197.         }
  198.    
  199.         // New format specifier
  200.         #emit PUSH.C     s_szBuffer
  201.    
  202.         // Max length
  203.         #emit PUSH.S     iLength
  204.    
  205.         // Output string
  206.         #emit PUSH.S     szOutput
  207.    
  208.         // Argument count
  209.         #emit LOAD.S.pri iArgCount
  210.         #emit SHL.C.pri  2
  211.         #emit ADD.C      12
  212.         #emit PUSH.pri
  213.    
  214.         // Save the argument count for later
  215.         #emit MOVE.alt
  216.    
  217.         // Call format (duh)
  218.         #emit SYSREQ.C   format
  219.    
  220.         // Add 4 to the argument count
  221.         #emit CONST.pri  4
  222.         #emit ADD
  223.         #emit MOVE.alt
  224.    
  225.         // Remove <argument count> from the stack
  226.         #emit LCTRL      4
  227.         #emit ADD
  228.         #emit SCTRL      4
  229.     }
  230.    
  231.     // Return in case anyone uses it
  232.     return 1;
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement