1 /* do not edit automatically generated by mc from FormatStrings. */
2 /* FormatStrings.mod provides a pseudo printf capability.
4 Copyright (C) 2005-2025 Free Software Foundation, Inc.
5 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
7 This file is part of GNU Modula-2.
9 GNU Modula-2 is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GNU Modula-2 is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
31 # if !defined (PROC_D)
33 typedef void (*PROC_t
) (void);
34 typedef struct { PROC_t proc
; } PROC
;
45 #if defined(__cplusplus)
49 #define _FormatStrings_C
51 #include "GFormatStrings.h"
52 # include "GDynamicStrings.h"
53 # include "GStringConvert.h"
60 Sprintf0 - returns a String containing, s, after it has had its
61 escape sequences translated.
64 extern "C" DynamicStrings_String
FormatStrings_Sprintf0 (DynamicStrings_String fmt
);
67 Sprintf1 - returns a String containing, s, together with encapsulated
68 entity, w. It only formats the first %s or %d with n.
71 extern "C" DynamicStrings_String
FormatStrings_Sprintf1 (DynamicStrings_String fmt
, const unsigned char *w_
, unsigned int _w_high
);
74 Sprintf2 - returns a string, s, which has been formatted.
77 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
);
80 Sprintf3 - returns a string, s, which has been formatted.
83 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
);
86 Sprintf4 - returns a string, s, which has been formatted.
89 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
);
92 HandleEscape - translates \a, \b, \e, \f,
93 , \r, \x[hex] \[octal] into
94 their respective ascii codes. It also converts \[any] into
95 a single [any] character.
98 extern "C" DynamicStrings_String
FormatStrings_HandleEscape (DynamicStrings_String s
);
104 static void doDSdbEnter (void);
110 static void doDSdbExit (DynamicStrings_String s
);
116 static void DSdbEnter (void);
122 static void DSdbExit (DynamicStrings_String s
);
125 IsDigit - returns TRUE if ch lies in the range: 0..9
128 static bool IsDigit (char ch
);
134 static void Cast (unsigned char *a
, unsigned int _a_high
, const unsigned char *b_
, unsigned int _b_high
);
140 static bool isHex (char ch
);
146 static unsigned int toHex (char ch
);
152 static unsigned int toOct (char ch
);
158 static bool isOct (char ch
);
161 FormatString - returns a String containing, s, together with encapsulated
162 entity, w. It only formats the first %s or %d or %u with n.
163 A new string is returned.
166 static DynamicStrings_String
FormatString (DynamicStrings_String fmt
, int *startpos
, DynamicStrings_String in
, const unsigned char *w_
, unsigned int _w_high
);
169 FormatString - returns a String containing, s, together with encapsulated
170 entity, w. It only formats the first %s or %d or %u with n.
171 A new string is returned.
174 static DynamicStrings_String
PerformFormatString (DynamicStrings_String fmt
, int *startpos
, DynamicStrings_String in
, const unsigned char *w_
, unsigned int _w_high
);
177 Copy - copies, fmt[start:end] -> in and returns in. Providing that start >= 0.
180 static DynamicStrings_String
Copy (DynamicStrings_String fmt
, DynamicStrings_String in
, int start
, int end
);
183 HandlePercent - pre-condition: s, is a string.
184 Post-condition: a new string is returned which is a copy of,
185 s, except %% is transformed into %.
188 static DynamicStrings_String
HandlePercent (DynamicStrings_String fmt
, DynamicStrings_String s
, int startpos
);
195 static void doDSdbEnter (void)
197 DynamicStrings_PushAllocation ();
205 static void doDSdbExit (DynamicStrings_String s
)
207 s
= DynamicStrings_PopAllocationExemption (true, s
);
215 static void DSdbEnter (void)
224 static void DSdbExit (DynamicStrings_String s
)
230 IsDigit - returns TRUE if ch lies in the range: 0..9
233 static bool IsDigit (char ch
)
235 return (ch
>= '0') && (ch
<= '9');
236 /* static analysis guarentees a RETURN statement will be used before here. */
237 __builtin_unreachable ();
245 static void Cast (unsigned char *a
, unsigned int _a_high
, const unsigned char *b_
, unsigned int _b_high
)
248 unsigned char b
[_b_high
+1];
250 /* make a local copy of each unbounded array. */
251 memcpy (b
, b_
, _b_high
+1);
253 if (_a_high
== _b_high
)
255 for (i
=0; i
<=_a_high
; i
++)
257 const_cast<unsigned char *>(a
)[i
] = b
[i
];
263 __builtin_unreachable ();
272 static bool isHex (char ch
)
274 return (((ch
>= '0') && (ch
<= '9')) || ((ch
>= 'A') && (ch
<= 'F'))) || ((ch
>= 'a') && (ch
<= 'f'));
275 /* static analysis guarentees a RETURN statement will be used before here. */
276 __builtin_unreachable ();
284 static unsigned int toHex (char ch
)
286 if ((ch
>= '0') && (ch
<= '9'))
288 return ((unsigned int) (ch
))- ((unsigned int) ('0'));
290 else if ((ch
>= 'A') && (ch
<= 'F'))
292 /* avoid dangling else. */
293 return ( ((unsigned int) (ch
))- ((unsigned int) ('A')))+10;
297 /* avoid dangling else. */
298 return ( ((unsigned int) (ch
))- ((unsigned int) ('a')))+10;
300 /* static analysis guarentees a RETURN statement will be used before here. */
301 __builtin_unreachable ();
309 static unsigned int toOct (char ch
)
311 return ((unsigned int) (ch
))- ((unsigned int) ('0'));
312 /* static analysis guarentees a RETURN statement will be used before here. */
313 __builtin_unreachable ();
321 static bool isOct (char ch
)
323 return (ch
>= '0') && (ch
<= '8');
324 /* static analysis guarentees a RETURN statement will be used before here. */
325 __builtin_unreachable ();
330 FormatString - returns a String containing, s, together with encapsulated
331 entity, w. It only formats the first %s or %d or %u with n.
332 A new string is returned.
335 static DynamicStrings_String
FormatString (DynamicStrings_String fmt
, int *startpos
, DynamicStrings_String in
, const unsigned char *w_
, unsigned int _w_high
)
337 DynamicStrings_String s
;
338 unsigned char w
[_w_high
+1];
340 /* make a local copy of each unbounded array. */
341 memcpy (w
, w_
, _w_high
+1);
344 if ((*startpos
) >= 0)
346 s
= PerformFormatString (fmt
, startpos
, in
, (const unsigned char *) w
, _w_high
);
350 s
= DynamicStrings_Dup (in
);
354 /* static analysis guarentees a RETURN statement will be used before here. */
355 __builtin_unreachable ();
360 FormatString - returns a String containing, s, together with encapsulated
361 entity, w. It only formats the first %s or %d or %u with n.
362 A new string is returned.
365 static DynamicStrings_String
PerformFormatString (DynamicStrings_String fmt
, int *startpos
, DynamicStrings_String in
, const unsigned char *w_
, unsigned int _w_high
)
376 DynamicStrings_String p
;
377 unsigned char w
[_w_high
+1];
379 /* make a local copy of each unbounded array. */
380 memcpy (w
, w_
, _w_high
+1);
382 while ((*startpos
) >= 0)
384 nextperc
= DynamicStrings_Index (fmt
, '%', static_cast<unsigned int> ((*startpos
)));
385 afterperc
= nextperc
;
389 if ((DynamicStrings_char (fmt
, afterperc
)) == '-')
398 ch
= DynamicStrings_char (fmt
, afterperc
);
410 width
= (width
*10)+((int ) ( ((unsigned int) (ch
))- ((unsigned int) ('0'))));
412 ch
= DynamicStrings_char (fmt
, afterperc
);
414 if ((ch
== 'c') || (ch
== 's'))
419 ch2
= static_cast<char> (w
[0]);
420 p
= DynamicStrings_ConCatChar (DynamicStrings_InitString ((const char *) "", 0), ch2
);
424 Cast ((unsigned char *) &p
, (sizeof (p
)-1), (const unsigned char *) w
, _w_high
);
425 p
= DynamicStrings_Dup (p
);
427 if ((width
> 0) && (((int ) (DynamicStrings_Length (p
))) < width
))
429 /* avoid gcc warning by using compound statement even if not strictly necessary. */
432 /* place trailing spaces after, p. */
433 p
= DynamicStrings_ConCat (p
, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " ", 1)), static_cast<unsigned int> (width
-((int ) (DynamicStrings_Length (p
)))))));
437 /* padd string, p, with leading spaces. */
438 p
= DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " ", 1)), static_cast<unsigned int> (width
-((int ) (DynamicStrings_Length (p
))))), DynamicStrings_Mark (p
));
441 /* include string, p, into, in. */
444 in
= DynamicStrings_ConCat (in
, DynamicStrings_Slice (fmt
, (*startpos
), nextperc
));
446 in
= DynamicStrings_ConCat (in
, p
);
447 (*startpos
) = afterperc
;
448 DSdbExit (static_cast<DynamicStrings_String
> (NULL
));
453 /* avoid dangling else. */
455 Cast ((unsigned char *) &c
, (sizeof (c
)-1), (const unsigned char *) w
, _w_high
);
456 in
= Copy (fmt
, in
, (*startpos
), nextperc
);
457 in
= DynamicStrings_ConCat (in
, StringConvert_IntegerToString (c
, static_cast<unsigned int> (width
), leader
, false, 10, false));
458 (*startpos
) = afterperc
;
459 DSdbExit (static_cast<DynamicStrings_String
> (NULL
));
464 /* avoid dangling else. */
466 Cast ((unsigned char *) &u
, (sizeof (u
)-1), (const unsigned char *) w
, _w_high
);
467 in
= DynamicStrings_ConCat (in
, DynamicStrings_Slice (fmt
, (*startpos
), nextperc
));
468 in
= DynamicStrings_ConCat (in
, StringConvert_CardinalToString (u
, static_cast<unsigned int> (width
), leader
, 16, true));
469 (*startpos
) = afterperc
;
470 DSdbExit (static_cast<DynamicStrings_String
> (NULL
));
475 /* avoid dangling else. */
477 Cast ((unsigned char *) &u
, (sizeof (u
)-1), (const unsigned char *) w
, _w_high
);
478 in
= DynamicStrings_ConCat (in
, DynamicStrings_Slice (fmt
, (*startpos
), nextperc
));
479 in
= DynamicStrings_ConCat (in
, StringConvert_CardinalToString (u
, static_cast<unsigned int> (width
), leader
, 10, false));
480 (*startpos
) = afterperc
;
481 DSdbExit (static_cast<DynamicStrings_String
> (NULL
));
486 /* avoid dangling else. */
488 /* copy format string. */
491 in
= DynamicStrings_ConCat (in
, DynamicStrings_Slice (fmt
, (*startpos
), nextperc
));
493 /* and the character after the %. */
494 in
= DynamicStrings_ConCat (in
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ch
)));
496 (*startpos
) = afterperc
;
501 DSdbExit (static_cast<DynamicStrings_String
> (NULL
));
505 DSdbExit (static_cast<DynamicStrings_String
> (NULL
));
507 /* static analysis guarentees a RETURN statement will be used before here. */
508 __builtin_unreachable ();
513 Copy - copies, fmt[start:end] -> in and returns in. Providing that start >= 0.
516 static DynamicStrings_String
Copy (DynamicStrings_String fmt
, DynamicStrings_String in
, int start
, int end
)
520 /* avoid gcc warning by using compound statement even if not strictly necessary. */
523 in
= DynamicStrings_ConCat (in
, DynamicStrings_Mark (DynamicStrings_Slice (fmt
, start
, end
)));
527 /* avoid dangling else. */
528 in
= DynamicStrings_ConCat (in
, DynamicStrings_Mark (DynamicStrings_Slice (fmt
, start
, 0)));
532 /* static analysis guarentees a RETURN statement will be used before here. */
533 __builtin_unreachable ();
538 HandlePercent - pre-condition: s, is a string.
539 Post-condition: a new string is returned which is a copy of,
540 s, except %% is transformed into %.
543 static DynamicStrings_String
HandlePercent (DynamicStrings_String fmt
, DynamicStrings_String s
, int startpos
)
547 if ((startpos
== ((int ) (DynamicStrings_Length (fmt
)))) || (startpos
< 0))
554 while ((startpos
>= 0) && (prevpos
< ((int ) (DynamicStrings_Length (fmt
)))))
556 startpos
= DynamicStrings_Index (fmt
, '%', static_cast<unsigned int> (startpos
));
557 if (startpos
>= prevpos
)
561 s
= DynamicStrings_ConCat (s
, DynamicStrings_Mark (DynamicStrings_Slice (fmt
, prevpos
, startpos
)));
564 if ((DynamicStrings_char (fmt
, startpos
)) == '%')
566 s
= DynamicStrings_ConCatChar (s
, '%');
572 if (prevpos
< ((int ) (DynamicStrings_Length (fmt
))))
574 s
= DynamicStrings_ConCat (s
, DynamicStrings_Mark (DynamicStrings_Slice (fmt
, prevpos
, 0)));
578 /* static analysis guarentees a RETURN statement will be used before here. */
579 __builtin_unreachable ();
584 Sprintf0 - returns a String containing, s, after it has had its
585 escape sequences translated.
588 extern "C" DynamicStrings_String
FormatStrings_Sprintf0 (DynamicStrings_String fmt
)
590 DynamicStrings_String s
;
593 fmt
= FormatStrings_HandleEscape (fmt
);
594 s
= HandlePercent (fmt
, DynamicStrings_InitString ((const char *) "", 0), 0);
597 /* static analysis guarentees a RETURN statement will be used before here. */
598 __builtin_unreachable ();
603 Sprintf1 - returns a String containing, s, together with encapsulated
604 entity, w. It only formats the first %s or %d with n.
607 extern "C" DynamicStrings_String
FormatStrings_Sprintf1 (DynamicStrings_String fmt
, const unsigned char *w_
, unsigned int _w_high
)
610 DynamicStrings_String s
;
611 unsigned char w
[_w_high
+1];
613 /* make a local copy of each unbounded array. */
614 memcpy (w
, w_
, _w_high
+1);
617 fmt
= FormatStrings_HandleEscape (fmt
);
619 s
= FormatString (fmt
, &i
, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w
, _w_high
);
620 s
= HandlePercent (fmt
, s
, i
);
623 /* static analysis guarentees a RETURN statement will be used before here. */
624 __builtin_unreachable ();
629 Sprintf2 - returns a string, s, which has been formatted.
632 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
)
635 DynamicStrings_String s
;
636 unsigned char w1
[_w1_high
+1];
637 unsigned char w2
[_w2_high
+1];
639 /* make a local copy of each unbounded array. */
640 memcpy (w1
, w1_
, _w1_high
+1);
641 memcpy (w2
, w2_
, _w2_high
+1);
644 fmt
= FormatStrings_HandleEscape (fmt
);
646 s
= FormatString (fmt
, &i
, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w1
, _w1_high
);
647 s
= FormatString (fmt
, &i
, s
, (const unsigned char *) w2
, _w2_high
);
648 s
= HandlePercent (fmt
, s
, i
);
651 /* static analysis guarentees a RETURN statement will be used before here. */
652 __builtin_unreachable ();
657 Sprintf3 - returns a string, s, which has been formatted.
660 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
)
663 DynamicStrings_String s
;
664 unsigned char w1
[_w1_high
+1];
665 unsigned char w2
[_w2_high
+1];
666 unsigned char w3
[_w3_high
+1];
668 /* make a local copy of each unbounded array. */
669 memcpy (w1
, w1_
, _w1_high
+1);
670 memcpy (w2
, w2_
, _w2_high
+1);
671 memcpy (w3
, w3_
, _w3_high
+1);
674 fmt
= FormatStrings_HandleEscape (fmt
);
676 s
= FormatString (fmt
, &i
, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w1
, _w1_high
);
677 s
= FormatString (fmt
, &i
, s
, (const unsigned char *) w2
, _w2_high
);
678 s
= FormatString (fmt
, &i
, s
, (const unsigned char *) w3
, _w3_high
);
679 s
= HandlePercent (fmt
, s
, i
);
682 /* static analysis guarentees a RETURN statement will be used before here. */
683 __builtin_unreachable ();
688 Sprintf4 - returns a string, s, which has been formatted.
691 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
)
694 DynamicStrings_String s
;
695 unsigned char w1
[_w1_high
+1];
696 unsigned char w2
[_w2_high
+1];
697 unsigned char w3
[_w3_high
+1];
698 unsigned char w4
[_w4_high
+1];
700 /* make a local copy of each unbounded array. */
701 memcpy (w1
, w1_
, _w1_high
+1);
702 memcpy (w2
, w2_
, _w2_high
+1);
703 memcpy (w3
, w3_
, _w3_high
+1);
704 memcpy (w4
, w4_
, _w4_high
+1);
707 fmt
= FormatStrings_HandleEscape (fmt
);
709 s
= FormatString (fmt
, &i
, DynamicStrings_InitString ((const char *) "", 0), (const unsigned char *) w1
, _w1_high
);
710 s
= FormatString (fmt
, &i
, s
, (const unsigned char *) w2
, _w2_high
);
711 s
= FormatString (fmt
, &i
, s
, (const unsigned char *) w3
, _w3_high
);
712 s
= FormatString (fmt
, &i
, s
, (const unsigned char *) w4
, _w4_high
);
713 s
= HandlePercent (fmt
, s
, i
);
716 /* static analysis guarentees a RETURN statement will be used before here. */
717 __builtin_unreachable ();
722 HandleEscape - translates \a, \b, \e, \f,
723 , \r, \x[hex] \[octal] into
724 their respective ascii codes. It also converts \[any] into
725 a single [any] character.
728 extern "C" DynamicStrings_String
FormatStrings_HandleEscape (DynamicStrings_String s
)
730 DynamicStrings_String d
;
737 d
= DynamicStrings_InitString ((const char *) "", 0);
738 i
= DynamicStrings_Index (s
, '\\', 0);
744 /* initially i might be zero which means the end of the string, which is not what we want. */
745 d
= DynamicStrings_ConCat (d
, DynamicStrings_Slice (s
, j
, i
));
747 ch
= DynamicStrings_char (s
, i
+1);
750 /* requires a bell. */
751 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_bel
)));
755 /* avoid dangling else. */
756 /* requires a backspace. */
757 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_bs
)));
761 /* avoid dangling else. */
762 /* requires a escape. */
763 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_esc
)));
767 /* avoid dangling else. */
768 /* requires a formfeed. */
769 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_ff
)));
773 /* avoid dangling else. */
774 /* requires a newline. */
775 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_nl
)));
779 /* avoid dangling else. */
780 /* requires a carriage return. */
781 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_cr
)));
785 /* avoid dangling else. */
786 /* requires a tab. */
787 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ASCII_tab
)));
791 /* avoid dangling else. */
793 if (isHex (DynamicStrings_char (s
, i
+1)))
795 b
= (unsigned char ) (toHex (DynamicStrings_char (s
, i
+1)));
797 if (isHex (DynamicStrings_char (s
, i
+1)))
799 b
= (unsigned char ) ((((unsigned int ) (b
))*0x010)+(toHex (DynamicStrings_char (s
, i
+1))));
800 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar ((char ) (b
))));
806 /* avoid dangling else. */
807 b
= (unsigned char ) (toOct (ch
));
809 if (isOct (DynamicStrings_char (s
, i
+1)))
811 b
= (unsigned char ) ((((unsigned int ) (b
))*8)+(toOct (DynamicStrings_char (s
, i
+1))));
813 if (isOct (DynamicStrings_char (s
, i
+1)))
815 b
= (unsigned char ) ((((unsigned int ) (b
))*8)+(toOct (DynamicStrings_char (s
, i
+1))));
818 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar ((char ) (b
))));
822 /* avoid dangling else. */
823 /* copy escaped character. */
824 d
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_InitStringChar (ch
)));
828 i
= DynamicStrings_Index (s
, '\\', (unsigned int ) (i
));
830 /* s := Assign(s, Mark(ConCat(d, Mark(Slice(s, j, 0))))) ; dont Mark(s) in the Slice as we Assign contents */
831 s
= DynamicStrings_ConCat (d
, DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s
), j
, 0)));
834 /* static analysis guarentees a RETURN statement will be used before here. */
835 __builtin_unreachable ();
838 extern "C" void _M2_FormatStrings_init (__attribute__((unused
)) int argc
, __attribute__((unused
)) char *argv
[], __attribute__((unused
)) char *envp
[])
842 extern "C" void _M2_FormatStrings_fini (__attribute__((unused
)) int argc
, __attribute__((unused
)) char *argv
[], __attribute__((unused
)) char *envp
[])