Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- stock formatex(szOutput[], iLength = sizeof(szOutput), const szFormatString[], {FORMAT_TAGS}:...) {
- static
- s_szBuffer[FORMAT_BUFFER_SIZE],
- bool:s_bIsInCustomSpecifier = false
- ;
- // If formatex is called inside a custom specifier, the original "format" will be used
- // to prevent having s_szBuffer overwritten. Specifiers shouldn't depend on other specifiers, anyway.
- if (s_bIsInCustomSpecifier) {
- new
- iNumArgs,
- i
- ;
- #emit LOAD.S.pri 8
- #emit STOR.S.pri iNumArgs
- #emit SHR.C.pri 2
- #emit STOR.S.pri i
- while (--i >= 0) {
- #emit LOAD.S.pri i
- #emit SHL.C.pri 2
- #emit ADD.C 12
- #emit MOVE.alt
- #emit LCTRL 5
- #emit ADD
- #emit LOAD.I
- #emit PUSH.pri
- }
- #emit LOAD.S.pri iNumArgs
- #emit PUSH.pri
- #emit MOVE.alt
- #emit SYSREQ.C format
- #emit CONST.pri 4
- #emit ADD
- #emit MOVE.alt
- #emit LCTRL 4
- #emit ADD
- #emit SCTRL 4
- } else {
- new
- iPos = -1,
- iArg = 12 + (3 * 4),
- iArgCount,
- iAddress,
- iArgValue,
- aiArgs[128],
- i
- ;
- if (!gs_bIsInitialized)
- InitializeFormatSpecifiers();
- iLength = min(FORMAT_BUFFER_SIZE, iLength);
- s_szBuffer[0] = 0;
- strunpack(s_szBuffer, szFormatString);
- while (-1 != (iPos = strfind(s_szBuffer, !"%", _, ++iPos))) {
- while (s_szBuffer[++iPos]) {
- // Look for custom formats
- if (1 <= s_szBuffer[iPos] < sizeof(gs_CustomFormatFunctions) && gs_CustomFormatFunctions[s_szBuffer[iPos]] != -1) {
- new
- iFunc = gs_CustomFormatFunctions[s_szBuffer[iPos]]
- ;
- static
- s_szCustomFormatBuffer[FORMAT_CUSTOM_SPEC_BUFFER_SIZE]
- ;
- strdel(s_szBuffer, iPos - 1, iPos + 1);
- s_szCustomFormatBuffer[0] = 0;
- #emit LCTRL 5
- #emit LOAD.S.alt iArg
- #emit ADD
- #emit LOAD.I
- #emit MOVE.alt
- #emit LOAD.I
- #emit PUSH.pri
- #emit PUSH.alt
- iArg += 4;
- s_bIsInCustomSpecifier = true;
- #emit PUSH.C s_szCustomFormatBuffer
- #emit PUSH.C 12
- #emit LCTRL 6
- #emit ADD.C 28
- #emit PUSH.pri
- #emit LOAD.S.pri iFunc
- #emit SCTRL 6
- s_bIsInCustomSpecifier = false;
- strins(s_szBuffer, s_szCustomFormatBuffer, iPos - 1);
- break;
- }
- switch (s_szBuffer[iPos]) {
- // Handled by the original format function
- case '*', 'i', 'd', 'x', 'h', 'c', 's', 'f', 'b', 'q': {
- // Get the argument address and save it for later
- #emit LCTRL 5
- #emit LOAD.S.alt iArg
- #emit ADD
- #emit LOAD.I
- #emit STOR.S.pri iAddress
- #emit MOVE.pri
- #emit ADD.C 4
- #emit STOR.S.pri iArg
- aiArgs[iArgCount++] = iAddress;
- if (s_szBuffer[iPos] == '*')
- continue;
- break;
- }
- // Unsigned numbers
- case 'u': {
- new
- szBuffer[11]
- ;
- #emit LCTRL 5
- #emit LOAD.S.alt iArg
- #emit ADD
- #emit LOAD.I
- #emit LOAD.I
- #emit STOR.S.pri iArgValue
- #emit MOVE.pri
- #emit ADD.C 4
- #emit STOR.S.pri iArg
- strdel(s_szBuffer, iPos - 1, iPos + 1);
- if (!iArgValue) {
- strins(s_szBuffer, "0", iPos - 1);
- } else {
- new
- j = sizeof(szBuffer) - 1
- ;
- while (iArgValue) {
- // szBuffer[--i]
- #emit ADDR.alt szBuffer // alt = *szBuffer
- #emit LOAD.S.pri j // pri = i
- #emit DEC.pri // pri -= 1
- #emit STOR.S.pri j // i = pri
- #emit IDXADDR // pri = alt + i * 4
- #emit PUSH.pri // Store pri for later
- // Now do an unsigned divide on uValue then use both the quotient and remainder!
- #emit LOAD.S.pri iArgValue // pri = uValue
- #emit CONST.alt 10
- #emit UDIV // pri = uValue / 10; alt = uValue % 10
- #emit STOR.S.pri iArgValue // uValue = pri
- #emit CONST.pri '0'
- #emit ADD // pri = '0' + (uValue % 10)
- #emit POP.alt // alt = szBuffer[i]
- #emit STOR.I // szBuffer[i] = pri
- }
- strins(s_szBuffer, szBuffer[j], iPos - 1);
- }
- }
- case '0' .. '9', ' ', '.':
- continue;
- case '%':
- break;
- default: {
- break;
- }
- }
- }
- }
- i = iArgCount;
- // Push the arguments we stored above
- while (--i >= 0) {
- #emit ADDR.alt aiArgs
- #emit LOAD.S.pri i
- #emit LIDX
- #emit PUSH.pri
- #emit STOR.S.pri iAddress
- }
- // New format specifier
- #emit PUSH.C s_szBuffer
- // Max length
- #emit PUSH.S iLength
- // Output string
- #emit PUSH.S szOutput
- // Argument count
- #emit LOAD.S.pri iArgCount
- #emit SHL.C.pri 2
- #emit ADD.C 12
- #emit PUSH.pri
- // Save the argument count for later
- #emit MOVE.alt
- // Call format (duh)
- #emit SYSREQ.C format
- // Add 4 to the argument count
- #emit CONST.pri 4
- #emit ADD
- #emit MOVE.alt
- // Remove <argument count> from the stack
- #emit LCTRL 4
- #emit ADD
- #emit SCTRL 4
- }
- // Return in case anyone uses it
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement