| /* do not edit automatically generated by mc from FormatStrings. */ |
| /* FormatStrings.mod provides a pseudo printf capability. |
| |
| Copyright (C) 2005-2025 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
| |
| This file is part of GNU Modula-2. |
| |
| GNU Modula-2 is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GNU Modula-2 is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include <stdbool.h> |
| # if !defined (PROC_D) |
| # define PROC_D |
| typedef void (*PROC_t) (void); |
| typedef struct { PROC_t proc; } PROC; |
| # endif |
| |
| # if !defined (TRUE) |
| # define TRUE (1==1) |
| # endif |
| |
| # if !defined (FALSE) |
| # define FALSE (1==0) |
| # endif |
| |
| #if defined(__cplusplus) |
| # undef NULL |
| # define NULL 0 |
| #endif |
| #define _FormatStrings_C |
| |
| #include "GFormatStrings.h" |
| # include "GDynamicStrings.h" |
| # include "GStringConvert.h" |
| # include "GSYSTEM.h" |
| # include "GASCII.h" |
| # include "GM2RTS.h" |
| |
| |
| /* |
| Sprintf0 - returns a String containing, s, after it has had its |
| escape sequences translated. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf0 (DynamicStrings_String fmt); |
| |
| /* |
| Sprintf1 - returns a String containing, s, together with encapsulated |
| entity, w. It only formats the first %s or %d with n. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf1 (DynamicStrings_String fmt, const unsigned char *w_, unsigned int _w_high); |
| |
| /* |
| Sprintf2 - returns a string, s, which has been formatted. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf2 (DynamicStrings_String fmt, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high); |
| |
| /* |
| Sprintf3 - returns a string, s, which has been formatted. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf3 (DynamicStrings_String fmt, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high); |
| |
| /* |
| Sprintf4 - returns a string, s, which has been formatted. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf4 (DynamicStrings_String fmt, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high, const unsigned char *w4_, unsigned int _w4_high); |
| |
| /* |
| HandleEscape - translates \a, \b, \e, \f, |
| , \r, \x[hex] \[octal] into |
| their respective ascii codes. It also converts \[any] into |
| a single [any] character. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_HandleEscape (DynamicStrings_String s); |
| |
| /* |
| doDSdbEnter - |
| */ |
| |
| static void doDSdbEnter (void); |
| |
| /* |
| doDSdbExit - |
| */ |
| |
| static void doDSdbExit (DynamicStrings_String s); |
| |
| /* |
| DSdbEnter - |
| */ |
| |
| static void DSdbEnter (void); |
| |
| /* |
| DSdbExit - |
| */ |
| |
| static void DSdbExit (DynamicStrings_String s); |
| |
| /* |
| IsDigit - returns TRUE if ch lies in the range: 0..9 |
| */ |
| |
| static bool IsDigit (char ch); |
| |
| /* |
| Cast - casts a := b |
| */ |
| |
| static void Cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high); |
| |
| /* |
| isHex - |
| */ |
| |
| static bool isHex (char ch); |
| |
| /* |
| toHex - |
| */ |
| |
| static unsigned int toHex (char ch); |
| |
| /* |
| toOct - |
| */ |
| |
| static unsigned int toOct (char ch); |
| |
| /* |
| isOct - |
| */ |
| |
| static bool isOct (char ch); |
| |
| /* |
| FormatString - returns a String containing, s, together with encapsulated |
| entity, w. It only formats the first %s or %d or %u with n. |
| A new string is returned. |
| */ |
| |
| static DynamicStrings_String FormatString (DynamicStrings_String fmt, int *startpos, DynamicStrings_String in, const unsigned char *w_, unsigned int _w_high); |
| |
| /* |
| FormatString - returns a String containing, s, together with encapsulated |
| entity, w. It only formats the first %s or %d or %u with n. |
| A new string is returned. |
| */ |
| |
| static DynamicStrings_String PerformFormatString (DynamicStrings_String fmt, int *startpos, DynamicStrings_String in, const unsigned char *w_, unsigned int _w_high); |
| |
| /* |
| Copy - copies, fmt[start:end] -> in and returns in. Providing that start >= 0. |
| */ |
| |
| static DynamicStrings_String Copy (DynamicStrings_String fmt, DynamicStrings_String in, int start, int end); |
| |
| /* |
| HandlePercent - pre-condition: s, is a string. |
| Post-condition: a new string is returned which is a copy of, |
| s, except %% is transformed into %. |
| */ |
| |
| static DynamicStrings_String HandlePercent (DynamicStrings_String fmt, DynamicStrings_String s, int startpos); |
| |
| |
| /* |
| doDSdbEnter - |
| */ |
| |
| static void doDSdbEnter (void) |
| { |
| DynamicStrings_PushAllocation (); |
| } |
| |
| |
| /* |
| doDSdbExit - |
| */ |
| |
| static void doDSdbExit (DynamicStrings_String s) |
| { |
| s = DynamicStrings_PopAllocationExemption (true, s); |
| } |
| |
| |
| /* |
| DSdbEnter - |
| */ |
| |
| static void DSdbEnter (void) |
| { |
| } |
| |
| |
| /* |
| DSdbExit - |
| */ |
| |
| static void DSdbExit (DynamicStrings_String s) |
| { |
| } |
| |
| |
| /* |
| IsDigit - returns TRUE if ch lies in the range: 0..9 |
| */ |
| |
| static bool IsDigit (char ch) |
| { |
| return (ch >= '0') && (ch <= '9'); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Cast - casts a := b |
| */ |
| |
| static void Cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high) |
| { |
| unsigned int i; |
| unsigned char b[_b_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (b, b_, _b_high+1); |
| |
| if (_a_high == _b_high) |
| { |
| for (i=0; i<=_a_high; i++) |
| { |
| const_cast<unsigned char *>(a)[i] = b[i]; |
| } |
| } |
| else |
| { |
| M2RTS_HALT (-1); |
| __builtin_unreachable (); |
| } |
| } |
| |
| |
| /* |
| isHex - |
| */ |
| |
| static bool isHex (char ch) |
| { |
| return (((ch >= '0') && (ch <= '9')) || ((ch >= 'A') && (ch <= 'F'))) || ((ch >= 'a') && (ch <= 'f')); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| toHex - |
| */ |
| |
| static unsigned int toHex (char ch) |
| { |
| if ((ch >= '0') && (ch <= '9')) |
| { |
| return ((unsigned int) (ch))- ((unsigned int) ('0')); |
| } |
| else if ((ch >= 'A') && (ch <= 'F')) |
| { |
| /* avoid dangling else. */ |
| return ( ((unsigned int) (ch))- ((unsigned int) ('A')))+10; |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| return ( ((unsigned int) (ch))- ((unsigned int) ('a')))+10; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| toOct - |
| */ |
| |
| static unsigned int toOct (char ch) |
| { |
| return ((unsigned int) (ch))- ((unsigned int) ('0')); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| isOct - |
| */ |
| |
| static bool isOct (char ch) |
| { |
| return (ch >= '0') && (ch <= '8'); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| FormatString - returns a String containing, s, together with encapsulated |
| entity, w. It only formats the first %s or %d or %u with n. |
| A new string is returned. |
| */ |
| |
| static DynamicStrings_String FormatString (DynamicStrings_String fmt, int *startpos, DynamicStrings_String in, const unsigned char *w_, unsigned int _w_high) |
| { |
| DynamicStrings_String s; |
| unsigned char w[_w_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (w, w_, _w_high+1); |
| |
| DSdbEnter (); |
| if ((*startpos) >= 0) |
| { |
| s = PerformFormatString (fmt, startpos, in, (const unsigned char *) w, _w_high); |
| } |
| else |
| { |
| s = DynamicStrings_Dup (in); |
| } |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| FormatString - returns a String containing, s, together with encapsulated |
| entity, w. It only formats the first %s or %d or %u with n. |
| A new string is returned. |
| */ |
| |
| static DynamicStrings_String PerformFormatString (DynamicStrings_String fmt, int *startpos, DynamicStrings_String in, const unsigned char *w_, unsigned int _w_high) |
| { |
| bool left; |
| unsigned int u; |
| int c; |
| int width; |
| int nextperc; |
| int afterperc; |
| char leader; |
| char ch; |
| char ch2; |
| DynamicStrings_String p; |
| unsigned char w[_w_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (w, w_, _w_high+1); |
| |
| while ((*startpos) >= 0) |
| { |
| nextperc = DynamicStrings_Index (fmt, '%', static_cast<unsigned int> ((*startpos))); |
| afterperc = nextperc; |
| if (nextperc >= 0) |
| { |
| afterperc += 1; |
| if ((DynamicStrings_char (fmt, afterperc)) == '-') |
| { |
| left = true; |
| afterperc += 1; |
| } |
| else |
| { |
| left = false; |
| } |
| ch = DynamicStrings_char (fmt, afterperc); |
| if (ch == '0') |
| { |
| leader = '0'; |
| } |
| else |
| { |
| leader = ' '; |
| } |
| width = 0; |
| while (IsDigit (ch)) |
| { |
| width = (width*10)+((int ) ( ((unsigned int) (ch))- ((unsigned int) ('0')))); |
| afterperc += 1; |
| ch = DynamicStrings_char (fmt, afterperc); |
| } |
| if ((ch == 'c') || (ch == 's')) |
| { |
| afterperc += 1; |
| if (ch == 'c') |
| { |
| ch2 = static_cast<char> (w[0]); |
| p = DynamicStrings_ConCatChar (DynamicStrings_InitString ((const char *) "", 0), ch2); |
| } |
| else |
| { |
| Cast ((unsigned char *) &p, (sizeof (p)-1), (const unsigned char *) w, _w_high); |
| p = DynamicStrings_Dup (p); |
| } |
| if ((width > 0) && (((int ) (DynamicStrings_Length (p))) < width)) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if (left) |
| { |
| /* place trailing spaces after, p. */ |
| p = DynamicStrings_ConCat (p, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " ", 1)), static_cast<unsigned int> (width-((int ) (DynamicStrings_Length (p))))))); |
| } |
| else |
| { |
| /* padd string, p, with leading spaces. */ |
| p = DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " ", 1)), static_cast<unsigned int> (width-((int ) (DynamicStrings_Length (p))))), DynamicStrings_Mark (p)); |
| } |
| } |
| /* include string, p, into, in. */ |
| if (nextperc > 0) |
| { |
| in = DynamicStrings_ConCat (in, DynamicStrings_Slice (fmt, (*startpos), nextperc)); |
| } |
| in = DynamicStrings_ConCat (in, p); |
| (*startpos) = afterperc; |
| DSdbExit (static_cast<DynamicStrings_String> (NULL)); |
| return in; |
| } |
| else if (ch == 'd') |
| { |
| /* avoid dangling else. */ |
| afterperc += 1; |
| Cast ((unsigned char *) &c, (sizeof (c)-1), (const unsigned char *) w, _w_high); |
| in = Copy (fmt, in, (*startpos), nextperc); |
| in = DynamicStrings_ConCat (in, StringConvert_IntegerToString (c, static_cast<unsigned int> (width), leader, false, 10, false)); |
| (*startpos) = afterperc; |
| DSdbExit (static_cast<DynamicStrings_String> (NULL)); |
| return in; |
| } |
| else if (ch == 'x') |
| { |
| /* avoid dangling else. */ |
| afterperc += 1; |
| Cast ((unsigned char *) &u, (sizeof (u)-1), (const unsigned char *) w, _w_high); |
| in = Copy (fmt, in, (*startpos), nextperc); |
| in = DynamicStrings_ConCat (in, StringConvert_CardinalToString (u, static_cast<unsigned int> (width), leader, 16, true)); |
| (*startpos) = afterperc; |
| DSdbExit (static_cast<DynamicStrings_String> (NULL)); |
| return in; |
| } |
| else if (ch == 'u') |
| { |
| /* avoid dangling else. */ |
| afterperc += 1; |
| Cast ((unsigned char *) &u, (sizeof (u)-1), (const unsigned char *) w, _w_high); |
| in = Copy (fmt, in, (*startpos), nextperc); |
| in = DynamicStrings_ConCat (in, StringConvert_CardinalToString (u, static_cast<unsigned int> (width), leader, 10, false)); |
| (*startpos) = afterperc; |
| DSdbExit (static_cast<DynamicStrings_String> (NULL)); |
| return in; |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| afterperc += 1; |
| /* copy format string. */ |
| if (nextperc > 0) |
| { |
| in = DynamicStrings_ConCat (in, DynamicStrings_Slice (fmt, (*startpos), nextperc)); |
| } |
| /* and the character after the %. */ |
| in = DynamicStrings_ConCat (in, DynamicStrings_Mark (DynamicStrings_InitStringChar (ch))); |
| } |
| (*startpos) = afterperc; |
| } |
| else |
| { |
| /* nothing to do. */ |
| DSdbExit (static_cast<DynamicStrings_String> (NULL)); |
| return in; |
| } |
| } |
| DSdbExit (static_cast<DynamicStrings_String> (NULL)); |
| return in; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Copy - copies, fmt[start:end] -> in and returns in. Providing that start >= 0. |
| */ |
| |
| static DynamicStrings_String Copy (DynamicStrings_String fmt, DynamicStrings_String in, int start, int end) |
| { |
| if (start >= 0) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if (end > 0) |
| { |
| in = DynamicStrings_ConCat (in, DynamicStrings_Mark (DynamicStrings_Slice (fmt, start, end))); |
| } |
| else if (end < 0) |
| { |
| /* avoid dangling else. */ |
| in = DynamicStrings_ConCat (in, DynamicStrings_Mark (DynamicStrings_Slice (fmt, start, 0))); |
| } |
| } |
| return in; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| HandlePercent - pre-condition: s, is a string. |
| Post-condition: a new string is returned which is a copy of, |
| s, except %% is transformed into %. |
| */ |
| |
| static DynamicStrings_String HandlePercent (DynamicStrings_String fmt, DynamicStrings_String s, int startpos) |
| { |
| int prevpos; |
| |
| if ((startpos == ((int ) (DynamicStrings_Length (fmt)))) || (startpos < 0)) |
| { |
| return s; |
| } |
| else |
| { |
| prevpos = startpos; |
| while ((startpos >= 0) && (prevpos < ((int ) (DynamicStrings_Length (fmt))))) |
| { |
| startpos = DynamicStrings_Index (fmt, '%', static_cast<unsigned int> (startpos)); |
| if (startpos >= prevpos) |
| { |
| if (startpos > 0) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Slice (fmt, prevpos, startpos))); |
| } |
| startpos += 1; |
| if ((DynamicStrings_char (fmt, startpos)) == '%') |
| { |
| s = DynamicStrings_ConCatChar (s, '%'); |
| startpos += 1; |
| } |
| prevpos = startpos; |
| } |
| } |
| if (prevpos < ((int ) (DynamicStrings_Length (fmt)))) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Slice (fmt, prevpos, 0))); |
| } |
| return s; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Sprintf0 - returns a String containing, s, after it has had its |
| escape sequences translated. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf0 (DynamicStrings_String fmt) |
| { |
| DynamicStrings_String s; |
| |
| DSdbEnter (); |
| fmt = FormatStrings_HandleEscape (fmt); |
| s = HandlePercent (fmt, DynamicStrings_InitString ((const char *) "", 0), 0); |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Sprintf1 - returns a String containing, s, together with encapsulated |
| entity, w. It only formats the first %s or %d with n. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf1 (DynamicStrings_String fmt, const unsigned char *w_, unsigned int _w_high) |
| { |
| int i; |
| DynamicStrings_String s; |
| unsigned char w[_w_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (w, w_, _w_high+1); |
| |
| DSdbEnter (); |
| fmt = FormatStrings_HandleEscape (fmt); |
| i = 0; |
| s = FormatString (fmt, &i, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w, _w_high); |
| s = HandlePercent (fmt, s, i); |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Sprintf2 - returns a string, s, which has been formatted. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf2 (DynamicStrings_String fmt, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high) |
| { |
| int i; |
| DynamicStrings_String s; |
| unsigned char w1[_w1_high+1]; |
| unsigned char w2[_w2_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (w1, w1_, _w1_high+1); |
| memcpy (w2, w2_, _w2_high+1); |
| |
| DSdbEnter (); |
| fmt = FormatStrings_HandleEscape (fmt); |
| i = 0; |
| s = FormatString (fmt, &i, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w1, _w1_high); |
| s = FormatString (fmt, &i, s, (const unsigned char *) w2, _w2_high); |
| s = HandlePercent (fmt, s, i); |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Sprintf3 - returns a string, s, which has been formatted. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf3 (DynamicStrings_String fmt, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high) |
| { |
| int i; |
| DynamicStrings_String s; |
| unsigned char w1[_w1_high+1]; |
| unsigned char w2[_w2_high+1]; |
| unsigned char w3[_w3_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (w1, w1_, _w1_high+1); |
| memcpy (w2, w2_, _w2_high+1); |
| memcpy (w3, w3_, _w3_high+1); |
| |
| DSdbEnter (); |
| fmt = FormatStrings_HandleEscape (fmt); |
| i = 0; |
| s = FormatString (fmt, &i, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w1, _w1_high); |
| s = FormatString (fmt, &i, s, (const unsigned char *) w2, _w2_high); |
| s = FormatString (fmt, &i, s, (const unsigned char *) w3, _w3_high); |
| s = HandlePercent (fmt, s, i); |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Sprintf4 - returns a string, s, which has been formatted. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_Sprintf4 (DynamicStrings_String fmt, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high, const unsigned char *w4_, unsigned int _w4_high) |
| { |
| int i; |
| DynamicStrings_String s; |
| unsigned char w1[_w1_high+1]; |
| unsigned char w2[_w2_high+1]; |
| unsigned char w3[_w3_high+1]; |
| unsigned char w4[_w4_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (w1, w1_, _w1_high+1); |
| memcpy (w2, w2_, _w2_high+1); |
| memcpy (w3, w3_, _w3_high+1); |
| memcpy (w4, w4_, _w4_high+1); |
| |
| DSdbEnter (); |
| fmt = FormatStrings_HandleEscape (fmt); |
| i = 0; |
| s = FormatString (fmt, &i, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w1, _w1_high); |
| s = FormatString (fmt, &i, s, (const unsigned char *) w2, _w2_high); |
| s = FormatString (fmt, &i, s, (const unsigned char *) w3, _w3_high); |
| s = FormatString (fmt, &i, s, (const unsigned char *) w4, _w4_high); |
| s = HandlePercent (fmt, s, i); |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| HandleEscape - translates \a, \b, \e, \f, |
| , \r, \x[hex] \[octal] into |
| their respective ascii codes. It also converts \[any] into |
| a single [any] character. |
| */ |
| |
| extern "C" DynamicStrings_String FormatStrings_HandleEscape (DynamicStrings_String s) |
| { |
| DynamicStrings_String d; |
| int i; |
| int j; |
| char ch; |
| unsigned char b; |
| |
| DSdbEnter (); |
| d = DynamicStrings_InitString ((const char *) "", 0); |
| i = DynamicStrings_Index (s, '\\', 0); |
| j = 0; |
| while (i >= 0) |
| { |
| if (i > 0) |
| { |
| /* initially i might be zero which means the end of the string, which is not what we want. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Slice (s, j, i)); |
| } |
| ch = DynamicStrings_char (s, i+1); |
| if (ch == 'a') |
| { |
| /* requires a bell. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_bel))); |
| } |
| else if (ch == 'b') |
| { |
| /* avoid dangling else. */ |
| /* requires a backspace. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_bs))); |
| } |
| else if (ch == 'e') |
| { |
| /* avoid dangling else. */ |
| /* requires a escape. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_esc))); |
| } |
| else if (ch == 'f') |
| { |
| /* avoid dangling else. */ |
| /* requires a formfeed. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_ff))); |
| } |
| else if (ch == 'n') |
| { |
| /* avoid dangling else. */ |
| /* requires a newline. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_nl))); |
| } |
| else if (ch == 'r') |
| { |
| /* avoid dangling else. */ |
| /* requires a carriage return. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_cr))); |
| } |
| else if (ch == 't') |
| { |
| /* avoid dangling else. */ |
| /* requires a tab. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_tab))); |
| } |
| else if (ch == 'x') |
| { |
| /* avoid dangling else. */ |
| i += 1; |
| if (isHex (DynamicStrings_char (s, i+1))) |
| { |
| b = (unsigned char ) (toHex (DynamicStrings_char (s, i+1))); |
| i += 1; |
| if (isHex (DynamicStrings_char (s, i+1))) |
| { |
| b = (unsigned char ) ((((unsigned int ) (b))*0x010)+(toHex (DynamicStrings_char (s, i+1)))); |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar ((char ) (b)))); |
| } |
| } |
| } |
| else if (isOct (ch)) |
| { |
| /* avoid dangling else. */ |
| b = (unsigned char ) (toOct (ch)); |
| i += 1; |
| if (isOct (DynamicStrings_char (s, i+1))) |
| { |
| b = (unsigned char ) ((((unsigned int ) (b))*8)+(toOct (DynamicStrings_char (s, i+1)))); |
| i += 1; |
| if (isOct (DynamicStrings_char (s, i+1))) |
| { |
| b = (unsigned char ) ((((unsigned int ) (b))*8)+(toOct (DynamicStrings_char (s, i+1)))); |
| } |
| } |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar ((char ) (b)))); |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| /* copy escaped character. */ |
| d = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_InitStringChar (ch))); |
| } |
| i += 2; |
| j = i; |
| i = DynamicStrings_Index (s, '\\', (unsigned int ) (i)); |
| } |
| /* s := Assign(s, Mark(ConCat(d, Mark(Slice(s, j, 0))))) ; dont Mark(s) in the Slice as we Assign contents */ |
| s = DynamicStrings_ConCat (d, DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), j, 0))); |
| DSdbExit (s); |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| extern "C" void _M2_FormatStrings_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |
| |
| extern "C" void _M2_FormatStrings_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |