ReactOS  0.4.15-dev-5496-g599ba9c
trio.c
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15  *
16  *************************************************************************
17  *
18  * A note to trio contributors:
19  *
20  * Avoid heap allocation at all costs to ensure that the trio functions
21  * are async-safe. The exceptions are the printf/fprintf functions, which
22  * uses fputc, and the asprintf functions and the <alloc> modifier, which
23  * by design are required to allocate form the heap.
24  *
25  ************************************************************************/
26 
27 /*
28  * TODO:
29  * - Scan is probably too permissive about its modifiers.
30  * - C escapes in %#[] ?
31  * - Multibyte characters (done for format parsing, except scan groups)
32  * - Complex numbers? (C99 _Complex)
33  * - Boolean values? (C99 _Bool)
34  * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used
35  * to print the mantissa, e.g. NaN(0xc000000000000000)
36  * - Should we support the GNU %a alloc modifier? GNU has an ugly hack
37  * for %a, because C99 used %a for other purposes. If specified as
38  * %as or %a[ it is interpreted as the alloc modifier, otherwise as
39  * the C99 hex-float. This means that you cannot scan %as as a hex-float
40  * immediately followed by an 's'.
41  * - Scanning of collating symbols.
42  */
43 
44 /*************************************************************************
45  * Trio include files
46  */
47 #include "triodef.h"
48 #include "trio.h"
49 #include "triop.h"
50 #include "trionan.h"
51 #if !defined(TRIO_MINIMAL)
52 # include "triostr.h"
53 #endif
54 
55 /**************************************************************************
56  *
57  * Definitions
58  *
59  *************************************************************************/
60 
61 #include <math.h>
62 #include <limits.h>
63 #include <float.h>
64 
65 #if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \
66  || defined(USE_MULTIBYTE) || TRIO_WIDECHAR) \
67  && !defined(_WIN32_WCE)
68 # define TRIO_COMPILER_SUPPORTS_MULTIBYTE
69 # if !defined(MB_LEN_MAX)
70 # define MB_LEN_MAX 6
71 # endif
72 #endif
73 
74 #if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
75 # define TRIO_COMPILER_SUPPORTS_MSVC_INT
76 #endif
77 
78 #if defined(_WIN32_WCE)
79 #include <wincecompat.h>
80 #endif
81 
82 /*************************************************************************
83  * Generic definitions
84  */
85 
86 #if !(defined(DEBUG) || defined(NDEBUG))
87 # define NDEBUG
88 #endif
89 
90 #include <assert.h>
91 #include <ctype.h>
92 #if !defined(TRIO_COMPILER_SUPPORTS_C99)
93 # define isblank(x) (((x)==32) || ((x)==9))
94 #endif
95 #if defined(TRIO_COMPILER_ANCIENT)
96 # include <varargs.h>
97 #else
98 # include <stdarg.h>
99 #endif
100 #include <stddef.h>
101 #include <errno.h>
102 
103 #ifndef NULL
104 # define NULL 0
105 #endif
106 #define NIL ((char)0)
107 #ifndef FALSE
108 # define FALSE (1 == 0)
109 # define TRUE (! FALSE)
110 #endif
111 #define BOOLEAN_T int
112 
113 /* mincore() can be used for debugging purposes */
114 #define VALID(x) (NULL != (x))
115 
116 #if TRIO_ERRORS
117  /*
118  * Encode the error code and the position. This is decoded
119  * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
120  */
121 # define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
122 #else
123 # define TRIO_ERROR_RETURN(x,y) (-1)
124 #endif
125 
126 #ifndef VA_LIST_IS_ARRAY
127 #define TRIO_VA_LIST_PTR va_list *
128 #define TRIO_VA_LIST_ADDR(l) (&(l))
129 #define TRIO_VA_LIST_DEREF(l) (*(l))
130 #else
131 #define TRIO_VA_LIST_PTR va_list
132 #define TRIO_VA_LIST_ADDR(l) (l)
133 #define TRIO_VA_LIST_DEREF(l) (l)
134 #endif
135 
136 typedef unsigned long trio_flags_t;
137 
138 
139 /*************************************************************************
140  * Platform specific definitions
141  */
142 #if defined(TRIO_PLATFORM_UNIX) || defined(TRIO_PLATFORM_OS400)
143 # include <unistd.h>
144 # include <signal.h>
145 # include <locale.h>
146 # define USE_LOCALE
147 #endif /* TRIO_PLATFORM_UNIX */
148 #if defined(TRIO_PLATFORM_VMS)
149 # include <unistd.h>
150 #endif
151 #if defined(TRIO_PLATFORM_WIN32)
152 # if defined(_WIN32_WCE)
153 # include <wincecompat.h>
154 # else
155 # include <io.h>
156 # define read _read
157 # define write _write
158 # endif
159 #endif /* TRIO_PLATFORM_WIN32 */
160 
161 #if TRIO_WIDECHAR
162 # if defined(TRIO_COMPILER_SUPPORTS_ISO94)
163 # include <wchar.h>
164 # include <wctype.h>
165 typedef wchar_t trio_wchar_t;
166 typedef wint_t trio_wint_t;
167 # else
168 typedef char trio_wchar_t;
169 typedef int trio_wint_t;
170 # define WCONST(x) L ## x
171 # define WEOF EOF
172 # define iswalnum(x) isalnum(x)
173 # define iswalpha(x) isalpha(x)
174 # define iswblank(x) isblank(x)
175 # define iswcntrl(x) iscntrl(x)
176 # define iswdigit(x) isdigit(x)
177 # define iswgraph(x) isgraph(x)
178 # define iswlower(x) islower(x)
179 # define iswprint(x) isprint(x)
180 # define iswpunct(x) ispunct(x)
181 # define iswspace(x) isspace(x)
182 # define iswupper(x) isupper(x)
183 # define iswxdigit(x) isxdigit(x)
184 # endif
185 #endif
186 
187 
188 /*************************************************************************
189  * Compiler dependent definitions
190  */
191 
192 /* Support for long long */
193 #ifndef __cplusplus
194 # if !defined(USE_LONGLONG)
195 # if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
196 # define USE_LONGLONG
197 # elif defined(TRIO_COMPILER_SUNPRO)
198 # define USE_LONGLONG
199 # elif defined(_LONG_LONG) || defined(_LONGLONG)
200 # define USE_LONGLONG
201 # endif
202 # endif
203 #endif
204 
205 /* The extra long numbers */
206 #if defined(USE_LONGLONG)
207 typedef signed long long int trio_longlong_t;
208 typedef unsigned long long int trio_ulonglong_t;
209 #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
210 typedef signed __int64 trio_longlong_t;
211 typedef unsigned __int64 trio_ulonglong_t;
212 #else
213 typedef TRIO_SIGNED long int trio_longlong_t;
214 typedef unsigned long int trio_ulonglong_t;
215 #endif
216 
217 /* Maximal and fixed integer types */
218 #if defined(TRIO_COMPILER_SUPPORTS_C99) && !defined( __VMS )
219 # include <stdint.h>
220 typedef intmax_t trio_intmax_t;
221 typedef uintmax_t trio_uintmax_t;
222 typedef int8_t trio_int8_t;
223 typedef int16_t trio_int16_t;
224 typedef int32_t trio_int32_t;
225 typedef int64_t trio_int64_t;
226 #elif defined(TRIO_COMPILER_SUPPORTS_UNIX98) || defined( __VMS )
227 # include <inttypes.h>
228 #ifdef __VMS
229 typedef long long int intmax_t;
230 typedef unsigned long long int uintmax_t;
231 #endif
232 typedef intmax_t trio_intmax_t;
233 typedef uintmax_t trio_uintmax_t;
234 typedef int8_t trio_int8_t;
235 typedef int16_t trio_int16_t;
236 typedef int32_t trio_int32_t;
237 typedef int64_t trio_int64_t;
238 #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
241 typedef __int8 trio_int8_t;
242 typedef __int16 trio_int16_t;
243 typedef __int32 trio_int32_t;
244 typedef __int64 trio_int64_t;
245 #else
248 # if defined(TRIO_INT8_T)
249 typedef TRIO_INT8_T trio_int8_t;
250 # else
252 # endif
253 # if defined(TRIO_INT16_T)
254 typedef TRIO_INT16_T trio_int16_t;
255 # else
256 typedef TRIO_SIGNED short trio_int16_t;
257 # endif
258 # if defined(TRIO_INT32_T)
259 typedef TRIO_INT32_T trio_int32_t;
260 # else
262 # endif
263 # if defined(TRIO_INT64_T)
264 typedef TRIO_INT64_T trio_int64_t;
265 # else
267 # endif
268 #endif
269 
270 #if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \
271  || defined(TRIO_COMPILER_SUPPORTS_UNIX01))) \
272  && !defined(_WIN32_WCE)
273 # define floorl(x) floor((double)(x))
274 # define fmodl(x,y) fmod((double)(x),(double)(y))
275 # define powl(x,y) pow((double)(x),(double)(y))
276 #endif
277 
278 #define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
279 
280 /*************************************************************************
281  * Internal Definitions
282  */
283 
284 #ifndef DECIMAL_DIG
285 # define DECIMAL_DIG DBL_DIG
286 #endif
287 
288 /* Long double sizes */
289 #ifdef LDBL_DIG
290 # define MAX_MANTISSA_DIGITS LDBL_DIG
291 # define MAX_EXPONENT_DIGITS 4
292 # define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
293 #else
294 # define MAX_MANTISSA_DIGITS DECIMAL_DIG
295 # define MAX_EXPONENT_DIGITS 3
296 # define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
297 #endif
298 
299 #if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
300 # undef LDBL_DIG
301 # undef LDBL_MANT_DIG
302 # undef LDBL_EPSILON
303 # define LDBL_DIG DBL_DIG
304 # define LDBL_MANT_DIG DBL_MANT_DIG
305 # define LDBL_EPSILON DBL_EPSILON
306 #endif
307 
308 /* The maximal number of digits is for base 2 */
309 #define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
310 /* The width of a pointer. The number of bits in a hex digit is 4 */
311 #define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
312 
313 /* Infinite and Not-A-Number for floating-point */
314 #define INFINITE_LOWER "inf"
315 #define INFINITE_UPPER "INF"
316 #define LONG_INFINITE_LOWER "infinite"
317 #define LONG_INFINITE_UPPER "INFINITE"
318 #define NAN_LOWER "nan"
319 #define NAN_UPPER "NAN"
320 
321 #if !defined(HAVE_ISASCII) && !defined(isascii)
322 #ifndef __VMS
323 # define isascii(x) ((unsigned int)(x) < 128)
324 #endif
325 #endif
326 
327 /* Various constants */
328 enum {
331 
332  /* Flags. FLAGS_LAST must be less than ULONG_MAX */
366  /* Reused flags */
370  /* Compounded flags */
373 
375  NO_WIDTH = 0,
377  NO_SIZE = -1,
378 
379  /* Do not change these */
380  NO_BASE = -1,
381  MIN_BASE = 2,
382  MAX_BASE = 36,
386  BASE_HEX = 16,
387 
388  /* Maximal number of allowed parameters */
390  /* Maximal number of characters in class */
392 
393  /* Maximal string lengths for user-defined specifiers */
396 
397  /* Maximal length of locale separator strings */
399  /* Maximal number of integers in grouping */
401 
402  /* Initial size of asprintf buffer */
404 };
405 
406 #define NO_GROUPING ((int)CHAR_MAX)
407 
408 /* Fundamental formatting parameter types */
409 #define FORMAT_UNKNOWN 0
410 #define FORMAT_INT 1
411 #define FORMAT_DOUBLE 2
412 #define FORMAT_CHAR 3
413 #define FORMAT_STRING 4
414 #define FORMAT_POINTER 5
415 #define FORMAT_COUNT 6
416 #define FORMAT_PARAMETER 7
417 #define FORMAT_GROUP 8
418 #if TRIO_GNU
419 # define FORMAT_ERRNO 9
420 #endif
421 #if TRIO_EXTENSION
422 # define FORMAT_USER_DEFINED 10
423 #endif
424 
425 /* Character constants */
426 #define CHAR_IDENTIFIER '%'
427 #define CHAR_BACKSLASH '\\'
428 #define CHAR_QUOTE '\"'
429 #define CHAR_ADJUST ' '
430 
431 /* Character class expressions */
432 #define CLASS_ALNUM "[:alnum:]"
433 #define CLASS_ALPHA "[:alpha:]"
434 #define CLASS_BLANK "[:blank:]"
435 #define CLASS_CNTRL "[:cntrl:]"
436 #define CLASS_DIGIT "[:digit:]"
437 #define CLASS_GRAPH "[:graph:]"
438 #define CLASS_LOWER "[:lower:]"
439 #define CLASS_PRINT "[:print:]"
440 #define CLASS_PUNCT "[:punct:]"
441 #define CLASS_SPACE "[:space:]"
442 #define CLASS_UPPER "[:upper:]"
443 #define CLASS_XDIGIT "[:xdigit:]"
444 
445 /*
446  * SPECIFIERS:
447  *
448  *
449  * a Hex-float
450  * A Hex-float
451  * c Character
452  * C Widechar character (wint_t)
453  * d Decimal
454  * e Float
455  * E Float
456  * F Float
457  * F Float
458  * g Float
459  * G Float
460  * i Integer
461  * m Error message
462  * n Count
463  * o Octal
464  * p Pointer
465  * s String
466  * S Widechar string (wchar_t *)
467  * u Unsigned
468  * x Hex
469  * X Hex
470  * [] Group
471  * <> User-defined
472  *
473  * Reserved:
474  *
475  * D Binary Coded Decimal %D(length,precision) (OS/390)
476  */
477 #define SPECIFIER_CHAR 'c'
478 #define SPECIFIER_STRING 's'
479 #define SPECIFIER_DECIMAL 'd'
480 #define SPECIFIER_INTEGER 'i'
481 #define SPECIFIER_UNSIGNED 'u'
482 #define SPECIFIER_OCTAL 'o'
483 #define SPECIFIER_HEX 'x'
484 #define SPECIFIER_HEX_UPPER 'X'
485 #define SPECIFIER_FLOAT_E 'e'
486 #define SPECIFIER_FLOAT_E_UPPER 'E'
487 #define SPECIFIER_FLOAT_F 'f'
488 #define SPECIFIER_FLOAT_F_UPPER 'F'
489 #define SPECIFIER_FLOAT_G 'g'
490 #define SPECIFIER_FLOAT_G_UPPER 'G'
491 #define SPECIFIER_POINTER 'p'
492 #define SPECIFIER_GROUP '['
493 #define SPECIFIER_UNGROUP ']'
494 #define SPECIFIER_COUNT 'n'
495 #if TRIO_UNIX98
496 # define SPECIFIER_CHAR_UPPER 'C'
497 # define SPECIFIER_STRING_UPPER 'S'
498 #endif
499 #if TRIO_C99
500 # define SPECIFIER_HEXFLOAT 'a'
501 # define SPECIFIER_HEXFLOAT_UPPER 'A'
502 #endif
503 #if TRIO_GNU
504 # define SPECIFIER_ERRNO 'm'
505 #endif
506 #if TRIO_EXTENSION
507 # define SPECIFIER_BINARY 'b'
508 # define SPECIFIER_BINARY_UPPER 'B'
509 # define SPECIFIER_USER_DEFINED_BEGIN '<'
510 # define SPECIFIER_USER_DEFINED_END '>'
511 # define SPECIFIER_USER_DEFINED_SEPARATOR ':'
512 #endif
513 
514 /*
515  * QUALIFIERS:
516  *
517  *
518  * Numbers = d,i,o,u,x,X
519  * Float = a,A,e,E,f,F,g,G
520  * String = s
521  * Char = c
522  *
523  *
524  * 9$ Position
525  * Use the 9th parameter. 9 can be any number between 1 and
526  * the maximal argument
527  *
528  * 9 Width
529  * Set width to 9. 9 can be any number, but must not be postfixed
530  * by '$'
531  *
532  * h Short
533  * Numbers:
534  * (unsigned) short int
535  *
536  * hh Short short
537  * Numbers:
538  * (unsigned) char
539  *
540  * l Long
541  * Numbers:
542  * (unsigned) long int
543  * String:
544  * as the S specifier
545  * Char:
546  * as the C specifier
547  *
548  * ll Long Long
549  * Numbers:
550  * (unsigned) long long int
551  *
552  * L Long Double
553  * Float
554  * long double
555  *
556  * # Alternative
557  * Float:
558  * Decimal-point is always present
559  * String:
560  * non-printable characters are handled as \number
561  *
562  * Spacing
563  *
564  * + Sign
565  *
566  * - Alignment
567  *
568  * . Precision
569  *
570  * * Parameter
571  * print: use parameter
572  * scan: no parameter (ignore)
573  *
574  * q Quad
575  *
576  * Z size_t
577  *
578  * w Widechar
579  *
580  * ' Thousands/quote
581  * Numbers:
582  * Integer part grouped in thousands
583  * Binary numbers:
584  * Number grouped in nibbles (4 bits)
585  * String:
586  * Quoted string
587  *
588  * j intmax_t
589  * t prtdiff_t
590  * z size_t
591  *
592  * ! Sticky
593  * @ Parameter (for both print and scan)
594  *
595  * I n-bit Integer
596  * Numbers:
597  * The following options exists
598  * I8 = 8-bit integer
599  * I16 = 16-bit integer
600  * I32 = 32-bit integer
601  * I64 = 64-bit integer
602  */
603 #define QUALIFIER_POSITION '$'
604 #define QUALIFIER_SHORT 'h'
605 #define QUALIFIER_LONG 'l'
606 #define QUALIFIER_LONG_UPPER 'L'
607 #define QUALIFIER_ALTERNATIVE '#'
608 #define QUALIFIER_SPACE ' '
609 #define QUALIFIER_PLUS '+'
610 #define QUALIFIER_MINUS '-'
611 #define QUALIFIER_DOT '.'
612 #define QUALIFIER_STAR '*'
613 #define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
614 #if TRIO_C99
615 # define QUALIFIER_SIZE_T 'z'
616 # define QUALIFIER_PTRDIFF_T 't'
617 # define QUALIFIER_INTMAX_T 'j'
618 #endif
619 #if TRIO_BSD || TRIO_GNU
620 # define QUALIFIER_QUAD 'q'
621 #endif
622 #if TRIO_GNU
623 # define QUALIFIER_SIZE_T_UPPER 'Z'
624 #endif
625 #if TRIO_MISC
626 # define QUALIFIER_WIDECHAR 'w'
627 #endif
628 #if TRIO_MICROSOFT
629 # define QUALIFIER_FIXED_SIZE 'I'
630 #endif
631 #if TRIO_EXTENSION
632 # define QUALIFIER_QUOTE '\''
633 # define QUALIFIER_STICKY '!'
634 # define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
635 # define QUALIFIER_PARAM '@' /* Experimental */
636 # define QUALIFIER_COLON ':' /* For scanlists */
637 # define QUALIFIER_EQUAL '=' /* For scanlists */
638 # define QUALIFIER_ROUNDING_UPPER 'R'
639 #endif
640 
641 
642 /*************************************************************************
643  *
644  * Internal Structures
645  *
646  *************************************************************************/
647 
648 /* Parameters */
649 typedef struct {
650  /* An indication of which entry in the data union is used */
651  int type;
652  /* The flags */
654  /* The width qualifier */
655  int width;
656  /* The precision qualifier */
658  /* The base qualifier */
659  int base;
660  /* The size for the variable size qualifier */
661  int varsize;
662  /* The marker of the end of the specifier */
664  /* The data from the argument list */
665  union {
666  char *string;
667 #if TRIO_WIDECHAR
668  trio_wchar_t *wstring;
669 #endif
671  union {
674  } number;
675  double doubleNumber;
676  double *doublePointer;
680  } data;
681  /* For the user-defined specifier */
683  char user_data[MAX_USER_DATA];
685 
686 /* Container for customized functions */
687 typedef struct {
688  union {
689  trio_outstream_t out;
690  trio_instream_t in;
691  } stream;
693 } trio_custom_t;
694 
695 /* General trio "class" */
696 typedef struct _trio_class_t {
697  /*
698  * The function to write characters to a stream.
699  */
700  void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int));
701  /*
702  * The function to read characters from a stream.
703  */
704  void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
705  /*
706  * The current location in the stream.
707  */
709  /*
710  * The character currently being processed.
711  */
712  int current;
713  /*
714  * The number of characters that would have been written/read
715  * if there had been sufficient space.
716  */
718  /*
719  * The number of characters that are actually written/read.
720  * Processed and committed will only differ for the *nprintf
721  * and *nscanf functions.
722  */
724  /*
725  * The upper limit of characters that may be written/read.
726  */
727  int max;
728  /*
729  * The last output error that was detected.
730  */
731  int error;
732 } trio_class_t;
733 
734 /* References (for user-defined callbacks) */
735 typedef struct _trio_reference_t {
739 
740 /* Registered entries (for user-defined callbacks) */
741 typedef struct _trio_userdef_t {
743  trio_callback_t callback;
744  char *name;
746 
747 /*************************************************************************
748  *
749  * Internal Variables
750  *
751  *************************************************************************/
752 
753 static TRIO_CONST char rcsid[] = "@(#)$Id$";
754 
755 /*
756  * Need this to workaround a parser bug in HP C/iX compiler that fails
757  * to resolves macro definitions that includes type 'long double',
758  * e.g: va_arg(arg_ptr, long double)
759  */
760 #if defined(TRIO_PLATFORM_MPEIX)
761 static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
762 #endif
763 
764 static TRIO_CONST char internalNullString[] = "(nil)";
765 
766 #if defined(USE_LOCALE)
767 static struct lconv *internalLocaleValues = NULL;
768 #endif
769 
770 /*
771  * UNIX98 says "in a locale where the radix character is not defined,
772  * the radix character defaults to a period (.)"
773  */
776 static char internalDecimalPoint = '.';
780 
781 static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
782 static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
784 static int internalDigitArray[128];
785 #if TRIO_EXTENSION
788 #endif
789 
790 #if TRIO_EXTENSION
794 #endif
795 
796 
797 /*************************************************************************
798  *
799  * Internal Functions
800  *
801  ************************************************************************/
802 
803 #if defined(TRIO_MINIMAL)
804 # define TRIO_STRING_PUBLIC static
805 # include "triostr.c"
806 #endif /* defined(TRIO_MINIMAL) */
807 
808 /*************************************************************************
809  * TrioIsQualifier
810  *
811  * Description:
812  * Remember to add all new qualifiers to this function.
813  * QUALIFIER_POSITION must not be added.
814  */
816 TrioIsQualifier
817 TRIO_ARGS1((character),
818  TRIO_CONST char character)
819 {
820  /* QUALIFIER_POSITION is not included */
821  switch (character)
822  {
823  case '0': case '1': case '2': case '3': case '4':
824  case '5': case '6': case '7': case '8': case '9':
825  case QUALIFIER_PLUS:
826  case QUALIFIER_MINUS:
827  case QUALIFIER_SPACE:
828  case QUALIFIER_DOT:
829  case QUALIFIER_STAR:
831  case QUALIFIER_SHORT:
832  case QUALIFIER_LONG:
835 #if defined(QUALIFIER_SIZE_T)
836  case QUALIFIER_SIZE_T:
837 #endif
838 #if defined(QUALIFIER_PTRDIFF_T)
839  case QUALIFIER_PTRDIFF_T:
840 #endif
841 #if defined(QUALIFIER_INTMAX_T)
842  case QUALIFIER_INTMAX_T:
843 #endif
844 #if defined(QUALIFIER_QUAD)
845  case QUALIFIER_QUAD:
846 #endif
847 #if defined(QUALIFIER_SIZE_T_UPPER)
849 #endif
850 #if defined(QUALIFIER_WIDECHAR)
851  case QUALIFIER_WIDECHAR:
852 #endif
853 #if defined(QUALIFIER_QUOTE)
854  case QUALIFIER_QUOTE:
855 #endif
856 #if defined(QUALIFIER_STICKY)
857  case QUALIFIER_STICKY:
858 #endif
859 #if defined(QUALIFIER_VARSIZE)
860  case QUALIFIER_VARSIZE:
861 #endif
862 #if defined(QUALIFIER_PARAM)
863  case QUALIFIER_PARAM:
864 #endif
865 #if defined(QUALIFIER_FIXED_SIZE)
867 #endif
868 #if defined(QUALIFIER_ROUNDING_UPPER)
870 #endif
871  return TRUE;
872  default:
873  return FALSE;
874  }
875 }
876 
877 /*************************************************************************
878  * TrioSetLocale
879  */
880 #if defined(USE_LOCALE)
881 TRIO_PRIVATE void
882 TrioSetLocale(TRIO_NOARGS)
883 {
884  internalLocaleValues = (struct lconv *)localeconv();
885  if (internalLocaleValues)
886  {
887  if ((internalLocaleValues->decimal_point) &&
888  (internalLocaleValues->decimal_point[0] != NIL))
889  {
890  internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point);
892  {
893  internalDecimalPoint = internalLocaleValues->decimal_point[0];
894  }
895  else
896  {
898  trio_copy_max(internalDecimalPointString,
900  internalLocaleValues->decimal_point);
901  }
902  }
903  if ((internalLocaleValues->thousands_sep) &&
904  (internalLocaleValues->thousands_sep[0] != NIL))
905  {
906  trio_copy_max(internalThousandSeparator,
908  internalLocaleValues->thousands_sep);
910  }
911  if ((internalLocaleValues->grouping) &&
912  (internalLocaleValues->grouping[0] != NIL))
913  {
914  trio_copy_max(internalGrouping,
915  sizeof(internalGrouping),
916  internalLocaleValues->grouping);
917  }
918  }
919 }
920 #endif /* defined(USE_LOCALE) */
921 
922 TRIO_PRIVATE int
923 TrioCalcThousandSeparatorLength
925  int digits)
926 {
927 #if TRIO_EXTENSION
928  int count = 0;
929  int step = NO_GROUPING;
930  char *groupingPointer = internalGrouping;
931 
932  while (digits > 0)
933  {
934  if (*groupingPointer == CHAR_MAX)
935  {
936  /* Disable grouping */
937  break; /* while */
938  }
939  else if (*groupingPointer == 0)
940  {
941  /* Repeat last group */
942  if (step == NO_GROUPING)
943  {
944  /* Error in locale */
945  break; /* while */
946  }
947  }
948  else
949  {
950  step = *groupingPointer++;
951  }
952  if (digits > step)
954  digits -= step;
955  }
956  return count;
957 #else
958  return 0;
959 #endif
960 }
961 
963 TrioFollowedBySeparator
964 TRIO_ARGS1((position),
965  int position)
966 {
967 #if TRIO_EXTENSION
968  int step = 0;
969  char *groupingPointer = internalGrouping;
970 
971  position--;
972  if (position == 0)
973  return FALSE;
974  while (position > 0)
975  {
976  if (*groupingPointer == CHAR_MAX)
977  {
978  /* Disable grouping */
979  break; /* while */
980  }
981  else if (*groupingPointer != 0)
982  {
983  step = *groupingPointer++;
984  }
985  if (step == 0)
986  break;
987  position -= step;
988  }
989  return (position == 0);
990 #else
991  return FALSE;
992 #endif
993 }
994 
995 /*************************************************************************
996  * TrioGetPosition
997  *
998  * Get the %n$ position.
999  */
1000 TRIO_PRIVATE int
1001 TrioGetPosition
1002 TRIO_ARGS2((format, indexPointer),
1003  TRIO_CONST char *format,
1004  int *indexPointer)
1005 {
1006 #if TRIO_UNIX98
1007  char *tmpformat;
1008  int number = 0;
1009  int index = *indexPointer;
1010 
1011  number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
1012  index = (int)(tmpformat - format);
1013  if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
1014  {
1015  *indexPointer = index;
1016  /*
1017  * number is decreased by 1, because n$ starts from 1, whereas
1018  * the array it is indexing starts from 0.
1019  */
1020  return number - 1;
1021  }
1022 #endif
1023  return NO_POSITION;
1024 }
1025 
1026 #if TRIO_EXTENSION
1027 /*************************************************************************
1028  * TrioFindNamespace
1029  *
1030  * Find registered user-defined specifier.
1031  * The prev argument is used for optimization only.
1032  */
1034 TrioFindNamespace
1036  TRIO_CONST char *name,
1037  trio_userdef_t **prev)
1038 {
1039  trio_userdef_t *def;
1040 
1043 
1044  for (def = internalUserDef; def; def = def->next)
1045  {
1046  /* Case-sensitive string comparison */
1047  if (trio_equal_case(def->name, name))
1048  break;
1049 
1050  if (prev)
1051  *prev = def;
1052  }
1053 
1056 
1057  return def;
1058 }
1059 #endif
1060 
1061 /*************************************************************************
1062  * TrioPower
1063  *
1064  * Description:
1065  * Calculate pow(base, exponent), where number and exponent are integers.
1066  */
1068 TrioPower
1069 TRIO_ARGS2((number, exponent),
1070  int number,
1071  int exponent)
1072 {
1074 
1075  if (number == 10)
1076  {
1077  switch (exponent)
1078  {
1079  /* Speed up calculation of common cases */
1080  case 0:
1082  break;
1083  case 1:
1085  break;
1086  case 2:
1088  break;
1089  case 3:
1091  break;
1092  case 4:
1094  break;
1095  case 5:
1097  break;
1098  case 6:
1100  break;
1101  case 7:
1103  break;
1104  case 8:
1106  break;
1107  case 9:
1109  break;
1110  default:
1112  (trio_long_double_t)exponent);
1113  break;
1114  }
1115  }
1116  else
1117  {
1118  return powl((trio_long_double_t)number, (trio_long_double_t)exponent);
1119  }
1120  return result;
1121 }
1122 
1123 /*************************************************************************
1124  * TrioLogarithm
1125  */
1126 TRIO_PRIVATE double
1127 TrioLogarithm
1129  double number,
1130  int base)
1131 {
1132  double result;
1133 
1134  if (number <= 0.0)
1135  {
1136  /* xlC crashes on log(0) */
1137  result = (number == 0.0) ? trio_ninf() : trio_nan();
1138  }
1139  else
1140  {
1141  if (base == 10)
1142  {
1143  result = log10(number);
1144  }
1145  else
1146  {
1147  result = log10(number) / log10((double)base);
1148  }
1149  }
1150  return result;
1151 }
1152 
1153 /*************************************************************************
1154  * TrioLogarithmBase
1155  */
1156 TRIO_PRIVATE double
1157 TrioLogarithmBase
1159  int base)
1160 {
1161  switch (base)
1162  {
1163  case BASE_BINARY : return 1.0;
1164  case BASE_OCTAL : return 3.0;
1165  case BASE_DECIMAL: return 3.321928094887362345;
1166  case BASE_HEX : return 4.0;
1167  default : return TrioLogarithm((double)base, 2);
1168  }
1169 }
1170 
1171 /*************************************************************************
1172  * TrioParse
1173  *
1174  * Description:
1175  * Parse the format string
1176  */
1177 TRIO_PRIVATE int
1178 TrioParse
1179 TRIO_ARGS5((type, format, parameters, arglist, argarray),
1180  int type,
1181  TRIO_CONST char *format,
1182  trio_parameter_t *parameters,
1184  trio_pointer_t *argarray)
1185 {
1186  /* Count the number of times a parameter is referenced */
1187  unsigned short usedEntries[MAX_PARAMETERS];
1188  /* Parameter counters */
1189  int parameterPosition;
1190  int currentParam;
1191  int maxParam = -1;
1192  /* Utility variables */
1194  int width;
1195  int precision;
1196  int varsize;
1197  int base;
1198  int index; /* Index into formatting string */
1199  int dots; /* Count number of dots in modifier part */
1200  BOOLEAN_T positional; /* Does the specifier have a positional? */
1201  BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */
1202  /*
1203  * indices specifies the order in which the parameters must be
1204  * read from the va_args (this is necessary to handle positionals)
1205  */
1206  int indices[MAX_PARAMETERS];
1207  int pos = 0;
1208  /* Various variables */
1209  char ch;
1210 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1211  int charlen;
1212 #endif
1213  int save_errno;
1214  int i = -1;
1215  int num;
1216  char *tmpformat;
1217 
1218  /* One and only one of arglist and argarray must be used */
1219  assert((arglist != NULL) ^ (argarray != NULL));
1220 
1221  /*
1222  * The 'parameters' array is not initialized, but we need to
1223  * know which entries we have used.
1224  */
1225  memset(usedEntries, 0, sizeof(usedEntries));
1226 
1227  save_errno = errno;
1228  index = 0;
1229  parameterPosition = 0;
1230 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1231  (void)mblen(NULL, 0);
1232 #endif
1233 
1234  while (format[index])
1235  {
1236 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1237  if (! isascii(format[index]))
1238  {
1239  /*
1240  * Multibyte characters cannot be legal specifiers or
1241  * modifiers, so we skip over them.
1242  */
1243  charlen = mblen(&format[index], MB_LEN_MAX);
1244  index += (charlen > 0) ? charlen : 1;
1245  continue; /* while */
1246  }
1247 #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
1248  if (CHAR_IDENTIFIER == format[index++])
1249  {
1250  if (CHAR_IDENTIFIER == format[index])
1251  {
1252  index++;
1253  continue; /* while */
1254  }
1255 
1256  flags = FLAGS_NEW;
1257  dots = 0;
1258  currentParam = TrioGetPosition(format, &index);
1259  positional = (NO_POSITION != currentParam);
1260  if (!positional)
1261  {
1262  /* We have no positional, get the next counter */
1263  currentParam = parameterPosition;
1264  }
1265  if(currentParam >= MAX_PARAMETERS)
1266  {
1267  /* Bail out completely to make the error more obvious */
1269  }
1270 
1271  if (currentParam > maxParam)
1272  maxParam = currentParam;
1273 
1274  /* Default values */
1275  width = NO_WIDTH;
1277  base = NO_BASE;
1278  varsize = NO_SIZE;
1279 
1280  while (TrioIsQualifier(format[index]))
1281  {
1282  ch = format[index++];
1283 
1284  switch (ch)
1285  {
1286  case QUALIFIER_SPACE:
1287  flags |= FLAGS_SPACE;
1288  break;
1289 
1290  case QUALIFIER_PLUS:
1291  flags |= FLAGS_SHOWSIGN;
1292  break;
1293 
1294  case QUALIFIER_MINUS:
1296  flags &= ~FLAGS_NILPADDING;
1297  break;
1298 
1299  case QUALIFIER_ALTERNATIVE:
1301  break;
1302 
1303  case QUALIFIER_DOT:
1304  if (dots == 0) /* Precision */
1305  {
1306  dots++;
1307 
1308  /* Skip if no precision */
1309  if (QUALIFIER_DOT == format[index])
1310  break;
1311 
1312  /* After the first dot we have the precision */
1314  if ((QUALIFIER_STAR == format[index])
1315 #if defined(QUALIFIER_PARAM)
1316  || (QUALIFIER_PARAM == format[index])
1317 #endif
1318  )
1319  {
1320  index++;
1322 
1323  precision = TrioGetPosition(format, &index);
1324  if (precision == NO_POSITION)
1325  {
1326  parameterPosition++;
1327  if (positional)
1328  precision = parameterPosition;
1329  else
1330  {
1331  precision = currentParam;
1332  currentParam = precision + 1;
1333  }
1334  }
1335  else
1336  {
1337  if (! positional)
1338  currentParam = precision + 1;
1339  if (width > maxParam)
1340  maxParam = precision;
1341  }
1342  if (currentParam > maxParam)
1343  maxParam = currentParam;
1344  }
1345  else
1346  {
1347  precision = trio_to_long(&format[index],
1348  &tmpformat,
1349  BASE_DECIMAL);
1350  index = (int)(tmpformat - format);
1351  }
1352  }
1353  else if (dots == 1) /* Base */
1354  {
1355  dots++;
1356 
1357  /* After the second dot we have the base */
1358  flags |= FLAGS_BASE;
1359  if ((QUALIFIER_STAR == format[index])
1360 #if defined(QUALIFIER_PARAM)
1361  || (QUALIFIER_PARAM == format[index])
1362 #endif
1363  )
1364  {
1365  index++;
1367  base = TrioGetPosition(format, &index);
1368  if (base == NO_POSITION)
1369  {
1370  parameterPosition++;
1371  if (positional)
1372  base = parameterPosition;
1373  else
1374  {
1375  base = currentParam;
1376  currentParam = base + 1;
1377  }
1378  }
1379  else
1380  {
1381  if (! positional)
1382  currentParam = base + 1;
1383  if (base > maxParam)
1384  maxParam = base;
1385  }
1386  if (currentParam > maxParam)
1387  maxParam = currentParam;
1388  }
1389  else
1390  {
1391  base = trio_to_long(&format[index],
1392  &tmpformat,
1393  BASE_DECIMAL);
1394  if (base > MAX_BASE)
1396  index = (int)(tmpformat - format);
1397  }
1398  }
1399  else
1400  {
1402  }
1403  break; /* QUALIFIER_DOT */
1404 
1405 #if defined(QUALIFIER_PARAM)
1406  case QUALIFIER_PARAM:
1407  type = TYPE_PRINT;
1408  /* FALLTHROUGH */
1409 #endif
1410  case QUALIFIER_STAR:
1411  /* This has different meanings for print and scan */
1412  if (TYPE_PRINT == type)
1413  {
1414  /* Read with from parameter */
1416  width = TrioGetPosition(format, &index);
1417  if (width == NO_POSITION)
1418  {
1419  parameterPosition++;
1420  if (positional)
1421  width = parameterPosition;
1422  else
1423  {
1424  width = currentParam;
1425  currentParam = width + 1;
1426  }
1427  }
1428  else
1429  {
1430  if (! positional)
1431  currentParam = width + 1;
1432  if (width > maxParam)
1433  maxParam = width;
1434  }
1435  if (currentParam > maxParam)
1436  maxParam = currentParam;
1437  }
1438  else
1439  {
1440  /* Scan, but do not store result */
1441  flags |= FLAGS_IGNORE;
1442  }
1443 
1444  break; /* QUALIFIER_STAR */
1445 
1446  case '0':
1447  if (! (flags & FLAGS_LEFTADJUST))
1449  /* FALLTHROUGH */
1450  case '1': case '2': case '3': case '4':
1451  case '5': case '6': case '7': case '8': case '9':
1452  flags |= FLAGS_WIDTH;
1453  /* &format[index - 1] is used to "rewind" the read
1454  * character from format
1455  */
1456  width = trio_to_long(&format[index - 1],
1457  &tmpformat,
1458  BASE_DECIMAL);
1459  index = (int)(tmpformat - format);
1460  break;
1461 
1462  case QUALIFIER_SHORT:
1463  if (flags & FLAGS_SHORTSHORT)
1465  else if (flags & FLAGS_SHORT)
1467  else
1468  flags |= FLAGS_SHORT;
1469  break;
1470 
1471  case QUALIFIER_LONG:
1472  if (flags & FLAGS_QUAD)
1474  else if (flags & FLAGS_LONG)
1475  flags |= FLAGS_QUAD;
1476  else
1477  flags |= FLAGS_LONG;
1478  break;
1479 
1480  case QUALIFIER_LONG_UPPER:
1482  break;
1483 
1484 #if defined(QUALIFIER_SIZE_T)
1485  case QUALIFIER_SIZE_T:
1486  flags |= FLAGS_SIZE_T;
1487  /* Modify flags for later truncation of number */
1488  if (sizeof(size_t) == sizeof(trio_ulonglong_t))
1489  flags |= FLAGS_QUAD;
1490  else if (sizeof(size_t) == sizeof(long))
1491  flags |= FLAGS_LONG;
1492  break;
1493 #endif
1494 
1495 #if defined(QUALIFIER_PTRDIFF_T)
1496  case QUALIFIER_PTRDIFF_T:
1498  if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
1499  flags |= FLAGS_QUAD;
1500  else if (sizeof(ptrdiff_t) == sizeof(long))
1501  flags |= FLAGS_LONG;
1502  break;
1503 #endif
1504 
1505 #if defined(QUALIFIER_INTMAX_T)
1506  case QUALIFIER_INTMAX_T:
1507  flags |= FLAGS_INTMAX_T;
1508  if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
1509  flags |= FLAGS_QUAD;
1510  else if (sizeof(trio_intmax_t) == sizeof(long))
1511  flags |= FLAGS_LONG;
1512  break;
1513 #endif
1514 
1515 #if defined(QUALIFIER_QUAD)
1516  case QUALIFIER_QUAD:
1517  flags |= FLAGS_QUAD;
1518  break;
1519 #endif
1520 
1521 #if defined(QUALIFIER_FIXED_SIZE)
1522  case QUALIFIER_FIXED_SIZE:
1523  if (flags & FLAGS_FIXED_SIZE)
1525 
1529 
1530  if ((format[index] == '6') &&
1531  (format[index + 1] == '4'))
1532  {
1533  varsize = sizeof(trio_int64_t);
1534  index += 2;
1535  }
1536  else if ((format[index] == '3') &&
1537  (format[index + 1] == '2'))
1538  {
1539  varsize = sizeof(trio_int32_t);
1540  index += 2;
1541  }
1542  else if ((format[index] == '1') &&
1543  (format[index + 1] == '6'))
1544  {
1545  varsize = sizeof(trio_int16_t);
1546  index += 2;
1547  }
1548  else if (format[index] == '8')
1549  {
1550  varsize = sizeof(trio_int8_t);
1551  index++;
1552  }
1553  else
1555 
1557  break;
1558 #endif
1559 
1560 #if defined(QUALIFIER_WIDECHAR)
1561  case QUALIFIER_WIDECHAR:
1562  flags |= FLAGS_WIDECHAR;
1563  break;
1564 #endif
1565 
1566 #if defined(QUALIFIER_SIZE_T_UPPER)
1568  break;
1569 #endif
1570 
1571 #if defined(QUALIFIER_QUOTE)
1572  case QUALIFIER_QUOTE:
1573  flags |= FLAGS_QUOTE;
1574  break;
1575 #endif
1576 
1577 #if defined(QUALIFIER_STICKY)
1578  case QUALIFIER_STICKY:
1579  flags |= FLAGS_STICKY;
1580  gotSticky = TRUE;
1581  break;
1582 #endif
1583 
1584 #if defined(QUALIFIER_VARSIZE)
1585  case QUALIFIER_VARSIZE:
1587  parameterPosition++;
1588  if (positional)
1589  varsize = parameterPosition;
1590  else
1591  {
1592  varsize = currentParam;
1593  currentParam = varsize + 1;
1594  }
1595  if (currentParam > maxParam)
1596  maxParam = currentParam;
1597  break;
1598 #endif
1599 
1600 #if defined(QUALIFIER_ROUNDING_UPPER)
1602  flags |= FLAGS_ROUNDING;
1603  break;
1604 #endif
1605 
1606  default:
1607  /* Bail out completely to make the error more obvious */
1609  }
1610  } /* while qualifier */
1611 
1612  /*
1613  * Parameters only need the type and value. The value is
1614  * read later.
1615  */
1617  {
1618  usedEntries[width] += 1;
1619  parameters[pos].type = FORMAT_PARAMETER;
1620  parameters[pos].flags = 0;
1621  indices[width] = pos;
1622  width = pos++;
1623  }
1625  {
1626  usedEntries[precision] += 1;
1627  parameters[pos].type = FORMAT_PARAMETER;
1628  parameters[pos].flags = 0;
1629  indices[precision] = pos;
1630  precision = pos++;
1631  }
1633  {
1634  usedEntries[base] += 1;
1635  parameters[pos].type = FORMAT_PARAMETER;
1636  parameters[pos].flags = 0;
1637  indices[base] = pos;
1638  base = pos++;
1639  }
1641  {
1642  usedEntries[varsize] += 1;
1643  parameters[pos].type = FORMAT_PARAMETER;
1644  parameters[pos].flags = 0;
1645  indices[varsize] = pos;
1646  varsize = pos++;
1647  }
1648 
1649  indices[currentParam] = pos;
1650 
1651  switch (format[index++])
1652  {
1653 #if defined(SPECIFIER_CHAR_UPPER)
1654  case SPECIFIER_CHAR_UPPER:
1655  flags |= FLAGS_WIDECHAR;
1656  /* FALLTHROUGH */
1657 #endif
1658  case SPECIFIER_CHAR:
1659  if (flags & FLAGS_LONG)
1660  flags |= FLAGS_WIDECHAR;
1661  else if (flags & FLAGS_SHORT)
1662  flags &= ~FLAGS_WIDECHAR;
1663  parameters[pos].type = FORMAT_CHAR;
1664  break;
1665 
1666 #if defined(SPECIFIER_STRING_UPPER)
1668  flags |= FLAGS_WIDECHAR;
1669  /* FALLTHROUGH */
1670 #endif
1671  case SPECIFIER_STRING:
1672  if (flags & FLAGS_LONG)
1673  flags |= FLAGS_WIDECHAR;
1674  else if (flags & FLAGS_SHORT)
1675  flags &= ~FLAGS_WIDECHAR;
1676  parameters[pos].type = FORMAT_STRING;
1677  break;
1678 
1679  case SPECIFIER_GROUP:
1680  if (TYPE_SCAN == type)
1681  {
1682  int depth = 1;
1683  parameters[pos].type = FORMAT_GROUP;
1685  index++;
1686  if (format[index] == SPECIFIER_UNGROUP)
1687  index++;
1688  if (format[index] == QUALIFIER_MINUS)
1689  index++;
1690  /* Skip nested brackets */
1691  while (format[index] != NIL)
1692  {
1693  if (format[index] == SPECIFIER_GROUP)
1694  {
1695  depth++;
1696  }
1697  else if (format[index] == SPECIFIER_UNGROUP)
1698  {
1699  if (--depth <= 0)
1700  {
1701  index++;
1702  break;
1703  }
1704  }
1705  index++;
1706  }
1707  }
1708  break;
1709 
1710  case SPECIFIER_INTEGER:
1711  parameters[pos].type = FORMAT_INT;
1712  break;
1713 
1714  case SPECIFIER_UNSIGNED:
1715  flags |= FLAGS_UNSIGNED;
1716  parameters[pos].type = FORMAT_INT;
1717  break;
1718 
1719  case SPECIFIER_DECIMAL:
1720  /* Disable base modifier */
1722  base = BASE_DECIMAL;
1723  parameters[pos].type = FORMAT_INT;
1724  break;
1725 
1726  case SPECIFIER_OCTAL:
1727  flags |= FLAGS_UNSIGNED;
1729  base = BASE_OCTAL;
1730  parameters[pos].type = FORMAT_INT;
1731  break;
1732 
1733 #if defined(SPECIFIER_BINARY)
1735  flags |= FLAGS_UPPER;
1736  /* FALLTHROUGH */
1737  case SPECIFIER_BINARY:
1740  base = BASE_BINARY;
1741  parameters[pos].type = FORMAT_INT;
1742  break;
1743 #endif
1744 
1745  case SPECIFIER_HEX_UPPER:
1746  flags |= FLAGS_UPPER;
1747  /* FALLTHROUGH */
1748  case SPECIFIER_HEX:
1749  flags |= FLAGS_UNSIGNED;
1751  base = BASE_HEX;
1752  parameters[pos].type = FORMAT_INT;
1753  break;
1754 
1756  flags |= FLAGS_UPPER;
1757  /* FALLTHROUGH */
1758  case SPECIFIER_FLOAT_E:
1759  flags |= FLAGS_FLOAT_E;
1760  parameters[pos].type = FORMAT_DOUBLE;
1761  break;
1762 
1764  flags |= FLAGS_UPPER;
1765  /* FALLTHROUGH */
1766  case SPECIFIER_FLOAT_G:
1767  flags |= FLAGS_FLOAT_G;
1768  parameters[pos].type = FORMAT_DOUBLE;
1769  break;
1770 
1772  flags |= FLAGS_UPPER;
1773  /* FALLTHROUGH */
1774  case SPECIFIER_FLOAT_F:
1775  parameters[pos].type = FORMAT_DOUBLE;
1776  break;
1777 
1778  case SPECIFIER_POINTER:
1779  if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
1780  flags |= FLAGS_QUAD;
1781  else if (sizeof(trio_pointer_t) == sizeof(long))
1782  flags |= FLAGS_LONG;
1783  parameters[pos].type = FORMAT_POINTER;
1784  break;
1785 
1786  case SPECIFIER_COUNT:
1787  parameters[pos].type = FORMAT_COUNT;
1788  break;
1789 
1790 #if defined(SPECIFIER_HEXFLOAT)
1791 # if defined(SPECIFIER_HEXFLOAT_UPPER)
1793  flags |= FLAGS_UPPER;
1794  /* FALLTHROUGH */
1795 # endif
1796  case SPECIFIER_HEXFLOAT:
1797  base = BASE_HEX;
1798  parameters[pos].type = FORMAT_DOUBLE;
1799  break;
1800 #endif
1801 
1802 #if defined(FORMAT_ERRNO)
1803  case SPECIFIER_ERRNO:
1804  parameters[pos].type = FORMAT_ERRNO;
1805  break;
1806 #endif
1807 
1808 #if defined(SPECIFIER_USER_DEFINED_BEGIN)
1810  {
1811  unsigned int max;
1812  int without_namespace = TRUE;
1813 
1814  parameters[pos].type = FORMAT_USER_DEFINED;
1815  parameters[pos].user_name[0] = NIL;
1816  tmpformat = (char *)&format[index];
1817 
1818  while ((ch = format[index]))
1819  {
1820  index++;
1821  if (ch == SPECIFIER_USER_DEFINED_END)
1822  {
1823  if (without_namespace)
1824  {
1825  /* We must get the handle first */
1826  parameters[pos].type = FORMAT_PARAMETER;
1827  parameters[pos].indexAfterSpecifier = index;
1828  parameters[pos].flags = FLAGS_USER_DEFINED;
1829  /* Adjust parameters for insertion of new one */
1830  pos++;
1831  usedEntries[currentParam] += 1;
1832  parameters[pos].type = FORMAT_USER_DEFINED;
1833  currentParam++;
1834  indices[currentParam] = pos;
1835  if (currentParam > maxParam)
1836  maxParam = currentParam;
1837  }
1838  /* Copy the user data */
1839  max = (unsigned int)(&format[index] - tmpformat);
1840  if (max > MAX_USER_DATA)
1841  max = MAX_USER_DATA;
1842  trio_copy_max(parameters[pos].user_data,
1843  max,
1844  tmpformat);
1845  break; /* while */
1846  }
1848  {
1849  without_namespace = FALSE;
1850  /* Copy the namespace for later looking-up */
1851  max = (int)(&format[index] - tmpformat);
1852  if (max > MAX_USER_NAME)
1853  max = MAX_USER_NAME;
1854  trio_copy_max(parameters[pos].user_name,
1855  max,
1856  tmpformat);
1857  tmpformat = (char *)&format[index];
1858  }
1859  }
1860  if (ch != SPECIFIER_USER_DEFINED_END)
1862  }
1863  break;
1864 #endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
1865 
1866  default:
1867  /* Bail out completely to make the error more obvious */
1869  }
1870 
1871  /* Count the number of times this entry has been used */
1872  usedEntries[currentParam] += 1;
1873 
1874  /* Find last sticky parameters */
1875  if (gotSticky && !(flags & FLAGS_STICKY))
1876  {
1877  for (i = pos - 1; i >= 0; i--)
1878  {
1879  if (parameters[i].type == FORMAT_PARAMETER)
1880  continue;
1881  if ((parameters[i].flags & FLAGS_STICKY) &&
1882  (parameters[i].type == parameters[pos].type))
1883  {
1884  /* Do not overwrite current qualifiers */
1885  flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
1886  if (width == NO_WIDTH)
1887  width = parameters[i].width;
1888  if (precision == NO_PRECISION)
1889  precision = parameters[i].precision;
1890  if (base == NO_BASE)
1891  base = parameters[i].base;
1892  break;
1893  }
1894  }
1895  }
1896 
1897  parameters[pos].indexAfterSpecifier = index;
1898  parameters[pos].flags = flags;
1899  parameters[pos].width = width;
1900  parameters[pos].precision = precision;
1901  parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base;
1902  parameters[pos].varsize = varsize;
1903  pos++;
1904 
1905  if (! positional)
1906  parameterPosition++;
1907 
1908  } /* if identifier */
1909 
1910  } /* while format characters left */
1911 
1912  for (num = 0; num <= maxParam; num++)
1913  {
1914  if (usedEntries[num] != 1)
1915  {
1916  if (usedEntries[num] == 0) /* gap detected */
1917  return TRIO_ERROR_RETURN(TRIO_EGAP, num);
1918  else /* double references detected */
1920  }
1921 
1922  i = indices[num];
1923 
1924  /*
1925  * FORMAT_PARAMETERS are only present if they must be read,
1926  * so it makes no sense to check the ignore flag (besides,
1927  * the flags variable is not set for that particular type)
1928  */
1929  if ((parameters[i].type != FORMAT_PARAMETER) &&
1930  (parameters[i].flags & FLAGS_IGNORE))
1931  continue; /* for all arguments */
1932 
1933  /*
1934  * The stack arguments are read according to ANSI C89
1935  * default argument promotions:
1936  *
1937  * char = int
1938  * short = int
1939  * unsigned char = unsigned int
1940  * unsigned short = unsigned int
1941  * float = double
1942  *
1943  * In addition to the ANSI C89 these types are read (the
1944  * default argument promotions of C99 has not been
1945  * considered yet)
1946  *
1947  * long long
1948  * long double
1949  * size_t
1950  * ptrdiff_t
1951  * intmax_t
1952  */
1953  switch (parameters[i].type)
1954  {
1955  case FORMAT_GROUP:
1956  case FORMAT_STRING:
1957 #if TRIO_WIDECHAR
1958  if (flags & FLAGS_WIDECHAR)
1959  {
1960  parameters[i].data.wstring = (argarray == NULL)
1961  ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_wchar_t *)
1962  : (trio_wchar_t *)(argarray[num]);
1963  }
1964  else
1965 #endif
1966  {
1967  parameters[i].data.string = (argarray == NULL)
1968  ? va_arg(TRIO_VA_LIST_DEREF(arglist), char *)
1969  : (char *)(argarray[num]);
1970  }
1971  break;
1972 
1973 #if defined(FORMAT_USER_DEFINED)
1974  case FORMAT_USER_DEFINED:
1975 #endif
1976  case FORMAT_POINTER:
1977  case FORMAT_COUNT:
1978  case FORMAT_UNKNOWN:
1979  parameters[i].data.pointer = (argarray == NULL)
1981  : argarray[num];
1982  break;
1983 
1984  case FORMAT_CHAR:
1985  case FORMAT_INT:
1986  if (TYPE_SCAN == type)
1987  {
1988  if (argarray == NULL)
1989  parameters[i].data.pointer =
1991  else
1992  {
1993  if (parameters[i].type == FORMAT_CHAR)
1994  parameters[i].data.pointer =
1995  (trio_pointer_t)((char *)argarray[num]);
1996  else if (parameters[i].flags & FLAGS_SHORT)
1997  parameters[i].data.pointer =
1998  (trio_pointer_t)((short *)argarray[num]);
1999  else
2000  parameters[i].data.pointer =
2001  (trio_pointer_t)((int *)argarray[num]);
2002  }
2003  }
2004  else
2005  {
2006 #if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
2007  if (parameters[i].flags
2009  {
2010  if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
2011  {
2012  /*
2013  * Variable sizes are mapped onto the fixed sizes, in
2014  * accordance with integer promotion.
2015  *
2016  * Please note that this may not be portable, as we
2017  * only guess the size, not the layout of the numbers.
2018  * For example, if int is little-endian, and long is
2019  * big-endian, then this will fail.
2020  */
2021  varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
2022  }
2023  else
2024  {
2025  /* Used for the I<bits> modifiers */
2026  varsize = parameters[i].varsize;
2027  }
2028  parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
2029 
2030  if (varsize <= (int)sizeof(int))
2031  ;
2032  else if (varsize <= (int)sizeof(long))
2033  parameters[i].flags |= FLAGS_LONG;
2034 #if defined(QUALIFIER_INTMAX_T)
2035  else if (varsize <= (int)sizeof(trio_longlong_t))
2036  parameters[i].flags |= FLAGS_QUAD;
2037  else
2038  parameters[i].flags |= FLAGS_INTMAX_T;
2039 #else
2040  else
2041  parameters[i].flags |= FLAGS_QUAD;
2042 #endif
2043  }
2044 #endif /* defined(QUALIFIER_VARSIZE) */
2045 #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
2046  if (parameters[i].flags & FLAGS_SIZE_T)
2047  parameters[i].data.number.as_unsigned = (argarray == NULL)
2049  : (trio_uintmax_t)(*((size_t *)argarray[num]));
2050  else
2051 #endif
2052 #if defined(QUALIFIER_PTRDIFF_T)
2053  if (parameters[i].flags & FLAGS_PTRDIFF_T)
2054  parameters[i].data.number.as_unsigned = (argarray == NULL)
2056  : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
2057  else
2058 #endif
2059 #if defined(QUALIFIER_INTMAX_T)
2060  if (parameters[i].flags & FLAGS_INTMAX_T)
2061  parameters[i].data.number.as_unsigned = (argarray == NULL)
2063  : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
2064  else
2065 #endif
2066  if (parameters[i].flags & FLAGS_QUAD)
2067  parameters[i].data.number.as_unsigned = (argarray == NULL)
2069  : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
2070  else if (parameters[i].flags & FLAGS_LONG)
2071  parameters[i].data.number.as_unsigned = (argarray == NULL)
2073  : (trio_uintmax_t)(*((long *)argarray[num]));
2074  else
2075  {
2076  if (argarray == NULL)
2077  parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int);
2078  else
2079  {
2080  if (parameters[i].type == FORMAT_CHAR)
2081  parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
2082  else if (parameters[i].flags & FLAGS_SHORT)
2083  parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
2084  else
2085  parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
2086  }
2087  }
2088  }
2089  break;
2090 
2091  case FORMAT_PARAMETER:
2092  /*
2093  * The parameter for the user-defined specifier is a pointer,
2094  * whereas the rest (width, precision, base) uses an integer.
2095  */
2096  if (parameters[i].flags & FLAGS_USER_DEFINED)
2097  parameters[i].data.pointer = (argarray == NULL)
2099  : argarray[num];
2100  else
2101  parameters[i].data.number.as_unsigned = (argarray == NULL)
2103  : (trio_uintmax_t)(*((int *)argarray[num]));
2104  break;
2105 
2106  case FORMAT_DOUBLE:
2107  if (TYPE_SCAN == type)
2108  {
2109  if (parameters[i].flags & FLAGS_LONGDOUBLE)
2110  parameters[i].data.longdoublePointer = (argarray == NULL)
2112  : (trio_long_double_t *)argarray[num];
2113  else
2114  {
2115  if (parameters[i].flags & FLAGS_LONG)
2116  parameters[i].data.doublePointer = (argarray == NULL)
2117  ? va_arg(TRIO_VA_LIST_DEREF(arglist), double *)
2118  : (double *)argarray[num];
2119  else
2120  parameters[i].data.doublePointer = (argarray == NULL)
2121  ? (double *)va_arg(TRIO_VA_LIST_DEREF(arglist), float *)
2122  : (double *)((float *)argarray[num]);
2123  }
2124  }
2125  else
2126  {
2127  if (parameters[i].flags & FLAGS_LONGDOUBLE)
2128  parameters[i].data.longdoubleNumber = (argarray == NULL)
2130  : (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
2131  else
2132  {
2133  if (argarray == NULL)
2134  parameters[i].data.longdoubleNumber =
2136  else
2137  {
2138  if (parameters[i].flags & FLAGS_SHORT)
2139  parameters[i].data.longdoubleNumber =
2140  (trio_long_double_t)(*((float *)argarray[num]));
2141  else
2142  parameters[i].data.longdoubleNumber =
2143  (trio_long_double_t)(*((double *)argarray[num]));
2144  }
2145  }
2146  }
2147  break;
2148 
2149 #if defined(FORMAT_ERRNO)
2150  case FORMAT_ERRNO:
2151  parameters[i].data.errorNumber = save_errno;
2152  break;
2153 #endif
2154 
2155  default:
2156  break;
2157  }
2158  } /* for all specifiers */
2159  return num;
2160 }
2161 
2162 
2163 /*************************************************************************
2164  *
2165  * FORMATTING
2166  *
2167  ************************************************************************/
2168 
2169 
2170 /*************************************************************************
2171  * TrioWriteNumber
2172  *
2173  * Description:
2174  * Output a number.
2175  * The complexity of this function is a result of the complexity
2176  * of the dependencies of the flags.
2177  */
2178 TRIO_PRIVATE void
2179 TrioWriteNumber
2181  trio_class_t *self,
2184  int width,
2185  int precision,
2186  int base)
2187 {
2188  BOOLEAN_T isNegative;
2189  BOOLEAN_T isNumberZero;
2190  BOOLEAN_T isPrecisionZero;
2191  BOOLEAN_T ignoreNumber;
2193  char *bufferend;
2194  char *pointer;
2195  TRIO_CONST char *digits;
2196  int i;
2197  int length;
2198  char *p;
2199  int count;
2200 
2201  assert(VALID(self));
2202  assert(VALID(self->OutStream));
2203  assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
2204 
2206  if (base == NO_BASE)
2207  base = BASE_DECIMAL;
2208 
2209  isNumberZero = (number == 0);
2210  isPrecisionZero = (precision == 0);
2211  ignoreNumber = (isNumberZero
2212  && isPrecisionZero
2213  && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL)));
2214 
2215  if (flags & FLAGS_UNSIGNED)
2216  {
2217  isNegative = FALSE;
2218  flags &= ~FLAGS_SHOWSIGN;
2219  }
2220  else
2221  {
2222  isNegative = ((trio_intmax_t)number < 0);
2223  if (isNegative)
2224  number = -((trio_intmax_t)number);
2225  }
2226 
2227  if (flags & FLAGS_QUAD)
2228  number &= (trio_ulonglong_t)-1;
2229  else if (flags & FLAGS_LONG)
2230  number &= (unsigned long)-1;
2231  else
2232  number &= (unsigned int)-1;
2233 
2234  /* Build number */
2235  pointer = bufferend = &buffer[sizeof(buffer) - 1];
2236  *pointer-- = NIL;
2237  for (i = 1; i < (int)sizeof(buffer); i++)
2238  {
2239  *pointer-- = digits[number % base];
2240  number /= base;
2241  if (number == 0)
2242  break;
2243 
2244  if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
2245  {
2246  /*
2247  * We are building the number from the least significant
2248  * to the most significant digit, so we have to copy the
2249  * thousand separator backwards
2250  */
2252  if (((int)(pointer - buffer) - length) > 0)
2253  {
2255  while (length-- > 0)
2256  *pointer-- = *p--;
2257  }
2258  }
2259  }
2260 
2261  if (! ignoreNumber)
2262  {
2263  /* Adjust width */
2264  width -= (bufferend - pointer) - 1;
2265  }
2266 
2267  /* Adjust precision */
2268  if (NO_PRECISION != precision)
2269  {
2270  precision -= (bufferend - pointer) - 1;
2271  if (precision < 0)
2272  precision = 0;
2274  }
2275 
2276  /* Calculate padding */
2277  count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION)))
2278  ? precision
2279  : 0;
2280 
2281  /* Adjust width further */
2282  if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
2283  width--;
2284  if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
2285  {
2286  switch (base)
2287  {
2288  case BASE_BINARY:
2289  case BASE_HEX:
2290  width -= 2;
2291  break;
2292  case BASE_OCTAL:
2293  if (!(flags & FLAGS_NILPADDING) || (count == 0))
2294  width--;
2295  break;
2296  default:
2297  break;
2298  }
2299  }
2300 
2301  /* Output prefixes spaces if needed */
2302  if (! ((flags & FLAGS_LEFTADJUST) ||
2304  {
2305  while (width-- > count)
2306  self->OutStream(self, CHAR_ADJUST);
2307  }
2308 
2309  /* width has been adjusted for signs and alternatives */
2310  if (isNegative)
2311  self->OutStream(self, '-');
2312  else if (flags & FLAGS_SHOWSIGN)
2313  self->OutStream(self, '+');
2314  else if (flags & FLAGS_SPACE)
2315  self->OutStream(self, ' ');
2316 
2317  /* Prefix is not written when the value is zero */
2318  if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
2319  {
2320  switch (base)
2321  {
2322  case BASE_BINARY:
2323  self->OutStream(self, '0');
2324  self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b');
2325  break;
2326 
2327  case BASE_OCTAL:
2328  if (!(flags & FLAGS_NILPADDING) || (count == 0))
2329  self->OutStream(self, '0');
2330  break;
2331 
2332  case BASE_HEX:
2333  self->OutStream(self, '0');
2334  self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
2335  break;
2336 
2337  default:
2338  break;
2339  } /* switch base */
2340  }
2341 
2342  /* Output prefixed zero padding if needed */
2343  if (flags & FLAGS_NILPADDING)
2344  {
2345  if (precision == NO_PRECISION)
2346  precision = width;
2347  while (precision-- > 0)
2348  {
2349  self->OutStream(self, '0');
2350  width--;
2351  }
2352  }
2353 
2354  if (! ignoreNumber)
2355  {
2356  /* Output the number itself */
2357  while (*(++pointer))
2358  {
2359  self->OutStream(self, *pointer);
2360  }
2361  }
2362 
2363  /* Output trailing spaces if needed */
2364  if (flags & FLAGS_LEFTADJUST)
2365  {
2366  while (width-- > 0)
2367  self->OutStream(self, CHAR_ADJUST);
2368  }
2369 }
2370 
2371 /*************************************************************************
2372  * TrioWriteStringCharacter
2373  *
2374  * Description:
2375  * Output a single character of a string
2376  */
2377 TRIO_PRIVATE void
2378 TrioWriteStringCharacter
2379 TRIO_ARGS3((self, ch, flags),
2380  trio_class_t *self,
2381  int ch,
2383 {
2384  if (flags & FLAGS_ALTERNATIVE)
2385  {
2386  if (! isprint(ch))
2387  {
2388  /*
2389  * Non-printable characters are converted to C escapes or
2390  * \number, if no C escape exists.
2391  */
2392  self->OutStream(self, CHAR_BACKSLASH);
2393  switch (ch)
2394  {
2395  case '\007': self->OutStream(self, 'a'); break;
2396  case '\b': self->OutStream(self, 'b'); break;
2397  case '\f': self->OutStream(self, 'f'); break;
2398  case '\n': self->OutStream(self, 'n'); break;
2399  case '\r': self->OutStream(self, 'r'); break;
2400  case '\t': self->OutStream(self, 't'); break;
2401  case '\v': self->OutStream(self, 'v'); break;
2402  case '\\': self->OutStream(self, '\\'); break;
2403  default:
2404  self->OutStream(self, 'x');
2405  TrioWriteNumber(self, (trio_uintmax_t)ch,
2407  2, 2, BASE_HEX);
2408  break;
2409  }
2410  }
2411  else if (ch == CHAR_BACKSLASH)
2412  {
2413  self->OutStream(self, CHAR_BACKSLASH);
2414  self->OutStream(self, CHAR_BACKSLASH);
2415  }
2416  else
2417  {
2418  self->OutStream(self, ch);
2419  }
2420  }
2421  else
2422  {
2423  self->OutStream(self, ch);
2424  }
2425 }
2426 
2427 /*************************************************************************
2428  * TrioWriteString
2429  *
2430  * Description:
2431  * Output a string
2432  */
2433 TRIO_PRIVATE void
2434 TrioWriteString
2435 TRIO_ARGS5((self, string, flags, width, precision),
2436  trio_class_t *self,
2437  TRIO_CONST char *string,
2439  int width,
2440  int precision)
2441 {
2442  int length;
2443  int ch;
2444 
2445  assert(VALID(self));
2446  assert(VALID(self->OutStream));
2447 
2448  if (string == NULL)
2449  {
2450  string = internalNullString;
2451  length = sizeof(internalNullString) - 1;
2452  /* Disable quoting for the null pointer */
2453  flags &= (~FLAGS_QUOTE);
2454  width = 0;
2455  }
2456  else
2457  {
2458  length = trio_length(string);
2459  }
2460  if ((NO_PRECISION != precision) &&
2461  (precision < length))
2462  {
2463  length = precision;
2464  }
2465  width -= length;
2466 
2467  if (flags & FLAGS_QUOTE)
2468  self->OutStream(self, CHAR_QUOTE);
2469 
2470  if (! (flags & FLAGS_LEFTADJUST))
2471  {
2472  while (width-- > 0)
2473  self->OutStream(self, CHAR_ADJUST);
2474  }
2475 
2476  while (length-- > 0)
2477  {
2478  /* The ctype parameters must be an unsigned char (or EOF) */
2479  ch = (int)((unsigned char)(*string++));
2480  TrioWriteStringCharacter(self, ch, flags);
2481  }
2482 
2483  if (flags & FLAGS_LEFTADJUST)
2484  {
2485  while (width-- > 0)
2486  self->OutStream(self, CHAR_ADJUST);
2487  }
2488  if (flags & FLAGS_QUOTE)
2489  self->OutStream(self, CHAR_QUOTE);
2490 }
2491 
2492 /*************************************************************************
2493  * TrioWriteWideStringCharacter
2494  *
2495  * Description:
2496  * Output a wide string as a multi-byte sequence
2497  */
2498 #if TRIO_WIDECHAR
2499 TRIO_PRIVATE int
2500 TrioWriteWideStringCharacter
2501 TRIO_ARGS4((self, wch, flags, width),
2502  trio_class_t *self,
2503  trio_wchar_t wch,
2505  int width)
2506 {
2507  int size;
2508  int i;
2509  int ch;
2510  char *string;
2511  char buffer[MB_LEN_MAX + 1];
2512 
2513  if (width == NO_WIDTH)
2514  width = sizeof(buffer);
2515 
2516  size = wctomb(buffer, wch);
2517  if ((size <= 0) || (size > width) || (buffer[0] == NIL))
2518  return 0;
2519 
2520  string = buffer;
2521  i = size;
2522  while ((width >= i) && (width-- > 0) && (i-- > 0))
2523  {
2524  /* The ctype parameters must be an unsigned char (or EOF) */
2525  ch = (int)((unsigned char)(*string++));
2526  TrioWriteStringCharacter(self, ch, flags);
2527  }
2528  return size;
2529 }
2530 #endif /* TRIO_WIDECHAR */
2531 
2532 /*************************************************************************
2533  * TrioWriteWideString
2534  *
2535  * Description:
2536  * Output a wide character string as a multi-byte string
2537  */
2538 #if TRIO_WIDECHAR
2539 TRIO_PRIVATE void
2540 TrioWriteWideString
2541 TRIO_ARGS5((self, wstring, flags, width, precision),
2542  trio_class_t *self,
2543  TRIO_CONST trio_wchar_t *wstring,
2545  int width,
2546  int precision)
2547 {
2548  int length;
2549  int size;
2550 
2551  assert(VALID(self));
2552  assert(VALID(self->OutStream));
2553 
2554 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2555  (void)mblen(NULL, 0);
2556 #endif
2557 
2558  if (wstring == NULL)
2559  {
2560  TrioWriteString(self, NULL, flags, width, precision);
2561  return;
2562  }
2563 
2564  if (NO_PRECISION == precision)
2565  {
2566  length = INT_MAX;
2567  }
2568  else
2569  {
2570  length = precision;
2571  width -= length;
2572  }
2573 
2574  if (flags & FLAGS_QUOTE)
2575  self->OutStream(self, CHAR_QUOTE);
2576 
2577  if (! (flags & FLAGS_LEFTADJUST))
2578  {
2579  while (width-- > 0)
2580  self->OutStream(self, CHAR_ADJUST);
2581  }
2582 
2583  while (length > 0)
2584  {
2585  size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
2586  if (size == 0)
2587  break; /* while */
2588  length -= size;
2589  }
2590 
2591  if (flags & FLAGS_LEFTADJUST)
2592  {
2593  while (width-- > 0)
2594  self->OutStream(self, CHAR_ADJUST);
2595  }
2596  if (flags & FLAGS_QUOTE)
2597  self->OutStream(self, CHAR_QUOTE);
2598 }
2599 #endif /* TRIO_WIDECHAR */
2600 
2601 /*************************************************************************
2602  * TrioWriteDouble
2603  *
2604  * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm
2605  *
2606  * "5.2.4.2.2 paragraph #4
2607  *
2608  * The accuracy [...] is implementation defined, as is the accuracy
2609  * of the conversion between floating-point internal representations
2610  * and string representations performed by the library routine in
2611  * <stdio.h>"
2612  */
2613 /* FIXME: handle all instances of constant long-double number (L)
2614  * and *l() math functions.
2615  */
2616 TRIO_PRIVATE void
2617 TrioWriteDouble
2619  trio_class_t *self,
2622  int width,
2623  int precision,
2624  int base)
2625 {
2626  trio_long_double_t integerNumber;
2627  trio_long_double_t fractionNumber;
2628  trio_long_double_t workNumber;
2629  int integerDigits;
2630  int fractionDigits;
2631  int exponentDigits;
2632  int baseDigits;
2633  int integerThreshold;
2634  int fractionThreshold;
2635  int expectedWidth;
2636  int exponent = 0;
2637  unsigned int uExponent = 0;
2638  int exponentBase;
2639  trio_long_double_t dblBase;
2640  trio_long_double_t dblIntegerBase;
2641  trio_long_double_t dblFractionBase;
2642  trio_long_double_t integerAdjust;
2643  trio_long_double_t fractionAdjust;
2644  BOOLEAN_T isNegative;
2645  BOOLEAN_T isExponentNegative = FALSE;
2646  BOOLEAN_T requireTwoDigitExponent;
2647  BOOLEAN_T isHex;
2648  TRIO_CONST char *digits;
2649  char *groupingPointer;
2650  int i;
2651  int index;
2652  BOOLEAN_T hasOnlyZeroes;
2653  int zeroes = 0;
2654  register int trailingZeroes;
2655  BOOLEAN_T keepTrailingZeroes;
2656  BOOLEAN_T keepDecimalPoint;
2657  trio_long_double_t epsilon;
2658 
2659  assert(VALID(self));
2660  assert(VALID(self->OutStream));
2661  assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
2662 
2663  /* Determine sign and look for special quantities */
2664  switch (trio_fpclassify_and_signbit(number, &isNegative))
2665  {
2666  case TRIO_FP_NAN:
2667  TrioWriteString(self,
2668  (flags & FLAGS_UPPER)
2669  ? NAN_UPPER
2670  : NAN_LOWER,
2671  flags, width, precision);
2672  return;
2673 
2674  case TRIO_FP_INFINITE:
2675  if (isNegative)
2676  {
2677  /* Negative infinity */
2678  TrioWriteString(self,
2679  (flags & FLAGS_UPPER)
2680  ? "-" INFINITE_UPPER
2681  : "-" INFINITE_LOWER,
2682  flags, width, precision);
2683  return;
2684  }
2685  else
2686  {
2687  /* Positive infinity */
2688  TrioWriteString(self,
2689  (flags & FLAGS_UPPER)
2690  ? INFINITE_UPPER
2691  : INFINITE_LOWER,
2692  flags, width, precision);
2693  return;
2694  }
2695 
2696  default:
2697  /* Finitude */
2698  break;
2699  }
2700 
2701  /* Normal numbers */
2702  if (flags & FLAGS_LONGDOUBLE)
2703  {
2704  baseDigits = (base == 10)
2705  ? LDBL_DIG
2706  : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
2707  epsilon = LDBL_EPSILON;
2708  }
2709  else if (flags & FLAGS_SHORT)
2710  {
2711  baseDigits = (base == BASE_DECIMAL)
2712  ? FLT_DIG
2713  : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base));
2714  epsilon = FLT_EPSILON;
2715  }
2716  else
2717  {
2718  baseDigits = (base == BASE_DECIMAL)
2719  ? DBL_DIG
2720  : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
2721  epsilon = DBL_EPSILON;
2722  }
2723 
2725  isHex = (base == BASE_HEX);
2726  if (base == NO_BASE)
2727  base = BASE_DECIMAL;
2728  dblBase = (trio_long_double_t)base;
2729  keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) ||
2730  ( (flags & FLAGS_FLOAT_G) &&
2731  !(flags & FLAGS_ALTERNATIVE) ) );
2732 
2733  if (flags & FLAGS_ROUNDING)
2734  precision = baseDigits;
2735 
2736  if (precision == NO_PRECISION)
2737  {
2738  if (isHex)
2739  {
2740  keepTrailingZeroes = FALSE;
2742  }
2743  else
2744  {
2745  precision = FLT_DIG;
2746  }
2747  }
2748 
2749  if (isNegative)
2750  number = -number;
2751 
2752  if (isHex)
2753  flags |= FLAGS_FLOAT_E;
2754 
2755  if (flags & FLAGS_FLOAT_G)
2756  {
2757  if (precision == 0)
2758  precision = 1;
2759 
2760  if ((number < 1.0E-4) || (number > powl(base,
2762  {
2763  /* Use scientific notation */
2764  flags |= FLAGS_FLOAT_E;
2765  }
2766  else if (number < 1.0)
2767  {
2768  /*
2769  * Use normal notation. If the integer part of the number is
2770  * zero, then adjust the precision to include leading fractional
2771  * zeros.
2772  */
2773  workNumber = TrioLogarithm(number, base);
2774  workNumber = TRIO_FABS(workNumber);
2775  if (workNumber - floorl(workNumber) < 0.001)
2776  workNumber--;
2777  zeroes = (int)floorl(workNumber);
2778  }
2779  }
2780 
2781  if (flags & FLAGS_FLOAT_E)
2782  {
2783  /* Scale the number */
2784  workNumber = TrioLogarithm(number, base);
2785  if (trio_isinf(workNumber) == -1)
2786  {
2787  exponent = 0;
2788  /* Undo setting */
2789  if (flags & FLAGS_FLOAT_G)
2790  flags &= ~FLAGS_FLOAT_E;
2791  }
2792  else
2793  {
2794  exponent = (int)floorl(workNumber);
2795  number /= powl(dblBase, (trio_long_double_t)exponent);
2796  isExponentNegative = (exponent < 0);
2797  uExponent = (isExponentNegative) ? -exponent : exponent;
2798  if (isHex)
2799  uExponent *= 4; /* log16(2) */
2800  /* No thousand separators */
2801  flags &= ~FLAGS_QUOTE;
2802  }
2803  }
2804 
2805  integerNumber = floorl(number);
2806  fractionNumber = number - integerNumber;
2807 
2808  /*
2809  * Truncated number.
2810  *
2811  * Precision is number of significant digits for FLOAT_G
2812  * and number of fractional digits for others.
2813  */
2814  integerDigits = (integerNumber > epsilon)
2815  ? 1 + (int)TrioLogarithm(integerNumber, base)
2816  : 1;
2817  fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
2818  ? precision - integerDigits
2819  : zeroes + precision;
2820 
2821  dblFractionBase = TrioPower(base, fractionDigits);
2822 
2823  workNumber = number + 0.5 / dblFractionBase;
2824  if (floorl(number) != floorl(workNumber))
2825  {
2826  if (flags & FLAGS_FLOAT_E)
2827  {
2828  /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
2829  exponent++;
2830  isExponentNegative = (exponent < 0);
2831  uExponent = (isExponentNegative) ? -exponent : exponent;
2832  if (isHex)
2833  uExponent *= 4; /* log16(2) */
2834  workNumber = (number + 0.5 / dblFractionBase) / dblBase;
2835  integerNumber = floorl(workNumber);
2836  fractionNumber = workNumber - integerNumber;
2837  }
2838  else
2839  {
2840  /* Adjust if number was rounded up one digit (ie. 99 to 100) */
2841  integerNumber = floorl(number + 0.5);
2842  fractionNumber = 0.0;
2843  integerDigits = (integerNumber > epsilon)
2844  ? 1 + (int)TrioLogarithm(integerNumber, base)
2845  : 1;
2846  }
2847  }
2848 
2849  /* Estimate accuracy */
2850  integerAdjust = fractionAdjust = 0.5;
2851  if (flags & FLAGS_ROUNDING)
2852  {
2853  if (integerDigits > baseDigits)
2854  {
2855  integerThreshold = baseDigits;
2856  fractionDigits = 0;
2857  dblFractionBase = 1.0;
2858  fractionThreshold = 0;
2859  precision = 0; /* Disable decimal-point */
2860  integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1);
2861  fractionAdjust = 0.0;
2862  }
2863  else
2864  {
2865  integerThreshold = integerDigits;
2866  fractionThreshold = fractionDigits - integerThreshold;
2867  fractionAdjust = 1.0;
2868  }
2869  }
2870  else
2871  {
2872  integerThreshold = INT_MAX;
2873  fractionThreshold = INT_MAX;
2874  }
2875 
2876  /*
2877  * Calculate expected width.
2878  * sign + integer part + thousands separators + decimal point
2879  * + fraction + exponent
2880  */
2881  fractionAdjust /= dblFractionBase;
2882  hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
2883  keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
2884  !((precision == 0) ||
2885  (!keepTrailingZeroes && hasOnlyZeroes)) );
2886  if (flags & FLAGS_FLOAT_E)
2887  {
2888  exponentDigits = (uExponent == 0)
2889  ? 1
2890  : (int)ceil(TrioLogarithm((double)(uExponent + 1),
2891  (isHex) ? 10.0 : base));
2892  }
2893  else
2894  exponentDigits = 0;
2895  requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1));
2896 
2897  expectedWidth = integerDigits + fractionDigits
2898  + (keepDecimalPoint
2900  : 0)
2901  + ((flags & FLAGS_QUOTE)
2902  ? TrioCalcThousandSeparatorLength(integerDigits)
2903  : 0);
2904  if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
2905  expectedWidth += sizeof("-") - 1;
2906  if (exponentDigits > 0)
2907  expectedWidth += exponentDigits +
2908  ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
2909  if (isHex)
2910  expectedWidth += sizeof("0X") - 1;
2911 
2912  /* Output prefixing */
2913  if (flags & FLAGS_NILPADDING)
2914  {
2915  /* Leading zeros must be after sign */
2916  if (isNegative)
2917  self->OutStream(self, '-');
2918  else if (flags & FLAGS_SHOWSIGN)
2919  self->OutStream(self, '+');
2920  else if (flags & FLAGS_SPACE)
2921  self->OutStream(self, ' ');
2922  if (isHex)
2923  {
2924  self->OutStream(self, '0');
2925  self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
2926  }
2927  if (!(flags & FLAGS_LEFTADJUST))
2928  {
2929  for (i = expectedWidth; i < width; i++)
2930  {
2931  self->OutStream(self, '0');
2932  }
2933  }
2934  }
2935  else
2936  {
2937  /* Leading spaces must be before sign */
2938  if (!(flags & FLAGS_LEFTADJUST))
2939  {
2940  for (i = expectedWidth; i < width; i++)
2941  {
2942  self->OutStream(self, CHAR_ADJUST);
2943  }
2944  }
2945  if (isNegative)
2946  self->OutStream(self, '-');
2947  else if (flags & FLAGS_SHOWSIGN)
2948  self->OutStream(self, '+');
2949  else if (flags & FLAGS_SPACE)
2950  self->OutStream(self, ' ');
2951  if (isHex)
2952  {
2953  self->OutStream(self, '0');
2954  self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
2955  }
2956  }
2957 
2958  /* Output the integer part and thousand separators */
2959  dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1);
2960  for (i = 0; i < integerDigits; i++)
2961  {
2962  workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase));
2963  if (i > integerThreshold)
2964  {
2965  /* Beyond accuracy */
2966  self->OutStream(self, digits[0]);
2967  }
2968  else
2969  {
2970  self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
2971  }
2972  dblIntegerBase *= dblBase;
2973 
2974  if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
2975  && TrioFollowedBySeparator(integerDigits - i))
2976  {
2977  for (groupingPointer = internalThousandSeparator;
2978  *groupingPointer != NIL;
2979  groupingPointer++)
2980  {
2981  self->OutStream(self, *groupingPointer);
2982  }
2983  }
2984  }
2985 
2986  /* Insert decimal point and build the fraction part */
2987  trailingZeroes = 0;
2988 
2989  if (keepDecimalPoint)
2990  {
2992  {
2993  self->OutStream(self, internalDecimalPoint);
2994  }
2995  else
2996  {
2997  for (i = 0; i < internalDecimalPointLength; i++)
2998  {
2999  self->OutStream(self, internalDecimalPointString[i]);
3000  }
3001  }
3002  }
3003 
3004  for (i = 0; i < fractionDigits; i++)
3005  {
3006  if ((integerDigits > integerThreshold) || (i > fractionThreshold))
3007  {
3008  /* Beyond accuracy */
3009  trailingZeroes++;
3010  }
3011  else
3012  {
3013  fractionNumber *= dblBase;
3014  fractionAdjust *= dblBase;
3015  workNumber = floorl(fractionNumber + fractionAdjust);
3016  fractionNumber -= workNumber;
3017  index = (int)fmodl(workNumber, dblBase);
3018  if (index == 0)
3019  {
3020  trailingZeroes++;
3021  }
3022  else
3023  {
3024  while (trailingZeroes > 0)
3025  {
3026  /* Not trailing zeroes after all */
3027  self->OutStream(self, digits[0]);
3028  trailingZeroes--;
3029  }
3030  self->OutStream(self, digits[index]);
3031  }
3032  }
3033  }
3034 
3035  if (keepTrailingZeroes)
3036  {
3037  while (trailingZeroes > 0)
3038  {
3039  self->OutStream(self, digits[0]);
3040  trailingZeroes--;
3041  }
3042  }
3043 
3044  /* Output exponent */
3045  if (exponentDigits > 0)
3046  {
3047  self->OutStream(self,
3048  isHex
3049  ? ((flags & FLAGS_UPPER) ? 'P' : 'p')
3050  : ((flags & FLAGS_UPPER) ? 'E' : 'e'));
3051  self->OutStream(self, (isExponentNegative) ? '-' : '+');
3052 
3053  /* The exponent must contain at least two digits */
3054  if (requireTwoDigitExponent)
3055  self->OutStream(self, '0');
3056 
3057  if (isHex)
3058  base = 10.0;
3059  exponentBase = (int)TrioPower(base, exponentDigits - 1);
3060  for (i = 0; i < exponentDigits; i++)
3061  {
3062  self->OutStream(self, digits[(uExponent / exponentBase) % base]);
3063  exponentBase /= base;
3064  }
3065  }
3066  /* Output trailing spaces */
3067  if (flags & FLAGS_LEFTADJUST)
3068  {
3069  for (i = expectedWidth; i < width; i++)
3070  {
3071  self->OutStream(self, CHAR_ADJUST);
3072  }
3073  }
3074 }
3075 
3076 /*************************************************************************
3077  * TrioFormatProcess
3078  *
3079  * Description:
3080  * This is the main engine for formatting output
3081  */
3082 TRIO_PRIVATE int
3083 TrioFormatProcess
3084 TRIO_ARGS3((data, format, parameters),
3085  trio_class_t *data,
3086  TRIO_CONST char *format,
3087  trio_parameter_t *parameters)
3088 {
3089 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3090  int charlen;
3091 #endif
3092  int i;
3093  TRIO_CONST char *string;
3096  int width;
3097  int precision;
3098  int base;
3099  int index;
3100 
3101  index = 0;
3102  i = 0;
3103 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3104  (void)mblen(NULL, 0);
3105 #endif
3106 
3107  while (format[index])
3108  {
3109 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3110  if (! isascii(format[index]))
3111  {
3112  charlen = mblen(&format[index], MB_LEN_MAX);
3113  /*
3114  * Only valid multibyte characters are handled here. Invalid
3115  * multibyte characters (charlen == -1) are handled as normal
3116  * characters.
3117  */
3118  if (charlen != -1)
3119  {
3120  while (charlen-- > 0)
3121  {
3122  data->OutStream(data, format[index++]);
3123  }
3124  continue; /* while characters left in formatting string */
3125  }
3126  }
3127 #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
3128  if (CHAR_IDENTIFIER == format[index])
3129  {
3130  if (CHAR_IDENTIFIER == format[index + 1])
3131  {
3132  data->OutStream(data, CHAR_IDENTIFIER);
3133  index += 2;
3134  }
3135  else
3136  {
3137  /* Skip the parameter entries */
3138  while (parameters[i].type == FORMAT_PARAMETER)
3139  i++;
3140 
3141  flags = parameters[i].flags;
3142 
3143  /* Find width */
3144  width = parameters[i].width;
3146  {
3147  /* Get width from parameter list */
3148  width = (int)parameters[width].data.number.as_signed;
3149  if (width < 0)
3150  {
3151  /*
3152  * A negative width is the same as the - flag and
3153  * a positive width.
3154  */
3156  flags &= ~FLAGS_NILPADDING;
3157  width = -width;
3158  }
3159  }
3160 
3161  /* Find precision */
3162  if (flags & FLAGS_PRECISION)
3163  {
3164  precision = parameters[i].precision;
3166  {
3167  /* Get precision from parameter list */
3168  precision = (int)parameters[precision].data.number.as_signed;
3169  if (precision < 0)
3170  {
3171  /*
3172  * A negative precision is the same as no
3173  * precision
3174  */
3176  }
3177  }
3178  }
3179  else
3180  {
3182  }
3183 
3184  /* Find base */
3185  base = parameters[i].base;
3187  {
3188  /* Get base from parameter list */
3189  base = (int)parameters[base].data.number.as_signed;
3190  }
3191 
3192  switch (parameters[i].type)
3193  {
3194  case FORMAT_CHAR:
3195  if (flags & FLAGS_QUOTE)
3196  data->OutStream(data, CHAR_QUOTE);
3197  if (! (flags & FLAGS_LEFTADJUST))
3198  {
3199  while (--width > 0)
3200  data->OutStream(data, CHAR_ADJUST);
3201  }
3202 #if TRIO_WIDECHAR
3203  if (flags & FLAGS_WIDECHAR)
3204  {
3205  TrioWriteWideStringCharacter(data,
3206  (trio_wchar_t)parameters[i].data.number.as_signed,
3207  flags,
3208  NO_WIDTH);
3209  }
3210  else
3211 #endif
3212  {
3213  TrioWriteStringCharacter(data,
3214  (int)parameters[i].data.number.as_signed,
3215  flags);
3216  }
3217 
3218  if (flags & FLAGS_LEFTADJUST)
3219  {
3220  while(--width > 0)
3221  data->OutStream(data, CHAR_ADJUST);
3222  }
3223  if (flags & FLAGS_QUOTE)
3224  data->OutStream(data, CHAR_QUOTE);
3225 
3226  break; /* FORMAT_CHAR */
3227 
3228  case FORMAT_INT:
3229  TrioWriteNumber(data,
3230  parameters[i].data.number.as_unsigned,
3231  flags,
3232  width,
3233  precision,
3234  base);
3235 
3236  break; /* FORMAT_INT */
3237 
3238  case FORMAT_DOUBLE:
3239  TrioWriteDouble(data,
3240  parameters[i].data.longdoubleNumber,
3241  flags,
3242  width,
3243  precision,
3244  base);
3245  break; /* FORMAT_DOUBLE */
3246 
3247  case FORMAT_STRING:
3248 #if TRIO_WIDECHAR
3249  if (flags & FLAGS_WIDECHAR)
3250  {
3251  TrioWriteWideString(data,
3252  parameters[i].data.wstring,
3253  flags,
3254  width,
3255  precision);
3256  }
3257  else
3258 #endif
3259  {
3260  TrioWriteString(data,
3261  parameters[i].data.string,
3262  flags,
3263  width,
3264  precision);
3265  }
3266  break; /* FORMAT_STRING */
3267 
3268  case FORMAT_POINTER:
3269  {
3271 
3272  reference.data = data;
3273  reference.parameter = &parameters[i];
3274  trio_print_pointer(&reference, parameters[i].data.pointer);
3275  }
3276  break; /* FORMAT_POINTER */
3277 
3278  case FORMAT_COUNT:
3279  pointer = parameters[i].data.pointer;
3280  if (NULL != pointer)
3281  {
3282  /*
3283  * C99 paragraph 7.19.6.1.8 says "the number of
3284  * characters written to the output stream so far by
3285  * this call", which is data->committed
3286  */
3287 #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
3288  if (flags & FLAGS_SIZE_T)
3289  *(size_t *)pointer = (size_t)data->committed;
3290  else
3291 #endif
3292 #if defined(QUALIFIER_PTRDIFF_T)
3293  if (flags & FLAGS_PTRDIFF_T)
3294  *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
3295  else
3296 #endif
3297 #if defined(QUALIFIER_INTMAX_T)
3298  if (flags & FLAGS_INTMAX_T)
3299  *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
3300  else
3301 #endif
3302  if (flags & FLAGS_QUAD)
3303  {
3304  *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
3305  }
3306  else if (flags & FLAGS_LONG)
3307  {
3308  *(long int *)pointer = (long int)data->committed;
3309  }
3310  else if (flags & FLAGS_SHORT)
3311  {
3312  *(short int *)pointer = (short int)data->committed;
3313  }
3314  else
3315  {
3316  *(int *)pointer = (int)data->committed;
3317  }
3318  }
3319  break; /* FORMAT_COUNT */
3320 
3321  case FORMAT_PARAMETER:
3322  break; /* FORMAT_PARAMETER */
3323 
3324 #if defined(FORMAT_ERRNO)
3325  case FORMAT_ERRNO:
3326  string = trio_error(parameters[i].data.errorNumber);
3327  if (string)
3328  {
3329  TrioWriteString(data,
3330  string,
3331  flags,
3332  width,
3333  precision);
3334  }
3335  else
3336  {
3337  data->OutStream(data, '#');
3338  TrioWriteNumber(data,
3339  (trio_uintmax_t)parameters[i].data.errorNumber,
3340  flags,
3341  width,
3342  precision,
3343  BASE_DECIMAL);
3344  }
3345  break; /* FORMAT_ERRNO */
3346 #endif /* defined(FORMAT_ERRNO) */
3347 
3348 #if defined(FORMAT_USER_DEFINED)
3349  case FORMAT_USER_DEFINED:
3350  {
3352  trio_userdef_t *def = NULL;
3353 
3354  if (parameters[i].user_name[0] == NIL)
3355  {
3356  /* Use handle */
3357  if ((i > 0) ||
3358  (parameters[i - 1].type == FORMAT_PARAMETER))
3359  def = (trio_userdef_t *)parameters[i - 1].data.pointer;
3360  }
3361  else
3362  {
3363  /* Look up namespace */
3364  def = TrioFindNamespace(parameters[i].user_name, NULL);
3365  }
3366  if (def) {
3367  reference.data = data;
3368  reference.parameter = &parameters[i];
3369  def->callback(&reference);
3370  }
3371  }
3372  break;
3373 #endif /* defined(FORMAT_USER_DEFINED) */
3374 
3375  default:
3376  break;
3377  } /* switch parameter type */
3378 
3379  /* Prepare for next */
3380  index = parameters[i].indexAfterSpecifier;
3381  i++;
3382  }
3383  }
3384  else /* not identifier */
3385  {
3386  data->OutStream(data, format[index++]);
3387  }
3388  }
3389  return data->processed;
3390 }
3391 
3392 /*************************************************************************
3393  * TrioFormatRef
3394  */
3395 TRIO_PRIVATE int
3396 TrioFormatRef
3399  TRIO_CONST char *format,
3401  trio_pointer_t *argarray)
3402 {
3403  int status;
3404  trio_parameter_t parameters[MAX_PARAMETERS];
3405 
3406  status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
3407  if (status < 0)
3408  return status;
3409 
3410  status = TrioFormatProcess(reference->data, format, parameters);
3411  if (reference->data->error != 0)
3412  {
3413  status = reference->data->error;
3414  }
3415  return status;
3416 }
3417 
3418 /*************************************************************************
3419  * TrioFormat
3420  */
3421 TRIO_PRIVATE int
3422 TrioFormat
3423 TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
3424  trio_pointer_t destination,
3425  size_t destinationSize,
3426  void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
3427  TRIO_CONST char *format,
3429  trio_pointer_t *argarray)
3430 {
3431  int status;
3433  trio_parameter_t parameters[MAX_PARAMETERS];
3434 
3435  assert(VALID(OutStream));
3436  assert(VALID(format));
3437 
3438  memset(&data, 0, sizeof(data));
3439  data.OutStream = OutStream;
3440  data.location = destination;
3441  data.max = destinationSize;
3442  data.error = 0;
3443 
3444 #if defined(USE_LOCALE)
3445  if (NULL == internalLocaleValues)
3446  {
3447  TrioSetLocale();
3448  }
3449 #endif
3450 
3451  status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
3452  if (status < 0)
3453  return status;
3454 
3455  status = TrioFormatProcess(&data, format, parameters);
3456  if (data.error != 0)
3457  {
3458  status = data.error;
3459  }
3460  return status;
3461 }
3462 
3463 /*************************************************************************
3464  * TrioOutStreamFile
3465  */
3466 TRIO_PRIVATE void
3467 TrioOutStreamFile
3468 TRIO_ARGS2((self, output),
3469  trio_class_t *self,
3470  int output)
3471 {
3472  FILE *file;
3473 
3474  assert(VALID(self));
3475  assert(VALID(self->location));
3476 
3477  file = (FILE *)self->location;
3478  self->processed++;
3479  if (fputc(output, file) == EOF)
3480  {
3481  self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0);
3482  }
3483  else
3484  {
3485  self->committed++;
3486  }
3487 }
3488 
3489 /*************************************************************************
3490  * TrioOutStreamFileDescriptor
3491  */
3492 TRIO_PRIVATE void
3493 TrioOutStreamFileDescriptor
3494 TRIO_ARGS2((self, output),
3495  trio_class_t *self,
3496  int output)
3497 {
3498  int fd;
3499  char ch;
3500 
3501  assert(VALID(self));
3502 
3503  fd = *((int *)self->location);
3504  ch = (char)output;
3505  self->processed++;
3506  if (write(fd, &ch, sizeof(char)) == -1)
3507  {
3508  self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
3509  }
3510  else
3511  {
3512  self->committed++;
3513  }
3514 }
3515 
3516 /*************************************************************************
3517  * TrioOutStreamCustom
3518  */
3519 TRIO_PRIVATE void
3520 TrioOutStreamCustom
3521 TRIO_ARGS2((self, output),
3522  trio_class_t *self,
3523  int output)
3524 {
3525  int status;
3527 
3528  assert(VALID(self));
3529  assert(VALID(self->location));
3530 
3531  data = (trio_custom_t *)self->location;
3532  if (data->stream.out)
3533  {
3534  status = (data->stream.out)(data->closure, output);
3535  if (status >= 0)
3536  {
3537  self->committed++;
3538  }
3539  else
3540  {
3541  if (self->error == 0)
3542  {
3543  self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status);
3544  }
3545  }
3546  }
3547  self->processed++;
3548 }
3549 
3550 /*************************************************************************
3551  * TrioOutStreamString
3552  */
3553 TRIO_PRIVATE void
3554 TrioOutStreamString
3555 TRIO_ARGS2((self, output),
3556  trio_class_t *self,
3557  int output)
3558 {
3559  char **buffer;
3560 
3561  assert(VALID(self));
3562  assert(VALID(self->location));
3563 
3564  buffer = (char **)self->location;
3565  **buffer = (char)output;
3566  (*buffer)++;
3567  self->processed++;
3568  self->committed++;
3569 }
3570 
3571 /*************************************************************************
3572  * TrioOutStreamStringMax
3573  */
3574 TRIO_PRIVATE void
3575 TrioOutStreamStringMax
3576 TRIO_ARGS2((self, output),
3577  trio_class_t *self,
3578  int output)
3579 {
3580  char **buffer;
3581 
3582  assert(VALID(self));
3583  assert(VALID(self->location));
3584 
3585  buffer = (char **)self->location;
3586 
3587  if (self->processed < self->max)
3588  {
3589  **buffer = (char)output;
3590  (*buffer)++;
3591  self->committed++;
3592  }
3593  self->processed++;
3594 }
3595 
3596 /*************************************************************************
3597  * TrioOutStreamStringDynamic
3598  */
3599 TRIO_PRIVATE void
3600 TrioOutStreamStringDynamic
3601 TRIO_ARGS2((self, output),
3602  trio_class_t *self,
3603  int output)
3604 {
3605  assert(VALID(self));
3606  assert(VALID(self->location));
3607 
3608  if (self->error == 0)
3609  {
3610  trio_xstring_append_char((trio_string_t *)self->location,
3611  (char)output);
3612  self->committed++;
3613  }
3614  /* The processed variable must always be increased */
3615  self->processed++;
3616 }
3617 
3618 /*************************************************************************
3619  *
3620  * Formatted printing functions
3621  *
3622  ************************************************************************/
3623 
3624 #if defined(TRIO_DOCUMENTATION)
3625 # include "doc/doc_printf.h"
3626 #endif
3627 
3631 /*************************************************************************
3632  * printf
3633  */
3634 
3642 TRIO_PUBLIC int
3643 trio_printf
3644 TRIO_VARGS2((format, va_alist),
3645  TRIO_CONST char *format,
3646  TRIO_VA_DECL)
3647 {
3648  int status;
3649  va_list args;
3650 
3651  assert(VALID(format));
3652 
3654  status = TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3655  TRIO_VA_END(args);
3656  return status;
3657 }
3658 
3666 TRIO_PUBLIC int
3667 trio_vprintf
3669  TRIO_CONST char *format,
3670  va_list args)
3671 {
3672  assert(VALID(format));
3673 
3674  return TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3675 }
3676 
3684 TRIO_PUBLIC int
3685 trio_printfv
3687  TRIO_CONST char *format,
3688  trio_pointer_t * args)
3689 {
3690  assert(VALID(format));
3691 
3692  return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
3693 }
3694 
3695 /*************************************************************************
3696  * fprintf
3697  */
3698 
3707 TRIO_PUBLIC int
3708 trio_fprintf
3709 TRIO_VARGS3((file, format, va_alist),
3710  FILE *file,
3711  TRIO_CONST char *format,
3712  TRIO_VA_DECL)
3713 {
3714  int status;
3715  va_list args;
3716 
3717  assert(VALID(file));
3718  assert(VALID(format));
3719 
3721  status = TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3722  TRIO_VA_END(args);
3723  return status;
3724 }
3725 
3734 TRIO_PUBLIC int
3735 trio_vfprintf
3737  FILE *file,
3738  TRIO_CONST char *format,
3739  va_list args)
3740 {
3741  assert(VALID(file));
3742  assert(VALID(format));
3743 
3744  return TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3745 }
3746 
3755 TRIO_PUBLIC int
3756 trio_fprintfv
3758  FILE *file,
3759  TRIO_CONST char *format,
3760  trio_pointer_t * args)
3761 {
3762  assert(VALID(file));
3763  assert(VALID(format));
3764 
3765  return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
3766 }
3767 
3768 /*************************************************************************
3769  * dprintf
3770  */
3771 
3780 TRIO_PUBLIC int
3781 trio_dprintf
3782 TRIO_VARGS3((fd, format, va_alist),
3783  int fd,
3784  TRIO_CONST char *format,
3785  TRIO_VA_DECL)
3786 {
3787  int status;
3788  va_list args;
3789 
3790  assert(VALID(format));
3791 
3793  status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL);
3794  TRIO_VA_END(args);
3795  return status;
3796 }
3797 
3806 TRIO_PUBLIC int
3807 trio_vdprintf
3809  int fd,
3810  TRIO_CONST char *format,
3811  va_list args)
3812 {
3813  assert(VALID(format));
3814 
3815  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL);
3816 }
3817 
3826 TRIO_PUBLIC int
3827 trio_dprintfv
3829  int fd,
3830  TRIO_CONST char *format,
3832 {
3833  assert(VALID(format));
3834 
3835  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
3836 }
3837 
3838 /*************************************************************************
3839  * cprintf
3840  */
3841 TRIO_PUBLIC int
3842 trio_cprintf
3843 TRIO_VARGS4((stream, closure, format, va_alist),
3844  trio_outstream_t stream,
3845  trio_pointer_t closure,
3846  TRIO_CONST char *format,
3847  TRIO_VA_DECL)
3848 {
3849  int status;
3850  va_list args;
3852 
3853  assert(VALID(stream));
3854  assert(VALID(format));
3855 
3857  data.stream.out = stream;
3858  data.closure = closure;
3859  status = TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL);
3860  TRIO_VA_END(args);
3861  return status;
3862 }
3863 
3864 TRIO_PUBLIC int
3865 trio_vcprintf
3867  trio_outstream_t stream,
3868  trio_pointer_t closure,
3869  TRIO_CONST char *format,
3870  va_list args)
3871 {
3873 
3874  assert(VALID(stream));
3875  assert(VALID(format));
3876 
3877  data.stream.out = stream;
3878  data.closure = closure;
3879  return TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL);
3880 }
3881 
3882 TRIO_PUBLIC int
3883 trio_cprintfv
3885  trio_outstream_t stream,
3886  trio_pointer_t closure,
3887  TRIO_CONST char *format,
3888  void **args)
3889 {
3891 
3892  assert(VALID(stream));
3893  assert(VALID(format));
3894 
3895  data.stream.out = stream;
3896  data.closure = closure;
3897  return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
3898 }
3899 
3900 /*************************************************************************
3901  * sprintf
3902  */
3903 
3912 TRIO_PUBLIC int
3913 trio_sprintf
3915  char *buffer,
3916  TRIO_CONST char *format,
3917  TRIO_VA_DECL)
3918 {
3919  int status;
3920  va_list args;
3921 
3922  assert(VALID(buffer));
3923  assert(VALID(format));
3924 
3926  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL);
3927  *buffer = NIL; /* Terminate with NIL character */
3928  TRIO_VA_END(args);
3929  return status;
3930 }
3931 
3940 TRIO_PUBLIC int
3941 trio_vsprintf
3943  char *buffer,
3944  TRIO_CONST char *format,
3945  va_list args)
3946 {
3947  int status;
3948 
3949  assert(VALID(buffer));
3950  assert(VALID(format));
3951 
3952  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL);
3953  *buffer = NIL;
3954  return status;
3955 }
3956 
3965 TRIO_PUBLIC int
3966 trio_sprintfv
3968  char *buffer,
3969  TRIO_CONST char *format,
3971 {
3972  int status;
3973 
3974  assert(VALID(buffer));
3975  assert(VALID(format));
3976 
3977  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
3978  *buffer = NIL;
3979  return status;
3980 }
3981 
3982 /*************************************************************************
3983  * snprintf
3984  */
3985 
3995 TRIO_PUBLIC int
3996 trio_snprintf
3998  char *buffer,
3999  size_t max,
4000  TRIO_CONST char *format,
4001  TRIO_VA_DECL)
4002 {
4003  int status;
4004  va_list args;
4005 
4006  assert(VALID(buffer));
4007  assert(VALID(format));
4008 
4010  status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4011  TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4012  if (max > 0)
4013  *buffer = NIL;
4014  TRIO_VA_END(args);
4015  return status;
4016 }
4017 
4027 TRIO_PUBLIC int
4028 trio_vsnprintf
4030  char *buffer,
4031  size_t max,
4032  TRIO_CONST char *format,
4033  va_list args)
4034 {
4035  int status;
4036 
4037  assert(VALID(buffer));
4038  assert(VALID(format));
4039 
4040  status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4041  TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4042  if (max > 0)
4043  *buffer = NIL;
4044  return status;
4045 }
4046 
4056 TRIO_PUBLIC int
4057 trio_snprintfv
4059  char *buffer,
4060  size_t max,
4061  TRIO_CONST char *format,
4063 {
4064  int status;
4065 
4066  assert(VALID(buffer));
4067  assert(VALID(format));
4068 
4069  status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4070  TrioOutStreamStringMax, format, NULL, args);
4071  if (max > 0)
4072  *buffer = NIL;
4073  return status;
4074 }
4075 
4076 /*************************************************************************
4077  * snprintfcat
4078  * Appends the new string to the buffer string overwriting the '\0'
4079  * character at the end of buffer.
4080  */
4081 TRIO_PUBLIC int
4082 trio_snprintfcat
4083 TRIO_VARGS4((buffer, max, format, va_alist),
4084  char *buffer,
4085  size_t max,
4086  TRIO_CONST char *format,
4087  TRIO_VA_DECL)
4088 {
4089  int status;
4090  va_list args;
4091  size_t buf_len;
4092 
4094 
4095  assert(VALID(buffer));
4096  assert(VALID(format));
4097 
4098  buf_len = trio_length(buffer);
4099  buffer = &buffer[buf_len];
4100 
4101  status = TrioFormat(&buffer, max - 1 - buf_len,
4102  TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4103  TRIO_VA_END(args);
4104  *buffer = NIL;
4105  return status;
4106 }
4107 
4108 TRIO_PUBLIC int
4109 trio_vsnprintfcat
4111  char *buffer,
4112  size_t max,
4113  TRIO_CONST char *format,
4114  va_list args)
4115 {
4116  int status;
4117  size_t buf_len;
4118 
4119  assert(VALID(buffer));
4120  assert(VALID(format));
4121 
4122  buf_len = trio_length(buffer);
4123  buffer = &buffer[buf_len];
4124  status = TrioFormat(&buffer, max - 1 - buf_len,
4125  TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4126  *buffer = NIL;
4127  return status;
4128 }
4129 
4130 /*************************************************************************
4131  * trio_aprintf
4132  */
4133 
4134 /* Deprecated */
4135 TRIO_PUBLIC char *
4136 trio_aprintf
4137 TRIO_VARGS2((format, va_alist),
4138  TRIO_CONST char *format,
4139  TRIO_VA_DECL)
4140 {
4141  va_list args;
4143  char *result = NULL;
4144 
4145  assert(VALID(format));
4146 
4147  info = trio_xstring_duplicate("");
4148  if (info)
4149  {
4151  (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
4153  TRIO_VA_END(args);
4154 
4155  trio_string_terminate(info);
4156  result = trio_string_extract(info);
4157  trio_string_destroy(info);
4158  }
4159  return result;
4160 }
4161 
4162 /* Deprecated */
4163 TRIO_PUBLIC char *
4164 trio_vaprintf
4166  TRIO_CONST char *format,
4167  va_list args)
4168 {
4170  char *result = NULL;
4171 
4172  assert(VALID(format));
4173 
4174  info = trio_xstring_duplicate("");
4175  if (info)
4176  {
4177  (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
4179  trio_string_terminate(info);
4180  result = trio_string_extract(info);
4181  trio_string_destroy(info);
4182  }
4183  return result;
4184 }
4185 
4186 TRIO_PUBLIC int
4187 trio_asprintf
4189  char **result,
4190  TRIO_CONST char *format,
4191  TRIO_VA_DECL)
4192 {
4193  va_list args;
4194  int status;
4196 
4197  assert(VALID(format));
4198 
4199  *result = NULL;
4200 
4201  info = trio_xstring_duplicate("");
4202  if (info == NULL)
4203  {
4205  }
4206  else
4207  {
4209  status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
4211  TRIO_VA_END(args);
4212  if (status >= 0)
4213  {
4214  trio_string_terminate(info);
4215  *result = trio_string_extract(info);
4216  }
4217  trio_string_destroy(info);
4218  }
4219  return status;
4220 }
4221 
4222 TRIO_PUBLIC int
4223 trio_vasprintf
4225  char **result,
4226  TRIO_CONST char *format,
4227  va_list args)
4228 {
4229  int status;
4231 
4232  assert(VALID(format));
4233 
4234  *result = NULL;
4235 
4236  info = trio_xstring_duplicate("");
4237  if (info == NULL)
4238  {
4240  }
4241  else
4242  {
4243  status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
4245  if (status >= 0)
4246  {
4247  trio_string_terminate(info);
4248  *result = trio_string_extract(info);
4249  }
4250  trio_string_destroy(info);
4251  }
4252  return status;
4253 }
4254 
4257 /*************************************************************************
4258  *
4259  * CALLBACK
4260  *
4261  ************************************************************************/
4262 
4263 #if defined(TRIO_DOCUMENTATION)
4264 # include "doc/doc_register.h"
4265 #endif
4266 
4271 #if TRIO_EXTENSION
4272 
4273 /*************************************************************************
4274  * trio_register
4275  */
4276 
4285 trio_register
4287  trio_callback_t callback,
4288  TRIO_CONST char *name)
4289 {
4290  trio_userdef_t *def;
4291  trio_userdef_t *prev = NULL;
4292 
4293  if (callback == NULL)
4294  return NULL;
4295 
4296  if (name)
4297  {
4298  /* Handle built-in namespaces */
4299  if (name[0] == ':')
4300  {
4301  if (trio_equal(name, ":enter"))
4302  {
4304  }
4305  else if (trio_equal(name, ":leave"))
4306  {
4308  }
4309  return NULL;
4310  }
4311 
4312  /* Bail out if namespace is too long */
4313  if (trio_length(name) >= MAX_USER_NAME)
4314  return NULL;
4315 
4316  /* Bail out if namespace already is registered */
4317  def = TrioFindNamespace(name, &prev);
4318  if (def)
4319  return NULL;
4320  }
4321 
4322  def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t));
4323  if (def)
4324  {
4327 
4328  if (name)
4329  {
4330  /* Link into internal list */
4331  if (prev == NULL)
4332  internalUserDef = def;
4333  else
4334  prev->next = def;
4335  }
4336  /* Initialize */
4337  def->callback = callback;
4338  def->name = (name == NULL)
4339  ? NULL
4340  : trio_duplicate(name);
4341  def->next = NULL;
4342 
4345  }
4346  return (trio_pointer_t)def;
4347 }
4348 
4354 void
4355 trio_unregister
4358 {
4360  trio_userdef_t *def;
4361  trio_userdef_t *prev = NULL;
4362 
4363  assert(VALID(self));
4364 
4365  if (self->name)
4366  {
4367  def = TrioFindNamespace(self->name, &prev);
4368  if (def)
4369  {
4372 
4373  if (prev == NULL)
4375  else
4376  prev->next = def->next;
4377 
4380  }
4381  trio_destroy(self->name);
4382  }
4383  TRIO_FREE(self);
4384 }
4385 
4386 /*************************************************************************
4387  * trio_get_format [public]
4388  */
4389 TRIO_CONST char *
4390 trio_get_format
4393 {
4394 #if defined(FORMAT_USER_DEFINED)
4395  assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
4396 #endif
4397 
4398  return (((trio_reference_t *)ref)->parameter->user_data);
4399 }
4400 
4401 /*************************************************************************
4402  * trio_get_argument [public]
4403  */
4405 trio_get_argument
4406 TRIO_ARGS1((ref),
4408 {
4409 #if defined(FORMAT_USER_DEFINED)
4410  assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
4411 #endif
4412 
4413  return ((trio_reference_t *)ref)->parameter->data.pointer;
4414 }
4415 
4416 /*************************************************************************
4417  * trio_get_width / trio_set_width [public]
4418  */
4419 int
4420 trio_get_width
4421 TRIO_ARGS1((ref),
4423 {
4424  return ((trio_reference_t *)ref)->parameter->width;
4425 }
4426 
4427 void
4428 trio_set_width
4431  int width)
4432 {
4433  ((trio_reference_t *)ref)->parameter->width = width;
4434 }
4435 
4436 /*************************************************************************
4437  * trio_get_precision / trio_set_precision [public]
4438  */
4439 int
4440 trio_get_precision
4441 TRIO_ARGS1((ref),
4443 {
4444  return (((trio_reference_t *)ref)->parameter->precision);
4445 }
4446 
4447 void
4448 trio_set_precision
4451  int precision)
4452 {
4453  ((trio_reference_t *)ref)->parameter->precision = precision;
4454 }
4455 
4456 /*************************************************************************
4457  * trio_get_base / trio_set_base [public]
4458  */
4459 int
4460 trio_get_base
4461 TRIO_ARGS1((ref),
4463 {
4464  return (((trio_reference_t *)ref)->parameter->base);
4465 }
4466 
4467 void
4468 trio_set_base
4471  int base)
4472 {
4473  ((trio_reference_t *)ref)->parameter->base = base;
4474 }
4475 
4476 /*************************************************************************
4477  * trio_get_long / trio_set_long [public]
4478  */
4479 int
4480 trio_get_long
4481 TRIO_ARGS1((ref),
4483 {
4484  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG)
4485  ? TRUE
4486  : FALSE;
4487 }
4488 
4489 void
4490 trio_set_long
4491 TRIO_ARGS2((ref, is_long),
4493  int is_long)
4494 {
4495  if (is_long)
4496  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG;
4497  else
4498  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG;
4499 }
4500 
4501 /*************************************************************************
4502  * trio_get_longlong / trio_set_longlong [public]
4503  */
4504 int
4505 trio_get_longlong
4506 TRIO_ARGS1((ref),
4508 {
4509  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD)
4510  ? TRUE
4511  : FALSE;
4512 }
4513 
4514 void
4515 trio_set_longlong
4516 TRIO_ARGS2((ref, is_longlong),
4518  int is_longlong)
4519 {
4520  if (is_longlong)
4521  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD;
4522  else
4523  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD;
4524 }
4525 
4526 /*************************************************************************
4527  * trio_get_longdouble / trio_set_longdouble [public]
4528  */
4529 int
4530 trio_get_longdouble
4531 TRIO_ARGS1((ref),
4533 {
4534  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE)
4535  ? TRUE
4536  : FALSE;
4537 }
4538 
4539 void
4540 trio_set_longdouble
4541 TRIO_ARGS2((ref, is_longdouble),
4543  int is_longdouble)
4544 {
4545  if (is_longdouble)
4546  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE;
4547  else
4548  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
4549 }
4550 
4551 /*************************************************************************
4552  * trio_get_short / trio_set_short [public]
4553  */
4554 int
4555 trio_get_short
4556 TRIO_ARGS1((ref),
4558 {
4559  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT)
4560  ? TRUE
4561  : FALSE;
4562 }
4563 
4564 void
4565 trio_set_short
4566 TRIO_ARGS2((ref, is_short),
4568  int is_short)
4569 {
4570  if (is_short)
4571  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT;
4572  else
4573  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT;
4574 }
4575 
4576 /*************************************************************************
4577  * trio_get_shortshort / trio_set_shortshort [public]
4578  */
4579 int
4580 trio_get_shortshort
4581 TRIO_ARGS1((ref),
4583 {
4584  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT)
4585  ? TRUE
4586  : FALSE;
4587 }
4588 
4589 void
4590 trio_set_shortshort
4591 TRIO_ARGS2((ref, is_shortshort),
4593  int is_shortshort)
4594 {
4595  if (is_shortshort)
4596  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT;
4597  else
4598  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT;
4599 }
4600 
4601 /*************************************************************************
4602  * trio_get_alternative / trio_set_alternative [public]
4603  */
4604 int
4605 trio_get_alternative
4606 TRIO_ARGS1((ref),
4608 {
4609  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE)
4610  ? TRUE
4611  : FALSE;
4612 }
4613 
4614 void
4615 trio_set_alternative
4616 TRIO_ARGS2((ref, is_alternative),
4618  int is_alternative)
4619 {
4620  if (is_alternative)
4621  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE;
4622  else
4623  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE;
4624 }
4625 
4626 /*************************************************************************
4627  * trio_get_alignment / trio_set_alignment [public]
4628  */
4629 int
4630 trio_get_alignment
4631 TRIO_ARGS1((ref),
4633 {
4634  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST)
4635  ? TRUE
4636  : FALSE;
4637 }
4638 
4639 void
4640 trio_set_alignment
4641 TRIO_ARGS2((ref, is_leftaligned),
4643  int is_leftaligned)
4644 {
4645  if (is_leftaligned)
4646  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST;
4647  else
4648  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST;
4649 }
4650 
4651 /*************************************************************************
4652  * trio_get_spacing /trio_set_spacing [public]
4653  */
4654 int
4655 trio_get_spacing
4656 TRIO_ARGS1((ref),
4658 {
4659  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE)
4660  ? TRUE
4661  : FALSE;
4662 }
4663 
4664 void
4665 trio_set_spacing
4668  int is_space)
4669 {
4670  if (is_space)
4671  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE;
4672  else
4673  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE;
4674 }
4675 
4676 /*************************************************************************
4677  * trio_get_sign / trio_set_sign [public]
4678  */
4679 int
4680 trio_get_sign
4681 TRIO_ARGS1((ref),
4683 {
4684  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN)
4685  ? TRUE
4686  : FALSE;
4687 }
4688 
4689 void
4690 trio_set_sign
4691 TRIO_ARGS2((ref, is_sign),
4693  int is_sign)
4694 {
4695  if (is_sign)
4696  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN;
4697  else
4698  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN;
4699 }
4700 
4701 /*************************************************************************
4702  * trio_get_padding / trio_set_padding [public]
4703  */
4704 int
4705 trio_get_padding
4706 TRIO_ARGS1((ref),
4708 {
4709  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING)
4710  ? TRUE
4711  : FALSE;
4712 }
4713 
4714 void
4715 trio_set_padding
4716 TRIO_ARGS2((ref, is_padding),
4718  int is_padding)
4719 {
4720  if (is_padding)
4721  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING;
4722  else
4723  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING;
4724 }
4725 
4726 /*************************************************************************
4727  * trio_get_quote / trio_set_quote [public]
4728  */
4729 int
4730 trio_get_quote
4731 TRIO_ARGS1((ref),
4733 {
4734  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE)
4735  ? TRUE
4736  : FALSE;
4737 }
4738 
4739 void
4740 trio_set_quote
4741 TRIO_ARGS2((ref, is_quote),
4743  int is_quote)
4744 {
4745  if (is_quote)
4746  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE;
4747  else
4748  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
4749 }
4750 
4751 /*************************************************************************
4752  * trio_get_upper / trio_set_upper [public]
4753  */
4754 int
4755 trio_get_upper
4756 TRIO_ARGS1((ref),
4758 {
4759  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER)
4760  ? TRUE
4761  : FALSE;
4762 }
4763 
4764 void
4765 trio_set_upper
4768  int is_upper)
4769 {
4770  if (is_upper)
4771  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER;
4772  else
4773  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER;
4774 }
4775 
4776 /*************************************************************************
4777  * trio_get_largest / trio_set_largest [public]
4778  */
4779 #if TRIO_C99
4780 int
4781 trio_get_largest
4782 TRIO_ARGS1((ref),
4784 {
4785  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T)
4786  ? TRUE
4787  : FALSE;
4788 }
4789 
4790 void
4791 trio_set_largest
4792 TRIO_ARGS2((ref, is_largest),
4794  int is_largest)
4795 {
4796  if (is_largest)
4797  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T;
4798  else
4799  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
4800 }
4801 #endif
4802 
4803 /*************************************************************************
4804  * trio_get_ptrdiff / trio_set_ptrdiff [public]
4805  */
4806 int
4807 trio_get_ptrdiff
4808 TRIO_ARGS1((ref),
4810 {
4811  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T)
4812  ? TRUE
4813  : FALSE;
4814 }
4815 
4816 void
4817 trio_set_ptrdiff
4818 TRIO_ARGS2((ref, is_ptrdiff),
4820  int is_ptrdiff)
4821 {
4822  if (is_ptrdiff)
4823  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T;
4824  else
4825  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
4826 }
4827 
4828 /*************************************************************************
4829  * trio_get_size / trio_set_size [public]
4830  */
4831 #if TRIO_C99
4832 int
4833 trio_get_size
4834 TRIO_ARGS1((ref),
4836 {
4837  return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T)
4838  ? TRUE
4839  : FALSE;
4840 }
4841 
4842 void
4843 trio_set_size
4844 TRIO_ARGS2((ref, is_size),
4846  int is_size)
4847 {
4848  if (is_size)
4849  ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T;
4850  else
4851  ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
4852 }
4853 #endif
4854 
4855 /*************************************************************************
4856  * trio_print_int [public]
4857  */
4858 void
4859 trio_print_int
4862  int number)
4863 {
4865 
4866  TrioWriteNumber(self->data,
4868  self->parameter->flags,
4869  self->parameter->width,
4870  self->parameter->precision,
4871  self->parameter->base);
4872 }
4873 
4874 /*************************************************************************
4875  * trio_print_uint [public]
4876  */
4877 void
4878 trio_print_uint
4881  unsigned int number)
4882 {
4884 
4885  TrioWriteNumber(self->data,
4887  self->parameter->flags | FLAGS_UNSIGNED,
4888  self->parameter->width,
4889  self->parameter->precision,
4890  self->parameter->base);
4891 }
4892 
4893 /*************************************************************************
4894  * trio_print_double [public]
4895  */
4896 void
4897 trio_print_double
4900  double number)
4901 {
4903 
4904  TrioWriteDouble(self->data,
4905  number,
4906  self->parameter->flags,
4907  self->parameter->width,
4908  self->parameter->precision,
4909  self->parameter->base);
4910 }
4911 
4912 /*************************************************************************
4913  * trio_print_string [public]
4914  */
4915 void
4916 trio_print_string
4917 TRIO_ARGS2((ref, string),
4919  char *string)
4920 {
4922 
4923  TrioWriteString(self->data,
4924  string,
4925  self->parameter->flags,
4926  self->parameter->width,
4927  self->parameter->precision);
4928 }
4929 
4930 /*************************************************************************
4931  * trio_print_ref [public]
4932  */
4933 int
4934 trio_print_ref
4935 TRIO_VARGS3((ref, format, va_alist),
4937  TRIO_CONST char *format,
4938  TRIO_VA_DECL)
4939 {
4940  int status;
4941  va_list arglist;
4942 
4943  assert(VALID(format));
4944 
4948  return status;
4949 }
4950 
4951 /*************************************************************************
4952  * trio_vprint_ref [public]
4953  */
4954 int
4955 trio_vprint_ref
4958  TRIO_CONST char *format,
4959  va_list arglist)
4960 {
4961  assert(VALID(format));
4962 
4963  return TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL);
4964 }
4965 
4966 /*************************************************************************
4967  * trio_printv_ref [public]
4968  */
4969 int
4970 trio_printv_ref
4971 TRIO_ARGS3((ref, format, argarray),
4973  TRIO_CONST char *format,
4974  trio_pointer_t *argarray)
4975 {
4976  assert(VALID(format));
4977 
4978  return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
4979 }
4980 
4981 #endif /* TRIO_EXTENSION */
4982 
4983 /*************************************************************************
4984  * trio_print_pointer [public]
4985  */
4986 void
4987 trio_print_pointer
4991 {
4995 
4996  if (NULL == pointer)
4997  {
4998  TRIO_CONST char *string = internalNullString;
4999  while (*string)
5000  self->data->OutStream(self->data, *string++);
5001  }
5002  else
5003  {
5004  /*
5005  * The subtraction of the null pointer is a workaround
5006  * to avoid a compiler warning. The performance overhead
5007  * is negligible (and likely to be removed by an
5008  * optimizing compiler). The (char *) casting is done
5009  * to please ANSI C++.
5010  */
5011  number = (trio_uintmax_t)((char *)pointer - (char *)0);
5012  /* Shrink to size of pointer */
5013  number &= (trio_uintmax_t)-1;
5014  flags = self->parameter->flags;
5017  TrioWriteNumber(self->data,
5018  number,
5019  flags,
5020  POINTER_WIDTH,
5021  NO_PRECISION,
5022  BASE_HEX);
5023  }
5024 }
5025 
5028 /*************************************************************************
5029  *
5030  * LOCALES
5031  *
5032  ************************************************************************/
5033 
5034 /*************************************************************************
5035  * trio_locale_set_decimal_point
5036  *
5037  * Decimal point can only be one character. The input argument is a
5038  * string to enable multibyte characters. At most MB_LEN_MAX characters
5039  * will be used.
5040  */
5041 TRIO_PUBLIC void
5042 trio_locale_set_decimal_point
5043 TRIO_ARGS1((decimalPoint),
5044  char *decimalPoint)
5045 {
5046 #if defined(USE_LOCALE)
5047  if (NULL == internalLocaleValues)
5048  {
5049  TrioSetLocale();
5050  }
5051 #endif
5052  internalDecimalPointLength = trio_length(decimalPoint);
5053  if (internalDecimalPointLength == 1)
5054  {
5055  internalDecimalPoint = *decimalPoint;
5056  }
5057  else
5058  {
5060  trio_copy_max(internalDecimalPointString,
5062  decimalPoint);
5063  }
5064 }
5065 
5066 /*************************************************************************
5067  * trio_locale_set_thousand_separator
5068  *
5069  * See trio_locale_set_decimal_point
5070  */
5071 TRIO_PUBLIC void
5072 trio_locale_set_thousand_separator
5073 TRIO_ARGS1((thousandSeparator),
5074  char *thousandSeparator)
5075 {
5076 #if defined(USE_LOCALE)
5077  if (NULL == internalLocaleValues)
5078  {
5079  TrioSetLocale();
5080  }
5081 #endif
5082  trio_copy_max(internalThousandSeparator,
5083  sizeof(internalThousandSeparator),
5084  thousandSeparator);
5086 }
5087 
5088 /*************************************************************************
5089  * trio_locale_set_grouping
5090  *
5091  * Array of bytes. Reversed order.
5092  *
5093  * CHAR_MAX : No further grouping
5094  * 0 : Repeat last group for the remaining digits (not necessary
5095  * as C strings are zero-terminated)
5096  * n : Set current group to n
5097  *
5098  * Same order as the grouping attribute in LC_NUMERIC.
5099  */
5100 TRIO_PUBLIC void
5101 trio_locale_set_grouping
5103  char *grouping)
5104 {
5105 #if defined(USE_LOCALE)
5106  if (NULL == internalLocaleValues)
5107  {
5108  TrioSetLocale();
5109  }
5110 #endif
5111  trio_copy_max(internalGrouping,
5112  sizeof(internalGrouping),
5113  grouping);
5114 }
5115 
5116 
5117 /*************************************************************************
5118  *
5119  * SCANNING
5120  *
5121  ************************************************************************/
5122 
5123 /*************************************************************************
5124  * TrioSkipWhitespaces
5125  */
5126 TRIO_PRIVATE int
5127 TrioSkipWhitespaces
5128 TRIO_ARGS1((self),
5129  trio_class_t *self)
5130 {
5131  int ch;
5132 
5133  ch = self->current;
5134  while (isspace(ch))
5135  {
5136  self->InStream(self, &ch);
5137  }
5138  return ch;
5139 }
5140 
5141 /*************************************************************************
5142  * TrioGetCollation
5143  */
5144 #if TRIO_EXTENSION
5145 TRIO_PRIVATE void
5147 {
5148  int i;
5149  int j;
5150  int k;
5151  char first[2];
5152  char second[2];
5153 
5154  /* This is computationally expensive */
5155  first[1] = NIL;
5156  second[1] = NIL;
5157  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5158  {
5159  k = 0;
5160  first[0] = (char)i;
5161  for (j = 0; j < MAX_CHARACTER_CLASS; j++)
5162  {
5163  second[0] = (char)j;
5164  if (trio_equal_locale(first, second))
5165  internalCollationArray[i][k++] = (char)j;
5166  }
5168  }
5169 }
5170 #endif
5171 
5172 /*************************************************************************
5173  * TrioGetCharacterClass
5174  *
5175  * FIXME:
5176  * multibyte
5177  */
5178 TRIO_PRIVATE int
5179 TrioGetCharacterClass
5180 TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
5181  TRIO_CONST char *format,
5182  int *indexPointer,
5183  trio_flags_t *flagsPointer,
5184  int *characterclass)
5185 {
5186  int index = *indexPointer;
5187  int i;
5188  char ch;
5189  char range_begin;
5190  char range_end;
5191 
5192  *flagsPointer &= ~FLAGS_EXCLUDE;
5193 
5195  {
5196  *flagsPointer |= FLAGS_EXCLUDE;
5197  index++;
5198  }
5199  /*
5200  * If the ungroup character is at the beginning of the scanlist,
5201  * it will be part of the class, and a second ungroup character
5202  * must follow to end the group.
5203  */
5204  if (format[index] == SPECIFIER_UNGROUP)
5205  {
5206  characterclass[(int)SPECIFIER_UNGROUP]++;
5207  index++;
5208  }
5209  /*
5210  * Minus is used to specify ranges. To include minus in the class,
5211  * it must be at the beginning of the list
5212  */
5213  if (format[index] == QUALIFIER_MINUS)
5214  {
5215  characterclass[(int)QUALIFIER_MINUS]++;
5216  index++;
5217  }
5218  /* Collect characters */
5219  for (ch = format[index];
5220  (ch != SPECIFIER_UNGROUP) && (ch != NIL);
5221  ch = format[++index])
5222  {
5223  switch (ch)
5224  {
5225  case QUALIFIER_MINUS: /* Scanlist ranges */
5226 
5227  /*
5228  * Both C99 and UNIX98 describes ranges as implementation-
5229  * defined.
5230  *
5231  * We support the following behaviour (although this may
5232  * change as we become wiser)
5233  * - only increasing ranges, ie. [a-b] but not [b-a]
5234  * - transitive ranges, ie. [a-b-c] == [a-c]
5235  * - trailing minus, ie. [a-] is interpreted as an 'a'
5236  * and a '-'
5237  * - duplicates (although we can easily convert these
5238  * into errors)
5239  */
5240  range_begin = format[index - 1];
5241  range_end = format[++index];
5242  if (range_end == SPECIFIER_UNGROUP)
5243  {
5244  /* Trailing minus is included */
5245  characterclass[(int)ch]++;
5246  ch = range_end;
5247  break; /* for */
5248  }
5249  if (range_end == NIL)
5250  return TRIO_ERROR_RETURN(