1c2c66affSColin Finck /*************************************************************************
2c2c66affSColin Finck *
3c2c66affSColin Finck * $Id$
4c2c66affSColin Finck *
5c2c66affSColin Finck * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
6c2c66affSColin Finck *
7c2c66affSColin Finck * Permission to use, copy, modify, and distribute this software for any
8c2c66affSColin Finck * purpose with or without fee is hereby granted, provided that the above
9c2c66affSColin Finck * copyright notice and this permission notice appear in all copies.
10c2c66affSColin Finck *
11c2c66affSColin Finck * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12c2c66affSColin Finck * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13*40ee59d6SThomas Faber * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14c2c66affSColin Finck * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15c2c66affSColin Finck *
16c2c66affSColin Finck *************************************************************************
17c2c66affSColin Finck *
18c2c66affSColin Finck * A note to trio contributors:
19c2c66affSColin Finck *
20c2c66affSColin Finck * Avoid heap allocation at all costs to ensure that the trio functions
21c2c66affSColin Finck * are async-safe. The exceptions are the printf/fprintf functions, which
22c2c66affSColin Finck * uses fputc, and the asprintf functions and the <alloc> modifier, which
23c2c66affSColin Finck * by design are required to allocate form the heap.
24c2c66affSColin Finck *
25c2c66affSColin Finck ************************************************************************/
26c2c66affSColin Finck
27c2c66affSColin Finck /*
28c2c66affSColin Finck * TODO:
29c2c66affSColin Finck * - Scan is probably too permissive about its modifiers.
30c2c66affSColin Finck * - C escapes in %#[] ?
31c2c66affSColin Finck * - Multibyte characters (done for format parsing, except scan groups)
32c2c66affSColin Finck * - Complex numbers? (C99 _Complex)
33c2c66affSColin Finck * - Boolean values? (C99 _Bool)
34c2c66affSColin Finck * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used
35c2c66affSColin Finck * to print the mantissa, e.g. NaN(0xc000000000000000)
36c2c66affSColin Finck * - Should we support the GNU %a alloc modifier? GNU has an ugly hack
37c2c66affSColin Finck * for %a, because C99 used %a for other purposes. If specified as
38c2c66affSColin Finck * %as or %a[ it is interpreted as the alloc modifier, otherwise as
39c2c66affSColin Finck * the C99 hex-float. This means that you cannot scan %as as a hex-float
40c2c66affSColin Finck * immediately followed by an 's'.
41c2c66affSColin Finck * - Scanning of collating symbols.
42c2c66affSColin Finck */
43c2c66affSColin Finck
44c2c66affSColin Finck /*************************************************************************
45c2c66affSColin Finck * Trio include files
46c2c66affSColin Finck */
47c2c66affSColin Finck #include "triodef.h"
48c2c66affSColin Finck #include "trio.h"
49c2c66affSColin Finck #include "triop.h"
50c2c66affSColin Finck #include "trionan.h"
51c2c66affSColin Finck #if !defined(TRIO_MINIMAL)
52c2c66affSColin Finck # include "triostr.h"
53c2c66affSColin Finck #endif
54c2c66affSColin Finck
55c2c66affSColin Finck /**************************************************************************
56c2c66affSColin Finck *
57c2c66affSColin Finck * Definitions
58c2c66affSColin Finck *
59c2c66affSColin Finck *************************************************************************/
60c2c66affSColin Finck
61c2c66affSColin Finck #include <math.h>
62c2c66affSColin Finck #include <limits.h>
63c2c66affSColin Finck #include <float.h>
64c2c66affSColin Finck
65c2c66affSColin Finck #if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \
66c2c66affSColin Finck || defined(USE_MULTIBYTE) || TRIO_WIDECHAR) \
67c2c66affSColin Finck && !defined(_WIN32_WCE)
68c2c66affSColin Finck # define TRIO_COMPILER_SUPPORTS_MULTIBYTE
69c2c66affSColin Finck # if !defined(MB_LEN_MAX)
70c2c66affSColin Finck # define MB_LEN_MAX 6
71c2c66affSColin Finck # endif
72c2c66affSColin Finck #endif
73c2c66affSColin Finck
74c2c66affSColin Finck #if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
75c2c66affSColin Finck # define TRIO_COMPILER_SUPPORTS_MSVC_INT
76c2c66affSColin Finck #endif
77c2c66affSColin Finck
78c2c66affSColin Finck #if defined(_WIN32_WCE)
79c2c66affSColin Finck #include <wincecompat.h>
80c2c66affSColin Finck #endif
81c2c66affSColin Finck
82c2c66affSColin Finck /*************************************************************************
83c2c66affSColin Finck * Generic definitions
84c2c66affSColin Finck */
85c2c66affSColin Finck
86c2c66affSColin Finck #if !(defined(DEBUG) || defined(NDEBUG))
87c2c66affSColin Finck # define NDEBUG
88c2c66affSColin Finck #endif
89c2c66affSColin Finck
90c2c66affSColin Finck #include <assert.h>
91c2c66affSColin Finck #include <ctype.h>
92c2c66affSColin Finck #if !defined(TRIO_COMPILER_SUPPORTS_C99)
93c2c66affSColin Finck # define isblank(x) (((x)==32) || ((x)==9))
94c2c66affSColin Finck #endif
95c2c66affSColin Finck #if defined(TRIO_COMPILER_ANCIENT)
96c2c66affSColin Finck # include <varargs.h>
97c2c66affSColin Finck #else
98c2c66affSColin Finck # include <stdarg.h>
99c2c66affSColin Finck #endif
100c2c66affSColin Finck #include <stddef.h>
101c2c66affSColin Finck #include <errno.h>
102c2c66affSColin Finck
103c2c66affSColin Finck #ifndef NULL
104c2c66affSColin Finck # define NULL 0
105c2c66affSColin Finck #endif
106c2c66affSColin Finck #define NIL ((char)0)
107c2c66affSColin Finck #ifndef FALSE
108c2c66affSColin Finck # define FALSE (1 == 0)
109c2c66affSColin Finck # define TRUE (! FALSE)
110c2c66affSColin Finck #endif
111c2c66affSColin Finck #define BOOLEAN_T int
112c2c66affSColin Finck
113c2c66affSColin Finck /* mincore() can be used for debugging purposes */
114c2c66affSColin Finck #define VALID(x) (NULL != (x))
115c2c66affSColin Finck
116c2c66affSColin Finck #if TRIO_ERRORS
117c2c66affSColin Finck /*
118c2c66affSColin Finck * Encode the error code and the position. This is decoded
119c2c66affSColin Finck * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
120c2c66affSColin Finck */
121c2c66affSColin Finck # define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
122c2c66affSColin Finck #else
123c2c66affSColin Finck # define TRIO_ERROR_RETURN(x,y) (-1)
124c2c66affSColin Finck #endif
125c2c66affSColin Finck
126c2c66affSColin Finck #ifndef VA_LIST_IS_ARRAY
127c2c66affSColin Finck #define TRIO_VA_LIST_PTR va_list *
128c2c66affSColin Finck #define TRIO_VA_LIST_ADDR(l) (&(l))
129c2c66affSColin Finck #define TRIO_VA_LIST_DEREF(l) (*(l))
130c2c66affSColin Finck #else
131c2c66affSColin Finck #define TRIO_VA_LIST_PTR va_list
132c2c66affSColin Finck #define TRIO_VA_LIST_ADDR(l) (l)
133c2c66affSColin Finck #define TRIO_VA_LIST_DEREF(l) (l)
134c2c66affSColin Finck #endif
135c2c66affSColin Finck
136c2c66affSColin Finck typedef unsigned long trio_flags_t;
137c2c66affSColin Finck
138c2c66affSColin Finck
139c2c66affSColin Finck /*************************************************************************
140c2c66affSColin Finck * Platform specific definitions
141c2c66affSColin Finck */
142c2c66affSColin Finck #if defined(TRIO_PLATFORM_UNIX) || defined(TRIO_PLATFORM_OS400)
143c2c66affSColin Finck # include <unistd.h>
144c2c66affSColin Finck # include <signal.h>
145c2c66affSColin Finck # include <locale.h>
146c2c66affSColin Finck # define USE_LOCALE
147c2c66affSColin Finck #endif /* TRIO_PLATFORM_UNIX */
148c2c66affSColin Finck #if defined(TRIO_PLATFORM_VMS)
149c2c66affSColin Finck # include <unistd.h>
150c2c66affSColin Finck #endif
151c2c66affSColin Finck #if defined(TRIO_PLATFORM_WIN32)
152c2c66affSColin Finck # if defined(_WIN32_WCE)
153c2c66affSColin Finck # include <wincecompat.h>
154c2c66affSColin Finck # else
155c2c66affSColin Finck # include <io.h>
156c2c66affSColin Finck # define read _read
157c2c66affSColin Finck # define write _write
158c2c66affSColin Finck # endif
159c2c66affSColin Finck #endif /* TRIO_PLATFORM_WIN32 */
160c2c66affSColin Finck
161c2c66affSColin Finck #if TRIO_WIDECHAR
162c2c66affSColin Finck # if defined(TRIO_COMPILER_SUPPORTS_ISO94)
163c2c66affSColin Finck # include <wchar.h>
164c2c66affSColin Finck # include <wctype.h>
165c2c66affSColin Finck typedef wchar_t trio_wchar_t;
166c2c66affSColin Finck typedef wint_t trio_wint_t;
167c2c66affSColin Finck # else
168c2c66affSColin Finck typedef char trio_wchar_t;
169c2c66affSColin Finck typedef int trio_wint_t;
170c2c66affSColin Finck # define WCONST(x) L ## x
171c2c66affSColin Finck # define WEOF EOF
172c2c66affSColin Finck # define iswalnum(x) isalnum(x)
173c2c66affSColin Finck # define iswalpha(x) isalpha(x)
174c2c66affSColin Finck # define iswblank(x) isblank(x)
175c2c66affSColin Finck # define iswcntrl(x) iscntrl(x)
176c2c66affSColin Finck # define iswdigit(x) isdigit(x)
177c2c66affSColin Finck # define iswgraph(x) isgraph(x)
178c2c66affSColin Finck # define iswlower(x) islower(x)
179c2c66affSColin Finck # define iswprint(x) isprint(x)
180c2c66affSColin Finck # define iswpunct(x) ispunct(x)
181c2c66affSColin Finck # define iswspace(x) isspace(x)
182c2c66affSColin Finck # define iswupper(x) isupper(x)
183c2c66affSColin Finck # define iswxdigit(x) isxdigit(x)
184c2c66affSColin Finck # endif
185c2c66affSColin Finck #endif
186c2c66affSColin Finck
187c2c66affSColin Finck
188c2c66affSColin Finck /*************************************************************************
189c2c66affSColin Finck * Compiler dependent definitions
190c2c66affSColin Finck */
191c2c66affSColin Finck
192c2c66affSColin Finck /* Support for long long */
193c2c66affSColin Finck #ifndef __cplusplus
194c2c66affSColin Finck # if !defined(USE_LONGLONG)
195c2c66affSColin Finck # if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
196c2c66affSColin Finck # define USE_LONGLONG
197c2c66affSColin Finck # elif defined(TRIO_COMPILER_SUNPRO)
198c2c66affSColin Finck # define USE_LONGLONG
199c2c66affSColin Finck # elif defined(_LONG_LONG) || defined(_LONGLONG)
200c2c66affSColin Finck # define USE_LONGLONG
201c2c66affSColin Finck # endif
202c2c66affSColin Finck # endif
203c2c66affSColin Finck #endif
204c2c66affSColin Finck
205c2c66affSColin Finck /* The extra long numbers */
206c2c66affSColin Finck #if defined(USE_LONGLONG)
207c2c66affSColin Finck typedef signed long long int trio_longlong_t;
208c2c66affSColin Finck typedef unsigned long long int trio_ulonglong_t;
209c2c66affSColin Finck #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
210c2c66affSColin Finck typedef signed __int64 trio_longlong_t;
211c2c66affSColin Finck typedef unsigned __int64 trio_ulonglong_t;
212c2c66affSColin Finck #else
213c2c66affSColin Finck typedef TRIO_SIGNED long int trio_longlong_t;
214c2c66affSColin Finck typedef unsigned long int trio_ulonglong_t;
215c2c66affSColin Finck #endif
216c2c66affSColin Finck
217c2c66affSColin Finck /* Maximal and fixed integer types */
218c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_C99) && !defined( __VMS )
219c2c66affSColin Finck # include <stdint.h>
220c2c66affSColin Finck typedef intmax_t trio_intmax_t;
221c2c66affSColin Finck typedef uintmax_t trio_uintmax_t;
222c2c66affSColin Finck typedef int8_t trio_int8_t;
223c2c66affSColin Finck typedef int16_t trio_int16_t;
224c2c66affSColin Finck typedef int32_t trio_int32_t;
225c2c66affSColin Finck typedef int64_t trio_int64_t;
226c2c66affSColin Finck #elif defined(TRIO_COMPILER_SUPPORTS_UNIX98) || defined( __VMS )
227c2c66affSColin Finck # include <inttypes.h>
228c2c66affSColin Finck #ifdef __VMS
229c2c66affSColin Finck typedef long long int intmax_t;
230c2c66affSColin Finck typedef unsigned long long int uintmax_t;
231c2c66affSColin Finck #endif
232c2c66affSColin Finck typedef intmax_t trio_intmax_t;
233c2c66affSColin Finck typedef uintmax_t trio_uintmax_t;
234c2c66affSColin Finck typedef int8_t trio_int8_t;
235c2c66affSColin Finck typedef int16_t trio_int16_t;
236c2c66affSColin Finck typedef int32_t trio_int32_t;
237c2c66affSColin Finck typedef int64_t trio_int64_t;
238c2c66affSColin Finck #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
239c2c66affSColin Finck typedef trio_longlong_t trio_intmax_t;
240c2c66affSColin Finck typedef trio_ulonglong_t trio_uintmax_t;
241c2c66affSColin Finck typedef __int8 trio_int8_t;
242c2c66affSColin Finck typedef __int16 trio_int16_t;
243c2c66affSColin Finck typedef __int32 trio_int32_t;
244c2c66affSColin Finck typedef __int64 trio_int64_t;
245c2c66affSColin Finck #else
246c2c66affSColin Finck typedef trio_longlong_t trio_intmax_t;
247c2c66affSColin Finck typedef trio_ulonglong_t trio_uintmax_t;
248c2c66affSColin Finck # if defined(TRIO_INT8_T)
249c2c66affSColin Finck typedef TRIO_INT8_T trio_int8_t;
250c2c66affSColin Finck # else
251c2c66affSColin Finck typedef TRIO_SIGNED char trio_int8_t;
252c2c66affSColin Finck # endif
253c2c66affSColin Finck # if defined(TRIO_INT16_T)
254c2c66affSColin Finck typedef TRIO_INT16_T trio_int16_t;
255c2c66affSColin Finck # else
256c2c66affSColin Finck typedef TRIO_SIGNED short trio_int16_t;
257c2c66affSColin Finck # endif
258c2c66affSColin Finck # if defined(TRIO_INT32_T)
259c2c66affSColin Finck typedef TRIO_INT32_T trio_int32_t;
260c2c66affSColin Finck # else
261c2c66affSColin Finck typedef TRIO_SIGNED int trio_int32_t;
262c2c66affSColin Finck # endif
263c2c66affSColin Finck # if defined(TRIO_INT64_T)
264c2c66affSColin Finck typedef TRIO_INT64_T trio_int64_t;
265c2c66affSColin Finck # else
266c2c66affSColin Finck typedef trio_longlong_t trio_int64_t;
267c2c66affSColin Finck # endif
268c2c66affSColin Finck #endif
269c2c66affSColin Finck
270c2c66affSColin Finck #if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \
271c2c66affSColin Finck || defined(TRIO_COMPILER_SUPPORTS_UNIX01))) \
272c2c66affSColin Finck && !defined(_WIN32_WCE)
273c2c66affSColin Finck # define floorl(x) floor((double)(x))
274c2c66affSColin Finck # define fmodl(x,y) fmod((double)(x),(double)(y))
275c2c66affSColin Finck # define powl(x,y) pow((double)(x),(double)(y))
276c2c66affSColin Finck #endif
277c2c66affSColin Finck
278c2c66affSColin Finck #define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
279c2c66affSColin Finck
280c2c66affSColin Finck /*************************************************************************
281c2c66affSColin Finck * Internal Definitions
282c2c66affSColin Finck */
283c2c66affSColin Finck
284c2c66affSColin Finck #ifndef DECIMAL_DIG
285c2c66affSColin Finck # define DECIMAL_DIG DBL_DIG
286c2c66affSColin Finck #endif
287c2c66affSColin Finck
288c2c66affSColin Finck /* Long double sizes */
289c2c66affSColin Finck #ifdef LDBL_DIG
290c2c66affSColin Finck # define MAX_MANTISSA_DIGITS LDBL_DIG
291c2c66affSColin Finck # define MAX_EXPONENT_DIGITS 4
292c2c66affSColin Finck # define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
293c2c66affSColin Finck #else
294c2c66affSColin Finck # define MAX_MANTISSA_DIGITS DECIMAL_DIG
295c2c66affSColin Finck # define MAX_EXPONENT_DIGITS 3
296c2c66affSColin Finck # define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
297c2c66affSColin Finck #endif
298c2c66affSColin Finck
299c2c66affSColin Finck #if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
300c2c66affSColin Finck # undef LDBL_DIG
301c2c66affSColin Finck # undef LDBL_MANT_DIG
302c2c66affSColin Finck # undef LDBL_EPSILON
303c2c66affSColin Finck # define LDBL_DIG DBL_DIG
304c2c66affSColin Finck # define LDBL_MANT_DIG DBL_MANT_DIG
305c2c66affSColin Finck # define LDBL_EPSILON DBL_EPSILON
306c2c66affSColin Finck #endif
307c2c66affSColin Finck
308c2c66affSColin Finck /* The maximal number of digits is for base 2 */
309c2c66affSColin Finck #define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
310c2c66affSColin Finck /* The width of a pointer. The number of bits in a hex digit is 4 */
311c2c66affSColin Finck #define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
312c2c66affSColin Finck
313c2c66affSColin Finck /* Infinite and Not-A-Number for floating-point */
314c2c66affSColin Finck #define INFINITE_LOWER "inf"
315c2c66affSColin Finck #define INFINITE_UPPER "INF"
316c2c66affSColin Finck #define LONG_INFINITE_LOWER "infinite"
317c2c66affSColin Finck #define LONG_INFINITE_UPPER "INFINITE"
318c2c66affSColin Finck #define NAN_LOWER "nan"
319c2c66affSColin Finck #define NAN_UPPER "NAN"
320c2c66affSColin Finck
321c2c66affSColin Finck #if !defined(HAVE_ISASCII) && !defined(isascii)
322c2c66affSColin Finck #ifndef __VMS
323c2c66affSColin Finck # define isascii(x) ((unsigned int)(x) < 128)
324c2c66affSColin Finck #endif
325c2c66affSColin Finck #endif
326c2c66affSColin Finck
327c2c66affSColin Finck /* Various constants */
328c2c66affSColin Finck enum {
329c2c66affSColin Finck TYPE_PRINT = 1,
330c2c66affSColin Finck TYPE_SCAN = 2,
331c2c66affSColin Finck
332c2c66affSColin Finck /* Flags. FLAGS_LAST must be less than ULONG_MAX */
333c2c66affSColin Finck FLAGS_NEW = 0,
334c2c66affSColin Finck FLAGS_STICKY = 1,
335c2c66affSColin Finck FLAGS_SPACE = 2 * FLAGS_STICKY,
336c2c66affSColin Finck FLAGS_SHOWSIGN = 2 * FLAGS_SPACE,
337c2c66affSColin Finck FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN,
338c2c66affSColin Finck FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST,
339c2c66affSColin Finck FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE,
340c2c66affSColin Finck FLAGS_SHORTSHORT = 2 * FLAGS_SHORT,
341c2c66affSColin Finck FLAGS_LONG = 2 * FLAGS_SHORTSHORT,
342c2c66affSColin Finck FLAGS_QUAD = 2 * FLAGS_LONG,
343c2c66affSColin Finck FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD,
344c2c66affSColin Finck FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE,
345c2c66affSColin Finck FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T,
346c2c66affSColin Finck FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T,
347c2c66affSColin Finck FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T,
348c2c66affSColin Finck FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING,
349c2c66affSColin Finck FLAGS_UPPER = 2 * FLAGS_UNSIGNED,
350c2c66affSColin Finck FLAGS_WIDTH = 2 * FLAGS_UPPER,
351c2c66affSColin Finck FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH,
352c2c66affSColin Finck FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER,
353c2c66affSColin Finck FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION,
354c2c66affSColin Finck FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER,
355c2c66affSColin Finck FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE,
356c2c66affSColin Finck FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER,
357c2c66affSColin Finck FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E,
358c2c66affSColin Finck FLAGS_QUOTE = 2 * FLAGS_FLOAT_G,
359c2c66affSColin Finck FLAGS_WIDECHAR = 2 * FLAGS_QUOTE,
360c2c66affSColin Finck FLAGS_ALLOC = 2 * FLAGS_WIDECHAR,
361c2c66affSColin Finck FLAGS_IGNORE = 2 * FLAGS_ALLOC,
362c2c66affSColin Finck FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE,
363c2c66affSColin Finck FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
364c2c66affSColin Finck FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER,
365c2c66affSColin Finck FLAGS_LAST = FLAGS_FIXED_SIZE,
366c2c66affSColin Finck /* Reused flags */
367c2c66affSColin Finck FLAGS_EXCLUDE = FLAGS_SHORT,
368c2c66affSColin Finck FLAGS_USER_DEFINED = FLAGS_IGNORE,
369c2c66affSColin Finck FLAGS_ROUNDING = FLAGS_INTMAX_T,
370c2c66affSColin Finck /* Compounded flags */
371c2c66affSColin Finck FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
372c2c66affSColin Finck FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT,
373c2c66affSColin Finck
374c2c66affSColin Finck NO_POSITION = -1,
375c2c66affSColin Finck NO_WIDTH = 0,
376c2c66affSColin Finck NO_PRECISION = -1,
377c2c66affSColin Finck NO_SIZE = -1,
378c2c66affSColin Finck
379c2c66affSColin Finck /* Do not change these */
380c2c66affSColin Finck NO_BASE = -1,
381c2c66affSColin Finck MIN_BASE = 2,
382c2c66affSColin Finck MAX_BASE = 36,
383c2c66affSColin Finck BASE_BINARY = 2,
384c2c66affSColin Finck BASE_OCTAL = 8,
385c2c66affSColin Finck BASE_DECIMAL = 10,
386c2c66affSColin Finck BASE_HEX = 16,
387c2c66affSColin Finck
388c2c66affSColin Finck /* Maximal number of allowed parameters */
389c2c66affSColin Finck MAX_PARAMETERS = 64,
390c2c66affSColin Finck /* Maximal number of characters in class */
391c2c66affSColin Finck MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
392c2c66affSColin Finck
393c2c66affSColin Finck /* Maximal string lengths for user-defined specifiers */
394c2c66affSColin Finck MAX_USER_NAME = 64,
395c2c66affSColin Finck MAX_USER_DATA = 256,
396c2c66affSColin Finck
397c2c66affSColin Finck /* Maximal length of locale separator strings */
398c2c66affSColin Finck MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
399c2c66affSColin Finck /* Maximal number of integers in grouping */
400c2c66affSColin Finck MAX_LOCALE_GROUPS = 64,
401c2c66affSColin Finck
402c2c66affSColin Finck /* Initial size of asprintf buffer */
403c2c66affSColin Finck DYNAMIC_START_SIZE = 32
404c2c66affSColin Finck };
405c2c66affSColin Finck
406c2c66affSColin Finck #define NO_GROUPING ((int)CHAR_MAX)
407c2c66affSColin Finck
408c2c66affSColin Finck /* Fundamental formatting parameter types */
409c2c66affSColin Finck #define FORMAT_UNKNOWN 0
410c2c66affSColin Finck #define FORMAT_INT 1
411c2c66affSColin Finck #define FORMAT_DOUBLE 2
412c2c66affSColin Finck #define FORMAT_CHAR 3
413c2c66affSColin Finck #define FORMAT_STRING 4
414c2c66affSColin Finck #define FORMAT_POINTER 5
415c2c66affSColin Finck #define FORMAT_COUNT 6
416c2c66affSColin Finck #define FORMAT_PARAMETER 7
417c2c66affSColin Finck #define FORMAT_GROUP 8
418c2c66affSColin Finck #if TRIO_GNU
419c2c66affSColin Finck # define FORMAT_ERRNO 9
420c2c66affSColin Finck #endif
421c2c66affSColin Finck #if TRIO_EXTENSION
422c2c66affSColin Finck # define FORMAT_USER_DEFINED 10
423c2c66affSColin Finck #endif
424c2c66affSColin Finck
425c2c66affSColin Finck /* Character constants */
426c2c66affSColin Finck #define CHAR_IDENTIFIER '%'
427c2c66affSColin Finck #define CHAR_BACKSLASH '\\'
428c2c66affSColin Finck #define CHAR_QUOTE '\"'
429c2c66affSColin Finck #define CHAR_ADJUST ' '
430c2c66affSColin Finck
431c2c66affSColin Finck /* Character class expressions */
432c2c66affSColin Finck #define CLASS_ALNUM "[:alnum:]"
433c2c66affSColin Finck #define CLASS_ALPHA "[:alpha:]"
434c2c66affSColin Finck #define CLASS_BLANK "[:blank:]"
435c2c66affSColin Finck #define CLASS_CNTRL "[:cntrl:]"
436c2c66affSColin Finck #define CLASS_DIGIT "[:digit:]"
437c2c66affSColin Finck #define CLASS_GRAPH "[:graph:]"
438c2c66affSColin Finck #define CLASS_LOWER "[:lower:]"
439c2c66affSColin Finck #define CLASS_PRINT "[:print:]"
440c2c66affSColin Finck #define CLASS_PUNCT "[:punct:]"
441c2c66affSColin Finck #define CLASS_SPACE "[:space:]"
442c2c66affSColin Finck #define CLASS_UPPER "[:upper:]"
443c2c66affSColin Finck #define CLASS_XDIGIT "[:xdigit:]"
444c2c66affSColin Finck
445c2c66affSColin Finck /*
446c2c66affSColin Finck * SPECIFIERS:
447c2c66affSColin Finck *
448c2c66affSColin Finck *
449c2c66affSColin Finck * a Hex-float
450c2c66affSColin Finck * A Hex-float
451c2c66affSColin Finck * c Character
452c2c66affSColin Finck * C Widechar character (wint_t)
453c2c66affSColin Finck * d Decimal
454c2c66affSColin Finck * e Float
455c2c66affSColin Finck * E Float
456c2c66affSColin Finck * F Float
457c2c66affSColin Finck * F Float
458c2c66affSColin Finck * g Float
459c2c66affSColin Finck * G Float
460c2c66affSColin Finck * i Integer
461c2c66affSColin Finck * m Error message
462c2c66affSColin Finck * n Count
463c2c66affSColin Finck * o Octal
464c2c66affSColin Finck * p Pointer
465c2c66affSColin Finck * s String
466c2c66affSColin Finck * S Widechar string (wchar_t *)
467c2c66affSColin Finck * u Unsigned
468c2c66affSColin Finck * x Hex
469c2c66affSColin Finck * X Hex
470c2c66affSColin Finck * [] Group
471c2c66affSColin Finck * <> User-defined
472c2c66affSColin Finck *
473c2c66affSColin Finck * Reserved:
474c2c66affSColin Finck *
475c2c66affSColin Finck * D Binary Coded Decimal %D(length,precision) (OS/390)
476c2c66affSColin Finck */
477c2c66affSColin Finck #define SPECIFIER_CHAR 'c'
478c2c66affSColin Finck #define SPECIFIER_STRING 's'
479c2c66affSColin Finck #define SPECIFIER_DECIMAL 'd'
480c2c66affSColin Finck #define SPECIFIER_INTEGER 'i'
481c2c66affSColin Finck #define SPECIFIER_UNSIGNED 'u'
482c2c66affSColin Finck #define SPECIFIER_OCTAL 'o'
483c2c66affSColin Finck #define SPECIFIER_HEX 'x'
484c2c66affSColin Finck #define SPECIFIER_HEX_UPPER 'X'
485c2c66affSColin Finck #define SPECIFIER_FLOAT_E 'e'
486c2c66affSColin Finck #define SPECIFIER_FLOAT_E_UPPER 'E'
487c2c66affSColin Finck #define SPECIFIER_FLOAT_F 'f'
488c2c66affSColin Finck #define SPECIFIER_FLOAT_F_UPPER 'F'
489c2c66affSColin Finck #define SPECIFIER_FLOAT_G 'g'
490c2c66affSColin Finck #define SPECIFIER_FLOAT_G_UPPER 'G'
491c2c66affSColin Finck #define SPECIFIER_POINTER 'p'
492c2c66affSColin Finck #define SPECIFIER_GROUP '['
493c2c66affSColin Finck #define SPECIFIER_UNGROUP ']'
494c2c66affSColin Finck #define SPECIFIER_COUNT 'n'
495c2c66affSColin Finck #if TRIO_UNIX98
496c2c66affSColin Finck # define SPECIFIER_CHAR_UPPER 'C'
497c2c66affSColin Finck # define SPECIFIER_STRING_UPPER 'S'
498c2c66affSColin Finck #endif
499c2c66affSColin Finck #if TRIO_C99
500c2c66affSColin Finck # define SPECIFIER_HEXFLOAT 'a'
501c2c66affSColin Finck # define SPECIFIER_HEXFLOAT_UPPER 'A'
502c2c66affSColin Finck #endif
503c2c66affSColin Finck #if TRIO_GNU
504c2c66affSColin Finck # define SPECIFIER_ERRNO 'm'
505c2c66affSColin Finck #endif
506c2c66affSColin Finck #if TRIO_EXTENSION
507c2c66affSColin Finck # define SPECIFIER_BINARY 'b'
508c2c66affSColin Finck # define SPECIFIER_BINARY_UPPER 'B'
509c2c66affSColin Finck # define SPECIFIER_USER_DEFINED_BEGIN '<'
510c2c66affSColin Finck # define SPECIFIER_USER_DEFINED_END '>'
511c2c66affSColin Finck # define SPECIFIER_USER_DEFINED_SEPARATOR ':'
512c2c66affSColin Finck #endif
513c2c66affSColin Finck
514c2c66affSColin Finck /*
515c2c66affSColin Finck * QUALIFIERS:
516c2c66affSColin Finck *
517c2c66affSColin Finck *
518c2c66affSColin Finck * Numbers = d,i,o,u,x,X
519c2c66affSColin Finck * Float = a,A,e,E,f,F,g,G
520c2c66affSColin Finck * String = s
521c2c66affSColin Finck * Char = c
522c2c66affSColin Finck *
523c2c66affSColin Finck *
524c2c66affSColin Finck * 9$ Position
525c2c66affSColin Finck * Use the 9th parameter. 9 can be any number between 1 and
526c2c66affSColin Finck * the maximal argument
527c2c66affSColin Finck *
528c2c66affSColin Finck * 9 Width
529c2c66affSColin Finck * Set width to 9. 9 can be any number, but must not be postfixed
530c2c66affSColin Finck * by '$'
531c2c66affSColin Finck *
532c2c66affSColin Finck * h Short
533c2c66affSColin Finck * Numbers:
534c2c66affSColin Finck * (unsigned) short int
535c2c66affSColin Finck *
536c2c66affSColin Finck * hh Short short
537c2c66affSColin Finck * Numbers:
538c2c66affSColin Finck * (unsigned) char
539c2c66affSColin Finck *
540c2c66affSColin Finck * l Long
541c2c66affSColin Finck * Numbers:
542c2c66affSColin Finck * (unsigned) long int
543c2c66affSColin Finck * String:
544c2c66affSColin Finck * as the S specifier
545c2c66affSColin Finck * Char:
546c2c66affSColin Finck * as the C specifier
547c2c66affSColin Finck *
548c2c66affSColin Finck * ll Long Long
549c2c66affSColin Finck * Numbers:
550c2c66affSColin Finck * (unsigned) long long int
551c2c66affSColin Finck *
552c2c66affSColin Finck * L Long Double
553c2c66affSColin Finck * Float
554c2c66affSColin Finck * long double
555c2c66affSColin Finck *
556c2c66affSColin Finck * # Alternative
557c2c66affSColin Finck * Float:
558c2c66affSColin Finck * Decimal-point is always present
559c2c66affSColin Finck * String:
560c2c66affSColin Finck * non-printable characters are handled as \number
561c2c66affSColin Finck *
562c2c66affSColin Finck * Spacing
563c2c66affSColin Finck *
564c2c66affSColin Finck * + Sign
565c2c66affSColin Finck *
566c2c66affSColin Finck * - Alignment
567c2c66affSColin Finck *
568c2c66affSColin Finck * . Precision
569c2c66affSColin Finck *
570c2c66affSColin Finck * * Parameter
571c2c66affSColin Finck * print: use parameter
572c2c66affSColin Finck * scan: no parameter (ignore)
573c2c66affSColin Finck *
574c2c66affSColin Finck * q Quad
575c2c66affSColin Finck *
576c2c66affSColin Finck * Z size_t
577c2c66affSColin Finck *
578c2c66affSColin Finck * w Widechar
579c2c66affSColin Finck *
580c2c66affSColin Finck * ' Thousands/quote
581c2c66affSColin Finck * Numbers:
582c2c66affSColin Finck * Integer part grouped in thousands
583c2c66affSColin Finck * Binary numbers:
584c2c66affSColin Finck * Number grouped in nibbles (4 bits)
585c2c66affSColin Finck * String:
586c2c66affSColin Finck * Quoted string
587c2c66affSColin Finck *
588c2c66affSColin Finck * j intmax_t
589c2c66affSColin Finck * t prtdiff_t
590c2c66affSColin Finck * z size_t
591c2c66affSColin Finck *
592c2c66affSColin Finck * ! Sticky
593c2c66affSColin Finck * @ Parameter (for both print and scan)
594c2c66affSColin Finck *
595c2c66affSColin Finck * I n-bit Integer
596c2c66affSColin Finck * Numbers:
597c2c66affSColin Finck * The following options exists
598c2c66affSColin Finck * I8 = 8-bit integer
599c2c66affSColin Finck * I16 = 16-bit integer
600c2c66affSColin Finck * I32 = 32-bit integer
601c2c66affSColin Finck * I64 = 64-bit integer
602c2c66affSColin Finck */
603c2c66affSColin Finck #define QUALIFIER_POSITION '$'
604c2c66affSColin Finck #define QUALIFIER_SHORT 'h'
605c2c66affSColin Finck #define QUALIFIER_LONG 'l'
606c2c66affSColin Finck #define QUALIFIER_LONG_UPPER 'L'
607c2c66affSColin Finck #define QUALIFIER_ALTERNATIVE '#'
608c2c66affSColin Finck #define QUALIFIER_SPACE ' '
609c2c66affSColin Finck #define QUALIFIER_PLUS '+'
610c2c66affSColin Finck #define QUALIFIER_MINUS '-'
611c2c66affSColin Finck #define QUALIFIER_DOT '.'
612c2c66affSColin Finck #define QUALIFIER_STAR '*'
613c2c66affSColin Finck #define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
614c2c66affSColin Finck #if TRIO_C99
615c2c66affSColin Finck # define QUALIFIER_SIZE_T 'z'
616c2c66affSColin Finck # define QUALIFIER_PTRDIFF_T 't'
617c2c66affSColin Finck # define QUALIFIER_INTMAX_T 'j'
618c2c66affSColin Finck #endif
619c2c66affSColin Finck #if TRIO_BSD || TRIO_GNU
620c2c66affSColin Finck # define QUALIFIER_QUAD 'q'
621c2c66affSColin Finck #endif
622c2c66affSColin Finck #if TRIO_GNU
623c2c66affSColin Finck # define QUALIFIER_SIZE_T_UPPER 'Z'
624c2c66affSColin Finck #endif
625c2c66affSColin Finck #if TRIO_MISC
626c2c66affSColin Finck # define QUALIFIER_WIDECHAR 'w'
627c2c66affSColin Finck #endif
628c2c66affSColin Finck #if TRIO_MICROSOFT
629c2c66affSColin Finck # define QUALIFIER_FIXED_SIZE 'I'
630c2c66affSColin Finck #endif
631c2c66affSColin Finck #if TRIO_EXTENSION
632c2c66affSColin Finck # define QUALIFIER_QUOTE '\''
633c2c66affSColin Finck # define QUALIFIER_STICKY '!'
634c2c66affSColin Finck # define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
635c2c66affSColin Finck # define QUALIFIER_PARAM '@' /* Experimental */
636c2c66affSColin Finck # define QUALIFIER_COLON ':' /* For scanlists */
637c2c66affSColin Finck # define QUALIFIER_EQUAL '=' /* For scanlists */
638c2c66affSColin Finck # define QUALIFIER_ROUNDING_UPPER 'R'
639c2c66affSColin Finck #endif
640c2c66affSColin Finck
641c2c66affSColin Finck
642c2c66affSColin Finck /*************************************************************************
643c2c66affSColin Finck *
644c2c66affSColin Finck * Internal Structures
645c2c66affSColin Finck *
646c2c66affSColin Finck *************************************************************************/
647c2c66affSColin Finck
648c2c66affSColin Finck /* Parameters */
649c2c66affSColin Finck typedef struct {
650c2c66affSColin Finck /* An indication of which entry in the data union is used */
651c2c66affSColin Finck int type;
652c2c66affSColin Finck /* The flags */
653c2c66affSColin Finck trio_flags_t flags;
654c2c66affSColin Finck /* The width qualifier */
655c2c66affSColin Finck int width;
656c2c66affSColin Finck /* The precision qualifier */
657c2c66affSColin Finck int precision;
658c2c66affSColin Finck /* The base qualifier */
659c2c66affSColin Finck int base;
660c2c66affSColin Finck /* The size for the variable size qualifier */
661c2c66affSColin Finck int varsize;
662c2c66affSColin Finck /* The marker of the end of the specifier */
663c2c66affSColin Finck int indexAfterSpecifier;
664c2c66affSColin Finck /* The data from the argument list */
665c2c66affSColin Finck union {
666c2c66affSColin Finck char *string;
667c2c66affSColin Finck #if TRIO_WIDECHAR
668c2c66affSColin Finck trio_wchar_t *wstring;
669c2c66affSColin Finck #endif
670c2c66affSColin Finck trio_pointer_t pointer;
671c2c66affSColin Finck union {
672c2c66affSColin Finck trio_intmax_t as_signed;
673c2c66affSColin Finck trio_uintmax_t as_unsigned;
674c2c66affSColin Finck } number;
675c2c66affSColin Finck double doubleNumber;
676c2c66affSColin Finck double *doublePointer;
677c2c66affSColin Finck trio_long_double_t longdoubleNumber;
678c2c66affSColin Finck trio_long_double_t *longdoublePointer;
679c2c66affSColin Finck int errorNumber;
680c2c66affSColin Finck } data;
681c2c66affSColin Finck /* For the user-defined specifier */
682c2c66affSColin Finck char user_name[MAX_USER_NAME];
683c2c66affSColin Finck char user_data[MAX_USER_DATA];
684c2c66affSColin Finck } trio_parameter_t;
685c2c66affSColin Finck
686c2c66affSColin Finck /* Container for customized functions */
687c2c66affSColin Finck typedef struct {
688c2c66affSColin Finck union {
689c2c66affSColin Finck trio_outstream_t out;
690c2c66affSColin Finck trio_instream_t in;
691c2c66affSColin Finck } stream;
692c2c66affSColin Finck trio_pointer_t closure;
693c2c66affSColin Finck } trio_custom_t;
694c2c66affSColin Finck
695c2c66affSColin Finck /* General trio "class" */
696c2c66affSColin Finck typedef struct _trio_class_t {
697c2c66affSColin Finck /*
698c2c66affSColin Finck * The function to write characters to a stream.
699c2c66affSColin Finck */
700c2c66affSColin Finck void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int));
701c2c66affSColin Finck /*
702c2c66affSColin Finck * The function to read characters from a stream.
703c2c66affSColin Finck */
704c2c66affSColin Finck void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
705c2c66affSColin Finck /*
706c2c66affSColin Finck * The current location in the stream.
707c2c66affSColin Finck */
708c2c66affSColin Finck trio_pointer_t location;
709c2c66affSColin Finck /*
710c2c66affSColin Finck * The character currently being processed.
711c2c66affSColin Finck */
712c2c66affSColin Finck int current;
713c2c66affSColin Finck /*
714c2c66affSColin Finck * The number of characters that would have been written/read
715c2c66affSColin Finck * if there had been sufficient space.
716c2c66affSColin Finck */
717c2c66affSColin Finck int processed;
718c2c66affSColin Finck /*
719c2c66affSColin Finck * The number of characters that are actually written/read.
720c2c66affSColin Finck * Processed and committed will only differ for the *nprintf
721c2c66affSColin Finck * and *nscanf functions.
722c2c66affSColin Finck */
723c2c66affSColin Finck int committed;
724c2c66affSColin Finck /*
725c2c66affSColin Finck * The upper limit of characters that may be written/read.
726c2c66affSColin Finck */
727c2c66affSColin Finck int max;
728c2c66affSColin Finck /*
729c2c66affSColin Finck * The last output error that was detected.
730c2c66affSColin Finck */
731c2c66affSColin Finck int error;
732c2c66affSColin Finck } trio_class_t;
733c2c66affSColin Finck
734c2c66affSColin Finck /* References (for user-defined callbacks) */
735c2c66affSColin Finck typedef struct _trio_reference_t {
736c2c66affSColin Finck trio_class_t *data;
737c2c66affSColin Finck trio_parameter_t *parameter;
738c2c66affSColin Finck } trio_reference_t;
739c2c66affSColin Finck
740c2c66affSColin Finck /* Registered entries (for user-defined callbacks) */
741c2c66affSColin Finck typedef struct _trio_userdef_t {
742c2c66affSColin Finck struct _trio_userdef_t *next;
743c2c66affSColin Finck trio_callback_t callback;
744c2c66affSColin Finck char *name;
745c2c66affSColin Finck } trio_userdef_t;
746c2c66affSColin Finck
747c2c66affSColin Finck /*************************************************************************
748c2c66affSColin Finck *
749c2c66affSColin Finck * Internal Variables
750c2c66affSColin Finck *
751c2c66affSColin Finck *************************************************************************/
752c2c66affSColin Finck
753c2c66affSColin Finck static TRIO_CONST char rcsid[] = "@(#)$Id$";
754c2c66affSColin Finck
755c2c66affSColin Finck /*
756c2c66affSColin Finck * Need this to workaround a parser bug in HP C/iX compiler that fails
757c2c66affSColin Finck * to resolves macro definitions that includes type 'long double',
758c2c66affSColin Finck * e.g: va_arg(arg_ptr, long double)
759c2c66affSColin Finck */
760c2c66affSColin Finck #if defined(TRIO_PLATFORM_MPEIX)
761c2c66affSColin Finck static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
762c2c66affSColin Finck #endif
763c2c66affSColin Finck
764c2c66affSColin Finck static TRIO_CONST char internalNullString[] = "(nil)";
765c2c66affSColin Finck
766c2c66affSColin Finck #if defined(USE_LOCALE)
767c2c66affSColin Finck static struct lconv *internalLocaleValues = NULL;
768c2c66affSColin Finck #endif
769c2c66affSColin Finck
770c2c66affSColin Finck /*
771c2c66affSColin Finck * UNIX98 says "in a locale where the radix character is not defined,
772c2c66affSColin Finck * the radix character defaults to a period (.)"
773c2c66affSColin Finck */
774c2c66affSColin Finck static int internalDecimalPointLength = 1;
775c2c66affSColin Finck static int internalThousandSeparatorLength = 1;
776c2c66affSColin Finck static char internalDecimalPoint = '.';
777c2c66affSColin Finck static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
778c2c66affSColin Finck static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
779c2c66affSColin Finck static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
780c2c66affSColin Finck
781c2c66affSColin Finck static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
782c2c66affSColin Finck static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
783c2c66affSColin Finck static BOOLEAN_T internalDigitsUnconverted = TRUE;
784c2c66affSColin Finck static int internalDigitArray[128];
785c2c66affSColin Finck #if TRIO_EXTENSION
786c2c66affSColin Finck static BOOLEAN_T internalCollationUnconverted = TRUE;
787c2c66affSColin Finck static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
788c2c66affSColin Finck #endif
789c2c66affSColin Finck
790c2c66affSColin Finck #if TRIO_EXTENSION
791c2c66affSColin Finck static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
792c2c66affSColin Finck static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
793c2c66affSColin Finck static trio_userdef_t *internalUserDef = NULL;
794c2c66affSColin Finck #endif
795c2c66affSColin Finck
796c2c66affSColin Finck
797c2c66affSColin Finck /*************************************************************************
798c2c66affSColin Finck *
799c2c66affSColin Finck * Internal Functions
800c2c66affSColin Finck *
801c2c66affSColin Finck ************************************************************************/
802c2c66affSColin Finck
803c2c66affSColin Finck #if defined(TRIO_MINIMAL)
804c2c66affSColin Finck # define TRIO_STRING_PUBLIC static
805c2c66affSColin Finck # include "triostr.c"
806c2c66affSColin Finck #endif /* defined(TRIO_MINIMAL) */
807c2c66affSColin Finck
808c2c66affSColin Finck /*************************************************************************
809c2c66affSColin Finck * TrioIsQualifier
810c2c66affSColin Finck *
811c2c66affSColin Finck * Description:
812c2c66affSColin Finck * Remember to add all new qualifiers to this function.
813c2c66affSColin Finck * QUALIFIER_POSITION must not be added.
814c2c66affSColin Finck */
815c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
816c2c66affSColin Finck TrioIsQualifier
817c2c66affSColin Finck TRIO_ARGS1((character),
818c2c66affSColin Finck TRIO_CONST char character)
819c2c66affSColin Finck {
820c2c66affSColin Finck /* QUALIFIER_POSITION is not included */
821c2c66affSColin Finck switch (character)
822c2c66affSColin Finck {
823c2c66affSColin Finck case '0': case '1': case '2': case '3': case '4':
824c2c66affSColin Finck case '5': case '6': case '7': case '8': case '9':
825c2c66affSColin Finck case QUALIFIER_PLUS:
826c2c66affSColin Finck case QUALIFIER_MINUS:
827c2c66affSColin Finck case QUALIFIER_SPACE:
828c2c66affSColin Finck case QUALIFIER_DOT:
829c2c66affSColin Finck case QUALIFIER_STAR:
830c2c66affSColin Finck case QUALIFIER_ALTERNATIVE:
831c2c66affSColin Finck case QUALIFIER_SHORT:
832c2c66affSColin Finck case QUALIFIER_LONG:
833c2c66affSColin Finck case QUALIFIER_LONG_UPPER:
834c2c66affSColin Finck case QUALIFIER_CIRCUMFLEX:
835c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T)
836c2c66affSColin Finck case QUALIFIER_SIZE_T:
837c2c66affSColin Finck #endif
838c2c66affSColin Finck #if defined(QUALIFIER_PTRDIFF_T)
839c2c66affSColin Finck case QUALIFIER_PTRDIFF_T:
840c2c66affSColin Finck #endif
841c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
842c2c66affSColin Finck case QUALIFIER_INTMAX_T:
843c2c66affSColin Finck #endif
844c2c66affSColin Finck #if defined(QUALIFIER_QUAD)
845c2c66affSColin Finck case QUALIFIER_QUAD:
846c2c66affSColin Finck #endif
847c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T_UPPER)
848c2c66affSColin Finck case QUALIFIER_SIZE_T_UPPER:
849c2c66affSColin Finck #endif
850c2c66affSColin Finck #if defined(QUALIFIER_WIDECHAR)
851c2c66affSColin Finck case QUALIFIER_WIDECHAR:
852c2c66affSColin Finck #endif
853c2c66affSColin Finck #if defined(QUALIFIER_QUOTE)
854c2c66affSColin Finck case QUALIFIER_QUOTE:
855c2c66affSColin Finck #endif
856c2c66affSColin Finck #if defined(QUALIFIER_STICKY)
857c2c66affSColin Finck case QUALIFIER_STICKY:
858c2c66affSColin Finck #endif
859c2c66affSColin Finck #if defined(QUALIFIER_VARSIZE)
860c2c66affSColin Finck case QUALIFIER_VARSIZE:
861c2c66affSColin Finck #endif
862c2c66affSColin Finck #if defined(QUALIFIER_PARAM)
863c2c66affSColin Finck case QUALIFIER_PARAM:
864c2c66affSColin Finck #endif
865c2c66affSColin Finck #if defined(QUALIFIER_FIXED_SIZE)
866c2c66affSColin Finck case QUALIFIER_FIXED_SIZE:
867c2c66affSColin Finck #endif
868c2c66affSColin Finck #if defined(QUALIFIER_ROUNDING_UPPER)
869c2c66affSColin Finck case QUALIFIER_ROUNDING_UPPER:
870c2c66affSColin Finck #endif
871c2c66affSColin Finck return TRUE;
872c2c66affSColin Finck default:
873c2c66affSColin Finck return FALSE;
874c2c66affSColin Finck }
875c2c66affSColin Finck }
876c2c66affSColin Finck
877c2c66affSColin Finck /*************************************************************************
878c2c66affSColin Finck * TrioSetLocale
879c2c66affSColin Finck */
880c2c66affSColin Finck #if defined(USE_LOCALE)
881c2c66affSColin Finck TRIO_PRIVATE void
TrioSetLocale(TRIO_NOARGS)882c2c66affSColin Finck TrioSetLocale(TRIO_NOARGS)
883c2c66affSColin Finck {
884c2c66affSColin Finck internalLocaleValues = (struct lconv *)localeconv();
885c2c66affSColin Finck if (internalLocaleValues)
886c2c66affSColin Finck {
887c2c66affSColin Finck if ((internalLocaleValues->decimal_point) &&
888c2c66affSColin Finck (internalLocaleValues->decimal_point[0] != NIL))
889c2c66affSColin Finck {
890c2c66affSColin Finck internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point);
891c2c66affSColin Finck if (internalDecimalPointLength == 1)
892c2c66affSColin Finck {
893c2c66affSColin Finck internalDecimalPoint = internalLocaleValues->decimal_point[0];
894c2c66affSColin Finck }
895c2c66affSColin Finck else
896c2c66affSColin Finck {
897c2c66affSColin Finck internalDecimalPoint = NIL;
898c2c66affSColin Finck trio_copy_max(internalDecimalPointString,
899c2c66affSColin Finck sizeof(internalDecimalPointString),
900c2c66affSColin Finck internalLocaleValues->decimal_point);
901c2c66affSColin Finck }
902c2c66affSColin Finck }
903c2c66affSColin Finck if ((internalLocaleValues->thousands_sep) &&
904c2c66affSColin Finck (internalLocaleValues->thousands_sep[0] != NIL))
905c2c66affSColin Finck {
906c2c66affSColin Finck trio_copy_max(internalThousandSeparator,
907c2c66affSColin Finck sizeof(internalThousandSeparator),
908c2c66affSColin Finck internalLocaleValues->thousands_sep);
909c2c66affSColin Finck internalThousandSeparatorLength = trio_length(internalThousandSeparator);
910c2c66affSColin Finck }
911c2c66affSColin Finck if ((internalLocaleValues->grouping) &&
912c2c66affSColin Finck (internalLocaleValues->grouping[0] != NIL))
913c2c66affSColin Finck {
914c2c66affSColin Finck trio_copy_max(internalGrouping,
915c2c66affSColin Finck sizeof(internalGrouping),
916c2c66affSColin Finck internalLocaleValues->grouping);
917c2c66affSColin Finck }
918c2c66affSColin Finck }
919c2c66affSColin Finck }
920c2c66affSColin Finck #endif /* defined(USE_LOCALE) */
921c2c66affSColin Finck
922c2c66affSColin Finck TRIO_PRIVATE int
923c2c66affSColin Finck TrioCalcThousandSeparatorLength
924c2c66affSColin Finck TRIO_ARGS1((digits),
925c2c66affSColin Finck int digits)
926c2c66affSColin Finck {
927c2c66affSColin Finck #if TRIO_EXTENSION
928c2c66affSColin Finck int count = 0;
929c2c66affSColin Finck int step = NO_GROUPING;
930c2c66affSColin Finck char *groupingPointer = internalGrouping;
931c2c66affSColin Finck
932c2c66affSColin Finck while (digits > 0)
933c2c66affSColin Finck {
934c2c66affSColin Finck if (*groupingPointer == CHAR_MAX)
935c2c66affSColin Finck {
936c2c66affSColin Finck /* Disable grouping */
937c2c66affSColin Finck break; /* while */
938c2c66affSColin Finck }
939c2c66affSColin Finck else if (*groupingPointer == 0)
940c2c66affSColin Finck {
941c2c66affSColin Finck /* Repeat last group */
942c2c66affSColin Finck if (step == NO_GROUPING)
943c2c66affSColin Finck {
944c2c66affSColin Finck /* Error in locale */
945c2c66affSColin Finck break; /* while */
946c2c66affSColin Finck }
947c2c66affSColin Finck }
948c2c66affSColin Finck else
949c2c66affSColin Finck {
950c2c66affSColin Finck step = *groupingPointer++;
951c2c66affSColin Finck }
952c2c66affSColin Finck if (digits > step)
953c2c66affSColin Finck count += internalThousandSeparatorLength;
954c2c66affSColin Finck digits -= step;
955c2c66affSColin Finck }
956c2c66affSColin Finck return count;
957c2c66affSColin Finck #else
958c2c66affSColin Finck return 0;
959c2c66affSColin Finck #endif
960c2c66affSColin Finck }
961c2c66affSColin Finck
962c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
963c2c66affSColin Finck TrioFollowedBySeparator
964c2c66affSColin Finck TRIO_ARGS1((position),
965c2c66affSColin Finck int position)
966c2c66affSColin Finck {
967c2c66affSColin Finck #if TRIO_EXTENSION
968c2c66affSColin Finck int step = 0;
969c2c66affSColin Finck char *groupingPointer = internalGrouping;
970c2c66affSColin Finck
971c2c66affSColin Finck position--;
972c2c66affSColin Finck if (position == 0)
973c2c66affSColin Finck return FALSE;
974c2c66affSColin Finck while (position > 0)
975c2c66affSColin Finck {
976c2c66affSColin Finck if (*groupingPointer == CHAR_MAX)
977c2c66affSColin Finck {
978c2c66affSColin Finck /* Disable grouping */
979c2c66affSColin Finck break; /* while */
980c2c66affSColin Finck }
981c2c66affSColin Finck else if (*groupingPointer != 0)
982c2c66affSColin Finck {
983c2c66affSColin Finck step = *groupingPointer++;
984c2c66affSColin Finck }
985c2c66affSColin Finck if (step == 0)
986c2c66affSColin Finck break;
987c2c66affSColin Finck position -= step;
988c2c66affSColin Finck }
989c2c66affSColin Finck return (position == 0);
990c2c66affSColin Finck #else
991c2c66affSColin Finck return FALSE;
992c2c66affSColin Finck #endif
993c2c66affSColin Finck }
994c2c66affSColin Finck
995c2c66affSColin Finck /*************************************************************************
996c2c66affSColin Finck * TrioGetPosition
997c2c66affSColin Finck *
998c2c66affSColin Finck * Get the %n$ position.
999c2c66affSColin Finck */
1000c2c66affSColin Finck TRIO_PRIVATE int
1001c2c66affSColin Finck TrioGetPosition
1002c2c66affSColin Finck TRIO_ARGS2((format, indexPointer),
1003c2c66affSColin Finck TRIO_CONST char *format,
1004c2c66affSColin Finck int *indexPointer)
1005c2c66affSColin Finck {
1006c2c66affSColin Finck #if TRIO_UNIX98
1007c2c66affSColin Finck char *tmpformat;
1008c2c66affSColin Finck int number = 0;
1009c2c66affSColin Finck int index = *indexPointer;
1010c2c66affSColin Finck
1011c2c66affSColin Finck number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
1012c2c66affSColin Finck index = (int)(tmpformat - format);
1013c2c66affSColin Finck if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
1014c2c66affSColin Finck {
1015c2c66affSColin Finck *indexPointer = index;
1016c2c66affSColin Finck /*
1017c2c66affSColin Finck * number is decreased by 1, because n$ starts from 1, whereas
1018c2c66affSColin Finck * the array it is indexing starts from 0.
1019c2c66affSColin Finck */
1020c2c66affSColin Finck return number - 1;
1021c2c66affSColin Finck }
1022c2c66affSColin Finck #endif
1023c2c66affSColin Finck return NO_POSITION;
1024c2c66affSColin Finck }
1025c2c66affSColin Finck
1026c2c66affSColin Finck #if TRIO_EXTENSION
1027c2c66affSColin Finck /*************************************************************************
1028c2c66affSColin Finck * TrioFindNamespace
1029c2c66affSColin Finck *
1030c2c66affSColin Finck * Find registered user-defined specifier.
1031c2c66affSColin Finck * The prev argument is used for optimization only.
1032c2c66affSColin Finck */
1033c2c66affSColin Finck TRIO_PRIVATE trio_userdef_t *
1034c2c66affSColin Finck TrioFindNamespace
1035c2c66affSColin Finck TRIO_ARGS2((name, prev),
1036c2c66affSColin Finck TRIO_CONST char *name,
1037c2c66affSColin Finck trio_userdef_t **prev)
1038c2c66affSColin Finck {
1039c2c66affSColin Finck trio_userdef_t *def;
1040c2c66affSColin Finck
1041c2c66affSColin Finck if (internalEnterCriticalRegion)
1042c2c66affSColin Finck (void)internalEnterCriticalRegion(NULL);
1043c2c66affSColin Finck
1044c2c66affSColin Finck for (def = internalUserDef; def; def = def->next)
1045c2c66affSColin Finck {
1046c2c66affSColin Finck /* Case-sensitive string comparison */
1047c2c66affSColin Finck if (trio_equal_case(def->name, name))
1048c2c66affSColin Finck break;
1049c2c66affSColin Finck
1050c2c66affSColin Finck if (prev)
1051c2c66affSColin Finck *prev = def;
1052c2c66affSColin Finck }
1053c2c66affSColin Finck
1054c2c66affSColin Finck if (internalLeaveCriticalRegion)
1055c2c66affSColin Finck (void)internalLeaveCriticalRegion(NULL);
1056c2c66affSColin Finck
1057c2c66affSColin Finck return def;
1058c2c66affSColin Finck }
1059c2c66affSColin Finck #endif
1060c2c66affSColin Finck
1061c2c66affSColin Finck /*************************************************************************
1062c2c66affSColin Finck * TrioPower
1063c2c66affSColin Finck *
1064c2c66affSColin Finck * Description:
1065c2c66affSColin Finck * Calculate pow(base, exponent), where number and exponent are integers.
1066c2c66affSColin Finck */
1067c2c66affSColin Finck TRIO_PRIVATE trio_long_double_t
1068c2c66affSColin Finck TrioPower
1069c2c66affSColin Finck TRIO_ARGS2((number, exponent),
1070c2c66affSColin Finck int number,
1071c2c66affSColin Finck int exponent)
1072c2c66affSColin Finck {
1073c2c66affSColin Finck trio_long_double_t result;
1074c2c66affSColin Finck
1075c2c66affSColin Finck if (number == 10)
1076c2c66affSColin Finck {
1077c2c66affSColin Finck switch (exponent)
1078c2c66affSColin Finck {
1079c2c66affSColin Finck /* Speed up calculation of common cases */
1080c2c66affSColin Finck case 0:
1081c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1);
1082c2c66affSColin Finck break;
1083c2c66affSColin Finck case 1:
1084c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0);
1085c2c66affSColin Finck break;
1086c2c66affSColin Finck case 2:
1087c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1);
1088c2c66affSColin Finck break;
1089c2c66affSColin Finck case 3:
1090c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2);
1091c2c66affSColin Finck break;
1092c2c66affSColin Finck case 4:
1093c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3);
1094c2c66affSColin Finck break;
1095c2c66affSColin Finck case 5:
1096c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4);
1097c2c66affSColin Finck break;
1098c2c66affSColin Finck case 6:
1099c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5);
1100c2c66affSColin Finck break;
1101c2c66affSColin Finck case 7:
1102c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6);
1103c2c66affSColin Finck break;
1104c2c66affSColin Finck case 8:
1105c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7);
1106c2c66affSColin Finck break;
1107c2c66affSColin Finck case 9:
1108c2c66affSColin Finck result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8);
1109c2c66affSColin Finck break;
1110c2c66affSColin Finck default:
1111c2c66affSColin Finck result = powl((trio_long_double_t)number,
1112c2c66affSColin Finck (trio_long_double_t)exponent);
1113c2c66affSColin Finck break;
1114c2c66affSColin Finck }
1115c2c66affSColin Finck }
1116c2c66affSColin Finck else
1117c2c66affSColin Finck {
1118c2c66affSColin Finck return powl((trio_long_double_t)number, (trio_long_double_t)exponent);
1119c2c66affSColin Finck }
1120c2c66affSColin Finck return result;
1121c2c66affSColin Finck }
1122c2c66affSColin Finck
1123c2c66affSColin Finck /*************************************************************************
1124c2c66affSColin Finck * TrioLogarithm
1125c2c66affSColin Finck */
1126c2c66affSColin Finck TRIO_PRIVATE double
1127c2c66affSColin Finck TrioLogarithm
1128c2c66affSColin Finck TRIO_ARGS2((number, base),
1129c2c66affSColin Finck double number,
1130c2c66affSColin Finck int base)
1131c2c66affSColin Finck {
1132c2c66affSColin Finck double result;
1133c2c66affSColin Finck
1134c2c66affSColin Finck if (number <= 0.0)
1135c2c66affSColin Finck {
1136c2c66affSColin Finck /* xlC crashes on log(0) */
1137c2c66affSColin Finck result = (number == 0.0) ? trio_ninf() : trio_nan();
1138c2c66affSColin Finck }
1139c2c66affSColin Finck else
1140c2c66affSColin Finck {
1141c2c66affSColin Finck if (base == 10)
1142c2c66affSColin Finck {
1143c2c66affSColin Finck result = log10(number);
1144c2c66affSColin Finck }
1145c2c66affSColin Finck else
1146c2c66affSColin Finck {
1147c2c66affSColin Finck result = log10(number) / log10((double)base);
1148c2c66affSColin Finck }
1149c2c66affSColin Finck }
1150c2c66affSColin Finck return result;
1151c2c66affSColin Finck }
1152c2c66affSColin Finck
1153c2c66affSColin Finck /*************************************************************************
1154c2c66affSColin Finck * TrioLogarithmBase
1155c2c66affSColin Finck */
1156c2c66affSColin Finck TRIO_PRIVATE double
1157c2c66affSColin Finck TrioLogarithmBase
1158c2c66affSColin Finck TRIO_ARGS1((base),
1159c2c66affSColin Finck int base)
1160c2c66affSColin Finck {
1161c2c66affSColin Finck switch (base)
1162c2c66affSColin Finck {
1163c2c66affSColin Finck case BASE_BINARY : return 1.0;
1164c2c66affSColin Finck case BASE_OCTAL : return 3.0;
1165c2c66affSColin Finck case BASE_DECIMAL: return 3.321928094887362345;
1166c2c66affSColin Finck case BASE_HEX : return 4.0;
1167c2c66affSColin Finck default : return TrioLogarithm((double)base, 2);
1168c2c66affSColin Finck }
1169c2c66affSColin Finck }
1170c2c66affSColin Finck
1171c2c66affSColin Finck /*************************************************************************
1172c2c66affSColin Finck * TrioParse
1173c2c66affSColin Finck *
1174c2c66affSColin Finck * Description:
1175c2c66affSColin Finck * Parse the format string
1176c2c66affSColin Finck */
1177c2c66affSColin Finck TRIO_PRIVATE int
1178c2c66affSColin Finck TrioParse
1179c2c66affSColin Finck TRIO_ARGS5((type, format, parameters, arglist, argarray),
1180c2c66affSColin Finck int type,
1181c2c66affSColin Finck TRIO_CONST char *format,
1182c2c66affSColin Finck trio_parameter_t *parameters,
1183c2c66affSColin Finck TRIO_VA_LIST_PTR arglist,
1184c2c66affSColin Finck trio_pointer_t *argarray)
1185c2c66affSColin Finck {
1186c2c66affSColin Finck /* Count the number of times a parameter is referenced */
1187c2c66affSColin Finck unsigned short usedEntries[MAX_PARAMETERS];
1188c2c66affSColin Finck /* Parameter counters */
1189c2c66affSColin Finck int parameterPosition;
1190c2c66affSColin Finck int currentParam;
1191c2c66affSColin Finck int maxParam = -1;
1192c2c66affSColin Finck /* Utility variables */
1193c2c66affSColin Finck trio_flags_t flags;
1194c2c66affSColin Finck int width;
1195c2c66affSColin Finck int precision;
1196c2c66affSColin Finck int varsize;
1197c2c66affSColin Finck int base;
1198c2c66affSColin Finck int index; /* Index into formatting string */
1199c2c66affSColin Finck int dots; /* Count number of dots in modifier part */
1200c2c66affSColin Finck BOOLEAN_T positional; /* Does the specifier have a positional? */
1201c2c66affSColin Finck BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */
1202c2c66affSColin Finck /*
1203c2c66affSColin Finck * indices specifies the order in which the parameters must be
1204c2c66affSColin Finck * read from the va_args (this is necessary to handle positionals)
1205c2c66affSColin Finck */
1206c2c66affSColin Finck int indices[MAX_PARAMETERS];
1207c2c66affSColin Finck int pos = 0;
1208c2c66affSColin Finck /* Various variables */
1209c2c66affSColin Finck char ch;
1210c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1211c2c66affSColin Finck int charlen;
1212c2c66affSColin Finck #endif
1213c2c66affSColin Finck int save_errno;
1214c2c66affSColin Finck int i = -1;
1215c2c66affSColin Finck int num;
1216c2c66affSColin Finck char *tmpformat;
1217c2c66affSColin Finck
1218c2c66affSColin Finck /* One and only one of arglist and argarray must be used */
1219c2c66affSColin Finck assert((arglist != NULL) ^ (argarray != NULL));
1220c2c66affSColin Finck
1221c2c66affSColin Finck /*
1222c2c66affSColin Finck * The 'parameters' array is not initialized, but we need to
1223c2c66affSColin Finck * know which entries we have used.
1224c2c66affSColin Finck */
1225c2c66affSColin Finck memset(usedEntries, 0, sizeof(usedEntries));
1226c2c66affSColin Finck
1227c2c66affSColin Finck save_errno = errno;
1228c2c66affSColin Finck index = 0;
1229c2c66affSColin Finck parameterPosition = 0;
1230c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1231c2c66affSColin Finck (void)mblen(NULL, 0);
1232c2c66affSColin Finck #endif
1233c2c66affSColin Finck
1234c2c66affSColin Finck while (format[index])
1235c2c66affSColin Finck {
1236c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1237c2c66affSColin Finck if (! isascii(format[index]))
1238c2c66affSColin Finck {
1239c2c66affSColin Finck /*
1240c2c66affSColin Finck * Multibyte characters cannot be legal specifiers or
1241c2c66affSColin Finck * modifiers, so we skip over them.
1242c2c66affSColin Finck */
1243c2c66affSColin Finck charlen = mblen(&format[index], MB_LEN_MAX);
1244c2c66affSColin Finck index += (charlen > 0) ? charlen : 1;
1245c2c66affSColin Finck continue; /* while */
1246c2c66affSColin Finck }
1247c2c66affSColin Finck #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
1248c2c66affSColin Finck if (CHAR_IDENTIFIER == format[index++])
1249c2c66affSColin Finck {
1250c2c66affSColin Finck if (CHAR_IDENTIFIER == format[index])
1251c2c66affSColin Finck {
1252c2c66affSColin Finck index++;
1253c2c66affSColin Finck continue; /* while */
1254c2c66affSColin Finck }
1255c2c66affSColin Finck
1256c2c66affSColin Finck flags = FLAGS_NEW;
1257c2c66affSColin Finck dots = 0;
1258c2c66affSColin Finck currentParam = TrioGetPosition(format, &index);
1259c2c66affSColin Finck positional = (NO_POSITION != currentParam);
1260c2c66affSColin Finck if (!positional)
1261c2c66affSColin Finck {
1262c2c66affSColin Finck /* We have no positional, get the next counter */
1263c2c66affSColin Finck currentParam = parameterPosition;
1264c2c66affSColin Finck }
1265c2c66affSColin Finck if(currentParam >= MAX_PARAMETERS)
1266c2c66affSColin Finck {
1267c2c66affSColin Finck /* Bail out completely to make the error more obvious */
1268c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_ETOOMANY, index);
1269c2c66affSColin Finck }
1270c2c66affSColin Finck
1271c2c66affSColin Finck if (currentParam > maxParam)
1272c2c66affSColin Finck maxParam = currentParam;
1273c2c66affSColin Finck
1274c2c66affSColin Finck /* Default values */
1275c2c66affSColin Finck width = NO_WIDTH;
1276c2c66affSColin Finck precision = NO_PRECISION;
1277c2c66affSColin Finck base = NO_BASE;
1278c2c66affSColin Finck varsize = NO_SIZE;
1279c2c66affSColin Finck
1280c2c66affSColin Finck while (TrioIsQualifier(format[index]))
1281c2c66affSColin Finck {
1282c2c66affSColin Finck ch = format[index++];
1283c2c66affSColin Finck
1284c2c66affSColin Finck switch (ch)
1285c2c66affSColin Finck {
1286c2c66affSColin Finck case QUALIFIER_SPACE:
1287c2c66affSColin Finck flags |= FLAGS_SPACE;
1288c2c66affSColin Finck break;
1289c2c66affSColin Finck
1290c2c66affSColin Finck case QUALIFIER_PLUS:
1291c2c66affSColin Finck flags |= FLAGS_SHOWSIGN;
1292c2c66affSColin Finck break;
1293c2c66affSColin Finck
1294c2c66affSColin Finck case QUALIFIER_MINUS:
1295c2c66affSColin Finck flags |= FLAGS_LEFTADJUST;
1296c2c66affSColin Finck flags &= ~FLAGS_NILPADDING;
1297c2c66affSColin Finck break;
1298c2c66affSColin Finck
1299c2c66affSColin Finck case QUALIFIER_ALTERNATIVE:
1300c2c66affSColin Finck flags |= FLAGS_ALTERNATIVE;
1301c2c66affSColin Finck break;
1302c2c66affSColin Finck
1303c2c66affSColin Finck case QUALIFIER_DOT:
1304c2c66affSColin Finck if (dots == 0) /* Precision */
1305c2c66affSColin Finck {
1306c2c66affSColin Finck dots++;
1307c2c66affSColin Finck
1308c2c66affSColin Finck /* Skip if no precision */
1309c2c66affSColin Finck if (QUALIFIER_DOT == format[index])
1310c2c66affSColin Finck break;
1311c2c66affSColin Finck
1312c2c66affSColin Finck /* After the first dot we have the precision */
1313c2c66affSColin Finck flags |= FLAGS_PRECISION;
1314c2c66affSColin Finck if ((QUALIFIER_STAR == format[index])
1315c2c66affSColin Finck #if defined(QUALIFIER_PARAM)
1316c2c66affSColin Finck || (QUALIFIER_PARAM == format[index])
1317c2c66affSColin Finck #endif
1318c2c66affSColin Finck )
1319c2c66affSColin Finck {
1320c2c66affSColin Finck index++;
1321c2c66affSColin Finck flags |= FLAGS_PRECISION_PARAMETER;
1322c2c66affSColin Finck
1323c2c66affSColin Finck precision = TrioGetPosition(format, &index);
1324c2c66affSColin Finck if (precision == NO_POSITION)
1325c2c66affSColin Finck {
1326c2c66affSColin Finck parameterPosition++;
1327c2c66affSColin Finck if (positional)
1328c2c66affSColin Finck precision = parameterPosition;
1329c2c66affSColin Finck else
1330c2c66affSColin Finck {
1331c2c66affSColin Finck precision = currentParam;
1332c2c66affSColin Finck currentParam = precision + 1;
1333c2c66affSColin Finck }
1334c2c66affSColin Finck }
1335c2c66affSColin Finck else
1336c2c66affSColin Finck {
1337c2c66affSColin Finck if (! positional)
1338c2c66affSColin Finck currentParam = precision + 1;
1339c2c66affSColin Finck if (width > maxParam)
1340c2c66affSColin Finck maxParam = precision;
1341c2c66affSColin Finck }
1342c2c66affSColin Finck if (currentParam > maxParam)
1343c2c66affSColin Finck maxParam = currentParam;
1344c2c66affSColin Finck }
1345c2c66affSColin Finck else
1346c2c66affSColin Finck {
1347c2c66affSColin Finck precision = trio_to_long(&format[index],
1348c2c66affSColin Finck &tmpformat,
1349c2c66affSColin Finck BASE_DECIMAL);
1350c2c66affSColin Finck index = (int)(tmpformat - format);
1351c2c66affSColin Finck }
1352c2c66affSColin Finck }
1353c2c66affSColin Finck else if (dots == 1) /* Base */
1354c2c66affSColin Finck {
1355c2c66affSColin Finck dots++;
1356c2c66affSColin Finck
1357c2c66affSColin Finck /* After the second dot we have the base */
1358c2c66affSColin Finck flags |= FLAGS_BASE;
1359c2c66affSColin Finck if ((QUALIFIER_STAR == format[index])
1360c2c66affSColin Finck #if defined(QUALIFIER_PARAM)
1361c2c66affSColin Finck || (QUALIFIER_PARAM == format[index])
1362c2c66affSColin Finck #endif
1363c2c66affSColin Finck )
1364c2c66affSColin Finck {
1365c2c66affSColin Finck index++;
1366c2c66affSColin Finck flags |= FLAGS_BASE_PARAMETER;
1367c2c66affSColin Finck base = TrioGetPosition(format, &index);
1368c2c66affSColin Finck if (base == NO_POSITION)
1369c2c66affSColin Finck {
1370c2c66affSColin Finck parameterPosition++;
1371c2c66affSColin Finck if (positional)
1372c2c66affSColin Finck base = parameterPosition;
1373c2c66affSColin Finck else
1374c2c66affSColin Finck {
1375c2c66affSColin Finck base = currentParam;
1376c2c66affSColin Finck currentParam = base + 1;
1377c2c66affSColin Finck }
1378c2c66affSColin Finck }
1379c2c66affSColin Finck else
1380c2c66affSColin Finck {
1381c2c66affSColin Finck if (! positional)
1382c2c66affSColin Finck currentParam = base + 1;
1383c2c66affSColin Finck if (base > maxParam)
1384c2c66affSColin Finck maxParam = base;
1385c2c66affSColin Finck }
1386c2c66affSColin Finck if (currentParam > maxParam)
1387c2c66affSColin Finck maxParam = currentParam;
1388c2c66affSColin Finck }
1389c2c66affSColin Finck else
1390c2c66affSColin Finck {
1391c2c66affSColin Finck base = trio_to_long(&format[index],
1392c2c66affSColin Finck &tmpformat,
1393c2c66affSColin Finck BASE_DECIMAL);
1394c2c66affSColin Finck if (base > MAX_BASE)
1395c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1396c2c66affSColin Finck index = (int)(tmpformat - format);
1397c2c66affSColin Finck }
1398c2c66affSColin Finck }
1399c2c66affSColin Finck else
1400c2c66affSColin Finck {
1401c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1402c2c66affSColin Finck }
1403c2c66affSColin Finck break; /* QUALIFIER_DOT */
1404c2c66affSColin Finck
1405c2c66affSColin Finck #if defined(QUALIFIER_PARAM)
1406c2c66affSColin Finck case QUALIFIER_PARAM:
1407c2c66affSColin Finck type = TYPE_PRINT;
1408c2c66affSColin Finck /* FALLTHROUGH */
1409c2c66affSColin Finck #endif
1410c2c66affSColin Finck case QUALIFIER_STAR:
1411c2c66affSColin Finck /* This has different meanings for print and scan */
1412c2c66affSColin Finck if (TYPE_PRINT == type)
1413c2c66affSColin Finck {
1414c2c66affSColin Finck /* Read with from parameter */
1415c2c66affSColin Finck flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
1416c2c66affSColin Finck width = TrioGetPosition(format, &index);
1417c2c66affSColin Finck if (width == NO_POSITION)
1418c2c66affSColin Finck {
1419c2c66affSColin Finck parameterPosition++;
1420c2c66affSColin Finck if (positional)
1421c2c66affSColin Finck width = parameterPosition;
1422c2c66affSColin Finck else
1423c2c66affSColin Finck {
1424c2c66affSColin Finck width = currentParam;
1425c2c66affSColin Finck currentParam = width + 1;
1426c2c66affSColin Finck }
1427c2c66affSColin Finck }
1428c2c66affSColin Finck else
1429c2c66affSColin Finck {
1430c2c66affSColin Finck if (! positional)
1431c2c66affSColin Finck currentParam = width + 1;
1432c2c66affSColin Finck if (width > maxParam)
1433c2c66affSColin Finck maxParam = width;
1434c2c66affSColin Finck }
1435c2c66affSColin Finck if (currentParam > maxParam)
1436c2c66affSColin Finck maxParam = currentParam;
1437c2c66affSColin Finck }
1438c2c66affSColin Finck else
1439c2c66affSColin Finck {
1440c2c66affSColin Finck /* Scan, but do not store result */
1441c2c66affSColin Finck flags |= FLAGS_IGNORE;
1442c2c66affSColin Finck }
1443c2c66affSColin Finck
1444c2c66affSColin Finck break; /* QUALIFIER_STAR */
1445c2c66affSColin Finck
1446c2c66affSColin Finck case '0':
1447c2c66affSColin Finck if (! (flags & FLAGS_LEFTADJUST))
1448c2c66affSColin Finck flags |= FLAGS_NILPADDING;
1449c2c66affSColin Finck /* FALLTHROUGH */
1450c2c66affSColin Finck case '1': case '2': case '3': case '4':
1451c2c66affSColin Finck case '5': case '6': case '7': case '8': case '9':
1452c2c66affSColin Finck flags |= FLAGS_WIDTH;
1453c2c66affSColin Finck /* &format[index - 1] is used to "rewind" the read
1454c2c66affSColin Finck * character from format
1455c2c66affSColin Finck */
1456c2c66affSColin Finck width = trio_to_long(&format[index - 1],
1457c2c66affSColin Finck &tmpformat,
1458c2c66affSColin Finck BASE_DECIMAL);
1459c2c66affSColin Finck index = (int)(tmpformat - format);
1460c2c66affSColin Finck break;
1461c2c66affSColin Finck
1462c2c66affSColin Finck case QUALIFIER_SHORT:
1463c2c66affSColin Finck if (flags & FLAGS_SHORTSHORT)
1464c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1465c2c66affSColin Finck else if (flags & FLAGS_SHORT)
1466c2c66affSColin Finck flags |= FLAGS_SHORTSHORT;
1467c2c66affSColin Finck else
1468c2c66affSColin Finck flags |= FLAGS_SHORT;
1469c2c66affSColin Finck break;
1470c2c66affSColin Finck
1471c2c66affSColin Finck case QUALIFIER_LONG:
1472c2c66affSColin Finck if (flags & FLAGS_QUAD)
1473c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1474c2c66affSColin Finck else if (flags & FLAGS_LONG)
1475c2c66affSColin Finck flags |= FLAGS_QUAD;
1476c2c66affSColin Finck else
1477c2c66affSColin Finck flags |= FLAGS_LONG;
1478c2c66affSColin Finck break;
1479c2c66affSColin Finck
1480c2c66affSColin Finck case QUALIFIER_LONG_UPPER:
1481c2c66affSColin Finck flags |= FLAGS_LONGDOUBLE;
1482c2c66affSColin Finck break;
1483c2c66affSColin Finck
1484c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T)
1485c2c66affSColin Finck case QUALIFIER_SIZE_T:
1486c2c66affSColin Finck flags |= FLAGS_SIZE_T;
1487c2c66affSColin Finck /* Modify flags for later truncation of number */
1488c2c66affSColin Finck if (sizeof(size_t) == sizeof(trio_ulonglong_t))
1489c2c66affSColin Finck flags |= FLAGS_QUAD;
1490c2c66affSColin Finck else if (sizeof(size_t) == sizeof(long))
1491c2c66affSColin Finck flags |= FLAGS_LONG;
1492c2c66affSColin Finck break;
1493c2c66affSColin Finck #endif
1494c2c66affSColin Finck
1495c2c66affSColin Finck #if defined(QUALIFIER_PTRDIFF_T)
1496c2c66affSColin Finck case QUALIFIER_PTRDIFF_T:
1497c2c66affSColin Finck flags |= FLAGS_PTRDIFF_T;
1498c2c66affSColin Finck if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
1499c2c66affSColin Finck flags |= FLAGS_QUAD;
1500c2c66affSColin Finck else if (sizeof(ptrdiff_t) == sizeof(long))
1501c2c66affSColin Finck flags |= FLAGS_LONG;
1502c2c66affSColin Finck break;
1503c2c66affSColin Finck #endif
1504c2c66affSColin Finck
1505c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
1506c2c66affSColin Finck case QUALIFIER_INTMAX_T:
1507c2c66affSColin Finck flags |= FLAGS_INTMAX_T;
1508c2c66affSColin Finck if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
1509c2c66affSColin Finck flags |= FLAGS_QUAD;
1510c2c66affSColin Finck else if (sizeof(trio_intmax_t) == sizeof(long))
1511c2c66affSColin Finck flags |= FLAGS_LONG;
1512c2c66affSColin Finck break;
1513c2c66affSColin Finck #endif
1514c2c66affSColin Finck
1515c2c66affSColin Finck #if defined(QUALIFIER_QUAD)
1516c2c66affSColin Finck case QUALIFIER_QUAD:
1517c2c66affSColin Finck flags |= FLAGS_QUAD;
1518c2c66affSColin Finck break;
1519c2c66affSColin Finck #endif
1520c2c66affSColin Finck
1521c2c66affSColin Finck #if defined(QUALIFIER_FIXED_SIZE)
1522c2c66affSColin Finck case QUALIFIER_FIXED_SIZE:
1523c2c66affSColin Finck if (flags & FLAGS_FIXED_SIZE)
1524c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1525c2c66affSColin Finck
1526c2c66affSColin Finck if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
1527c2c66affSColin Finck FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
1528c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1529c2c66affSColin Finck
1530c2c66affSColin Finck if ((format[index] == '6') &&
1531c2c66affSColin Finck (format[index + 1] == '4'))
1532c2c66affSColin Finck {
1533c2c66affSColin Finck varsize = sizeof(trio_int64_t);
1534c2c66affSColin Finck index += 2;
1535c2c66affSColin Finck }
1536c2c66affSColin Finck else if ((format[index] == '3') &&
1537c2c66affSColin Finck (format[index + 1] == '2'))
1538c2c66affSColin Finck {
1539c2c66affSColin Finck varsize = sizeof(trio_int32_t);
1540c2c66affSColin Finck index += 2;
1541c2c66affSColin Finck }
1542c2c66affSColin Finck else if ((format[index] == '1') &&
1543c2c66affSColin Finck (format[index + 1] == '6'))
1544c2c66affSColin Finck {
1545c2c66affSColin Finck varsize = sizeof(trio_int16_t);
1546c2c66affSColin Finck index += 2;
1547c2c66affSColin Finck }
1548c2c66affSColin Finck else if (format[index] == '8')
1549c2c66affSColin Finck {
1550c2c66affSColin Finck varsize = sizeof(trio_int8_t);
1551c2c66affSColin Finck index++;
1552c2c66affSColin Finck }
1553c2c66affSColin Finck else
1554c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1555c2c66affSColin Finck
1556c2c66affSColin Finck flags |= FLAGS_FIXED_SIZE;
1557c2c66affSColin Finck break;
1558c2c66affSColin Finck #endif
1559c2c66affSColin Finck
1560c2c66affSColin Finck #if defined(QUALIFIER_WIDECHAR)
1561c2c66affSColin Finck case QUALIFIER_WIDECHAR:
1562c2c66affSColin Finck flags |= FLAGS_WIDECHAR;
1563c2c66affSColin Finck break;
1564c2c66affSColin Finck #endif
1565c2c66affSColin Finck
1566c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T_UPPER)
1567c2c66affSColin Finck case QUALIFIER_SIZE_T_UPPER:
1568c2c66affSColin Finck break;
1569c2c66affSColin Finck #endif
1570c2c66affSColin Finck
1571c2c66affSColin Finck #if defined(QUALIFIER_QUOTE)
1572c2c66affSColin Finck case QUALIFIER_QUOTE:
1573c2c66affSColin Finck flags |= FLAGS_QUOTE;
1574c2c66affSColin Finck break;
1575c2c66affSColin Finck #endif
1576c2c66affSColin Finck
1577c2c66affSColin Finck #if defined(QUALIFIER_STICKY)
1578c2c66affSColin Finck case QUALIFIER_STICKY:
1579c2c66affSColin Finck flags |= FLAGS_STICKY;
1580c2c66affSColin Finck gotSticky = TRUE;
1581c2c66affSColin Finck break;
1582c2c66affSColin Finck #endif
1583c2c66affSColin Finck
1584c2c66affSColin Finck #if defined(QUALIFIER_VARSIZE)
1585c2c66affSColin Finck case QUALIFIER_VARSIZE:
1586c2c66affSColin Finck flags |= FLAGS_VARSIZE_PARAMETER;
1587c2c66affSColin Finck parameterPosition++;
1588c2c66affSColin Finck if (positional)
1589c2c66affSColin Finck varsize = parameterPosition;
1590c2c66affSColin Finck else
1591c2c66affSColin Finck {
1592c2c66affSColin Finck varsize = currentParam;
1593c2c66affSColin Finck currentParam = varsize + 1;
1594c2c66affSColin Finck }
1595c2c66affSColin Finck if (currentParam > maxParam)
1596c2c66affSColin Finck maxParam = currentParam;
1597c2c66affSColin Finck break;
1598c2c66affSColin Finck #endif
1599c2c66affSColin Finck
1600c2c66affSColin Finck #if defined(QUALIFIER_ROUNDING_UPPER)
1601c2c66affSColin Finck case QUALIFIER_ROUNDING_UPPER:
1602c2c66affSColin Finck flags |= FLAGS_ROUNDING;
1603c2c66affSColin Finck break;
1604c2c66affSColin Finck #endif
1605c2c66affSColin Finck
1606c2c66affSColin Finck default:
1607c2c66affSColin Finck /* Bail out completely to make the error more obvious */
1608c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1609c2c66affSColin Finck }
1610c2c66affSColin Finck } /* while qualifier */
1611c2c66affSColin Finck
1612c2c66affSColin Finck /*
1613c2c66affSColin Finck * Parameters only need the type and value. The value is
1614c2c66affSColin Finck * read later.
1615c2c66affSColin Finck */
1616c2c66affSColin Finck if (flags & FLAGS_WIDTH_PARAMETER)
1617c2c66affSColin Finck {
1618c2c66affSColin Finck usedEntries[width] += 1;
1619c2c66affSColin Finck parameters[pos].type = FORMAT_PARAMETER;
1620c2c66affSColin Finck parameters[pos].flags = 0;
1621c2c66affSColin Finck indices[width] = pos;
1622c2c66affSColin Finck width = pos++;
1623c2c66affSColin Finck }
1624c2c66affSColin Finck if (flags & FLAGS_PRECISION_PARAMETER)
1625c2c66affSColin Finck {
1626c2c66affSColin Finck usedEntries[precision] += 1;
1627c2c66affSColin Finck parameters[pos].type = FORMAT_PARAMETER;
1628c2c66affSColin Finck parameters[pos].flags = 0;
1629c2c66affSColin Finck indices[precision] = pos;
1630c2c66affSColin Finck precision = pos++;
1631c2c66affSColin Finck }
1632c2c66affSColin Finck if (flags & FLAGS_BASE_PARAMETER)
1633c2c66affSColin Finck {
1634c2c66affSColin Finck usedEntries[base] += 1;
1635c2c66affSColin Finck parameters[pos].type = FORMAT_PARAMETER;
1636c2c66affSColin Finck parameters[pos].flags = 0;
1637c2c66affSColin Finck indices[base] = pos;
1638c2c66affSColin Finck base = pos++;
1639c2c66affSColin Finck }
1640c2c66affSColin Finck if (flags & FLAGS_VARSIZE_PARAMETER)
1641c2c66affSColin Finck {
1642c2c66affSColin Finck usedEntries[varsize] += 1;
1643c2c66affSColin Finck parameters[pos].type = FORMAT_PARAMETER;
1644c2c66affSColin Finck parameters[pos].flags = 0;
1645c2c66affSColin Finck indices[varsize] = pos;
1646c2c66affSColin Finck varsize = pos++;
1647c2c66affSColin Finck }
1648c2c66affSColin Finck
1649c2c66affSColin Finck indices[currentParam] = pos;
1650c2c66affSColin Finck
1651c2c66affSColin Finck switch (format[index++])
1652c2c66affSColin Finck {
1653c2c66affSColin Finck #if defined(SPECIFIER_CHAR_UPPER)
1654c2c66affSColin Finck case SPECIFIER_CHAR_UPPER:
1655c2c66affSColin Finck flags |= FLAGS_WIDECHAR;
1656c2c66affSColin Finck /* FALLTHROUGH */
1657c2c66affSColin Finck #endif
1658c2c66affSColin Finck case SPECIFIER_CHAR:
1659c2c66affSColin Finck if (flags & FLAGS_LONG)
1660c2c66affSColin Finck flags |= FLAGS_WIDECHAR;
1661c2c66affSColin Finck else if (flags & FLAGS_SHORT)
1662c2c66affSColin Finck flags &= ~FLAGS_WIDECHAR;
1663c2c66affSColin Finck parameters[pos].type = FORMAT_CHAR;
1664c2c66affSColin Finck break;
1665c2c66affSColin Finck
1666c2c66affSColin Finck #if defined(SPECIFIER_STRING_UPPER)
1667c2c66affSColin Finck case SPECIFIER_STRING_UPPER:
1668c2c66affSColin Finck flags |= FLAGS_WIDECHAR;
1669c2c66affSColin Finck /* FALLTHROUGH */
1670c2c66affSColin Finck #endif
1671c2c66affSColin Finck case SPECIFIER_STRING:
1672c2c66affSColin Finck if (flags & FLAGS_LONG)
1673c2c66affSColin Finck flags |= FLAGS_WIDECHAR;
1674c2c66affSColin Finck else if (flags & FLAGS_SHORT)
1675c2c66affSColin Finck flags &= ~FLAGS_WIDECHAR;
1676c2c66affSColin Finck parameters[pos].type = FORMAT_STRING;
1677c2c66affSColin Finck break;
1678c2c66affSColin Finck
1679c2c66affSColin Finck case SPECIFIER_GROUP:
1680c2c66affSColin Finck if (TYPE_SCAN == type)
1681c2c66affSColin Finck {
1682c2c66affSColin Finck int depth = 1;
1683c2c66affSColin Finck parameters[pos].type = FORMAT_GROUP;
1684c2c66affSColin Finck if (format[index] == QUALIFIER_CIRCUMFLEX)
1685c2c66affSColin Finck index++;
1686c2c66affSColin Finck if (format[index] == SPECIFIER_UNGROUP)
1687c2c66affSColin Finck index++;
1688c2c66affSColin Finck if (format[index] == QUALIFIER_MINUS)
1689c2c66affSColin Finck index++;
1690c2c66affSColin Finck /* Skip nested brackets */
1691c2c66affSColin Finck while (format[index] != NIL)
1692c2c66affSColin Finck {
1693c2c66affSColin Finck if (format[index] == SPECIFIER_GROUP)
1694c2c66affSColin Finck {
1695c2c66affSColin Finck depth++;
1696c2c66affSColin Finck }
1697c2c66affSColin Finck else if (format[index] == SPECIFIER_UNGROUP)
1698c2c66affSColin Finck {
1699c2c66affSColin Finck if (--depth <= 0)
1700c2c66affSColin Finck {
1701c2c66affSColin Finck index++;
1702c2c66affSColin Finck break;
1703c2c66affSColin Finck }
1704c2c66affSColin Finck }
1705c2c66affSColin Finck index++;
1706c2c66affSColin Finck }
1707c2c66affSColin Finck }
1708c2c66affSColin Finck break;
1709c2c66affSColin Finck
1710c2c66affSColin Finck case SPECIFIER_INTEGER:
1711c2c66affSColin Finck parameters[pos].type = FORMAT_INT;
1712c2c66affSColin Finck break;
1713c2c66affSColin Finck
1714c2c66affSColin Finck case SPECIFIER_UNSIGNED:
1715c2c66affSColin Finck flags |= FLAGS_UNSIGNED;
1716c2c66affSColin Finck parameters[pos].type = FORMAT_INT;
1717c2c66affSColin Finck break;
1718c2c66affSColin Finck
1719c2c66affSColin Finck case SPECIFIER_DECIMAL:
1720c2c66affSColin Finck /* Disable base modifier */
1721c2c66affSColin Finck flags &= ~FLAGS_BASE_PARAMETER;
1722c2c66affSColin Finck base = BASE_DECIMAL;
1723c2c66affSColin Finck parameters[pos].type = FORMAT_INT;
1724c2c66affSColin Finck break;
1725c2c66affSColin Finck
1726c2c66affSColin Finck case SPECIFIER_OCTAL:
1727c2c66affSColin Finck flags |= FLAGS_UNSIGNED;
1728c2c66affSColin Finck flags &= ~FLAGS_BASE_PARAMETER;
1729c2c66affSColin Finck base = BASE_OCTAL;
1730c2c66affSColin Finck parameters[pos].type = FORMAT_INT;
1731c2c66affSColin Finck break;
1732c2c66affSColin Finck
1733c2c66affSColin Finck #if defined(SPECIFIER_BINARY)
1734c2c66affSColin Finck case SPECIFIER_BINARY_UPPER:
1735c2c66affSColin Finck flags |= FLAGS_UPPER;
1736c2c66affSColin Finck /* FALLTHROUGH */
1737c2c66affSColin Finck case SPECIFIER_BINARY:
1738c2c66affSColin Finck flags |= FLAGS_NILPADDING;
1739c2c66affSColin Finck flags &= ~FLAGS_BASE_PARAMETER;
1740c2c66affSColin Finck base = BASE_BINARY;
1741c2c66affSColin Finck parameters[pos].type = FORMAT_INT;
1742c2c66affSColin Finck break;
1743c2c66affSColin Finck #endif
1744c2c66affSColin Finck
1745c2c66affSColin Finck case SPECIFIER_HEX_UPPER:
1746c2c66affSColin Finck flags |= FLAGS_UPPER;
1747c2c66affSColin Finck /* FALLTHROUGH */
1748c2c66affSColin Finck case SPECIFIER_HEX:
1749c2c66affSColin Finck flags |= FLAGS_UNSIGNED;
1750c2c66affSColin Finck flags &= ~FLAGS_BASE_PARAMETER;
1751c2c66affSColin Finck base = BASE_HEX;
1752c2c66affSColin Finck parameters[pos].type = FORMAT_INT;
1753c2c66affSColin Finck break;
1754c2c66affSColin Finck
1755c2c66affSColin Finck case SPECIFIER_FLOAT_E_UPPER:
1756c2c66affSColin Finck flags |= FLAGS_UPPER;
1757c2c66affSColin Finck /* FALLTHROUGH */
1758c2c66affSColin Finck case SPECIFIER_FLOAT_E:
1759c2c66affSColin Finck flags |= FLAGS_FLOAT_E;
1760c2c66affSColin Finck parameters[pos].type = FORMAT_DOUBLE;
1761c2c66affSColin Finck break;
1762c2c66affSColin Finck
1763c2c66affSColin Finck case SPECIFIER_FLOAT_G_UPPER:
1764c2c66affSColin Finck flags |= FLAGS_UPPER;
1765c2c66affSColin Finck /* FALLTHROUGH */
1766c2c66affSColin Finck case SPECIFIER_FLOAT_G:
1767c2c66affSColin Finck flags |= FLAGS_FLOAT_G;
1768c2c66affSColin Finck parameters[pos].type = FORMAT_DOUBLE;
1769c2c66affSColin Finck break;
1770c2c66affSColin Finck
1771c2c66affSColin Finck case SPECIFIER_FLOAT_F_UPPER:
1772c2c66affSColin Finck flags |= FLAGS_UPPER;
1773c2c66affSColin Finck /* FALLTHROUGH */
1774c2c66affSColin Finck case SPECIFIER_FLOAT_F:
1775c2c66affSColin Finck parameters[pos].type = FORMAT_DOUBLE;
1776c2c66affSColin Finck break;
1777c2c66affSColin Finck
1778c2c66affSColin Finck case SPECIFIER_POINTER:
1779c2c66affSColin Finck if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
1780c2c66affSColin Finck flags |= FLAGS_QUAD;
1781c2c66affSColin Finck else if (sizeof(trio_pointer_t) == sizeof(long))
1782c2c66affSColin Finck flags |= FLAGS_LONG;
1783c2c66affSColin Finck parameters[pos].type = FORMAT_POINTER;
1784c2c66affSColin Finck break;
1785c2c66affSColin Finck
1786c2c66affSColin Finck case SPECIFIER_COUNT:
1787c2c66affSColin Finck parameters[pos].type = FORMAT_COUNT;
1788c2c66affSColin Finck break;
1789c2c66affSColin Finck
1790c2c66affSColin Finck #if defined(SPECIFIER_HEXFLOAT)
1791c2c66affSColin Finck # if defined(SPECIFIER_HEXFLOAT_UPPER)
1792c2c66affSColin Finck case SPECIFIER_HEXFLOAT_UPPER:
1793c2c66affSColin Finck flags |= FLAGS_UPPER;
1794c2c66affSColin Finck /* FALLTHROUGH */
1795c2c66affSColin Finck # endif
1796c2c66affSColin Finck case SPECIFIER_HEXFLOAT:
1797c2c66affSColin Finck base = BASE_HEX;
1798c2c66affSColin Finck parameters[pos].type = FORMAT_DOUBLE;
1799c2c66affSColin Finck break;
1800c2c66affSColin Finck #endif
1801c2c66affSColin Finck
1802c2c66affSColin Finck #if defined(FORMAT_ERRNO)
1803c2c66affSColin Finck case SPECIFIER_ERRNO:
1804c2c66affSColin Finck parameters[pos].type = FORMAT_ERRNO;
1805c2c66affSColin Finck break;
1806c2c66affSColin Finck #endif
1807c2c66affSColin Finck
1808c2c66affSColin Finck #if defined(SPECIFIER_USER_DEFINED_BEGIN)
1809c2c66affSColin Finck case SPECIFIER_USER_DEFINED_BEGIN:
1810c2c66affSColin Finck {
1811c2c66affSColin Finck unsigned int max;
1812c2c66affSColin Finck int without_namespace = TRUE;
1813c2c66affSColin Finck
1814c2c66affSColin Finck parameters[pos].type = FORMAT_USER_DEFINED;
1815c2c66affSColin Finck parameters[pos].user_name[0] = NIL;
1816c2c66affSColin Finck tmpformat = (char *)&format[index];
1817c2c66affSColin Finck
1818c2c66affSColin Finck while ((ch = format[index]))
1819c2c66affSColin Finck {
1820c2c66affSColin Finck index++;
1821c2c66affSColin Finck if (ch == SPECIFIER_USER_DEFINED_END)
1822c2c66affSColin Finck {
1823c2c66affSColin Finck if (without_namespace)
1824c2c66affSColin Finck {
1825c2c66affSColin Finck /* We must get the handle first */
1826c2c66affSColin Finck parameters[pos].type = FORMAT_PARAMETER;
1827c2c66affSColin Finck parameters[pos].indexAfterSpecifier = index;
1828c2c66affSColin Finck parameters[pos].flags = FLAGS_USER_DEFINED;
1829c2c66affSColin Finck /* Adjust parameters for insertion of new one */
1830c2c66affSColin Finck pos++;
1831c2c66affSColin Finck usedEntries[currentParam] += 1;
1832c2c66affSColin Finck parameters[pos].type = FORMAT_USER_DEFINED;
1833c2c66affSColin Finck currentParam++;
1834c2c66affSColin Finck indices[currentParam] = pos;
1835c2c66affSColin Finck if (currentParam > maxParam)
1836c2c66affSColin Finck maxParam = currentParam;
1837c2c66affSColin Finck }
1838c2c66affSColin Finck /* Copy the user data */
1839c2c66affSColin Finck max = (unsigned int)(&format[index] - tmpformat);
1840c2c66affSColin Finck if (max > MAX_USER_DATA)
1841c2c66affSColin Finck max = MAX_USER_DATA;
1842c2c66affSColin Finck trio_copy_max(parameters[pos].user_data,
1843c2c66affSColin Finck max,
1844c2c66affSColin Finck tmpformat);
1845c2c66affSColin Finck break; /* while */
1846c2c66affSColin Finck }
1847c2c66affSColin Finck if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
1848c2c66affSColin Finck {
1849c2c66affSColin Finck without_namespace = FALSE;
1850c2c66affSColin Finck /* Copy the namespace for later looking-up */
1851c2c66affSColin Finck max = (int)(&format[index] - tmpformat);
1852c2c66affSColin Finck if (max > MAX_USER_NAME)
1853c2c66affSColin Finck max = MAX_USER_NAME;
1854c2c66affSColin Finck trio_copy_max(parameters[pos].user_name,
1855c2c66affSColin Finck max,
1856c2c66affSColin Finck tmpformat);
1857c2c66affSColin Finck tmpformat = (char *)&format[index];
1858c2c66affSColin Finck }
1859c2c66affSColin Finck }
1860c2c66affSColin Finck if (ch != SPECIFIER_USER_DEFINED_END)
1861c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1862c2c66affSColin Finck }
1863c2c66affSColin Finck break;
1864c2c66affSColin Finck #endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
1865c2c66affSColin Finck
1866c2c66affSColin Finck default:
1867c2c66affSColin Finck /* Bail out completely to make the error more obvious */
1868c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1869c2c66affSColin Finck }
1870c2c66affSColin Finck
1871c2c66affSColin Finck /* Count the number of times this entry has been used */
1872c2c66affSColin Finck usedEntries[currentParam] += 1;
1873c2c66affSColin Finck
1874c2c66affSColin Finck /* Find last sticky parameters */
1875c2c66affSColin Finck if (gotSticky && !(flags & FLAGS_STICKY))
1876c2c66affSColin Finck {
1877c2c66affSColin Finck for (i = pos - 1; i >= 0; i--)
1878c2c66affSColin Finck {
1879c2c66affSColin Finck if (parameters[i].type == FORMAT_PARAMETER)
1880c2c66affSColin Finck continue;
1881c2c66affSColin Finck if ((parameters[i].flags & FLAGS_STICKY) &&
1882c2c66affSColin Finck (parameters[i].type == parameters[pos].type))
1883c2c66affSColin Finck {
1884c2c66affSColin Finck /* Do not overwrite current qualifiers */
1885c2c66affSColin Finck flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
1886c2c66affSColin Finck if (width == NO_WIDTH)
1887c2c66affSColin Finck width = parameters[i].width;
1888c2c66affSColin Finck if (precision == NO_PRECISION)
1889c2c66affSColin Finck precision = parameters[i].precision;
1890c2c66affSColin Finck if (base == NO_BASE)
1891c2c66affSColin Finck base = parameters[i].base;
1892c2c66affSColin Finck break;
1893c2c66affSColin Finck }
1894c2c66affSColin Finck }
1895c2c66affSColin Finck }
1896c2c66affSColin Finck
1897c2c66affSColin Finck parameters[pos].indexAfterSpecifier = index;
1898c2c66affSColin Finck parameters[pos].flags = flags;
1899c2c66affSColin Finck parameters[pos].width = width;
1900c2c66affSColin Finck parameters[pos].precision = precision;
1901c2c66affSColin Finck parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base;
1902c2c66affSColin Finck parameters[pos].varsize = varsize;
1903c2c66affSColin Finck pos++;
1904c2c66affSColin Finck
1905c2c66affSColin Finck if (! positional)
1906c2c66affSColin Finck parameterPosition++;
1907c2c66affSColin Finck
1908c2c66affSColin Finck } /* if identifier */
1909c2c66affSColin Finck
1910c2c66affSColin Finck } /* while format characters left */
1911c2c66affSColin Finck
1912c2c66affSColin Finck for (num = 0; num <= maxParam; num++)
1913c2c66affSColin Finck {
1914c2c66affSColin Finck if (usedEntries[num] != 1)
1915c2c66affSColin Finck {
1916c2c66affSColin Finck if (usedEntries[num] == 0) /* gap detected */
1917c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EGAP, num);
1918c2c66affSColin Finck else /* double references detected */
1919c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EDBLREF, num);
1920c2c66affSColin Finck }
1921c2c66affSColin Finck
1922c2c66affSColin Finck i = indices[num];
1923c2c66affSColin Finck
1924c2c66affSColin Finck /*
1925c2c66affSColin Finck * FORMAT_PARAMETERS are only present if they must be read,
1926c2c66affSColin Finck * so it makes no sense to check the ignore flag (besides,
1927c2c66affSColin Finck * the flags variable is not set for that particular type)
1928c2c66affSColin Finck */
1929c2c66affSColin Finck if ((parameters[i].type != FORMAT_PARAMETER) &&
1930c2c66affSColin Finck (parameters[i].flags & FLAGS_IGNORE))
1931c2c66affSColin Finck continue; /* for all arguments */
1932c2c66affSColin Finck
1933c2c66affSColin Finck /*
1934c2c66affSColin Finck * The stack arguments are read according to ANSI C89
1935c2c66affSColin Finck * default argument promotions:
1936c2c66affSColin Finck *
1937c2c66affSColin Finck * char = int
1938c2c66affSColin Finck * short = int
1939c2c66affSColin Finck * unsigned char = unsigned int
1940c2c66affSColin Finck * unsigned short = unsigned int
1941c2c66affSColin Finck * float = double
1942c2c66affSColin Finck *
1943c2c66affSColin Finck * In addition to the ANSI C89 these types are read (the
1944c2c66affSColin Finck * default argument promotions of C99 has not been
1945c2c66affSColin Finck * considered yet)
1946c2c66affSColin Finck *
1947c2c66affSColin Finck * long long
1948c2c66affSColin Finck * long double
1949c2c66affSColin Finck * size_t
1950c2c66affSColin Finck * ptrdiff_t
1951c2c66affSColin Finck * intmax_t
1952c2c66affSColin Finck */
1953c2c66affSColin Finck switch (parameters[i].type)
1954c2c66affSColin Finck {
1955c2c66affSColin Finck case FORMAT_GROUP:
1956c2c66affSColin Finck case FORMAT_STRING:
1957c2c66affSColin Finck #if TRIO_WIDECHAR
1958c2c66affSColin Finck if (flags & FLAGS_WIDECHAR)
1959c2c66affSColin Finck {
1960c2c66affSColin Finck parameters[i].data.wstring = (argarray == NULL)
1961c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_wchar_t *)
1962c2c66affSColin Finck : (trio_wchar_t *)(argarray[num]);
1963c2c66affSColin Finck }
1964c2c66affSColin Finck else
1965c2c66affSColin Finck #endif
1966c2c66affSColin Finck {
1967c2c66affSColin Finck parameters[i].data.string = (argarray == NULL)
1968c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), char *)
1969c2c66affSColin Finck : (char *)(argarray[num]);
1970c2c66affSColin Finck }
1971c2c66affSColin Finck break;
1972c2c66affSColin Finck
1973c2c66affSColin Finck #if defined(FORMAT_USER_DEFINED)
1974c2c66affSColin Finck case FORMAT_USER_DEFINED:
1975c2c66affSColin Finck #endif
1976c2c66affSColin Finck case FORMAT_POINTER:
1977c2c66affSColin Finck case FORMAT_COUNT:
1978c2c66affSColin Finck case FORMAT_UNKNOWN:
1979c2c66affSColin Finck parameters[i].data.pointer = (argarray == NULL)
1980c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t )
1981c2c66affSColin Finck : argarray[num];
1982c2c66affSColin Finck break;
1983c2c66affSColin Finck
1984c2c66affSColin Finck case FORMAT_CHAR:
1985c2c66affSColin Finck case FORMAT_INT:
1986c2c66affSColin Finck if (TYPE_SCAN == type)
1987c2c66affSColin Finck {
1988c2c66affSColin Finck if (argarray == NULL)
1989c2c66affSColin Finck parameters[i].data.pointer =
1990c2c66affSColin Finck (trio_pointer_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t);
1991c2c66affSColin Finck else
1992c2c66affSColin Finck {
1993c2c66affSColin Finck if (parameters[i].type == FORMAT_CHAR)
1994c2c66affSColin Finck parameters[i].data.pointer =
1995c2c66affSColin Finck (trio_pointer_t)((char *)argarray[num]);
1996c2c66affSColin Finck else if (parameters[i].flags & FLAGS_SHORT)
1997c2c66affSColin Finck parameters[i].data.pointer =
1998c2c66affSColin Finck (trio_pointer_t)((short *)argarray[num]);
1999c2c66affSColin Finck else
2000c2c66affSColin Finck parameters[i].data.pointer =
2001c2c66affSColin Finck (trio_pointer_t)((int *)argarray[num]);
2002c2c66affSColin Finck }
2003c2c66affSColin Finck }
2004c2c66affSColin Finck else
2005c2c66affSColin Finck {
2006c2c66affSColin Finck #if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
2007c2c66affSColin Finck if (parameters[i].flags
2008c2c66affSColin Finck & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
2009c2c66affSColin Finck {
2010c2c66affSColin Finck if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
2011c2c66affSColin Finck {
2012c2c66affSColin Finck /*
2013c2c66affSColin Finck * Variable sizes are mapped onto the fixed sizes, in
2014c2c66affSColin Finck * accordance with integer promotion.
2015c2c66affSColin Finck *
2016c2c66affSColin Finck * Please note that this may not be portable, as we
2017c2c66affSColin Finck * only guess the size, not the layout of the numbers.
2018c2c66affSColin Finck * For example, if int is little-endian, and long is
2019c2c66affSColin Finck * big-endian, then this will fail.
2020c2c66affSColin Finck */
2021c2c66affSColin Finck varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
2022c2c66affSColin Finck }
2023c2c66affSColin Finck else
2024c2c66affSColin Finck {
2025c2c66affSColin Finck /* Used for the I<bits> modifiers */
2026c2c66affSColin Finck varsize = parameters[i].varsize;
2027c2c66affSColin Finck }
2028c2c66affSColin Finck parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
2029c2c66affSColin Finck
2030c2c66affSColin Finck if (varsize <= (int)sizeof(int))
2031c2c66affSColin Finck ;
2032c2c66affSColin Finck else if (varsize <= (int)sizeof(long))
2033c2c66affSColin Finck parameters[i].flags |= FLAGS_LONG;
2034c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
2035c2c66affSColin Finck else if (varsize <= (int)sizeof(trio_longlong_t))
2036c2c66affSColin Finck parameters[i].flags |= FLAGS_QUAD;
2037c2c66affSColin Finck else
2038c2c66affSColin Finck parameters[i].flags |= FLAGS_INTMAX_T;
2039c2c66affSColin Finck #else
2040c2c66affSColin Finck else
2041c2c66affSColin Finck parameters[i].flags |= FLAGS_QUAD;
2042c2c66affSColin Finck #endif
2043c2c66affSColin Finck }
2044c2c66affSColin Finck #endif /* defined(QUALIFIER_VARSIZE) */
2045c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
2046c2c66affSColin Finck if (parameters[i].flags & FLAGS_SIZE_T)
2047c2c66affSColin Finck parameters[i].data.number.as_unsigned = (argarray == NULL)
2048c2c66affSColin Finck ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), size_t)
2049c2c66affSColin Finck : (trio_uintmax_t)(*((size_t *)argarray[num]));
2050c2c66affSColin Finck else
2051c2c66affSColin Finck #endif
2052c2c66affSColin Finck #if defined(QUALIFIER_PTRDIFF_T)
2053c2c66affSColin Finck if (parameters[i].flags & FLAGS_PTRDIFF_T)
2054c2c66affSColin Finck parameters[i].data.number.as_unsigned = (argarray == NULL)
2055c2c66affSColin Finck ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), ptrdiff_t)
2056c2c66affSColin Finck : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
2057c2c66affSColin Finck else
2058c2c66affSColin Finck #endif
2059c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
2060c2c66affSColin Finck if (parameters[i].flags & FLAGS_INTMAX_T)
2061c2c66affSColin Finck parameters[i].data.number.as_unsigned = (argarray == NULL)
2062c2c66affSColin Finck ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_intmax_t)
2063c2c66affSColin Finck : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
2064c2c66affSColin Finck else
2065c2c66affSColin Finck #endif
2066c2c66affSColin Finck if (parameters[i].flags & FLAGS_QUAD)
2067c2c66affSColin Finck parameters[i].data.number.as_unsigned = (argarray == NULL)
2068c2c66affSColin Finck ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_ulonglong_t)
2069c2c66affSColin Finck : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
2070c2c66affSColin Finck else if (parameters[i].flags & FLAGS_LONG)
2071c2c66affSColin Finck parameters[i].data.number.as_unsigned = (argarray == NULL)
2072c2c66affSColin Finck ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), long)
2073c2c66affSColin Finck : (trio_uintmax_t)(*((long *)argarray[num]));
2074c2c66affSColin Finck else
2075c2c66affSColin Finck {
2076c2c66affSColin Finck if (argarray == NULL)
2077c2c66affSColin Finck parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int);
2078c2c66affSColin Finck else
2079c2c66affSColin Finck {
2080c2c66affSColin Finck if (parameters[i].type == FORMAT_CHAR)
2081c2c66affSColin Finck parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
2082c2c66affSColin Finck else if (parameters[i].flags & FLAGS_SHORT)
2083c2c66affSColin Finck parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
2084c2c66affSColin Finck else
2085c2c66affSColin Finck parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
2086c2c66affSColin Finck }
2087c2c66affSColin Finck }
2088c2c66affSColin Finck }
2089c2c66affSColin Finck break;
2090c2c66affSColin Finck
2091c2c66affSColin Finck case FORMAT_PARAMETER:
2092c2c66affSColin Finck /*
2093c2c66affSColin Finck * The parameter for the user-defined specifier is a pointer,
2094c2c66affSColin Finck * whereas the rest (width, precision, base) uses an integer.
2095c2c66affSColin Finck */
2096c2c66affSColin Finck if (parameters[i].flags & FLAGS_USER_DEFINED)
2097c2c66affSColin Finck parameters[i].data.pointer = (argarray == NULL)
2098c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t )
2099c2c66affSColin Finck : argarray[num];
2100c2c66affSColin Finck else
2101c2c66affSColin Finck parameters[i].data.number.as_unsigned = (argarray == NULL)
2102c2c66affSColin Finck ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int)
2103c2c66affSColin Finck : (trio_uintmax_t)(*((int *)argarray[num]));
2104c2c66affSColin Finck break;
2105c2c66affSColin Finck
2106c2c66affSColin Finck case FORMAT_DOUBLE:
2107c2c66affSColin Finck if (TYPE_SCAN == type)
2108c2c66affSColin Finck {
2109c2c66affSColin Finck if (parameters[i].flags & FLAGS_LONGDOUBLE)
2110c2c66affSColin Finck parameters[i].data.longdoublePointer = (argarray == NULL)
2111c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_long_double_t *)
2112c2c66affSColin Finck : (trio_long_double_t *)argarray[num];
2113c2c66affSColin Finck else
2114c2c66affSColin Finck {
2115c2c66affSColin Finck if (parameters[i].flags & FLAGS_LONG)
2116c2c66affSColin Finck parameters[i].data.doublePointer = (argarray == NULL)
2117c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), double *)
2118c2c66affSColin Finck : (double *)argarray[num];
2119c2c66affSColin Finck else
2120c2c66affSColin Finck parameters[i].data.doublePointer = (argarray == NULL)
2121c2c66affSColin Finck ? (double *)va_arg(TRIO_VA_LIST_DEREF(arglist), float *)
2122c2c66affSColin Finck : (double *)((float *)argarray[num]);
2123c2c66affSColin Finck }
2124c2c66affSColin Finck }
2125c2c66affSColin Finck else
2126c2c66affSColin Finck {
2127c2c66affSColin Finck if (parameters[i].flags & FLAGS_LONGDOUBLE)
2128c2c66affSColin Finck parameters[i].data.longdoubleNumber = (argarray == NULL)
2129c2c66affSColin Finck ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_long_double_t)
2130c2c66affSColin Finck : (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
2131c2c66affSColin Finck else
2132c2c66affSColin Finck {
2133c2c66affSColin Finck if (argarray == NULL)
2134c2c66affSColin Finck parameters[i].data.longdoubleNumber =
2135c2c66affSColin Finck (trio_long_double_t)va_arg(TRIO_VA_LIST_DEREF(arglist), double);
2136c2c66affSColin Finck else
2137c2c66affSColin Finck {
2138c2c66affSColin Finck if (parameters[i].flags & FLAGS_SHORT)
2139c2c66affSColin Finck parameters[i].data.longdoubleNumber =
2140c2c66affSColin Finck (trio_long_double_t)(*((float *)argarray[num]));
2141c2c66affSColin Finck else
2142c2c66affSColin Finck parameters[i].data.longdoubleNumber =
2143c2c66affSColin Finck (trio_long_double_t)(*((double *)argarray[num]));
2144c2c66affSColin Finck }
2145c2c66affSColin Finck }
2146c2c66affSColin Finck }
2147c2c66affSColin Finck break;
2148c2c66affSColin Finck
2149c2c66affSColin Finck #if defined(FORMAT_ERRNO)
2150c2c66affSColin Finck case FORMAT_ERRNO:
2151c2c66affSColin Finck parameters[i].data.errorNumber = save_errno;
2152c2c66affSColin Finck break;
2153c2c66affSColin Finck #endif
2154c2c66affSColin Finck
2155c2c66affSColin Finck default:
2156c2c66affSColin Finck break;
2157c2c66affSColin Finck }
2158c2c66affSColin Finck } /* for all specifiers */
2159c2c66affSColin Finck return num;
2160c2c66affSColin Finck }
2161c2c66affSColin Finck
2162c2c66affSColin Finck
2163c2c66affSColin Finck /*************************************************************************
2164c2c66affSColin Finck *
2165c2c66affSColin Finck * FORMATTING
2166c2c66affSColin Finck *
2167c2c66affSColin Finck ************************************************************************/
2168c2c66affSColin Finck
2169c2c66affSColin Finck
2170c2c66affSColin Finck /*************************************************************************
2171c2c66affSColin Finck * TrioWriteNumber
2172c2c66affSColin Finck *
2173c2c66affSColin Finck * Description:
2174c2c66affSColin Finck * Output a number.
2175c2c66affSColin Finck * The complexity of this function is a result of the complexity
2176c2c66affSColin Finck * of the dependencies of the flags.
2177c2c66affSColin Finck */
2178c2c66affSColin Finck TRIO_PRIVATE void
2179c2c66affSColin Finck TrioWriteNumber
2180c2c66affSColin Finck TRIO_ARGS6((self, number, flags, width, precision, base),
2181c2c66affSColin Finck trio_class_t *self,
2182c2c66affSColin Finck trio_uintmax_t number,
2183c2c66affSColin Finck trio_flags_t flags,
2184c2c66affSColin Finck int width,
2185c2c66affSColin Finck int precision,
2186c2c66affSColin Finck int base)
2187c2c66affSColin Finck {
2188c2c66affSColin Finck BOOLEAN_T isNegative;
2189c2c66affSColin Finck BOOLEAN_T isNumberZero;
2190c2c66affSColin Finck BOOLEAN_T isPrecisionZero;
2191c2c66affSColin Finck BOOLEAN_T ignoreNumber;
2192c2c66affSColin Finck char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
2193c2c66affSColin Finck char *bufferend;
2194c2c66affSColin Finck char *pointer;
2195c2c66affSColin Finck TRIO_CONST char *digits;
2196c2c66affSColin Finck int i;
2197c2c66affSColin Finck int length;
2198c2c66affSColin Finck char *p;
2199c2c66affSColin Finck int count;
2200c2c66affSColin Finck
2201c2c66affSColin Finck assert(VALID(self));
2202c2c66affSColin Finck assert(VALID(self->OutStream));
2203c2c66affSColin Finck assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
2204c2c66affSColin Finck
2205c2c66affSColin Finck digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
2206c2c66affSColin Finck if (base == NO_BASE)
2207c2c66affSColin Finck base = BASE_DECIMAL;
2208c2c66affSColin Finck
2209c2c66affSColin Finck isNumberZero = (number == 0);
2210c2c66affSColin Finck isPrecisionZero = (precision == 0);
2211c2c66affSColin Finck ignoreNumber = (isNumberZero
2212c2c66affSColin Finck && isPrecisionZero
2213c2c66affSColin Finck && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL)));
2214c2c66affSColin Finck
2215c2c66affSColin Finck if (flags & FLAGS_UNSIGNED)
2216c2c66affSColin Finck {
2217c2c66affSColin Finck isNegative = FALSE;
2218c2c66affSColin Finck flags &= ~FLAGS_SHOWSIGN;
2219c2c66affSColin Finck }
2220c2c66affSColin Finck else
2221c2c66affSColin Finck {
2222c2c66affSColin Finck isNegative = ((trio_intmax_t)number < 0);
2223c2c66affSColin Finck if (isNegative)
2224c2c66affSColin Finck number = -((trio_intmax_t)number);
2225c2c66affSColin Finck }
2226c2c66affSColin Finck
2227c2c66affSColin Finck if (flags & FLAGS_QUAD)
2228c2c66affSColin Finck number &= (trio_ulonglong_t)-1;
2229c2c66affSColin Finck else if (flags & FLAGS_LONG)
2230c2c66affSColin Finck number &= (unsigned long)-1;
2231c2c66affSColin Finck else
2232c2c66affSColin Finck number &= (unsigned int)-1;
2233c2c66affSColin Finck
2234c2c66affSColin Finck /* Build number */
2235c2c66affSColin Finck pointer = bufferend = &buffer[sizeof(buffer) - 1];
2236c2c66affSColin Finck *pointer-- = NIL;
2237c2c66affSColin Finck for (i = 1; i < (int)sizeof(buffer); i++)
2238c2c66affSColin Finck {
2239c2c66affSColin Finck *pointer-- = digits[number % base];
2240c2c66affSColin Finck number /= base;
2241c2c66affSColin Finck if (number == 0)
2242c2c66affSColin Finck break;
2243c2c66affSColin Finck
2244c2c66affSColin Finck if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
2245c2c66affSColin Finck {
2246c2c66affSColin Finck /*
2247c2c66affSColin Finck * We are building the number from the least significant
2248c2c66affSColin Finck * to the most significant digit, so we have to copy the
2249c2c66affSColin Finck * thousand separator backwards
2250c2c66affSColin Finck */
2251c2c66affSColin Finck length = internalThousandSeparatorLength;
2252c2c66affSColin Finck if (((int)(pointer - buffer) - length) > 0)
2253c2c66affSColin Finck {
2254c2c66affSColin Finck p = &internalThousandSeparator[length - 1];
2255c2c66affSColin Finck while (length-- > 0)
2256c2c66affSColin Finck *pointer-- = *p--;
2257c2c66affSColin Finck }
2258c2c66affSColin Finck }
2259c2c66affSColin Finck }
2260c2c66affSColin Finck
2261c2c66affSColin Finck if (! ignoreNumber)
2262c2c66affSColin Finck {
2263c2c66affSColin Finck /* Adjust width */
2264c2c66affSColin Finck width -= (bufferend - pointer) - 1;
2265c2c66affSColin Finck }
2266c2c66affSColin Finck
2267c2c66affSColin Finck /* Adjust precision */
2268c2c66affSColin Finck if (NO_PRECISION != precision)
2269c2c66affSColin Finck {
2270c2c66affSColin Finck precision -= (bufferend - pointer) - 1;
2271c2c66affSColin Finck if (precision < 0)
2272c2c66affSColin Finck precision = 0;
2273c2c66affSColin Finck flags |= FLAGS_NILPADDING;
2274c2c66affSColin Finck }
2275c2c66affSColin Finck
2276c2c66affSColin Finck /* Calculate padding */
2277c2c66affSColin Finck count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION)))
2278c2c66affSColin Finck ? precision
2279c2c66affSColin Finck : 0;
2280c2c66affSColin Finck
2281c2c66affSColin Finck /* Adjust width further */
2282c2c66affSColin Finck if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
2283c2c66affSColin Finck width--;
2284c2c66affSColin Finck if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
2285c2c66affSColin Finck {
2286c2c66affSColin Finck switch (base)
2287c2c66affSColin Finck {
2288c2c66affSColin Finck case BASE_BINARY:
2289c2c66affSColin Finck case BASE_HEX:
2290c2c66affSColin Finck width -= 2;
2291c2c66affSColin Finck break;
2292c2c66affSColin Finck case BASE_OCTAL:
2293c2c66affSColin Finck if (!(flags & FLAGS_NILPADDING) || (count == 0))
2294c2c66affSColin Finck width--;
2295c2c66affSColin Finck break;
2296c2c66affSColin Finck default:
2297c2c66affSColin Finck break;
2298c2c66affSColin Finck }
2299c2c66affSColin Finck }
2300c2c66affSColin Finck
2301c2c66affSColin Finck /* Output prefixes spaces if needed */
2302c2c66affSColin Finck if (! ((flags & FLAGS_LEFTADJUST) ||
2303c2c66affSColin Finck ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION))))
2304c2c66affSColin Finck {
2305c2c66affSColin Finck while (width-- > count)
2306c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2307c2c66affSColin Finck }
2308c2c66affSColin Finck
2309c2c66affSColin Finck /* width has been adjusted for signs and alternatives */
2310c2c66affSColin Finck if (isNegative)
2311c2c66affSColin Finck self->OutStream(self, '-');
2312c2c66affSColin Finck else if (flags & FLAGS_SHOWSIGN)
2313c2c66affSColin Finck self->OutStream(self, '+');
2314c2c66affSColin Finck else if (flags & FLAGS_SPACE)
2315c2c66affSColin Finck self->OutStream(self, ' ');
2316c2c66affSColin Finck
2317c2c66affSColin Finck /* Prefix is not written when the value is zero */
2318c2c66affSColin Finck if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
2319c2c66affSColin Finck {
2320c2c66affSColin Finck switch (base)
2321c2c66affSColin Finck {
2322c2c66affSColin Finck case BASE_BINARY:
2323c2c66affSColin Finck self->OutStream(self, '0');
2324c2c66affSColin Finck self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b');
2325c2c66affSColin Finck break;
2326c2c66affSColin Finck
2327c2c66affSColin Finck case BASE_OCTAL:
2328c2c66affSColin Finck if (!(flags & FLAGS_NILPADDING) || (count == 0))
2329c2c66affSColin Finck self->OutStream(self, '0');
2330c2c66affSColin Finck break;
2331c2c66affSColin Finck
2332c2c66affSColin Finck case BASE_HEX:
2333c2c66affSColin Finck self->OutStream(self, '0');
2334c2c66affSColin Finck self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
2335c2c66affSColin Finck break;
2336c2c66affSColin Finck
2337c2c66affSColin Finck default:
2338c2c66affSColin Finck break;
2339c2c66affSColin Finck } /* switch base */
2340c2c66affSColin Finck }
2341c2c66affSColin Finck
2342c2c66affSColin Finck /* Output prefixed zero padding if needed */
2343c2c66affSColin Finck if (flags & FLAGS_NILPADDING)
2344c2c66affSColin Finck {
2345c2c66affSColin Finck if (precision == NO_PRECISION)
2346c2c66affSColin Finck precision = width;
2347c2c66affSColin Finck while (precision-- > 0)
2348c2c66affSColin Finck {
2349c2c66affSColin Finck self->OutStream(self, '0');
2350c2c66affSColin Finck width--;
2351c2c66affSColin Finck }
2352c2c66affSColin Finck }
2353c2c66affSColin Finck
2354c2c66affSColin Finck if (! ignoreNumber)
2355c2c66affSColin Finck {
2356c2c66affSColin Finck /* Output the number itself */
2357c2c66affSColin Finck while (*(++pointer))
2358c2c66affSColin Finck {
2359c2c66affSColin Finck self->OutStream(self, *pointer);
2360c2c66affSColin Finck }
2361c2c66affSColin Finck }
2362c2c66affSColin Finck
2363c2c66affSColin Finck /* Output trailing spaces if needed */
2364c2c66affSColin Finck if (flags & FLAGS_LEFTADJUST)
2365c2c66affSColin Finck {
2366c2c66affSColin Finck while (width-- > 0)
2367c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2368c2c66affSColin Finck }
2369c2c66affSColin Finck }
2370c2c66affSColin Finck
2371c2c66affSColin Finck /*************************************************************************
2372c2c66affSColin Finck * TrioWriteStringCharacter
2373c2c66affSColin Finck *
2374c2c66affSColin Finck * Description:
2375c2c66affSColin Finck * Output a single character of a string
2376c2c66affSColin Finck */
2377c2c66affSColin Finck TRIO_PRIVATE void
2378c2c66affSColin Finck TrioWriteStringCharacter
2379c2c66affSColin Finck TRIO_ARGS3((self, ch, flags),
2380c2c66affSColin Finck trio_class_t *self,
2381c2c66affSColin Finck int ch,
2382c2c66affSColin Finck trio_flags_t flags)
2383c2c66affSColin Finck {
2384c2c66affSColin Finck if (flags & FLAGS_ALTERNATIVE)
2385c2c66affSColin Finck {
2386c2c66affSColin Finck if (! isprint(ch))
2387c2c66affSColin Finck {
2388c2c66affSColin Finck /*
2389c2c66affSColin Finck * Non-printable characters are converted to C escapes or
2390c2c66affSColin Finck * \number, if no C escape exists.
2391c2c66affSColin Finck */
2392c2c66affSColin Finck self->OutStream(self, CHAR_BACKSLASH);
2393c2c66affSColin Finck switch (ch)
2394c2c66affSColin Finck {
2395c2c66affSColin Finck case '\007': self->OutStream(self, 'a'); break;
2396c2c66affSColin Finck case '\b': self->OutStream(self, 'b'); break;
2397c2c66affSColin Finck case '\f': self->OutStream(self, 'f'); break;
2398c2c66affSColin Finck case '\n': self->OutStream(self, 'n'); break;
2399c2c66affSColin Finck case '\r': self->OutStream(self, 'r'); break;
2400c2c66affSColin Finck case '\t': self->OutStream(self, 't'); break;
2401c2c66affSColin Finck case '\v': self->OutStream(self, 'v'); break;
2402c2c66affSColin Finck case '\\': self->OutStream(self, '\\'); break;
2403c2c66affSColin Finck default:
2404c2c66affSColin Finck self->OutStream(self, 'x');
2405c2c66affSColin Finck TrioWriteNumber(self, (trio_uintmax_t)ch,
2406c2c66affSColin Finck FLAGS_UNSIGNED | FLAGS_NILPADDING,
2407c2c66affSColin Finck 2, 2, BASE_HEX);
2408c2c66affSColin Finck break;
2409c2c66affSColin Finck }
2410c2c66affSColin Finck }
2411c2c66affSColin Finck else if (ch == CHAR_BACKSLASH)
2412c2c66affSColin Finck {
2413c2c66affSColin Finck self->OutStream(self, CHAR_BACKSLASH);
2414c2c66affSColin Finck self->OutStream(self, CHAR_BACKSLASH);
2415c2c66affSColin Finck }
2416c2c66affSColin Finck else
2417c2c66affSColin Finck {
2418c2c66affSColin Finck self->OutStream(self, ch);
2419c2c66affSColin Finck }
2420c2c66affSColin Finck }
2421c2c66affSColin Finck else
2422c2c66affSColin Finck {
2423c2c66affSColin Finck self->OutStream(self, ch);
2424c2c66affSColin Finck }
2425c2c66affSColin Finck }
2426c2c66affSColin Finck
2427c2c66affSColin Finck /*************************************************************************
2428c2c66affSColin Finck * TrioWriteString
2429c2c66affSColin Finck *
2430c2c66affSColin Finck * Description:
2431c2c66affSColin Finck * Output a string
2432c2c66affSColin Finck */
2433c2c66affSColin Finck TRIO_PRIVATE void
2434c2c66affSColin Finck TrioWriteString
2435c2c66affSColin Finck TRIO_ARGS5((self, string, flags, width, precision),
2436c2c66affSColin Finck trio_class_t *self,
2437c2c66affSColin Finck TRIO_CONST char *string,
2438c2c66affSColin Finck trio_flags_t flags,
2439c2c66affSColin Finck int width,
2440c2c66affSColin Finck int precision)
2441c2c66affSColin Finck {
2442c2c66affSColin Finck int length;
2443c2c66affSColin Finck int ch;
2444c2c66affSColin Finck
2445c2c66affSColin Finck assert(VALID(self));
2446c2c66affSColin Finck assert(VALID(self->OutStream));
2447c2c66affSColin Finck
2448c2c66affSColin Finck if (string == NULL)
2449c2c66affSColin Finck {
2450c2c66affSColin Finck string = internalNullString;
2451c2c66affSColin Finck length = sizeof(internalNullString) - 1;
2452c2c66affSColin Finck /* Disable quoting for the null pointer */
2453c2c66affSColin Finck flags &= (~FLAGS_QUOTE);
2454c2c66affSColin Finck width = 0;
2455c2c66affSColin Finck }
2456c2c66affSColin Finck else
2457c2c66affSColin Finck {
2458c2c66affSColin Finck length = trio_length(string);
2459c2c66affSColin Finck }
2460c2c66affSColin Finck if ((NO_PRECISION != precision) &&
2461c2c66affSColin Finck (precision < length))
2462c2c66affSColin Finck {
2463c2c66affSColin Finck length = precision;
2464c2c66affSColin Finck }
2465c2c66affSColin Finck width -= length;
2466c2c66affSColin Finck
2467c2c66affSColin Finck if (flags & FLAGS_QUOTE)
2468c2c66affSColin Finck self->OutStream(self, CHAR_QUOTE);
2469c2c66affSColin Finck
2470c2c66affSColin Finck if (! (flags & FLAGS_LEFTADJUST))
2471c2c66affSColin Finck {
2472c2c66affSColin Finck while (width-- > 0)
2473c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2474c2c66affSColin Finck }
2475c2c66affSColin Finck
2476c2c66affSColin Finck while (length-- > 0)
2477c2c66affSColin Finck {
2478c2c66affSColin Finck /* The ctype parameters must be an unsigned char (or EOF) */
2479c2c66affSColin Finck ch = (int)((unsigned char)(*string++));
2480c2c66affSColin Finck TrioWriteStringCharacter(self, ch, flags);
2481c2c66affSColin Finck }
2482c2c66affSColin Finck
2483c2c66affSColin Finck if (flags & FLAGS_LEFTADJUST)
2484c2c66affSColin Finck {
2485c2c66affSColin Finck while (width-- > 0)
2486c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2487c2c66affSColin Finck }
2488c2c66affSColin Finck if (flags & FLAGS_QUOTE)
2489c2c66affSColin Finck self->OutStream(self, CHAR_QUOTE);
2490c2c66affSColin Finck }
2491c2c66affSColin Finck
2492c2c66affSColin Finck /*************************************************************************
2493c2c66affSColin Finck * TrioWriteWideStringCharacter
2494c2c66affSColin Finck *
2495c2c66affSColin Finck * Description:
2496c2c66affSColin Finck * Output a wide string as a multi-byte sequence
2497c2c66affSColin Finck */
2498c2c66affSColin Finck #if TRIO_WIDECHAR
2499c2c66affSColin Finck TRIO_PRIVATE int
2500c2c66affSColin Finck TrioWriteWideStringCharacter
2501c2c66affSColin Finck TRIO_ARGS4((self, wch, flags, width),
2502c2c66affSColin Finck trio_class_t *self,
2503c2c66affSColin Finck trio_wchar_t wch,
2504c2c66affSColin Finck trio_flags_t flags,
2505c2c66affSColin Finck int width)
2506c2c66affSColin Finck {
2507c2c66affSColin Finck int size;
2508c2c66affSColin Finck int i;
2509c2c66affSColin Finck int ch;
2510c2c66affSColin Finck char *string;
2511c2c66affSColin Finck char buffer[MB_LEN_MAX + 1];
2512c2c66affSColin Finck
2513c2c66affSColin Finck if (width == NO_WIDTH)
2514c2c66affSColin Finck width = sizeof(buffer);
2515c2c66affSColin Finck
2516c2c66affSColin Finck size = wctomb(buffer, wch);
2517c2c66affSColin Finck if ((size <= 0) || (size > width) || (buffer[0] == NIL))
2518c2c66affSColin Finck return 0;
2519c2c66affSColin Finck
2520c2c66affSColin Finck string = buffer;
2521c2c66affSColin Finck i = size;
2522c2c66affSColin Finck while ((width >= i) && (width-- > 0) && (i-- > 0))
2523c2c66affSColin Finck {
2524c2c66affSColin Finck /* The ctype parameters must be an unsigned char (or EOF) */
2525c2c66affSColin Finck ch = (int)((unsigned char)(*string++));
2526c2c66affSColin Finck TrioWriteStringCharacter(self, ch, flags);
2527c2c66affSColin Finck }
2528c2c66affSColin Finck return size;
2529c2c66affSColin Finck }
2530c2c66affSColin Finck #endif /* TRIO_WIDECHAR */
2531c2c66affSColin Finck
2532c2c66affSColin Finck /*************************************************************************
2533c2c66affSColin Finck * TrioWriteWideString
2534c2c66affSColin Finck *
2535c2c66affSColin Finck * Description:
2536c2c66affSColin Finck * Output a wide character string as a multi-byte string
2537c2c66affSColin Finck */
2538c2c66affSColin Finck #if TRIO_WIDECHAR
2539c2c66affSColin Finck TRIO_PRIVATE void
2540c2c66affSColin Finck TrioWriteWideString
2541c2c66affSColin Finck TRIO_ARGS5((self, wstring, flags, width, precision),
2542c2c66affSColin Finck trio_class_t *self,
2543c2c66affSColin Finck TRIO_CONST trio_wchar_t *wstring,
2544c2c66affSColin Finck trio_flags_t flags,
2545c2c66affSColin Finck int width,
2546c2c66affSColin Finck int precision)
2547c2c66affSColin Finck {
2548c2c66affSColin Finck int length;
2549c2c66affSColin Finck int size;
2550c2c66affSColin Finck
2551c2c66affSColin Finck assert(VALID(self));
2552c2c66affSColin Finck assert(VALID(self->OutStream));
2553c2c66affSColin Finck
2554c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2555c2c66affSColin Finck (void)mblen(NULL, 0);
2556c2c66affSColin Finck #endif
2557c2c66affSColin Finck
2558c2c66affSColin Finck if (wstring == NULL)
2559c2c66affSColin Finck {
2560c2c66affSColin Finck TrioWriteString(self, NULL, flags, width, precision);
2561c2c66affSColin Finck return;
2562c2c66affSColin Finck }
2563c2c66affSColin Finck
2564c2c66affSColin Finck if (NO_PRECISION == precision)
2565c2c66affSColin Finck {
2566c2c66affSColin Finck length = INT_MAX;
2567c2c66affSColin Finck }
2568c2c66affSColin Finck else
2569c2c66affSColin Finck {
2570c2c66affSColin Finck length = precision;
2571c2c66affSColin Finck width -= length;
2572c2c66affSColin Finck }
2573c2c66affSColin Finck
2574c2c66affSColin Finck if (flags & FLAGS_QUOTE)
2575c2c66affSColin Finck self->OutStream(self, CHAR_QUOTE);
2576c2c66affSColin Finck
2577c2c66affSColin Finck if (! (flags & FLAGS_LEFTADJUST))
2578c2c66affSColin Finck {
2579c2c66affSColin Finck while (width-- > 0)
2580c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2581c2c66affSColin Finck }
2582c2c66affSColin Finck
2583c2c66affSColin Finck while (length > 0)
2584c2c66affSColin Finck {
2585c2c66affSColin Finck size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
2586c2c66affSColin Finck if (size == 0)
2587c2c66affSColin Finck break; /* while */
2588c2c66affSColin Finck length -= size;
2589c2c66affSColin Finck }
2590c2c66affSColin Finck
2591c2c66affSColin Finck if (flags & FLAGS_LEFTADJUST)
2592c2c66affSColin Finck {
2593c2c66affSColin Finck while (width-- > 0)
2594c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2595c2c66affSColin Finck }
2596c2c66affSColin Finck if (flags & FLAGS_QUOTE)
2597c2c66affSColin Finck self->OutStream(self, CHAR_QUOTE);
2598c2c66affSColin Finck }
2599c2c66affSColin Finck #endif /* TRIO_WIDECHAR */
2600c2c66affSColin Finck
2601c2c66affSColin Finck /*************************************************************************
2602c2c66affSColin Finck * TrioWriteDouble
2603c2c66affSColin Finck *
2604c2c66affSColin Finck * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm
2605c2c66affSColin Finck *
2606c2c66affSColin Finck * "5.2.4.2.2 paragraph #4
2607c2c66affSColin Finck *
2608c2c66affSColin Finck * The accuracy [...] is implementation defined, as is the accuracy
2609c2c66affSColin Finck * of the conversion between floating-point internal representations
2610f22fa382SThomas Faber * and string representations performed by the library routine in
2611c2c66affSColin Finck * <stdio.h>"
2612c2c66affSColin Finck */
2613c2c66affSColin Finck /* FIXME: handle all instances of constant long-double number (L)
2614c2c66affSColin Finck * and *l() math functions.
2615c2c66affSColin Finck */
2616c2c66affSColin Finck TRIO_PRIVATE void
2617c2c66affSColin Finck TrioWriteDouble
2618c2c66affSColin Finck TRIO_ARGS6((self, number, flags, width, precision, base),
2619c2c66affSColin Finck trio_class_t *self,
2620c2c66affSColin Finck trio_long_double_t number,
2621c2c66affSColin Finck trio_flags_t flags,
2622c2c66affSColin Finck int width,
2623c2c66affSColin Finck int precision,
2624c2c66affSColin Finck int base)
2625c2c66affSColin Finck {
2626c2c66affSColin Finck trio_long_double_t integerNumber;
2627c2c66affSColin Finck trio_long_double_t fractionNumber;
2628c2c66affSColin Finck trio_long_double_t workNumber;
2629c2c66affSColin Finck int integerDigits;
2630c2c66affSColin Finck int fractionDigits;
2631c2c66affSColin Finck int exponentDigits;
2632c2c66affSColin Finck int baseDigits;
2633c2c66affSColin Finck int integerThreshold;
2634c2c66affSColin Finck int fractionThreshold;
2635c2c66affSColin Finck int expectedWidth;
2636c2c66affSColin Finck int exponent = 0;
2637c2c66affSColin Finck unsigned int uExponent = 0;
2638c2c66affSColin Finck int exponentBase;
2639c2c66affSColin Finck trio_long_double_t dblBase;
2640c2c66affSColin Finck trio_long_double_t dblIntegerBase;
2641c2c66affSColin Finck trio_long_double_t dblFractionBase;
2642c2c66affSColin Finck trio_long_double_t integerAdjust;
2643c2c66affSColin Finck trio_long_double_t fractionAdjust;
2644c2c66affSColin Finck BOOLEAN_T isNegative;
2645c2c66affSColin Finck BOOLEAN_T isExponentNegative = FALSE;
2646c2c66affSColin Finck BOOLEAN_T requireTwoDigitExponent;
2647c2c66affSColin Finck BOOLEAN_T isHex;
2648c2c66affSColin Finck TRIO_CONST char *digits;
2649c2c66affSColin Finck char *groupingPointer;
2650c2c66affSColin Finck int i;
2651c2c66affSColin Finck int index;
2652c2c66affSColin Finck BOOLEAN_T hasOnlyZeroes;
2653c2c66affSColin Finck int zeroes = 0;
2654c2c66affSColin Finck register int trailingZeroes;
2655c2c66affSColin Finck BOOLEAN_T keepTrailingZeroes;
2656c2c66affSColin Finck BOOLEAN_T keepDecimalPoint;
2657c2c66affSColin Finck trio_long_double_t epsilon;
2658c2c66affSColin Finck
2659c2c66affSColin Finck assert(VALID(self));
2660c2c66affSColin Finck assert(VALID(self->OutStream));
2661c2c66affSColin Finck assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
2662c2c66affSColin Finck
2663c2c66affSColin Finck /* Determine sign and look for special quantities */
2664c2c66affSColin Finck switch (trio_fpclassify_and_signbit(number, &isNegative))
2665c2c66affSColin Finck {
2666c2c66affSColin Finck case TRIO_FP_NAN:
2667c2c66affSColin Finck TrioWriteString(self,
2668c2c66affSColin Finck (flags & FLAGS_UPPER)
2669c2c66affSColin Finck ? NAN_UPPER
2670c2c66affSColin Finck : NAN_LOWER,
2671c2c66affSColin Finck flags, width, precision);
2672c2c66affSColin Finck return;
2673c2c66affSColin Finck
2674c2c66affSColin Finck case TRIO_FP_INFINITE:
2675c2c66affSColin Finck if (isNegative)
2676c2c66affSColin Finck {
2677c2c66affSColin Finck /* Negative infinity */
2678c2c66affSColin Finck TrioWriteString(self,
2679c2c66affSColin Finck (flags & FLAGS_UPPER)
2680c2c66affSColin Finck ? "-" INFINITE_UPPER
2681c2c66affSColin Finck : "-" INFINITE_LOWER,
2682c2c66affSColin Finck flags, width, precision);
2683c2c66affSColin Finck return;
2684c2c66affSColin Finck }
2685c2c66affSColin Finck else
2686c2c66affSColin Finck {
2687c2c66affSColin Finck /* Positive infinity */
2688c2c66affSColin Finck TrioWriteString(self,
2689c2c66affSColin Finck (flags & FLAGS_UPPER)
2690c2c66affSColin Finck ? INFINITE_UPPER
2691c2c66affSColin Finck : INFINITE_LOWER,
2692c2c66affSColin Finck flags, width, precision);
2693c2c66affSColin Finck return;
2694c2c66affSColin Finck }
2695c2c66affSColin Finck
2696c2c66affSColin Finck default:
2697c2c66affSColin Finck /* Finitude */
2698c2c66affSColin Finck break;
2699c2c66affSColin Finck }
2700c2c66affSColin Finck
2701c2c66affSColin Finck /* Normal numbers */
2702c2c66affSColin Finck if (flags & FLAGS_LONGDOUBLE)
2703c2c66affSColin Finck {
2704c2c66affSColin Finck baseDigits = (base == 10)
2705c2c66affSColin Finck ? LDBL_DIG
2706c2c66affSColin Finck : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
2707c2c66affSColin Finck epsilon = LDBL_EPSILON;
2708c2c66affSColin Finck }
2709c2c66affSColin Finck else if (flags & FLAGS_SHORT)
2710c2c66affSColin Finck {
2711c2c66affSColin Finck baseDigits = (base == BASE_DECIMAL)
2712c2c66affSColin Finck ? FLT_DIG
2713c2c66affSColin Finck : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base));
2714c2c66affSColin Finck epsilon = FLT_EPSILON;
2715c2c66affSColin Finck }
2716c2c66affSColin Finck else
2717c2c66affSColin Finck {
2718c2c66affSColin Finck baseDigits = (base == BASE_DECIMAL)
2719c2c66affSColin Finck ? DBL_DIG
2720c2c66affSColin Finck : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
2721c2c66affSColin Finck epsilon = DBL_EPSILON;
2722c2c66affSColin Finck }
2723c2c66affSColin Finck
2724c2c66affSColin Finck digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
2725c2c66affSColin Finck isHex = (base == BASE_HEX);
2726c2c66affSColin Finck if (base == NO_BASE)
2727c2c66affSColin Finck base = BASE_DECIMAL;
2728c2c66affSColin Finck dblBase = (trio_long_double_t)base;
2729c2c66affSColin Finck keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) ||
2730c2c66affSColin Finck ( (flags & FLAGS_FLOAT_G) &&
2731c2c66affSColin Finck !(flags & FLAGS_ALTERNATIVE) ) );
2732c2c66affSColin Finck
2733c2c66affSColin Finck if (flags & FLAGS_ROUNDING)
2734c2c66affSColin Finck precision = baseDigits;
2735c2c66affSColin Finck
2736c2c66affSColin Finck if (precision == NO_PRECISION)
2737c2c66affSColin Finck {
2738c2c66affSColin Finck if (isHex)
2739c2c66affSColin Finck {
2740c2c66affSColin Finck keepTrailingZeroes = FALSE;
2741c2c66affSColin Finck precision = FLT_MANT_DIG;
2742c2c66affSColin Finck }
2743c2c66affSColin Finck else
2744c2c66affSColin Finck {
2745c2c66affSColin Finck precision = FLT_DIG;
2746c2c66affSColin Finck }
2747c2c66affSColin Finck }
2748c2c66affSColin Finck
2749c2c66affSColin Finck if (isNegative)
2750c2c66affSColin Finck number = -number;
2751c2c66affSColin Finck
2752c2c66affSColin Finck if (isHex)
2753c2c66affSColin Finck flags |= FLAGS_FLOAT_E;
2754c2c66affSColin Finck
2755c2c66affSColin Finck if (flags & FLAGS_FLOAT_G)
2756c2c66affSColin Finck {
2757c2c66affSColin Finck if (precision == 0)
2758c2c66affSColin Finck precision = 1;
2759c2c66affSColin Finck
2760c2c66affSColin Finck if ((number < 1.0E-4) || (number > powl(base,
2761c2c66affSColin Finck (trio_long_double_t)precision)))
2762c2c66affSColin Finck {
2763c2c66affSColin Finck /* Use scientific notation */
2764c2c66affSColin Finck flags |= FLAGS_FLOAT_E;
2765c2c66affSColin Finck }
2766c2c66affSColin Finck else if (number < 1.0)
2767c2c66affSColin Finck {
2768c2c66affSColin Finck /*
2769c2c66affSColin Finck * Use normal notation. If the integer part of the number is
2770c2c66affSColin Finck * zero, then adjust the precision to include leading fractional
2771c2c66affSColin Finck * zeros.
2772c2c66affSColin Finck */
2773c2c66affSColin Finck workNumber = TrioLogarithm(number, base);
2774c2c66affSColin Finck workNumber = TRIO_FABS(workNumber);
2775c2c66affSColin Finck if (workNumber - floorl(workNumber) < 0.001)
2776c2c66affSColin Finck workNumber--;
2777c2c66affSColin Finck zeroes = (int)floorl(workNumber);
2778c2c66affSColin Finck }
2779c2c66affSColin Finck }
2780c2c66affSColin Finck
2781c2c66affSColin Finck if (flags & FLAGS_FLOAT_E)
2782c2c66affSColin Finck {
2783c2c66affSColin Finck /* Scale the number */
2784c2c66affSColin Finck workNumber = TrioLogarithm(number, base);
2785c2c66affSColin Finck if (trio_isinf(workNumber) == -1)
2786c2c66affSColin Finck {
2787c2c66affSColin Finck exponent = 0;
2788c2c66affSColin Finck /* Undo setting */
2789c2c66affSColin Finck if (flags & FLAGS_FLOAT_G)
2790c2c66affSColin Finck flags &= ~FLAGS_FLOAT_E;
2791c2c66affSColin Finck }
2792c2c66affSColin Finck else
2793c2c66affSColin Finck {
2794c2c66affSColin Finck exponent = (int)floorl(workNumber);
2795c2c66affSColin Finck number /= powl(dblBase, (trio_long_double_t)exponent);
2796c2c66affSColin Finck isExponentNegative = (exponent < 0);
2797c2c66affSColin Finck uExponent = (isExponentNegative) ? -exponent : exponent;
2798c2c66affSColin Finck if (isHex)
2799c2c66affSColin Finck uExponent *= 4; /* log16(2) */
2800c2c66affSColin Finck /* No thousand separators */
2801c2c66affSColin Finck flags &= ~FLAGS_QUOTE;
2802c2c66affSColin Finck }
2803c2c66affSColin Finck }
2804c2c66affSColin Finck
2805c2c66affSColin Finck integerNumber = floorl(number);
2806c2c66affSColin Finck fractionNumber = number - integerNumber;
2807c2c66affSColin Finck
2808c2c66affSColin Finck /*
2809c2c66affSColin Finck * Truncated number.
2810c2c66affSColin Finck *
2811c2c66affSColin Finck * Precision is number of significant digits for FLOAT_G
2812c2c66affSColin Finck * and number of fractional digits for others.
2813c2c66affSColin Finck */
2814c2c66affSColin Finck integerDigits = (integerNumber > epsilon)
2815c2c66affSColin Finck ? 1 + (int)TrioLogarithm(integerNumber, base)
2816c2c66affSColin Finck : 1;
2817c2c66affSColin Finck fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
2818c2c66affSColin Finck ? precision - integerDigits
2819c2c66affSColin Finck : zeroes + precision;
2820c2c66affSColin Finck
2821c2c66affSColin Finck dblFractionBase = TrioPower(base, fractionDigits);
2822c2c66affSColin Finck
2823c2c66affSColin Finck workNumber = number + 0.5 / dblFractionBase;
2824c2c66affSColin Finck if (floorl(number) != floorl(workNumber))
2825c2c66affSColin Finck {
2826c2c66affSColin Finck if (flags & FLAGS_FLOAT_E)
2827c2c66affSColin Finck {
2828c2c66affSColin Finck /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
2829c2c66affSColin Finck exponent++;
2830c2c66affSColin Finck isExponentNegative = (exponent < 0);
2831c2c66affSColin Finck uExponent = (isExponentNegative) ? -exponent : exponent;
2832c2c66affSColin Finck if (isHex)
2833c2c66affSColin Finck uExponent *= 4; /* log16(2) */
2834c2c66affSColin Finck workNumber = (number + 0.5 / dblFractionBase) / dblBase;
2835c2c66affSColin Finck integerNumber = floorl(workNumber);
2836c2c66affSColin Finck fractionNumber = workNumber - integerNumber;
2837c2c66affSColin Finck }
2838c2c66affSColin Finck else
2839c2c66affSColin Finck {
2840c2c66affSColin Finck /* Adjust if number was rounded up one digit (ie. 99 to 100) */
2841c2c66affSColin Finck integerNumber = floorl(number + 0.5);
2842c2c66affSColin Finck fractionNumber = 0.0;
2843c2c66affSColin Finck integerDigits = (integerNumber > epsilon)
2844c2c66affSColin Finck ? 1 + (int)TrioLogarithm(integerNumber, base)
2845c2c66affSColin Finck : 1;
2846c2c66affSColin Finck }
2847c2c66affSColin Finck }
2848c2c66affSColin Finck
2849c2c66affSColin Finck /* Estimate accuracy */
2850c2c66affSColin Finck integerAdjust = fractionAdjust = 0.5;
2851c2c66affSColin Finck if (flags & FLAGS_ROUNDING)
2852c2c66affSColin Finck {
2853c2c66affSColin Finck if (integerDigits > baseDigits)
2854c2c66affSColin Finck {
2855c2c66affSColin Finck integerThreshold = baseDigits;
2856c2c66affSColin Finck fractionDigits = 0;
2857c2c66affSColin Finck dblFractionBase = 1.0;
2858c2c66affSColin Finck fractionThreshold = 0;
2859c2c66affSColin Finck precision = 0; /* Disable decimal-point */
2860c2c66affSColin Finck integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1);
2861c2c66affSColin Finck fractionAdjust = 0.0;
2862c2c66affSColin Finck }
2863c2c66affSColin Finck else
2864c2c66affSColin Finck {
2865c2c66affSColin Finck integerThreshold = integerDigits;
2866c2c66affSColin Finck fractionThreshold = fractionDigits - integerThreshold;
2867c2c66affSColin Finck fractionAdjust = 1.0;
2868c2c66affSColin Finck }
2869c2c66affSColin Finck }
2870c2c66affSColin Finck else
2871c2c66affSColin Finck {
2872c2c66affSColin Finck integerThreshold = INT_MAX;
2873c2c66affSColin Finck fractionThreshold = INT_MAX;
2874c2c66affSColin Finck }
2875c2c66affSColin Finck
2876c2c66affSColin Finck /*
2877c2c66affSColin Finck * Calculate expected width.
2878c2c66affSColin Finck * sign + integer part + thousands separators + decimal point
2879c2c66affSColin Finck * + fraction + exponent
2880c2c66affSColin Finck */
2881c2c66affSColin Finck fractionAdjust /= dblFractionBase;
2882c2c66affSColin Finck hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
2883c2c66affSColin Finck keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
2884c2c66affSColin Finck !((precision == 0) ||
2885c2c66affSColin Finck (!keepTrailingZeroes && hasOnlyZeroes)) );
2886c2c66affSColin Finck if (flags & FLAGS_FLOAT_E)
2887c2c66affSColin Finck {
2888c2c66affSColin Finck exponentDigits = (uExponent == 0)
2889c2c66affSColin Finck ? 1
2890c2c66affSColin Finck : (int)ceil(TrioLogarithm((double)(uExponent + 1),
2891c2c66affSColin Finck (isHex) ? 10.0 : base));
2892c2c66affSColin Finck }
2893c2c66affSColin Finck else
2894c2c66affSColin Finck exponentDigits = 0;
2895c2c66affSColin Finck requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1));
2896c2c66affSColin Finck
2897c2c66affSColin Finck expectedWidth = integerDigits + fractionDigits
2898c2c66affSColin Finck + (keepDecimalPoint
2899c2c66affSColin Finck ? internalDecimalPointLength
2900c2c66affSColin Finck : 0)
2901c2c66affSColin Finck + ((flags & FLAGS_QUOTE)
2902c2c66affSColin Finck ? TrioCalcThousandSeparatorLength(integerDigits)
2903c2c66affSColin Finck : 0);
2904c2c66affSColin Finck if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
2905c2c66affSColin Finck expectedWidth += sizeof("-") - 1;
2906c2c66affSColin Finck if (exponentDigits > 0)
2907c2c66affSColin Finck expectedWidth += exponentDigits +
2908c2c66affSColin Finck ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
2909c2c66affSColin Finck if (isHex)
2910c2c66affSColin Finck expectedWidth += sizeof("0X") - 1;
2911c2c66affSColin Finck
2912c2c66affSColin Finck /* Output prefixing */
2913c2c66affSColin Finck if (flags & FLAGS_NILPADDING)
2914c2c66affSColin Finck {
2915c2c66affSColin Finck /* Leading zeros must be after sign */
2916c2c66affSColin Finck if (isNegative)
2917c2c66affSColin Finck self->OutStream(self, '-');
2918c2c66affSColin Finck else if (flags & FLAGS_SHOWSIGN)
2919c2c66affSColin Finck self->OutStream(self, '+');
2920c2c66affSColin Finck else if (flags & FLAGS_SPACE)
2921c2c66affSColin Finck self->OutStream(self, ' ');
2922c2c66affSColin Finck if (isHex)
2923c2c66affSColin Finck {
2924c2c66affSColin Finck self->OutStream(self, '0');
2925c2c66affSColin Finck self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
2926c2c66affSColin Finck }
2927c2c66affSColin Finck if (!(flags & FLAGS_LEFTADJUST))
2928c2c66affSColin Finck {
2929c2c66affSColin Finck for (i = expectedWidth; i < width; i++)
2930c2c66affSColin Finck {
2931c2c66affSColin Finck self->OutStream(self, '0');
2932c2c66affSColin Finck }
2933c2c66affSColin Finck }
2934c2c66affSColin Finck }
2935c2c66affSColin Finck else
2936c2c66affSColin Finck {
2937c2c66affSColin Finck /* Leading spaces must be before sign */
2938c2c66affSColin Finck if (!(flags & FLAGS_LEFTADJUST))
2939c2c66affSColin Finck {
2940c2c66affSColin Finck for (i = expectedWidth; i < width; i++)
2941c2c66affSColin Finck {
2942c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
2943c2c66affSColin Finck }
2944c2c66affSColin Finck }
2945c2c66affSColin Finck if (isNegative)
2946c2c66affSColin Finck self->OutStream(self, '-');
2947c2c66affSColin Finck else if (flags & FLAGS_SHOWSIGN)
2948c2c66affSColin Finck self->OutStream(self, '+');
2949c2c66affSColin Finck else if (flags & FLAGS_SPACE)
2950c2c66affSColin Finck self->OutStream(self, ' ');
2951c2c66affSColin Finck if (isHex)
2952c2c66affSColin Finck {
2953c2c66affSColin Finck self->OutStream(self, '0');
2954c2c66affSColin Finck self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
2955c2c66affSColin Finck }
2956c2c66affSColin Finck }
2957c2c66affSColin Finck
2958c2c66affSColin Finck /* Output the integer part and thousand separators */
2959c2c66affSColin Finck dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1);
2960c2c66affSColin Finck for (i = 0; i < integerDigits; i++)
2961c2c66affSColin Finck {
2962c2c66affSColin Finck workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase));
2963c2c66affSColin Finck if (i > integerThreshold)
2964c2c66affSColin Finck {
2965c2c66affSColin Finck /* Beyond accuracy */
2966c2c66affSColin Finck self->OutStream(self, digits[0]);
2967c2c66affSColin Finck }
2968c2c66affSColin Finck else
2969c2c66affSColin Finck {
2970c2c66affSColin Finck self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
2971c2c66affSColin Finck }
2972c2c66affSColin Finck dblIntegerBase *= dblBase;
2973c2c66affSColin Finck
2974c2c66affSColin Finck if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
2975c2c66affSColin Finck && TrioFollowedBySeparator(integerDigits - i))
2976c2c66affSColin Finck {
2977c2c66affSColin Finck for (groupingPointer = internalThousandSeparator;
2978c2c66affSColin Finck *groupingPointer != NIL;
2979c2c66affSColin Finck groupingPointer++)
2980c2c66affSColin Finck {
2981c2c66affSColin Finck self->OutStream(self, *groupingPointer);
2982c2c66affSColin Finck }
2983c2c66affSColin Finck }
2984c2c66affSColin Finck }
2985c2c66affSColin Finck
2986c2c66affSColin Finck /* Insert decimal point and build the fraction part */
2987c2c66affSColin Finck trailingZeroes = 0;
2988c2c66affSColin Finck
2989c2c66affSColin Finck if (keepDecimalPoint)
2990c2c66affSColin Finck {
2991c2c66affSColin Finck if (internalDecimalPoint)
2992c2c66affSColin Finck {
2993c2c66affSColin Finck self->OutStream(self, internalDecimalPoint);
2994c2c66affSColin Finck }
2995c2c66affSColin Finck else
2996c2c66affSColin Finck {
2997c2c66affSColin Finck for (i = 0; i < internalDecimalPointLength; i++)
2998c2c66affSColin Finck {
2999c2c66affSColin Finck self->OutStream(self, internalDecimalPointString[i]);
3000c2c66affSColin Finck }
3001c2c66affSColin Finck }
3002c2c66affSColin Finck }
3003c2c66affSColin Finck
3004c2c66affSColin Finck for (i = 0; i < fractionDigits; i++)
3005c2c66affSColin Finck {
3006c2c66affSColin Finck if ((integerDigits > integerThreshold) || (i > fractionThreshold))
3007c2c66affSColin Finck {
3008c2c66affSColin Finck /* Beyond accuracy */
3009c2c66affSColin Finck trailingZeroes++;
3010c2c66affSColin Finck }
3011c2c66affSColin Finck else
3012c2c66affSColin Finck {
3013c2c66affSColin Finck fractionNumber *= dblBase;
3014c2c66affSColin Finck fractionAdjust *= dblBase;
3015c2c66affSColin Finck workNumber = floorl(fractionNumber + fractionAdjust);
3016c2c66affSColin Finck fractionNumber -= workNumber;
3017c2c66affSColin Finck index = (int)fmodl(workNumber, dblBase);
3018c2c66affSColin Finck if (index == 0)
3019c2c66affSColin Finck {
3020c2c66affSColin Finck trailingZeroes++;
3021c2c66affSColin Finck }
3022c2c66affSColin Finck else
3023c2c66affSColin Finck {
3024c2c66affSColin Finck while (trailingZeroes > 0)
3025c2c66affSColin Finck {
3026c2c66affSColin Finck /* Not trailing zeroes after all */
3027c2c66affSColin Finck self->OutStream(self, digits[0]);
3028c2c66affSColin Finck trailingZeroes--;
3029c2c66affSColin Finck }
3030c2c66affSColin Finck self->OutStream(self, digits[index]);
3031c2c66affSColin Finck }
3032c2c66affSColin Finck }
3033c2c66affSColin Finck }
3034c2c66affSColin Finck
3035c2c66affSColin Finck if (keepTrailingZeroes)
3036c2c66affSColin Finck {
3037c2c66affSColin Finck while (trailingZeroes > 0)
3038c2c66affSColin Finck {
3039c2c66affSColin Finck self->OutStream(self, digits[0]);
3040c2c66affSColin Finck trailingZeroes--;
3041c2c66affSColin Finck }
3042c2c66affSColin Finck }
3043c2c66affSColin Finck
3044c2c66affSColin Finck /* Output exponent */
3045c2c66affSColin Finck if (exponentDigits > 0)
3046c2c66affSColin Finck {
3047c2c66affSColin Finck self->OutStream(self,
3048c2c66affSColin Finck isHex
3049c2c66affSColin Finck ? ((flags & FLAGS_UPPER) ? 'P' : 'p')
3050c2c66affSColin Finck : ((flags & FLAGS_UPPER) ? 'E' : 'e'));
3051c2c66affSColin Finck self->OutStream(self, (isExponentNegative) ? '-' : '+');
3052c2c66affSColin Finck
3053c2c66affSColin Finck /* The exponent must contain at least two digits */
3054c2c66affSColin Finck if (requireTwoDigitExponent)
3055c2c66affSColin Finck self->OutStream(self, '0');
3056c2c66affSColin Finck
3057c2c66affSColin Finck if (isHex)
3058c2c66affSColin Finck base = 10.0;
3059c2c66affSColin Finck exponentBase = (int)TrioPower(base, exponentDigits - 1);
3060c2c66affSColin Finck for (i = 0; i < exponentDigits; i++)
3061c2c66affSColin Finck {
3062c2c66affSColin Finck self->OutStream(self, digits[(uExponent / exponentBase) % base]);
3063c2c66affSColin Finck exponentBase /= base;
3064c2c66affSColin Finck }
3065c2c66affSColin Finck }
3066c2c66affSColin Finck /* Output trailing spaces */
3067c2c66affSColin Finck if (flags & FLAGS_LEFTADJUST)
3068c2c66affSColin Finck {
3069c2c66affSColin Finck for (i = expectedWidth; i < width; i++)
3070c2c66affSColin Finck {
3071c2c66affSColin Finck self->OutStream(self, CHAR_ADJUST);
3072c2c66affSColin Finck }
3073c2c66affSColin Finck }
3074c2c66affSColin Finck }
3075c2c66affSColin Finck
3076c2c66affSColin Finck /*************************************************************************
3077c2c66affSColin Finck * TrioFormatProcess
3078c2c66affSColin Finck *
3079c2c66affSColin Finck * Description:
3080c2c66affSColin Finck * This is the main engine for formatting output
3081c2c66affSColin Finck */
3082c2c66affSColin Finck TRIO_PRIVATE int
3083c2c66affSColin Finck TrioFormatProcess
3084c2c66affSColin Finck TRIO_ARGS3((data, format, parameters),
3085c2c66affSColin Finck trio_class_t *data,
3086c2c66affSColin Finck TRIO_CONST char *format,
3087c2c66affSColin Finck trio_parameter_t *parameters)
3088c2c66affSColin Finck {
3089c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3090c2c66affSColin Finck int charlen;
3091c2c66affSColin Finck #endif
3092c2c66affSColin Finck int i;
3093c2c66affSColin Finck TRIO_CONST char *string;
3094c2c66affSColin Finck trio_pointer_t pointer;
3095c2c66affSColin Finck trio_flags_t flags;
3096c2c66affSColin Finck int width;
3097c2c66affSColin Finck int precision;
3098c2c66affSColin Finck int base;
3099c2c66affSColin Finck int index;
3100c2c66affSColin Finck
3101c2c66affSColin Finck index = 0;
3102c2c66affSColin Finck i = 0;
3103c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3104c2c66affSColin Finck (void)mblen(NULL, 0);
3105c2c66affSColin Finck #endif
3106c2c66affSColin Finck
3107c2c66affSColin Finck while (format[index])
3108c2c66affSColin Finck {
3109c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3110c2c66affSColin Finck if (! isascii(format[index]))
3111c2c66affSColin Finck {
3112c2c66affSColin Finck charlen = mblen(&format[index], MB_LEN_MAX);
3113c2c66affSColin Finck /*
3114c2c66affSColin Finck * Only valid multibyte characters are handled here. Invalid
3115c2c66affSColin Finck * multibyte characters (charlen == -1) are handled as normal
3116c2c66affSColin Finck * characters.
3117c2c66affSColin Finck */
3118c2c66affSColin Finck if (charlen != -1)
3119c2c66affSColin Finck {
3120c2c66affSColin Finck while (charlen-- > 0)
3121c2c66affSColin Finck {
3122c2c66affSColin Finck data->OutStream(data, format[index++]);
3123c2c66affSColin Finck }
3124c2c66affSColin Finck continue; /* while characters left in formatting string */
3125c2c66affSColin Finck }
3126c2c66affSColin Finck }
3127c2c66affSColin Finck #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
3128c2c66affSColin Finck if (CHAR_IDENTIFIER == format[index])
3129c2c66affSColin Finck {
3130c2c66affSColin Finck if (CHAR_IDENTIFIER == format[index + 1])
3131c2c66affSColin Finck {
3132c2c66affSColin Finck data->OutStream(data, CHAR_IDENTIFIER);
3133c2c66affSColin Finck index += 2;
3134c2c66affSColin Finck }
3135c2c66affSColin Finck else
3136c2c66affSColin Finck {
3137c2c66affSColin Finck /* Skip the parameter entries */
3138c2c66affSColin Finck while (parameters[i].type == FORMAT_PARAMETER)
3139c2c66affSColin Finck i++;
3140c2c66affSColin Finck
3141c2c66affSColin Finck flags = parameters[i].flags;
3142c2c66affSColin Finck
3143c2c66affSColin Finck /* Find width */
3144c2c66affSColin Finck width = parameters[i].width;
3145c2c66affSColin Finck if (flags & FLAGS_WIDTH_PARAMETER)
3146c2c66affSColin Finck {
3147c2c66affSColin Finck /* Get width from parameter list */
3148c2c66affSColin Finck width = (int)parameters[width].data.number.as_signed;
3149c2c66affSColin Finck if (width < 0)
3150c2c66affSColin Finck {
3151c2c66affSColin Finck /*
3152c2c66affSColin Finck * A negative width is the same as the - flag and
3153c2c66affSColin Finck * a positive width.
3154c2c66affSColin Finck */
3155c2c66affSColin Finck flags |= FLAGS_LEFTADJUST;
3156c2c66affSColin Finck flags &= ~FLAGS_NILPADDING;
3157c2c66affSColin Finck width = -width;
3158c2c66affSColin Finck }
3159c2c66affSColin Finck }
3160c2c66affSColin Finck
3161c2c66affSColin Finck /* Find precision */
3162c2c66affSColin Finck if (flags & FLAGS_PRECISION)
3163c2c66affSColin Finck {
3164c2c66affSColin Finck precision = parameters[i].precision;
3165c2c66affSColin Finck if (flags & FLAGS_PRECISION_PARAMETER)
3166c2c66affSColin Finck {
3167c2c66affSColin Finck /* Get precision from parameter list */
3168c2c66affSColin Finck precision = (int)parameters[precision].data.number.as_signed;
3169c2c66affSColin Finck if (precision < 0)
3170c2c66affSColin Finck {
3171c2c66affSColin Finck /*
3172c2c66affSColin Finck * A negative precision is the same as no
3173c2c66affSColin Finck * precision
3174c2c66affSColin Finck */
3175c2c66affSColin Finck precision = NO_PRECISION;
3176c2c66affSColin Finck }
3177c2c66affSColin Finck }
3178c2c66affSColin Finck }
3179c2c66affSColin Finck else
3180c2c66affSColin Finck {
3181c2c66affSColin Finck precision = NO_PRECISION;
3182c2c66affSColin Finck }
3183c2c66affSColin Finck
3184c2c66affSColin Finck /* Find base */
3185c2c66affSColin Finck base = parameters[i].base;
3186c2c66affSColin Finck if (flags & FLAGS_BASE_PARAMETER)
3187c2c66affSColin Finck {
3188c2c66affSColin Finck /* Get base from parameter list */
3189c2c66affSColin Finck base = (int)parameters[base].data.number.as_signed;
3190c2c66affSColin Finck }
3191c2c66affSColin Finck
3192c2c66affSColin Finck switch (parameters[i].type)
3193c2c66affSColin Finck {
3194c2c66affSColin Finck case FORMAT_CHAR:
3195c2c66affSColin Finck if (flags & FLAGS_QUOTE)
3196c2c66affSColin Finck data->OutStream(data, CHAR_QUOTE);
3197c2c66affSColin Finck if (! (flags & FLAGS_LEFTADJUST))
3198c2c66affSColin Finck {
3199c2c66affSColin Finck while (--width > 0)
3200c2c66affSColin Finck data->OutStream(data, CHAR_ADJUST);
3201c2c66affSColin Finck }
3202c2c66affSColin Finck #if TRIO_WIDECHAR
3203c2c66affSColin Finck if (flags & FLAGS_WIDECHAR)
3204c2c66affSColin Finck {
3205c2c66affSColin Finck TrioWriteWideStringCharacter(data,
3206c2c66affSColin Finck (trio_wchar_t)parameters[i].data.number.as_signed,
3207c2c66affSColin Finck flags,
3208c2c66affSColin Finck NO_WIDTH);
3209c2c66affSColin Finck }
3210c2c66affSColin Finck else
3211c2c66affSColin Finck #endif
3212c2c66affSColin Finck {
3213c2c66affSColin Finck TrioWriteStringCharacter(data,
3214c2c66affSColin Finck (int)parameters[i].data.number.as_signed,
3215c2c66affSColin Finck flags);
3216c2c66affSColin Finck }
3217c2c66affSColin Finck
3218c2c66affSColin Finck if (flags & FLAGS_LEFTADJUST)
3219c2c66affSColin Finck {
3220c2c66affSColin Finck while(--width > 0)
3221c2c66affSColin Finck data->OutStream(data, CHAR_ADJUST);
3222c2c66affSColin Finck }
3223c2c66affSColin Finck if (flags & FLAGS_QUOTE)
3224c2c66affSColin Finck data->OutStream(data, CHAR_QUOTE);
3225c2c66affSColin Finck
3226c2c66affSColin Finck break; /* FORMAT_CHAR */
3227c2c66affSColin Finck
3228c2c66affSColin Finck case FORMAT_INT:
3229c2c66affSColin Finck TrioWriteNumber(data,
3230c2c66affSColin Finck parameters[i].data.number.as_unsigned,
3231c2c66affSColin Finck flags,
3232c2c66affSColin Finck width,
3233c2c66affSColin Finck precision,
3234c2c66affSColin Finck base);
3235c2c66affSColin Finck
3236c2c66affSColin Finck break; /* FORMAT_INT */
3237c2c66affSColin Finck
3238c2c66affSColin Finck case FORMAT_DOUBLE:
3239c2c66affSColin Finck TrioWriteDouble(data,
3240c2c66affSColin Finck parameters[i].data.longdoubleNumber,
3241c2c66affSColin Finck flags,
3242c2c66affSColin Finck width,
3243c2c66affSColin Finck precision,
3244c2c66affSColin Finck base);
3245c2c66affSColin Finck break; /* FORMAT_DOUBLE */
3246c2c66affSColin Finck
3247c2c66affSColin Finck case FORMAT_STRING:
3248c2c66affSColin Finck #if TRIO_WIDECHAR
3249c2c66affSColin Finck if (flags & FLAGS_WIDECHAR)
3250c2c66affSColin Finck {
3251c2c66affSColin Finck TrioWriteWideString(data,
3252c2c66affSColin Finck parameters[i].data.wstring,
3253c2c66affSColin Finck flags,
3254c2c66affSColin Finck width,
3255c2c66affSColin Finck precision);
3256c2c66affSColin Finck }
3257c2c66affSColin Finck else
3258c2c66affSColin Finck #endif
3259c2c66affSColin Finck {
3260c2c66affSColin Finck TrioWriteString(data,
3261c2c66affSColin Finck parameters[i].data.string,
3262c2c66affSColin Finck flags,
3263c2c66affSColin Finck width,
3264c2c66affSColin Finck precision);
3265c2c66affSColin Finck }
3266c2c66affSColin Finck break; /* FORMAT_STRING */
3267c2c66affSColin Finck
3268c2c66affSColin Finck case FORMAT_POINTER:
3269c2c66affSColin Finck {
3270c2c66affSColin Finck trio_reference_t reference;
3271c2c66affSColin Finck
3272c2c66affSColin Finck reference.data = data;
3273c2c66affSColin Finck reference.parameter = ¶meters[i];
3274c2c66affSColin Finck trio_print_pointer(&reference, parameters[i].data.pointer);
3275c2c66affSColin Finck }
3276c2c66affSColin Finck break; /* FORMAT_POINTER */
3277c2c66affSColin Finck
3278c2c66affSColin Finck case FORMAT_COUNT:
3279c2c66affSColin Finck pointer = parameters[i].data.pointer;
3280c2c66affSColin Finck if (NULL != pointer)
3281c2c66affSColin Finck {
3282c2c66affSColin Finck /*
3283c2c66affSColin Finck * C99 paragraph 7.19.6.1.8 says "the number of
3284c2c66affSColin Finck * characters written to the output stream so far by
3285c2c66affSColin Finck * this call", which is data->committed
3286c2c66affSColin Finck */
3287c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
3288c2c66affSColin Finck if (flags & FLAGS_SIZE_T)
3289c2c66affSColin Finck *(size_t *)pointer = (size_t)data->committed;
3290c2c66affSColin Finck else
3291c2c66affSColin Finck #endif
3292c2c66affSColin Finck #if defined(QUALIFIER_PTRDIFF_T)
3293c2c66affSColin Finck if (flags & FLAGS_PTRDIFF_T)
3294c2c66affSColin Finck *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
3295c2c66affSColin Finck else
3296c2c66affSColin Finck #endif
3297c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
3298c2c66affSColin Finck if (flags & FLAGS_INTMAX_T)
3299c2c66affSColin Finck *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
3300c2c66affSColin Finck else
3301c2c66affSColin Finck #endif
3302c2c66affSColin Finck if (flags & FLAGS_QUAD)
3303c2c66affSColin Finck {
3304c2c66affSColin Finck *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
3305c2c66affSColin Finck }
3306c2c66affSColin Finck else if (flags & FLAGS_LONG)
3307c2c66affSColin Finck {
3308c2c66affSColin Finck *(long int *)pointer = (long int)data->committed;
3309c2c66affSColin Finck }
3310c2c66affSColin Finck else if (flags & FLAGS_SHORT)
3311c2c66affSColin Finck {
3312c2c66affSColin Finck *(short int *)pointer = (short int)data->committed;
3313c2c66affSColin Finck }
3314c2c66affSColin Finck else
3315c2c66affSColin Finck {
3316c2c66affSColin Finck *(int *)pointer = (int)data->committed;
3317c2c66affSColin Finck }
3318c2c66affSColin Finck }
3319c2c66affSColin Finck break; /* FORMAT_COUNT */
3320c2c66affSColin Finck
3321c2c66affSColin Finck case FORMAT_PARAMETER:
3322c2c66affSColin Finck break; /* FORMAT_PARAMETER */
3323c2c66affSColin Finck
3324c2c66affSColin Finck #if defined(FORMAT_ERRNO)
3325c2c66affSColin Finck case FORMAT_ERRNO:
3326c2c66affSColin Finck string = trio_error(parameters[i].data.errorNumber);
3327c2c66affSColin Finck if (string)
3328c2c66affSColin Finck {
3329c2c66affSColin Finck TrioWriteString(data,
3330c2c66affSColin Finck string,
3331c2c66affSColin Finck flags,
3332c2c66affSColin Finck width,
3333c2c66affSColin Finck precision);
3334c2c66affSColin Finck }
3335c2c66affSColin Finck else
3336c2c66affSColin Finck {
3337c2c66affSColin Finck data->OutStream(data, '#');
3338c2c66affSColin Finck TrioWriteNumber(data,
3339c2c66affSColin Finck (trio_uintmax_t)parameters[i].data.errorNumber,
3340c2c66affSColin Finck flags,
3341c2c66affSColin Finck width,
3342c2c66affSColin Finck precision,
3343c2c66affSColin Finck BASE_DECIMAL);
3344c2c66affSColin Finck }
3345c2c66affSColin Finck break; /* FORMAT_ERRNO */
3346c2c66affSColin Finck #endif /* defined(FORMAT_ERRNO) */
3347c2c66affSColin Finck
3348c2c66affSColin Finck #if defined(FORMAT_USER_DEFINED)
3349c2c66affSColin Finck case FORMAT_USER_DEFINED:
3350c2c66affSColin Finck {
3351c2c66affSColin Finck trio_reference_t reference;
3352c2c66affSColin Finck trio_userdef_t *def = NULL;
3353c2c66affSColin Finck
3354c2c66affSColin Finck if (parameters[i].user_name[0] == NIL)
3355c2c66affSColin Finck {
3356c2c66affSColin Finck /* Use handle */
3357c2c66affSColin Finck if ((i > 0) ||
3358c2c66affSColin Finck (parameters[i - 1].type == FORMAT_PARAMETER))
3359c2c66affSColin Finck def = (trio_userdef_t *)parameters[i - 1].data.pointer;
3360c2c66affSColin Finck }
3361c2c66affSColin Finck else
3362c2c66affSColin Finck {
3363c2c66affSColin Finck /* Look up namespace */
3364c2c66affSColin Finck def = TrioFindNamespace(parameters[i].user_name, NULL);
3365c2c66affSColin Finck }
3366c2c66affSColin Finck if (def) {
3367c2c66affSColin Finck reference.data = data;
3368c2c66affSColin Finck reference.parameter = ¶meters[i];
3369c2c66affSColin Finck def->callback(&reference);
3370c2c66affSColin Finck }
3371c2c66affSColin Finck }
3372c2c66affSColin Finck break;
3373c2c66affSColin Finck #endif /* defined(FORMAT_USER_DEFINED) */
3374c2c66affSColin Finck
3375c2c66affSColin Finck default:
3376c2c66affSColin Finck break;
3377c2c66affSColin Finck } /* switch parameter type */
3378c2c66affSColin Finck
3379c2c66affSColin Finck /* Prepare for next */
3380c2c66affSColin Finck index = parameters[i].indexAfterSpecifier;
3381c2c66affSColin Finck i++;
3382c2c66affSColin Finck }
3383c2c66affSColin Finck }
3384c2c66affSColin Finck else /* not identifier */
3385c2c66affSColin Finck {
3386c2c66affSColin Finck data->OutStream(data, format[index++]);
3387c2c66affSColin Finck }
3388c2c66affSColin Finck }
3389c2c66affSColin Finck return data->processed;
3390c2c66affSColin Finck }
3391c2c66affSColin Finck
3392c2c66affSColin Finck /*************************************************************************
3393c2c66affSColin Finck * TrioFormatRef
3394c2c66affSColin Finck */
3395c2c66affSColin Finck TRIO_PRIVATE int
3396c2c66affSColin Finck TrioFormatRef
3397c2c66affSColin Finck TRIO_ARGS4((reference, format, arglist, argarray),
3398c2c66affSColin Finck trio_reference_t *reference,
3399c2c66affSColin Finck TRIO_CONST char *format,
3400c2c66affSColin Finck TRIO_VA_LIST_PTR arglist,
3401c2c66affSColin Finck trio_pointer_t *argarray)
3402c2c66affSColin Finck {
3403c2c66affSColin Finck int status;
3404c2c66affSColin Finck trio_parameter_t parameters[MAX_PARAMETERS];
3405c2c66affSColin Finck
3406c2c66affSColin Finck status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
3407c2c66affSColin Finck if (status < 0)
3408c2c66affSColin Finck return status;
3409c2c66affSColin Finck
3410c2c66affSColin Finck status = TrioFormatProcess(reference->data, format, parameters);
3411c2c66affSColin Finck if (reference->data->error != 0)
3412c2c66affSColin Finck {
3413c2c66affSColin Finck status = reference->data->error;
3414c2c66affSColin Finck }
3415c2c66affSColin Finck return status;
3416c2c66affSColin Finck }
3417c2c66affSColin Finck
3418c2c66affSColin Finck /*************************************************************************
3419c2c66affSColin Finck * TrioFormat
3420c2c66affSColin Finck */
3421c2c66affSColin Finck TRIO_PRIVATE int
3422c2c66affSColin Finck TrioFormat
3423c2c66affSColin Finck TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
3424c2c66affSColin Finck trio_pointer_t destination,
3425c2c66affSColin Finck size_t destinationSize,
3426c2c66affSColin Finck void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
3427c2c66affSColin Finck TRIO_CONST char *format,
3428c2c66affSColin Finck TRIO_VA_LIST_PTR arglist,
3429c2c66affSColin Finck trio_pointer_t *argarray)
3430c2c66affSColin Finck {
3431c2c66affSColin Finck int status;
3432c2c66affSColin Finck trio_class_t data;
3433c2c66affSColin Finck trio_parameter_t parameters[MAX_PARAMETERS];
3434c2c66affSColin Finck
3435c2c66affSColin Finck assert(VALID(OutStream));
3436c2c66affSColin Finck assert(VALID(format));
3437c2c66affSColin Finck
3438c2c66affSColin Finck memset(&data, 0, sizeof(data));
3439c2c66affSColin Finck data.OutStream = OutStream;
3440c2c66affSColin Finck data.location = destination;
3441c2c66affSColin Finck data.max = destinationSize;
3442c2c66affSColin Finck data.error = 0;
3443c2c66affSColin Finck
3444c2c66affSColin Finck #if defined(USE_LOCALE)
3445c2c66affSColin Finck if (NULL == internalLocaleValues)
3446c2c66affSColin Finck {
3447c2c66affSColin Finck TrioSetLocale();
3448c2c66affSColin Finck }
3449c2c66affSColin Finck #endif
3450c2c66affSColin Finck
3451c2c66affSColin Finck status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
3452c2c66affSColin Finck if (status < 0)
3453c2c66affSColin Finck return status;
3454c2c66affSColin Finck
3455c2c66affSColin Finck status = TrioFormatProcess(&data, format, parameters);
3456c2c66affSColin Finck if (data.error != 0)
3457c2c66affSColin Finck {
3458c2c66affSColin Finck status = data.error;
3459c2c66affSColin Finck }
3460c2c66affSColin Finck return status;
3461c2c66affSColin Finck }
3462c2c66affSColin Finck
3463c2c66affSColin Finck /*************************************************************************
3464c2c66affSColin Finck * TrioOutStreamFile
3465c2c66affSColin Finck */
3466c2c66affSColin Finck TRIO_PRIVATE void
3467c2c66affSColin Finck TrioOutStreamFile
3468c2c66affSColin Finck TRIO_ARGS2((self, output),
3469c2c66affSColin Finck trio_class_t *self,
3470c2c66affSColin Finck int output)
3471c2c66affSColin Finck {
3472c2c66affSColin Finck FILE *file;
3473c2c66affSColin Finck
3474c2c66affSColin Finck assert(VALID(self));
3475c2c66affSColin Finck assert(VALID(self->location));
3476c2c66affSColin Finck
3477c2c66affSColin Finck file = (FILE *)self->location;
3478c2c66affSColin Finck self->processed++;
3479c2c66affSColin Finck if (fputc(output, file) == EOF)
3480c2c66affSColin Finck {
3481c2c66affSColin Finck self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0);
3482c2c66affSColin Finck }
3483c2c66affSColin Finck else
3484c2c66affSColin Finck {
3485c2c66affSColin Finck self->committed++;
3486c2c66affSColin Finck }
3487c2c66affSColin Finck }
3488c2c66affSColin Finck
3489c2c66affSColin Finck /*************************************************************************
3490c2c66affSColin Finck * TrioOutStreamFileDescriptor
3491c2c66affSColin Finck */
3492c2c66affSColin Finck TRIO_PRIVATE void
3493c2c66affSColin Finck TrioOutStreamFileDescriptor
3494c2c66affSColin Finck TRIO_ARGS2((self, output),
3495c2c66affSColin Finck trio_class_t *self,
3496c2c66affSColin Finck int output)
3497c2c66affSColin Finck {
3498c2c66affSColin Finck int fd;
3499c2c66affSColin Finck char ch;
3500c2c66affSColin Finck
3501c2c66affSColin Finck assert(VALID(self));
3502c2c66affSColin Finck
3503c2c66affSColin Finck fd = *((int *)self->location);
3504c2c66affSColin Finck ch = (char)output;
3505c2c66affSColin Finck self->processed++;
3506c2c66affSColin Finck if (write(fd, &ch, sizeof(char)) == -1)
3507c2c66affSColin Finck {
3508c2c66affSColin Finck self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
3509c2c66affSColin Finck }
3510c2c66affSColin Finck else
3511c2c66affSColin Finck {
3512c2c66affSColin Finck self->committed++;
3513c2c66affSColin Finck }
3514c2c66affSColin Finck }
3515c2c66affSColin Finck
3516c2c66affSColin Finck /*************************************************************************
3517c2c66affSColin Finck * TrioOutStreamCustom
3518c2c66affSColin Finck */
3519c2c66affSColin Finck TRIO_PRIVATE void
3520c2c66affSColin Finck TrioOutStreamCustom
3521c2c66affSColin Finck TRIO_ARGS2((self, output),
3522c2c66affSColin Finck trio_class_t *self,
3523c2c66affSColin Finck int output)
3524c2c66affSColin Finck {
3525c2c66affSColin Finck int status;
3526c2c66affSColin Finck trio_custom_t *data;
3527c2c66affSColin Finck
3528c2c66affSColin Finck assert(VALID(self));
3529c2c66affSColin Finck assert(VALID(self->location));
3530c2c66affSColin Finck
3531c2c66affSColin Finck data = (trio_custom_t *)self->location;
3532c2c66affSColin Finck if (data->stream.out)
3533c2c66affSColin Finck {
3534c2c66affSColin Finck status = (data->stream.out)(data->closure, output);
3535c2c66affSColin Finck if (status >= 0)
3536c2c66affSColin Finck {
3537c2c66affSColin Finck self->committed++;
3538c2c66affSColin Finck }
3539c2c66affSColin Finck else
3540c2c66affSColin Finck {
3541c2c66affSColin Finck if (self->error == 0)
3542c2c66affSColin Finck {
3543c2c66affSColin Finck self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status);
3544c2c66affSColin Finck }
3545c2c66affSColin Finck }
3546c2c66affSColin Finck }
3547c2c66affSColin Finck self->processed++;
3548c2c66affSColin Finck }
3549c2c66affSColin Finck
3550c2c66affSColin Finck /*************************************************************************
3551c2c66affSColin Finck * TrioOutStreamString
3552c2c66affSColin Finck */
3553c2c66affSColin Finck TRIO_PRIVATE void
3554c2c66affSColin Finck TrioOutStreamString
3555c2c66affSColin Finck TRIO_ARGS2((self, output),
3556c2c66affSColin Finck trio_class_t *self,
3557c2c66affSColin Finck int output)
3558c2c66affSColin Finck {
3559c2c66affSColin Finck char **buffer;
3560c2c66affSColin Finck
3561c2c66affSColin Finck assert(VALID(self));
3562c2c66affSColin Finck assert(VALID(self->location));
3563c2c66affSColin Finck
3564c2c66affSColin Finck buffer = (char **)self->location;
3565c2c66affSColin Finck **buffer = (char)output;
3566c2c66affSColin Finck (*buffer)++;
3567c2c66affSColin Finck self->processed++;
3568c2c66affSColin Finck self->committed++;
3569c2c66affSColin Finck }
3570c2c66affSColin Finck
3571c2c66affSColin Finck /*************************************************************************
3572c2c66affSColin Finck * TrioOutStreamStringMax
3573c2c66affSColin Finck */
3574c2c66affSColin Finck TRIO_PRIVATE void
3575c2c66affSColin Finck TrioOutStreamStringMax
3576c2c66affSColin Finck TRIO_ARGS2((self, output),
3577c2c66affSColin Finck trio_class_t *self,
3578c2c66affSColin Finck int output)
3579c2c66affSColin Finck {
3580c2c66affSColin Finck char **buffer;
3581c2c66affSColin Finck
3582c2c66affSColin Finck assert(VALID(self));
3583c2c66affSColin Finck assert(VALID(self->location));
3584c2c66affSColin Finck
3585c2c66affSColin Finck buffer = (char **)self->location;
3586c2c66affSColin Finck
3587c2c66affSColin Finck if (self->processed < self->max)
3588c2c66affSColin Finck {
3589c2c66affSColin Finck **buffer = (char)output;
3590c2c66affSColin Finck (*buffer)++;
3591c2c66affSColin Finck self->committed++;
3592c2c66affSColin Finck }
3593c2c66affSColin Finck self->processed++;
3594c2c66affSColin Finck }
3595c2c66affSColin Finck
3596c2c66affSColin Finck /*************************************************************************
3597c2c66affSColin Finck * TrioOutStreamStringDynamic
3598c2c66affSColin Finck */
3599c2c66affSColin Finck TRIO_PRIVATE void
3600c2c66affSColin Finck TrioOutStreamStringDynamic
3601c2c66affSColin Finck TRIO_ARGS2((self, output),
3602c2c66affSColin Finck trio_class_t *self,
3603c2c66affSColin Finck int output)
3604c2c66affSColin Finck {
3605c2c66affSColin Finck assert(VALID(self));
3606c2c66affSColin Finck assert(VALID(self->location));
3607c2c66affSColin Finck
3608c2c66affSColin Finck if (self->error == 0)
3609c2c66affSColin Finck {
3610c2c66affSColin Finck trio_xstring_append_char((trio_string_t *)self->location,
3611c2c66affSColin Finck (char)output);
3612c2c66affSColin Finck self->committed++;
3613c2c66affSColin Finck }
3614c2c66affSColin Finck /* The processed variable must always be increased */
3615c2c66affSColin Finck self->processed++;
3616c2c66affSColin Finck }
3617c2c66affSColin Finck
3618c2c66affSColin Finck /*************************************************************************
3619c2c66affSColin Finck *
3620c2c66affSColin Finck * Formatted printing functions
3621c2c66affSColin Finck *
3622c2c66affSColin Finck ************************************************************************/
3623c2c66affSColin Finck
3624c2c66affSColin Finck #if defined(TRIO_DOCUMENTATION)
3625c2c66affSColin Finck # include "doc/doc_printf.h"
3626c2c66affSColin Finck #endif
3627c2c66affSColin Finck /** @addtogroup Printf
3628c2c66affSColin Finck @{
3629c2c66affSColin Finck */
3630c2c66affSColin Finck
3631c2c66affSColin Finck /*************************************************************************
3632c2c66affSColin Finck * printf
3633c2c66affSColin Finck */
3634c2c66affSColin Finck
3635c2c66affSColin Finck /**
3636c2c66affSColin Finck Print to standard output stream.
3637c2c66affSColin Finck
3638c2c66affSColin Finck @param format Formatting string.
3639c2c66affSColin Finck @param ... Arguments.
3640c2c66affSColin Finck @return Number of printed characters.
3641c2c66affSColin Finck */
3642c2c66affSColin Finck TRIO_PUBLIC int
3643c2c66affSColin Finck trio_printf
3644c2c66affSColin Finck TRIO_VARGS2((format, va_alist),
3645c2c66affSColin Finck TRIO_CONST char *format,
3646c2c66affSColin Finck TRIO_VA_DECL)
3647c2c66affSColin Finck {
3648c2c66affSColin Finck int status;
3649c2c66affSColin Finck va_list args;
3650c2c66affSColin Finck
3651c2c66affSColin Finck assert(VALID(format));
3652c2c66affSColin Finck
3653c2c66affSColin Finck TRIO_VA_START(args, format);
3654c2c66affSColin Finck status = TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3655c2c66affSColin Finck TRIO_VA_END(args);
3656c2c66affSColin Finck return status;
3657c2c66affSColin Finck }
3658c2c66affSColin Finck
3659c2c66affSColin Finck /**
3660c2c66affSColin Finck Print to standard output stream.
3661c2c66affSColin Finck
3662c2c66affSColin Finck @param format Formatting string.
3663c2c66affSColin Finck @param args Arguments.
3664c2c66affSColin Finck @return Number of printed characters.
3665c2c66affSColin Finck */
3666c2c66affSColin Finck TRIO_PUBLIC int
3667c2c66affSColin Finck trio_vprintf
3668c2c66affSColin Finck TRIO_ARGS2((format, args),
3669c2c66affSColin Finck TRIO_CONST char *format,
3670c2c66affSColin Finck va_list args)
3671c2c66affSColin Finck {
3672c2c66affSColin Finck assert(VALID(format));
3673c2c66affSColin Finck
3674c2c66affSColin Finck return TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3675c2c66affSColin Finck }
3676c2c66affSColin Finck
3677c2c66affSColin Finck /**
3678c2c66affSColin Finck Print to standard output stream.
3679c2c66affSColin Finck
3680c2c66affSColin Finck @param format Formatting string.
3681c2c66affSColin Finck @param args Arguments.
3682c2c66affSColin Finck @return Number of printed characters.
3683c2c66affSColin Finck */
3684c2c66affSColin Finck TRIO_PUBLIC int
3685c2c66affSColin Finck trio_printfv
3686c2c66affSColin Finck TRIO_ARGS2((format, args),
3687c2c66affSColin Finck TRIO_CONST char *format,
3688c2c66affSColin Finck trio_pointer_t * args)
3689c2c66affSColin Finck {
3690c2c66affSColin Finck assert(VALID(format));
3691c2c66affSColin Finck
3692c2c66affSColin Finck return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
3693c2c66affSColin Finck }
3694c2c66affSColin Finck
3695c2c66affSColin Finck /*************************************************************************
3696c2c66affSColin Finck * fprintf
3697c2c66affSColin Finck */
3698c2c66affSColin Finck
3699c2c66affSColin Finck /**
3700c2c66affSColin Finck Print to file.
3701c2c66affSColin Finck
3702c2c66affSColin Finck @param file File pointer.
3703c2c66affSColin Finck @param format Formatting string.
3704c2c66affSColin Finck @param ... Arguments.
3705c2c66affSColin Finck @return Number of printed characters.
3706c2c66affSColin Finck */
3707c2c66affSColin Finck TRIO_PUBLIC int
3708c2c66affSColin Finck trio_fprintf
3709c2c66affSColin Finck TRIO_VARGS3((file, format, va_alist),
3710c2c66affSColin Finck FILE *file,
3711c2c66affSColin Finck TRIO_CONST char *format,
3712c2c66affSColin Finck TRIO_VA_DECL)
3713c2c66affSColin Finck {
3714c2c66affSColin Finck int status;
3715c2c66affSColin Finck va_list args;
3716c2c66affSColin Finck
3717c2c66affSColin Finck assert(VALID(file));
3718c2c66affSColin Finck assert(VALID(format));
3719c2c66affSColin Finck
3720c2c66affSColin Finck TRIO_VA_START(args, format);
3721c2c66affSColin Finck status = TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3722c2c66affSColin Finck TRIO_VA_END(args);
3723c2c66affSColin Finck return status;
3724c2c66affSColin Finck }
3725c2c66affSColin Finck
3726c2c66affSColin Finck /**
3727c2c66affSColin Finck Print to file.
3728c2c66affSColin Finck
3729c2c66affSColin Finck @param file File pointer.
3730c2c66affSColin Finck @param format Formatting string.
3731c2c66affSColin Finck @param args Arguments.
3732c2c66affSColin Finck @return Number of printed characters.
3733c2c66affSColin Finck */
3734c2c66affSColin Finck TRIO_PUBLIC int
3735c2c66affSColin Finck trio_vfprintf
3736c2c66affSColin Finck TRIO_ARGS3((file, format, args),
3737c2c66affSColin Finck FILE *file,
3738c2c66affSColin Finck TRIO_CONST char *format,
3739c2c66affSColin Finck va_list args)
3740c2c66affSColin Finck {
3741c2c66affSColin Finck assert(VALID(file));
3742c2c66affSColin Finck assert(VALID(format));
3743c2c66affSColin Finck
3744c2c66affSColin Finck return TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL);
3745c2c66affSColin Finck }
3746c2c66affSColin Finck
3747c2c66affSColin Finck /**
3748c2c66affSColin Finck Print to file.
3749c2c66affSColin Finck
3750c2c66affSColin Finck @param file File pointer.
3751c2c66affSColin Finck @param format Formatting string.
3752c2c66affSColin Finck @param args Arguments.
3753c2c66affSColin Finck @return Number of printed characters.
3754c2c66affSColin Finck */
3755c2c66affSColin Finck TRIO_PUBLIC int
3756c2c66affSColin Finck trio_fprintfv
3757c2c66affSColin Finck TRIO_ARGS3((file, format, args),
3758c2c66affSColin Finck FILE *file,
3759c2c66affSColin Finck TRIO_CONST char *format,
3760c2c66affSColin Finck trio_pointer_t * args)
3761c2c66affSColin Finck {
3762c2c66affSColin Finck assert(VALID(file));
3763c2c66affSColin Finck assert(VALID(format));
3764c2c66affSColin Finck
3765c2c66affSColin Finck return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
3766c2c66affSColin Finck }
3767c2c66affSColin Finck
3768c2c66affSColin Finck /*************************************************************************
3769c2c66affSColin Finck * dprintf
3770c2c66affSColin Finck */
3771c2c66affSColin Finck
3772c2c66affSColin Finck /**
3773c2c66affSColin Finck Print to file descriptor.
3774c2c66affSColin Finck
3775c2c66affSColin Finck @param fd File descriptor.
3776c2c66affSColin Finck @param format Formatting string.
3777c2c66affSColin Finck @param ... Arguments.
3778c2c66affSColin Finck @return Number of printed characters.
3779c2c66affSColin Finck */
3780c2c66affSColin Finck TRIO_PUBLIC int
3781c2c66affSColin Finck trio_dprintf
3782c2c66affSColin Finck TRIO_VARGS3((fd, format, va_alist),
3783c2c66affSColin Finck int fd,
3784c2c66affSColin Finck TRIO_CONST char *format,
3785c2c66affSColin Finck TRIO_VA_DECL)
3786c2c66affSColin Finck {
3787c2c66affSColin Finck int status;
3788c2c66affSColin Finck va_list args;
3789c2c66affSColin Finck
3790c2c66affSColin Finck assert(VALID(format));
3791c2c66affSColin Finck
3792c2c66affSColin Finck TRIO_VA_START(args, format);
3793c2c66affSColin Finck status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL);
3794c2c66affSColin Finck TRIO_VA_END(args);
3795c2c66affSColin Finck return status;
3796c2c66affSColin Finck }
3797c2c66affSColin Finck
3798c2c66affSColin Finck /**
3799c2c66affSColin Finck Print to file descriptor.
3800c2c66affSColin Finck
3801c2c66affSColin Finck @param fd File descriptor.
3802c2c66affSColin Finck @param format Formatting string.
3803c2c66affSColin Finck @param args Arguments.
3804c2c66affSColin Finck @return Number of printed characters.
3805c2c66affSColin Finck */
3806c2c66affSColin Finck TRIO_PUBLIC int
3807c2c66affSColin Finck trio_vdprintf
3808c2c66affSColin Finck TRIO_ARGS3((fd, format, args),
3809c2c66affSColin Finck int fd,
3810c2c66affSColin Finck TRIO_CONST char *format,
3811c2c66affSColin Finck va_list args)
3812c2c66affSColin Finck {
3813c2c66affSColin Finck assert(VALID(format));
3814c2c66affSColin Finck
3815c2c66affSColin Finck return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL);
3816c2c66affSColin Finck }
3817c2c66affSColin Finck
3818c2c66affSColin Finck /**
3819c2c66affSColin Finck Print to file descriptor.
3820c2c66affSColin Finck
3821c2c66affSColin Finck @param fd File descriptor.
3822c2c66affSColin Finck @param format Formatting string.
3823c2c66affSColin Finck @param args Arguments.
3824c2c66affSColin Finck @return Number of printed characters.
3825c2c66affSColin Finck */
3826c2c66affSColin Finck TRIO_PUBLIC int
3827c2c66affSColin Finck trio_dprintfv
3828c2c66affSColin Finck TRIO_ARGS3((fd, format, args),
3829c2c66affSColin Finck int fd,
3830c2c66affSColin Finck TRIO_CONST char *format,
3831c2c66affSColin Finck trio_pointer_t *args)
3832c2c66affSColin Finck {
3833c2c66affSColin Finck assert(VALID(format));
3834c2c66affSColin Finck
3835c2c66affSColin Finck return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
3836c2c66affSColin Finck }
3837c2c66affSColin Finck
3838c2c66affSColin Finck /*************************************************************************
3839c2c66affSColin Finck * cprintf
3840c2c66affSColin Finck */
3841c2c66affSColin Finck TRIO_PUBLIC int
3842c2c66affSColin Finck trio_cprintf
3843c2c66affSColin Finck TRIO_VARGS4((stream, closure, format, va_alist),
3844c2c66affSColin Finck trio_outstream_t stream,
3845c2c66affSColin Finck trio_pointer_t closure,
3846c2c66affSColin Finck TRIO_CONST char *format,
3847c2c66affSColin Finck TRIO_VA_DECL)
3848c2c66affSColin Finck {
3849c2c66affSColin Finck int status;
3850c2c66affSColin Finck va_list args;
3851c2c66affSColin Finck trio_custom_t data;
3852c2c66affSColin Finck
3853c2c66affSColin Finck assert(VALID(stream));
3854c2c66affSColin Finck assert(VALID(format));
3855c2c66affSColin Finck
3856c2c66affSColin Finck TRIO_VA_START(args, format);
3857c2c66affSColin Finck data.stream.out = stream;
3858c2c66affSColin Finck data.closure = closure;
3859c2c66affSColin Finck status = TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL);
3860c2c66affSColin Finck TRIO_VA_END(args);
3861c2c66affSColin Finck return status;
3862c2c66affSColin Finck }
3863c2c66affSColin Finck
3864c2c66affSColin Finck TRIO_PUBLIC int
3865c2c66affSColin Finck trio_vcprintf
3866c2c66affSColin Finck TRIO_ARGS4((stream, closure, format, args),
3867c2c66affSColin Finck trio_outstream_t stream,
3868c2c66affSColin Finck trio_pointer_t closure,
3869c2c66affSColin Finck TRIO_CONST char *format,
3870c2c66affSColin Finck va_list args)
3871c2c66affSColin Finck {
3872c2c66affSColin Finck trio_custom_t data;
3873c2c66affSColin Finck
3874c2c66affSColin Finck assert(VALID(stream));
3875c2c66affSColin Finck assert(VALID(format));
3876c2c66affSColin Finck
3877c2c66affSColin Finck data.stream.out = stream;
3878c2c66affSColin Finck data.closure = closure;
3879c2c66affSColin Finck return TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL);
3880c2c66affSColin Finck }
3881c2c66affSColin Finck
3882c2c66affSColin Finck TRIO_PUBLIC int
3883c2c66affSColin Finck trio_cprintfv
3884c2c66affSColin Finck TRIO_ARGS4((stream, closure, format, args),
3885c2c66affSColin Finck trio_outstream_t stream,
3886c2c66affSColin Finck trio_pointer_t closure,
3887c2c66affSColin Finck TRIO_CONST char *format,
3888c2c66affSColin Finck void **args)
3889c2c66affSColin Finck {
3890c2c66affSColin Finck trio_custom_t data;
3891c2c66affSColin Finck
3892c2c66affSColin Finck assert(VALID(stream));
3893c2c66affSColin Finck assert(VALID(format));
3894c2c66affSColin Finck
3895c2c66affSColin Finck data.stream.out = stream;
3896c2c66affSColin Finck data.closure = closure;
3897c2c66affSColin Finck return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
3898c2c66affSColin Finck }
3899c2c66affSColin Finck
3900c2c66affSColin Finck /*************************************************************************
3901c2c66affSColin Finck * sprintf
3902c2c66affSColin Finck */
3903c2c66affSColin Finck
3904c2c66affSColin Finck /**
3905c2c66affSColin Finck Print to string.
3906c2c66affSColin Finck
3907c2c66affSColin Finck @param buffer Output string.
3908c2c66affSColin Finck @param format Formatting string.
3909c2c66affSColin Finck @param ... Arguments.
3910c2c66affSColin Finck @return Number of printed characters.
3911c2c66affSColin Finck */
3912c2c66affSColin Finck TRIO_PUBLIC int
3913c2c66affSColin Finck trio_sprintf
3914c2c66affSColin Finck TRIO_VARGS3((buffer, format, va_alist),
3915c2c66affSColin Finck char *buffer,
3916c2c66affSColin Finck TRIO_CONST char *format,
3917c2c66affSColin Finck TRIO_VA_DECL)
3918c2c66affSColin Finck {
3919c2c66affSColin Finck int status;
3920c2c66affSColin Finck va_list args;
3921c2c66affSColin Finck
3922c2c66affSColin Finck assert(VALID(buffer));
3923c2c66affSColin Finck assert(VALID(format));
3924c2c66affSColin Finck
3925c2c66affSColin Finck TRIO_VA_START(args, format);
3926c2c66affSColin Finck status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL);
3927c2c66affSColin Finck *buffer = NIL; /* Terminate with NIL character */
3928c2c66affSColin Finck TRIO_VA_END(args);
3929c2c66affSColin Finck return status;
3930c2c66affSColin Finck }
3931c2c66affSColin Finck
3932c2c66affSColin Finck /**
3933c2c66affSColin Finck Print to string.
3934c2c66affSColin Finck
3935c2c66affSColin Finck @param buffer Output string.
3936c2c66affSColin Finck @param format Formatting string.
3937c2c66affSColin Finck @param args Arguments.
3938c2c66affSColin Finck @return Number of printed characters.
3939c2c66affSColin Finck */
3940c2c66affSColin Finck TRIO_PUBLIC int
3941c2c66affSColin Finck trio_vsprintf
3942c2c66affSColin Finck TRIO_ARGS3((buffer, format, args),
3943c2c66affSColin Finck char *buffer,
3944c2c66affSColin Finck TRIO_CONST char *format,
3945c2c66affSColin Finck va_list args)
3946c2c66affSColin Finck {
3947c2c66affSColin Finck int status;
3948c2c66affSColin Finck
3949c2c66affSColin Finck assert(VALID(buffer));
3950c2c66affSColin Finck assert(VALID(format));
3951c2c66affSColin Finck
3952c2c66affSColin Finck status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL);
3953c2c66affSColin Finck *buffer = NIL;
3954c2c66affSColin Finck return status;
3955c2c66affSColin Finck }
3956c2c66affSColin Finck
3957c2c66affSColin Finck /**
3958c2c66affSColin Finck Print to string.
3959c2c66affSColin Finck
3960c2c66affSColin Finck @param buffer Output string.
3961c2c66affSColin Finck @param format Formatting string.
3962c2c66affSColin Finck @param args Arguments.
3963c2c66affSColin Finck @return Number of printed characters.
3964c2c66affSColin Finck */
3965c2c66affSColin Finck TRIO_PUBLIC int
3966c2c66affSColin Finck trio_sprintfv
3967c2c66affSColin Finck TRIO_ARGS3((buffer, format, args),
3968c2c66affSColin Finck char *buffer,
3969c2c66affSColin Finck TRIO_CONST char *format,
3970c2c66affSColin Finck trio_pointer_t *args)
3971c2c66affSColin Finck {
3972c2c66affSColin Finck int status;
3973c2c66affSColin Finck
3974c2c66affSColin Finck assert(VALID(buffer));
3975c2c66affSColin Finck assert(VALID(format));
3976c2c66affSColin Finck
3977c2c66affSColin Finck status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
3978c2c66affSColin Finck *buffer = NIL;
3979c2c66affSColin Finck return status;
3980c2c66affSColin Finck }
3981c2c66affSColin Finck
3982c2c66affSColin Finck /*************************************************************************
3983c2c66affSColin Finck * snprintf
3984c2c66affSColin Finck */
3985c2c66affSColin Finck
3986c2c66affSColin Finck /**
3987c2c66affSColin Finck Print at most @p max characters to string.
3988c2c66affSColin Finck
3989c2c66affSColin Finck @param buffer Output string.
3990c2c66affSColin Finck @param max Maximum number of characters to print.
3991c2c66affSColin Finck @param format Formatting string.
3992c2c66affSColin Finck @param ... Arguments.
3993c2c66affSColin Finck @return Number of printed characters.
3994c2c66affSColin Finck */
3995c2c66affSColin Finck TRIO_PUBLIC int
3996c2c66affSColin Finck trio_snprintf
3997c2c66affSColin Finck TRIO_VARGS4((buffer, max, format, va_alist),
3998c2c66affSColin Finck char *buffer,
3999c2c66affSColin Finck size_t max,
4000c2c66affSColin Finck TRIO_CONST char *format,
4001c2c66affSColin Finck TRIO_VA_DECL)
4002c2c66affSColin Finck {
4003c2c66affSColin Finck int status;
4004c2c66affSColin Finck va_list args;
4005c2c66affSColin Finck
4006c2c66affSColin Finck assert(VALID(buffer));
4007c2c66affSColin Finck assert(VALID(format));
4008c2c66affSColin Finck
4009c2c66affSColin Finck TRIO_VA_START(args, format);
4010c2c66affSColin Finck status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4011c2c66affSColin Finck TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4012c2c66affSColin Finck if (max > 0)
4013c2c66affSColin Finck *buffer = NIL;
4014c2c66affSColin Finck TRIO_VA_END(args);
4015c2c66affSColin Finck return status;
4016c2c66affSColin Finck }
4017c2c66affSColin Finck
4018c2c66affSColin Finck /**
4019c2c66affSColin Finck Print at most @p max characters to string.
4020c2c66affSColin Finck
4021c2c66affSColin Finck @param buffer Output string.
4022c2c66affSColin Finck @param max Maximum number of characters to print.
4023c2c66affSColin Finck @param format Formatting string.
4024c2c66affSColin Finck @param args Arguments.
4025c2c66affSColin Finck @return Number of printed characters.
4026c2c66affSColin Finck */
4027c2c66affSColin Finck TRIO_PUBLIC int
4028c2c66affSColin Finck trio_vsnprintf
4029c2c66affSColin Finck TRIO_ARGS4((buffer, max, format, args),
4030c2c66affSColin Finck char *buffer,
4031c2c66affSColin Finck size_t max,
4032c2c66affSColin Finck TRIO_CONST char *format,
4033c2c66affSColin Finck va_list args)
4034c2c66affSColin Finck {
4035c2c66affSColin Finck int status;
4036c2c66affSColin Finck
4037c2c66affSColin Finck assert(VALID(buffer));
4038c2c66affSColin Finck assert(VALID(format));
4039c2c66affSColin Finck
4040c2c66affSColin Finck status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4041c2c66affSColin Finck TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4042c2c66affSColin Finck if (max > 0)
4043c2c66affSColin Finck *buffer = NIL;
4044c2c66affSColin Finck return status;
4045c2c66affSColin Finck }
4046c2c66affSColin Finck
4047c2c66affSColin Finck /**
4048c2c66affSColin Finck Print at most @p max characters to string.
4049c2c66affSColin Finck
4050c2c66affSColin Finck @param buffer Output string.
4051c2c66affSColin Finck @param max Maximum number of characters to print.
4052c2c66affSColin Finck @param format Formatting string.
4053c2c66affSColin Finck @param args Arguments.
4054c2c66affSColin Finck @return Number of printed characters.
4055c2c66affSColin Finck */
4056c2c66affSColin Finck TRIO_PUBLIC int
4057c2c66affSColin Finck trio_snprintfv
4058c2c66affSColin Finck TRIO_ARGS4((buffer, max, format, args),
4059c2c66affSColin Finck char *buffer,
4060c2c66affSColin Finck size_t max,
4061c2c66affSColin Finck TRIO_CONST char *format,
4062c2c66affSColin Finck trio_pointer_t *args)
4063c2c66affSColin Finck {
4064c2c66affSColin Finck int status;
4065c2c66affSColin Finck
4066c2c66affSColin Finck assert(VALID(buffer));
4067c2c66affSColin Finck assert(VALID(format));
4068c2c66affSColin Finck
4069c2c66affSColin Finck status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4070c2c66affSColin Finck TrioOutStreamStringMax, format, NULL, args);
4071c2c66affSColin Finck if (max > 0)
4072c2c66affSColin Finck *buffer = NIL;
4073c2c66affSColin Finck return status;
4074c2c66affSColin Finck }
4075c2c66affSColin Finck
4076c2c66affSColin Finck /*************************************************************************
4077c2c66affSColin Finck * snprintfcat
4078c2c66affSColin Finck * Appends the new string to the buffer string overwriting the '\0'
4079c2c66affSColin Finck * character at the end of buffer.
4080c2c66affSColin Finck */
4081c2c66affSColin Finck TRIO_PUBLIC int
4082c2c66affSColin Finck trio_snprintfcat
4083c2c66affSColin Finck TRIO_VARGS4((buffer, max, format, va_alist),
4084c2c66affSColin Finck char *buffer,
4085c2c66affSColin Finck size_t max,
4086c2c66affSColin Finck TRIO_CONST char *format,
4087c2c66affSColin Finck TRIO_VA_DECL)
4088c2c66affSColin Finck {
4089c2c66affSColin Finck int status;
4090c2c66affSColin Finck va_list args;
4091c2c66affSColin Finck size_t buf_len;
4092c2c66affSColin Finck
4093c2c66affSColin Finck TRIO_VA_START(args, format);
4094c2c66affSColin Finck
4095c2c66affSColin Finck assert(VALID(buffer));
4096c2c66affSColin Finck assert(VALID(format));
4097c2c66affSColin Finck
4098c2c66affSColin Finck buf_len = trio_length(buffer);
4099c2c66affSColin Finck buffer = &buffer[buf_len];
4100c2c66affSColin Finck
4101c2c66affSColin Finck status = TrioFormat(&buffer, max - 1 - buf_len,
4102c2c66affSColin Finck TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4103c2c66affSColin Finck TRIO_VA_END(args);
4104c2c66affSColin Finck *buffer = NIL;
4105c2c66affSColin Finck return status;
4106c2c66affSColin Finck }
4107c2c66affSColin Finck
4108c2c66affSColin Finck TRIO_PUBLIC int
4109c2c66affSColin Finck trio_vsnprintfcat
4110c2c66affSColin Finck TRIO_ARGS4((buffer, max, format, args),
4111c2c66affSColin Finck char *buffer,
4112c2c66affSColin Finck size_t max,
4113c2c66affSColin Finck TRIO_CONST char *format,
4114c2c66affSColin Finck va_list args)
4115c2c66affSColin Finck {
4116c2c66affSColin Finck int status;
4117c2c66affSColin Finck size_t buf_len;
4118c2c66affSColin Finck
4119c2c66affSColin Finck assert(VALID(buffer));
4120c2c66affSColin Finck assert(VALID(format));
4121c2c66affSColin Finck
4122c2c66affSColin Finck buf_len = trio_length(buffer);
4123c2c66affSColin Finck buffer = &buffer[buf_len];
4124c2c66affSColin Finck status = TrioFormat(&buffer, max - 1 - buf_len,
4125c2c66affSColin Finck TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL);
4126c2c66affSColin Finck *buffer = NIL;
4127c2c66affSColin Finck return status;
4128c2c66affSColin Finck }
4129c2c66affSColin Finck
4130c2c66affSColin Finck /*************************************************************************
4131c2c66affSColin Finck * trio_aprintf
4132c2c66affSColin Finck */
4133c2c66affSColin Finck
4134c2c66affSColin Finck /* Deprecated */
4135c2c66affSColin Finck TRIO_PUBLIC char *
4136c2c66affSColin Finck trio_aprintf
4137c2c66affSColin Finck TRIO_VARGS2((format, va_alist),
4138c2c66affSColin Finck TRIO_CONST char *format,
4139c2c66affSColin Finck TRIO_VA_DECL)
4140c2c66affSColin Finck {
4141c2c66affSColin Finck va_list args;
4142c2c66affSColin Finck trio_string_t *info;
4143c2c66affSColin Finck char *result = NULL;
4144c2c66affSColin Finck
4145c2c66affSColin Finck assert(VALID(format));
4146c2c66affSColin Finck
4147c2c66affSColin Finck info = trio_xstring_duplicate("");
4148c2c66affSColin Finck if (info)
4149c2c66affSColin Finck {
4150c2c66affSColin Finck TRIO_VA_START(args, format);
4151c2c66affSColin Finck (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
4152c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
4153c2c66affSColin Finck TRIO_VA_END(args);
4154c2c66affSColin Finck
4155c2c66affSColin Finck trio_string_terminate(info);
4156c2c66affSColin Finck result = trio_string_extract(info);
4157c2c66affSColin Finck trio_string_destroy(info);
4158c2c66affSColin Finck }
4159c2c66affSColin Finck return result;
4160c2c66affSColin Finck }
4161c2c66affSColin Finck
4162c2c66affSColin Finck /* Deprecated */
4163c2c66affSColin Finck TRIO_PUBLIC char *
4164c2c66affSColin Finck trio_vaprintf
4165c2c66affSColin Finck TRIO_ARGS2((format, args),
4166c2c66affSColin Finck TRIO_CONST char *format,
4167c2c66affSColin Finck va_list args)
4168c2c66affSColin Finck {
4169c2c66affSColin Finck trio_string_t *info;
4170c2c66affSColin Finck char *result = NULL;
4171c2c66affSColin Finck
4172c2c66affSColin Finck assert(VALID(format));
4173c2c66affSColin Finck
4174c2c66affSColin Finck info = trio_xstring_duplicate("");
4175c2c66affSColin Finck if (info)
4176c2c66affSColin Finck {
4177c2c66affSColin Finck (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
4178c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
4179c2c66affSColin Finck trio_string_terminate(info);
4180c2c66affSColin Finck result = trio_string_extract(info);
4181c2c66affSColin Finck trio_string_destroy(info);
4182c2c66affSColin Finck }
4183c2c66affSColin Finck return result;
4184c2c66affSColin Finck }
4185c2c66affSColin Finck
4186c2c66affSColin Finck TRIO_PUBLIC int
4187c2c66affSColin Finck trio_asprintf
4188c2c66affSColin Finck TRIO_VARGS3((result, format, va_alist),
4189c2c66affSColin Finck char **result,
4190c2c66affSColin Finck TRIO_CONST char *format,
4191c2c66affSColin Finck TRIO_VA_DECL)
4192c2c66affSColin Finck {
4193c2c66affSColin Finck va_list args;
4194c2c66affSColin Finck int status;
4195c2c66affSColin Finck trio_string_t *info;
4196c2c66affSColin Finck
4197c2c66affSColin Finck assert(VALID(format));
4198c2c66affSColin Finck
4199c2c66affSColin Finck *result = NULL;
4200c2c66affSColin Finck
4201c2c66affSColin Finck info = trio_xstring_duplicate("");
4202c2c66affSColin Finck if (info == NULL)
4203c2c66affSColin Finck {
4204c2c66affSColin Finck status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
4205c2c66affSColin Finck }
4206c2c66affSColin Finck else
4207c2c66affSColin Finck {
4208c2c66affSColin Finck TRIO_VA_START(args, format);
4209c2c66affSColin Finck status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
4210c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
4211c2c66affSColin Finck TRIO_VA_END(args);
4212c2c66affSColin Finck if (status >= 0)
4213c2c66affSColin Finck {
4214c2c66affSColin Finck trio_string_terminate(info);
4215c2c66affSColin Finck *result = trio_string_extract(info);
4216c2c66affSColin Finck }
4217c2c66affSColin Finck trio_string_destroy(info);
4218c2c66affSColin Finck }
4219c2c66affSColin Finck return status;
4220c2c66affSColin Finck }
4221c2c66affSColin Finck
4222c2c66affSColin Finck TRIO_PUBLIC int
4223c2c66affSColin Finck trio_vasprintf
4224c2c66affSColin Finck TRIO_ARGS3((result, format, args),
4225c2c66affSColin Finck char **result,
4226c2c66affSColin Finck TRIO_CONST char *format,
4227c2c66affSColin Finck va_list args)
4228c2c66affSColin Finck {
4229c2c66affSColin Finck int status;
4230c2c66affSColin Finck trio_string_t *info;
4231c2c66affSColin Finck
4232c2c66affSColin Finck assert(VALID(format));
4233c2c66affSColin Finck
4234c2c66affSColin Finck *result = NULL;
4235c2c66affSColin Finck
4236c2c66affSColin Finck info = trio_xstring_duplicate("");
4237c2c66affSColin Finck if (info == NULL)
4238c2c66affSColin Finck {
4239c2c66affSColin Finck status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
4240c2c66affSColin Finck }
4241c2c66affSColin Finck else
4242c2c66affSColin Finck {
4243c2c66affSColin Finck status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
4244c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
4245c2c66affSColin Finck if (status >= 0)
4246c2c66affSColin Finck {
4247c2c66affSColin Finck trio_string_terminate(info);
4248c2c66affSColin Finck *result = trio_string_extract(info);
4249c2c66affSColin Finck }
4250c2c66affSColin Finck trio_string_destroy(info);
4251c2c66affSColin Finck }
4252c2c66affSColin Finck return status;
4253c2c66affSColin Finck }
4254c2c66affSColin Finck
4255c2c66affSColin Finck /** @} End of Printf documentation module */
4256c2c66affSColin Finck
4257c2c66affSColin Finck /*************************************************************************
4258c2c66affSColin Finck *
4259c2c66affSColin Finck * CALLBACK
4260c2c66affSColin Finck *
4261c2c66affSColin Finck ************************************************************************/
4262c2c66affSColin Finck
4263c2c66affSColin Finck #if defined(TRIO_DOCUMENTATION)
4264c2c66affSColin Finck # include "doc/doc_register.h"
4265c2c66affSColin Finck #endif
4266c2c66affSColin Finck /**
4267c2c66affSColin Finck @addtogroup UserDefined
4268c2c66affSColin Finck @{
4269c2c66affSColin Finck */
4270c2c66affSColin Finck
4271c2c66affSColin Finck #if TRIO_EXTENSION
4272c2c66affSColin Finck
4273c2c66affSColin Finck /*************************************************************************
4274c2c66affSColin Finck * trio_register
4275c2c66affSColin Finck */
4276c2c66affSColin Finck
4277c2c66affSColin Finck /**
4278c2c66affSColin Finck Register new user-defined specifier.
4279c2c66affSColin Finck
4280c2c66affSColin Finck @param callback
4281c2c66affSColin Finck @param name
4282c2c66affSColin Finck @return Handle.
4283c2c66affSColin Finck */
4284c2c66affSColin Finck TRIO_PUBLIC trio_pointer_t
4285c2c66affSColin Finck trio_register
4286c2c66affSColin Finck TRIO_ARGS2((callback, name),
4287c2c66affSColin Finck trio_callback_t callback,
4288c2c66affSColin Finck TRIO_CONST char *name)
4289c2c66affSColin Finck {
4290c2c66affSColin Finck trio_userdef_t *def;
4291c2c66affSColin Finck trio_userdef_t *prev = NULL;
4292c2c66affSColin Finck
4293c2c66affSColin Finck if (callback == NULL)
4294c2c66affSColin Finck return NULL;
4295c2c66affSColin Finck
4296c2c66affSColin Finck if (name)
4297c2c66affSColin Finck {
4298c2c66affSColin Finck /* Handle built-in namespaces */
4299c2c66affSColin Finck if (name[0] == ':')
4300c2c66affSColin Finck {
4301c2c66affSColin Finck if (trio_equal(name, ":enter"))
4302c2c66affSColin Finck {
4303c2c66affSColin Finck internalEnterCriticalRegion = callback;
4304c2c66affSColin Finck }
4305c2c66affSColin Finck else if (trio_equal(name, ":leave"))
4306c2c66affSColin Finck {
4307c2c66affSColin Finck internalLeaveCriticalRegion = callback;
4308c2c66affSColin Finck }
4309c2c66affSColin Finck return NULL;
4310c2c66affSColin Finck }
4311c2c66affSColin Finck
4312c2c66affSColin Finck /* Bail out if namespace is too long */
4313c2c66affSColin Finck if (trio_length(name) >= MAX_USER_NAME)
4314c2c66affSColin Finck return NULL;
4315c2c66affSColin Finck
4316c2c66affSColin Finck /* Bail out if namespace already is registered */
4317c2c66affSColin Finck def = TrioFindNamespace(name, &prev);
4318c2c66affSColin Finck if (def)
4319c2c66affSColin Finck return NULL;
4320c2c66affSColin Finck }
4321c2c66affSColin Finck
4322c2c66affSColin Finck def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t));
4323c2c66affSColin Finck if (def)
4324c2c66affSColin Finck {
4325c2c66affSColin Finck if (internalEnterCriticalRegion)
4326c2c66affSColin Finck (void)internalEnterCriticalRegion(NULL);
4327c2c66affSColin Finck
4328c2c66affSColin Finck if (name)
4329c2c66affSColin Finck {
4330c2c66affSColin Finck /* Link into internal list */
4331c2c66affSColin Finck if (prev == NULL)
4332c2c66affSColin Finck internalUserDef = def;
4333c2c66affSColin Finck else
4334c2c66affSColin Finck prev->next = def;
4335c2c66affSColin Finck }
4336c2c66affSColin Finck /* Initialize */
4337c2c66affSColin Finck def->callback = callback;
4338c2c66affSColin Finck def->name = (name == NULL)
4339c2c66affSColin Finck ? NULL
4340c2c66affSColin Finck : trio_duplicate(name);
4341c2c66affSColin Finck def->next = NULL;
4342c2c66affSColin Finck
4343c2c66affSColin Finck if (internalLeaveCriticalRegion)
4344c2c66affSColin Finck (void)internalLeaveCriticalRegion(NULL);
4345c2c66affSColin Finck }
4346c2c66affSColin Finck return (trio_pointer_t)def;
4347c2c66affSColin Finck }
4348c2c66affSColin Finck
4349c2c66affSColin Finck /**
4350c2c66affSColin Finck Unregister an existing user-defined specifier.
4351c2c66affSColin Finck
4352c2c66affSColin Finck @param handle
4353c2c66affSColin Finck */
4354c2c66affSColin Finck void
4355c2c66affSColin Finck trio_unregister
4356c2c66affSColin Finck TRIO_ARGS1((handle),
4357c2c66affSColin Finck trio_pointer_t handle)
4358c2c66affSColin Finck {
4359c2c66affSColin Finck trio_userdef_t *self = (trio_userdef_t *)handle;
4360c2c66affSColin Finck trio_userdef_t *def;
4361c2c66affSColin Finck trio_userdef_t *prev = NULL;
4362c2c66affSColin Finck
4363c2c66affSColin Finck assert(VALID(self));
4364c2c66affSColin Finck
4365c2c66affSColin Finck if (self->name)
4366c2c66affSColin Finck {
4367c2c66affSColin Finck def = TrioFindNamespace(self->name, &prev);
4368c2c66affSColin Finck if (def)
4369c2c66affSColin Finck {
4370c2c66affSColin Finck if (internalEnterCriticalRegion)
4371c2c66affSColin Finck (void)internalEnterCriticalRegion(NULL);
4372c2c66affSColin Finck
4373c2c66affSColin Finck if (prev == NULL)
4374c2c66affSColin Finck internalUserDef = NULL;
4375c2c66affSColin Finck else
4376c2c66affSColin Finck prev->next = def->next;
4377c2c66affSColin Finck
4378c2c66affSColin Finck if (internalLeaveCriticalRegion)
4379c2c66affSColin Finck (void)internalLeaveCriticalRegion(NULL);
4380c2c66affSColin Finck }
4381c2c66affSColin Finck trio_destroy(self->name);
4382c2c66affSColin Finck }
4383c2c66affSColin Finck TRIO_FREE(self);
4384c2c66affSColin Finck }
4385c2c66affSColin Finck
4386c2c66affSColin Finck /*************************************************************************
4387c2c66affSColin Finck * trio_get_format [public]
4388c2c66affSColin Finck */
4389c2c66affSColin Finck TRIO_CONST char *
4390c2c66affSColin Finck trio_get_format
4391c2c66affSColin Finck TRIO_ARGS1((ref),
4392c2c66affSColin Finck trio_pointer_t ref)
4393c2c66affSColin Finck {
4394c2c66affSColin Finck #if defined(FORMAT_USER_DEFINED)
4395c2c66affSColin Finck assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
4396c2c66affSColin Finck #endif
4397c2c66affSColin Finck
4398c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->user_data);
4399c2c66affSColin Finck }
4400c2c66affSColin Finck
4401c2c66affSColin Finck /*************************************************************************
4402c2c66affSColin Finck * trio_get_argument [public]
4403c2c66affSColin Finck */
4404c2c66affSColin Finck trio_pointer_t
4405c2c66affSColin Finck trio_get_argument
4406c2c66affSColin Finck TRIO_ARGS1((ref),
4407c2c66affSColin Finck trio_pointer_t ref)
4408c2c66affSColin Finck {
4409c2c66affSColin Finck #if defined(FORMAT_USER_DEFINED)
4410c2c66affSColin Finck assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
4411c2c66affSColin Finck #endif
4412c2c66affSColin Finck
4413c2c66affSColin Finck return ((trio_reference_t *)ref)->parameter->data.pointer;
4414c2c66affSColin Finck }
4415c2c66affSColin Finck
4416c2c66affSColin Finck /*************************************************************************
4417c2c66affSColin Finck * trio_get_width / trio_set_width [public]
4418c2c66affSColin Finck */
4419c2c66affSColin Finck int
4420c2c66affSColin Finck trio_get_width
4421c2c66affSColin Finck TRIO_ARGS1((ref),
4422c2c66affSColin Finck trio_pointer_t ref)
4423c2c66affSColin Finck {
4424c2c66affSColin Finck return ((trio_reference_t *)ref)->parameter->width;
4425c2c66affSColin Finck }
4426c2c66affSColin Finck
4427c2c66affSColin Finck void
4428c2c66affSColin Finck trio_set_width
4429c2c66affSColin Finck TRIO_ARGS2((ref, width),
4430c2c66affSColin Finck trio_pointer_t ref,
4431c2c66affSColin Finck int width)
4432c2c66affSColin Finck {
4433c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->width = width;
4434c2c66affSColin Finck }
4435c2c66affSColin Finck
4436c2c66affSColin Finck /*************************************************************************
4437c2c66affSColin Finck * trio_get_precision / trio_set_precision [public]
4438c2c66affSColin Finck */
4439c2c66affSColin Finck int
4440c2c66affSColin Finck trio_get_precision
4441c2c66affSColin Finck TRIO_ARGS1((ref),
4442c2c66affSColin Finck trio_pointer_t ref)
4443c2c66affSColin Finck {
4444c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->precision);
4445c2c66affSColin Finck }
4446c2c66affSColin Finck
4447c2c66affSColin Finck void
4448c2c66affSColin Finck trio_set_precision
4449c2c66affSColin Finck TRIO_ARGS2((ref, precision),
4450c2c66affSColin Finck trio_pointer_t ref,
4451c2c66affSColin Finck int precision)
4452c2c66affSColin Finck {
4453c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->precision = precision;
4454c2c66affSColin Finck }
4455c2c66affSColin Finck
4456c2c66affSColin Finck /*************************************************************************
4457c2c66affSColin Finck * trio_get_base / trio_set_base [public]
4458c2c66affSColin Finck */
4459c2c66affSColin Finck int
4460c2c66affSColin Finck trio_get_base
4461c2c66affSColin Finck TRIO_ARGS1((ref),
4462c2c66affSColin Finck trio_pointer_t ref)
4463c2c66affSColin Finck {
4464c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->base);
4465c2c66affSColin Finck }
4466c2c66affSColin Finck
4467c2c66affSColin Finck void
4468c2c66affSColin Finck trio_set_base
4469c2c66affSColin Finck TRIO_ARGS2((ref, base),
4470c2c66affSColin Finck trio_pointer_t ref,
4471c2c66affSColin Finck int base)
4472c2c66affSColin Finck {
4473c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->base = base;
4474c2c66affSColin Finck }
4475c2c66affSColin Finck
4476c2c66affSColin Finck /*************************************************************************
4477c2c66affSColin Finck * trio_get_long / trio_set_long [public]
4478c2c66affSColin Finck */
4479c2c66affSColin Finck int
4480c2c66affSColin Finck trio_get_long
4481c2c66affSColin Finck TRIO_ARGS1((ref),
4482c2c66affSColin Finck trio_pointer_t ref)
4483c2c66affSColin Finck {
4484c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG)
4485c2c66affSColin Finck ? TRUE
4486c2c66affSColin Finck : FALSE;
4487c2c66affSColin Finck }
4488c2c66affSColin Finck
4489c2c66affSColin Finck void
4490c2c66affSColin Finck trio_set_long
4491c2c66affSColin Finck TRIO_ARGS2((ref, is_long),
4492c2c66affSColin Finck trio_pointer_t ref,
4493c2c66affSColin Finck int is_long)
4494c2c66affSColin Finck {
4495c2c66affSColin Finck if (is_long)
4496c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG;
4497c2c66affSColin Finck else
4498c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG;
4499c2c66affSColin Finck }
4500c2c66affSColin Finck
4501c2c66affSColin Finck /*************************************************************************
4502c2c66affSColin Finck * trio_get_longlong / trio_set_longlong [public]
4503c2c66affSColin Finck */
4504c2c66affSColin Finck int
4505c2c66affSColin Finck trio_get_longlong
4506c2c66affSColin Finck TRIO_ARGS1((ref),
4507c2c66affSColin Finck trio_pointer_t ref)
4508c2c66affSColin Finck {
4509c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD)
4510c2c66affSColin Finck ? TRUE
4511c2c66affSColin Finck : FALSE;
4512c2c66affSColin Finck }
4513c2c66affSColin Finck
4514c2c66affSColin Finck void
4515c2c66affSColin Finck trio_set_longlong
4516c2c66affSColin Finck TRIO_ARGS2((ref, is_longlong),
4517c2c66affSColin Finck trio_pointer_t ref,
4518c2c66affSColin Finck int is_longlong)
4519c2c66affSColin Finck {
4520c2c66affSColin Finck if (is_longlong)
4521c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD;
4522c2c66affSColin Finck else
4523c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD;
4524c2c66affSColin Finck }
4525c2c66affSColin Finck
4526c2c66affSColin Finck /*************************************************************************
4527c2c66affSColin Finck * trio_get_longdouble / trio_set_longdouble [public]
4528c2c66affSColin Finck */
4529c2c66affSColin Finck int
4530c2c66affSColin Finck trio_get_longdouble
4531c2c66affSColin Finck TRIO_ARGS1((ref),
4532c2c66affSColin Finck trio_pointer_t ref)
4533c2c66affSColin Finck {
4534c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE)
4535c2c66affSColin Finck ? TRUE
4536c2c66affSColin Finck : FALSE;
4537c2c66affSColin Finck }
4538c2c66affSColin Finck
4539c2c66affSColin Finck void
4540c2c66affSColin Finck trio_set_longdouble
4541c2c66affSColin Finck TRIO_ARGS2((ref, is_longdouble),
4542c2c66affSColin Finck trio_pointer_t ref,
4543c2c66affSColin Finck int is_longdouble)
4544c2c66affSColin Finck {
4545c2c66affSColin Finck if (is_longdouble)
4546c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE;
4547c2c66affSColin Finck else
4548c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
4549c2c66affSColin Finck }
4550c2c66affSColin Finck
4551c2c66affSColin Finck /*************************************************************************
4552c2c66affSColin Finck * trio_get_short / trio_set_short [public]
4553c2c66affSColin Finck */
4554c2c66affSColin Finck int
4555c2c66affSColin Finck trio_get_short
4556c2c66affSColin Finck TRIO_ARGS1((ref),
4557c2c66affSColin Finck trio_pointer_t ref)
4558c2c66affSColin Finck {
4559c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT)
4560c2c66affSColin Finck ? TRUE
4561c2c66affSColin Finck : FALSE;
4562c2c66affSColin Finck }
4563c2c66affSColin Finck
4564c2c66affSColin Finck void
4565c2c66affSColin Finck trio_set_short
4566c2c66affSColin Finck TRIO_ARGS2((ref, is_short),
4567c2c66affSColin Finck trio_pointer_t ref,
4568c2c66affSColin Finck int is_short)
4569c2c66affSColin Finck {
4570c2c66affSColin Finck if (is_short)
4571c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT;
4572c2c66affSColin Finck else
4573c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT;
4574c2c66affSColin Finck }
4575c2c66affSColin Finck
4576c2c66affSColin Finck /*************************************************************************
4577c2c66affSColin Finck * trio_get_shortshort / trio_set_shortshort [public]
4578c2c66affSColin Finck */
4579c2c66affSColin Finck int
4580c2c66affSColin Finck trio_get_shortshort
4581c2c66affSColin Finck TRIO_ARGS1((ref),
4582c2c66affSColin Finck trio_pointer_t ref)
4583c2c66affSColin Finck {
4584c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT)
4585c2c66affSColin Finck ? TRUE
4586c2c66affSColin Finck : FALSE;
4587c2c66affSColin Finck }
4588c2c66affSColin Finck
4589c2c66affSColin Finck void
4590c2c66affSColin Finck trio_set_shortshort
4591c2c66affSColin Finck TRIO_ARGS2((ref, is_shortshort),
4592c2c66affSColin Finck trio_pointer_t ref,
4593c2c66affSColin Finck int is_shortshort)
4594c2c66affSColin Finck {
4595c2c66affSColin Finck if (is_shortshort)
4596c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT;
4597c2c66affSColin Finck else
4598c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT;
4599c2c66affSColin Finck }
4600c2c66affSColin Finck
4601c2c66affSColin Finck /*************************************************************************
4602c2c66affSColin Finck * trio_get_alternative / trio_set_alternative [public]
4603c2c66affSColin Finck */
4604c2c66affSColin Finck int
4605c2c66affSColin Finck trio_get_alternative
4606c2c66affSColin Finck TRIO_ARGS1((ref),
4607c2c66affSColin Finck trio_pointer_t ref)
4608c2c66affSColin Finck {
4609c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE)
4610c2c66affSColin Finck ? TRUE
4611c2c66affSColin Finck : FALSE;
4612c2c66affSColin Finck }
4613c2c66affSColin Finck
4614c2c66affSColin Finck void
4615c2c66affSColin Finck trio_set_alternative
4616c2c66affSColin Finck TRIO_ARGS2((ref, is_alternative),
4617c2c66affSColin Finck trio_pointer_t ref,
4618c2c66affSColin Finck int is_alternative)
4619c2c66affSColin Finck {
4620c2c66affSColin Finck if (is_alternative)
4621c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE;
4622c2c66affSColin Finck else
4623c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE;
4624c2c66affSColin Finck }
4625c2c66affSColin Finck
4626c2c66affSColin Finck /*************************************************************************
4627c2c66affSColin Finck * trio_get_alignment / trio_set_alignment [public]
4628c2c66affSColin Finck */
4629c2c66affSColin Finck int
4630c2c66affSColin Finck trio_get_alignment
4631c2c66affSColin Finck TRIO_ARGS1((ref),
4632c2c66affSColin Finck trio_pointer_t ref)
4633c2c66affSColin Finck {
4634c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST)
4635c2c66affSColin Finck ? TRUE
4636c2c66affSColin Finck : FALSE;
4637c2c66affSColin Finck }
4638c2c66affSColin Finck
4639c2c66affSColin Finck void
4640c2c66affSColin Finck trio_set_alignment
4641c2c66affSColin Finck TRIO_ARGS2((ref, is_leftaligned),
4642c2c66affSColin Finck trio_pointer_t ref,
4643c2c66affSColin Finck int is_leftaligned)
4644c2c66affSColin Finck {
4645c2c66affSColin Finck if (is_leftaligned)
4646c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST;
4647c2c66affSColin Finck else
4648c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST;
4649c2c66affSColin Finck }
4650c2c66affSColin Finck
4651c2c66affSColin Finck /*************************************************************************
4652c2c66affSColin Finck * trio_get_spacing /trio_set_spacing [public]
4653c2c66affSColin Finck */
4654c2c66affSColin Finck int
4655c2c66affSColin Finck trio_get_spacing
4656c2c66affSColin Finck TRIO_ARGS1((ref),
4657c2c66affSColin Finck trio_pointer_t ref)
4658c2c66affSColin Finck {
4659c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE)
4660c2c66affSColin Finck ? TRUE
4661c2c66affSColin Finck : FALSE;
4662c2c66affSColin Finck }
4663c2c66affSColin Finck
4664c2c66affSColin Finck void
4665c2c66affSColin Finck trio_set_spacing
4666c2c66affSColin Finck TRIO_ARGS2((ref, is_space),
4667c2c66affSColin Finck trio_pointer_t ref,
4668c2c66affSColin Finck int is_space)
4669c2c66affSColin Finck {
4670c2c66affSColin Finck if (is_space)
4671c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE;
4672c2c66affSColin Finck else
4673c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE;
4674c2c66affSColin Finck }
4675c2c66affSColin Finck
4676c2c66affSColin Finck /*************************************************************************
4677c2c66affSColin Finck * trio_get_sign / trio_set_sign [public]
4678c2c66affSColin Finck */
4679c2c66affSColin Finck int
4680c2c66affSColin Finck trio_get_sign
4681c2c66affSColin Finck TRIO_ARGS1((ref),
4682c2c66affSColin Finck trio_pointer_t ref)
4683c2c66affSColin Finck {
4684c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN)
4685c2c66affSColin Finck ? TRUE
4686c2c66affSColin Finck : FALSE;
4687c2c66affSColin Finck }
4688c2c66affSColin Finck
4689c2c66affSColin Finck void
4690c2c66affSColin Finck trio_set_sign
4691c2c66affSColin Finck TRIO_ARGS2((ref, is_sign),
4692c2c66affSColin Finck trio_pointer_t ref,
4693c2c66affSColin Finck int is_sign)
4694c2c66affSColin Finck {
4695c2c66affSColin Finck if (is_sign)
4696c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN;
4697c2c66affSColin Finck else
4698c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN;
4699c2c66affSColin Finck }
4700c2c66affSColin Finck
4701c2c66affSColin Finck /*************************************************************************
4702c2c66affSColin Finck * trio_get_padding / trio_set_padding [public]
4703c2c66affSColin Finck */
4704c2c66affSColin Finck int
4705c2c66affSColin Finck trio_get_padding
4706c2c66affSColin Finck TRIO_ARGS1((ref),
4707c2c66affSColin Finck trio_pointer_t ref)
4708c2c66affSColin Finck {
4709c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING)
4710c2c66affSColin Finck ? TRUE
4711c2c66affSColin Finck : FALSE;
4712c2c66affSColin Finck }
4713c2c66affSColin Finck
4714c2c66affSColin Finck void
4715c2c66affSColin Finck trio_set_padding
4716c2c66affSColin Finck TRIO_ARGS2((ref, is_padding),
4717c2c66affSColin Finck trio_pointer_t ref,
4718c2c66affSColin Finck int is_padding)
4719c2c66affSColin Finck {
4720c2c66affSColin Finck if (is_padding)
4721c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING;
4722c2c66affSColin Finck else
4723c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING;
4724c2c66affSColin Finck }
4725c2c66affSColin Finck
4726c2c66affSColin Finck /*************************************************************************
4727c2c66affSColin Finck * trio_get_quote / trio_set_quote [public]
4728c2c66affSColin Finck */
4729c2c66affSColin Finck int
4730c2c66affSColin Finck trio_get_quote
4731c2c66affSColin Finck TRIO_ARGS1((ref),
4732c2c66affSColin Finck trio_pointer_t ref)
4733c2c66affSColin Finck {
4734c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE)
4735c2c66affSColin Finck ? TRUE
4736c2c66affSColin Finck : FALSE;
4737c2c66affSColin Finck }
4738c2c66affSColin Finck
4739c2c66affSColin Finck void
4740c2c66affSColin Finck trio_set_quote
4741c2c66affSColin Finck TRIO_ARGS2((ref, is_quote),
4742c2c66affSColin Finck trio_pointer_t ref,
4743c2c66affSColin Finck int is_quote)
4744c2c66affSColin Finck {
4745c2c66affSColin Finck if (is_quote)
4746c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE;
4747c2c66affSColin Finck else
4748c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
4749c2c66affSColin Finck }
4750c2c66affSColin Finck
4751c2c66affSColin Finck /*************************************************************************
4752c2c66affSColin Finck * trio_get_upper / trio_set_upper [public]
4753c2c66affSColin Finck */
4754c2c66affSColin Finck int
4755c2c66affSColin Finck trio_get_upper
4756c2c66affSColin Finck TRIO_ARGS1((ref),
4757c2c66affSColin Finck trio_pointer_t ref)
4758c2c66affSColin Finck {
4759c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER)
4760c2c66affSColin Finck ? TRUE
4761c2c66affSColin Finck : FALSE;
4762c2c66affSColin Finck }
4763c2c66affSColin Finck
4764c2c66affSColin Finck void
4765c2c66affSColin Finck trio_set_upper
4766c2c66affSColin Finck TRIO_ARGS2((ref, is_upper),
4767c2c66affSColin Finck trio_pointer_t ref,
4768c2c66affSColin Finck int is_upper)
4769c2c66affSColin Finck {
4770c2c66affSColin Finck if (is_upper)
4771c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER;
4772c2c66affSColin Finck else
4773c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER;
4774c2c66affSColin Finck }
4775c2c66affSColin Finck
4776c2c66affSColin Finck /*************************************************************************
4777c2c66affSColin Finck * trio_get_largest / trio_set_largest [public]
4778c2c66affSColin Finck */
4779c2c66affSColin Finck #if TRIO_C99
4780c2c66affSColin Finck int
4781c2c66affSColin Finck trio_get_largest
4782c2c66affSColin Finck TRIO_ARGS1((ref),
4783c2c66affSColin Finck trio_pointer_t ref)
4784c2c66affSColin Finck {
4785c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T)
4786c2c66affSColin Finck ? TRUE
4787c2c66affSColin Finck : FALSE;
4788c2c66affSColin Finck }
4789c2c66affSColin Finck
4790c2c66affSColin Finck void
4791c2c66affSColin Finck trio_set_largest
4792c2c66affSColin Finck TRIO_ARGS2((ref, is_largest),
4793c2c66affSColin Finck trio_pointer_t ref,
4794c2c66affSColin Finck int is_largest)
4795c2c66affSColin Finck {
4796c2c66affSColin Finck if (is_largest)
4797c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T;
4798c2c66affSColin Finck else
4799c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
4800c2c66affSColin Finck }
4801c2c66affSColin Finck #endif
4802c2c66affSColin Finck
4803c2c66affSColin Finck /*************************************************************************
4804c2c66affSColin Finck * trio_get_ptrdiff / trio_set_ptrdiff [public]
4805c2c66affSColin Finck */
4806c2c66affSColin Finck int
4807c2c66affSColin Finck trio_get_ptrdiff
4808c2c66affSColin Finck TRIO_ARGS1((ref),
4809c2c66affSColin Finck trio_pointer_t ref)
4810c2c66affSColin Finck {
4811c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T)
4812c2c66affSColin Finck ? TRUE
4813c2c66affSColin Finck : FALSE;
4814c2c66affSColin Finck }
4815c2c66affSColin Finck
4816c2c66affSColin Finck void
4817c2c66affSColin Finck trio_set_ptrdiff
4818c2c66affSColin Finck TRIO_ARGS2((ref, is_ptrdiff),
4819c2c66affSColin Finck trio_pointer_t ref,
4820c2c66affSColin Finck int is_ptrdiff)
4821c2c66affSColin Finck {
4822c2c66affSColin Finck if (is_ptrdiff)
4823c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T;
4824c2c66affSColin Finck else
4825c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
4826c2c66affSColin Finck }
4827c2c66affSColin Finck
4828c2c66affSColin Finck /*************************************************************************
4829c2c66affSColin Finck * trio_get_size / trio_set_size [public]
4830c2c66affSColin Finck */
4831c2c66affSColin Finck #if TRIO_C99
4832c2c66affSColin Finck int
4833c2c66affSColin Finck trio_get_size
4834c2c66affSColin Finck TRIO_ARGS1((ref),
4835c2c66affSColin Finck trio_pointer_t ref)
4836c2c66affSColin Finck {
4837c2c66affSColin Finck return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T)
4838c2c66affSColin Finck ? TRUE
4839c2c66affSColin Finck : FALSE;
4840c2c66affSColin Finck }
4841c2c66affSColin Finck
4842c2c66affSColin Finck void
4843c2c66affSColin Finck trio_set_size
4844c2c66affSColin Finck TRIO_ARGS2((ref, is_size),
4845c2c66affSColin Finck trio_pointer_t ref,
4846c2c66affSColin Finck int is_size)
4847c2c66affSColin Finck {
4848c2c66affSColin Finck if (is_size)
4849c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T;
4850c2c66affSColin Finck else
4851c2c66affSColin Finck ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
4852c2c66affSColin Finck }
4853c2c66affSColin Finck #endif
4854c2c66affSColin Finck
4855c2c66affSColin Finck /*************************************************************************
4856c2c66affSColin Finck * trio_print_int [public]
4857c2c66affSColin Finck */
4858c2c66affSColin Finck void
4859c2c66affSColin Finck trio_print_int
4860c2c66affSColin Finck TRIO_ARGS2((ref, number),
4861c2c66affSColin Finck trio_pointer_t ref,
4862c2c66affSColin Finck int number)
4863c2c66affSColin Finck {
4864c2c66affSColin Finck trio_reference_t *self = (trio_reference_t *)ref;
4865c2c66affSColin Finck
4866c2c66affSColin Finck TrioWriteNumber(self->data,
4867c2c66affSColin Finck (trio_uintmax_t)number,
4868c2c66affSColin Finck self->parameter->flags,
4869c2c66affSColin Finck self->parameter->width,
4870c2c66affSColin Finck self->parameter->precision,
4871c2c66affSColin Finck self->parameter->base);
4872c2c66affSColin Finck }
4873c2c66affSColin Finck
4874c2c66affSColin Finck /*************************************************************************
4875c2c66affSColin Finck * trio_print_uint [public]
4876c2c66affSColin Finck */
4877c2c66affSColin Finck void
4878c2c66affSColin Finck trio_print_uint
4879c2c66affSColin Finck TRIO_ARGS2((ref, number),
4880c2c66affSColin Finck trio_pointer_t ref,
4881c2c66affSColin Finck unsigned int number)
4882c2c66affSColin Finck {
4883c2c66affSColin Finck trio_reference_t *self = (trio_reference_t *)ref;
4884c2c66affSColin Finck
4885c2c66affSColin Finck TrioWriteNumber(self->data,
4886c2c66affSColin Finck (trio_uintmax_t)number,
4887c2c66affSColin Finck self->parameter->flags | FLAGS_UNSIGNED,
4888c2c66affSColin Finck self->parameter->width,
4889c2c66affSColin Finck self->parameter->precision,
4890c2c66affSColin Finck self->parameter->base);
4891c2c66affSColin Finck }
4892c2c66affSColin Finck
4893c2c66affSColin Finck /*************************************************************************
4894c2c66affSColin Finck * trio_print_double [public]
4895c2c66affSColin Finck */
4896c2c66affSColin Finck void
4897c2c66affSColin Finck trio_print_double
4898c2c66affSColin Finck TRIO_ARGS2((ref, number),
4899c2c66affSColin Finck trio_pointer_t ref,
4900c2c66affSColin Finck double number)
4901c2c66affSColin Finck {
4902c2c66affSColin Finck trio_reference_t *self = (trio_reference_t *)ref;
4903c2c66affSColin Finck
4904c2c66affSColin Finck TrioWriteDouble(self->data,
4905c2c66affSColin Finck number,
4906c2c66affSColin Finck self->parameter->flags,
4907c2c66affSColin Finck self->parameter->width,
4908c2c66affSColin Finck self->parameter->precision,
4909c2c66affSColin Finck self->parameter->base);
4910c2c66affSColin Finck }
4911c2c66affSColin Finck
4912c2c66affSColin Finck /*************************************************************************
4913c2c66affSColin Finck * trio_print_string [public]
4914c2c66affSColin Finck */
4915c2c66affSColin Finck void
4916c2c66affSColin Finck trio_print_string
4917c2c66affSColin Finck TRIO_ARGS2((ref, string),
4918c2c66affSColin Finck trio_pointer_t ref,
4919c2c66affSColin Finck char *string)
4920c2c66affSColin Finck {
4921c2c66affSColin Finck trio_reference_t *self = (trio_reference_t *)ref;
4922c2c66affSColin Finck
4923c2c66affSColin Finck TrioWriteString(self->data,
4924c2c66affSColin Finck string,
4925c2c66affSColin Finck self->parameter->flags,
4926c2c66affSColin Finck self->parameter->width,
4927c2c66affSColin Finck self->parameter->precision);
4928c2c66affSColin Finck }
4929c2c66affSColin Finck
4930c2c66affSColin Finck /*************************************************************************
4931c2c66affSColin Finck * trio_print_ref [public]
4932c2c66affSColin Finck */
4933c2c66affSColin Finck int
4934c2c66affSColin Finck trio_print_ref
4935c2c66affSColin Finck TRIO_VARGS3((ref, format, va_alist),
4936c2c66affSColin Finck trio_pointer_t ref,
4937c2c66affSColin Finck TRIO_CONST char *format,
4938c2c66affSColin Finck TRIO_VA_DECL)
4939c2c66affSColin Finck {
4940c2c66affSColin Finck int status;
4941c2c66affSColin Finck va_list arglist;
4942c2c66affSColin Finck
4943c2c66affSColin Finck assert(VALID(format));
4944c2c66affSColin Finck
4945c2c66affSColin Finck TRIO_VA_START(arglist, format);
4946c2c66affSColin Finck status = TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL);
4947c2c66affSColin Finck TRIO_VA_END(arglist);
4948c2c66affSColin Finck return status;
4949c2c66affSColin Finck }
4950c2c66affSColin Finck
4951c2c66affSColin Finck /*************************************************************************
4952c2c66affSColin Finck * trio_vprint_ref [public]
4953c2c66affSColin Finck */
4954c2c66affSColin Finck int
4955c2c66affSColin Finck trio_vprint_ref
4956c2c66affSColin Finck TRIO_ARGS3((ref, format, arglist),
4957c2c66affSColin Finck trio_pointer_t ref,
4958c2c66affSColin Finck TRIO_CONST char *format,
4959c2c66affSColin Finck va_list arglist)
4960c2c66affSColin Finck {
4961c2c66affSColin Finck assert(VALID(format));
4962c2c66affSColin Finck
4963c2c66affSColin Finck return TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL);
4964c2c66affSColin Finck }
4965c2c66affSColin Finck
4966c2c66affSColin Finck /*************************************************************************
4967c2c66affSColin Finck * trio_printv_ref [public]
4968c2c66affSColin Finck */
4969c2c66affSColin Finck int
4970c2c66affSColin Finck trio_printv_ref
4971c2c66affSColin Finck TRIO_ARGS3((ref, format, argarray),
4972c2c66affSColin Finck trio_pointer_t ref,
4973c2c66affSColin Finck TRIO_CONST char *format,
4974c2c66affSColin Finck trio_pointer_t *argarray)
4975c2c66affSColin Finck {
4976c2c66affSColin Finck assert(VALID(format));
4977c2c66affSColin Finck
4978c2c66affSColin Finck return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
4979c2c66affSColin Finck }
4980c2c66affSColin Finck
4981c2c66affSColin Finck #endif /* TRIO_EXTENSION */
4982c2c66affSColin Finck
4983c2c66affSColin Finck /*************************************************************************
4984c2c66affSColin Finck * trio_print_pointer [public]
4985c2c66affSColin Finck */
4986c2c66affSColin Finck void
4987c2c66affSColin Finck trio_print_pointer
4988c2c66affSColin Finck TRIO_ARGS2((ref, pointer),
4989c2c66affSColin Finck trio_pointer_t ref,
4990c2c66affSColin Finck trio_pointer_t pointer)
4991c2c66affSColin Finck {
4992c2c66affSColin Finck trio_reference_t *self = (trio_reference_t *)ref;
4993c2c66affSColin Finck trio_flags_t flags;
4994c2c66affSColin Finck trio_uintmax_t number;
4995c2c66affSColin Finck
4996c2c66affSColin Finck if (NULL == pointer)
4997c2c66affSColin Finck {
4998c2c66affSColin Finck TRIO_CONST char *string = internalNullString;
4999c2c66affSColin Finck while (*string)
5000c2c66affSColin Finck self->data->OutStream(self->data, *string++);
5001c2c66affSColin Finck }
5002c2c66affSColin Finck else
5003c2c66affSColin Finck {
5004c2c66affSColin Finck /*
5005c2c66affSColin Finck * The subtraction of the null pointer is a workaround
5006c2c66affSColin Finck * to avoid a compiler warning. The performance overhead
5007c2c66affSColin Finck * is negligible (and likely to be removed by an
5008c2c66affSColin Finck * optimizing compiler). The (char *) casting is done
5009c2c66affSColin Finck * to please ANSI C++.
5010c2c66affSColin Finck */
5011c2c66affSColin Finck number = (trio_uintmax_t)((char *)pointer - (char *)0);
5012c2c66affSColin Finck /* Shrink to size of pointer */
5013c2c66affSColin Finck number &= (trio_uintmax_t)-1;
5014c2c66affSColin Finck flags = self->parameter->flags;
5015c2c66affSColin Finck flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
5016c2c66affSColin Finck FLAGS_NILPADDING);
5017c2c66affSColin Finck TrioWriteNumber(self->data,
5018c2c66affSColin Finck number,
5019c2c66affSColin Finck flags,
5020c2c66affSColin Finck POINTER_WIDTH,
5021c2c66affSColin Finck NO_PRECISION,
5022c2c66affSColin Finck BASE_HEX);
5023c2c66affSColin Finck }
5024c2c66affSColin Finck }
5025c2c66affSColin Finck
5026c2c66affSColin Finck /** @} End of UserDefined documentation module */
5027c2c66affSColin Finck
5028c2c66affSColin Finck /*************************************************************************
5029c2c66affSColin Finck *
5030c2c66affSColin Finck * LOCALES
5031c2c66affSColin Finck *
5032c2c66affSColin Finck ************************************************************************/
5033c2c66affSColin Finck
5034c2c66affSColin Finck /*************************************************************************
5035c2c66affSColin Finck * trio_locale_set_decimal_point
5036c2c66affSColin Finck *
5037c2c66affSColin Finck * Decimal point can only be one character. The input argument is a
5038c2c66affSColin Finck * string to enable multibyte characters. At most MB_LEN_MAX characters
5039c2c66affSColin Finck * will be used.
5040c2c66affSColin Finck */
5041c2c66affSColin Finck TRIO_PUBLIC void
5042c2c66affSColin Finck trio_locale_set_decimal_point
5043c2c66affSColin Finck TRIO_ARGS1((decimalPoint),
5044c2c66affSColin Finck char *decimalPoint)
5045c2c66affSColin Finck {
5046c2c66affSColin Finck #if defined(USE_LOCALE)
5047c2c66affSColin Finck if (NULL == internalLocaleValues)
5048c2c66affSColin Finck {
5049c2c66affSColin Finck TrioSetLocale();
5050c2c66affSColin Finck }
5051c2c66affSColin Finck #endif
5052c2c66affSColin Finck internalDecimalPointLength = trio_length(decimalPoint);
5053c2c66affSColin Finck if (internalDecimalPointLength == 1)
5054c2c66affSColin Finck {
5055c2c66affSColin Finck internalDecimalPoint = *decimalPoint;
5056c2c66affSColin Finck }
5057c2c66affSColin Finck else
5058c2c66affSColin Finck {
5059c2c66affSColin Finck internalDecimalPoint = NIL;
5060c2c66affSColin Finck trio_copy_max(internalDecimalPointString,
5061c2c66affSColin Finck sizeof(internalDecimalPointString),
5062c2c66affSColin Finck decimalPoint);
5063c2c66affSColin Finck }
5064c2c66affSColin Finck }
5065c2c66affSColin Finck
5066c2c66affSColin Finck /*************************************************************************
5067c2c66affSColin Finck * trio_locale_set_thousand_separator
5068c2c66affSColin Finck *
5069c2c66affSColin Finck * See trio_locale_set_decimal_point
5070c2c66affSColin Finck */
5071c2c66affSColin Finck TRIO_PUBLIC void
5072c2c66affSColin Finck trio_locale_set_thousand_separator
5073c2c66affSColin Finck TRIO_ARGS1((thousandSeparator),
5074c2c66affSColin Finck char *thousandSeparator)
5075c2c66affSColin Finck {
5076c2c66affSColin Finck #if defined(USE_LOCALE)
5077c2c66affSColin Finck if (NULL == internalLocaleValues)
5078c2c66affSColin Finck {
5079c2c66affSColin Finck TrioSetLocale();
5080c2c66affSColin Finck }
5081c2c66affSColin Finck #endif
5082c2c66affSColin Finck trio_copy_max(internalThousandSeparator,
5083c2c66affSColin Finck sizeof(internalThousandSeparator),
5084c2c66affSColin Finck thousandSeparator);
5085c2c66affSColin Finck internalThousandSeparatorLength = trio_length(internalThousandSeparator);
5086c2c66affSColin Finck }
5087c2c66affSColin Finck
5088c2c66affSColin Finck /*************************************************************************
5089c2c66affSColin Finck * trio_locale_set_grouping
5090c2c66affSColin Finck *
5091c2c66affSColin Finck * Array of bytes. Reversed order.
5092c2c66affSColin Finck *
5093c2c66affSColin Finck * CHAR_MAX : No further grouping
5094c2c66affSColin Finck * 0 : Repeat last group for the remaining digits (not necessary
5095c2c66affSColin Finck * as C strings are zero-terminated)
5096c2c66affSColin Finck * n : Set current group to n
5097c2c66affSColin Finck *
5098c2c66affSColin Finck * Same order as the grouping attribute in LC_NUMERIC.
5099c2c66affSColin Finck */
5100c2c66affSColin Finck TRIO_PUBLIC void
5101c2c66affSColin Finck trio_locale_set_grouping
5102c2c66affSColin Finck TRIO_ARGS1((grouping),
5103c2c66affSColin Finck char *grouping)
5104c2c66affSColin Finck {
5105c2c66affSColin Finck #if defined(USE_LOCALE)
5106c2c66affSColin Finck if (NULL == internalLocaleValues)
5107c2c66affSColin Finck {
5108c2c66affSColin Finck TrioSetLocale();
5109c2c66affSColin Finck }
5110c2c66affSColin Finck #endif
5111c2c66affSColin Finck trio_copy_max(internalGrouping,
5112c2c66affSColin Finck sizeof(internalGrouping),
5113c2c66affSColin Finck grouping);
5114c2c66affSColin Finck }
5115c2c66affSColin Finck
5116c2c66affSColin Finck
5117c2c66affSColin Finck /*************************************************************************
5118c2c66affSColin Finck *
5119c2c66affSColin Finck * SCANNING
5120c2c66affSColin Finck *
5121c2c66affSColin Finck ************************************************************************/
5122c2c66affSColin Finck
5123c2c66affSColin Finck /*************************************************************************
5124c2c66affSColin Finck * TrioSkipWhitespaces
5125c2c66affSColin Finck */
5126c2c66affSColin Finck TRIO_PRIVATE int
5127c2c66affSColin Finck TrioSkipWhitespaces
5128c2c66affSColin Finck TRIO_ARGS1((self),
5129c2c66affSColin Finck trio_class_t *self)
5130c2c66affSColin Finck {
5131c2c66affSColin Finck int ch;
5132c2c66affSColin Finck
5133c2c66affSColin Finck ch = self->current;
5134c2c66affSColin Finck while (isspace(ch))
5135c2c66affSColin Finck {
5136c2c66affSColin Finck self->InStream(self, &ch);
5137c2c66affSColin Finck }
5138c2c66affSColin Finck return ch;
5139c2c66affSColin Finck }
5140c2c66affSColin Finck
5141c2c66affSColin Finck /*************************************************************************
5142c2c66affSColin Finck * TrioGetCollation
5143c2c66affSColin Finck */
5144c2c66affSColin Finck #if TRIO_EXTENSION
5145c2c66affSColin Finck TRIO_PRIVATE void
TrioGetCollation(TRIO_NOARGS)5146c2c66affSColin Finck TrioGetCollation(TRIO_NOARGS)
5147c2c66affSColin Finck {
5148c2c66affSColin Finck int i;
5149c2c66affSColin Finck int j;
5150c2c66affSColin Finck int k;
5151c2c66affSColin Finck char first[2];
5152c2c66affSColin Finck char second[2];
5153c2c66affSColin Finck
5154c2c66affSColin Finck /* This is computationally expensive */
5155c2c66affSColin Finck first[1] = NIL;
5156c2c66affSColin Finck second[1] = NIL;
5157c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5158c2c66affSColin Finck {
5159c2c66affSColin Finck k = 0;
5160c2c66affSColin Finck first[0] = (char)i;
5161c2c66affSColin Finck for (j = 0; j < MAX_CHARACTER_CLASS; j++)
5162c2c66affSColin Finck {
5163c2c66affSColin Finck second[0] = (char)j;
5164c2c66affSColin Finck if (trio_equal_locale(first, second))
5165c2c66affSColin Finck internalCollationArray[i][k++] = (char)j;
5166c2c66affSColin Finck }
5167c2c66affSColin Finck internalCollationArray[i][k] = NIL;
5168c2c66affSColin Finck }
5169c2c66affSColin Finck }
5170c2c66affSColin Finck #endif
5171c2c66affSColin Finck
5172c2c66affSColin Finck /*************************************************************************
5173c2c66affSColin Finck * TrioGetCharacterClass
5174c2c66affSColin Finck *
5175c2c66affSColin Finck * FIXME:
5176c2c66affSColin Finck * multibyte
5177c2c66affSColin Finck */
5178c2c66affSColin Finck TRIO_PRIVATE int
5179c2c66affSColin Finck TrioGetCharacterClass
5180c2c66affSColin Finck TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
5181c2c66affSColin Finck TRIO_CONST char *format,
5182c2c66affSColin Finck int *indexPointer,
5183c2c66affSColin Finck trio_flags_t *flagsPointer,
5184c2c66affSColin Finck int *characterclass)
5185c2c66affSColin Finck {
5186c2c66affSColin Finck int index = *indexPointer;
5187c2c66affSColin Finck int i;
5188c2c66affSColin Finck char ch;
5189c2c66affSColin Finck char range_begin;
5190c2c66affSColin Finck char range_end;
5191c2c66affSColin Finck
5192c2c66affSColin Finck *flagsPointer &= ~FLAGS_EXCLUDE;
5193c2c66affSColin Finck
5194c2c66affSColin Finck if (format[index] == QUALIFIER_CIRCUMFLEX)
5195c2c66affSColin Finck {
5196c2c66affSColin Finck *flagsPointer |= FLAGS_EXCLUDE;
5197c2c66affSColin Finck index++;
5198c2c66affSColin Finck }
5199c2c66affSColin Finck /*
5200c2c66affSColin Finck * If the ungroup character is at the beginning of the scanlist,
5201c2c66affSColin Finck * it will be part of the class, and a second ungroup character
5202c2c66affSColin Finck * must follow to end the group.
5203c2c66affSColin Finck */
5204c2c66affSColin Finck if (format[index] == SPECIFIER_UNGROUP)
5205c2c66affSColin Finck {
5206c2c66affSColin Finck characterclass[(int)SPECIFIER_UNGROUP]++;
5207c2c66affSColin Finck index++;
5208c2c66affSColin Finck }
5209c2c66affSColin Finck /*
5210c2c66affSColin Finck * Minus is used to specify ranges. To include minus in the class,
5211c2c66affSColin Finck * it must be at the beginning of the list
5212c2c66affSColin Finck */
5213c2c66affSColin Finck if (format[index] == QUALIFIER_MINUS)
5214c2c66affSColin Finck {
5215c2c66affSColin Finck characterclass[(int)QUALIFIER_MINUS]++;
5216c2c66affSColin Finck index++;
5217c2c66affSColin Finck }
5218c2c66affSColin Finck /* Collect characters */
5219c2c66affSColin Finck for (ch = format[index];
5220c2c66affSColin Finck (ch != SPECIFIER_UNGROUP) && (ch != NIL);
5221c2c66affSColin Finck ch = format[++index])
5222c2c66affSColin Finck {
5223c2c66affSColin Finck switch (ch)
5224c2c66affSColin Finck {
5225c2c66affSColin Finck case QUALIFIER_MINUS: /* Scanlist ranges */
5226c2c66affSColin Finck
5227c2c66affSColin Finck /*
5228c2c66affSColin Finck * Both C99 and UNIX98 describes ranges as implementation-
5229c2c66affSColin Finck * defined.
5230c2c66affSColin Finck *
5231c2c66affSColin Finck * We support the following behaviour (although this may
5232c2c66affSColin Finck * change as we become wiser)
5233c2c66affSColin Finck * - only increasing ranges, ie. [a-b] but not [b-a]
5234c2c66affSColin Finck * - transitive ranges, ie. [a-b-c] == [a-c]
5235c2c66affSColin Finck * - trailing minus, ie. [a-] is interpreted as an 'a'
5236c2c66affSColin Finck * and a '-'
5237c2c66affSColin Finck * - duplicates (although we can easily convert these
5238c2c66affSColin Finck * into errors)
5239c2c66affSColin Finck */
5240c2c66affSColin Finck range_begin = format[index - 1];
5241c2c66affSColin Finck range_end = format[++index];
5242c2c66affSColin Finck if (range_end == SPECIFIER_UNGROUP)
5243c2c66affSColin Finck {
5244c2c66affSColin Finck /* Trailing minus is included */
5245c2c66affSColin Finck characterclass[(int)ch]++;
5246c2c66affSColin Finck ch = range_end;
5247c2c66affSColin Finck break; /* for */
5248c2c66affSColin Finck }
5249c2c66affSColin Finck if (range_end == NIL)
5250c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
5251c2c66affSColin Finck if (range_begin > range_end)
5252c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_ERANGE, index);
5253c2c66affSColin Finck
5254c2c66affSColin Finck for (i = (int)range_begin; i <= (int)range_end; i++)
5255c2c66affSColin Finck characterclass[i]++;
5256c2c66affSColin Finck
5257c2c66affSColin Finck ch = range_end;
5258c2c66affSColin Finck break;
5259c2c66affSColin Finck
5260c2c66affSColin Finck #if TRIO_EXTENSION
5261c2c66affSColin Finck
5262c2c66affSColin Finck case SPECIFIER_GROUP:
5263c2c66affSColin Finck
5264c2c66affSColin Finck switch (format[index + 1])
5265c2c66affSColin Finck {
5266c2c66affSColin Finck case QUALIFIER_DOT: /* Collating symbol */
5267c2c66affSColin Finck /*
5268c2c66affSColin Finck * FIXME: This will be easier to implement when multibyte
5269c2c66affSColin Finck * characters have been implemented. Until now, we ignore
5270c2c66affSColin Finck * this feature.
5271c2c66affSColin Finck */
5272c2c66affSColin Finck for (i = index + 2; ; i++)
5273c2c66affSColin Finck {
5274c2c66affSColin Finck if (format[i] == NIL)
5275c2c66affSColin Finck /* Error in syntax */
5276c2c66affSColin Finck return -1;
5277c2c66affSColin Finck else if (format[i] == QUALIFIER_DOT)
5278c2c66affSColin Finck break; /* for */
5279c2c66affSColin Finck }
5280c2c66affSColin Finck if (format[++i] != SPECIFIER_UNGROUP)
5281c2c66affSColin Finck return -1;
5282c2c66affSColin Finck
5283c2c66affSColin Finck index = i;
5284c2c66affSColin Finck break;
5285c2c66affSColin Finck
5286c2c66affSColin Finck case QUALIFIER_EQUAL: /* Equivalence class expressions */
5287c2c66affSColin Finck {
5288c2c66affSColin Finck unsigned int j;
5289c2c66affSColin Finck unsigned int k;
5290c2c66affSColin Finck
5291c2c66affSColin Finck if (internalCollationUnconverted)
5292c2c66affSColin Finck {
5293c2c66affSColin Finck /* Lazy evaluation of collation array */
5294c2c66affSColin Finck TrioGetCollation();
5295c2c66affSColin Finck internalCollationUnconverted = FALSE;
5296c2c66affSColin Finck }
5297c2c66affSColin Finck for (i = index + 2; ; i++)
5298c2c66affSColin Finck {
5299c2c66affSColin Finck if (format[i] == NIL)
5300c2c66affSColin Finck /* Error in syntax */
5301c2c66affSColin Finck return -1;
5302c2c66affSColin Finck else if (format[i] == QUALIFIER_EQUAL)
5303c2c66affSColin Finck break; /* for */
5304c2c66affSColin Finck else
5305c2c66affSColin Finck {
5306c2c66affSColin Finck /* Mark any equivalent character */
5307c2c66affSColin Finck k = (unsigned int)format[i];
5308c2c66affSColin Finck for (j = 0; internalCollationArray[k][j] != NIL; j++)
5309c2c66affSColin Finck characterclass[(int)internalCollationArray[k][j]]++;
5310c2c66affSColin Finck }
5311c2c66affSColin Finck }
5312c2c66affSColin Finck if (format[++i] != SPECIFIER_UNGROUP)
5313c2c66affSColin Finck return -1;
5314c2c66affSColin Finck
5315c2c66affSColin Finck index = i;
5316c2c66affSColin Finck }
5317c2c66affSColin Finck break;
5318c2c66affSColin Finck
5319c2c66affSColin Finck case QUALIFIER_COLON: /* Character class expressions */
5320c2c66affSColin Finck
5321c2c66affSColin Finck if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
5322c2c66affSColin Finck &format[index]))
5323c2c66affSColin Finck {
5324c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5325c2c66affSColin Finck if (isalnum(i))
5326c2c66affSColin Finck characterclass[i]++;
5327c2c66affSColin Finck index += sizeof(CLASS_ALNUM) - 1;
5328c2c66affSColin Finck }
5329c2c66affSColin Finck else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
5330c2c66affSColin Finck &format[index]))
5331c2c66affSColin Finck {
5332c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5333c2c66affSColin Finck if (isalpha(i))
5334c2c66affSColin Finck characterclass[i]++;
5335c2c66affSColin Finck index += sizeof(CLASS_ALPHA) - 1;
5336c2c66affSColin Finck }
5337c2c66affSColin Finck else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
5338c2c66affSColin Finck &format[index]))
5339c2c66affSColin Finck {
5340c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5341c2c66affSColin Finck if (iscntrl(i))
5342c2c66affSColin Finck characterclass[i]++;
5343c2c66affSColin Finck index += sizeof(CLASS_CNTRL) - 1;
5344c2c66affSColin Finck }
5345c2c66affSColin Finck else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
5346c2c66affSColin Finck &format[index]))
5347c2c66affSColin Finck {
5348c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5349c2c66affSColin Finck if (isdigit(i))
5350c2c66affSColin Finck characterclass[i]++;
5351c2c66affSColin Finck index += sizeof(CLASS_DIGIT) - 1;
5352c2c66affSColin Finck }
5353c2c66affSColin Finck else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
5354c2c66affSColin Finck &format[index]))
5355c2c66affSColin Finck {
5356c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5357c2c66affSColin Finck if (isgraph(i))
5358c2c66affSColin Finck characterclass[i]++;
5359c2c66affSColin Finck index += sizeof(CLASS_GRAPH) - 1;
5360c2c66affSColin Finck }
5361c2c66affSColin Finck else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
5362c2c66affSColin Finck &format[index]))
5363c2c66affSColin Finck {
5364c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5365c2c66affSColin Finck if (islower(i))
5366c2c66affSColin Finck characterclass[i]++;
5367c2c66affSColin Finck index += sizeof(CLASS_LOWER) - 1;
5368c2c66affSColin Finck }
5369c2c66affSColin Finck else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
5370c2c66affSColin Finck &format[index]))
5371c2c66affSColin Finck {
5372c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5373c2c66affSColin Finck if (isprint(i))
5374c2c66affSColin Finck characterclass[i]++;
5375c2c66affSColin Finck index += sizeof(CLASS_PRINT) - 1;
5376c2c66affSColin Finck }
5377c2c66affSColin Finck else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
5378c2c66affSColin Finck &format[index]))
5379c2c66affSColin Finck {
5380c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5381c2c66affSColin Finck if (ispunct(i))
5382c2c66affSColin Finck characterclass[i]++;
5383c2c66affSColin Finck index += sizeof(CLASS_PUNCT) - 1;
5384c2c66affSColin Finck }
5385c2c66affSColin Finck else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
5386c2c66affSColin Finck &format[index]))
5387c2c66affSColin Finck {
5388c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5389c2c66affSColin Finck if (isspace(i))
5390c2c66affSColin Finck characterclass[i]++;
5391c2c66affSColin Finck index += sizeof(CLASS_SPACE) - 1;
5392c2c66affSColin Finck }
5393c2c66affSColin Finck else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
5394c2c66affSColin Finck &format[index]))
5395c2c66affSColin Finck {
5396c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5397c2c66affSColin Finck if (isupper(i))
5398c2c66affSColin Finck characterclass[i]++;
5399c2c66affSColin Finck index += sizeof(CLASS_UPPER) - 1;
5400c2c66affSColin Finck }
5401c2c66affSColin Finck else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
5402c2c66affSColin Finck &format[index]))
5403c2c66affSColin Finck {
5404c2c66affSColin Finck for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5405c2c66affSColin Finck if (isxdigit(i))
5406c2c66affSColin Finck characterclass[i]++;
5407c2c66affSColin Finck index += sizeof(CLASS_XDIGIT) - 1;
5408c2c66affSColin Finck }
5409c2c66affSColin Finck else
5410c2c66affSColin Finck {
5411c2c66affSColin Finck characterclass[(int)ch]++;
5412c2c66affSColin Finck }
5413c2c66affSColin Finck break;
5414c2c66affSColin Finck
5415c2c66affSColin Finck default:
5416c2c66affSColin Finck characterclass[(int)ch]++;
5417c2c66affSColin Finck break;
5418c2c66affSColin Finck }
5419c2c66affSColin Finck break;
5420c2c66affSColin Finck
5421c2c66affSColin Finck #endif /* TRIO_EXTENSION */
5422c2c66affSColin Finck
5423c2c66affSColin Finck default:
5424c2c66affSColin Finck characterclass[(int)ch]++;
5425c2c66affSColin Finck break;
5426c2c66affSColin Finck }
5427c2c66affSColin Finck }
5428c2c66affSColin Finck return 0;
5429c2c66affSColin Finck }
5430c2c66affSColin Finck
5431c2c66affSColin Finck /*************************************************************************
5432c2c66affSColin Finck * TrioReadNumber
5433c2c66affSColin Finck *
5434c2c66affSColin Finck * We implement our own number conversion in preference of strtol and
5435c2c66affSColin Finck * strtoul, because we must handle 'long long' and thousand separators.
5436c2c66affSColin Finck */
5437c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
5438c2c66affSColin Finck TrioReadNumber
5439c2c66affSColin Finck TRIO_ARGS5((self, target, flags, width, base),
5440c2c66affSColin Finck trio_class_t *self,
5441c2c66affSColin Finck trio_uintmax_t *target,
5442c2c66affSColin Finck trio_flags_t flags,
5443c2c66affSColin Finck int width,
5444c2c66affSColin Finck int base)
5445c2c66affSColin Finck {
5446c2c66affSColin Finck trio_uintmax_t number = 0;
5447c2c66affSColin Finck int digit;
5448c2c66affSColin Finck int count;
5449c2c66affSColin Finck BOOLEAN_T isNegative = FALSE;
5450c2c66affSColin Finck BOOLEAN_T gotNumber = FALSE;
5451c2c66affSColin Finck int j;
5452c2c66affSColin Finck
5453c2c66affSColin Finck assert(VALID(self));
5454c2c66affSColin Finck assert(VALID(self->InStream));
5455c2c66affSColin Finck assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE));
5456c2c66affSColin Finck
5457c2c66affSColin Finck if (internalDigitsUnconverted)
5458c2c66affSColin Finck {
5459c2c66affSColin Finck /* Lazy evaluation of digits array */
5460c2c66affSColin Finck memset(internalDigitArray, -1, sizeof(internalDigitArray));
5461c2c66affSColin Finck for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++)
5462c2c66affSColin Finck {
5463c2c66affSColin Finck internalDigitArray[(int)internalDigitsLower[j]] = j;
5464c2c66affSColin Finck internalDigitArray[(int)internalDigitsUpper[j]] = j;
5465c2c66affSColin Finck }
5466c2c66affSColin Finck internalDigitsUnconverted = FALSE;
5467c2c66affSColin Finck }
5468c2c66affSColin Finck
5469c2c66affSColin Finck TrioSkipWhitespaces(self);
5470c2c66affSColin Finck
5471c2c66affSColin Finck if (!(flags & FLAGS_UNSIGNED))
5472c2c66affSColin Finck {
5473c2c66affSColin Finck /* Leading sign */
5474c2c66affSColin Finck if (self->current == '+')
5475c2c66affSColin Finck {
5476c2c66affSColin Finck self->InStream(self, NULL);
5477c2c66affSColin Finck }
5478c2c66affSColin Finck else if (self->current == '-')
5479c2c66affSColin Finck {
5480c2c66affSColin Finck self->InStream(self, NULL);
5481c2c66affSColin Finck isNegative = TRUE;
5482c2c66affSColin Finck }
5483c2c66affSColin Finck }
5484c2c66affSColin Finck
5485c2c66affSColin Finck count = self->processed;
5486c2c66affSColin Finck
5487c2c66affSColin Finck if (flags & FLAGS_ALTERNATIVE)
5488c2c66affSColin Finck {
5489c2c66affSColin Finck switch (base)
5490c2c66affSColin Finck {
5491c2c66affSColin Finck case NO_BASE:
5492c2c66affSColin Finck case BASE_OCTAL:
5493c2c66affSColin Finck case BASE_HEX:
5494c2c66affSColin Finck case BASE_BINARY:
5495c2c66affSColin Finck if (self->current == '0')
5496c2c66affSColin Finck {
5497c2c66affSColin Finck self->InStream(self, NULL);
5498c2c66affSColin Finck if (self->current)
5499c2c66affSColin Finck {
5500c2c66affSColin Finck if ((base == BASE_HEX) &&
5501c2c66affSColin Finck (trio_to_upper(self->current) == 'X'))
5502c2c66affSColin Finck {
5503c2c66affSColin Finck self->InStream(self, NULL);
5504c2c66affSColin Finck }
5505c2c66affSColin Finck else if ((base == BASE_BINARY) &&
5506c2c66affSColin Finck (trio_to_upper(self->current) == 'B'))
5507c2c66affSColin Finck {
5508c2c66affSColin Finck self->InStream(self, NULL);
5509c2c66affSColin Finck }
5510c2c66affSColin Finck }
5511c2c66affSColin Finck }
5512c2c66affSColin Finck else
5513c2c66affSColin Finck return FALSE;
5514c2c66affSColin Finck break;
5515c2c66affSColin Finck default:
5516c2c66affSColin Finck break;
5517c2c66affSColin Finck }
5518c2c66affSColin Finck }
5519c2c66affSColin Finck
5520c2c66affSColin Finck while (((width == NO_WIDTH) || (self->processed - count < width)) &&
5521c2c66affSColin Finck (! ((self->current == EOF) || isspace(self->current))))
5522c2c66affSColin Finck {
5523c2c66affSColin Finck if (isascii(self->current))
5524c2c66affSColin Finck {
5525c2c66affSColin Finck digit = internalDigitArray[self->current];
5526c2c66affSColin Finck /* Abort if digit is not allowed in the specified base */
5527c2c66affSColin Finck if ((digit == -1) || (digit >= base))
5528c2c66affSColin Finck break;
5529c2c66affSColin Finck }
5530c2c66affSColin Finck else if (flags & FLAGS_QUOTE)
5531c2c66affSColin Finck {
5532c2c66affSColin Finck /* Compare with thousands separator */
5533c2c66affSColin Finck for (j = 0; internalThousandSeparator[j] && self->current; j++)
5534c2c66affSColin Finck {
5535c2c66affSColin Finck if (internalThousandSeparator[j] != self->current)
5536c2c66affSColin Finck break;
5537c2c66affSColin Finck
5538c2c66affSColin Finck self->InStream(self, NULL);
5539c2c66affSColin Finck }
5540c2c66affSColin Finck if (internalThousandSeparator[j])
5541c2c66affSColin Finck break; /* Mismatch */
5542c2c66affSColin Finck else
5543c2c66affSColin Finck continue; /* Match */
5544c2c66affSColin Finck }
5545c2c66affSColin Finck else
5546c2c66affSColin Finck break;
5547c2c66affSColin Finck
5548c2c66affSColin Finck number *= base;
5549c2c66affSColin Finck number += digit;
5550c2c66affSColin Finck gotNumber = TRUE; /* we need at least one digit */
5551c2c66affSColin Finck
5552c2c66affSColin Finck self->InStream(self, NULL);
5553c2c66affSColin Finck }
5554c2c66affSColin Finck
5555c2c66affSColin Finck /* Was anything read at all? */
5556c2c66affSColin Finck if (!gotNumber)
5557c2c66affSColin Finck return FALSE;
5558c2c66affSColin Finck
5559c2c66affSColin Finck if (target)
5560c2c66affSColin Finck *target = (isNegative) ? -((trio_intmax_t)number) : number;
5561c2c66affSColin Finck return TRUE;
5562c2c66affSColin Finck }
5563c2c66affSColin Finck
5564c2c66affSColin Finck /*************************************************************************
5565c2c66affSColin Finck * TrioReadChar
5566c2c66affSColin Finck */
5567c2c66affSColin Finck TRIO_PRIVATE int
5568c2c66affSColin Finck TrioReadChar
5569c2c66affSColin Finck TRIO_ARGS4((self, target, flags, width),
5570c2c66affSColin Finck trio_class_t *self,
5571c2c66affSColin Finck char *target,
5572c2c66affSColin Finck trio_flags_t flags,
5573c2c66affSColin Finck int width)
5574c2c66affSColin Finck {
5575c2c66affSColin Finck int i;
5576c2c66affSColin Finck char ch;
5577c2c66affSColin Finck trio_uintmax_t number;
5578c2c66affSColin Finck
5579c2c66affSColin Finck assert(VALID(self));
5580c2c66affSColin Finck assert(VALID(self->InStream));
5581c2c66affSColin Finck
5582c2c66affSColin Finck for (i = 0;
5583c2c66affSColin Finck (self->current != EOF) && (i < width);
5584c2c66affSColin Finck i++)
5585c2c66affSColin Finck {
5586c2c66affSColin Finck ch = (char)self->current;
5587c2c66affSColin Finck self->InStream(self, NULL);
5588c2c66affSColin Finck if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
5589c2c66affSColin Finck {
5590c2c66affSColin Finck switch (self->current)
5591c2c66affSColin Finck {
5592c2c66affSColin Finck case '\\': ch = '\\'; break;
5593c2c66affSColin Finck case 'a': ch = '\007'; break;
5594c2c66affSColin Finck case 'b': ch = '\b'; break;
5595c2c66affSColin Finck case 'f': ch = '\f'; break;
5596c2c66affSColin Finck case 'n': ch = '\n'; break;
5597c2c66affSColin Finck case 'r': ch = '\r'; break;
5598c2c66affSColin Finck case 't': ch = '\t'; break;
5599c2c66affSColin Finck case 'v': ch = '\v'; break;
5600c2c66affSColin Finck default:
5601c2c66affSColin Finck if (isdigit(self->current))
5602c2c66affSColin Finck {
5603c2c66affSColin Finck /* Read octal number */
5604c2c66affSColin Finck if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
5605c2c66affSColin Finck return 0;
5606c2c66affSColin Finck ch = (char)number;
5607c2c66affSColin Finck }
5608c2c66affSColin Finck else if (trio_to_upper(self->current) == 'X')
5609c2c66affSColin Finck {
5610c2c66affSColin Finck /* Read hexadecimal number */
5611c2c66affSColin Finck self->InStream(self, NULL);
5612c2c66affSColin Finck if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
5613c2c66affSColin Finck return 0;
5614c2c66affSColin Finck ch = (char)number;
5615c2c66affSColin Finck }
5616c2c66affSColin Finck else
5617c2c66affSColin Finck {
5618c2c66affSColin Finck ch = (char)self->current;
5619c2c66affSColin Finck }
5620c2c66affSColin Finck break;
5621c2c66affSColin Finck }
5622c2c66affSColin Finck }
5623c2c66affSColin Finck
5624c2c66affSColin Finck if (target)
5625c2c66affSColin Finck target[i] = ch;
5626c2c66affSColin Finck }
5627c2c66affSColin Finck return i + 1;
5628c2c66affSColin Finck }
5629c2c66affSColin Finck
5630c2c66affSColin Finck /*************************************************************************
5631c2c66affSColin Finck * TrioReadString
5632c2c66affSColin Finck */
5633c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
5634c2c66affSColin Finck TrioReadString
5635c2c66affSColin Finck TRIO_ARGS4((self, target, flags, width),
5636c2c66affSColin Finck trio_class_t *self,
5637c2c66affSColin Finck char *target,
5638c2c66affSColin Finck trio_flags_t flags,
5639c2c66affSColin Finck int width)
5640c2c66affSColin Finck {
5641c2c66affSColin Finck int i;
5642c2c66affSColin Finck
5643c2c66affSColin Finck assert(VALID(self));
5644c2c66affSColin Finck assert(VALID(self->InStream));
5645c2c66affSColin Finck
5646c2c66affSColin Finck TrioSkipWhitespaces(self);
5647c2c66affSColin Finck
5648c2c66affSColin Finck /*
5649c2c66affSColin Finck * Continue until end of string is reached, a whitespace is encountered,
5650c2c66affSColin Finck * or width is exceeded
5651c2c66affSColin Finck */
5652c2c66affSColin Finck for (i = 0;
5653c2c66affSColin Finck ((width == NO_WIDTH) || (i < width)) &&
5654c2c66affSColin Finck (! ((self->current == EOF) || isspace(self->current)));
5655c2c66affSColin Finck i++)
5656c2c66affSColin Finck {
5657c2c66affSColin Finck if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0)
5658c2c66affSColin Finck break; /* for */
5659c2c66affSColin Finck }
5660c2c66affSColin Finck if (target)
5661c2c66affSColin Finck target[i] = NIL;
5662c2c66affSColin Finck return TRUE;
5663c2c66affSColin Finck }
5664c2c66affSColin Finck
5665c2c66affSColin Finck /*************************************************************************
5666c2c66affSColin Finck * TrioReadWideChar
5667c2c66affSColin Finck */
5668c2c66affSColin Finck #if TRIO_WIDECHAR
5669c2c66affSColin Finck TRIO_PRIVATE int
5670c2c66affSColin Finck TrioReadWideChar
5671c2c66affSColin Finck TRIO_ARGS4((self, target, flags, width),
5672c2c66affSColin Finck trio_class_t *self,
5673c2c66affSColin Finck trio_wchar_t *target,
5674c2c66affSColin Finck trio_flags_t flags,
5675c2c66affSColin Finck int width)
5676c2c66affSColin Finck {
5677c2c66affSColin Finck int i;
5678c2c66affSColin Finck int j;
5679c2c66affSColin Finck int size;
5680c2c66affSColin Finck int amount = 0;
5681c2c66affSColin Finck trio_wchar_t wch;
5682c2c66affSColin Finck char buffer[MB_LEN_MAX + 1];
5683c2c66affSColin Finck
5684c2c66affSColin Finck assert(VALID(self));
5685c2c66affSColin Finck assert(VALID(self->InStream));
5686c2c66affSColin Finck
5687c2c66affSColin Finck for (i = 0;
5688c2c66affSColin Finck (self->current != EOF) && (i < width);
5689c2c66affSColin Finck i++)
5690c2c66affSColin Finck {
5691c2c66affSColin Finck if (isascii(self->current))
5692c2c66affSColin Finck {
5693c2c66affSColin Finck if (TrioReadChar(self, buffer, flags, 1) == 0)
5694c2c66affSColin Finck return 0;
5695c2c66affSColin Finck buffer[1] = NIL;
5696c2c66affSColin Finck }
5697c2c66affSColin Finck else
5698c2c66affSColin Finck {
5699c2c66affSColin Finck /*
5700c2c66affSColin Finck * Collect a multibyte character, by enlarging buffer until
5701c2c66affSColin Finck * it contains a fully legal multibyte character, or the
5702c2c66affSColin Finck * buffer is full.
5703c2c66affSColin Finck */
5704c2c66affSColin Finck j = 0;
5705c2c66affSColin Finck do
5706c2c66affSColin Finck {
5707c2c66affSColin Finck buffer[j++] = (char)self->current;
5708c2c66affSColin Finck buffer[j] = NIL;
5709c2c66affSColin Finck self->InStream(self, NULL);
5710c2c66affSColin Finck }
5711c2c66affSColin Finck while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j));
5712c2c66affSColin Finck }
5713c2c66affSColin Finck if (target)
5714c2c66affSColin Finck {
5715c2c66affSColin Finck size = mbtowc(&wch, buffer, sizeof(buffer));
5716c2c66affSColin Finck if (size > 0)
5717c2c66affSColin Finck target[i] = wch;
5718c2c66affSColin Finck }
5719c2c66affSColin Finck amount += size;
5720c2c66affSColin Finck self->InStream(self, NULL);
5721c2c66affSColin Finck }
5722c2c66affSColin Finck return amount;
5723c2c66affSColin Finck }
5724c2c66affSColin Finck #endif /* TRIO_WIDECHAR */
5725c2c66affSColin Finck
5726c2c66affSColin Finck /*************************************************************************
5727c2c66affSColin Finck * TrioReadWideString
5728c2c66affSColin Finck */
5729c2c66affSColin Finck #if TRIO_WIDECHAR
5730c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
5731c2c66affSColin Finck TrioReadWideString
5732c2c66affSColin Finck TRIO_ARGS4((self, target, flags, width),
5733c2c66affSColin Finck trio_class_t *self,
5734c2c66affSColin Finck trio_wchar_t *target,
5735c2c66affSColin Finck trio_flags_t flags,
5736c2c66affSColin Finck int width)
5737c2c66affSColin Finck {
5738c2c66affSColin Finck int i;
5739c2c66affSColin Finck int size;
5740c2c66affSColin Finck
5741c2c66affSColin Finck assert(VALID(self));
5742c2c66affSColin Finck assert(VALID(self->InStream));
5743c2c66affSColin Finck
5744c2c66affSColin Finck TrioSkipWhitespaces(self);
5745c2c66affSColin Finck
5746c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
5747c2c66affSColin Finck (void)mblen(NULL, 0);
5748c2c66affSColin Finck #endif
5749c2c66affSColin Finck
5750c2c66affSColin Finck /*
5751c2c66affSColin Finck * Continue until end of string is reached, a whitespace is encountered,
5752c2c66affSColin Finck * or width is exceeded
5753c2c66affSColin Finck */
5754c2c66affSColin Finck for (i = 0;
5755c2c66affSColin Finck ((width == NO_WIDTH) || (i < width)) &&
5756c2c66affSColin Finck (! ((self->current == EOF) || isspace(self->current)));
5757c2c66affSColin Finck )
5758c2c66affSColin Finck {
5759c2c66affSColin Finck size = TrioReadWideChar(self, &target[i], flags, 1);
5760c2c66affSColin Finck if (size == 0)
5761c2c66affSColin Finck break; /* for */
5762c2c66affSColin Finck
5763c2c66affSColin Finck i += size;
5764c2c66affSColin Finck }
5765c2c66affSColin Finck if (target)
5766c2c66affSColin Finck target[i] = WCONST('\0');
5767c2c66affSColin Finck return TRUE;
5768c2c66affSColin Finck }
5769c2c66affSColin Finck #endif /* TRIO_WIDECHAR */
5770c2c66affSColin Finck
5771c2c66affSColin Finck /*************************************************************************
5772c2c66affSColin Finck * TrioReadGroup
5773c2c66affSColin Finck *
5774c2c66affSColin Finck * FIXME: characterclass does not work with multibyte characters
5775c2c66affSColin Finck */
5776c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
5777c2c66affSColin Finck TrioReadGroup
5778c2c66affSColin Finck TRIO_ARGS5((self, target, characterclass, flags, width),
5779c2c66affSColin Finck trio_class_t *self,
5780c2c66affSColin Finck char *target,
5781c2c66affSColin Finck int *characterclass,
5782c2c66affSColin Finck trio_flags_t flags,
5783c2c66affSColin Finck int width)
5784c2c66affSColin Finck {
5785c2c66affSColin Finck int ch;
5786c2c66affSColin Finck int i;
5787c2c66affSColin Finck
5788c2c66affSColin Finck assert(VALID(self));
5789c2c66affSColin Finck assert(VALID(self->InStream));
5790c2c66affSColin Finck
5791c2c66affSColin Finck ch = self->current;
5792c2c66affSColin Finck for (i = 0;
5793c2c66affSColin Finck ((width == NO_WIDTH) || (i < width)) &&
5794c2c66affSColin Finck (! ((ch == EOF) ||
5795c2c66affSColin Finck (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0))));
5796c2c66affSColin Finck i++)
5797c2c66affSColin Finck {
5798c2c66affSColin Finck if (target)
5799c2c66affSColin Finck target[i] = (char)ch;
5800c2c66affSColin Finck self->InStream(self, &ch);
5801c2c66affSColin Finck }
5802c2c66affSColin Finck
5803c2c66affSColin Finck if (target)
5804c2c66affSColin Finck target[i] = NIL;
5805c2c66affSColin Finck return TRUE;
5806c2c66affSColin Finck }
5807c2c66affSColin Finck
5808c2c66affSColin Finck /*************************************************************************
5809c2c66affSColin Finck * TrioReadDouble
5810c2c66affSColin Finck *
5811c2c66affSColin Finck * FIXME:
5812c2c66affSColin Finck * add long double
5813c2c66affSColin Finck * handle base
5814c2c66affSColin Finck */
5815c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
5816c2c66affSColin Finck TrioReadDouble
5817c2c66affSColin Finck TRIO_ARGS4((self, target, flags, width),
5818c2c66affSColin Finck trio_class_t *self,
5819c2c66affSColin Finck trio_pointer_t target,
5820c2c66affSColin Finck trio_flags_t flags,
5821c2c66affSColin Finck int width)
5822c2c66affSColin Finck {
5823c2c66affSColin Finck int ch;
5824c2c66affSColin Finck char doubleString[512];
5825c2c66affSColin Finck int index = 0;
5826c2c66affSColin Finck int start;
5827c2c66affSColin Finck int j;
5828c2c66affSColin Finck BOOLEAN_T isHex = FALSE;
5829c2c66affSColin Finck
5830c2c66affSColin Finck doubleString[0] = 0;
5831c2c66affSColin Finck
5832c2c66affSColin Finck if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
5833c2c66affSColin Finck width = sizeof(doubleString) - 1;
5834c2c66affSColin Finck
5835c2c66affSColin Finck TrioSkipWhitespaces(self);
5836c2c66affSColin Finck
5837c2c66affSColin Finck /*
5838c2c66affSColin Finck * Read entire double number from stream. trio_to_double requires
5839c2c66affSColin Finck * a string as input, but InStream can be anything, so we have to
5840c2c66affSColin Finck * collect all characters.
5841c2c66affSColin Finck */
5842c2c66affSColin Finck ch = self->current;
5843c2c66affSColin Finck if ((ch == '+') || (ch == '-'))
5844c2c66affSColin Finck {
5845c2c66affSColin Finck doubleString[index++] = (char)ch;
5846c2c66affSColin Finck self->InStream(self, &ch);
5847c2c66affSColin Finck width--;
5848c2c66affSColin Finck }
5849c2c66affSColin Finck
5850c2c66affSColin Finck start = index;
5851c2c66affSColin Finck switch (ch)
5852c2c66affSColin Finck {
5853c2c66affSColin Finck case 'n':
5854c2c66affSColin Finck case 'N':
5855c2c66affSColin Finck /* Not-a-number */
5856c2c66affSColin Finck if (index != 0)
5857c2c66affSColin Finck break;
5858c2c66affSColin Finck /* FALLTHROUGH */
5859c2c66affSColin Finck case 'i':
5860c2c66affSColin Finck case 'I':
5861c2c66affSColin Finck /* Infinity */
5862c2c66affSColin Finck while (isalpha(ch) && (index - start < width))
5863c2c66affSColin Finck {
5864c2c66affSColin Finck doubleString[index++] = (char)ch;
5865c2c66affSColin Finck self->InStream(self, &ch);
5866c2c66affSColin Finck }
5867c2c66affSColin Finck doubleString[index] = NIL;
5868c2c66affSColin Finck
5869c2c66affSColin Finck /* Case insensitive string comparison */
5870c2c66affSColin Finck if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
5871c2c66affSColin Finck trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
5872c2c66affSColin Finck {
5873c2c66affSColin Finck if (flags & FLAGS_LONGDOUBLE)
5874c2c66affSColin Finck {
5875c2c66affSColin Finck if ((start == 1) && (doubleString[0] == '-'))
5876c2c66affSColin Finck {
5877c2c66affSColin Finck *((trio_long_double_t *)target) = trio_ninf();
5878c2c66affSColin Finck }
5879c2c66affSColin Finck else
5880c2c66affSColin Finck {
5881c2c66affSColin Finck *((trio_long_double_t *)target) = trio_pinf();
5882c2c66affSColin Finck }
5883c2c66affSColin Finck }
5884c2c66affSColin Finck else
5885c2c66affSColin Finck {
5886c2c66affSColin Finck if ((start == 1) && (doubleString[0] == '-'))
5887c2c66affSColin Finck {
5888c2c66affSColin Finck *((double *)target) = trio_ninf();
5889c2c66affSColin Finck }
5890c2c66affSColin Finck else
5891c2c66affSColin Finck {
5892c2c66affSColin Finck *((double *)target) = trio_pinf();
5893c2c66affSColin Finck }
5894c2c66affSColin Finck }
5895c2c66affSColin Finck return TRUE;
5896c2c66affSColin Finck }
5897c2c66affSColin Finck if (trio_equal(doubleString, NAN_UPPER))
5898c2c66affSColin Finck {
5899f22fa382SThomas Faber /* NaN must not have a preceding + nor - */
5900c2c66affSColin Finck if (flags & FLAGS_LONGDOUBLE)
5901c2c66affSColin Finck {
5902c2c66affSColin Finck *((trio_long_double_t *)target) = trio_nan();
5903c2c66affSColin Finck }
5904c2c66affSColin Finck else
5905c2c66affSColin Finck {
5906c2c66affSColin Finck *((double *)target) = trio_nan();
5907c2c66affSColin Finck }
5908c2c66affSColin Finck return TRUE;
5909c2c66affSColin Finck }
5910c2c66affSColin Finck return FALSE;
5911c2c66affSColin Finck
5912c2c66affSColin Finck case '0':
5913c2c66affSColin Finck doubleString[index++] = (char)ch;
5914c2c66affSColin Finck self->InStream(self, &ch);
5915c2c66affSColin Finck if (trio_to_upper(ch) == 'X')
5916c2c66affSColin Finck {
5917c2c66affSColin Finck isHex = TRUE;
5918c2c66affSColin Finck doubleString[index++] = (char)ch;
5919c2c66affSColin Finck self->InStream(self, &ch);
5920c2c66affSColin Finck }
5921c2c66affSColin Finck break;
5922c2c66affSColin Finck
5923c2c66affSColin Finck default:
5924c2c66affSColin Finck break;
5925c2c66affSColin Finck }
5926c2c66affSColin Finck
5927c2c66affSColin Finck while ((ch != EOF) && (index - start < width))
5928c2c66affSColin Finck {
5929c2c66affSColin Finck /* Integer part */
5930c2c66affSColin Finck if (isHex ? isxdigit(ch) : isdigit(ch))
5931c2c66affSColin Finck {
5932c2c66affSColin Finck doubleString[index++] = (char)ch;
5933c2c66affSColin Finck self->InStream(self, &ch);
5934c2c66affSColin Finck }
5935c2c66affSColin Finck else if (flags & FLAGS_QUOTE)
5936c2c66affSColin Finck {
5937c2c66affSColin Finck /* Compare with thousands separator */
5938c2c66affSColin Finck for (j = 0; internalThousandSeparator[j] && self->current; j++)
5939c2c66affSColin Finck {
5940c2c66affSColin Finck if (internalThousandSeparator[j] != self->current)
5941c2c66affSColin Finck break;
5942c2c66affSColin Finck
5943c2c66affSColin Finck self->InStream(self, &ch);
5944c2c66affSColin Finck }
5945c2c66affSColin Finck if (internalThousandSeparator[j])
5946c2c66affSColin Finck break; /* Mismatch */
5947c2c66affSColin Finck else
5948c2c66affSColin Finck continue; /* Match */
5949c2c66affSColin Finck }
5950c2c66affSColin Finck else
5951c2c66affSColin Finck break; /* while */
5952c2c66affSColin Finck }
5953c2c66affSColin Finck if (ch == '.')
5954c2c66affSColin Finck {
5955c2c66affSColin Finck /* Decimal part */
5956c2c66affSColin Finck doubleString[index++] = (char)ch;
5957c2c66affSColin Finck self->InStream(self, &ch);
5958c2c66affSColin Finck while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
5959c2c66affSColin Finck (index - start < width))
5960c2c66affSColin Finck {
5961c2c66affSColin Finck doubleString[index++] = (char)ch;
5962c2c66affSColin Finck self->InStream(self, &ch);
5963c2c66affSColin Finck }
5964c2c66affSColin Finck if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
5965c2c66affSColin Finck {
5966c2c66affSColin Finck /* Exponent */
5967c2c66affSColin Finck doubleString[index++] = (char)ch;
5968c2c66affSColin Finck self->InStream(self, &ch);
5969c2c66affSColin Finck if ((ch == '+') || (ch == '-'))
5970c2c66affSColin Finck {
5971c2c66affSColin Finck doubleString[index++] = (char)ch;
5972c2c66affSColin Finck self->InStream(self, &ch);
5973c2c66affSColin Finck }
5974c2c66affSColin Finck while (isdigit(ch) && (index - start < width))
5975c2c66affSColin Finck {
5976c2c66affSColin Finck doubleString[index++] = (char)ch;
5977c2c66affSColin Finck self->InStream(self, &ch);
5978c2c66affSColin Finck }
5979c2c66affSColin Finck }
5980c2c66affSColin Finck }
5981c2c66affSColin Finck
5982c2c66affSColin Finck if ((index == start) || (*doubleString == NIL))
5983c2c66affSColin Finck return FALSE;
5984c2c66affSColin Finck
5985c2c66affSColin Finck doubleString[index] = 0;
5986c2c66affSColin Finck
5987c2c66affSColin Finck if (flags & FLAGS_LONGDOUBLE)
5988c2c66affSColin Finck {
5989c2c66affSColin Finck *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
5990c2c66affSColin Finck }
5991c2c66affSColin Finck else
5992c2c66affSColin Finck {
5993c2c66affSColin Finck *((double *)target) = trio_to_double(doubleString, NULL);
5994c2c66affSColin Finck }
5995c2c66affSColin Finck return TRUE;
5996c2c66affSColin Finck }
5997c2c66affSColin Finck
5998c2c66affSColin Finck /*************************************************************************
5999c2c66affSColin Finck * TrioReadPointer
6000c2c66affSColin Finck */
6001c2c66affSColin Finck TRIO_PRIVATE BOOLEAN_T
6002c2c66affSColin Finck TrioReadPointer
6003c2c66affSColin Finck TRIO_ARGS3((self, target, flags),
6004c2c66affSColin Finck trio_class_t *self,
6005c2c66affSColin Finck trio_pointer_t *target,
6006c2c66affSColin Finck trio_flags_t flags)
6007c2c66affSColin Finck {
6008c2c66affSColin Finck trio_uintmax_t number;
6009c2c66affSColin Finck char buffer[sizeof(internalNullString)];
6010c2c66affSColin Finck
6011c2c66affSColin Finck flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING);
6012c2c66affSColin Finck
6013c2c66affSColin Finck if (TrioReadNumber(self,
6014c2c66affSColin Finck &number,
6015c2c66affSColin Finck flags,
6016c2c66affSColin Finck POINTER_WIDTH,
6017c2c66affSColin Finck BASE_HEX))
6018c2c66affSColin Finck {
6019c2c66affSColin Finck /*
6020c2c66affSColin Finck * The strange assignment of number is a workaround for a compiler
6021c2c66affSColin Finck * warning
6022c2c66affSColin Finck */
6023c2c66affSColin Finck if (target)
6024c2c66affSColin Finck *target = (char *)0 + number;
6025c2c66affSColin Finck return TRUE;
6026c2c66affSColin Finck }
6027c2c66affSColin Finck else if (TrioReadString(self,
6028c2c66affSColin Finck (flags & FLAGS_IGNORE)
6029c2c66affSColin Finck ? NULL
6030c2c66affSColin Finck : buffer,
6031c2c66affSColin Finck 0,
6032c2c66affSColin Finck sizeof(internalNullString) - 1))
6033c2c66affSColin Finck {
6034c2c66affSColin Finck if (trio_equal_case(buffer, internalNullString))
6035c2c66affSColin Finck {
6036c2c66affSColin Finck if (target)
6037c2c66affSColin Finck *target = NULL;
6038c2c66affSColin Finck return TRUE;
6039c2c66affSColin Finck }
6040c2c66affSColin Finck }
6041c2c66affSColin Finck return FALSE;
6042c2c66affSColin Finck }
6043c2c66affSColin Finck
6044c2c66affSColin Finck /*************************************************************************
6045c2c66affSColin Finck * TrioScanProcess
6046c2c66affSColin Finck */
6047c2c66affSColin Finck TRIO_PRIVATE int
6048c2c66affSColin Finck TrioScanProcess
6049c2c66affSColin Finck TRIO_ARGS3((data, format, parameters),
6050c2c66affSColin Finck trio_class_t *data,
6051c2c66affSColin Finck TRIO_CONST char *format,
6052c2c66affSColin Finck trio_parameter_t *parameters)
6053c2c66affSColin Finck {
6054c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
6055c2c66affSColin Finck int charlen;
6056c2c66affSColin Finck int cnt;
6057c2c66affSColin Finck #endif
6058c2c66affSColin Finck int assignment;
6059c2c66affSColin Finck int ch;
6060c2c66affSColin Finck int index; /* Index of format string */
6061c2c66affSColin Finck int i; /* Index of current parameter */
6062c2c66affSColin Finck trio_flags_t flags;
6063c2c66affSColin Finck int width;
6064c2c66affSColin Finck int base;
6065c2c66affSColin Finck trio_pointer_t pointer;
6066c2c66affSColin Finck
6067c2c66affSColin Finck assignment = 0;
6068c2c66affSColin Finck i = 0;
6069c2c66affSColin Finck index = 0;
6070c2c66affSColin Finck data->InStream(data, &ch);
6071c2c66affSColin Finck
6072c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
6073c2c66affSColin Finck (void)mblen(NULL, 0);
6074c2c66affSColin Finck #endif
6075c2c66affSColin Finck
6076c2c66affSColin Finck while (format[index])
6077c2c66affSColin Finck {
6078c2c66affSColin Finck #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
6079c2c66affSColin Finck if (! isascii(format[index]))
6080c2c66affSColin Finck {
6081c2c66affSColin Finck charlen = mblen(&format[index], MB_LEN_MAX);
6082c2c66affSColin Finck if (charlen != -1)
6083c2c66affSColin Finck {
6084c2c66affSColin Finck /* Compare multibyte characters in format string */
6085c2c66affSColin Finck for (cnt = 0; cnt < charlen - 1; cnt++)
6086c2c66affSColin Finck {
6087c2c66affSColin Finck if (ch != format[index + cnt])
6088c2c66affSColin Finck {
6089c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
6090c2c66affSColin Finck }
6091c2c66affSColin Finck data->InStream(data, &ch);
6092c2c66affSColin Finck }
6093c2c66affSColin Finck continue; /* while characters left in formatting string */
6094c2c66affSColin Finck }
6095c2c66affSColin Finck }
6096c2c66affSColin Finck #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
6097c2c66affSColin Finck
6098c2c66affSColin Finck if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
6099c2c66affSColin Finck {
6100c2c66affSColin Finck return (assignment > 0) ? assignment : EOF;
6101c2c66affSColin Finck }
6102c2c66affSColin Finck
6103c2c66affSColin Finck if (CHAR_IDENTIFIER == format[index])
6104c2c66affSColin Finck {
6105c2c66affSColin Finck if (CHAR_IDENTIFIER == format[index + 1])
6106c2c66affSColin Finck {
6107c2c66affSColin Finck /* Two % in format matches one % in input stream */
6108c2c66affSColin Finck if (CHAR_IDENTIFIER == ch)
6109c2c66affSColin Finck {
6110c2c66affSColin Finck data->InStream(data, &ch);
6111c2c66affSColin Finck index += 2;
6112c2c66affSColin Finck continue; /* while format chars left */
6113c2c66affSColin Finck }
6114c2c66affSColin Finck else
6115c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
6116c2c66affSColin Finck }
6117c2c66affSColin Finck
6118c2c66affSColin Finck /* Skip the parameter entries */
6119c2c66affSColin Finck while (parameters[i].type == FORMAT_PARAMETER)
6120c2c66affSColin Finck i++;
6121c2c66affSColin Finck
6122c2c66affSColin Finck flags = parameters[i].flags;
6123c2c66affSColin Finck /* Find width */
6124c2c66affSColin Finck width = parameters[i].width;
6125c2c66affSColin Finck if (flags & FLAGS_WIDTH_PARAMETER)
6126c2c66affSColin Finck {
6127c2c66affSColin Finck /* Get width from parameter list */
6128c2c66affSColin Finck width = (int)parameters[width].data.number.as_signed;
6129c2c66affSColin Finck }
6130c2c66affSColin Finck /* Find base */
6131c2c66affSColin Finck base = parameters[i].base;
6132c2c66affSColin Finck if (flags & FLAGS_BASE_PARAMETER)
6133c2c66affSColin Finck {
6134c2c66affSColin Finck /* Get base from parameter list */
6135c2c66affSColin Finck base = (int)parameters[base].data.number.as_signed;
6136c2c66affSColin Finck }
6137c2c66affSColin Finck
6138c2c66affSColin Finck switch (parameters[i].type)
6139c2c66affSColin Finck {
6140c2c66affSColin Finck case FORMAT_INT:
6141c2c66affSColin Finck {
6142c2c66affSColin Finck trio_uintmax_t number;
6143c2c66affSColin Finck
6144c2c66affSColin Finck if (0 == base)
6145c2c66affSColin Finck base = BASE_DECIMAL;
6146c2c66affSColin Finck
6147c2c66affSColin Finck if (!TrioReadNumber(data,
6148c2c66affSColin Finck &number,
6149c2c66affSColin Finck flags,
6150c2c66affSColin Finck width,
6151c2c66affSColin Finck base))
6152c2c66affSColin Finck return assignment;
6153c2c66affSColin Finck
6154c2c66affSColin Finck if (!(flags & FLAGS_IGNORE))
6155c2c66affSColin Finck {
6156c2c66affSColin Finck assignment++;
6157c2c66affSColin Finck
6158c2c66affSColin Finck pointer = parameters[i].data.pointer;
6159c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
6160c2c66affSColin Finck if (flags & FLAGS_SIZE_T)
6161c2c66affSColin Finck *(size_t *)pointer = (size_t)number;
6162c2c66affSColin Finck else
6163c2c66affSColin Finck #endif
6164c2c66affSColin Finck #if defined(QUALIFIER_PTRDIFF_T)
6165c2c66affSColin Finck if (flags & FLAGS_PTRDIFF_T)
6166c2c66affSColin Finck *(ptrdiff_t *)pointer = (ptrdiff_t)number;
6167c2c66affSColin Finck else
6168c2c66affSColin Finck #endif
6169c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
6170c2c66affSColin Finck if (flags & FLAGS_INTMAX_T)
6171c2c66affSColin Finck *(trio_intmax_t *)pointer = (trio_intmax_t)number;
6172c2c66affSColin Finck else
6173c2c66affSColin Finck #endif
6174c2c66affSColin Finck if (flags & FLAGS_QUAD)
6175c2c66affSColin Finck *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
6176c2c66affSColin Finck else if (flags & FLAGS_LONG)
6177c2c66affSColin Finck *(long int *)pointer = (long int)number;
6178c2c66affSColin Finck else if (flags & FLAGS_SHORT)
6179c2c66affSColin Finck *(short int *)pointer = (short int)number;
6180c2c66affSColin Finck else
6181c2c66affSColin Finck *(int *)pointer = (int)number;
6182c2c66affSColin Finck }
6183c2c66affSColin Finck }
6184c2c66affSColin Finck break; /* FORMAT_INT */
6185c2c66affSColin Finck
6186c2c66affSColin Finck case FORMAT_STRING:
6187c2c66affSColin Finck #if TRIO_WIDECHAR
6188c2c66affSColin Finck if (flags & FLAGS_WIDECHAR)
6189c2c66affSColin Finck {
6190c2c66affSColin Finck if (!TrioReadWideString(data,
6191c2c66affSColin Finck (flags & FLAGS_IGNORE)
6192c2c66affSColin Finck ? NULL
6193c2c66affSColin Finck : parameters[i].data.wstring,
6194c2c66affSColin Finck flags,
6195c2c66affSColin Finck width))
6196c2c66affSColin Finck return assignment;
6197c2c66affSColin Finck }
6198c2c66affSColin Finck else
6199c2c66affSColin Finck #endif
6200c2c66affSColin Finck {
6201c2c66affSColin Finck if (!TrioReadString(data,
6202c2c66affSColin Finck (flags & FLAGS_IGNORE)
6203c2c66affSColin Finck ? NULL
6204c2c66affSColin Finck : parameters[i].data.string,
6205c2c66affSColin Finck flags,
6206c2c66affSColin Finck width))
6207c2c66affSColin Finck return assignment;
6208c2c66affSColin Finck }
6209c2c66affSColin Finck if (!(flags & FLAGS_IGNORE))
6210c2c66affSColin Finck assignment++;
6211c2c66affSColin Finck break; /* FORMAT_STRING */
6212c2c66affSColin Finck
6213c2c66affSColin Finck case FORMAT_DOUBLE:
6214c2c66affSColin Finck {
6215c2c66affSColin Finck trio_pointer_t pointer;
6216c2c66affSColin Finck
6217c2c66affSColin Finck if (flags & FLAGS_IGNORE)
6218c2c66affSColin Finck {
6219c2c66affSColin Finck pointer = NULL;
6220c2c66affSColin Finck }
6221c2c66affSColin Finck else
6222c2c66affSColin Finck {
6223c2c66affSColin Finck pointer = (flags & FLAGS_LONGDOUBLE)
6224c2c66affSColin Finck ? (trio_pointer_t)parameters[i].data.longdoublePointer
6225c2c66affSColin Finck : (trio_pointer_t)parameters[i].data.doublePointer;
6226c2c66affSColin Finck }
6227c2c66affSColin Finck if (!TrioReadDouble(data, pointer, flags, width))
6228c2c66affSColin Finck {
6229c2c66affSColin Finck return assignment;
6230c2c66affSColin Finck }
6231c2c66affSColin Finck if (!(flags & FLAGS_IGNORE))
6232c2c66affSColin Finck {
6233c2c66affSColin Finck assignment++;
6234c2c66affSColin Finck }
6235c2c66affSColin Finck break; /* FORMAT_DOUBLE */
6236c2c66affSColin Finck }
6237c2c66affSColin Finck case FORMAT_GROUP:
6238c2c66affSColin Finck {
6239c2c66affSColin Finck int characterclass[MAX_CHARACTER_CLASS + 1];
6240c2c66affSColin Finck int rc;
6241c2c66affSColin Finck
6242c2c66affSColin Finck /* Skip over modifiers */
6243c2c66affSColin Finck while (format[index] != SPECIFIER_GROUP)
6244c2c66affSColin Finck {
6245c2c66affSColin Finck index++;
6246c2c66affSColin Finck }
6247c2c66affSColin Finck /* Skip over group specifier */
6248c2c66affSColin Finck index++;
6249c2c66affSColin Finck
6250c2c66affSColin Finck memset(characterclass, 0, sizeof(characterclass));
6251c2c66affSColin Finck rc = TrioGetCharacterClass(format,
6252c2c66affSColin Finck &index,
6253c2c66affSColin Finck &flags,
6254c2c66affSColin Finck characterclass);
6255c2c66affSColin Finck if (rc < 0)
6256c2c66affSColin Finck return rc;
6257c2c66affSColin Finck
6258c2c66affSColin Finck if (!TrioReadGroup(data,
6259c2c66affSColin Finck (flags & FLAGS_IGNORE)
6260c2c66affSColin Finck ? NULL
6261c2c66affSColin Finck : parameters[i].data.string,
6262c2c66affSColin Finck characterclass,
6263c2c66affSColin Finck flags,
6264c2c66affSColin Finck parameters[i].width))
6265c2c66affSColin Finck return assignment;
6266c2c66affSColin Finck if (!(flags & FLAGS_IGNORE))
6267c2c66affSColin Finck assignment++;
6268c2c66affSColin Finck }
6269c2c66affSColin Finck break; /* FORMAT_GROUP */
6270c2c66affSColin Finck
6271c2c66affSColin Finck case FORMAT_COUNT:
6272c2c66affSColin Finck pointer = parameters[i].data.pointer;
6273c2c66affSColin Finck if (NULL != pointer)
6274c2c66affSColin Finck {
6275c2c66affSColin Finck int count = data->committed;
6276c2c66affSColin Finck if (ch != EOF)
6277c2c66affSColin Finck count--; /* a character is read, but is not consumed yet */
6278c2c66affSColin Finck #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
6279c2c66affSColin Finck if (flags & FLAGS_SIZE_T)
6280c2c66affSColin Finck *(size_t *)pointer = (size_t)count;
6281c2c66affSColin Finck else
6282c2c66affSColin Finck #endif
6283c2c66affSColin Finck #if defined(QUALIFIER_PTRDIFF_T)
6284c2c66affSColin Finck if (flags & FLAGS_PTRDIFF_T)
6285c2c66affSColin Finck *(ptrdiff_t *)pointer = (ptrdiff_t)count;
6286c2c66affSColin Finck else
6287c2c66affSColin Finck #endif
6288c2c66affSColin Finck #if defined(QUALIFIER_INTMAX_T)
6289c2c66affSColin Finck if (flags & FLAGS_INTMAX_T)
6290c2c66affSColin Finck *(trio_intmax_t *)pointer = (trio_intmax_t)count;
6291c2c66affSColin Finck else
6292c2c66affSColin Finck #endif
6293c2c66affSColin Finck if (flags & FLAGS_QUAD)
6294c2c66affSColin Finck {
6295c2c66affSColin Finck *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
6296c2c66affSColin Finck }
6297c2c66affSColin Finck else if (flags & FLAGS_LONG)
6298c2c66affSColin Finck {
6299c2c66affSColin Finck *(long int *)pointer = (long int)count;
6300c2c66affSColin Finck }
6301c2c66affSColin Finck else if (flags & FLAGS_SHORT)
6302c2c66affSColin Finck {
6303c2c66affSColin Finck *(short int *)pointer = (short int)count;
6304c2c66affSColin Finck }
6305c2c66affSColin Finck else
6306c2c66affSColin Finck {
6307c2c66affSColin Finck *(int *)pointer = (int)count;
6308c2c66affSColin Finck }
6309c2c66affSColin Finck }
6310c2c66affSColin Finck break; /* FORMAT_COUNT */
6311c2c66affSColin Finck
6312c2c66affSColin Finck case FORMAT_CHAR:
6313c2c66affSColin Finck #if TRIO_WIDECHAR
6314c2c66affSColin Finck if (flags & FLAGS_WIDECHAR)
6315c2c66affSColin Finck {
6316c2c66affSColin Finck if (TrioReadWideChar(data,
6317c2c66affSColin Finck (flags & FLAGS_IGNORE)
6318c2c66affSColin Finck ? NULL
6319c2c66affSColin Finck : parameters[i].data.wstring,
6320c2c66affSColin Finck flags,
6321c2c66affSColin Finck (width == NO_WIDTH) ? 1 : width) == 0)
6322c2c66affSColin Finck return assignment;
6323c2c66affSColin Finck }
6324c2c66affSColin Finck else
6325c2c66affSColin Finck #endif
6326c2c66affSColin Finck {
6327c2c66affSColin Finck if (TrioReadChar(data,
6328c2c66affSColin Finck (flags & FLAGS_IGNORE)
6329c2c66affSColin Finck ? NULL
6330c2c66affSColin Finck : parameters[i].data.string,
6331c2c66affSColin Finck flags,
6332c2c66affSColin Finck (width == NO_WIDTH) ? 1 : width) == 0)
6333c2c66affSColin Finck return assignment;
6334c2c66affSColin Finck }
6335c2c66affSColin Finck if (!(flags & FLAGS_IGNORE))
6336c2c66affSColin Finck assignment++;
6337c2c66affSColin Finck break; /* FORMAT_CHAR */
6338c2c66affSColin Finck
6339c2c66affSColin Finck case FORMAT_POINTER:
6340c2c66affSColin Finck if (!TrioReadPointer(data,
6341c2c66affSColin Finck (flags & FLAGS_IGNORE)
6342c2c66affSColin Finck ? NULL
6343c2c66affSColin Finck : (trio_pointer_t *)parameters[i].data.pointer,
6344c2c66affSColin Finck flags))
6345c2c66affSColin Finck return assignment;
6346c2c66affSColin Finck if (!(flags & FLAGS_IGNORE))
6347c2c66affSColin Finck assignment++;
6348c2c66affSColin Finck break; /* FORMAT_POINTER */
6349c2c66affSColin Finck
6350c2c66affSColin Finck case FORMAT_PARAMETER:
6351c2c66affSColin Finck break; /* FORMAT_PARAMETER */
6352c2c66affSColin Finck
6353c2c66affSColin Finck default:
6354c2c66affSColin Finck return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
6355c2c66affSColin Finck }
6356c2c66affSColin Finck ch = data->current;
6357c2c66affSColin Finck index = parameters[i].indexAfterSpecifier;
6358c2c66affSColin Finck i++;
6359c2c66affSColin Finck }
6360c2c66affSColin Finck else /* Not an % identifier */
6361c2c66affSColin Finck {
6362c2c66affSColin Finck if (isspace((int)format[index]))
6363c2c66affSColin Finck {
6364c2c66affSColin Finck /* Whitespaces may match any amount of whitespaces */
6365c2c66affSColin Finck ch = TrioSkipWhitespaces(data);
6366c2c66affSColin Finck }
6367c2c66affSColin Finck else if (ch == format[index])
6368c2c66affSColin Finck {
6369c2c66affSColin Finck data->InStream(data, &ch);
6370c2c66affSColin Finck }
6371c2c66affSColin Finck else
6372c2c66affSColin Finck return assignment;
6373c2c66affSColin Finck
6374c2c66affSColin Finck index++;
6375c2c66affSColin Finck }
6376c2c66affSColin Finck }
6377c2c66affSColin Finck return assignment;
6378c2c66affSColin Finck }
6379c2c66affSColin Finck
6380c2c66affSColin Finck /*************************************************************************
6381c2c66affSColin Finck * TrioScan
6382c2c66affSColin Finck */
6383c2c66affSColin Finck TRIO_PRIVATE int
6384c2c66affSColin Finck TrioScan
6385c2c66affSColin Finck TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
6386c2c66affSColin Finck trio_pointer_t source,
6387c2c66affSColin Finck size_t sourceSize,
6388c2c66affSColin Finck void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
6389c2c66affSColin Finck TRIO_CONST char *format,
6390c2c66affSColin Finck TRIO_VA_LIST_PTR arglist,
6391c2c66affSColin Finck trio_pointer_t *argarray)
6392c2c66affSColin Finck {
6393c2c66affSColin Finck int status;
6394c2c66affSColin Finck trio_parameter_t parameters[MAX_PARAMETERS];
6395c2c66affSColin Finck trio_class_t data;
6396c2c66affSColin Finck
6397c2c66affSColin Finck assert(VALID(InStream));
6398c2c66affSColin Finck assert(VALID(format));
6399c2c66affSColin Finck
6400c2c66affSColin Finck memset(&data, 0, sizeof(data));
6401c2c66affSColin Finck data.InStream = InStream;
6402c2c66affSColin Finck data.location = (trio_pointer_t)source;
6403c2c66affSColin Finck data.max = sourceSize;
6404c2c66affSColin Finck data.error = 0;
6405c2c66affSColin Finck
6406c2c66affSColin Finck #if defined(USE_LOCALE)
6407c2c66affSColin Finck if (NULL == internalLocaleValues)
6408c2c66affSColin Finck {
6409c2c66affSColin Finck TrioSetLocale();
6410c2c66affSColin Finck }
6411c2c66affSColin Finck #endif
6412c2c66affSColin Finck
6413c2c66affSColin Finck status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
6414c2c66affSColin Finck if (status < 0)
6415c2c66affSColin Finck return status;
6416c2c66affSColin Finck
6417c2c66affSColin Finck status = TrioScanProcess(&data, format, parameters);
6418c2c66affSColin Finck if (data.error != 0)
6419c2c66affSColin Finck {
6420c2c66affSColin Finck status = data.error;
6421c2c66affSColin Finck }
6422c2c66affSColin Finck return status;
6423c2c66affSColin Finck }
6424c2c66affSColin Finck
6425c2c66affSColin Finck /*************************************************************************
6426c2c66affSColin Finck * TrioInStreamFile
6427c2c66affSColin Finck */
6428c2c66affSColin Finck TRIO_PRIVATE void
6429c2c66affSColin Finck TrioInStreamFile
6430c2c66affSColin Finck TRIO_ARGS2((self, intPointer),
6431c2c66affSColin Finck trio_class_t *self,
6432c2c66affSColin Finck int *intPointer)
6433c2c66affSColin Finck {
6434c2c66affSColin Finck FILE *file;
6435c2c66affSColin Finck
6436c2c66affSColin Finck assert(VALID(self));
6437c2c66affSColin Finck assert(VALID(self->location));
6438c2c66affSColin Finck assert(VALID(file));
6439c2c66affSColin Finck
6440c2c66affSColin Finck file = (FILE *)self->location;
6441c2c66affSColin Finck
6442c2c66affSColin Finck self->current = fgetc(file);
6443c2c66affSColin Finck if (self->current == EOF)
6444c2c66affSColin Finck {
6445c2c66affSColin Finck self->error = (ferror(file))
6446c2c66affSColin Finck ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0)
6447c2c66affSColin Finck : TRIO_ERROR_RETURN(TRIO_EOF, 0);
6448c2c66affSColin Finck }
6449c2c66affSColin Finck else
6450c2c66affSColin Finck {
6451c2c66affSColin Finck self->processed++;
6452c2c66affSColin Finck self->committed++;
6453c2c66affSColin Finck }
6454c2c66affSColin Finck
6455c2c66affSColin Finck if (VALID(intPointer))
6456c2c66affSColin Finck {
6457c2c66affSColin Finck *intPointer = self->current;
6458c2c66affSColin Finck }
6459c2c66affSColin Finck }
6460c2c66affSColin Finck
6461c2c66affSColin Finck /*************************************************************************
6462c2c66affSColin Finck * TrioInStreamFileDescriptor
6463c2c66affSColin Finck */
6464c2c66affSColin Finck TRIO_PRIVATE void
6465c2c66affSColin Finck TrioInStreamFileDescriptor
6466c2c66affSColin Finck TRIO_ARGS2((self, intPointer),
6467c2c66affSColin Finck trio_class_t *self,
6468c2c66affSColin Finck int *intPointer)
6469c2c66affSColin Finck {
6470c2c66affSColin Finck int fd;
6471c2c66affSColin Finck int size;
6472c2c66affSColin Finck unsigned char input;
6473c2c66affSColin Finck
6474c2c66affSColin Finck assert(VALID(self));
6475c2c66affSColin Finck assert(VALID(self->location));
6476c2c66affSColin Finck
6477c2c66affSColin Finck fd = *((int *)self->location);
6478c2c66affSColin Finck
6479c2c66affSColin Finck size = read(fd, &input, sizeof(char));
6480c2c66affSColin Finck if (size == -1)
6481c2c66affSColin Finck {
6482c2c66affSColin Finck self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
6483c2c66affSColin Finck self->current = EOF;
6484c2c66affSColin Finck }
6485c2c66affSColin Finck else
6486c2c66affSColin Finck {
6487c2c66affSColin Finck self->current = (size == 0) ? EOF : input;
6488c2c66affSColin Finck }
6489c2c66affSColin Finck if (self->current != EOF)
6490c2c66affSColin Finck {
6491c2c66affSColin Finck self->committed++;
6492c2c66affSColin Finck self->processed++;
6493c2c66affSColin Finck }
6494c2c66affSColin Finck
6495c2c66affSColin Finck if (VALID(intPointer))
6496c2c66affSColin Finck {
6497c2c66affSColin Finck *intPointer = self->current;
6498c2c66affSColin Finck }
6499c2c66affSColin Finck }
6500c2c66affSColin Finck
6501c2c66affSColin Finck /*************************************************************************
6502c2c66affSColin Finck * TrioInStreamCustom
6503c2c66affSColin Finck */
6504c2c66affSColin Finck TRIO_PRIVATE void
6505c2c66affSColin Finck TrioInStreamCustom
6506c2c66affSColin Finck TRIO_ARGS2((self, intPointer),
6507c2c66affSColin Finck trio_class_t *self,
6508c2c66affSColin Finck int *intPointer)
6509c2c66affSColin Finck {
6510c2c66affSColin Finck trio_custom_t *data;
6511c2c66affSColin Finck
6512c2c66affSColin Finck assert(VALID(self));
6513c2c66affSColin Finck assert(VALID(self->location));
6514c2c66affSColin Finck
6515c2c66affSColin Finck data = (trio_custom_t *)self->location;
6516c2c66affSColin Finck
6517c2c66affSColin Finck self->current = (data->stream.in == NULL)
6518c2c66affSColin Finck ? NIL
6519c2c66affSColin Finck : (data->stream.in)(data->closure);
6520c2c66affSColin Finck
6521c2c66affSColin Finck if (self->current == NIL)
6522c2c66affSColin Finck {
6523c2c66affSColin Finck self->current = EOF;
6524c2c66affSColin Finck }
6525c2c66affSColin Finck else
6526c2c66affSColin Finck {
6527c2c66affSColin Finck self->processed++;
6528c2c66affSColin Finck self->committed++;
6529c2c66affSColin Finck }
6530c2c66affSColin Finck
6531c2c66affSColin Finck if (VALID(intPointer))
6532c2c66affSColin Finck {
6533c2c66affSColin Finck *intPointer = self->current;
6534c2c66affSColin Finck }
6535c2c66affSColin Finck }
6536c2c66affSColin Finck
6537c2c66affSColin Finck /*************************************************************************
6538c2c66affSColin Finck * TrioInStreamString
6539c2c66affSColin Finck */
6540c2c66affSColin Finck TRIO_PRIVATE void
6541c2c66affSColin Finck TrioInStreamString
6542c2c66affSColin Finck TRIO_ARGS2((self, intPointer),
6543c2c66affSColin Finck trio_class_t *self,
6544c2c66affSColin Finck int *intPointer)
6545c2c66affSColin Finck {
6546c2c66affSColin Finck unsigned char **buffer;
6547c2c66affSColin Finck
6548c2c66affSColin Finck assert(VALID(self));
6549c2c66affSColin Finck assert(VALID(self->location));
6550c2c66affSColin Finck
6551c2c66affSColin Finck buffer = (unsigned char **)self->location;
6552c2c66affSColin Finck self->current = (*buffer)[0];
6553c2c66affSColin Finck if (self->current == NIL)
6554c2c66affSColin Finck {
6555c2c66affSColin Finck self->current = EOF;
6556c2c66affSColin Finck }
6557c2c66affSColin Finck else
6558c2c66affSColin Finck {
6559c2c66affSColin Finck (*buffer)++;
6560c2c66affSColin Finck self->processed++;
6561c2c66affSColin Finck self->committed++;
6562c2c66affSColin Finck }
6563c2c66affSColin Finck
6564c2c66affSColin Finck if (VALID(intPointer))
6565c2c66affSColin Finck {
6566c2c66affSColin Finck *intPointer = self->current;
6567c2c66affSColin Finck }
6568c2c66affSColin Finck }
6569c2c66affSColin Finck
6570c2c66affSColin Finck /*************************************************************************
6571c2c66affSColin Finck *
6572c2c66affSColin Finck * Formatted scanning functions
6573c2c66affSColin Finck *
6574c2c66affSColin Finck ************************************************************************/
6575c2c66affSColin Finck
6576c2c66affSColin Finck #if defined(TRIO_DOCUMENTATION)
6577c2c66affSColin Finck # include "doc/doc_scanf.h"
6578c2c66affSColin Finck #endif
6579c2c66affSColin Finck /** @addtogroup Scanf
6580c2c66affSColin Finck @{
6581c2c66affSColin Finck */
6582c2c66affSColin Finck
6583c2c66affSColin Finck /*************************************************************************
6584c2c66affSColin Finck * scanf
6585c2c66affSColin Finck */
6586c2c66affSColin Finck
6587c2c66affSColin Finck /**
6588c2c66affSColin Finck Scan characters from standard input stream.
6589c2c66affSColin Finck
6590c2c66affSColin Finck @param format Formatting string.
6591c2c66affSColin Finck @param ... Arguments.
6592c2c66affSColin Finck @return Number of scanned characters.
6593c2c66affSColin Finck */
6594c2c66affSColin Finck TRIO_PUBLIC int
6595c2c66affSColin Finck trio_scanf
6596c2c66affSColin Finck TRIO_VARGS2((format, va_alist),
6597c2c66affSColin Finck TRIO_CONST char *format,
6598c2c66affSColin Finck TRIO_VA_DECL)
6599c2c66affSColin Finck {
6600c2c66affSColin Finck int status;
6601c2c66affSColin Finck va_list args;
6602c2c66affSColin Finck
6603c2c66affSColin Finck assert(VALID(format));
6604c2c66affSColin Finck
6605c2c66affSColin Finck TRIO_VA_START(args, format);
6606c2c66affSColin Finck status = TrioScan((trio_pointer_t)stdin, 0,
6607c2c66affSColin Finck TrioInStreamFile,
6608c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6609c2c66affSColin Finck TRIO_VA_END(args);
6610c2c66affSColin Finck return status;
6611c2c66affSColin Finck }
6612c2c66affSColin Finck
6613c2c66affSColin Finck TRIO_PUBLIC int
6614c2c66affSColin Finck trio_vscanf
6615c2c66affSColin Finck TRIO_ARGS2((format, args),
6616c2c66affSColin Finck TRIO_CONST char *format,
6617c2c66affSColin Finck va_list args)
6618c2c66affSColin Finck {
6619c2c66affSColin Finck assert(VALID(format));
6620c2c66affSColin Finck
6621c2c66affSColin Finck return TrioScan((trio_pointer_t)stdin, 0,
6622c2c66affSColin Finck TrioInStreamFile,
6623c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6624c2c66affSColin Finck }
6625c2c66affSColin Finck
6626c2c66affSColin Finck TRIO_PUBLIC int
6627c2c66affSColin Finck trio_scanfv
6628c2c66affSColin Finck TRIO_ARGS2((format, args),
6629c2c66affSColin Finck TRIO_CONST char *format,
6630c2c66affSColin Finck trio_pointer_t *args)
6631c2c66affSColin Finck {
6632c2c66affSColin Finck assert(VALID(format));
6633c2c66affSColin Finck
6634c2c66affSColin Finck return TrioScan((trio_pointer_t)stdin, 0,
6635c2c66affSColin Finck TrioInStreamFile,
6636c2c66affSColin Finck format, NULL, args);
6637c2c66affSColin Finck }
6638c2c66affSColin Finck
6639c2c66affSColin Finck /*************************************************************************
6640c2c66affSColin Finck * fscanf
6641c2c66affSColin Finck */
6642c2c66affSColin Finck TRIO_PUBLIC int
6643c2c66affSColin Finck trio_fscanf
6644c2c66affSColin Finck TRIO_VARGS3((file, format, va_alist),
6645c2c66affSColin Finck FILE *file,
6646c2c66affSColin Finck TRIO_CONST char *format,
6647c2c66affSColin Finck TRIO_VA_DECL)
6648c2c66affSColin Finck {
6649c2c66affSColin Finck int status;
6650c2c66affSColin Finck va_list args;
6651c2c66affSColin Finck
6652c2c66affSColin Finck assert(VALID(file));
6653c2c66affSColin Finck assert(VALID(format));
6654c2c66affSColin Finck
6655c2c66affSColin Finck TRIO_VA_START(args, format);
6656c2c66affSColin Finck status = TrioScan((trio_pointer_t)file, 0,
6657c2c66affSColin Finck TrioInStreamFile,
6658c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6659c2c66affSColin Finck TRIO_VA_END(args);
6660c2c66affSColin Finck return status;
6661c2c66affSColin Finck }
6662c2c66affSColin Finck
6663c2c66affSColin Finck TRIO_PUBLIC int
6664c2c66affSColin Finck trio_vfscanf
6665c2c66affSColin Finck TRIO_ARGS3((file, format, args),
6666c2c66affSColin Finck FILE *file,
6667c2c66affSColin Finck TRIO_CONST char *format,
6668c2c66affSColin Finck va_list args)
6669c2c66affSColin Finck {
6670c2c66affSColin Finck assert(VALID(file));
6671c2c66affSColin Finck assert(VALID(format));
6672c2c66affSColin Finck
6673c2c66affSColin Finck return TrioScan((trio_pointer_t)file, 0,
6674c2c66affSColin Finck TrioInStreamFile,
6675c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6676c2c66affSColin Finck }
6677c2c66affSColin Finck
6678c2c66affSColin Finck TRIO_PUBLIC int
6679c2c66affSColin Finck trio_fscanfv
6680c2c66affSColin Finck TRIO_ARGS3((file, format, args),
6681c2c66affSColin Finck FILE *file,
6682c2c66affSColin Finck TRIO_CONST char *format,
6683c2c66affSColin Finck trio_pointer_t *args)
6684c2c66affSColin Finck {
6685c2c66affSColin Finck assert(VALID(file));
6686c2c66affSColin Finck assert(VALID(format));
6687c2c66affSColin Finck
6688c2c66affSColin Finck return TrioScan((trio_pointer_t)file, 0,
6689c2c66affSColin Finck TrioInStreamFile,
6690c2c66affSColin Finck format, NULL, args);
6691c2c66affSColin Finck }
6692c2c66affSColin Finck
6693c2c66affSColin Finck /*************************************************************************
6694c2c66affSColin Finck * dscanf
6695c2c66affSColin Finck */
6696c2c66affSColin Finck TRIO_PUBLIC int
6697c2c66affSColin Finck trio_dscanf
6698c2c66affSColin Finck TRIO_VARGS3((fd, format, va_alist),
6699c2c66affSColin Finck int fd,
6700c2c66affSColin Finck TRIO_CONST char *format,
6701c2c66affSColin Finck TRIO_VA_DECL)
6702c2c66affSColin Finck {
6703c2c66affSColin Finck int status;
6704c2c66affSColin Finck va_list args;
6705c2c66affSColin Finck
6706c2c66affSColin Finck assert(VALID(format));
6707c2c66affSColin Finck
6708c2c66affSColin Finck TRIO_VA_START(args, format);
6709c2c66affSColin Finck status = TrioScan((trio_pointer_t)&fd, 0,
6710c2c66affSColin Finck TrioInStreamFileDescriptor,
6711c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6712c2c66affSColin Finck TRIO_VA_END(args);
6713c2c66affSColin Finck return status;
6714c2c66affSColin Finck }
6715c2c66affSColin Finck
6716c2c66affSColin Finck TRIO_PUBLIC int
6717c2c66affSColin Finck trio_vdscanf
6718c2c66affSColin Finck TRIO_ARGS3((fd, format, args),
6719c2c66affSColin Finck int fd,
6720c2c66affSColin Finck TRIO_CONST char *format,
6721c2c66affSColin Finck va_list args)
6722c2c66affSColin Finck {
6723c2c66affSColin Finck assert(VALID(format));
6724c2c66affSColin Finck
6725c2c66affSColin Finck return TrioScan((trio_pointer_t)&fd, 0,
6726c2c66affSColin Finck TrioInStreamFileDescriptor,
6727c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6728c2c66affSColin Finck }
6729c2c66affSColin Finck
6730c2c66affSColin Finck TRIO_PUBLIC int
6731c2c66affSColin Finck trio_dscanfv
6732c2c66affSColin Finck TRIO_ARGS3((fd, format, args),
6733c2c66affSColin Finck int fd,
6734c2c66affSColin Finck TRIO_CONST char *format,
6735c2c66affSColin Finck trio_pointer_t *args)
6736c2c66affSColin Finck {
6737c2c66affSColin Finck assert(VALID(format));
6738c2c66affSColin Finck
6739c2c66affSColin Finck return TrioScan((trio_pointer_t)&fd, 0,
6740c2c66affSColin Finck TrioInStreamFileDescriptor,
6741c2c66affSColin Finck format, NULL, args);
6742c2c66affSColin Finck }
6743c2c66affSColin Finck
6744c2c66affSColin Finck /*************************************************************************
6745c2c66affSColin Finck * cscanf
6746c2c66affSColin Finck */
6747c2c66affSColin Finck TRIO_PUBLIC int
6748c2c66affSColin Finck trio_cscanf
6749c2c66affSColin Finck TRIO_VARGS4((stream, closure, format, va_alist),
6750c2c66affSColin Finck trio_instream_t stream,
6751c2c66affSColin Finck trio_pointer_t closure,
6752c2c66affSColin Finck TRIO_CONST char *format,
6753c2c66affSColin Finck TRIO_VA_DECL)
6754c2c66affSColin Finck {
6755c2c66affSColin Finck int status;
6756c2c66affSColin Finck va_list args;
6757c2c66affSColin Finck trio_custom_t data;
6758c2c66affSColin Finck
6759c2c66affSColin Finck assert(VALID(stream));
6760c2c66affSColin Finck assert(VALID(format));
6761c2c66affSColin Finck
6762c2c66affSColin Finck TRIO_VA_START(args, format);
6763c2c66affSColin Finck data.stream.in = stream;
6764c2c66affSColin Finck data.closure = closure;
6765c2c66affSColin Finck status = TrioScan(&data, 0, TrioInStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL);
6766c2c66affSColin Finck TRIO_VA_END(args);
6767c2c66affSColin Finck return status;
6768c2c66affSColin Finck }
6769c2c66affSColin Finck
6770c2c66affSColin Finck TRIO_PUBLIC int
6771c2c66affSColin Finck trio_vcscanf
6772c2c66affSColin Finck TRIO_ARGS4((stream, closure, format, args),
6773c2c66affSColin Finck trio_instream_t stream,
6774c2c66affSColin Finck trio_pointer_t closure,
6775c2c66affSColin Finck TRIO_CONST char *format,
6776c2c66affSColin Finck va_list args)
6777c2c66affSColin Finck {
6778c2c66affSColin Finck trio_custom_t data;
6779c2c66affSColin Finck
6780c2c66affSColin Finck assert(VALID(stream));
6781c2c66affSColin Finck assert(VALID(format));
6782c2c66affSColin Finck
6783c2c66affSColin Finck data.stream.in = stream;
6784c2c66affSColin Finck data.closure = closure;
6785c2c66affSColin Finck return TrioScan(&data, 0, TrioInStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL);
6786c2c66affSColin Finck }
6787c2c66affSColin Finck
6788c2c66affSColin Finck TRIO_PUBLIC int
6789c2c66affSColin Finck trio_cscanfv
6790c2c66affSColin Finck TRIO_ARGS4((stream, closure, format, args),
6791c2c66affSColin Finck trio_instream_t stream,
6792c2c66affSColin Finck trio_pointer_t closure,
6793c2c66affSColin Finck TRIO_CONST char *format,
6794c2c66affSColin Finck trio_pointer_t *args)
6795c2c66affSColin Finck {
6796c2c66affSColin Finck trio_custom_t data;
6797c2c66affSColin Finck
6798c2c66affSColin Finck assert(VALID(stream));
6799c2c66affSColin Finck assert(VALID(format));
6800c2c66affSColin Finck
6801c2c66affSColin Finck data.stream.in = stream;
6802c2c66affSColin Finck data.closure = closure;
6803c2c66affSColin Finck return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args);
6804c2c66affSColin Finck }
6805c2c66affSColin Finck
6806c2c66affSColin Finck /*************************************************************************
6807c2c66affSColin Finck * sscanf
6808c2c66affSColin Finck */
6809c2c66affSColin Finck TRIO_PUBLIC int
6810c2c66affSColin Finck trio_sscanf
6811c2c66affSColin Finck TRIO_VARGS3((buffer, format, va_alist),
6812c2c66affSColin Finck TRIO_CONST char *buffer,
6813c2c66affSColin Finck TRIO_CONST char *format,
6814c2c66affSColin Finck TRIO_VA_DECL)
6815c2c66affSColin Finck {
6816c2c66affSColin Finck int status;
6817c2c66affSColin Finck va_list args;
6818c2c66affSColin Finck
6819c2c66affSColin Finck assert(VALID(buffer));
6820c2c66affSColin Finck assert(VALID(format));
6821c2c66affSColin Finck
6822c2c66affSColin Finck TRIO_VA_START(args, format);
6823c2c66affSColin Finck status = TrioScan((trio_pointer_t)&buffer, 0,
6824c2c66affSColin Finck TrioInStreamString,
6825c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6826c2c66affSColin Finck TRIO_VA_END(args);
6827c2c66affSColin Finck return status;
6828c2c66affSColin Finck }
6829c2c66affSColin Finck
6830c2c66affSColin Finck TRIO_PUBLIC int
6831c2c66affSColin Finck trio_vsscanf
6832c2c66affSColin Finck TRIO_ARGS3((buffer, format, args),
6833c2c66affSColin Finck TRIO_CONST char *buffer,
6834c2c66affSColin Finck TRIO_CONST char *format,
6835c2c66affSColin Finck va_list args)
6836c2c66affSColin Finck {
6837c2c66affSColin Finck assert(VALID(buffer));
6838c2c66affSColin Finck assert(VALID(format));
6839c2c66affSColin Finck
6840c2c66affSColin Finck return TrioScan((trio_pointer_t)&buffer, 0,
6841c2c66affSColin Finck TrioInStreamString,
6842c2c66affSColin Finck format, TRIO_VA_LIST_ADDR(args), NULL);
6843c2c66affSColin Finck }
6844c2c66affSColin Finck
6845c2c66affSColin Finck TRIO_PUBLIC int
6846c2c66affSColin Finck trio_sscanfv
6847c2c66affSColin Finck TRIO_ARGS3((buffer, format, args),
6848c2c66affSColin Finck TRIO_CONST char *buffer,
6849c2c66affSColin Finck TRIO_CONST char *format,
6850c2c66affSColin Finck trio_pointer_t *args)
6851c2c66affSColin Finck {
6852c2c66affSColin Finck assert(VALID(buffer));
6853c2c66affSColin Finck assert(VALID(format));
6854c2c66affSColin Finck
6855c2c66affSColin Finck return TrioScan((trio_pointer_t)&buffer, 0,
6856c2c66affSColin Finck TrioInStreamString,
6857c2c66affSColin Finck format, NULL, args);
6858c2c66affSColin Finck }
6859c2c66affSColin Finck
6860c2c66affSColin Finck /** @} End of Scanf documentation module */
6861c2c66affSColin Finck
6862c2c66affSColin Finck /*************************************************************************
6863c2c66affSColin Finck * trio_strerror
6864c2c66affSColin Finck */
6865c2c66affSColin Finck TRIO_PUBLIC TRIO_CONST char *
6866c2c66affSColin Finck trio_strerror
6867c2c66affSColin Finck TRIO_ARGS1((errorcode),
6868c2c66affSColin Finck int errorcode)
6869c2c66affSColin Finck {
6870c2c66affSColin Finck /* Textual versions of the error codes */
6871c2c66affSColin Finck switch (TRIO_ERROR_CODE(errorcode))
6872c2c66affSColin Finck {
6873c2c66affSColin Finck case TRIO_EOF:
6874c2c66affSColin Finck return "End of file";
6875c2c66affSColin Finck case TRIO_EINVAL:
6876c2c66affSColin Finck return "Invalid argument";
6877c2c66affSColin Finck case TRIO_ETOOMANY:
6878c2c66affSColin Finck return "Too many arguments";
6879c2c66affSColin Finck case TRIO_EDBLREF:
6880c2c66affSColin Finck return "Double reference";
6881c2c66affSColin Finck case TRIO_EGAP:
6882c2c66affSColin Finck return "Reference gap";
6883c2c66affSColin Finck case TRIO_ENOMEM:
6884c2c66affSColin Finck return "Out of memory";
6885c2c66affSColin Finck case TRIO_ERANGE:
6886c2c66affSColin Finck return "Invalid range";
6887c2c66affSColin Finck case TRIO_ECUSTOM:
6888c2c66affSColin Finck return "Custom error";
6889c2c66affSColin Finck default:
6890c2c66affSColin Finck return "Unknown";
6891c2c66affSColin Finck }
6892c2c66affSColin Finck }
6893