~ubuntu-branches/ubuntu/oneiric/fetchmail/oneiric

« back to all changes in this revision

Viewing changes to trio/trio.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2010-06-22 23:12:15 UTC
  • mfrom: (30.1.5 maverick)
  • Revision ID: james.westby@ubuntu.com-20100622231215-y68w7lhrjt97qhuh
* Merge from Debian unstable, remaining changes:
  - Suggest default-mta | mail-transport-agent, not
    exim4 | mail-transport-agent.
  - debian/init, debian/fetchmail.postinst: don't stop fetchmail in
    runlevels [06], the default 'killall' handler should be sufficient
    because fetchmail writes are properly completed before telling the
    server it's ok to delete.
* Dropped changes:
  - don't depend on sysv-rc (>= 2.86.ds1-14.1ubuntu2); the 'multiuser'
    argument to update-rc.d is deprecated.
  - 06_cert_0_byte.patch: included upstream.
  - python2.6 compatibility: fix included in Debian.
* debian/rules, debian/fetchmailconf.install: fix up python2.6 compatibility
  by accounting for site-packages vs. dist-packages across python versions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*************************************************************************
2
2
 *
3
 
 * $Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $
 
3
 * $Id: trio.c,v 1.129 2009/09/20 11:37:15 breese Exp $
4
4
 *
5
 
 * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
 
5
 * Copyright (C) 1998, 2009 Bjorn Reese and Daniel Stenberg.
6
6
 *
7
7
 * Permission to use, copy, modify, and distribute this software for any
8
8
 * purpose with or without fee is hereby granted, provided that the above
47
47
#include "triodef.h"
48
48
#include "trio.h"
49
49
#include "triop.h"
 
50
 
 
51
#if defined(TRIO_EMBED_NAN)
 
52
# define TRIO_PUBLIC_NAN static
 
53
# if TRIO_FEATURE_FLOAT
 
54
#  define TRIO_FUNC_NAN
 
55
#  define TRIO_FUNC_NINF
 
56
#  define TRIO_FUNC_PINF
 
57
#  define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
 
58
#  define TRIO_FUNC_ISINF
 
59
# endif
 
60
#endif
50
61
#include "trionan.h"
51
 
#if !defined(TRIO_MINIMAL)
52
 
# include "triostr.h"
 
62
 
 
63
#if defined(TRIO_EMBED_STRING)
 
64
# define TRIO_PUBLIC_STRING static
 
65
# define TRIO_FUNC_LENGTH
 
66
# define TRIO_FUNC_LENGTH_MAX
 
67
# define TRIO_FUNC_TO_LONG
 
68
# if TRIO_FEATURE_LOCALE
 
69
#  define TRIO_FUNC_COPY_MAX
 
70
# endif
 
71
# if TRIO_FEATURE_DYNAMICSTRING
 
72
#  define TRIO_FUNC_XSTRING_DUPLICATE
 
73
# endif
 
74
# if TRIO_EXTENSION && TRIO_FEATURE_SCANF
 
75
#  define TRIO_FUNC_EQUAL_LOCALE
 
76
# endif
 
77
# if TRIO_FEATURE_ERRNO
 
78
#  define TRIO_FUNC_ERROR
 
79
# endif
 
80
# if TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF
 
81
#  define TRIO_FUNC_TO_DOUBLE
 
82
# endif
 
83
# if TRIO_FEATURE_DYNAMICSTRING
 
84
#  define TRIO_FUNC_STRING_EXTRACT
 
85
# endif
 
86
# if TRIO_FEATURE_DYNAMICSTRING
 
87
#  define TRIO_FUNC_STRING_TERMINATE
 
88
# endif
 
89
# if TRIO_FEATURE_USER_DEFINED
 
90
#  define TRIO_FUNC_DUPLICATE
 
91
# endif
 
92
# if TRIO_FEATURE_DYNAMICSTRING
 
93
#  define TRIO_FUNC_STRING_DESTROY
 
94
# endif
 
95
# if TRIO_FEATURE_USER_DEFINED
 
96
#  define TRIO_FUNC_DESTROY
 
97
# endif
 
98
# if TRIO_FEATURE_USER_DEFINED || (TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF)
 
99
#  define TRIO_FUNC_EQUAL
 
100
# endif
 
101
# if TRIO_FEATURE_USER_DEFINED || TRIO_FEATURE_SCANF
 
102
#  define TRIO_FUNC_EQUAL_CASE
 
103
# endif
 
104
# if (TRIO_EXTENSION && TRIO_FEATURE_SCANF)
 
105
#  define TRIO_FUNC_EQUAL_MAX
 
106
# endif
 
107
# if TRIO_FEATURE_SCANF
 
108
#  define TRIO_FUNC_TO_UPPER
 
109
# endif
 
110
# if TRIO_FEATURE_DYNAMICSTRING
 
111
#  define TRIO_FUNC_XSTRING_APPEND_CHAR
 
112
# endif
53
113
#endif
 
114
#include "triostr.h"
54
115
 
55
116
/**************************************************************************
56
117
 *
58
119
 *
59
120
 *************************************************************************/
60
121
 
61
 
#include <math.h>
62
122
#include <limits.h>
63
 
#include <float.h>
64
 
 
65
 
#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR
66
 
# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
67
 
# if !defined(MB_LEN_MAX)
68
 
#  define MB_LEN_MAX 6
69
 
# endif
70
 
#endif
71
 
 
72
 
#if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
73
 
# define TRIO_COMPILER_SUPPORTS_MSVC_INT
 
123
#if TRIO_FEATURE_FLOAT
 
124
# include <math.h>
 
125
# include <float.h>
 
126
#endif
 
127
 
 
128
#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_FEATURE_WIDECHAR
 
129
# if !defined(TRIO_PLATFORM_WINCE)
 
130
#  define TRIO_COMPILER_SUPPORTS_MULTIBYTE
 
131
#  if !defined(MB_LEN_MAX)
 
132
#   define MB_LEN_MAX 6
 
133
#  endif
 
134
# endif
 
135
#endif
 
136
 
 
137
#if (TRIO_COMPILER_VISUALC - 0 >= 1100) || defined(TRIO_COMPILER_BORLAND)
 
138
# define TRIO_COMPILER_SUPPORTS_VISUALC_INT
 
139
#endif
 
140
 
 
141
#if TRIO_FEATURE_FLOAT
 
142
# if defined(PREDEF_STANDARD_C99) \
 
143
  || defined(PREDEF_STANDARD_UNIX03)
 
144
#  if !defined(HAVE_FLOORL) && !defined(TRIO_NO_FLOORL)
 
145
#   define HAVE_FLOORL
 
146
#  endif
 
147
#  if !defined(HAVE_CEILL) && !defined(TRIO_NO_CEILL)
 
148
#   define HAVE_CEILL
 
149
#  endif
 
150
#  if !defined(HAVE_POWL) && !defined(TRIO_NO_POWL)
 
151
#   define HAVE_POWL
 
152
#  endif
 
153
#  if !defined(HAVE_FMODL) && !defined(TRIO_NO_FMODL)
 
154
#   define HAVE_FMODL
 
155
#  endif
 
156
#  if !defined(HAVE_LOG10L) && !defined(TRIO_NO_LOG10L)
 
157
#   define HAVE_LOG10L
 
158
#  endif
 
159
# endif
 
160
# if defined(TRIO_COMPILER_VISUALC)
 
161
#  if defined(floorl)
 
162
#   define HAVE_FLOORL
 
163
#  endif
 
164
#  if defined(ceill)
 
165
#   define HAVE_CEILL
 
166
#  endif
 
167
#  if defined(powl)
 
168
#   define HAVE_POWL
 
169
#  endif
 
170
#  if defined(fmodl)
 
171
#   define HAVE_FMODL
 
172
#  endif
 
173
#  if defined(log10l)
 
174
#   define HAVE_LOG10L
 
175
#  endif
 
176
# endif
74
177
#endif
75
178
 
76
179
/*************************************************************************
83
186
 
84
187
#include <assert.h>
85
188
#include <ctype.h>
86
 
#if !defined(TRIO_COMPILER_SUPPORTS_C99)
87
 
# define isblank(x) (((x)==32) || ((x)==9))
 
189
#if defined(PREDEF_STANDARD_C99) && !defined(isascii)
 
190
# define isascii(x) ((x) & 0x7F)
88
191
#endif
89
192
#if defined(TRIO_COMPILER_ANCIENT)
90
193
# include <varargs.h>
92
195
# include <stdarg.h>
93
196
#endif
94
197
#include <stddef.h>
95
 
#include <errno.h>
 
198
#if defined(TRIO_PLATFORM_WINCE)
 
199
extern int errno;
 
200
#else
 
201
# include <errno.h>
 
202
#endif
96
203
 
97
204
#ifndef NULL
98
205
# define NULL 0
107
214
/* mincore() can be used for debugging purposes */
108
215
#define VALID(x) (NULL != (x))
109
216
 
110
 
#if TRIO_ERRORS
 
217
#if TRIO_FEATURE_ERRORCODE
111
218
  /*
112
219
   * Encode the error code and the position. This is decoded
113
220
   * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
127
234
# include <unistd.h>
128
235
# include <signal.h>
129
236
# include <locale.h>
130
 
# define USE_LOCALE
 
237
# if !defined(TRIO_FEATURE_LOCALE)
 
238
#  define USE_LOCALE
 
239
# endif
131
240
#endif /* TRIO_PLATFORM_UNIX */
132
241
#if defined(TRIO_PLATFORM_VMS)
133
242
# include <unistd.h>
134
243
#endif
135
244
#if defined(TRIO_PLATFORM_WIN32)
136
 
# include <io.h>
137
 
# define read _read
138
 
# define write _write
 
245
# if defined(TRIO_PLATFORM_WINCE)
 
246
int read(int handle, char *buffer, unsigned int length);
 
247
int write(int handle, const char *buffer, unsigned int length);
 
248
# else
 
249
#  include <io.h>
 
250
#  define read _read
 
251
#  define write _write
 
252
# endif
139
253
#endif /* TRIO_PLATFORM_WIN32 */
140
254
 
141
 
#if TRIO_WIDECHAR
142
 
# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
 
255
#if TRIO_FEATURE_WIDECHAR
 
256
# if defined(PREDEF_STANDARD_C94)
143
257
#  include <wchar.h>
144
258
#  include <wctype.h>
145
259
typedef wchar_t trio_wchar_t;
151
265
#  define WEOF EOF
152
266
#  define iswalnum(x) isalnum(x)
153
267
#  define iswalpha(x) isalpha(x)
154
 
#  define iswblank(x) isblank(x)
155
268
#  define iswcntrl(x) iscntrl(x)
156
269
#  define iswdigit(x) isdigit(x)
157
270
#  define iswgraph(x) isgraph(x)
174
287
# if !defined(USE_LONGLONG)
175
288
#  if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
176
289
#   define USE_LONGLONG
177
 
#  elif defined(TRIO_COMPILER_SUNPRO)
178
 
#   define USE_LONGLONG
179
 
#  elif defined(_LONG_LONG) || defined(_LONGLONG)
180
 
#   define USE_LONGLONG
 
290
#  else
 
291
#   if defined(TRIO_COMPILER_SUNPRO)
 
292
#    define USE_LONGLONG
 
293
#   else
 
294
#    if defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1400)
 
295
#     define USE_LONGLONG
 
296
#    else
 
297
#     if defined(_LONG_LONG) || defined(_LONGLONG)
 
298
#      define USE_LONGLONG
 
299
#     endif
 
300
#    endif
 
301
#   endif
181
302
#  endif
182
303
# endif
183
304
#endif
186
307
#if defined(USE_LONGLONG)
187
308
typedef signed long long int trio_longlong_t;
188
309
typedef unsigned long long int trio_ulonglong_t;
189
 
#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
 
310
#else
 
311
# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
190
312
typedef signed __int64 trio_longlong_t;
191
313
typedef unsigned __int64 trio_ulonglong_t;
192
 
#else
 
314
# else
193
315
typedef TRIO_SIGNED long int trio_longlong_t;
194
316
typedef unsigned long int trio_ulonglong_t;
 
317
# endif
195
318
#endif
196
319
 
197
320
/* Maximal and fixed integer types */
198
 
#if defined(TRIO_COMPILER_SUPPORTS_C99)
 
321
#if defined(PREDEF_STANDARD_C99)
199
322
# include <stdint.h>
200
323
typedef intmax_t trio_intmax_t;
201
324
typedef uintmax_t trio_uintmax_t;
203
326
typedef int16_t trio_int16_t;
204
327
typedef int32_t trio_int32_t;
205
328
typedef int64_t trio_int64_t;
206
 
#elif defined(TRIO_COMPILER_SUPPORTS_UNIX98)
207
 
# include <inttypes.h>
 
329
#else
 
330
# if defined(PREDEF_STANDARD_UNIX98)
 
331
#  include <inttypes.h>
208
332
typedef intmax_t trio_intmax_t;
209
333
typedef uintmax_t trio_uintmax_t;
210
334
typedef int8_t trio_int8_t;
211
335
typedef int16_t trio_int16_t;
212
336
typedef int32_t trio_int32_t;
213
337
typedef int64_t trio_int64_t;
214
 
#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
 
338
# else
 
339
#  if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
215
340
typedef trio_longlong_t trio_intmax_t;
216
341
typedef trio_ulonglong_t trio_uintmax_t;
217
342
typedef __int8 trio_int8_t;
218
343
typedef __int16 trio_int16_t;
219
344
typedef __int32 trio_int32_t;
220
345
typedef __int64 trio_int64_t;
221
 
#else
 
346
#  else
222
347
typedef trio_longlong_t trio_intmax_t;
223
348
typedef trio_ulonglong_t trio_uintmax_t;
224
 
# if defined(TRIO_INT8_T)
 
349
#   if defined(TRIO_INT8_T)
225
350
typedef TRIO_INT8_T trio_int8_t;
226
 
# else
 
351
#   else
227
352
typedef TRIO_SIGNED char trio_int8_t;
228
 
# endif
229
 
# if defined(TRIO_INT16_T)
 
353
#   endif
 
354
#   if defined(TRIO_INT16_T)
230
355
typedef TRIO_INT16_T trio_int16_t;
231
 
# else
 
356
#   else
232
357
typedef TRIO_SIGNED short trio_int16_t;
233
 
# endif
234
 
# if defined(TRIO_INT32_T)
 
358
#   endif
 
359
#   if defined(TRIO_INT32_T)
235
360
typedef TRIO_INT32_T trio_int32_t;
236
 
# else
 
361
#   else
237
362
typedef TRIO_SIGNED int trio_int32_t;
238
 
# endif
239
 
# if defined(TRIO_INT64_T)
 
363
#   endif
 
364
#   if defined(TRIO_INT64_T)
240
365
typedef TRIO_INT64_T trio_int64_t;
241
 
# else
 
366
#   else
242
367
typedef trio_longlong_t trio_int64_t;
 
368
#   endif
 
369
#  endif
243
370
# endif
244
371
#endif
245
372
 
246
 
#if !(defined(TRIO_COMPILER_SUPPORTS_C99) \
247
 
 || defined(TRIO_COMPILER_SUPPORTS_UNIX01))
248
 
# define floorl(x) floor((double)(x))
249
 
# define fmodl(x,y) fmod((double)(x),(double)(y))
250
 
# define powl(x,y) pow((double)(x),(double)(y))
251
 
#endif
252
 
 
253
 
#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
 
373
#if defined(HAVE_FLOORL)
 
374
# define trio_floor(x) floorl((x))
 
375
#else
 
376
# define trio_floor(x) floor((double)(x))
 
377
#endif
 
378
 
 
379
#if defined(HAVE_CEILL)
 
380
# define trio_ceil(x) ceill((x))
 
381
#else
 
382
# define trio_ceil(x) ceil((double)(x))
 
383
#endif
 
384
 
 
385
#if defined(HAVE_FMODL)
 
386
# define trio_fmod(x,y) fmodl((x),(y))
 
387
#else
 
388
# define trio_fmod(x,y) fmod((double)(x),(double)(y))
 
389
#endif
 
390
 
 
391
#if defined(HAVE_POWL)
 
392
# define trio_pow(x,y) powl((x),(y))
 
393
#else
 
394
# define trio_pow(x,y) pow((double)(x),(double)(y))
 
395
#endif
 
396
 
 
397
#if defined(HAVE_LOG10L)
 
398
# define trio_log10(x) log10l((x))
 
399
#else
 
400
# define trio_log10(x) log10((double)(x))
 
401
#endif
 
402
 
 
403
#if TRIO_FEATURE_FLOAT
 
404
# define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
 
405
#endif
254
406
 
255
407
/*************************************************************************
256
408
 * Internal Definitions
257
409
 */
258
410
 
259
 
#ifndef DECIMAL_DIG
260
 
# define DECIMAL_DIG DBL_DIG
261
 
#endif
 
411
#if TRIO_FEATURE_FLOAT
 
412
 
 
413
# if !defined(DECIMAL_DIG)
 
414
#  define DECIMAL_DIG DBL_DIG
 
415
# endif
262
416
 
263
417
/* Long double sizes */
264
 
#ifdef LDBL_DIG
265
 
# define MAX_MANTISSA_DIGITS LDBL_DIG
266
 
# define MAX_EXPONENT_DIGITS 4
267
 
# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
268
 
#else
269
 
# define MAX_MANTISSA_DIGITS DECIMAL_DIG
270
 
# define MAX_EXPONENT_DIGITS 3
271
 
# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
272
 
#endif
273
 
 
274
 
#if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
275
 
# undef LDBL_DIG
276
 
# undef LDBL_MANT_DIG
277
 
# undef LDBL_EPSILON
278
 
# define LDBL_DIG DBL_DIG
279
 
# define LDBL_MANT_DIG DBL_MANT_DIG
280
 
# define LDBL_EPSILON DBL_EPSILON
281
 
#endif
 
418
# ifdef LDBL_DIG
 
419
#  define MAX_MANTISSA_DIGITS LDBL_DIG
 
420
#  define MAX_EXPONENT_DIGITS 4
 
421
#  define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
 
422
# else
 
423
#  define MAX_MANTISSA_DIGITS DECIMAL_DIG
 
424
#  define MAX_EXPONENT_DIGITS 3
 
425
#  define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
 
426
# endif
 
427
 
 
428
# if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
 
429
#  undef LDBL_DIG
 
430
#  undef LDBL_MANT_DIG
 
431
#  undef LDBL_EPSILON
 
432
#  define LDBL_DIG DBL_DIG
 
433
#  define LDBL_MANT_DIG DBL_MANT_DIG
 
434
#  define LDBL_EPSILON DBL_EPSILON
 
435
# endif
 
436
 
 
437
#endif /* TRIO_FEATURE_FLOAT */
282
438
 
283
439
/* The maximal number of digits is for base 2 */
284
440
#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
285
441
/* The width of a pointer. The number of bits in a hex digit is 4 */
286
442
#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
287
443
 
 
444
#if TRIO_FEATURE_FLOAT
288
445
/* Infinite and Not-A-Number for floating-point */
289
 
#define INFINITE_LOWER "inf"
290
 
#define INFINITE_UPPER "INF"
291
 
#define LONG_INFINITE_LOWER "infinite"
292
 
#define LONG_INFINITE_UPPER "INFINITE"
293
 
#define NAN_LOWER "nan"
294
 
#define NAN_UPPER "NAN"
 
446
# define INFINITE_LOWER "inf"
 
447
# define INFINITE_UPPER "INF"
 
448
# define LONG_INFINITE_LOWER "infinite"
 
449
# define LONG_INFINITE_UPPER "INFINITE"
 
450
# define NAN_LOWER "nan"
 
451
# define NAN_UPPER "NAN"
 
452
#endif
295
453
 
296
454
/* Various constants */
297
455
enum {
298
456
  TYPE_PRINT = 1,
 
457
#if TRIO_FEATURE_SCANF
299
458
  TYPE_SCAN  = 2,
 
459
#endif
300
460
 
301
461
  /* Flags. FLAGS_LAST must be less than ULONG_MAX */
302
462
  FLAGS_NEW                 = 0,
326
486
  FLAGS_FLOAT_G             = 2 * FLAGS_FLOAT_E,
327
487
  FLAGS_QUOTE               = 2 * FLAGS_FLOAT_G,
328
488
  FLAGS_WIDECHAR            = 2 * FLAGS_QUOTE,
329
 
  FLAGS_ALLOC               = 2 * FLAGS_WIDECHAR,
330
 
  FLAGS_IGNORE              = 2 * FLAGS_ALLOC,
 
489
  FLAGS_IGNORE              = 2 * FLAGS_WIDECHAR,
331
490
  FLAGS_IGNORE_PARAMETER    = 2 * FLAGS_IGNORE,
332
491
  FLAGS_VARSIZE_PARAMETER   = 2 * FLAGS_IGNORE_PARAMETER,
333
492
  FLAGS_FIXED_SIZE          = 2 * FLAGS_VARSIZE_PARAMETER,
335
494
  /* Reused flags */
336
495
  FLAGS_EXCLUDE             = FLAGS_SHORT,
337
496
  FLAGS_USER_DEFINED        = FLAGS_IGNORE,
 
497
  FLAGS_USER_DEFINED_PARAMETER = FLAGS_IGNORE_PARAMETER,
338
498
  FLAGS_ROUNDING            = FLAGS_INTMAX_T,
339
499
  /* Compounded flags */
340
500
  FLAGS_ALL_VARSIZES        = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
359
519
  /* Maximal number of characters in class */
360
520
  MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
361
521
 
 
522
#if TRIO_FEATURE_USER_DEFINED
362
523
  /* Maximal string lengths for user-defined specifiers */
363
524
  MAX_USER_NAME = 64,
364
525
  MAX_USER_DATA = 256,
 
526
#endif
365
527
  
366
528
  /* Maximal length of locale separator strings */
367
529
  MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
368
530
  /* Maximal number of integers in grouping */
369
 
  MAX_LOCALE_GROUPS = 64,
370
 
 
371
 
  /* Initial size of asprintf buffer */
372
 
  DYNAMIC_START_SIZE = 32
 
531
  MAX_LOCALE_GROUPS = 64
373
532
};
374
533
 
375
534
#define NO_GROUPING ((int)CHAR_MAX)
376
535
 
377
536
/* Fundamental formatting parameter types */
 
537
#define FORMAT_SENTINEL  -1     /* marks end of parameters array */
378
538
#define FORMAT_UNKNOWN   0
379
539
#define FORMAT_INT       1
380
540
#define FORMAT_DOUBLE    2
384
544
#define FORMAT_COUNT     6
385
545
#define FORMAT_PARAMETER 7
386
546
#define FORMAT_GROUP     8
387
 
#if TRIO_GNU
388
 
# define FORMAT_ERRNO    9
389
 
#endif
390
 
#if TRIO_EXTENSION
391
 
# define FORMAT_USER_DEFINED 10
392
 
#endif
 
547
#define FORMAT_ERRNO     9
 
548
#define FORMAT_USER_DEFINED 10
393
549
 
394
550
/* Character constants */
395
551
#define CHAR_IDENTIFIER '%'
 
552
#define CHAR_ALT_IDENTIFIER '$'
396
553
#define CHAR_BACKSLASH '\\'
397
554
#define CHAR_QUOTE '\"'
398
555
#define CHAR_ADJUST ' '
399
556
 
 
557
#if TRIO_EXTENSION
400
558
/* Character class expressions */
401
 
#define CLASS_ALNUM "[:alnum:]"
402
 
#define CLASS_ALPHA "[:alpha:]"
403
 
#define CLASS_BLANK "[:blank:]"
404
 
#define CLASS_CNTRL "[:cntrl:]"
405
 
#define CLASS_DIGIT "[:digit:]"
406
 
#define CLASS_GRAPH "[:graph:]"
407
 
#define CLASS_LOWER "[:lower:]"
408
 
#define CLASS_PRINT "[:print:]"
409
 
#define CLASS_PUNCT "[:punct:]"
410
 
#define CLASS_SPACE "[:space:]"
411
 
#define CLASS_UPPER "[:upper:]"
412
 
#define CLASS_XDIGIT "[:xdigit:]"
 
559
# define CLASS_ALNUM "[:alnum:]"
 
560
# define CLASS_ALPHA "[:alpha:]"
 
561
# define CLASS_BLANK "[:blank:]"
 
562
# define CLASS_CNTRL "[:cntrl:]"
 
563
# define CLASS_DIGIT "[:digit:]"
 
564
# define CLASS_GRAPH "[:graph:]"
 
565
# define CLASS_LOWER "[:lower:]"
 
566
# define CLASS_PRINT "[:print:]"
 
567
# define CLASS_PUNCT "[:punct:]"
 
568
# define CLASS_SPACE "[:space:]"
 
569
# define CLASS_UPPER "[:upper:]"
 
570
# define CLASS_XDIGIT "[:xdigit:]"
 
571
#endif
413
572
 
414
573
/*
415
574
 * SPECIFIERS:
451
610
#define SPECIFIER_OCTAL 'o'
452
611
#define SPECIFIER_HEX 'x'
453
612
#define SPECIFIER_HEX_UPPER 'X'
454
 
#define SPECIFIER_FLOAT_E 'e'
455
 
#define SPECIFIER_FLOAT_E_UPPER 'E'
456
 
#define SPECIFIER_FLOAT_F 'f'
457
 
#define SPECIFIER_FLOAT_F_UPPER 'F'
458
 
#define SPECIFIER_FLOAT_G 'g'
459
 
#define SPECIFIER_FLOAT_G_UPPER 'G'
 
613
#if TRIO_FEATURE_FLOAT
 
614
# define SPECIFIER_FLOAT_E 'e'
 
615
# define SPECIFIER_FLOAT_E_UPPER 'E'
 
616
# define SPECIFIER_FLOAT_F 'f'
 
617
# define SPECIFIER_FLOAT_F_UPPER 'F'
 
618
# define SPECIFIER_FLOAT_G 'g'
 
619
# define SPECIFIER_FLOAT_G_UPPER 'G'
 
620
#endif
460
621
#define SPECIFIER_POINTER 'p'
461
 
#define SPECIFIER_GROUP '['
462
 
#define SPECIFIER_UNGROUP ']'
 
622
#if TRIO_FEATURE_SCANF
 
623
# define SPECIFIER_GROUP '['
 
624
# define SPECIFIER_UNGROUP ']'
 
625
#endif
463
626
#define SPECIFIER_COUNT 'n'
464
627
#if TRIO_UNIX98
465
628
# define SPECIFIER_CHAR_UPPER 'C'
466
629
# define SPECIFIER_STRING_UPPER 'S'
467
630
#endif
468
 
#if TRIO_C99
469
 
# define SPECIFIER_HEXFLOAT 'a'
470
 
# define SPECIFIER_HEXFLOAT_UPPER 'A'
471
 
#endif
472
 
#if TRIO_GNU
473
 
# define SPECIFIER_ERRNO 'm'
474
 
#endif
475
 
#if TRIO_EXTENSION
 
631
#define SPECIFIER_HEXFLOAT 'a'
 
632
#define SPECIFIER_HEXFLOAT_UPPER 'A'
 
633
#define SPECIFIER_ERRNO 'm'
 
634
#if TRIO_FEATURE_BINARY
476
635
# define SPECIFIER_BINARY 'b'
477
636
# define SPECIFIER_BINARY_UPPER 'B'
 
637
#endif
 
638
#if TRIO_FEATURE_USER_DEFINED
478
639
# define SPECIFIER_USER_DEFINED_BEGIN '<'
479
640
# define SPECIFIER_USER_DEFINED_END '>'
480
641
# define SPECIFIER_USER_DEFINED_SEPARATOR ':'
 
642
# define SPECIFIER_USER_DEFINED_EXTRA '|'
481
643
#endif
482
644
 
483
645
/*
580
742
#define QUALIFIER_DOT '.'
581
743
#define QUALIFIER_STAR '*'
582
744
#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
583
 
#if TRIO_C99
584
 
# define QUALIFIER_SIZE_T 'z'
585
 
# define QUALIFIER_PTRDIFF_T 't'
586
 
# define QUALIFIER_INTMAX_T 'j'
587
 
#endif
588
 
#if TRIO_BSD || TRIO_GNU
589
 
# define QUALIFIER_QUAD 'q'
590
 
#endif
591
 
#if TRIO_GNU
592
 
# define QUALIFIER_SIZE_T_UPPER 'Z'
593
 
#endif
 
745
#define QUALIFIER_SIZE_T 'z'
 
746
#define QUALIFIER_PTRDIFF_T 't'
 
747
#define QUALIFIER_INTMAX_T 'j'
 
748
#define QUALIFIER_QUAD 'q'
 
749
#define QUALIFIER_SIZE_T_UPPER 'Z'
594
750
#if TRIO_MISC
595
751
# define QUALIFIER_WIDECHAR 'w'
596
752
#endif
597
 
#if TRIO_MICROSOFT
598
 
# define QUALIFIER_FIXED_SIZE 'I'
599
 
#endif
 
753
#define QUALIFIER_FIXED_SIZE 'I'
 
754
#define QUALIFIER_QUOTE '\''
 
755
#define QUALIFIER_STICKY '!'
 
756
#define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
 
757
#define QUALIFIER_ROUNDING_UPPER 'R'
600
758
#if TRIO_EXTENSION
601
 
# define QUALIFIER_QUOTE '\''
602
 
# define QUALIFIER_STICKY '!'
603
 
# define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
604
759
# define QUALIFIER_PARAM '@' /* Experimental */
605
760
# define QUALIFIER_COLON ':' /* For scanlists */
606
761
# define QUALIFIER_EQUAL '=' /* For scanlists */
607
 
# define QUALIFIER_ROUNDING_UPPER 'R'
608
762
#endif
609
763
 
610
764
 
626
780
  int precision;
627
781
  /* The base qualifier */
628
782
  int base;
 
783
  /* Base from specifier */
 
784
  int baseSpecifier;
629
785
  /* The size for the variable size qualifier */
630
786
  int varsize;
631
 
  /* The marker of the end of the specifier */
632
 
  int indexAfterSpecifier;
 
787
  /* Offset of the first character of the specifier */
 
788
  int beginOffset;
 
789
  /* Offset of the first character after the specifier */
 
790
  int endOffset;
 
791
  /* Position in the argument list that this parameter refers to */
 
792
  int position;
633
793
  /* The data from the argument list */
634
794
  union {
635
795
    char *string;
636
 
#if TRIO_WIDECHAR
 
796
#if TRIO_FEATURE_WIDECHAR
637
797
    trio_wchar_t *wstring;
638
798
#endif
639
799
    trio_pointer_t pointer;
641
801
      trio_intmax_t as_signed;
642
802
      trio_uintmax_t as_unsigned;
643
803
    } number;
 
804
#if TRIO_FEATURE_FLOAT
644
805
    double doubleNumber;
645
806
    double *doublePointer;
646
807
    trio_long_double_t longdoubleNumber;
647
808
    trio_long_double_t *longdoublePointer;
 
809
#endif
648
810
    int errorNumber;
649
811
  } data;
 
812
#if TRIO_FEATURE_USER_DEFINED
650
813
  /* For the user-defined specifier */
651
 
  char user_name[MAX_USER_NAME];
 
814
  union {
 
815
    char namespace[MAX_USER_NAME];
 
816
    int handler;        /* if flags & FLAGS_USER_DEFINED_PARAMETER */
 
817
  } user_defined;
652
818
  char user_data[MAX_USER_DATA];
 
819
#endif
653
820
} trio_parameter_t;
654
821
 
655
822
/* Container for customized functions */
672
839
   */
673
840
  void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
674
841
  /*
 
842
   * The function to undo read characters from a stream.
 
843
   */
 
844
  void (*UndoStream) TRIO_PROTO((struct _trio_class_t *));
 
845
  /*
675
846
   * The current location in the stream.
676
847
   */
677
848
  trio_pointer_t location;
684
855
   * if there had been sufficient space.
685
856
   */
686
857
  int processed;
687
 
  /*
688
 
   * The number of characters that are actually written/read.
689
 
   * Processed and committed will only differ for the *nprintf
690
 
   * and *nscanf functions.
691
 
   */
692
 
  int committed;
 
858
  union {
 
859
    /*
 
860
     * The number of characters that are actually written. Processed and
 
861
     * committed will only differ for the *nprintf functions.
 
862
     */
 
863
    int committed;
 
864
    /*
 
865
     * The number of look-ahead characters read.
 
866
     */
 
867
    int cached;
 
868
  } actually;
693
869
  /*
694
870
   * The upper limit of characters that may be written/read.
695
871
   */
706
882
  trio_parameter_t *parameter;
707
883
} trio_reference_t;
708
884
 
 
885
#if TRIO_FEATURE_USER_DEFINED
709
886
/* Registered entries (for user-defined callbacks) */
710
887
typedef struct _trio_userdef_t {
711
888
  struct _trio_userdef_t *next;
712
889
  trio_callback_t callback;
713
890
  char *name;
714
891
} trio_userdef_t;
 
892
#endif
715
893
 
716
894
/*************************************************************************
717
895
 *
719
897
 *
720
898
 *************************************************************************/
721
899
 
722
 
static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $";
 
900
static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.129 2009/09/20 11:37:15 breese Exp $";
723
901
 
 
902
#if TRIO_FEATURE_FLOAT
724
903
/*
725
904
 * Need this to workaround a parser bug in HP C/iX compiler that fails
726
905
 * to resolves macro definitions that includes type 'long double',
727
906
 * e.g: va_arg(arg_ptr, long double)
728
907
 */
729
 
#if defined(TRIO_PLATFORM_MPEIX)
 
908
# if defined(TRIO_PLATFORM_MPEIX)
730
909
static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
 
910
# endif
731
911
#endif
732
912
 
733
913
static TRIO_CONST char internalNullString[] = "(nil)";
740
920
 * UNIX98 says "in a locale where the radix character is not defined,
741
921
 * the radix character defaults to a period (.)"
742
922
 */
 
923
#if TRIO_FEATURE_FLOAT || TRIO_FEATURE_LOCALE || defined(USE_LOCALE)
743
924
static int internalDecimalPointLength = 1;
744
 
static int internalThousandSeparatorLength = 1;
745
925
static char internalDecimalPoint = '.';
746
926
static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
 
927
#endif
 
928
#if TRIO_FEATURE_QUOTE || TRIO_FEATURE_LOCALE || TRIO_EXTENSION
 
929
static int internalThousandSeparatorLength = 1;
747
930
static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
748
931
static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
 
932
#endif
749
933
 
750
934
static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
751
935
static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
936
#if TRIO_FEATURE_SCANF
752
937
static BOOLEAN_T internalDigitsUnconverted = TRUE;
753
938
static int internalDigitArray[128];
754
 
#if TRIO_EXTENSION
 
939
# if TRIO_EXTENSION
755
940
static BOOLEAN_T internalCollationUnconverted = TRUE;
756
941
static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
 
942
# endif
757
943
#endif
758
944
 
759
 
#if TRIO_EXTENSION
 
945
#if TRIO_FEATURE_USER_DEFINED
760
946
static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
761
947
static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
762
948
static trio_userdef_t *internalUserDef = NULL;
769
955
 *
770
956
 ************************************************************************/
771
957
 
772
 
#if defined(TRIO_MINIMAL)
773
 
# define TRIO_STRING_PUBLIC static
 
958
#if defined(TRIO_EMBED_NAN)
 
959
# include "trionan.c"
 
960
#endif
 
961
 
 
962
#if defined(TRIO_EMBED_STRING)
774
963
# include "triostr.c"
775
 
#endif /* defined(TRIO_MINIMAL) */
 
964
#endif
 
965
 
 
966
/*************************************************************************
 
967
 * TrioInitializeParameter
 
968
 *
 
969
 * Description:
 
970
 *  Initialize a trio_parameter_t struct.
 
971
 */
 
972
TRIO_PRIVATE void
 
973
TrioInitializeParameter
 
974
TRIO_ARGS1((parameter),
 
975
           trio_parameter_t *parameter)
 
976
{
 
977
  parameter->type = FORMAT_UNKNOWN;
 
978
  parameter->flags = 0;
 
979
  parameter->width = 0;
 
980
  parameter->precision = 0;
 
981
  parameter->base = 0;
 
982
  parameter->baseSpecifier = 0;
 
983
  parameter->varsize = 0;
 
984
  parameter->beginOffset = 0;
 
985
  parameter->endOffset = 0;
 
986
  parameter->position = 0;
 
987
  parameter->data.pointer = 0;
 
988
#if TRIO_FEATURE_USER_DEFINED
 
989
  parameter->user_defined.handler = 0;
 
990
  parameter->user_data[0] = 0;
 
991
#endif
 
992
}
 
993
 
 
994
/*************************************************************************
 
995
 * TrioCopyParameter
 
996
 *
 
997
 * Description:
 
998
 *  Copies one trio_parameter_t struct to another.
 
999
 */
 
1000
TRIO_PRIVATE void
 
1001
TrioCopyParameter
 
1002
TRIO_ARGS2((target, source),
 
1003
           trio_parameter_t *target,
 
1004
           TRIO_CONST trio_parameter_t *source)
 
1005
{
 
1006
#if TRIO_FEATURE_USER_DEFINED
 
1007
  size_t i;
 
1008
#endif
 
1009
 
 
1010
  target->type = source->type;
 
1011
  target->flags = source->flags;
 
1012
  target->width = source->width;
 
1013
  target->precision = source->precision;
 
1014
  target->base = source->base;
 
1015
  target->baseSpecifier = source->baseSpecifier;
 
1016
  target->varsize = source->varsize;
 
1017
  target->beginOffset = source->beginOffset;
 
1018
  target->endOffset = source->endOffset;
 
1019
  target->position = source->position;
 
1020
  target->data = source->data;
 
1021
 
 
1022
#if TRIO_FEATURE_USER_DEFINED
 
1023
  target->user_defined = source->user_defined;
 
1024
 
 
1025
  for (i = 0U; i < sizeof(target->user_data); ++i)
 
1026
    {
 
1027
      if ((target->user_data[i] = source->user_data[i]) == NIL)
 
1028
        break;
 
1029
    }
 
1030
#endif
 
1031
}
776
1032
 
777
1033
/*************************************************************************
778
1034
 * TrioIsQualifier
799
1055
    case QUALIFIER_ALTERNATIVE:
800
1056
    case QUALIFIER_SHORT:
801
1057
    case QUALIFIER_LONG:
 
1058
    case QUALIFIER_CIRCUMFLEX:
802
1059
    case QUALIFIER_LONG_UPPER:
803
 
    case QUALIFIER_CIRCUMFLEX:
804
 
#if defined(QUALIFIER_SIZE_T)
805
1060
    case QUALIFIER_SIZE_T:
806
 
#endif
807
 
#if defined(QUALIFIER_PTRDIFF_T)
808
1061
    case QUALIFIER_PTRDIFF_T:
809
 
#endif
810
 
#if defined(QUALIFIER_INTMAX_T)
811
1062
    case QUALIFIER_INTMAX_T:
812
 
#endif
813
 
#if defined(QUALIFIER_QUAD)
814
1063
    case QUALIFIER_QUAD:
815
 
#endif
816
 
#if defined(QUALIFIER_SIZE_T_UPPER)
817
1064
    case QUALIFIER_SIZE_T_UPPER:
818
 
#endif
819
1065
#if defined(QUALIFIER_WIDECHAR)
820
1066
    case QUALIFIER_WIDECHAR:
821
1067
#endif
822
 
#if defined(QUALIFIER_QUOTE)
823
1068
    case QUALIFIER_QUOTE:
824
 
#endif
825
 
#if defined(QUALIFIER_STICKY)
826
1069
    case QUALIFIER_STICKY:
827
 
#endif
828
 
#if defined(QUALIFIER_VARSIZE)
829
1070
    case QUALIFIER_VARSIZE:
830
 
#endif
831
1071
#if defined(QUALIFIER_PARAM)
832
1072
    case QUALIFIER_PARAM:
833
1073
#endif
834
 
#if defined(QUALIFIER_FIXED_SIZE)
835
1074
    case QUALIFIER_FIXED_SIZE:
836
 
#endif
837
 
#if defined(QUALIFIER_ROUNDING_UPPER)
838
1075
    case QUALIFIER_ROUNDING_UPPER:
839
 
#endif
840
1076
      return TRUE;
841
1077
    default:
842
1078
      return FALSE;
869
1105
                            internalLocaleValues->decimal_point);
870
1106
            }
871
1107
        }
 
1108
# if TRIO_EXTENSION
872
1109
      if ((internalLocaleValues->thousands_sep) &&
873
1110
          (internalLocaleValues->thousands_sep[0] != NIL))
874
1111
        {
877
1114
                        internalLocaleValues->thousands_sep);
878
1115
          internalThousandSeparatorLength = trio_length(internalThousandSeparator);
879
1116
        }
 
1117
# endif
 
1118
# if TRIO_EXTENSION
880
1119
      if ((internalLocaleValues->grouping) &&
881
1120
          (internalLocaleValues->grouping[0] != NIL))
882
1121
        {
884
1123
                        sizeof(internalGrouping),
885
1124
                        internalLocaleValues->grouping);
886
1125
        }
 
1126
# endif
887
1127
    }
888
1128
}
889
1129
#endif /* defined(USE_LOCALE) */
890
1130
 
 
1131
#if TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE
891
1132
TRIO_PRIVATE int
892
1133
TrioCalcThousandSeparatorLength
893
1134
TRIO_ARGS1((digits),
894
1135
           int digits)
895
1136
{
896
 
#if TRIO_EXTENSION
897
1137
  int count = 0;
898
1138
  int step = NO_GROUPING;
899
1139
  char *groupingPointer = internalGrouping;
923
1163
      digits -= step;
924
1164
    }
925
1165
  return count;
926
 
#else
927
 
  return 0;
928
 
#endif
929
1166
}
 
1167
#endif /* TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE */
930
1168
 
 
1169
#if TRIO_FEATURE_QUOTE
931
1170
TRIO_PRIVATE BOOLEAN_T
932
1171
TrioFollowedBySeparator
933
1172
TRIO_ARGS1((position),
934
1173
           int position)
935
1174
{
936
 
#if TRIO_EXTENSION
937
1175
  int step = 0;
938
1176
  char *groupingPointer = internalGrouping;
939
1177
 
956
1194
      position -= step;
957
1195
    }
958
1196
  return (position == 0);
959
 
#else
960
 
  return FALSE;
961
 
#endif
962
1197
}
 
1198
#endif /* TRIO_FEATURE_QUOTE */
963
1199
 
964
1200
/*************************************************************************
965
1201
 * TrioGetPosition
968
1204
 */
969
1205
TRIO_PRIVATE int
970
1206
TrioGetPosition
971
 
TRIO_ARGS2((format, indexPointer),
 
1207
TRIO_ARGS2((format, offsetPointer),
972
1208
           TRIO_CONST char *format,
973
 
           int *indexPointer)
 
1209
           int *offsetPointer)
974
1210
{
975
 
#if TRIO_UNIX98
 
1211
#if TRIO_FEATURE_POSITIONAL
976
1212
  char *tmpformat;
977
1213
  int number = 0;
978
 
  int index = *indexPointer;
 
1214
  int offset = *offsetPointer;
979
1215
 
980
 
  number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
981
 
  index = (int)(tmpformat - format);
982
 
  if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
 
1216
  number = (int)trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL);
 
1217
  offset = (int)(tmpformat - format);
 
1218
  if ((number != 0) && (QUALIFIER_POSITION == format[offset++]))
983
1219
    {
984
 
      *indexPointer = index;
 
1220
      *offsetPointer = offset;
985
1221
      /*
986
1222
       * number is decreased by 1, because n$ starts from 1, whereas
987
1223
       * the array it is indexing starts from 0.
992
1228
  return NO_POSITION;
993
1229
}
994
1230
 
995
 
#if TRIO_EXTENSION
996
1231
/*************************************************************************
997
1232
 * TrioFindNamespace
998
1233
 *
999
1234
 * Find registered user-defined specifier.
1000
1235
 * The prev argument is used for optimization only.
1001
1236
 */
 
1237
#if TRIO_FEATURE_USER_DEFINED
1002
1238
TRIO_PRIVATE trio_userdef_t *
1003
1239
TrioFindNamespace
1004
1240
TRIO_ARGS2((name, prev),
1033
1269
 * Description:
1034
1270
 *  Calculate pow(base, exponent), where number and exponent are integers.
1035
1271
 */
 
1272
#if TRIO_FEATURE_FLOAT
1036
1273
TRIO_PRIVATE trio_long_double_t
1037
1274
TrioPower
1038
1275
TRIO_ARGS2((number, exponent),
1077
1314
          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8);
1078
1315
          break;
1079
1316
        default:
1080
 
          result = powl((trio_long_double_t)number,
1081
 
                        (trio_long_double_t)exponent);
 
1317
          result = trio_pow((trio_long_double_t)number,
 
1318
                            (trio_long_double_t)exponent);
1082
1319
          break;
1083
1320
        }
1084
1321
    }
1085
1322
  else
1086
1323
    {
1087
 
      return powl((trio_long_double_t)number, (trio_long_double_t)exponent);
 
1324
      return trio_pow((trio_long_double_t)number,
 
1325
                      (trio_long_double_t)exponent);
1088
1326
    }
1089
1327
  return result;
1090
1328
}
 
1329
#endif /* TRIO_FEATURE_FLOAT */
1091
1330
 
1092
1331
/*************************************************************************
1093
1332
 * TrioLogarithm
1094
1333
 */
1095
 
TRIO_PRIVATE double
 
1334
#if TRIO_FEATURE_FLOAT
 
1335
TRIO_PRIVATE trio_long_double_t
1096
1336
TrioLogarithm
1097
1337
TRIO_ARGS2((number, base),
1098
 
           double number,
 
1338
           trio_long_double_t number,
1099
1339
           int base)
1100
1340
{
1101
 
  double result;
 
1341
  trio_long_double_t result;
1102
1342
 
1103
1343
  if (number <= 0.0)
1104
1344
    {
1109
1349
    {
1110
1350
      if (base == 10)
1111
1351
        {
1112
 
          result = log10(number);
 
1352
          result = trio_log10(number);
1113
1353
        }
1114
1354
      else
1115
1355
        {
1116
 
          result = log10(number) / log10((double)base);
 
1356
          result = trio_log10(number) / trio_log10((double)base);
1117
1357
        }
1118
1358
    }
1119
1359
  return result;
1120
1360
}
 
1361
#endif /* TRIO_FEATURE_FLOAT */
1121
1362
 
1122
1363
/*************************************************************************
1123
1364
 * TrioLogarithmBase
1124
1365
 */
 
1366
#if TRIO_FEATURE_FLOAT
1125
1367
TRIO_PRIVATE double
1126
1368
TrioLogarithmBase
1127
1369
TRIO_ARGS1((base),
1136
1378
    default          : return TrioLogarithm((double)base, 2);
1137
1379
    }
1138
1380
}
 
1381
#endif /* TRIO_FEATURE_FLOAT */
 
1382
 
 
1383
/*************************************************************************
 
1384
 * TrioParseQualifiers
 
1385
 *
 
1386
 * Description:
 
1387
 *  Parse the qualifiers of a potential conversion specifier
 
1388
 */
 
1389
TRIO_PRIVATE int
 
1390
TrioParseQualifiers
 
1391
TRIO_ARGS4((type, format, offset, parameter),
 
1392
           int type,
 
1393
           TRIO_CONST char *format,
 
1394
           int offset,
 
1395
           trio_parameter_t *parameter)
 
1396
{
 
1397
  char ch;
 
1398
  int dots = 0;  /* Count number of dots in modifier part */
 
1399
  char *tmpformat;
 
1400
 
 
1401
  parameter->beginOffset = offset - 1;
 
1402
  parameter->flags = FLAGS_NEW;
 
1403
  parameter->position = TrioGetPosition(format, &offset);
 
1404
 
 
1405
  /* Default values */
 
1406
  parameter->width = NO_WIDTH;
 
1407
  parameter->precision = NO_PRECISION;
 
1408
  parameter->base = NO_BASE;
 
1409
  parameter->varsize = NO_SIZE;
 
1410
 
 
1411
  while (TrioIsQualifier(format[offset]))
 
1412
    {
 
1413
      ch = format[offset++];
 
1414
 
 
1415
      switch (ch)
 
1416
        {
 
1417
        case QUALIFIER_SPACE:
 
1418
          parameter->flags |= FLAGS_SPACE;
 
1419
          break;
 
1420
 
 
1421
        case QUALIFIER_PLUS:
 
1422
          parameter->flags |= FLAGS_SHOWSIGN;
 
1423
          break;
 
1424
 
 
1425
        case QUALIFIER_MINUS:
 
1426
          parameter->flags |= FLAGS_LEFTADJUST;
 
1427
          parameter->flags &= ~FLAGS_NILPADDING;
 
1428
          break;
 
1429
 
 
1430
        case QUALIFIER_ALTERNATIVE:
 
1431
          parameter->flags |= FLAGS_ALTERNATIVE;
 
1432
          break;
 
1433
 
 
1434
        case QUALIFIER_DOT:
 
1435
          if (dots == 0) /* Precision */
 
1436
            {
 
1437
              dots++;
 
1438
 
 
1439
              /* Skip if no precision */
 
1440
              if (QUALIFIER_DOT == format[offset])
 
1441
                break;
 
1442
 
 
1443
              /* After the first dot we have the precision */
 
1444
              parameter->flags |= FLAGS_PRECISION;
 
1445
              if ((QUALIFIER_STAR == format[offset])
 
1446
#if defined(QUALIFIER_PARAM)
 
1447
                  || (QUALIFIER_PARAM == format[offset])
 
1448
#endif
 
1449
                  )
 
1450
                {
 
1451
                  offset++;
 
1452
                  parameter->flags |= FLAGS_PRECISION_PARAMETER;
 
1453
                  parameter->precision = TrioGetPosition(format, &offset);
 
1454
                }
 
1455
              else
 
1456
                {
 
1457
                  parameter->precision = trio_to_long(&format[offset],
 
1458
                                                      &tmpformat,
 
1459
                                                      BASE_DECIMAL);
 
1460
                  offset = (int)(tmpformat - format);
 
1461
                }
 
1462
            }
 
1463
          else if (dots == 1) /* Base */
 
1464
            {
 
1465
              dots++;
 
1466
 
 
1467
              /* After the second dot we have the base */
 
1468
              parameter->flags |= FLAGS_BASE;
 
1469
              if ((QUALIFIER_STAR == format[offset])
 
1470
#if defined(QUALIFIER_PARAM)
 
1471
                  || (QUALIFIER_PARAM == format[offset])
 
1472
#endif
 
1473
                  )
 
1474
                {
 
1475
                  offset++;
 
1476
                  parameter->flags |= FLAGS_BASE_PARAMETER;
 
1477
                  parameter->base = TrioGetPosition(format, &offset);
 
1478
                }
 
1479
              else
 
1480
                {
 
1481
                  parameter->base = trio_to_long(&format[offset],
 
1482
                                                 &tmpformat,
 
1483
                                                 BASE_DECIMAL);
 
1484
                  if (parameter->base > MAX_BASE)
 
1485
                    return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1486
                  offset = (int)(tmpformat - format);
 
1487
                }
 
1488
            }
 
1489
          else
 
1490
            {
 
1491
              return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1492
            }
 
1493
          break; /* QUALIFIER_DOT */
 
1494
 
 
1495
#if defined(QUALIFIER_PARAM)
 
1496
        case QUALIFIER_PARAM:
 
1497
          parameter->type = TYPE_PRINT;
 
1498
          /* FALLTHROUGH */
 
1499
#endif
 
1500
        case QUALIFIER_STAR:
 
1501
          /* This has different meanings for print and scan */
 
1502
          if (TYPE_PRINT == type)
 
1503
            {
 
1504
              /* Read with from parameter */
 
1505
              int width = TrioGetPosition(format, &offset);
 
1506
              parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
 
1507
              if (NO_POSITION != width)
 
1508
                parameter->width = width;
 
1509
              /* else keep parameter->width = NO_WIDTH which != NO_POSITION */
 
1510
            }
 
1511
#if TRIO_FEATURE_SCANF
 
1512
          else
 
1513
            {
 
1514
              /* Scan, but do not store result */
 
1515
              parameter->flags |= FLAGS_IGNORE;
 
1516
            }
 
1517
#endif
 
1518
          break; /* QUALIFIER_STAR */
 
1519
 
 
1520
        case '0':
 
1521
          if (! (parameter->flags & FLAGS_LEFTADJUST))
 
1522
            parameter->flags |= FLAGS_NILPADDING;
 
1523
          /* FALLTHROUGH */
 
1524
        case '1': case '2': case '3': case '4':
 
1525
        case '5': case '6': case '7': case '8': case '9':
 
1526
          parameter->flags |= FLAGS_WIDTH;
 
1527
          /*
 
1528
           * &format[offset - 1] is used to "rewind" the read
 
1529
           * character from format
 
1530
           */
 
1531
          parameter->width = trio_to_long(&format[offset - 1],
 
1532
                                          &tmpformat,
 
1533
                                          BASE_DECIMAL);
 
1534
          offset = (int)(tmpformat - format);
 
1535
          break;
 
1536
 
 
1537
        case QUALIFIER_SHORT:
 
1538
          if (parameter->flags & FLAGS_SHORTSHORT)
 
1539
            return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1540
          else if (parameter->flags & FLAGS_SHORT)
 
1541
            parameter->flags |= FLAGS_SHORTSHORT;
 
1542
          else
 
1543
            parameter->flags |= FLAGS_SHORT;
 
1544
          break;
 
1545
 
 
1546
        case QUALIFIER_LONG:
 
1547
          if (parameter->flags & FLAGS_QUAD)
 
1548
            return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1549
          else if (parameter->flags & FLAGS_LONG)
 
1550
            parameter->flags |= FLAGS_QUAD;
 
1551
          else
 
1552
            parameter->flags |= FLAGS_LONG;
 
1553
          break;
 
1554
 
 
1555
#if TRIO_FEATURE_LONGDOUBLE
 
1556
        case QUALIFIER_LONG_UPPER:
 
1557
          parameter->flags |= FLAGS_LONGDOUBLE;
 
1558
          break;
 
1559
#endif
 
1560
 
 
1561
#if TRIO_FEATURE_SIZE_T
 
1562
        case QUALIFIER_SIZE_T:
 
1563
          parameter->flags |= FLAGS_SIZE_T;
 
1564
          /* Modify flags for later truncation of number */
 
1565
          if (sizeof(size_t) == sizeof(trio_ulonglong_t))
 
1566
            parameter->flags |= FLAGS_QUAD;
 
1567
          else if (sizeof(size_t) == sizeof(long))
 
1568
            parameter->flags |= FLAGS_LONG;
 
1569
          break;
 
1570
#endif
 
1571
 
 
1572
#if TRIO_FEATURE_PTRDIFF_T
 
1573
        case QUALIFIER_PTRDIFF_T:
 
1574
          parameter->flags |= FLAGS_PTRDIFF_T;
 
1575
          if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
 
1576
            parameter->flags |= FLAGS_QUAD;
 
1577
          else if (sizeof(ptrdiff_t) == sizeof(long))
 
1578
            parameter->flags |= FLAGS_LONG;
 
1579
          break;
 
1580
#endif
 
1581
 
 
1582
#if TRIO_FEATURE_INTMAX_T
 
1583
        case QUALIFIER_INTMAX_T:
 
1584
          parameter->flags |= FLAGS_INTMAX_T;
 
1585
          if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
 
1586
            parameter->flags |= FLAGS_QUAD;
 
1587
          else if (sizeof(trio_intmax_t) == sizeof(long))
 
1588
            parameter->flags |= FLAGS_LONG;
 
1589
          break;
 
1590
#endif
 
1591
 
 
1592
#if TRIO_FEATURE_QUAD
 
1593
        case QUALIFIER_QUAD:
 
1594
          parameter->flags |= FLAGS_QUAD;
 
1595
          break;
 
1596
#endif
 
1597
 
 
1598
#if TRIO_FEATURE_FIXED_SIZE
 
1599
        case QUALIFIER_FIXED_SIZE:
 
1600
          if (parameter->flags & FLAGS_FIXED_SIZE)
 
1601
            return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1602
 
 
1603
          if (parameter->flags & (FLAGS_ALL_SIZES |
 
1604
                                  FLAGS_LONGDOUBLE |
 
1605
                                  FLAGS_WIDECHAR |
 
1606
                                  FLAGS_VARSIZE_PARAMETER))
 
1607
            return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1608
 
 
1609
          if ((format[offset] == '6') &&
 
1610
              (format[offset + 1] == '4'))
 
1611
            {
 
1612
              parameter->varsize = sizeof(trio_int64_t);
 
1613
              offset += 2;
 
1614
            }
 
1615
          else if ((format[offset] == '3') &&
 
1616
                   (format[offset + 1] == '2'))
 
1617
            {
 
1618
              parameter->varsize = sizeof(trio_int32_t);
 
1619
              offset += 2;
 
1620
            }
 
1621
          else if ((format[offset] == '1') &&
 
1622
                   (format[offset + 1] == '6'))
 
1623
            {
 
1624
              parameter->varsize = sizeof(trio_int16_t);
 
1625
              offset += 2;
 
1626
            }
 
1627
          else if (format[offset] == '8')
 
1628
            {
 
1629
              parameter->varsize = sizeof(trio_int8_t);
 
1630
              offset++;
 
1631
            }
 
1632
          else
 
1633
            return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1634
 
 
1635
          parameter->flags |= FLAGS_FIXED_SIZE;
 
1636
          break;
 
1637
#endif /* TRIO_FEATURE_FIXED_SIZE */
 
1638
 
 
1639
#if defined(QUALIFIER_WIDECHAR)
 
1640
        case QUALIFIER_WIDECHAR:
 
1641
          parameter->flags |= FLAGS_WIDECHAR;
 
1642
          break;
 
1643
#endif
 
1644
 
 
1645
#if TRIO_FEATURE_SIZE_T_UPPER
 
1646
        case QUALIFIER_SIZE_T_UPPER:
 
1647
          break;
 
1648
#endif
 
1649
 
 
1650
#if TRIO_FEATURE_QUOTE
 
1651
        case QUALIFIER_QUOTE:
 
1652
          parameter->flags |= FLAGS_QUOTE;
 
1653
          break;
 
1654
#endif
 
1655
 
 
1656
#if TRIO_FEATURE_STICKY
 
1657
        case QUALIFIER_STICKY:
 
1658
          parameter->flags |= FLAGS_STICKY;
 
1659
          break;
 
1660
#endif
 
1661
 
 
1662
#if TRIO_FEATURE_VARSIZE
 
1663
        case QUALIFIER_VARSIZE:
 
1664
          parameter->flags |= FLAGS_VARSIZE_PARAMETER;
 
1665
          break;
 
1666
#endif
 
1667
 
 
1668
#if TRIO_FEATURE_ROUNDING
 
1669
        case QUALIFIER_ROUNDING_UPPER:
 
1670
          parameter->flags |= FLAGS_ROUNDING;
 
1671
          break;
 
1672
#endif
 
1673
 
 
1674
        default:
 
1675
          /* Bail out completely to make the error more obvious */
 
1676
          return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1677
        }
 
1678
    } /* while qualifier */
 
1679
 
 
1680
  parameter->endOffset = offset;
 
1681
 
 
1682
  return 0;
 
1683
}
 
1684
 
 
1685
/*************************************************************************
 
1686
 * TrioParseSpecifier
 
1687
 *
 
1688
 * Description:
 
1689
 *  Parse the specifier part of a potential conversion specifier
 
1690
 */
 
1691
TRIO_PRIVATE int
 
1692
TrioParseSpecifier
 
1693
TRIO_ARGS4((type, format, offset, parameter),
 
1694
           int type,
 
1695
           TRIO_CONST char *format,
 
1696
           int offset,
 
1697
           trio_parameter_t *parameter)
 
1698
{
 
1699
  parameter->baseSpecifier = NO_BASE;
 
1700
 
 
1701
  switch (format[offset++])
 
1702
    {
 
1703
#if defined(SPECIFIER_CHAR_UPPER)
 
1704
    case SPECIFIER_CHAR_UPPER:
 
1705
      parameter->flags |= FLAGS_WIDECHAR;
 
1706
      /* FALLTHROUGH */
 
1707
#endif
 
1708
    case SPECIFIER_CHAR:
 
1709
      if (parameter->flags & FLAGS_LONG)
 
1710
        parameter->flags |= FLAGS_WIDECHAR;
 
1711
      else if (parameter->flags & FLAGS_SHORT)
 
1712
        parameter->flags &= ~FLAGS_WIDECHAR;
 
1713
      parameter->type = FORMAT_CHAR;
 
1714
      break;
 
1715
 
 
1716
#if defined(SPECIFIER_STRING_UPPER)
 
1717
    case SPECIFIER_STRING_UPPER:
 
1718
      parameter->flags |= FLAGS_WIDECHAR;
 
1719
      /* FALLTHROUGH */
 
1720
#endif
 
1721
    case SPECIFIER_STRING:
 
1722
      if (parameter->flags & FLAGS_LONG)
 
1723
        parameter->flags |= FLAGS_WIDECHAR;
 
1724
      else if (parameter->flags & FLAGS_SHORT)
 
1725
        parameter->flags &= ~FLAGS_WIDECHAR;
 
1726
      parameter->type = FORMAT_STRING;
 
1727
      break;
 
1728
 
 
1729
#if defined(SPECIFIER_GROUP)
 
1730
    case SPECIFIER_GROUP:
 
1731
      if (TYPE_SCAN == type)
 
1732
        {
 
1733
          int depth = 1;
 
1734
          parameter->type = FORMAT_GROUP;
 
1735
          if (format[offset] == QUALIFIER_CIRCUMFLEX)
 
1736
            offset++;
 
1737
          if (format[offset] == SPECIFIER_UNGROUP)
 
1738
            offset++;
 
1739
          if (format[offset] == QUALIFIER_MINUS)
 
1740
            offset++;
 
1741
          /* Skip nested brackets */
 
1742
          while (format[offset] != NIL)
 
1743
            {
 
1744
              if (format[offset] == SPECIFIER_GROUP)
 
1745
                {
 
1746
                  depth++;
 
1747
                }
 
1748
              else if (format[offset] == SPECIFIER_UNGROUP)
 
1749
              {
 
1750
                if (--depth <= 0)
 
1751
                  {
 
1752
                    offset++;
 
1753
                    break;
 
1754
                  }
 
1755
              }
 
1756
              offset++;
 
1757
            }
 
1758
        }
 
1759
      break;
 
1760
#endif /* defined(SPECIFIER_GROUP) */
 
1761
 
 
1762
    case SPECIFIER_INTEGER:
 
1763
      parameter->type = FORMAT_INT;
 
1764
      break;
 
1765
 
 
1766
    case SPECIFIER_UNSIGNED:
 
1767
      parameter->flags |= FLAGS_UNSIGNED;
 
1768
      parameter->type = FORMAT_INT;
 
1769
      break;
 
1770
 
 
1771
    case SPECIFIER_DECIMAL:
 
1772
      parameter->baseSpecifier = BASE_DECIMAL;
 
1773
      parameter->type = FORMAT_INT;
 
1774
      break;
 
1775
 
 
1776
    case SPECIFIER_OCTAL:
 
1777
      parameter->flags |= FLAGS_UNSIGNED;
 
1778
      parameter->baseSpecifier = BASE_OCTAL;
 
1779
      parameter->type = FORMAT_INT;
 
1780
      break;
 
1781
 
 
1782
#if TRIO_FEATURE_BINARY
 
1783
    case SPECIFIER_BINARY_UPPER:
 
1784
      parameter->flags |= FLAGS_UPPER;
 
1785
      /* FALLTHROUGH */
 
1786
    case SPECIFIER_BINARY:
 
1787
      parameter->flags |= FLAGS_NILPADDING;
 
1788
      parameter->baseSpecifier = BASE_BINARY;
 
1789
      parameter->type = FORMAT_INT;
 
1790
      break;
 
1791
#endif
 
1792
 
 
1793
    case SPECIFIER_HEX_UPPER:
 
1794
      parameter->flags |= FLAGS_UPPER;
 
1795
      /* FALLTHROUGH */
 
1796
    case SPECIFIER_HEX:
 
1797
      parameter->flags |= FLAGS_UNSIGNED;
 
1798
      parameter->baseSpecifier = BASE_HEX;
 
1799
      parameter->type = FORMAT_INT;
 
1800
      break;
 
1801
 
 
1802
#if defined(SPECIFIER_FLOAT_E)
 
1803
# if defined(SPECIFIER_FLOAT_E_UPPER)
 
1804
    case SPECIFIER_FLOAT_E_UPPER:
 
1805
      parameter->flags |= FLAGS_UPPER;
 
1806
      /* FALLTHROUGH */
 
1807
# endif
 
1808
    case SPECIFIER_FLOAT_E:
 
1809
      parameter->flags |= FLAGS_FLOAT_E;
 
1810
      parameter->type = FORMAT_DOUBLE;
 
1811
      break;
 
1812
#endif
 
1813
 
 
1814
#if defined(SPECIFIER_FLOAT_G)
 
1815
# if defined(SPECIFIER_FLOAT_G_UPPER)
 
1816
    case SPECIFIER_FLOAT_G_UPPER:
 
1817
      parameter->flags |= FLAGS_UPPER;
 
1818
      /* FALLTHROUGH */
 
1819
# endif
 
1820
    case SPECIFIER_FLOAT_G:
 
1821
      parameter->flags |= FLAGS_FLOAT_G;
 
1822
      parameter->type = FORMAT_DOUBLE;
 
1823
      break;
 
1824
#endif
 
1825
 
 
1826
#if defined(SPECIFIER_FLOAT_F)
 
1827
# if defined(SPECIFIER_FLOAT_F_UPPER)
 
1828
    case SPECIFIER_FLOAT_F_UPPER:
 
1829
      parameter->flags |= FLAGS_UPPER;
 
1830
      /* FALLTHROUGH */
 
1831
# endif
 
1832
    case SPECIFIER_FLOAT_F:
 
1833
      parameter->type = FORMAT_DOUBLE;
 
1834
      break;
 
1835
#endif
 
1836
 
 
1837
#if defined(TRIO_COMPILER_VISUALC)
 
1838
# pragma warning( push )
 
1839
# pragma warning( disable : 4127 ) /* Conditional expression is constant */
 
1840
#endif
 
1841
    case SPECIFIER_POINTER:
 
1842
      if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
 
1843
        parameter->flags |= FLAGS_QUAD;
 
1844
      else if (sizeof(trio_pointer_t) == sizeof(long))
 
1845
        parameter->flags |= FLAGS_LONG;
 
1846
      parameter->type = FORMAT_POINTER;
 
1847
      break;
 
1848
#if defined(TRIO_COMPILER_VISUALC)
 
1849
# pragma warning( pop )
 
1850
#endif
 
1851
 
 
1852
    case SPECIFIER_COUNT:
 
1853
      parameter->type = FORMAT_COUNT;
 
1854
      break;
 
1855
 
 
1856
#if TRIO_FEATURE_HEXFLOAT
 
1857
    case SPECIFIER_HEXFLOAT_UPPER:
 
1858
      parameter->flags |= FLAGS_UPPER;
 
1859
      /* FALLTHROUGH */
 
1860
    case SPECIFIER_HEXFLOAT:
 
1861
      parameter->baseSpecifier = BASE_HEX;
 
1862
      parameter->type = FORMAT_DOUBLE;
 
1863
      break;
 
1864
#endif
 
1865
 
 
1866
#if TRIO_FEATURE_ERRNO
 
1867
    case SPECIFIER_ERRNO:
 
1868
      parameter->type = FORMAT_ERRNO;
 
1869
      break;
 
1870
#endif
 
1871
 
 
1872
#if TRIO_FEATURE_USER_DEFINED
 
1873
    case SPECIFIER_USER_DEFINED_BEGIN:
 
1874
      {
 
1875
        unsigned int max;
 
1876
        int without_namespace = TRUE;
 
1877
        char* tmpformat = (char *)&format[offset];
 
1878
        int ch;
 
1879
 
 
1880
        parameter->type = FORMAT_USER_DEFINED;
 
1881
        parameter->user_defined.namespace[0] = NIL;
 
1882
 
 
1883
        while ((ch = format[offset]) != NIL)
 
1884
          {
 
1885
            offset++;
 
1886
            if ((ch == SPECIFIER_USER_DEFINED_END) || (ch == SPECIFIER_USER_DEFINED_EXTRA))
 
1887
              {
 
1888
                if (without_namespace)
 
1889
                  /* No namespace, handler will be passed as an argument */
 
1890
                  parameter->flags |= FLAGS_USER_DEFINED_PARAMETER;
 
1891
 
 
1892
                /* Copy the user data */
 
1893
                max = (unsigned int)(&format[offset] - tmpformat);
 
1894
                if (max > MAX_USER_DATA)
 
1895
                  max = MAX_USER_DATA;
 
1896
                trio_copy_max(parameter->user_data, max, tmpformat);
 
1897
 
 
1898
                /* Skip extra data (which is only there to keep the compiler happy) */
 
1899
                while ((ch != NIL) && (ch != SPECIFIER_USER_DEFINED_END))
 
1900
                  ch = format[offset++];
 
1901
 
 
1902
                break; /* while */
 
1903
              }
 
1904
 
 
1905
            if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
 
1906
              {
 
1907
                without_namespace = FALSE;
 
1908
                /* Copy the namespace for later looking-up */
 
1909
                max = (int)(&format[offset] - tmpformat);
 
1910
                if (max > MAX_USER_NAME)
 
1911
                  max = MAX_USER_NAME;
 
1912
                trio_copy_max(parameter->user_defined.namespace, max, tmpformat);
 
1913
                tmpformat = (char *)&format[offset];
 
1914
              }
 
1915
          }
 
1916
 
 
1917
        if (ch != SPECIFIER_USER_DEFINED_END)
 
1918
          return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1919
      }
 
1920
      break;
 
1921
#endif /* TRIO_FEATURE_USER_DEFINED */
 
1922
 
 
1923
    default:
 
1924
      /* Bail out completely to make the error more obvious */
 
1925
      return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
1926
  }
 
1927
 
 
1928
  parameter->endOffset = offset;
 
1929
 
 
1930
  return 0;
 
1931
}
1139
1932
 
1140
1933
/*************************************************************************
1141
1934
 * TrioParse
1149
1942
           int type,
1150
1943
           TRIO_CONST char *format,
1151
1944
           trio_parameter_t *parameters,
1152
 
           va_list *arglist,
 
1945
           va_list arglist,
1153
1946
           trio_pointer_t *argarray)
1154
1947
{
1155
1948
  /* Count the number of times a parameter is referenced */
1156
1949
  unsigned short usedEntries[MAX_PARAMETERS];
1157
1950
  /* Parameter counters */
1158
1951
  int parameterPosition;
1159
 
  int currentParam;
1160
1952
  int maxParam = -1;
1161
1953
  /* Utility variables */
1162
 
  trio_flags_t flags;
1163
 
  int width;
1164
 
  int precision;
1165
 
  int varsize;
1166
 
  int base;
1167
 
  int index;  /* Index into formatting string */
1168
 
  int dots;  /* Count number of dots in modifier part */
 
1954
  int offset;  /* Offset into formatting string */
1169
1955
  BOOLEAN_T positional;  /* Does the specifier have a positional? */
 
1956
#if TRIO_FEATURE_STICKY
1170
1957
  BOOLEAN_T gotSticky = FALSE;  /* Are there any sticky modifiers at all? */
 
1958
#endif
1171
1959
  /*
1172
1960
   * indices specifies the order in which the parameters must be
1173
1961
   * read from the va_args (this is necessary to handle positionals)
1175
1963
  int indices[MAX_PARAMETERS];
1176
1964
  int pos = 0;
1177
1965
  /* Various variables */
1178
 
  char ch;
1179
1966
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1180
1967
  int charlen;
1181
1968
#endif
1182
1969
  int save_errno;
1183
1970
  int i = -1;
1184
1971
  int num;
1185
 
  char *tmpformat;
 
1972
  trio_parameter_t workParameter;
 
1973
  int status;
1186
1974
 
1187
 
  /* One and only one of arglist and argarray must be used */
1188
 
  assert((arglist != NULL) ^ (argarray != NULL));
1189
 
  
1190
1975
  /*
1191
1976
   * The 'parameters' array is not initialized, but we need to
1192
1977
   * know which entries we have used.
1194
1979
  memset(usedEntries, 0, sizeof(usedEntries));
1195
1980
 
1196
1981
  save_errno = errno;
1197
 
  index = 0;
 
1982
  offset = 0;
1198
1983
  parameterPosition = 0;
1199
1984
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1200
1985
  (void)mblen(NULL, 0);
1201
1986
#endif
1202
1987
  
1203
 
  while (format[index])
 
1988
  while (format[offset])
1204
1989
    {
 
1990
      TrioInitializeParameter(&workParameter);
 
1991
 
1205
1992
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
1206
 
      if (! isascii(format[index]))
 
1993
      if (! isascii(format[offset]))
1207
1994
        {
1208
1995
          /*
1209
1996
           * Multibyte characters cannot be legal specifiers or
1210
1997
           * modifiers, so we skip over them.
1211
1998
           */
1212
 
          charlen = mblen(&format[index], MB_LEN_MAX);
1213
 
          index += (charlen > 0) ? charlen : 1;
 
1999
          charlen = mblen(&format[offset], MB_LEN_MAX);
 
2000
          offset += (charlen > 0) ? charlen : 1;
1214
2001
          continue; /* while */
1215
2002
        }
1216
2003
#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
1217
 
      if (CHAR_IDENTIFIER == format[index++])
 
2004
 
 
2005
      switch(format[offset++]) {
 
2006
 
 
2007
      case CHAR_IDENTIFIER:
1218
2008
        {
1219
 
          if (CHAR_IDENTIFIER == format[index])
 
2009
          if (CHAR_IDENTIFIER == format[offset])
1220
2010
            {
1221
 
              index++;
 
2011
              /* skip double "%" */
 
2012
              offset++;
1222
2013
              continue; /* while */
1223
2014
            }
1224
2015
 
1225
 
          flags = FLAGS_NEW;
1226
 
          dots = 0;
1227
 
          currentParam = TrioGetPosition(format, &index);
1228
 
          positional = (NO_POSITION != currentParam);
1229
 
          if (!positional)
1230
 
            {
1231
 
              /* We have no positional, get the next counter */
1232
 
              currentParam = parameterPosition;
1233
 
            }
1234
 
          if(currentParam >= MAX_PARAMETERS)
1235
 
            {
1236
 
              /* Bail out completely to make the error more obvious */
1237
 
              return TRIO_ERROR_RETURN(TRIO_ETOOMANY, index);
1238
 
            }
1239
 
 
1240
 
          if (currentParam > maxParam)
1241
 
            maxParam = currentParam;
1242
 
 
1243
 
          /* Default values */
1244
 
          width = NO_WIDTH;
1245
 
          precision = NO_PRECISION;
1246
 
          base = NO_BASE;
1247
 
          varsize = NO_SIZE;
1248
 
 
1249
 
          while (TrioIsQualifier(format[index]))
1250
 
            {
1251
 
              ch = format[index++];
1252
 
 
1253
 
              switch (ch)
1254
 
                {
1255
 
                case QUALIFIER_SPACE:
1256
 
                  flags |= FLAGS_SPACE;
1257
 
                  break;
1258
 
 
1259
 
                case QUALIFIER_PLUS:
1260
 
                  flags |= FLAGS_SHOWSIGN;
1261
 
                  break;
1262
 
 
1263
 
                case QUALIFIER_MINUS:
1264
 
                  flags |= FLAGS_LEFTADJUST;
1265
 
                  flags &= ~FLAGS_NILPADDING;
1266
 
                  break;
1267
 
 
1268
 
                case QUALIFIER_ALTERNATIVE:
1269
 
                  flags |= FLAGS_ALTERNATIVE;
1270
 
                  break;
1271
 
 
1272
 
                case QUALIFIER_DOT:
1273
 
                  if (dots == 0) /* Precision */
1274
 
                    {
1275
 
                      dots++;
1276
 
 
1277
 
                      /* Skip if no precision */
1278
 
                      if (QUALIFIER_DOT == format[index])
1279
 
                        break;
1280
 
                      
1281
 
                      /* After the first dot we have the precision */
1282
 
                      flags |= FLAGS_PRECISION;
1283
 
                      if ((QUALIFIER_STAR == format[index])
1284
 
#if defined(QUALIFIER_PARAM)
1285
 
                          || (QUALIFIER_PARAM == format[index])
1286
 
#endif
1287
 
                          )
1288
 
                        {
1289
 
                          index++;
1290
 
                          flags |= FLAGS_PRECISION_PARAMETER;
1291
 
 
1292
 
                          precision = TrioGetPosition(format, &index);
1293
 
                          if (precision == NO_POSITION)
1294
 
                            {
1295
 
                              parameterPosition++;
1296
 
                              if (positional)
1297
 
                                precision = parameterPosition;
1298
 
                              else
1299
 
                                {
1300
 
                                  precision = currentParam;
1301
 
                                  currentParam = precision + 1;
1302
 
                                }
1303
 
                            }
1304
 
                          else
1305
 
                            {
1306
 
                              if (! positional)
1307
 
                                currentParam = precision + 1;
1308
 
                              if (width > maxParam)
1309
 
                                maxParam = precision;
1310
 
                            }
1311
 
                          if (currentParam > maxParam)
1312
 
                            maxParam = currentParam;
1313
 
                        }
1314
 
                      else
1315
 
                        {
1316
 
                          precision = trio_to_long(&format[index],
1317
 
                                                   &tmpformat,
1318
 
                                                   BASE_DECIMAL);
1319
 
                          index = (int)(tmpformat - format);
1320
 
                        }
1321
 
                    }
1322
 
                  else if (dots == 1) /* Base */
1323
 
                    {
1324
 
                      dots++;
1325
 
                      
1326
 
                      /* After the second dot we have the base */
1327
 
                      flags |= FLAGS_BASE;
1328
 
                      if ((QUALIFIER_STAR == format[index])
1329
 
#if defined(QUALIFIER_PARAM)
1330
 
                          || (QUALIFIER_PARAM == format[index])
1331
 
#endif
1332
 
                          )
1333
 
                        {
1334
 
                          index++;
1335
 
                          flags |= FLAGS_BASE_PARAMETER;
1336
 
                          base = TrioGetPosition(format, &index);
1337
 
                          if (base == NO_POSITION)
1338
 
                            {
1339
 
                              parameterPosition++;
1340
 
                              if (positional)
1341
 
                                base = parameterPosition;
1342
 
                              else
1343
 
                                {
1344
 
                                  base = currentParam;
1345
 
                                  currentParam = base + 1;
1346
 
                                }
1347
 
                            }
1348
 
                          else
1349
 
                            {
1350
 
                              if (! positional)
1351
 
                                currentParam = base + 1;
1352
 
                              if (base > maxParam)
1353
 
                                maxParam = base;
1354
 
                            }
1355
 
                          if (currentParam > maxParam)
1356
 
                            maxParam = currentParam;
1357
 
                        }
1358
 
                      else
1359
 
                        {
1360
 
                          base = trio_to_long(&format[index],
1361
 
                                              &tmpformat,
1362
 
                                              BASE_DECIMAL);
1363
 
                          if (base > MAX_BASE)
1364
 
                            return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1365
 
                          index = (int)(tmpformat - format);
1366
 
                        }
1367
 
                    }
1368
 
                  else
1369
 
                    {
1370
 
                      return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1371
 
                    }
1372
 
                  break; /* QUALIFIER_DOT */
1373
 
 
1374
 
#if defined(QUALIFIER_PARAM)
1375
 
                case QUALIFIER_PARAM:
1376
 
                  type = TYPE_PRINT;
1377
 
                  /* FALLTHROUGH */
1378
 
#endif
1379
 
                case QUALIFIER_STAR:
1380
 
                  /* This has different meanings for print and scan */
1381
 
                  if (TYPE_PRINT == type)
1382
 
                    {
1383
 
                      /* Read with from parameter */
1384
 
                      flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
1385
 
                      width = TrioGetPosition(format, &index);
1386
 
                      if (width == NO_POSITION)
1387
 
                        {
1388
 
                          parameterPosition++;
1389
 
                          if (positional)
1390
 
                            width = parameterPosition;
1391
 
                          else
1392
 
                            {
1393
 
                              width = currentParam;
1394
 
                              currentParam = width + 1;
1395
 
                            }
1396
 
                        }
1397
 
                      else
1398
 
                        {
1399
 
                          if (! positional)
1400
 
                            currentParam = width + 1;
1401
 
                          if (width > maxParam)
1402
 
                            maxParam = width;
1403
 
                        }
1404
 
                      if (currentParam > maxParam)
1405
 
                        maxParam = currentParam;
1406
 
                    }
1407
 
                  else
1408
 
                    {
1409
 
                      /* Scan, but do not store result */
1410
 
                      flags |= FLAGS_IGNORE;
1411
 
                    }
1412
 
 
1413
 
                  break; /* QUALIFIER_STAR */
1414
 
 
1415
 
                case '0':
1416
 
                  if (! (flags & FLAGS_LEFTADJUST))
1417
 
                    flags |= FLAGS_NILPADDING;
1418
 
                  /* FALLTHROUGH */
1419
 
                case '1': case '2': case '3': case '4':
1420
 
                case '5': case '6': case '7': case '8': case '9':
1421
 
                  flags |= FLAGS_WIDTH;
1422
 
                  /* &format[index - 1] is used to "rewind" the read
1423
 
                   * character from format
1424
 
                   */
1425
 
                  width = trio_to_long(&format[index - 1],
1426
 
                                       &tmpformat,
1427
 
                                       BASE_DECIMAL);
1428
 
                  index = (int)(tmpformat - format);
1429
 
                  break;
1430
 
 
1431
 
                case QUALIFIER_SHORT:
1432
 
                  if (flags & FLAGS_SHORTSHORT)
1433
 
                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1434
 
                  else if (flags & FLAGS_SHORT)
1435
 
                    flags |= FLAGS_SHORTSHORT;
1436
 
                  else
1437
 
                    flags |= FLAGS_SHORT;
1438
 
                  break;
1439
 
 
1440
 
                case QUALIFIER_LONG:
1441
 
                  if (flags & FLAGS_QUAD)
1442
 
                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1443
 
                  else if (flags & FLAGS_LONG)
1444
 
                    flags |= FLAGS_QUAD;
1445
 
                  else
1446
 
                    flags |= FLAGS_LONG;
1447
 
                  break;
1448
 
 
1449
 
                case QUALIFIER_LONG_UPPER:
1450
 
                  flags |= FLAGS_LONGDOUBLE;
1451
 
                  break;
1452
 
 
1453
 
#if defined(QUALIFIER_SIZE_T)
1454
 
                case QUALIFIER_SIZE_T:
1455
 
                  flags |= FLAGS_SIZE_T;
1456
 
                  /* Modify flags for later truncation of number */
1457
 
                  if (sizeof(size_t) == sizeof(trio_ulonglong_t))
1458
 
                    flags |= FLAGS_QUAD;
1459
 
                  else if (sizeof(size_t) == sizeof(long))
1460
 
                    flags |= FLAGS_LONG;
1461
 
                  break;
1462
 
#endif
1463
 
 
1464
 
#if defined(QUALIFIER_PTRDIFF_T)
1465
 
                case QUALIFIER_PTRDIFF_T:
1466
 
                  flags |= FLAGS_PTRDIFF_T;
1467
 
                  if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
1468
 
                    flags |= FLAGS_QUAD;
1469
 
                  else if (sizeof(ptrdiff_t) == sizeof(long))
1470
 
                    flags |= FLAGS_LONG;
1471
 
                  break;
1472
 
#endif
1473
 
 
1474
 
#if defined(QUALIFIER_INTMAX_T)
1475
 
                case QUALIFIER_INTMAX_T:
1476
 
                  flags |= FLAGS_INTMAX_T;
1477
 
                  if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
1478
 
                    flags |= FLAGS_QUAD;
1479
 
                  else if (sizeof(trio_intmax_t) == sizeof(long))
1480
 
                    flags |= FLAGS_LONG;
1481
 
                  break;
1482
 
#endif
1483
 
 
1484
 
#if defined(QUALIFIER_QUAD)
1485
 
                case QUALIFIER_QUAD:
1486
 
                  flags |= FLAGS_QUAD;
1487
 
                  break;
1488
 
#endif
1489
 
 
1490
 
#if defined(QUALIFIER_FIXED_SIZE)
1491
 
                case QUALIFIER_FIXED_SIZE:
1492
 
                  if (flags & FLAGS_FIXED_SIZE)
1493
 
                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1494
 
 
1495
 
                  if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
1496
 
                               FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
1497
 
                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1498
 
 
1499
 
                  if ((format[index] == '6') &&
1500
 
                      (format[index + 1] == '4'))
1501
 
                    {
1502
 
                      varsize = sizeof(trio_int64_t);
1503
 
                      index += 2;
1504
 
                    }
1505
 
                  else if ((format[index] == '3') &&
1506
 
                           (format[index + 1] == '2'))
1507
 
                    {
1508
 
                      varsize = sizeof(trio_int32_t);
1509
 
                      index += 2;
1510
 
                    }
1511
 
                  else if ((format[index] == '1') &&
1512
 
                           (format[index + 1] == '6'))
1513
 
                    {
1514
 
                      varsize = sizeof(trio_int16_t);
1515
 
                      index += 2;
1516
 
                    }
1517
 
                  else if (format[index] == '8')
1518
 
                    {
1519
 
                      varsize = sizeof(trio_int8_t);
1520
 
                      index++;
1521
 
                    }
1522
 
                  else
1523
 
                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1524
 
                  
1525
 
                  flags |= FLAGS_FIXED_SIZE;
1526
 
                  break;
1527
 
#endif
1528
 
 
1529
 
#if defined(QUALIFIER_WIDECHAR)
1530
 
                case QUALIFIER_WIDECHAR:
1531
 
                  flags |= FLAGS_WIDECHAR;
1532
 
                  break;
1533
 
#endif
1534
 
 
1535
 
#if defined(QUALIFIER_SIZE_T_UPPER)
1536
 
                case QUALIFIER_SIZE_T_UPPER:
1537
 
                  break;
1538
 
#endif
1539
 
 
1540
 
#if defined(QUALIFIER_QUOTE)
1541
 
                case QUALIFIER_QUOTE:
1542
 
                  flags |= FLAGS_QUOTE;
1543
 
                  break;
1544
 
#endif
1545
 
 
1546
 
#if defined(QUALIFIER_STICKY)
1547
 
                case QUALIFIER_STICKY:
1548
 
                  flags |= FLAGS_STICKY;
1549
 
                  gotSticky = TRUE;
1550
 
                  break;
1551
 
#endif
1552
 
                  
1553
 
#if defined(QUALIFIER_VARSIZE)
1554
 
                case QUALIFIER_VARSIZE:
1555
 
                  flags |= FLAGS_VARSIZE_PARAMETER;
1556
 
                  parameterPosition++;
1557
 
                  if (positional)
1558
 
                    varsize = parameterPosition;
1559
 
                  else
1560
 
                    {
1561
 
                      varsize = currentParam;
1562
 
                      currentParam = varsize + 1;
1563
 
                    }
1564
 
                  if (currentParam > maxParam)
1565
 
                    maxParam = currentParam;
1566
 
                  break;
1567
 
#endif
1568
 
 
1569
 
#if defined(QUALIFIER_ROUNDING_UPPER)
1570
 
                case QUALIFIER_ROUNDING_UPPER:
1571
 
                  flags |= FLAGS_ROUNDING;
1572
 
                  break;
1573
 
#endif
1574
 
 
1575
 
                default:
1576
 
                  /* Bail out completely to make the error more obvious */
1577
 
                  return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1578
 
                }
1579
 
            } /* while qualifier */
1580
 
 
1581
 
          /*
1582
 
           * Parameters only need the type and value. The value is
1583
 
           * read later.
1584
 
           */
1585
 
          if (flags & FLAGS_WIDTH_PARAMETER)
1586
 
            {
1587
 
              usedEntries[width] += 1;
1588
 
              parameters[pos].type = FORMAT_PARAMETER;
1589
 
              parameters[pos].flags = 0;
1590
 
              indices[width] = pos;
1591
 
              width = pos++;
1592
 
            }
1593
 
          if (flags & FLAGS_PRECISION_PARAMETER)
1594
 
            {
1595
 
              usedEntries[precision] += 1;
1596
 
              parameters[pos].type = FORMAT_PARAMETER;
1597
 
              parameters[pos].flags = 0;
1598
 
              indices[precision] = pos;
1599
 
              precision = pos++;
1600
 
            }
1601
 
          if (flags & FLAGS_BASE_PARAMETER)
1602
 
            {
1603
 
              usedEntries[base] += 1;
1604
 
              parameters[pos].type = FORMAT_PARAMETER;
1605
 
              parameters[pos].flags = 0;
1606
 
              indices[base] = pos;
1607
 
              base = pos++;
1608
 
            }
1609
 
          if (flags & FLAGS_VARSIZE_PARAMETER)
1610
 
            {
1611
 
              usedEntries[varsize] += 1;
1612
 
              parameters[pos].type = FORMAT_PARAMETER;
1613
 
              parameters[pos].flags = 0;
1614
 
              indices[varsize] = pos;
1615
 
              varsize = pos++;
1616
 
            }
1617
 
          
1618
 
          indices[currentParam] = pos;
1619
 
          
1620
 
          switch (format[index++])
1621
 
            {
1622
 
#if defined(SPECIFIER_CHAR_UPPER)
1623
 
            case SPECIFIER_CHAR_UPPER:
1624
 
              flags |= FLAGS_WIDECHAR;
1625
 
              /* FALLTHROUGH */
1626
 
#endif
1627
 
            case SPECIFIER_CHAR:
1628
 
              if (flags & FLAGS_LONG)
1629
 
                flags |= FLAGS_WIDECHAR;
1630
 
              else if (flags & FLAGS_SHORT)
1631
 
                flags &= ~FLAGS_WIDECHAR;
1632
 
              parameters[pos].type = FORMAT_CHAR;
1633
 
              break;
1634
 
 
1635
 
#if defined(SPECIFIER_STRING_UPPER)
1636
 
            case SPECIFIER_STRING_UPPER:
1637
 
              flags |= FLAGS_WIDECHAR;
1638
 
              /* FALLTHROUGH */
1639
 
#endif
1640
 
            case SPECIFIER_STRING:
1641
 
              if (flags & FLAGS_LONG)
1642
 
                flags |= FLAGS_WIDECHAR;
1643
 
              else if (flags & FLAGS_SHORT)
1644
 
                flags &= ~FLAGS_WIDECHAR;
1645
 
              parameters[pos].type = FORMAT_STRING;
1646
 
              break;
1647
 
 
1648
 
            case SPECIFIER_GROUP:
1649
 
              if (TYPE_SCAN == type)
1650
 
                {
1651
 
                  int depth = 1;
1652
 
                  parameters[pos].type = FORMAT_GROUP;
1653
 
                  if (format[index] == QUALIFIER_CIRCUMFLEX)
1654
 
                    index++;
1655
 
                  if (format[index] == SPECIFIER_UNGROUP)
1656
 
                    index++;
1657
 
                  if (format[index] == QUALIFIER_MINUS)
1658
 
                    index++;
1659
 
                  /* Skip nested brackets */
1660
 
                  while (format[index] != NIL)
1661
 
                    {
1662
 
                      if (format[index] == SPECIFIER_GROUP)
1663
 
                        {
1664
 
                          depth++;
1665
 
                        }
1666
 
                      else if (format[index] == SPECIFIER_UNGROUP)
1667
 
                        {
1668
 
                          if (--depth <= 0)
1669
 
                            {
1670
 
                              index++;
1671
 
                              break;
1672
 
                            }
1673
 
                        }
1674
 
                      index++;
1675
 
                    }
1676
 
                }
1677
 
              break;
1678
 
              
1679
 
            case SPECIFIER_INTEGER:
1680
 
              parameters[pos].type = FORMAT_INT;
1681
 
              break;
1682
 
              
1683
 
            case SPECIFIER_UNSIGNED:
1684
 
              flags |= FLAGS_UNSIGNED;
1685
 
              parameters[pos].type = FORMAT_INT;
1686
 
              break;
1687
 
 
1688
 
            case SPECIFIER_DECIMAL:
1689
 
              /* Disable base modifier */
1690
 
              flags &= ~FLAGS_BASE_PARAMETER;
1691
 
              base = BASE_DECIMAL;
1692
 
              parameters[pos].type = FORMAT_INT;
1693
 
              break;
1694
 
 
1695
 
            case SPECIFIER_OCTAL:
1696
 
              flags |= FLAGS_UNSIGNED;
1697
 
              flags &= ~FLAGS_BASE_PARAMETER;
1698
 
              base = BASE_OCTAL;
1699
 
              parameters[pos].type = FORMAT_INT;
1700
 
              break;
1701
 
 
1702
 
#if defined(SPECIFIER_BINARY)
1703
 
            case SPECIFIER_BINARY_UPPER:
1704
 
              flags |= FLAGS_UPPER;
1705
 
              /* FALLTHROUGH */
1706
 
            case SPECIFIER_BINARY:
1707
 
              flags |= FLAGS_NILPADDING;
1708
 
              flags &= ~FLAGS_BASE_PARAMETER;
1709
 
              base = BASE_BINARY;
1710
 
              parameters[pos].type = FORMAT_INT;
1711
 
              break;
1712
 
#endif
1713
 
 
1714
 
            case SPECIFIER_HEX_UPPER:
1715
 
              flags |= FLAGS_UPPER;
1716
 
              /* FALLTHROUGH */
1717
 
            case SPECIFIER_HEX:
1718
 
              flags |= FLAGS_UNSIGNED;
1719
 
              flags &= ~FLAGS_BASE_PARAMETER;
1720
 
              base = BASE_HEX;
1721
 
              parameters[pos].type = FORMAT_INT;
1722
 
              break;
1723
 
 
1724
 
            case SPECIFIER_FLOAT_E_UPPER:
1725
 
              flags |= FLAGS_UPPER;
1726
 
              /* FALLTHROUGH */
1727
 
            case SPECIFIER_FLOAT_E:
1728
 
              flags |= FLAGS_FLOAT_E;
1729
 
              parameters[pos].type = FORMAT_DOUBLE;
1730
 
              break;
1731
 
 
1732
 
            case SPECIFIER_FLOAT_G_UPPER:
1733
 
              flags |= FLAGS_UPPER;
1734
 
              /* FALLTHROUGH */
1735
 
            case SPECIFIER_FLOAT_G:
1736
 
              flags |= FLAGS_FLOAT_G;
1737
 
              parameters[pos].type = FORMAT_DOUBLE;
1738
 
              break;
1739
 
 
1740
 
            case SPECIFIER_FLOAT_F_UPPER:
1741
 
              flags |= FLAGS_UPPER;
1742
 
              /* FALLTHROUGH */
1743
 
            case SPECIFIER_FLOAT_F:
1744
 
              parameters[pos].type = FORMAT_DOUBLE;
1745
 
              break;
1746
 
 
1747
 
            case SPECIFIER_POINTER:
1748
 
              if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
1749
 
                flags |= FLAGS_QUAD;
1750
 
              else if (sizeof(trio_pointer_t) == sizeof(long))
1751
 
                flags |= FLAGS_LONG;
1752
 
              parameters[pos].type = FORMAT_POINTER;
1753
 
              break;
1754
 
 
1755
 
            case SPECIFIER_COUNT:
1756
 
              parameters[pos].type = FORMAT_COUNT;
1757
 
              break;
1758
 
 
1759
 
#if defined(SPECIFIER_HEXFLOAT)
1760
 
# if defined(SPECIFIER_HEXFLOAT_UPPER)
1761
 
            case SPECIFIER_HEXFLOAT_UPPER:
1762
 
              flags |= FLAGS_UPPER;
1763
 
              /* FALLTHROUGH */
1764
 
# endif
1765
 
            case SPECIFIER_HEXFLOAT:
1766
 
              base = BASE_HEX;
1767
 
              parameters[pos].type = FORMAT_DOUBLE;
1768
 
              break;
1769
 
#endif
1770
 
 
1771
 
#if defined(FORMAT_ERRNO)
1772
 
            case SPECIFIER_ERRNO:
1773
 
              parameters[pos].type = FORMAT_ERRNO;
1774
 
              break;
1775
 
#endif
1776
 
 
1777
 
#if defined(SPECIFIER_USER_DEFINED_BEGIN)
1778
 
            case SPECIFIER_USER_DEFINED_BEGIN:
1779
 
              {
1780
 
                unsigned int max;
1781
 
                int without_namespace = TRUE;
1782
 
                
1783
 
                parameters[pos].type = FORMAT_USER_DEFINED;
1784
 
                parameters[pos].user_name[0] = NIL;
1785
 
                tmpformat = (char *)&format[index];
1786
 
              
1787
 
                while ((ch = format[index]))
1788
 
                  {
1789
 
                    index++;
1790
 
                    if (ch == SPECIFIER_USER_DEFINED_END)
1791
 
                      {
1792
 
                        if (without_namespace)
1793
 
                          {
1794
 
                            /* We must get the handle first */
1795
 
                            parameters[pos].type = FORMAT_PARAMETER;
1796
 
                            parameters[pos].indexAfterSpecifier = index;
1797
 
                            parameters[pos].flags = FLAGS_USER_DEFINED;
1798
 
                            /* Adjust parameters for insertion of new one */
1799
 
                            pos++;
1800
 
                            usedEntries[currentParam] += 1;
1801
 
                            parameters[pos].type = FORMAT_USER_DEFINED;
1802
 
                            currentParam++;
1803
 
                            indices[currentParam] = pos;
1804
 
                            if (currentParam > maxParam)
1805
 
                              maxParam = currentParam;
1806
 
                          }
1807
 
                        /* Copy the user data */
1808
 
                        max = (unsigned int)(&format[index] - tmpformat);
1809
 
                        if (max > MAX_USER_DATA)
1810
 
                          max = MAX_USER_DATA;
1811
 
                        trio_copy_max(parameters[pos].user_data,
1812
 
                                      max,
1813
 
                                      tmpformat);
1814
 
                        break; /* while */
1815
 
                      }
1816
 
                    if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
1817
 
                      {
1818
 
                        without_namespace = FALSE;
1819
 
                        /* Copy the namespace for later looking-up */
1820
 
                        max = (int)(&format[index] - tmpformat);
1821
 
                        if (max > MAX_USER_NAME)
1822
 
                          max = MAX_USER_NAME;
1823
 
                        trio_copy_max(parameters[pos].user_name,
1824
 
                                      max,
1825
 
                                      tmpformat);
1826
 
                        tmpformat = (char *)&format[index];
1827
 
                      }
1828
 
                  }
1829
 
                if (ch != SPECIFIER_USER_DEFINED_END)
1830
 
                  return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1831
 
              }
1832
 
              break;
1833
 
#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
1834
 
              
1835
 
            default:
1836
 
              /* Bail out completely to make the error more obvious */
1837
 
              return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
1838
 
            }
1839
 
 
1840
 
          /*  Count the number of times this entry has been used */
1841
 
          usedEntries[currentParam] += 1;
1842
 
          
1843
 
          /* Find last sticky parameters */
1844
 
          if (gotSticky && !(flags & FLAGS_STICKY))
1845
 
            {
1846
 
              for (i = pos - 1; i >= 0; i--)
1847
 
                {
1848
 
                  if (parameters[i].type == FORMAT_PARAMETER)
1849
 
                    continue;
1850
 
                  if ((parameters[i].flags & FLAGS_STICKY) &&
1851
 
                      (parameters[i].type == parameters[pos].type))
1852
 
                    {
1853
 
                      /* Do not overwrite current qualifiers */
1854
 
                      flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
1855
 
                      if (width == NO_WIDTH)
1856
 
                        width = parameters[i].width;
1857
 
                      if (precision == NO_PRECISION)
1858
 
                        precision = parameters[i].precision;
1859
 
                      if (base == NO_BASE)
1860
 
                        base = parameters[i].base;
1861
 
                      break;
1862
 
                    }
1863
 
                }
1864
 
            }
1865
 
          
1866
 
          parameters[pos].indexAfterSpecifier = index;
1867
 
          parameters[pos].flags = flags;
1868
 
          parameters[pos].width = width;
1869
 
          parameters[pos].precision = precision;
1870
 
          parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base;
1871
 
          parameters[pos].varsize = varsize;
1872
 
          pos++;
1873
 
          
1874
 
          if (! positional)
1875
 
            parameterPosition++;
1876
 
          
1877
 
        } /* if identifier */
1878
 
      
 
2016
          status = TrioParseQualifiers(type, format, offset, &workParameter);
 
2017
          if (status < 0)
 
2018
            return status; /* Return qualifier syntax error */
 
2019
 
 
2020
          status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
 
2021
          if (status < 0)
 
2022
            return status; /* Return specifier syntax error */
 
2023
        }
 
2024
        break;
 
2025
 
 
2026
#if TRIO_EXTENSION
 
2027
      case CHAR_ALT_IDENTIFIER:
 
2028
        {
 
2029
          status = TrioParseQualifiers(type, format, offset, &workParameter);
 
2030
          if (status < 0)
 
2031
            continue; /* False alert, not a user defined specifier */
 
2032
 
 
2033
          status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
 
2034
          if ((status < 0) || (FORMAT_USER_DEFINED != workParameter.type))
 
2035
            continue; /* False alert, not a user defined specifier */
 
2036
        }
 
2037
        break;
 
2038
#endif
 
2039
 
 
2040
      default:
 
2041
        continue; /* while */
 
2042
      }
 
2043
 
 
2044
      /* now handle the parsed conversion specification */
 
2045
      positional = (NO_POSITION != workParameter.position);
 
2046
 
 
2047
      /*
 
2048
       * Parameters only need the type and value. The value is
 
2049
       * read later.
 
2050
       */
 
2051
      if (workParameter.flags & FLAGS_WIDTH_PARAMETER)
 
2052
        {
 
2053
          if (workParameter.width == NO_WIDTH)
 
2054
            {
 
2055
              workParameter.width = parameterPosition++;
 
2056
            }
 
2057
          else
 
2058
            {
 
2059
              if (! positional)
 
2060
                  workParameter.position = workParameter.width + 1;
 
2061
            }
 
2062
 
 
2063
          usedEntries[workParameter.width] += 1;
 
2064
          if (workParameter.width > maxParam)
 
2065
            maxParam = workParameter.width;
 
2066
          parameters[pos].type = FORMAT_PARAMETER;
 
2067
          parameters[pos].flags = 0;
 
2068
          indices[workParameter.width] = pos;
 
2069
          workParameter.width = pos++;
 
2070
        }
 
2071
      if (workParameter.flags & FLAGS_PRECISION_PARAMETER)
 
2072
        {
 
2073
          if (workParameter.precision == NO_PRECISION)
 
2074
            {
 
2075
              workParameter.precision = parameterPosition++;
 
2076
            }
 
2077
          else
 
2078
            {
 
2079
              if (! positional)
 
2080
                  workParameter.position = workParameter.precision + 1;
 
2081
            }
 
2082
 
 
2083
          usedEntries[workParameter.precision] += 1;
 
2084
          if (workParameter.precision > maxParam)
 
2085
            maxParam = workParameter.precision;
 
2086
          parameters[pos].type = FORMAT_PARAMETER;
 
2087
          parameters[pos].flags = 0;
 
2088
          indices[workParameter.precision] = pos;
 
2089
          workParameter.precision = pos++;
 
2090
        }
 
2091
      if (workParameter.flags & FLAGS_BASE_PARAMETER)
 
2092
        {
 
2093
          if (workParameter.base == NO_BASE)
 
2094
            {
 
2095
              workParameter.base = parameterPosition++;
 
2096
            }
 
2097
          else
 
2098
            {
 
2099
              if (! positional)
 
2100
                  workParameter.position = workParameter.base + 1;
 
2101
            }
 
2102
 
 
2103
          usedEntries[workParameter.base] += 1;
 
2104
          if (workParameter.base > maxParam)
 
2105
            maxParam = workParameter.base;
 
2106
          parameters[pos].type = FORMAT_PARAMETER;
 
2107
          parameters[pos].flags = 0;
 
2108
          indices[workParameter.base] = pos;
 
2109
          workParameter.base = pos++;
 
2110
        }
 
2111
#if TRIO_FEATURE_VARSIZE
 
2112
      if (workParameter.flags & FLAGS_VARSIZE_PARAMETER)
 
2113
        {
 
2114
          workParameter.varsize = parameterPosition++;
 
2115
 
 
2116
          usedEntries[workParameter.varsize] += 1;
 
2117
          if (workParameter.varsize > maxParam)
 
2118
            maxParam = workParameter.varsize;
 
2119
          parameters[pos].type = FORMAT_PARAMETER;
 
2120
          parameters[pos].flags = 0;
 
2121
          indices[workParameter.varsize] = pos;
 
2122
          workParameter.varsize = pos++;
 
2123
        }
 
2124
#endif
 
2125
#if TRIO_FEATURE_USER_DEFINED
 
2126
      if (workParameter.flags & FLAGS_USER_DEFINED_PARAMETER)
 
2127
        {
 
2128
          workParameter.user_defined.handler = parameterPosition++;
 
2129
 
 
2130
          usedEntries[workParameter.user_defined.handler] += 1;
 
2131
          if (workParameter.user_defined.handler > maxParam)
 
2132
            maxParam = workParameter.user_defined.handler;
 
2133
          parameters[pos].type = FORMAT_PARAMETER;
 
2134
          parameters[pos].flags = FLAGS_USER_DEFINED;
 
2135
          indices[workParameter.user_defined.handler] = pos;
 
2136
          workParameter.user_defined.handler = pos++;
 
2137
        }
 
2138
#endif
 
2139
 
 
2140
      if (NO_POSITION == workParameter.position)
 
2141
        {
 
2142
          workParameter.position = parameterPosition++;
 
2143
        }
 
2144
 
 
2145
      if (workParameter.position > maxParam)
 
2146
        maxParam = workParameter.position;
 
2147
 
 
2148
      if (workParameter.position >= MAX_PARAMETERS)
 
2149
        {
 
2150
          /* Bail out completely to make the error more obvious */
 
2151
          return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset);
 
2152
        }
 
2153
 
 
2154
      indices[workParameter.position] = pos;
 
2155
 
 
2156
      /*  Count the number of times this entry has been used */
 
2157
      usedEntries[workParameter.position] += 1;
 
2158
 
 
2159
      /* Find last sticky parameters */
 
2160
#if TRIO_FEATURE_STICKY
 
2161
      if (workParameter.flags & FLAGS_STICKY)
 
2162
        {
 
2163
          gotSticky = TRUE;
 
2164
        }
 
2165
      else if (gotSticky)
 
2166
        {
 
2167
          for (i = pos - 1; i >= 0; i--)
 
2168
            {
 
2169
              if (parameters[i].type == FORMAT_PARAMETER)
 
2170
                continue;
 
2171
              if ((parameters[i].flags & FLAGS_STICKY) &&
 
2172
                  (parameters[i].type == workParameter.type))
 
2173
                {
 
2174
                  /* Do not overwrite current qualifiers */
 
2175
                  workParameter.flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
 
2176
                  if (workParameter.width == NO_WIDTH)
 
2177
                    workParameter.width = parameters[i].width;
 
2178
                  if (workParameter.precision == NO_PRECISION)
 
2179
                    workParameter.precision = parameters[i].precision;
 
2180
                  if (workParameter.base == NO_BASE)
 
2181
                    workParameter.base = parameters[i].base;
 
2182
                  break;
 
2183
                }
 
2184
            }
 
2185
        }
 
2186
#endif
 
2187
 
 
2188
      if (workParameter.base == NO_BASE)
 
2189
        workParameter.base = BASE_DECIMAL;
 
2190
 
 
2191
      offset = workParameter.endOffset;
 
2192
 
 
2193
      TrioCopyParameter(&parameters[pos++], &workParameter);
1879
2194
    } /* while format characters left */
1880
2195
 
 
2196
  parameters[pos].type = FORMAT_SENTINEL;  /* end parameter array with sentinel */
 
2197
  parameters[pos].beginOffset = offset;
 
2198
 
1881
2199
  for (num = 0; num <= maxParam; num++)
1882
2200
    {
1883
2201
      if (usedEntries[num] != 1)
1923
2241
        {
1924
2242
        case FORMAT_GROUP:
1925
2243
        case FORMAT_STRING:
1926
 
#if TRIO_WIDECHAR
1927
 
          if (flags & FLAGS_WIDECHAR)
 
2244
#if TRIO_FEATURE_WIDECHAR
 
2245
          if (parameters[i].flags & FLAGS_WIDECHAR)
1928
2246
            {
1929
2247
              parameters[i].data.wstring = (argarray == NULL)
1930
 
                ? va_arg(*arglist, trio_wchar_t *)
 
2248
                ? va_arg(arglist, trio_wchar_t *)
1931
2249
                : (trio_wchar_t *)(argarray[num]);
1932
2250
            }
1933
2251
          else
1934
2252
#endif
1935
2253
            {
1936
2254
              parameters[i].data.string = (argarray == NULL)
1937
 
                ? va_arg(*arglist, char *)
 
2255
                ? va_arg(arglist, char *)
1938
2256
                : (char *)(argarray[num]);
1939
2257
            }
1940
2258
          break;
1941
2259
 
1942
 
#if defined(FORMAT_USER_DEFINED)
 
2260
#if TRIO_FEATURE_USER_DEFINED
1943
2261
        case FORMAT_USER_DEFINED:
1944
2262
#endif
1945
2263
        case FORMAT_POINTER:
1946
2264
        case FORMAT_COUNT:
1947
2265
        case FORMAT_UNKNOWN:
1948
2266
          parameters[i].data.pointer = (argarray == NULL)
1949
 
            ? va_arg(*arglist, trio_pointer_t )
 
2267
            ? va_arg(arglist, trio_pointer_t )
1950
2268
            : argarray[num];
1951
2269
          break;
1952
2270
 
1953
2271
        case FORMAT_CHAR:
1954
2272
        case FORMAT_INT:
 
2273
#if TRIO_FEATURE_SCANF
1955
2274
          if (TYPE_SCAN == type)
1956
2275
            {
1957
2276
              if (argarray == NULL)
1958
2277
                parameters[i].data.pointer = 
1959
 
                  (trio_pointer_t)va_arg(*arglist, trio_pointer_t);
 
2278
                  (trio_pointer_t)va_arg(arglist, trio_pointer_t);
1960
2279
              else
1961
2280
                {
1962
2281
                  if (parameters[i].type == FORMAT_CHAR)
1971
2290
                }
1972
2291
            }
1973
2292
          else
 
2293
#endif /* TRIO_FEATURE_SCANF */
1974
2294
            {
1975
 
#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
 
2295
#if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE
1976
2296
              if (parameters[i].flags
1977
2297
                  & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
1978
2298
                {
 
2299
                  int varsize;
1979
2300
                  if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
1980
2301
                    {
1981
2302
                      /*
2000
2321
                    ;
2001
2322
                  else if (varsize <= (int)sizeof(long))
2002
2323
                    parameters[i].flags |= FLAGS_LONG;
2003
 
#if defined(QUALIFIER_INTMAX_T)
 
2324
#if TRIO_FEATURE_INTMAX_T
2004
2325
                  else if (varsize <= (int)sizeof(trio_longlong_t))
2005
2326
                    parameters[i].flags |= FLAGS_QUAD;
2006
2327
                  else
2010
2331
                    parameters[i].flags |= FLAGS_QUAD;
2011
2332
#endif
2012
2333
                }
2013
 
#endif /* defined(QUALIFIER_VARSIZE) */
2014
 
#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
 
2334
#endif /* TRIO_FEATURE_VARSIZE */
 
2335
#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
2015
2336
              if (parameters[i].flags & FLAGS_SIZE_T)
2016
2337
                parameters[i].data.number.as_unsigned = (argarray == NULL)
2017
 
                  ? (trio_uintmax_t)va_arg(*arglist, size_t)
 
2338
                  ? (trio_uintmax_t)va_arg(arglist, size_t)
2018
2339
                  : (trio_uintmax_t)(*((size_t *)argarray[num]));
2019
2340
              else
2020
2341
#endif
2021
 
#if defined(QUALIFIER_PTRDIFF_T)
 
2342
#if TRIO_FEATURE_PTRDIFF_T
2022
2343
              if (parameters[i].flags & FLAGS_PTRDIFF_T)
2023
2344
                parameters[i].data.number.as_unsigned = (argarray == NULL)
2024
 
                  ? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t)
 
2345
                  ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t)
2025
2346
                  : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
2026
2347
              else
2027
2348
#endif
2028
 
#if defined(QUALIFIER_INTMAX_T)
 
2349
#if TRIO_FEATURE_INTMAX_T
2029
2350
              if (parameters[i].flags & FLAGS_INTMAX_T)
2030
2351
                parameters[i].data.number.as_unsigned = (argarray == NULL)
2031
 
                  ? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t)
 
2352
                  ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t)
2032
2353
                  : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
2033
2354
              else
2034
2355
#endif
2035
2356
              if (parameters[i].flags & FLAGS_QUAD)
2036
2357
                parameters[i].data.number.as_unsigned = (argarray == NULL)
2037
 
                  ? (trio_uintmax_t)va_arg(*arglist, trio_ulonglong_t)
 
2358
                  ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t)
2038
2359
                  : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
2039
2360
              else if (parameters[i].flags & FLAGS_LONG)
2040
2361
                parameters[i].data.number.as_unsigned = (argarray == NULL)
2041
 
                  ? (trio_uintmax_t)va_arg(*arglist, long)
 
2362
                  ? (trio_uintmax_t)va_arg(arglist, long)
2042
2363
                  : (trio_uintmax_t)(*((long *)argarray[num]));
2043
2364
              else
2044
2365
                {
2045
2366
                  if (argarray == NULL)
2046
 
                    parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
 
2367
                    parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int);
2047
2368
                  else
2048
2369
                    {
2049
2370
                      if (parameters[i].type == FORMAT_CHAR)
2064
2385
           */
2065
2386
          if (parameters[i].flags & FLAGS_USER_DEFINED)
2066
2387
            parameters[i].data.pointer = (argarray == NULL)
2067
 
              ? va_arg(*arglist, trio_pointer_t )
 
2388
              ? va_arg(arglist, trio_pointer_t )
2068
2389
              : argarray[num];
2069
2390
          else
2070
2391
            parameters[i].data.number.as_unsigned = (argarray == NULL)
2071
 
              ? (trio_uintmax_t)va_arg(*arglist, int)
 
2392
              ? (trio_uintmax_t)va_arg(arglist, int)
2072
2393
              : (trio_uintmax_t)(*((int *)argarray[num]));
2073
2394
          break;
2074
2395
 
 
2396
#if TRIO_FEATURE_FLOAT
2075
2397
        case FORMAT_DOUBLE:
 
2398
# if TRIO_FEATURE_SCANF
2076
2399
          if (TYPE_SCAN == type)
2077
2400
            {
2078
2401
              if (parameters[i].flags & FLAGS_LONGDOUBLE)
2079
2402
                parameters[i].data.longdoublePointer = (argarray == NULL)
2080
 
                  ? va_arg(*arglist, trio_long_double_t *)
 
2403
                  ? va_arg(arglist, trio_long_double_t *)
2081
2404
                  : (trio_long_double_t *)argarray[num];
2082
2405
              else
2083
2406
                {
2084
2407
                  if (parameters[i].flags & FLAGS_LONG)
2085
2408
                    parameters[i].data.doublePointer = (argarray == NULL)
2086
 
                      ? va_arg(*arglist, double *)
 
2409
                      ? va_arg(arglist, double *)
2087
2410
                      : (double *)argarray[num];
2088
2411
                  else
2089
2412
                    parameters[i].data.doublePointer = (argarray == NULL)
2090
 
                      ? (double *)va_arg(*arglist, float *)
 
2413
                      ? (double *)va_arg(arglist, float *)
2091
2414
                      : (double *)((float *)argarray[num]);
2092
2415
                }
2093
2416
            }
2094
2417
          else
 
2418
# endif /* TRIO_FEATURE_SCANF */
2095
2419
            {
2096
2420
              if (parameters[i].flags & FLAGS_LONGDOUBLE)
2097
2421
                parameters[i].data.longdoubleNumber = (argarray == NULL)
2098
 
                  ? va_arg(*arglist, trio_long_double_t)
 
2422
                  ? va_arg(arglist, trio_long_double_t)
2099
2423
                  : (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
2100
2424
              else
2101
2425
                {
2102
2426
                  if (argarray == NULL)
2103
2427
                    parameters[i].data.longdoubleNumber =
2104
 
                      (trio_long_double_t)va_arg(*arglist, double);
 
2428
                      (trio_long_double_t)va_arg(arglist, double);
2105
2429
                  else
2106
2430
                    {
2107
2431
                      if (parameters[i].flags & FLAGS_SHORT)
2114
2438
                }
2115
2439
            }
2116
2440
          break;
 
2441
#endif /* TRIO_FEATURE_FLOAT */
2117
2442
 
2118
 
#if defined(FORMAT_ERRNO)
 
2443
#if TRIO_FEATURE_ERRNO
2119
2444
        case FORMAT_ERRNO:
2120
2445
          parameters[i].data.errorNumber = save_errno;
2121
2446
          break;
2163
2488
  char *pointer;
2164
2489
  TRIO_CONST char *digits;
2165
2490
  int i;
 
2491
#if TRIO_FEATURE_QUOTE
2166
2492
  int length;
2167
2493
  char *p;
 
2494
#endif
2168
2495
  int count;
 
2496
  int digitOffset;
2169
2497
 
2170
2498
  assert(VALID(self));
2171
2499
  assert(VALID(self->OutStream));
2205
2533
  *pointer-- = NIL;
2206
2534
  for (i = 1; i < (int)sizeof(buffer); i++)
2207
2535
    {
2208
 
      *pointer-- = digits[number % base];
 
2536
      digitOffset = number % base;
 
2537
      *pointer-- = digits[digitOffset];
2209
2538
      number /= base;
2210
2539
      if (number == 0)
2211
2540
        break;
2212
2541
 
 
2542
#if TRIO_FEATURE_QUOTE
2213
2543
      if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
2214
2544
        {
2215
2545
          /*
2225
2555
                *pointer-- = *p--;
2226
2556
            }
2227
2557
        }
 
2558
#endif
2228
2559
    }
2229
2560
 
2230
2561
  if (! ignoreNumber)
2418
2749
    {
2419
2750
      string = internalNullString;
2420
2751
      length = sizeof(internalNullString) - 1;
 
2752
#if TRIO_FEATURE_QUOTE
2421
2753
      /* Disable quoting for the null pointer */
2422
2754
      flags &= (~FLAGS_QUOTE);
 
2755
#endif
2423
2756
      width = 0;
2424
2757
    }
2425
2758
  else
2426
2759
    {
2427
 
      length = trio_length(string);
 
2760
      if (precision == 0)
 
2761
        {
 
2762
          length = trio_length(string);
 
2763
        }
 
2764
      else
 
2765
        {
 
2766
          length = trio_length_max(string, precision);
 
2767
        }
2428
2768
    }
2429
2769
  if ((NO_PRECISION != precision) &&
2430
2770
      (precision < length))
2433
2773
    }
2434
2774
  width -= length;
2435
2775
 
 
2776
#if TRIO_FEATURE_QUOTE
2436
2777
  if (flags & FLAGS_QUOTE)
2437
2778
    self->OutStream(self, CHAR_QUOTE);
 
2779
#endif
2438
2780
 
2439
2781
  if (! (flags & FLAGS_LEFTADJUST))
2440
2782
    {
2454
2796
      while (width-- > 0)
2455
2797
        self->OutStream(self, CHAR_ADJUST);
2456
2798
    }
 
2799
#if TRIO_FEATURE_QUOTE
2457
2800
  if (flags & FLAGS_QUOTE)
2458
2801
    self->OutStream(self, CHAR_QUOTE);
 
2802
#endif
2459
2803
}
2460
2804
 
2461
2805
/*************************************************************************
2464
2808
 * Description:
2465
2809
 *  Output a wide string as a multi-byte sequence
2466
2810
 */
2467
 
#if TRIO_WIDECHAR
 
2811
#if TRIO_FEATURE_WIDECHAR
2468
2812
TRIO_PRIVATE int
2469
2813
TrioWriteWideStringCharacter
2470
2814
TRIO_ARGS4((self, wch, flags, width),
2496
2840
    }
2497
2841
  return size;
2498
2842
}
2499
 
#endif /* TRIO_WIDECHAR */
 
2843
#endif /* TRIO_FEATURE_WIDECHAR */
2500
2844
 
2501
2845
/*************************************************************************
2502
2846
 * TrioWriteWideString
2504
2848
 * Description:
2505
2849
 *  Output a wide character string as a multi-byte string
2506
2850
 */
2507
 
#if TRIO_WIDECHAR
 
2851
#if TRIO_FEATURE_WIDECHAR
2508
2852
TRIO_PRIVATE void
2509
2853
TrioWriteWideString
2510
2854
TRIO_ARGS5((self, wstring, flags, width, precision),
2521
2865
  assert(VALID(self->OutStream));
2522
2866
 
2523
2867
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
 
2868
  /* Required by TrioWriteWideStringCharacter */
2524
2869
  (void)mblen(NULL, 0);
2525
2870
#endif
2526
2871
  
2540
2885
      width -= length;
2541
2886
    }
2542
2887
 
 
2888
#if TRIO_FEATURE_QUOTE
2543
2889
  if (flags & FLAGS_QUOTE)
2544
2890
    self->OutStream(self, CHAR_QUOTE);
 
2891
#endif
2545
2892
 
2546
2893
  if (! (flags & FLAGS_LEFTADJUST))
2547
2894
    {
2562
2909
      while (width-- > 0)
2563
2910
        self->OutStream(self, CHAR_ADJUST);
2564
2911
    }
 
2912
#if TRIO_FEATURE_QUOTE
2565
2913
  if (flags & FLAGS_QUOTE)
2566
2914
    self->OutStream(self, CHAR_QUOTE);
 
2915
#endif
2567
2916
}
2568
 
#endif /* TRIO_WIDECHAR */
 
2917
#endif /* TRIO_FEATURE_WIDECHAR */
2569
2918
 
2570
2919
/*************************************************************************
2571
2920
 * TrioWriteDouble
2582
2931
/* FIXME: handle all instances of constant long-double number (L)
2583
2932
 *   and *l() math functions.
2584
2933
 */
 
2934
#if TRIO_FEATURE_FLOAT
2585
2935
TRIO_PRIVATE void
2586
2936
TrioWriteDouble
2587
2937
TRIO_ARGS6((self, number, flags, width, precision, base),
2598
2948
  int integerDigits;
2599
2949
  int fractionDigits;
2600
2950
  int exponentDigits;
 
2951
  int workDigits;
2601
2952
  int baseDigits;
2602
2953
  int integerThreshold;
2603
2954
  int fractionThreshold;
2606
2957
  unsigned int uExponent = 0;
2607
2958
  int exponentBase;
2608
2959
  trio_long_double_t dblBase;
2609
 
  trio_long_double_t dblIntegerBase;
2610
2960
  trio_long_double_t dblFractionBase;
2611
2961
  trio_long_double_t integerAdjust;
2612
2962
  trio_long_double_t fractionAdjust;
 
2963
  trio_long_double_t workFractionNumber;
 
2964
  trio_long_double_t workFractionAdjust;
 
2965
  int fractionDigitsInspect;
2613
2966
  BOOLEAN_T isNegative;
2614
2967
  BOOLEAN_T isExponentNegative = FALSE;
2615
2968
  BOOLEAN_T requireTwoDigitExponent;
2616
2969
  BOOLEAN_T isHex;
2617
2970
  TRIO_CONST char *digits;
 
2971
# if TRIO_FEATURE_QUOTE
2618
2972
  char *groupingPointer;
 
2973
# endif
2619
2974
  int i;
2620
 
  int index;
 
2975
  int offset;
2621
2976
  BOOLEAN_T hasOnlyZeroes;
2622
 
  int zeroes = 0;
 
2977
  int leadingFractionZeroes = -1;
2623
2978
  register int trailingZeroes;
2624
2979
  BOOLEAN_T keepTrailingZeroes;
2625
2980
  BOOLEAN_T keepDecimalPoint;
2626
2981
  trio_long_double_t epsilon;
 
2982
  BOOLEAN_T adjustNumber = FALSE;
2627
2983
  
2628
2984
  assert(VALID(self));
2629
2985
  assert(VALID(self->OutStream));
2672
3028
    {
2673
3029
      baseDigits = (base == 10)
2674
3030
        ? LDBL_DIG
2675
 
        : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
 
3031
        : (int)trio_floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
2676
3032
      epsilon = LDBL_EPSILON;
2677
3033
    }
2678
3034
  else if (flags & FLAGS_SHORT)
2679
3035
    {
2680
3036
      baseDigits = (base == BASE_DECIMAL)
2681
3037
        ? FLT_DIG
2682
 
        : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base));
 
3038
        : (int)trio_floor(FLT_MANT_DIG / TrioLogarithmBase(base));
2683
3039
      epsilon = FLT_EPSILON;
2684
3040
    }
2685
3041
  else
2686
3042
    {
2687
3043
      baseDigits = (base == BASE_DECIMAL)
2688
3044
        ? DBL_DIG
2689
 
        : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
 
3045
        : (int)trio_floor(DBL_MANT_DIG / TrioLogarithmBase(base));
2690
3046
      epsilon = DBL_EPSILON;
2691
3047
    }
2692
3048
 
2699
3055
                          ( (flags & FLAGS_FLOAT_G) &&
2700
3056
                            !(flags & FLAGS_ALTERNATIVE) ) );
2701
3057
 
 
3058
# if TRIO_FEATURE_ROUNDING
2702
3059
  if (flags & FLAGS_ROUNDING)
2703
 
    precision = baseDigits;
 
3060
    {
 
3061
      precision = baseDigits;
 
3062
    }
 
3063
# endif
2704
3064
 
2705
3065
  if (precision == NO_PRECISION)
2706
3066
    {
2716
3076
    }
2717
3077
  
2718
3078
  if (isNegative)
2719
 
    number = -number;
 
3079
    {
 
3080
      number = -number;
 
3081
    }
2720
3082
 
2721
3083
  if (isHex)
2722
 
    flags |= FLAGS_FLOAT_E;
2723
 
  
 
3084
    {
 
3085
      flags |= FLAGS_FLOAT_E;
 
3086
    }
 
3087
 
 
3088
 reprocess:
 
3089
 
2724
3090
  if (flags & FLAGS_FLOAT_G)
2725
3091
    {
2726
3092
      if (precision == 0)
2727
3093
        precision = 1;
2728
3094
 
2729
 
      if ((number < 1.0E-4) || (number > powl(base,
2730
 
                                              (trio_long_double_t)precision)))
 
3095
      if ( (number < TRIO_SUFFIX_LONG(1.0E-4)) ||
 
3096
           (number >= TrioPower(base, (trio_long_double_t)precision)) )
2731
3097
        {
2732
3098
          /* Use scientific notation */
2733
3099
          flags |= FLAGS_FLOAT_E;
2741
3107
           */
2742
3108
          workNumber = TrioLogarithm(number, base);
2743
3109
          workNumber = TRIO_FABS(workNumber);
2744
 
          if (workNumber - floorl(workNumber) < 0.001)
 
3110
          if (workNumber - trio_floor(workNumber) < epsilon)
2745
3111
            workNumber--;
2746
 
          zeroes = (int)floorl(workNumber);
 
3112
          leadingFractionZeroes = (int)trio_floor(workNumber);
2747
3113
        }
2748
3114
    }
2749
3115
 
2760
3126
        }
2761
3127
      else
2762
3128
        {
2763
 
          exponent = (int)floorl(workNumber);
2764
 
          number /= powl(dblBase, (trio_long_double_t)exponent);
 
3129
          exponent = (int)trio_floor(workNumber);
 
3130
          workNumber = number;
 
3131
          /*
 
3132
           * The expression A * 10^-B is equivalent to A / 10^B but the former
 
3133
           * usually gives better accuracy.
 
3134
           */
 
3135
          workNumber *= TrioPower(dblBase, (trio_long_double_t)-exponent);
 
3136
          if (trio_isinf(workNumber)) {
 
3137
            /*
 
3138
             * Scaling is done it two steps to avoid problems with subnormal
 
3139
             * numbers.
 
3140
             */
 
3141
            workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent / 2));
 
3142
            workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent - (exponent / 2)));
 
3143
          }
 
3144
          number = workNumber;
2765
3145
          isExponentNegative = (exponent < 0);
2766
3146
          uExponent = (isExponentNegative) ? -exponent : exponent;
2767
3147
          if (isHex)
2768
3148
            uExponent *= 4; /* log16(2) */
 
3149
#if TRIO_FEATURE_QUOTE
2769
3150
          /* No thousand separators */
2770
3151
          flags &= ~FLAGS_QUOTE;
 
3152
#endif
2771
3153
        }
2772
3154
    }
2773
3155
 
2774
 
  integerNumber = floorl(number);
 
3156
  integerNumber = trio_floor(number);
2775
3157
  fractionNumber = number - integerNumber;
2776
 
  
 
3158
 
2777
3159
  /*
2778
3160
   * Truncated number.
2779
3161
   *
2780
 
   * Precision is number of significant digits for FLOAT_G
2781
 
   * and number of fractional digits for others.
 
3162
   * Precision is number of significant digits for FLOAT_G and number of
 
3163
   * fractional digits for others.
2782
3164
   */
2783
 
  integerDigits = (integerNumber > epsilon)
2784
 
    ? 1 + (int)TrioLogarithm(integerNumber, base)
2785
 
    : 1;
2786
 
  fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
2787
 
    ? precision - integerDigits
2788
 
    : zeroes + precision;
 
3165
  integerDigits = 1;
 
3166
  if (integerNumber > epsilon)
 
3167
    {
 
3168
      integerDigits += (int)TrioLogarithm(integerNumber, base);
 
3169
    }
 
3170
 
 
3171
  fractionDigits = precision;
 
3172
  if (flags & FLAGS_FLOAT_G)
 
3173
    {
 
3174
      if (leadingFractionZeroes > 0)
 
3175
        {
 
3176
          fractionDigits += leadingFractionZeroes;
 
3177
        }
 
3178
      if ((integerNumber > epsilon) || (number <= epsilon))
 
3179
        {
 
3180
          fractionDigits -= integerDigits;
 
3181
        }
 
3182
    }
2789
3183
 
2790
3184
  dblFractionBase = TrioPower(base, fractionDigits);
2791
 
  
2792
 
  workNumber = number + 0.5 / dblFractionBase;
2793
 
  if (floorl(number) != floorl(workNumber))
2794
 
    {
 
3185
 
 
3186
  if (integerNumber < 1.0)
 
3187
    {
 
3188
      workNumber = number * dblFractionBase + TRIO_SUFFIX_LONG(0.5);
 
3189
      if (trio_floor(number * dblFractionBase) != trio_floor(workNumber))
 
3190
        {
 
3191
          adjustNumber = TRUE;
 
3192
          /* Remove a leading fraction zero if fraction is rounded up */
 
3193
          if ((int)TrioLogarithm(number * dblFractionBase, base) != (int)TrioLogarithm(workNumber, base))
 
3194
            {
 
3195
              --leadingFractionZeroes;
 
3196
            }
 
3197
        }
 
3198
      workNumber /= dblFractionBase;
 
3199
    }
 
3200
  else
 
3201
    {
 
3202
      workNumber = number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase;
 
3203
      adjustNumber = (trio_floor(number) != trio_floor(workNumber));
 
3204
    }
 
3205
  if (adjustNumber)
 
3206
    {
 
3207
      if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_FLOAT_E))
 
3208
        {
 
3209
          /* The adjustment may require a change to scientific notation */
 
3210
          if ( (workNumber < TRIO_SUFFIX_LONG(1.0E-4)) ||
 
3211
               (workNumber >= TrioPower(base, (trio_long_double_t)precision)) )
 
3212
            {
 
3213
              /* Use scientific notation */
 
3214
              flags |= FLAGS_FLOAT_E;
 
3215
              goto reprocess;
 
3216
            }
 
3217
        }
 
3218
      
2795
3219
      if (flags & FLAGS_FLOAT_E)
2796
3220
        {
2797
 
          /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
2798
 
          exponent++;
2799
 
          isExponentNegative = (exponent < 0);
2800
 
          uExponent = (isExponentNegative) ? -exponent : exponent;
2801
 
          if (isHex)
2802
 
            uExponent *= 4; /* log16(2) */
2803
 
          workNumber = (number + 0.5 / dblFractionBase) / dblBase;
2804
 
          integerNumber = floorl(workNumber);
2805
 
          fractionNumber = workNumber - integerNumber;
 
3221
          workDigits = 1 + TrioLogarithm(trio_floor(workNumber), base);
 
3222
          if (integerDigits == workDigits)
 
3223
            {
 
3224
              /* Adjust if the same number of digits are used */
 
3225
              number += TRIO_SUFFIX_LONG(0.5) / dblFractionBase;
 
3226
              integerNumber = trio_floor(number);
 
3227
              fractionNumber = number - integerNumber;
 
3228
            }
 
3229
          else
 
3230
            {
 
3231
              /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
 
3232
              exponent++;
 
3233
              isExponentNegative = (exponent < 0);
 
3234
              uExponent = (isExponentNegative) ? -exponent : exponent;
 
3235
              if (isHex)
 
3236
                uExponent *= 4; /* log16(2) */
 
3237
              workNumber = (number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase) / dblBase;
 
3238
              integerNumber = trio_floor(workNumber);
 
3239
              fractionNumber = workNumber - integerNumber;
 
3240
            }
2806
3241
        }
2807
3242
      else
2808
3243
        {
2809
 
          /* Adjust if number was rounded up one digit (ie. 99 to 100) */
2810
 
          integerNumber = floorl(number + 0.5);
2811
 
          fractionNumber = 0.0;
2812
 
          integerDigits = (integerNumber > epsilon)
2813
 
            ? 1 + (int)TrioLogarithm(integerNumber, base)
2814
 
            : 1;
 
3244
          if (workNumber > 1.0)
 
3245
            {
 
3246
              /* Adjust if number was rounded up one digit (ie. 99 to 100) */
 
3247
              integerNumber = trio_floor(workNumber);
 
3248
              fractionNumber = 0.0;
 
3249
              integerDigits = (integerNumber > epsilon)
 
3250
                ? 1 + (int)TrioLogarithm(integerNumber, base)
 
3251
                : 1;
 
3252
              if (flags & FLAGS_FLOAT_G)
 
3253
                {
 
3254
                  if (flags & FLAGS_ALTERNATIVE)
 
3255
                    {
 
3256
                      if ((integerNumber > epsilon) || (number <= epsilon))
 
3257
                        {
 
3258
                          fractionDigits -= integerDigits;
 
3259
                        }
 
3260
                    }
 
3261
                  else
 
3262
                    {
 
3263
                      fractionDigits = 0;
 
3264
                    }
 
3265
                }
 
3266
            }
 
3267
          else
 
3268
            {
 
3269
              integerNumber = trio_floor(workNumber);
 
3270
              fractionNumber = workNumber - integerNumber;
 
3271
              if (flags & FLAGS_FLOAT_G)
 
3272
                {
 
3273
                  if (flags & FLAGS_ALTERNATIVE)
 
3274
                    {
 
3275
                      fractionDigits = precision;
 
3276
                      if (leadingFractionZeroes > 0)
 
3277
                        {
 
3278
                          fractionDigits += leadingFractionZeroes;
 
3279
                        }
 
3280
                      if ((integerNumber > epsilon) || (number <= epsilon))
 
3281
                        {
 
3282
                          fractionDigits -= integerDigits;
 
3283
                        }
 
3284
                    }
 
3285
                }
 
3286
            }
2815
3287
        }
2816
3288
    }
2817
3289
 
2818
3290
  /* Estimate accuracy */
2819
 
  integerAdjust = fractionAdjust = 0.5;
 
3291
  integerAdjust = fractionAdjust = TRIO_SUFFIX_LONG(0.5);
 
3292
# if TRIO_FEATURE_ROUNDING
2820
3293
  if (flags & FLAGS_ROUNDING)
2821
3294
    {
2822
3295
      if (integerDigits > baseDigits)
2837
3310
        }
2838
3311
    }
2839
3312
  else
 
3313
# endif
2840
3314
    {
2841
3315
      integerThreshold = INT_MAX;
2842
3316
      fractionThreshold = INT_MAX;
2848
3322
   *  + fraction + exponent
2849
3323
   */
2850
3324
  fractionAdjust /= dblFractionBase;
2851
 
  hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
 
3325
  hasOnlyZeroes = (trio_floor((fractionNumber + fractionAdjust) *
 
3326
                               dblFractionBase) < epsilon);
2852
3327
  keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
2853
3328
                       !((precision == 0) ||
2854
3329
                         (!keepTrailingZeroes && hasOnlyZeroes)) );
 
3330
 
 
3331
  expectedWidth = integerDigits + fractionDigits;
 
3332
 
 
3333
  if (!keepTrailingZeroes)
 
3334
    {
 
3335
      trailingZeroes = 0;
 
3336
      workFractionNumber = fractionNumber;
 
3337
      workFractionAdjust = fractionAdjust;
 
3338
      fractionDigitsInspect = fractionDigits;
 
3339
 
 
3340
      if (integerDigits > integerThreshold)
 
3341
        {
 
3342
          fractionDigitsInspect = 0;
 
3343
        }
 
3344
      else if (fractionThreshold  <= fractionDigits)
 
3345
        {
 
3346
          fractionDigitsInspect = fractionThreshold + 1;
 
3347
        }
 
3348
 
 
3349
      trailingZeroes = fractionDigits - fractionDigitsInspect;
 
3350
      for (i = 0; i < fractionDigitsInspect; i++)
 
3351
        {
 
3352
          workFractionNumber *= dblBase;
 
3353
          workFractionAdjust *= dblBase;
 
3354
          workNumber = trio_floor(workFractionNumber + workFractionAdjust);
 
3355
          workFractionNumber -= workNumber;
 
3356
          offset = (int)trio_fmod(workNumber, dblBase);
 
3357
          if (offset == 0)
 
3358
            {
 
3359
              trailingZeroes++;
 
3360
            }
 
3361
          else
 
3362
            {
 
3363
              trailingZeroes = 0;
 
3364
            }
 
3365
        }
 
3366
      expectedWidth -= trailingZeroes;
 
3367
    }
 
3368
  
 
3369
  if (keepDecimalPoint)
 
3370
    {
 
3371
      expectedWidth += internalDecimalPointLength;
 
3372
    }
 
3373
  
 
3374
#if TRIO_FEATURE_QUOTE
 
3375
  if (flags & FLAGS_QUOTE)
 
3376
    {
 
3377
      expectedWidth += TrioCalcThousandSeparatorLength(integerDigits);
 
3378
    }
 
3379
#endif
 
3380
  
 
3381
  if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
 
3382
    {
 
3383
      expectedWidth += sizeof("-") - 1;
 
3384
    }
 
3385
  
 
3386
  exponentDigits = 0;
2855
3387
  if (flags & FLAGS_FLOAT_E)
2856
3388
    {
2857
3389
      exponentDigits = (uExponent == 0)
2858
3390
        ? 1
2859
 
        : (int)ceil(TrioLogarithm((double)(uExponent + 1),
2860
 
                                  (isHex) ? 10.0 : base));
 
3391
        : (int)trio_ceil(TrioLogarithm((double)(uExponent + 1),
 
3392
                                       (isHex) ? 10 : base));
2861
3393
    }
2862
 
  else
2863
 
    exponentDigits = 0;
2864
3394
  requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1));
2865
 
 
2866
 
  expectedWidth = integerDigits + fractionDigits
2867
 
    + (keepDecimalPoint
2868
 
       ? internalDecimalPointLength
2869
 
       : 0)
2870
 
    + ((flags & FLAGS_QUOTE)
2871
 
       ? TrioCalcThousandSeparatorLength(integerDigits)
2872
 
       : 0);
2873
 
  if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
2874
 
    expectedWidth += sizeof("-") - 1;
2875
3395
  if (exponentDigits > 0)
2876
 
    expectedWidth += exponentDigits +
2877
 
      ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
 
3396
    {
 
3397
      expectedWidth += exponentDigits;
 
3398
      expectedWidth += (requireTwoDigitExponent
 
3399
                        ? sizeof("E+0") - 1
 
3400
                        : sizeof("E+") - 1);
 
3401
    }
 
3402
  
2878
3403
  if (isHex)
2879
 
    expectedWidth += sizeof("0X") - 1;
 
3404
    {
 
3405
      expectedWidth += sizeof("0X") - 1;
 
3406
    }
2880
3407
  
2881
3408
  /* Output prefixing */
2882
3409
  if (flags & FLAGS_NILPADDING)
2925
3452
    }
2926
3453
  
2927
3454
  /* Output the integer part and thousand separators */
2928
 
  dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1);
2929
3455
  for (i = 0; i < integerDigits; i++)
2930
3456
    {
2931
 
      workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase));
 
3457
      workNumber = trio_floor(((integerNumber + integerAdjust)
 
3458
                               / TrioPower(base, integerDigits - i - 1)));
2932
3459
      if (i > integerThreshold)
2933
3460
        {
2934
3461
          /* Beyond accuracy */
2936
3463
        }
2937
3464
      else
2938
3465
        {
2939
 
          self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
 
3466
          self->OutStream(self, digits[(int)trio_fmod(workNumber, dblBase)]);
2940
3467
        }
2941
 
      dblIntegerBase *= dblBase;
2942
 
      
 
3468
 
 
3469
#if TRIO_FEATURE_QUOTE
2943
3470
      if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
2944
3471
          && TrioFollowedBySeparator(integerDigits - i))
2945
3472
        {
2950
3477
              self->OutStream(self, *groupingPointer);
2951
3478
            }
2952
3479
        }
 
3480
#endif
2953
3481
    }
2954
3482
  
2955
3483
  /* Insert decimal point and build the fraction part */
2981
3509
        {
2982
3510
          fractionNumber *= dblBase;
2983
3511
          fractionAdjust *= dblBase;
2984
 
          workNumber = floorl(fractionNumber + fractionAdjust);
2985
 
          fractionNumber -= workNumber;
2986
 
          index = (int)fmodl(workNumber, dblBase);
2987
 
          if (index == 0)
 
3512
          workNumber = trio_floor(fractionNumber + fractionAdjust);
 
3513
          if (workNumber > fractionNumber)
 
3514
            {
 
3515
              /* fractionNumber should never become negative */
 
3516
              fractionNumber = 0.0;
 
3517
              fractionAdjust = 0.0;
 
3518
            }
 
3519
          else
 
3520
            {
 
3521
              fractionNumber -= workNumber;
 
3522
            }
 
3523
          offset = (int)trio_fmod(workNumber, dblBase);
 
3524
          if (offset == 0)
2988
3525
            {
2989
3526
              trailingZeroes++;
2990
3527
            }
2996
3533
                  self->OutStream(self, digits[0]);
2997
3534
                  trailingZeroes--;
2998
3535
                }
2999
 
              self->OutStream(self, digits[index]);
 
3536
              self->OutStream(self, digits[offset]);
3000
3537
            }
3001
3538
        }
3002
3539
    }
3024
3561
        self->OutStream(self, '0');
3025
3562
 
3026
3563
      if (isHex)
3027
 
        base = 10.0;
 
3564
        base = 10;
3028
3565
      exponentBase = (int)TrioPower(base, exponentDigits - 1);
3029
3566
      for (i = 0; i < exponentDigits; i++)
3030
3567
        {
3041
3578
        }
3042
3579
    }
3043
3580
}
 
3581
#endif /* TRIO_FEATURE_FLOAT */
3044
3582
 
3045
3583
/*************************************************************************
3046
3584
 * TrioFormatProcess
3055
3593
           TRIO_CONST char *format,
3056
3594
           trio_parameter_t *parameters)
3057
3595
{
3058
 
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3059
 
  int charlen;
3060
 
#endif
3061
3596
  int i;
 
3597
#if TRIO_FEATURE_ERRNO
3062
3598
  TRIO_CONST char *string;
 
3599
#endif
3063
3600
  trio_pointer_t pointer;
3064
3601
  trio_flags_t flags;
3065
3602
  int width;
3066
3603
  int precision;
3067
3604
  int base;
3068
 
  int index;
 
3605
  int offset;
3069
3606
  
3070
 
  index = 0;
 
3607
  offset = 0;
3071
3608
  i = 0;
3072
 
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3073
 
  (void)mblen(NULL, 0);
3074
 
#endif
3075
 
  
3076
 
  while (format[index])
 
3609
 
 
3610
  for (;;)
3077
3611
    {
3078
 
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
3079
 
      if (! isascii(format[index]))
3080
 
        {
3081
 
          charlen = mblen(&format[index], MB_LEN_MAX);
3082
 
          /*
3083
 
           * Only valid multibyte characters are handled here. Invalid
3084
 
           * multibyte characters (charlen == -1) are handled as normal
3085
 
           * characters.
3086
 
           */
3087
 
          if (charlen != -1)
3088
 
            {
3089
 
              while (charlen-- > 0)
3090
 
                {
3091
 
                  data->OutStream(data, format[index++]);
3092
 
                }
3093
 
              continue; /* while characters left in formatting string */
3094
 
            }
3095
 
        }
3096
 
#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
3097
 
      if (CHAR_IDENTIFIER == format[index])
3098
 
        {
3099
 
          if (CHAR_IDENTIFIER == format[index + 1])
 
3612
      /* Skip the parameter entries */
 
3613
      while (parameters[i].type == FORMAT_PARAMETER)
 
3614
        i++;
 
3615
 
 
3616
      /* Copy non conversion-specifier part of format string */
 
3617
      while (offset < parameters[i].beginOffset)
 
3618
        {
 
3619
          if (CHAR_IDENTIFIER == format[offset] && CHAR_IDENTIFIER == format[offset + 1])
3100
3620
            {
3101
3621
              data->OutStream(data, CHAR_IDENTIFIER);
3102
 
              index += 2;
 
3622
              offset += 2;
3103
3623
            }
3104
3624
          else
3105
3625
            {
3106
 
              /* Skip the parameter entries */
3107
 
              while (parameters[i].type == FORMAT_PARAMETER)
3108
 
                i++;
3109
 
              
3110
 
              flags = parameters[i].flags;
3111
 
 
3112
 
              /* Find width */
3113
 
              width = parameters[i].width;
3114
 
              if (flags & FLAGS_WIDTH_PARAMETER)
3115
 
                {
3116
 
                  /* Get width from parameter list */
3117
 
                  width = (int)parameters[width].data.number.as_signed;
3118
 
                  if (width < 0)
3119
 
                    {
3120
 
                      /*
3121
 
                       * A negative width is the same as the - flag and
3122
 
                       * a positive width.
3123
 
                       */
3124
 
                      flags |= FLAGS_LEFTADJUST;
3125
 
                      flags &= ~FLAGS_NILPADDING;
3126
 
                      width = -width;
3127
 
                    }
3128
 
                }
3129
 
              
3130
 
              /* Find precision */
3131
 
              if (flags & FLAGS_PRECISION)
3132
 
                {
3133
 
                  precision = parameters[i].precision;
3134
 
                  if (flags & FLAGS_PRECISION_PARAMETER)
3135
 
                    {
3136
 
                      /* Get precision from parameter list */
3137
 
                      precision = (int)parameters[precision].data.number.as_signed;
3138
 
                      if (precision < 0)
3139
 
                        {
3140
 
                          /*
3141
 
                           * A negative precision is the same as no
3142
 
                           * precision
3143
 
                           */
3144
 
                          precision = NO_PRECISION;
3145
 
                        }
3146
 
                    }
3147
 
                }
3148
 
              else
3149
 
                {
 
3626
              data->OutStream(data, format[offset++]);
 
3627
            }
 
3628
        }
 
3629
 
 
3630
      /* Abort if we reached end of format string */
 
3631
      if (parameters[i].type == FORMAT_SENTINEL)
 
3632
        break;
 
3633
 
 
3634
      /* Ouput parameter */
 
3635
      flags = parameters[i].flags;
 
3636
 
 
3637
      /* Find width */
 
3638
      width = parameters[i].width;
 
3639
      if (flags & FLAGS_WIDTH_PARAMETER)
 
3640
        {
 
3641
          /* Get width from parameter list */
 
3642
          width = (int)parameters[width].data.number.as_signed;
 
3643
          if (width < 0)
 
3644
            {
 
3645
              /*
 
3646
               * A negative width is the same as the - flag and
 
3647
               * a positive width.
 
3648
               */
 
3649
              flags |= FLAGS_LEFTADJUST;
 
3650
              flags &= ~FLAGS_NILPADDING;
 
3651
              width = -width;
 
3652
            }
 
3653
        }
 
3654
 
 
3655
      /* Find precision */
 
3656
      if (flags & FLAGS_PRECISION)
 
3657
        {
 
3658
          precision = parameters[i].precision;
 
3659
          if (flags & FLAGS_PRECISION_PARAMETER)
 
3660
            {
 
3661
              /* Get precision from parameter list */
 
3662
              precision = (int)parameters[precision].data.number.as_signed;
 
3663
              if (precision < 0)
 
3664
                {
 
3665
                  /*
 
3666
                   * A negative precision is the same as no
 
3667
                   * precision
 
3668
                   */
3150
3669
                  precision = NO_PRECISION;
3151
3670
                }
3152
 
 
3153
 
              /* Find base */
3154
 
              base = parameters[i].base;
3155
 
              if (flags & FLAGS_BASE_PARAMETER)
3156
 
                {
3157
 
                  /* Get base from parameter list */
3158
 
                  base = (int)parameters[base].data.number.as_signed;
3159
 
                }
3160
 
              
3161
 
              switch (parameters[i].type)
3162
 
                {
3163
 
                case FORMAT_CHAR:
3164
 
                  if (flags & FLAGS_QUOTE)
3165
 
                    data->OutStream(data, CHAR_QUOTE);
3166
 
                  if (! (flags & FLAGS_LEFTADJUST))
3167
 
                    {
3168
 
                      while (--width > 0)
3169
 
                        data->OutStream(data, CHAR_ADJUST);
3170
 
                    }
3171
 
#if TRIO_WIDECHAR
3172
 
                  if (flags & FLAGS_WIDECHAR)
3173
 
                    {
3174
 
                      TrioWriteWideStringCharacter(data,
3175
 
                                                   (trio_wchar_t)parameters[i].data.number.as_signed,
3176
 
                                                   flags,
3177
 
                                                   NO_WIDTH);
3178
 
                    }
3179
 
                  else
3180
 
#endif
3181
 
                    {
3182
 
                      TrioWriteStringCharacter(data,
3183
 
                                               (int)parameters[i].data.number.as_signed,
3184
 
                                               flags);
3185
 
                    }
3186
 
 
3187
 
                  if (flags & FLAGS_LEFTADJUST)
3188
 
                    {
3189
 
                      while(--width > 0)
3190
 
                        data->OutStream(data, CHAR_ADJUST);
3191
 
                    }
3192
 
                  if (flags & FLAGS_QUOTE)
3193
 
                    data->OutStream(data, CHAR_QUOTE);
3194
 
 
3195
 
                  break; /* FORMAT_CHAR */
3196
 
 
3197
 
                case FORMAT_INT:
3198
 
                  TrioWriteNumber(data,
3199
 
                                  parameters[i].data.number.as_unsigned,
3200
 
                                  flags,
3201
 
                                  width,
3202
 
                                  precision,
3203
 
                                  base);
3204
 
 
3205
 
                  break; /* FORMAT_INT */
3206
 
 
3207
 
                case FORMAT_DOUBLE:
3208
 
                  TrioWriteDouble(data,
3209
 
                                  parameters[i].data.longdoubleNumber,
3210
 
                                  flags,
3211
 
                                  width,
3212
 
                                  precision,
3213
 
                                  base);
3214
 
                  break; /* FORMAT_DOUBLE */
3215
 
 
3216
 
                case FORMAT_STRING:
3217
 
#if TRIO_WIDECHAR
3218
 
                  if (flags & FLAGS_WIDECHAR)
3219
 
                    {
3220
 
                      TrioWriteWideString(data,
3221
 
                                          parameters[i].data.wstring,
3222
 
                                          flags,
3223
 
                                          width,
3224
 
                                          precision);
3225
 
                    }
3226
 
                  else
3227
 
#endif
3228
 
                    {
3229
 
                      TrioWriteString(data,
3230
 
                                      parameters[i].data.string,
3231
 
                                      flags,
3232
 
                                      width,
3233
 
                                      precision);
3234
 
                    }
3235
 
                  break; /* FORMAT_STRING */
3236
 
 
3237
 
                case FORMAT_POINTER:
3238
 
                  {
3239
 
                    trio_reference_t reference;
3240
 
                    
3241
 
                    reference.data = data;
3242
 
                    reference.parameter = &parameters[i];
3243
 
                    trio_print_pointer(&reference, parameters[i].data.pointer);
3244
 
                  }
3245
 
                  break; /* FORMAT_POINTER */
3246
 
 
3247
 
                case FORMAT_COUNT:
3248
 
                  pointer = parameters[i].data.pointer;
3249
 
                  if (NULL != pointer)
3250
 
                    {
3251
 
                      /*
3252
 
                       * C99 paragraph 7.19.6.1.8 says "the number of
3253
 
                       * characters written to the output stream so far by
3254
 
                       * this call", which is data->committed
3255
 
                       */
3256
 
#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
3257
 
                      if (flags & FLAGS_SIZE_T)
3258
 
                        *(size_t *)pointer = (size_t)data->committed;
3259
 
                      else
3260
 
#endif
3261
 
#if defined(QUALIFIER_PTRDIFF_T)
3262
 
                      if (flags & FLAGS_PTRDIFF_T)
3263
 
                        *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
3264
 
                      else
3265
 
#endif
3266
 
#if defined(QUALIFIER_INTMAX_T)
3267
 
                      if (flags & FLAGS_INTMAX_T)
3268
 
                        *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
3269
 
                      else
3270
 
#endif
3271
 
                      if (flags & FLAGS_QUAD)
3272
 
                        {
3273
 
                          *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
3274
 
                        }
3275
 
                      else if (flags & FLAGS_LONG)
3276
 
                        {
3277
 
                          *(long int *)pointer = (long int)data->committed;
3278
 
                        }
3279
 
                      else if (flags & FLAGS_SHORT)
3280
 
                        {
3281
 
                          *(short int *)pointer = (short int)data->committed;
3282
 
                        }
3283
 
                      else
3284
 
                        {
3285
 
                          *(int *)pointer = (int)data->committed;
3286
 
                        }
3287
 
                    }
3288
 
                  break; /* FORMAT_COUNT */
3289
 
 
3290
 
                case FORMAT_PARAMETER:
3291
 
                  break; /* FORMAT_PARAMETER */
3292
 
 
3293
 
#if defined(FORMAT_ERRNO)
3294
 
                case FORMAT_ERRNO:
3295
 
                  string = trio_error(parameters[i].data.errorNumber);
3296
 
                  if (string)
3297
 
                    {
3298
 
                      TrioWriteString(data,
3299
 
                                      string,
3300
 
                                      flags,
3301
 
                                      width,
3302
 
                                      precision);
3303
 
                    }
3304
 
                  else
3305
 
                    {
3306
 
                      data->OutStream(data, '#');
3307
 
                      TrioWriteNumber(data,
3308
 
                                      (trio_uintmax_t)parameters[i].data.errorNumber,
3309
 
                                      flags,
3310
 
                                      width,
3311
 
                                      precision,
3312
 
                                      BASE_DECIMAL);
3313
 
                    }
3314
 
                  break; /* FORMAT_ERRNO */
3315
 
#endif /* defined(FORMAT_ERRNO) */
3316
 
 
3317
 
#if defined(FORMAT_USER_DEFINED)
3318
 
                case FORMAT_USER_DEFINED:
3319
 
                  {
3320
 
                    trio_reference_t reference;
3321
 
                    trio_userdef_t *def = NULL;
3322
 
 
3323
 
                    if (parameters[i].user_name[0] == NIL)
3324
 
                      {
3325
 
                        /* Use handle */
3326
 
                        if ((i > 0) ||
3327
 
                            (parameters[i - 1].type == FORMAT_PARAMETER))
3328
 
                          def = (trio_userdef_t *)parameters[i - 1].data.pointer;
3329
 
                      }
3330
 
                    else
3331
 
                      {
3332
 
                        /* Look up namespace */
3333
 
                        def = TrioFindNamespace(parameters[i].user_name, NULL);
3334
 
                      }
3335
 
                    if (def) {
3336
 
                      reference.data = data;
3337
 
                      reference.parameter = &parameters[i];
3338
 
                      def->callback(&reference);
3339
 
                    }
3340
 
                  }
3341
 
                  break;
3342
 
#endif /* defined(FORMAT_USER_DEFINED) */
3343
 
                  
3344
 
                default:
3345
 
                  break;
3346
 
                } /* switch parameter type */
3347
 
 
3348
 
              /* Prepare for next */
3349
 
              index = parameters[i].indexAfterSpecifier;
3350
 
              i++;
3351
 
            }
3352
 
        }
3353
 
      else /* not identifier */
3354
 
        {
3355
 
          data->OutStream(data, format[index++]);
3356
 
        }
 
3671
            }
 
3672
        }
 
3673
      else
 
3674
        {
 
3675
          precision = NO_PRECISION;
 
3676
        }
 
3677
 
 
3678
      /* Find base */
 
3679
      if (NO_BASE != parameters[i].baseSpecifier)
 
3680
        {
 
3681
          /* Base from specifier has priority */
 
3682
          base = parameters[i].baseSpecifier;
 
3683
        }
 
3684
      else if (flags & FLAGS_BASE_PARAMETER)
 
3685
        {
 
3686
          /* Get base from parameter list */
 
3687
          base = parameters[i].base;
 
3688
          base = (int)parameters[base].data.number.as_signed;
 
3689
        }
 
3690
      else
 
3691
        {
 
3692
          /* Use base from format string */
 
3693
          base = parameters[i].base;
 
3694
        }
 
3695
 
 
3696
      switch (parameters[i].type)
 
3697
        {
 
3698
        case FORMAT_CHAR:
 
3699
#if TRIO_FEATURE_QUOTE
 
3700
          if (flags & FLAGS_QUOTE)
 
3701
            data->OutStream(data, CHAR_QUOTE);
 
3702
#endif
 
3703
          if (! (flags & FLAGS_LEFTADJUST))
 
3704
            {
 
3705
              while (--width > 0)
 
3706
                data->OutStream(data, CHAR_ADJUST);
 
3707
            }
 
3708
#if TRIO_FEATURE_WIDECHAR
 
3709
          if (flags & FLAGS_WIDECHAR)
 
3710
            {
 
3711
              TrioWriteWideStringCharacter(data,
 
3712
                                           (trio_wchar_t)parameters[i].data.number.as_signed,
 
3713
                                           flags,
 
3714
                                           NO_WIDTH);
 
3715
            }
 
3716
          else
 
3717
#endif
 
3718
          {
 
3719
            TrioWriteStringCharacter(data,
 
3720
                                     (int)parameters[i].data.number.as_signed,
 
3721
                                     flags);
 
3722
          }
 
3723
 
 
3724
          if (flags & FLAGS_LEFTADJUST)
 
3725
            {
 
3726
              while(--width > 0)
 
3727
                data->OutStream(data, CHAR_ADJUST);
 
3728
            }
 
3729
#if TRIO_FEATURE_QUOTE
 
3730
          if (flags & FLAGS_QUOTE)
 
3731
            data->OutStream(data, CHAR_QUOTE);
 
3732
#endif
 
3733
 
 
3734
          break; /* FORMAT_CHAR */
 
3735
 
 
3736
        case FORMAT_INT:
 
3737
          TrioWriteNumber(data,
 
3738
                          parameters[i].data.number.as_unsigned,
 
3739
                          flags,
 
3740
                          width,
 
3741
                          precision,
 
3742
                          base);
 
3743
 
 
3744
          break; /* FORMAT_INT */
 
3745
 
 
3746
#if TRIO_FEATURE_FLOAT
 
3747
        case FORMAT_DOUBLE:
 
3748
          TrioWriteDouble(data,
 
3749
                          parameters[i].data.longdoubleNumber,
 
3750
                          flags,
 
3751
                          width,
 
3752
                          precision,
 
3753
                          base);
 
3754
          break; /* FORMAT_DOUBLE */
 
3755
#endif
 
3756
 
 
3757
        case FORMAT_STRING:
 
3758
#if TRIO_FEATURE_WIDECHAR
 
3759
          if (flags & FLAGS_WIDECHAR)
 
3760
            {
 
3761
              TrioWriteWideString(data,
 
3762
                                  parameters[i].data.wstring,
 
3763
                                  flags,
 
3764
                                  width,
 
3765
                                  precision);
 
3766
            }
 
3767
          else
 
3768
#endif
 
3769
            {
 
3770
              TrioWriteString(data,
 
3771
                              parameters[i].data.string,
 
3772
                              flags,
 
3773
                              width,
 
3774
                              precision);
 
3775
            }
 
3776
          break; /* FORMAT_STRING */
 
3777
 
 
3778
        case FORMAT_POINTER:
 
3779
          {
 
3780
            trio_reference_t reference;
 
3781
 
 
3782
            reference.data = data;
 
3783
            reference.parameter = &parameters[i];
 
3784
            trio_print_pointer(&reference, parameters[i].data.pointer);
 
3785
          }
 
3786
          break; /* FORMAT_POINTER */
 
3787
 
 
3788
        case FORMAT_COUNT:
 
3789
          pointer = parameters[i].data.pointer;
 
3790
          if (NULL != pointer)
 
3791
            {
 
3792
              /*
 
3793
               * C99 paragraph 7.19.6.1.8 says "the number of
 
3794
               * characters written to the output stream so far by
 
3795
               * this call", which is data->actually.committed
 
3796
               */
 
3797
#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
 
3798
              if (flags & FLAGS_SIZE_T)
 
3799
                *(size_t *)pointer = (size_t)data->actually.committed;
 
3800
              else
 
3801
#endif
 
3802
#if TRIO_FEATURE_PTRDIFF_T
 
3803
              if (flags & FLAGS_PTRDIFF_T)
 
3804
                *(ptrdiff_t *)pointer = (ptrdiff_t)data->actually.committed;
 
3805
              else
 
3806
#endif
 
3807
#if TRIO_FEATURE_INTMAX_T
 
3808
              if (flags & FLAGS_INTMAX_T)
 
3809
                *(trio_intmax_t *)pointer = (trio_intmax_t)data->actually.committed;
 
3810
              else
 
3811
#endif
 
3812
              if (flags & FLAGS_QUAD)
 
3813
                {
 
3814
                  *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->actually.committed;
 
3815
                }
 
3816
              else if (flags & FLAGS_LONG)
 
3817
                {
 
3818
                  *(long int *)pointer = (long int)data->actually.committed;
 
3819
                }
 
3820
              else if (flags & FLAGS_SHORT)
 
3821
                {
 
3822
                  *(short int *)pointer = (short int)data->actually.committed;
 
3823
                }
 
3824
              else
 
3825
                {
 
3826
                  *(int *)pointer = (int)data->actually.committed;
 
3827
                }
 
3828
            }
 
3829
          break; /* FORMAT_COUNT */
 
3830
 
 
3831
        case FORMAT_PARAMETER:
 
3832
          break; /* FORMAT_PARAMETER */
 
3833
 
 
3834
#if TRIO_FEATURE_ERRNO
 
3835
        case FORMAT_ERRNO:
 
3836
          string = trio_error(parameters[i].data.errorNumber);
 
3837
          if (string)
 
3838
            {
 
3839
              TrioWriteString(data,
 
3840
                              string,
 
3841
                              flags,
 
3842
                              width,
 
3843
                              precision);
 
3844
            }
 
3845
          else
 
3846
          {
 
3847
            data->OutStream(data, '#');
 
3848
            TrioWriteNumber(data,
 
3849
                            (trio_uintmax_t)parameters[i].data.errorNumber,
 
3850
                            flags,
 
3851
                            width,
 
3852
                            precision,
 
3853
                            BASE_DECIMAL);
 
3854
          }
 
3855
          break; /* FORMAT_ERRNO */
 
3856
#endif /* TRIO_FEATURE_ERRNO */
 
3857
 
 
3858
#if TRIO_FEATURE_USER_DEFINED
 
3859
        case FORMAT_USER_DEFINED:
 
3860
          {
 
3861
            trio_reference_t reference;
 
3862
            trio_userdef_t *def = NULL;
 
3863
 
 
3864
            if (parameters[i].flags & FLAGS_USER_DEFINED_PARAMETER)
 
3865
              {
 
3866
                /* Use handle */
 
3867
                if ((i > 0) ||
 
3868
                    (parameters[i - 1].type == FORMAT_PARAMETER))
 
3869
                  def = (trio_userdef_t *)parameters[i - 1].data.pointer;
 
3870
              }
 
3871
            else
 
3872
              {
 
3873
                /* Look up namespace */
 
3874
                def = TrioFindNamespace(parameters[i].user_defined.namespace, NULL);
 
3875
              }
 
3876
            if (def)
 
3877
              {
 
3878
                reference.data = data;
 
3879
                reference.parameter = &parameters[i];
 
3880
                def->callback(&reference);
 
3881
              }
 
3882
          }
 
3883
          break;
 
3884
#endif /* TRIO_FEATURE_USER_DEFINED */
 
3885
 
 
3886
        default:
 
3887
          break;
 
3888
        } /* switch parameter type */
 
3889
 
 
3890
      /* Prepare for next */
 
3891
      offset = parameters[i].endOffset;
 
3892
      i++;
3357
3893
    }
 
3894
 
3358
3895
  return data->processed;
3359
3896
}
3360
3897
 
3361
3898
/*************************************************************************
3362
3899
 * TrioFormatRef
3363
3900
 */
 
3901
#if TRIO_EXTENSION
3364
3902
TRIO_PRIVATE int
3365
3903
TrioFormatRef
3366
3904
TRIO_ARGS4((reference, format, arglist, argarray),
3367
3905
           trio_reference_t *reference,
3368
3906
           TRIO_CONST char *format,
3369
 
           va_list *arglist,
 
3907
           va_list arglist,
3370
3908
           trio_pointer_t *argarray)
3371
3909
{
3372
3910
  int status;
3383
3921
    }
3384
3922
  return status;
3385
3923
}
 
3924
#endif /* TRIO_EXTENSION */
3386
3925
 
3387
3926
/*************************************************************************
3388
3927
 * TrioFormat
3394
3933
           size_t destinationSize,
3395
3934
           void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
3396
3935
           TRIO_CONST char *format,
3397
 
           va_list *arglist,
 
3936
           va_list arglist,
3398
3937
           trio_pointer_t *argarray)
3399
3938
{
3400
3939
  int status;
3432
3971
/*************************************************************************
3433
3972
 * TrioOutStreamFile
3434
3973
 */
 
3974
#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
3435
3975
TRIO_PRIVATE void
3436
3976
TrioOutStreamFile
3437
3977
TRIO_ARGS2((self, output),
3451
3991
    }
3452
3992
  else
3453
3993
    {
3454
 
      self->committed++;
 
3994
      self->actually.committed++;
3455
3995
    }
3456
3996
}
 
3997
#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
3457
3998
 
3458
3999
/*************************************************************************
3459
4000
 * TrioOutStreamFileDescriptor
3460
4001
 */
 
4002
#if TRIO_FEATURE_FD
3461
4003
TRIO_PRIVATE void
3462
4004
TrioOutStreamFileDescriptor
3463
4005
TRIO_ARGS2((self, output),
3478
4020
    }
3479
4021
  else
3480
4022
    {
3481
 
      self->committed++;
 
4023
      self->actually.committed++;
3482
4024
    }
3483
4025
}
 
4026
#endif /* TRIO_FEATURE_FD */
3484
4027
 
3485
4028
/*************************************************************************
3486
4029
 * TrioOutStreamCustom
3487
4030
 */
 
4031
#if TRIO_FEATURE_CLOSURE
3488
4032
TRIO_PRIVATE void
3489
4033
TrioOutStreamCustom
3490
4034
TRIO_ARGS2((self, output),
3503
4047
      status = (data->stream.out)(data->closure, output);
3504
4048
      if (status >= 0)
3505
4049
        {
3506
 
          self->committed++;
 
4050
          self->actually.committed++;
3507
4051
        }
3508
4052
      else
3509
4053
        {
3515
4059
    }
3516
4060
  self->processed++;
3517
4061
}
 
4062
#endif /* TRIO_FEATURE_CLOSURE */
3518
4063
 
3519
4064
/*************************************************************************
3520
4065
 * TrioOutStreamString
3534
4079
  **buffer = (char)output;
3535
4080
  (*buffer)++;
3536
4081
  self->processed++;
3537
 
  self->committed++;
 
4082
  self->actually.committed++;
3538
4083
}
3539
4084
 
3540
4085
/*************************************************************************
3557
4102
    {
3558
4103
      **buffer = (char)output;
3559
4104
      (*buffer)++;
3560
 
      self->committed++;
 
4105
      self->actually.committed++;
3561
4106
    }
3562
4107
  self->processed++;
3563
4108
}
3565
4110
/*************************************************************************
3566
4111
 * TrioOutStreamStringDynamic
3567
4112
 */
 
4113
#if TRIO_FEATURE_DYNAMICSTRING
3568
4114
TRIO_PRIVATE void
3569
4115
TrioOutStreamStringDynamic
3570
4116
TRIO_ARGS2((self, output),
3578
4124
    {
3579
4125
      trio_xstring_append_char((trio_string_t *)self->location,
3580
4126
                               (char)output);
3581
 
      self->committed++;
 
4127
      self->actually.committed++;
3582
4128
    }
3583
4129
  /* The processed variable must always be increased */
3584
4130
  self->processed++;
3585
4131
}
 
4132
#endif /* TRIO_FEATURE_DYNAMICSTRING */
3586
4133
 
3587
4134
/*************************************************************************
3588
4135
 *
3608
4155
   @param ... Arguments.
3609
4156
   @return Number of printed characters.
3610
4157
 */
 
4158
#if TRIO_FEATURE_STDIO
3611
4159
TRIO_PUBLIC int
3612
4160
trio_printf
3613
4161
TRIO_VARGS2((format, va_alist),
3620
4168
  assert(VALID(format));
3621
4169
  
3622
4170
  TRIO_VA_START(args, format);
3623
 
  status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
 
4171
  status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
3624
4172
  TRIO_VA_END(args);
3625
4173
  return status;
3626
4174
}
 
4175
#endif /* TRIO_FEATURE_STDIO */
3627
4176
 
3628
4177
/**
3629
4178
   Print to standard output stream.
3632
4181
   @param args Arguments.
3633
4182
   @return Number of printed characters.
3634
4183
 */
 
4184
#if TRIO_FEATURE_STDIO
3635
4185
TRIO_PUBLIC int
3636
4186
trio_vprintf
3637
4187
TRIO_ARGS2((format, args),
3640
4190
{
3641
4191
  assert(VALID(format));
3642
4192
 
3643
 
  return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
 
4193
  return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
3644
4194
}
 
4195
#endif /* TRIO_FEATURE_STDIO */
3645
4196
 
3646
4197
/**
3647
4198
   Print to standard output stream.
3650
4201
   @param args Arguments.
3651
4202
   @return Number of printed characters.
3652
4203
 */
 
4204
#if TRIO_FEATURE_STDIO
3653
4205
TRIO_PUBLIC int
3654
4206
trio_printfv
3655
4207
TRIO_ARGS2((format, args),
3656
4208
           TRIO_CONST char *format,
3657
4209
           trio_pointer_t * args)
3658
4210
{
 
4211
  static va_list unused;
 
4212
  
3659
4213
  assert(VALID(format));
3660
4214
 
3661
 
  return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
 
4215
  return TrioFormat(stdout, 0, TrioOutStreamFile, format, unused, args);
3662
4216
}
 
4217
#endif /* TRIO_FEATURE_STDIO */
3663
4218
 
3664
4219
/*************************************************************************
3665
4220
 * fprintf
3673
4228
   @param ... Arguments.
3674
4229
   @return Number of printed characters.
3675
4230
 */
 
4231
#if TRIO_FEATURE_FILE
3676
4232
TRIO_PUBLIC int
3677
4233
trio_fprintf
3678
4234
TRIO_VARGS3((file, format, va_alist),
3687
4243
  assert(VALID(format));
3688
4244
  
3689
4245
  TRIO_VA_START(args, format);
3690
 
  status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
 
4246
  status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
3691
4247
  TRIO_VA_END(args);
3692
4248
  return status;
3693
4249
}
 
4250
#endif /* TRIO_FEATURE_FILE */
3694
4251
 
3695
4252
/**
3696
4253
   Print to file.
3700
4257
   @param args Arguments.
3701
4258
   @return Number of printed characters.
3702
4259
 */
 
4260
#if TRIO_FEATURE_FILE
3703
4261
TRIO_PUBLIC int
3704
4262
trio_vfprintf
3705
4263
TRIO_ARGS3((file, format, args),
3710
4268
  assert(VALID(file));
3711
4269
  assert(VALID(format));
3712
4270
  
3713
 
  return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
 
4271
  return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
3714
4272
}
 
4273
#endif /* TRIO_FEATURE_FILE */
3715
4274
 
3716
4275
/**
3717
4276
   Print to file.
3721
4280
   @param args Arguments.
3722
4281
   @return Number of printed characters.
3723
4282
 */
 
4283
#if TRIO_FEATURE_FILE
3724
4284
TRIO_PUBLIC int
3725
4285
trio_fprintfv
3726
4286
TRIO_ARGS3((file, format, args),
3728
4288
           TRIO_CONST char *format,
3729
4289
           trio_pointer_t * args)
3730
4290
{
 
4291
  static va_list unused;
 
4292
  
3731
4293
  assert(VALID(file));
3732
4294
  assert(VALID(format));
3733
4295
  
3734
 
  return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
 
4296
  return TrioFormat(file, 0, TrioOutStreamFile, format, unused, args);
3735
4297
}
 
4298
#endif /* TRIO_FEATURE_FILE */
3736
4299
 
3737
4300
/*************************************************************************
3738
4301
 * dprintf
3746
4309
   @param ... Arguments.
3747
4310
   @return Number of printed characters.
3748
4311
 */
 
4312
#if TRIO_FEATURE_FD
3749
4313
TRIO_PUBLIC int
3750
4314
trio_dprintf
3751
4315
TRIO_VARGS3((fd, format, va_alist),
3759
4323
  assert(VALID(format));
3760
4324
  
3761
4325
  TRIO_VA_START(args, format);
3762
 
  status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
 
4326
  status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
3763
4327
  TRIO_VA_END(args);
3764
4328
  return status;
3765
4329
}
 
4330
#endif /* TRIO_FEATURE_FD */
3766
4331
 
3767
4332
/**
3768
4333
   Print to file descriptor.
3772
4337
   @param args Arguments.
3773
4338
   @return Number of printed characters.
3774
4339
 */
 
4340
#if TRIO_FEATURE_FD
3775
4341
TRIO_PUBLIC int
3776
4342
trio_vdprintf
3777
4343
TRIO_ARGS3((fd, format, args),
3781
4347
{
3782
4348
  assert(VALID(format));
3783
4349
  
3784
 
  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
 
4350
  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
3785
4351
}
 
4352
#endif /* TRIO_FEATURE_FD */
3786
4353
 
3787
4354
/**
3788
4355
   Print to file descriptor.
3792
4359
   @param args Arguments.
3793
4360
   @return Number of printed characters.
3794
4361
 */
 
4362
#if TRIO_FEATURE_FD
3795
4363
TRIO_PUBLIC int
3796
4364
trio_dprintfv
3797
4365
TRIO_ARGS3((fd, format, args),
3799
4367
           TRIO_CONST char *format,
3800
4368
           trio_pointer_t *args)
3801
4369
{
 
4370
  static va_list unused;
 
4371
  
3802
4372
  assert(VALID(format));
3803
4373
  
3804
 
  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
 
4374
  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, unused, args);
3805
4375
}
 
4376
#endif /* TRIO_FEATURE_FD */
3806
4377
 
3807
4378
/*************************************************************************
3808
4379
 * cprintf
3809
4380
 */
 
4381
#if TRIO_FEATURE_CLOSURE
3810
4382
TRIO_PUBLIC int
3811
4383
trio_cprintf
3812
4384
TRIO_VARGS4((stream, closure, format, va_alist),
3825
4397
  TRIO_VA_START(args, format);
3826
4398
  data.stream.out = stream;
3827
4399
  data.closure = closure;
3828
 
  status = TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
 
4400
  status = TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
3829
4401
  TRIO_VA_END(args);
3830
4402
  return status;
3831
4403
}
 
4404
#endif /* TRIO_FEATURE_CLOSURE */
3832
4405
 
 
4406
#if TRIO_FEATURE_CLOSURE
3833
4407
TRIO_PUBLIC int
3834
4408
trio_vcprintf
3835
4409
TRIO_ARGS4((stream, closure, format, args),
3845
4419
 
3846
4420
  data.stream.out = stream;
3847
4421
  data.closure = closure;
3848
 
  return TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
 
4422
  return TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
3849
4423
}
 
4424
#endif /* TRIO_FEATURE_CLOSURE */
3850
4425
 
 
4426
#if TRIO_FEATURE_CLOSURE
3851
4427
TRIO_PUBLIC int
3852
4428
trio_cprintfv
3853
4429
TRIO_ARGS4((stream, closure, format, args),
3856
4432
           TRIO_CONST char *format,
3857
4433
           void **args)
3858
4434
{
 
4435
  static va_list unused;
3859
4436
  trio_custom_t data;
3860
4437
 
3861
4438
  assert(VALID(stream));
3863
4440
 
3864
4441
  data.stream.out = stream;
3865
4442
  data.closure = closure;
3866
 
  return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
 
4443
  return TrioFormat(&data, 0, TrioOutStreamCustom, format, unused, args);
3867
4444
}
 
4445
#endif /* TRIO_FEATURE_CLOSURE */
3868
4446
 
3869
4447
/*************************************************************************
3870
4448
 * sprintf
3892
4470
  assert(VALID(format));
3893
4471
  
3894
4472
  TRIO_VA_START(args, format);
3895
 
  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
 
4473
  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
3896
4474
  *buffer = NIL; /* Terminate with NIL character */
3897
4475
  TRIO_VA_END(args);
3898
4476
  return status;
3918
4496
  assert(VALID(buffer));
3919
4497
  assert(VALID(format));
3920
4498
 
3921
 
  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
 
4499
  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
3922
4500
  *buffer = NIL;
3923
4501
  return status;
3924
4502
}
3938
4516
           TRIO_CONST char *format,
3939
4517
           trio_pointer_t *args)
3940
4518
{
 
4519
  static va_list unused;
3941
4520
  int status;
3942
 
 
 
4521
  
3943
4522
  assert(VALID(buffer));
3944
4523
  assert(VALID(format));
3945
4524
 
3946
 
  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
 
4525
  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, unused, args);
3947
4526
  *buffer = NIL;
3948
4527
  return status;
3949
4528
}
3972
4551
  int status;
3973
4552
  va_list args;
3974
4553
 
3975
 
  assert(VALID(buffer));
 
4554
  assert(VALID(buffer) || (max == 0));
3976
4555
  assert(VALID(format));
3977
4556
 
3978
4557
  TRIO_VA_START(args, format);
3979
4558
  status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
3980
 
                      TrioOutStreamStringMax, format, &args, NULL);
 
4559
                      TrioOutStreamStringMax, format, args, NULL);
3981
4560
  if (max > 0)
3982
4561
    *buffer = NIL;
3983
4562
  TRIO_VA_END(args);
4003
4582
{
4004
4583
  int status;
4005
4584
 
4006
 
  assert(VALID(buffer));
 
4585
  assert(VALID(buffer) || (max == 0));
4007
4586
  assert(VALID(format));
4008
4587
 
4009
4588
  status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4010
 
                      TrioOutStreamStringMax, format, &args, NULL);
 
4589
                      TrioOutStreamStringMax, format, args, NULL);
4011
4590
  if (max > 0)
4012
4591
    *buffer = NIL;
4013
4592
  return status;
4030
4609
           TRIO_CONST char *format,
4031
4610
           trio_pointer_t *args)
4032
4611
{
 
4612
  static va_list unused;
4033
4613
  int status;
4034
4614
 
4035
 
  assert(VALID(buffer));
 
4615
  assert(VALID(buffer) || (max == 0));
4036
4616
  assert(VALID(format));
4037
4617
 
4038
4618
  status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
4039
 
                      TrioOutStreamStringMax, format, NULL, args);
 
4619
                      TrioOutStreamStringMax, format, unused, args);
4040
4620
  if (max > 0)
4041
4621
    *buffer = NIL;
4042
4622
  return status;
4047
4627
 * Appends the new string to the buffer string overwriting the '\0'
4048
4628
 * character at the end of buffer.
4049
4629
 */
 
4630
#if TRIO_EXTENSION
4050
4631
TRIO_PUBLIC int
4051
4632
trio_snprintfcat
4052
4633
TRIO_VARGS4((buffer, max, format, va_alist),
4068
4649
  buffer = &buffer[buf_len];
4069
4650
 
4070
4651
  status = TrioFormat(&buffer, max - 1 - buf_len,
4071
 
                      TrioOutStreamStringMax, format, &args, NULL);
 
4652
                      TrioOutStreamStringMax, format, args, NULL);
4072
4653
  TRIO_VA_END(args);
4073
4654
  *buffer = NIL;
4074
4655
  return status;
4075
4656
}
 
4657
#endif
4076
4658
 
 
4659
#if TRIO_EXTENSION
4077
4660
TRIO_PUBLIC int
4078
4661
trio_vsnprintfcat
4079
4662
TRIO_ARGS4((buffer, max, format, args),
4091
4674
  buf_len = trio_length(buffer);
4092
4675
  buffer = &buffer[buf_len];
4093
4676
  status = TrioFormat(&buffer, max - 1 - buf_len,
4094
 
                      TrioOutStreamStringMax, format, &args, NULL);
 
4677
                      TrioOutStreamStringMax, format, args, NULL);
4095
4678
  *buffer = NIL;
4096
4679
  return status;
4097
4680
}
 
4681
#endif
4098
4682
 
4099
4683
/*************************************************************************
4100
4684
 * trio_aprintf
4101
4685
 */
4102
4686
 
4103
 
/* Deprecated */
 
4687
#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
4104
4688
TRIO_PUBLIC char *
4105
4689
trio_aprintf
4106
4690
TRIO_VARGS2((format, va_alist),
4118
4702
    {
4119
4703
      TRIO_VA_START(args, format);
4120
4704
      (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
4121
 
                       format, &args, NULL);
 
4705
                       format, args, NULL);
4122
4706
      TRIO_VA_END(args);
4123
4707
 
4124
4708
      trio_string_terminate(info);
4127
4711
    }
4128
4712
  return result;
4129
4713
}
 
4714
#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
4130
4715
 
4131
 
/* Deprecated */
 
4716
#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
4132
4717
TRIO_PUBLIC char *
4133
4718
trio_vaprintf
4134
4719
TRIO_ARGS2((format, args),
4144
4729
  if (info)
4145
4730
    {
4146
4731
      (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
4147
 
                       format, &args, NULL);
 
4732
                       format, args, NULL);
4148
4733
      trio_string_terminate(info);
4149
4734
      result = trio_string_extract(info);
4150
4735
      trio_string_destroy(info);
4151
4736
    }
4152
4737
  return result;
4153
4738
}
4154
 
 
 
4739
#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
 
4740
 
 
4741
/**
 
4742
   Allocate and print to string.
 
4743
   The memory allocated and returned by @p result must be freed by the
 
4744
   calling application.
 
4745
 
 
4746
   @param result Output string.
 
4747
   @param format Formatting string.
 
4748
   @param ... Arguments.
 
4749
   @return Number of printed characters.
 
4750
 */
 
4751
#if TRIO_FEATURE_DYNAMICSTRING
4155
4752
TRIO_PUBLIC int
4156
4753
trio_asprintf
4157
4754
TRIO_VARGS3((result, format, va_alist),
4176
4773
    {
4177
4774
      TRIO_VA_START(args, format);
4178
4775
      status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
4179
 
                          format, &args, NULL);
 
4776
                          format, args, NULL);
4180
4777
      TRIO_VA_END(args);
4181
4778
      if (status >= 0)
4182
4779
        {
4187
4784
    }
4188
4785
  return status;
4189
4786
}
4190
 
 
 
4787
#endif /* TRIO_FEATURE_DYNAMICSTRING */
 
4788
 
 
4789
/**
 
4790
   Allocate and print to string.
 
4791
   The memory allocated and returned by @p result must be freed by the
 
4792
   calling application.
 
4793
 
 
4794
   @param result Output string.
 
4795
   @param format Formatting string.
 
4796
   @param args Arguments.
 
4797
   @return Number of printed characters.
 
4798
 */
 
4799
#if TRIO_FEATURE_DYNAMICSTRING
4191
4800
TRIO_PUBLIC int
4192
4801
trio_vasprintf
4193
4802
TRIO_ARGS3((result, format, args),
4210
4819
  else
4211
4820
    {
4212
4821
      status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
4213
 
                          format, &args, NULL);
 
4822
                          format, args, NULL);
4214
4823
      if (status >= 0)
4215
4824
        {
4216
4825
          trio_string_terminate(info);
4220
4829
    }
4221
4830
  return status;
4222
4831
}
 
4832
#endif /* TRIO_FEATURE_DYNAMICSTRING */
 
4833
 
 
4834
/**
 
4835
   Allocate and print to string.
 
4836
   The memory allocated and returned by @p result must be freed by the
 
4837
   calling application.
 
4838
 
 
4839
   @param result Output string.
 
4840
   @param format Formatting string.
 
4841
   @param args Arguments.
 
4842
   @return Number of printed characters.
 
4843
 */
 
4844
#if TRIO_FEATURE_DYNAMICSTRING
 
4845
TRIO_PUBLIC int
 
4846
trio_asprintfv
 
4847
TRIO_ARGS3((result, format, args),
 
4848
           char **result,
 
4849
           TRIO_CONST char *format,
 
4850
           trio_pointer_t * args)
 
4851
{
 
4852
  static va_list unused;
 
4853
  int status;
 
4854
  trio_string_t *info;
 
4855
  
 
4856
  assert(VALID(format));
 
4857
 
 
4858
  *result = NULL;
 
4859
 
 
4860
  info = trio_xstring_duplicate("");
 
4861
  if (info == NULL)
 
4862
    {
 
4863
      status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
 
4864
    }
 
4865
  else
 
4866
    {
 
4867
      status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
 
4868
                          format, unused, args);
 
4869
      if (status >= 0)
 
4870
        {
 
4871
          trio_string_terminate(info);
 
4872
          *result = trio_string_extract(info);
 
4873
        }
 
4874
      trio_string_destroy(info);
 
4875
    }
 
4876
  return status;
 
4877
}
 
4878
#endif /* TRIO_FEATURE_DYNAMICSTRING */
4223
4879
 
4224
4880
/** @} End of Printf documentation module */
4225
4881
 
4237
4893
   @{
4238
4894
*/
4239
4895
 
4240
 
#if TRIO_EXTENSION
 
4896
#if TRIO_FEATURE_USER_DEFINED
4241
4897
 
4242
4898
/*************************************************************************
4243
4899
 * trio_register
4340
4996
            (void)internalEnterCriticalRegion(NULL);
4341
4997
          
4342
4998
          if (prev == NULL)
4343
 
            internalUserDef = NULL;
 
4999
            internalUserDef = internalUserDef->next;
4344
5000
          else
4345
5001
            prev->next = def->next;
4346
5002
          
4360
5016
TRIO_ARGS1((ref),
4361
5017
           trio_pointer_t ref)
4362
5018
{
4363
 
#if defined(FORMAT_USER_DEFINED)
 
5019
#if TRIO_FEATURE_USER_DEFINED
4364
5020
  assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
4365
5021
#endif
4366
5022
  
4370
5026
/*************************************************************************
4371
5027
 * trio_get_argument [public]
4372
5028
 */
4373
 
trio_pointer_t 
 
5029
TRIO_CONST trio_pointer_t
4374
5030
trio_get_argument
4375
5031
TRIO_ARGS1((ref),
4376
5032
           trio_pointer_t ref)
4377
5033
{
4378
 
#if defined(FORMAT_USER_DEFINED)
 
5034
#if TRIO_FEATURE_USER_DEFINED
4379
5035
  assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
4380
5036
#endif
4381
 
  
 
5037
 
4382
5038
  return ((trio_reference_t *)ref)->parameter->data.pointer;
4383
5039
}
4384
5040
 
4495
5151
/*************************************************************************
4496
5152
 * trio_get_longdouble / trio_set_longdouble [public]
4497
5153
 */
 
5154
# if TRIO_FEATURE_FLOAT
4498
5155
int
4499
5156
trio_get_longdouble
4500
5157
TRIO_ARGS1((ref),
4516
5173
  else
4517
5174
    ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
4518
5175
}
 
5176
# endif /* TRIO_FEATURE_FLOAT */
4519
5177
 
4520
5178
/*************************************************************************
4521
5179
 * trio_get_short / trio_set_short [public]
4695
5353
/*************************************************************************
4696
5354
 * trio_get_quote / trio_set_quote [public]
4697
5355
 */
 
5356
# if TRIO_FEATURE_QUOTE
4698
5357
int
4699
5358
trio_get_quote
4700
5359
TRIO_ARGS1((ref),
4716
5375
  else
4717
5376
    ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
4718
5377
}
 
5378
#endif /* TRIO_FEATURE_QUOTE */
4719
5379
 
4720
5380
/*************************************************************************
4721
5381
 * trio_get_upper / trio_set_upper [public]
4745
5405
/*************************************************************************
4746
5406
 * trio_get_largest / trio_set_largest [public]
4747
5407
 */
4748
 
#if TRIO_C99
 
5408
#if TRIO_FEATURE_INTMAX_T
4749
5409
int
4750
5410
trio_get_largest
4751
5411
TRIO_ARGS1((ref),
4767
5427
  else
4768
5428
    ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
4769
5429
}
4770
 
#endif
 
5430
#endif /* TRIO_FEATURE_INTMAX_T */
4771
5431
 
4772
5432
/*************************************************************************
4773
5433
 * trio_get_ptrdiff / trio_set_ptrdiff [public]
4774
5434
 */
 
5435
#if TRIO_FEATURE_PTRDIFF_T
4775
5436
int
4776
5437
trio_get_ptrdiff
4777
5438
TRIO_ARGS1((ref),
4793
5454
  else
4794
5455
    ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
4795
5456
}
 
5457
#endif /* TRIO_FEATURE_PTRDIFF_T */
4796
5458
 
4797
5459
/*************************************************************************
4798
5460
 * trio_get_size / trio_set_size [public]
4799
5461
 */
4800
 
#if TRIO_C99
 
5462
#if TRIO_FEATURE_SIZE_T
4801
5463
int
4802
5464
trio_get_size
4803
5465
TRIO_ARGS1((ref),
4819
5481
  else
4820
5482
    ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
4821
5483
}
4822
 
#endif
 
5484
#endif /* TRIO_FEATURE_SIZE_T */
4823
5485
 
4824
5486
/*************************************************************************
4825
5487
 * trio_print_int [public]
4862
5524
/*************************************************************************
4863
5525
 * trio_print_double [public]
4864
5526
 */
 
5527
#if TRIO_FEATURE_FLOAT
4865
5528
void
4866
5529
trio_print_double
4867
5530
TRIO_ARGS2((ref, number),
4877
5540
                  self->parameter->precision,
4878
5541
                  self->parameter->base);
4879
5542
}
 
5543
#endif /* TRIO_FEATURE_FLOAT */
4880
5544
 
4881
5545
/*************************************************************************
4882
5546
 * trio_print_string [public]
4885
5549
trio_print_string
4886
5550
TRIO_ARGS2((ref, string),
4887
5551
           trio_pointer_t ref,
4888
 
           char *string)
 
5552
           TRIO_CONST char *string)
4889
5553
{
4890
5554
  trio_reference_t *self = (trio_reference_t *)ref;
4891
5555
 
4912
5576
  assert(VALID(format));
4913
5577
  
4914
5578
  TRIO_VA_START(arglist, format);
4915
 
  status = TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
 
5579
  status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
4916
5580
  TRIO_VA_END(arglist);
4917
5581
  return status;
4918
5582
}
4929
5593
{
4930
5594
  assert(VALID(format));
4931
5595
  
4932
 
  return TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
 
5596
  return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
4933
5597
}
4934
5598
 
4935
5599
/*************************************************************************
4942
5606
           TRIO_CONST char *format,
4943
5607
           trio_pointer_t *argarray)
4944
5608
{
 
5609
  static va_list unused;
 
5610
  
4945
5611
  assert(VALID(format));
4946
5612
  
4947
 
  return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
 
5613
  return TrioFormatRef((trio_reference_t *)ref, format, unused, argarray);
4948
5614
}
4949
5615
 
4950
 
#endif /* TRIO_EXTENSION */
 
5616
#endif
4951
5617
 
4952
5618
/*************************************************************************
4953
5619
 * trio_print_pointer [public]
5007
5673
 * string to enable multibyte characters. At most MB_LEN_MAX characters
5008
5674
 * will be used.
5009
5675
 */
 
5676
#if TRIO_FEATURE_LOCALE
5010
5677
TRIO_PUBLIC void
5011
5678
trio_locale_set_decimal_point
5012
5679
TRIO_ARGS1((decimalPoint),
5031
5698
                    decimalPoint);
5032
5699
    }
5033
5700
}
 
5701
#endif
5034
5702
 
5035
5703
/*************************************************************************
5036
5704
 * trio_locale_set_thousand_separator
5037
5705
 *
5038
5706
 * See trio_locale_set_decimal_point
5039
5707
 */
 
5708
#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
5040
5709
TRIO_PUBLIC void
5041
5710
trio_locale_set_thousand_separator
5042
5711
TRIO_ARGS1((thousandSeparator),
5043
5712
           char *thousandSeparator)
5044
5713
{
5045
 
#if defined(USE_LOCALE)
 
5714
# if defined(USE_LOCALE)
5046
5715
  if (NULL == internalLocaleValues)
5047
5716
    {
5048
5717
      TrioSetLocale();
5049
5718
    }
5050
 
#endif
 
5719
# endif
5051
5720
  trio_copy_max(internalThousandSeparator,
5052
5721
                sizeof(internalThousandSeparator),
5053
5722
                thousandSeparator);
5054
5723
  internalThousandSeparatorLength = trio_length(internalThousandSeparator);
5055
5724
}
 
5725
#endif
5056
5726
 
5057
5727
/*************************************************************************
5058
5728
 * trio_locale_set_grouping
5066
5736
 *
5067
5737
 * Same order as the grouping attribute in LC_NUMERIC.
5068
5738
 */
 
5739
#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
5069
5740
TRIO_PUBLIC void
5070
5741
trio_locale_set_grouping
5071
5742
TRIO_ARGS1((grouping),
5072
5743
           char *grouping)
5073
5744
{
5074
 
#if defined(USE_LOCALE)
 
5745
# if defined(USE_LOCALE)
5075
5746
  if (NULL == internalLocaleValues)
5076
5747
    {
5077
5748
      TrioSetLocale();
5078
5749
    }
5079
 
#endif
 
5750
# endif
5080
5751
  trio_copy_max(internalGrouping,
5081
5752
                sizeof(internalGrouping),
5082
5753
                grouping);
5083
5754
}
 
5755
#endif
5084
5756
 
5085
5757
 
5086
5758
/*************************************************************************
5089
5761
 *
5090
5762
 ************************************************************************/
5091
5763
 
 
5764
#if TRIO_FEATURE_SCANF
 
5765
 
5092
5766
/*************************************************************************
5093
5767
 * TrioSkipWhitespaces
5094
5768
 */
5146
5820
 */
5147
5821
TRIO_PRIVATE int
5148
5822
TrioGetCharacterClass
5149
 
TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
 
5823
TRIO_ARGS4((format, offsetPointer, flagsPointer, characterclass),
5150
5824
           TRIO_CONST char *format,
5151
 
           int *indexPointer,
 
5825
           int *offsetPointer,
5152
5826
           trio_flags_t *flagsPointer,
5153
5827
           int *characterclass)
5154
5828
{
5155
 
  int index = *indexPointer;
 
5829
  int offset = *offsetPointer;
5156
5830
  int i;
5157
5831
  char ch;
5158
5832
  char range_begin;
5160
5834
 
5161
5835
  *flagsPointer &= ~FLAGS_EXCLUDE;
5162
5836
 
5163
 
  if (format[index] == QUALIFIER_CIRCUMFLEX)
 
5837
  if (format[offset] == QUALIFIER_CIRCUMFLEX)
5164
5838
    {
5165
5839
      *flagsPointer |= FLAGS_EXCLUDE;
5166
 
      index++;
 
5840
      offset++;
5167
5841
    }
5168
5842
  /*
5169
5843
   * If the ungroup character is at the beginning of the scanlist,
5170
5844
   * it will be part of the class, and a second ungroup character
5171
5845
   * must follow to end the group.
5172
5846
   */
5173
 
  if (format[index] == SPECIFIER_UNGROUP)
 
5847
  if (format[offset] == SPECIFIER_UNGROUP)
5174
5848
    {
5175
5849
      characterclass[(int)SPECIFIER_UNGROUP]++;
5176
 
      index++;
 
5850
      offset++;
5177
5851
    }
5178
5852
  /*
5179
5853
   * Minus is used to specify ranges. To include minus in the class,
5180
5854
   * it must be at the beginning of the list
5181
5855
   */
5182
 
  if (format[index] == QUALIFIER_MINUS)
 
5856
  if (format[offset] == QUALIFIER_MINUS)
5183
5857
    {
5184
5858
      characterclass[(int)QUALIFIER_MINUS]++;
5185
 
      index++;
 
5859
      offset++;
5186
5860
    }
5187
5861
  /* Collect characters */
5188
 
  for (ch = format[index];
 
5862
  for (ch = format[offset];
5189
5863
       (ch != SPECIFIER_UNGROUP) && (ch != NIL);
5190
 
       ch = format[++index])
 
5864
       ch = format[++offset])
5191
5865
    {
5192
5866
      switch (ch)
5193
5867
        {
5206
5880
           * - duplicates (although we can easily convert these
5207
5881
           *   into errors)
5208
5882
           */
5209
 
          range_begin = format[index - 1];
5210
 
          range_end = format[++index];
 
5883
          range_begin = format[offset - 1];
 
5884
          range_end = format[++offset];
5211
5885
          if (range_end == SPECIFIER_UNGROUP)
5212
5886
            {
5213
5887
              /* Trailing minus is included */
5216
5890
              break; /* for */
5217
5891
            }
5218
5892
          if (range_end == NIL)
5219
 
            return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
 
5893
            return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
5220
5894
          if (range_begin > range_end)
5221
 
            return TRIO_ERROR_RETURN(TRIO_ERANGE, index);
 
5895
            return TRIO_ERROR_RETURN(TRIO_ERANGE, offset);
5222
5896
            
5223
5897
          for (i = (int)range_begin; i <= (int)range_end; i++)
5224
5898
            characterclass[i]++;
5230
5904
 
5231
5905
        case SPECIFIER_GROUP:
5232
5906
          
5233
 
          switch (format[index + 1])
 
5907
          switch (format[offset + 1])
5234
5908
            {
5235
5909
            case QUALIFIER_DOT: /* Collating symbol */
5236
5910
              /*
5238
5912
               * characters have been implemented. Until now, we ignore
5239
5913
               * this feature.
5240
5914
               */
5241
 
              for (i = index + 2; ; i++)
 
5915
              for (i = offset + 2; ; i++)
5242
5916
                {
5243
5917
                  if (format[i] == NIL)
5244
5918
                    /* Error in syntax */
5249
5923
              if (format[++i] != SPECIFIER_UNGROUP)
5250
5924
                return -1;
5251
5925
              
5252
 
              index = i;
 
5926
              offset = i;
5253
5927
              break;
5254
5928
          
5255
5929
            case QUALIFIER_EQUAL: /* Equivalence class expressions */
5263
5937
                    TrioGetCollation();
5264
5938
                    internalCollationUnconverted = FALSE;
5265
5939
                  }
5266
 
                for (i = index + 2; ; i++)
 
5940
                for (i = offset + 2; ; i++)
5267
5941
                  {
5268
5942
                    if (format[i] == NIL)
5269
5943
                      /* Error in syntax */
5281
5955
                if (format[++i] != SPECIFIER_UNGROUP)
5282
5956
                  return -1;
5283
5957
                
5284
 
                index = i;
 
5958
                offset = i;
5285
5959
              }
5286
5960
              break;
5287
5961
          
5288
5962
            case QUALIFIER_COLON: /* Character class expressions */
5289
5963
          
5290
5964
              if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
5291
 
                                 &format[index]))
 
5965
                                 &format[offset]))
5292
5966
                {
5293
5967
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5294
5968
                    if (isalnum(i))
5295
5969
                      characterclass[i]++;
5296
 
                  index += sizeof(CLASS_ALNUM) - 1;
 
5970
                  offset += sizeof(CLASS_ALNUM) - 1;
5297
5971
                }
5298
5972
              else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
5299
 
                                      &format[index]))
 
5973
                                      &format[offset]))
5300
5974
                {
5301
5975
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5302
5976
                    if (isalpha(i))
5303
5977
                      characterclass[i]++;
5304
 
                  index += sizeof(CLASS_ALPHA) - 1;
 
5978
                  offset += sizeof(CLASS_ALPHA) - 1;
5305
5979
                }
5306
5980
              else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
5307
 
                                      &format[index]))
 
5981
                                      &format[offset]))
5308
5982
                {
5309
5983
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5310
5984
                    if (iscntrl(i))
5311
5985
                      characterclass[i]++;
5312
 
                  index += sizeof(CLASS_CNTRL) - 1;
 
5986
                  offset += sizeof(CLASS_CNTRL) - 1;
5313
5987
                }
5314
5988
              else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
5315
 
                                      &format[index]))
 
5989
                                      &format[offset]))
5316
5990
                {
5317
5991
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5318
5992
                    if (isdigit(i))
5319
5993
                      characterclass[i]++;
5320
 
                  index += sizeof(CLASS_DIGIT) - 1;
 
5994
                  offset += sizeof(CLASS_DIGIT) - 1;
5321
5995
                }
5322
5996
              else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
5323
 
                                      &format[index]))
 
5997
                                      &format[offset]))
5324
5998
                {
5325
5999
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5326
6000
                    if (isgraph(i))
5327
6001
                      characterclass[i]++;
5328
 
                  index += sizeof(CLASS_GRAPH) - 1;
 
6002
                  offset += sizeof(CLASS_GRAPH) - 1;
5329
6003
                }
5330
6004
              else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
5331
 
                                      &format[index]))
 
6005
                                      &format[offset]))
5332
6006
                {
5333
6007
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5334
6008
                    if (islower(i))
5335
6009
                      characterclass[i]++;
5336
 
                  index += sizeof(CLASS_LOWER) - 1;
 
6010
                  offset += sizeof(CLASS_LOWER) - 1;
5337
6011
                }
5338
6012
              else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
5339
 
                                      &format[index]))
 
6013
                                      &format[offset]))
5340
6014
                {
5341
6015
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5342
6016
                    if (isprint(i))
5343
6017
                      characterclass[i]++;
5344
 
                  index += sizeof(CLASS_PRINT) - 1;
 
6018
                  offset += sizeof(CLASS_PRINT) - 1;
5345
6019
                }
5346
6020
              else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
5347
 
                                      &format[index]))
 
6021
                                      &format[offset]))
5348
6022
                {
5349
6023
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5350
6024
                    if (ispunct(i))
5351
6025
                      characterclass[i]++;
5352
 
                  index += sizeof(CLASS_PUNCT) - 1;
 
6026
                  offset += sizeof(CLASS_PUNCT) - 1;
5353
6027
                }
5354
6028
              else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
5355
 
                                      &format[index]))
 
6029
                                      &format[offset]))
5356
6030
                {
5357
6031
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5358
6032
                    if (isspace(i))
5359
6033
                      characterclass[i]++;
5360
 
                  index += sizeof(CLASS_SPACE) - 1;
 
6034
                  offset += sizeof(CLASS_SPACE) - 1;
5361
6035
                }
5362
6036
              else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
5363
 
                                      &format[index]))
 
6037
                                      &format[offset]))
5364
6038
                {
5365
6039
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5366
6040
                    if (isupper(i))
5367
6041
                      characterclass[i]++;
5368
 
                  index += sizeof(CLASS_UPPER) - 1;
 
6042
                  offset += sizeof(CLASS_UPPER) - 1;
5369
6043
                }
5370
6044
              else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
5371
 
                                      &format[index]))
 
6045
                                      &format[offset]))
5372
6046
                {
5373
6047
                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
5374
6048
                    if (isxdigit(i))
5375
6049
                      characterclass[i]++;
5376
 
                  index += sizeof(CLASS_XDIGIT) - 1;
 
6050
                  offset += sizeof(CLASS_XDIGIT) - 1;
5377
6051
                }
5378
6052
              else
5379
6053
                {
5437
6111
  
5438
6112
  TrioSkipWhitespaces(self);
5439
6113
  
5440
 
  if (!(flags & FLAGS_UNSIGNED))
5441
 
    {
5442
 
      /* Leading sign */
5443
 
      if (self->current == '+')
5444
 
        {
5445
 
          self->InStream(self, NULL);
5446
 
        }
5447
 
      else if (self->current == '-')
5448
 
        {
5449
 
          self->InStream(self, NULL);
5450
 
          isNegative = TRUE;
5451
 
        }
 
6114
  /* Leading sign */
 
6115
  if (self->current == '+')
 
6116
    {
 
6117
      self->InStream(self, NULL);
 
6118
    }
 
6119
  else if (self->current == '-')
 
6120
    {
 
6121
      self->InStream(self, NULL);
 
6122
      isNegative = TRUE;
5452
6123
    }
5453
6124
  
5454
6125
  count = self->processed;
5496
6167
          if ((digit == -1) || (digit >= base))
5497
6168
            break;
5498
6169
        }
 
6170
#if TRIO_FEATURE_QUOTE
5499
6171
      else if (flags & FLAGS_QUOTE)
5500
6172
        {
5501
6173
          /* Compare with thousands separator */
5511
6183
          else
5512
6184
            continue; /* Match */
5513
6185
        }
 
6186
#endif
5514
6187
      else
5515
6188
        break;
5516
6189
            
5526
6199
    return FALSE;
5527
6200
  
5528
6201
  if (target)
5529
 
    *target = (isNegative) ? -((trio_intmax_t)number) : number;
 
6202
    *target = (isNegative) ? (trio_uintmax_t)(-((trio_intmax_t)number)) : number;
5530
6203
  return TRUE;
5531
6204
}
5532
6205
 
5634
6307
/*************************************************************************
5635
6308
 * TrioReadWideChar
5636
6309
 */
5637
 
#if TRIO_WIDECHAR
 
6310
#if TRIO_FEATURE_WIDECHAR
5638
6311
TRIO_PRIVATE int
5639
6312
TrioReadWideChar
5640
6313
TRIO_ARGS4((self, target, flags, width),
5690
6363
    }
5691
6364
  return amount;
5692
6365
}
5693
 
#endif /* TRIO_WIDECHAR */
 
6366
#endif /* TRIO_FEATURE_WIDECHAR */
5694
6367
 
5695
6368
/*************************************************************************
5696
6369
 * TrioReadWideString
5697
6370
 */
5698
 
#if TRIO_WIDECHAR
 
6371
#if TRIO_FEATURE_WIDECHAR
5699
6372
TRIO_PRIVATE BOOLEAN_T
5700
6373
TrioReadWideString
5701
6374
TRIO_ARGS4((self, target, flags, width),
5713
6386
  TrioSkipWhitespaces(self);
5714
6387
 
5715
6388
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
 
6389
  /* Required by TrioReadWideChar */
5716
6390
  (void)mblen(NULL, 0);
5717
6391
#endif
5718
6392
  
5735
6409
    target[i] = WCONST('\0');
5736
6410
  return TRUE;
5737
6411
}
5738
 
#endif /* TRIO_WIDECHAR */
 
6412
#endif /* TRIO_FEATURE_WIDECHAR */
5739
6413
 
5740
6414
/*************************************************************************
5741
6415
 * TrioReadGroup
5742
6416
 *
 
6417
 * Reads non-empty character groups.
 
6418
 *
5743
6419
 * FIXME: characterclass does not work with multibyte characters
5744
6420
 */
5745
6421
TRIO_PRIVATE BOOLEAN_T
5768
6444
        target[i] = (char)ch;
5769
6445
      self->InStream(self, &ch);
5770
6446
    }
5771
 
  
 
6447
 
 
6448
  if (i == 0)
 
6449
    return FALSE;
 
6450
 
 
6451
  /* Terminate the string if input saved */
5772
6452
  if (target)
5773
6453
    target[i] = NIL;
5774
6454
  return TRUE;
5781
6461
 *  add long double
5782
6462
 *  handle base
5783
6463
 */
 
6464
#if TRIO_FEATURE_FLOAT
5784
6465
TRIO_PRIVATE BOOLEAN_T
5785
6466
TrioReadDouble
5786
6467
TRIO_ARGS4((self, target, flags, width),
5791
6472
{
5792
6473
  int ch;
5793
6474
  char doubleString[512];
5794
 
  int index = 0;
 
6475
  int offset = 0;
5795
6476
  int start;
 
6477
# if TRIO_FEATURE_QUOTE
5796
6478
  int j;
 
6479
# endif
5797
6480
  BOOLEAN_T isHex = FALSE;
 
6481
  trio_long_double_t infinity;
5798
6482
 
5799
6483
  doubleString[0] = 0;
5800
6484
  
5811
6495
  ch = self->current;
5812
6496
  if ((ch == '+') || (ch == '-'))
5813
6497
    {
5814
 
      doubleString[index++] = (char)ch;
 
6498
      doubleString[offset++] = (char)ch;
5815
6499
      self->InStream(self, &ch);
5816
6500
      width--;
5817
6501
    }
5818
6502
 
5819
 
  start = index;
 
6503
  start = offset;
5820
6504
  switch (ch)
5821
6505
    {
5822
6506
    case 'n':
5823
6507
    case 'N':
5824
6508
      /* Not-a-number */
5825
 
      if (index != 0)
 
6509
      if (offset != 0)
5826
6510
        break;
5827
6511
      /* FALLTHROUGH */
5828
6512
    case 'i':
5829
6513
    case 'I':
5830
6514
      /* Infinity */
5831
 
      while (isalpha(ch) && (index - start < width))
 
6515
      while (isalpha(ch) && (offset - start < width))
5832
6516
        {
5833
 
          doubleString[index++] = (char)ch;
 
6517
          doubleString[offset++] = (char)ch;
5834
6518
          self->InStream(self, &ch);
5835
6519
        }
5836
 
      doubleString[index] = NIL;
 
6520
      doubleString[offset] = NIL;
5837
6521
 
5838
6522
      /* Case insensitive string comparison */
5839
6523
      if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
5840
6524
          trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
5841
6525
        {
 
6526
          infinity = ((start == 1) && (doubleString[0] == '-'))
 
6527
            ? trio_ninf()
 
6528
            : trio_pinf();
5842
6529
          if (flags & FLAGS_LONGDOUBLE)
5843
6530
            {
5844
 
              if ((start == 1) && (doubleString[0] == '-'))
5845
 
                {
5846
 
                  *((trio_long_double_t *)target) = trio_ninf();
5847
 
                }
5848
 
              else
5849
 
                {
5850
 
                  *((trio_long_double_t *)target) = trio_pinf();
5851
 
                }
 
6531
              *((trio_long_double_t *)target) = infinity;
 
6532
            }
 
6533
          else if (flags & FLAGS_LONG)
 
6534
            {
 
6535
              *((double *)target) = infinity;
5852
6536
            }
5853
6537
          else
5854
6538
            {
5855
 
              if ((start == 1) && (doubleString[0] == '-'))
5856
 
                {
5857
 
                  *((double *)target) = trio_ninf();
5858
 
                }
5859
 
              else
5860
 
                {
5861
 
                  *((double *)target) = trio_pinf();
5862
 
                }
 
6539
              *((float *)target) = infinity;
5863
6540
            }
5864
6541
          return TRUE;
5865
6542
        }
5870
6547
            {
5871
6548
              *((trio_long_double_t *)target) = trio_nan();
5872
6549
            }
5873
 
          else
 
6550
          else if (flags & FLAGS_LONG)
5874
6551
            {
5875
6552
              *((double *)target) = trio_nan();
5876
6553
            }
 
6554
          else
 
6555
            {
 
6556
              *((float *)target) = trio_nan();
 
6557
            }
5877
6558
          return TRUE;
5878
6559
        }
5879
6560
      return FALSE;
5880
6561
 
5881
6562
    case '0':
5882
 
      doubleString[index++] = (char)ch;
 
6563
      doubleString[offset++] = (char)ch;
5883
6564
      self->InStream(self, &ch);
5884
6565
      if (trio_to_upper(ch) == 'X')
5885
6566
        {
5886
6567
          isHex = TRUE;
5887
 
          doubleString[index++] = (char)ch;
 
6568
          doubleString[offset++] = (char)ch;
5888
6569
          self->InStream(self, &ch);
5889
6570
        }
5890
6571
      break;
5893
6574
      break;
5894
6575
    }
5895
6576
  
5896
 
  while ((ch != EOF) && (index - start < width))
 
6577
  while ((ch != EOF) && (offset - start < width))
5897
6578
    {
5898
6579
      /* Integer part */
5899
6580
      if (isHex ? isxdigit(ch) : isdigit(ch))
5900
6581
        {
5901
 
          doubleString[index++] = (char)ch;
 
6582
          doubleString[offset++] = (char)ch;
5902
6583
          self->InStream(self, &ch);
5903
6584
        }
 
6585
# if TRIO_FEATURE_QUOTE
5904
6586
      else if (flags & FLAGS_QUOTE)
5905
6587
        {
5906
6588
          /* Compare with thousands separator */
5916
6598
          else
5917
6599
            continue; /* Match */
5918
6600
        }
 
6601
# endif
5919
6602
      else
5920
6603
        break; /* while */
5921
6604
    }
5922
6605
  if (ch == '.')
5923
6606
    {
5924
6607
      /* Decimal part */
5925
 
      doubleString[index++] = (char)ch;
 
6608
      doubleString[offset++] = (char)ch;
5926
6609
      self->InStream(self, &ch);
5927
6610
      while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
5928
 
             (index - start < width))
5929
 
        {
5930
 
          doubleString[index++] = (char)ch;
5931
 
          self->InStream(self, &ch);
5932
 
        }
5933
 
      if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
5934
 
        {
5935
 
          /* Exponent */
5936
 
          doubleString[index++] = (char)ch;
5937
 
          self->InStream(self, &ch);
5938
 
          if ((ch == '+') || (ch == '-'))
5939
 
            {
5940
 
              doubleString[index++] = (char)ch;
5941
 
              self->InStream(self, &ch);
5942
 
            }
5943
 
          while (isdigit(ch) && (index - start < width))
5944
 
            {
5945
 
              doubleString[index++] = (char)ch;
5946
 
              self->InStream(self, &ch);
5947
 
            }
 
6611
             (offset - start < width))
 
6612
        {
 
6613
          doubleString[offset++] = (char)ch;
 
6614
          self->InStream(self, &ch);
 
6615
        }
 
6616
    }
 
6617
  if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
 
6618
    {
 
6619
      /* Exponent */
 
6620
      doubleString[offset++] = (char)ch;
 
6621
      self->InStream(self, &ch);
 
6622
      if ((ch == '+') || (ch == '-'))
 
6623
        {
 
6624
          doubleString[offset++] = (char)ch;
 
6625
          self->InStream(self, &ch);
 
6626
        }
 
6627
      while (isdigit(ch) && (offset - start < width))
 
6628
        {
 
6629
          doubleString[offset++] = (char)ch;
 
6630
          self->InStream(self, &ch);
5948
6631
        }
5949
6632
    }
5950
6633
 
5951
 
  if ((index == start) || (*doubleString == NIL))
 
6634
  if ((offset == start) || (*doubleString == NIL))
5952
6635
    return FALSE;
5953
6636
 
5954
 
  doubleString[index] = 0;
 
6637
  doubleString[offset] = 0;
5955
6638
  
5956
6639
  if (flags & FLAGS_LONGDOUBLE)
5957
6640
    {
5958
6641
      *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
5959
6642
    }
5960
 
  else
 
6643
  else if (flags & FLAGS_LONG)
5961
6644
    {
5962
6645
      *((double *)target) = trio_to_double(doubleString, NULL);
5963
6646
    }
 
6647
  else
 
6648
    {
 
6649
      *((float *)target) = trio_to_float(doubleString, NULL);
 
6650
    }
5964
6651
  return TRUE;
5965
6652
}
 
6653
#endif /* TRIO_FEATURE_FLOAT */
5966
6654
 
5967
6655
/*************************************************************************
5968
6656
 * TrioReadPointer
5985
6673
                     POINTER_WIDTH,
5986
6674
                     BASE_HEX))
5987
6675
    {
5988
 
      /*
5989
 
       * The strange assignment of number is a workaround for a compiler
5990
 
       * warning
5991
 
       */
5992
6676
      if (target)
5993
 
        *target = (char *)0 + number;
 
6677
        {
 
6678
#if defined(TRIO_COMPILER_GCC) || defined(TRIO_COMPILER_MIPSPRO)
 
6679
          /*
 
6680
           * The strange assignment of number is a workaround for a compiler
 
6681
           * warning
 
6682
           */
 
6683
          *target = &((char *)0)[number];
 
6684
#else
 
6685
          *target = (trio_pointer_t)number;
 
6686
#endif
 
6687
        }
5994
6688
      return TRUE;
5995
6689
    }
5996
6690
  else if (TrioReadString(self,
5999
6693
                          : buffer,
6000
6694
                          0,
6001
6695
                          sizeof(internalNullString) - 1))
6002
 
    {  
 
6696
    {
6003
6697
      if (trio_equal_case(buffer, internalNullString))
6004
6698
        {
6005
6699
          if (target)
6020
6714
           TRIO_CONST char *format,
6021
6715
           trio_parameter_t *parameters)
6022
6716
{
6023
 
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
6024
 
  int charlen;
6025
 
  int cnt;
6026
 
#endif
 
6717
  int status;
6027
6718
  int assignment;
6028
6719
  int ch;
6029
 
  int index; /* Index of format string */
6030
 
  int i; /* Index of current parameter */
 
6720
  int offset; /* Offset of format string */
 
6721
  int i; /* Offset of current parameter */
6031
6722
  trio_flags_t flags;
6032
6723
  int width;
6033
6724
  int base;
6034
6725
  trio_pointer_t pointer;
6035
6726
 
 
6727
  /* Return on empty format string */
 
6728
  if (format[0] == NIL)
 
6729
    return 0;
 
6730
 
 
6731
  status = 0;
6036
6732
  assignment = 0;
6037
6733
  i = 0;
6038
 
  index = 0;
 
6734
  offset = 0;
6039
6735
  data->InStream(data, &ch);
6040
6736
 
6041
 
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
6042
 
  (void)mblen(NULL, 0);
6043
 
#endif
6044
 
 
6045
 
  while (format[index])
 
6737
  for (;;)
6046
6738
    {
6047
 
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
6048
 
      if (! isascii(format[index]))
6049
 
        {
6050
 
          charlen = mblen(&format[index], MB_LEN_MAX);
6051
 
          if (charlen != -1)
6052
 
            {
6053
 
              /* Compare multibyte characters in format string */
6054
 
              for (cnt = 0; cnt < charlen - 1; cnt++)
6055
 
                {
6056
 
                  if (ch != format[index + cnt])
6057
 
                    {
6058
 
                      return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
6059
 
                    }
6060
 
                  data->InStream(data, &ch);
6061
 
                }
6062
 
              continue; /* while characters left in formatting string */
6063
 
            }
6064
 
        }
6065
 
#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
6066
 
      
6067
 
      if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
6068
 
        {
6069
 
          return (assignment > 0) ? assignment : EOF;
6070
 
        }
6071
 
      
6072
 
      if (CHAR_IDENTIFIER == format[index])
6073
 
        {
6074
 
          if (CHAR_IDENTIFIER == format[index + 1])
 
6739
      /* Skip the parameter entries */
 
6740
      while (parameters[i].type == FORMAT_PARAMETER)
 
6741
        {
 
6742
          assert(i <= MAX_PARAMETERS);
 
6743
          i++;
 
6744
        }
 
6745
 
 
6746
      /* Compare non conversion-specifier part of format string */
 
6747
      while (offset < parameters[i].beginOffset)
 
6748
        {
 
6749
          if ((CHAR_IDENTIFIER == format[offset]) &&
 
6750
              (CHAR_IDENTIFIER == format[offset + 1]))
6075
6751
            {
6076
6752
              /* Two % in format matches one % in input stream */
6077
6753
              if (CHAR_IDENTIFIER == ch)
6078
6754
                {
6079
6755
                  data->InStream(data, &ch);
6080
 
                  index += 2;
 
6756
                  offset += 2;
6081
6757
                  continue; /* while format chars left */
6082
6758
                }
6083
6759
              else
6084
 
                return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
6085
 
            }
6086
 
 
6087
 
          /* Skip the parameter entries */
6088
 
          while (parameters[i].type == FORMAT_PARAMETER)
6089
 
            i++;
6090
 
          
6091
 
          flags = parameters[i].flags;
6092
 
          /* Find width */
6093
 
          width = parameters[i].width;
6094
 
          if (flags & FLAGS_WIDTH_PARAMETER)
6095
 
            {
6096
 
              /* Get width from parameter list */
6097
 
              width = (int)parameters[width].data.number.as_signed;
6098
 
            }
6099
 
          /* Find base */
6100
 
          base = parameters[i].base;
6101
 
          if (flags & FLAGS_BASE_PARAMETER)
6102
 
            {
6103
 
              /* Get base from parameter list */
6104
 
              base = (int)parameters[base].data.number.as_signed;
6105
 
            }
6106
 
          
6107
 
          switch (parameters[i].type)
6108
 
            {
6109
 
            case FORMAT_INT:
6110
 
              {
6111
 
                trio_uintmax_t number;
6112
 
 
6113
 
                if (0 == base)
6114
 
                  base = BASE_DECIMAL;
6115
 
 
6116
 
                if (!TrioReadNumber(data,
6117
 
                                    &number,
6118
 
                                    flags,
6119
 
                                    width,
6120
 
                                    base))
6121
 
                  return assignment;
6122
 
 
6123
 
                if (!(flags & FLAGS_IGNORE))
6124
 
                  {
6125
 
                    assignment++;
6126
 
 
6127
 
                    pointer = parameters[i].data.pointer;
6128
 
#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
6129
 
                    if (flags & FLAGS_SIZE_T)
6130
 
                      *(size_t *)pointer = (size_t)number;
6131
 
                    else
6132
 
#endif
6133
 
#if defined(QUALIFIER_PTRDIFF_T)
6134
 
                    if (flags & FLAGS_PTRDIFF_T)
6135
 
                      *(ptrdiff_t *)pointer = (ptrdiff_t)number;
6136
 
                    else
6137
 
#endif
6138
 
#if defined(QUALIFIER_INTMAX_T)
6139
 
                    if (flags & FLAGS_INTMAX_T)
6140
 
                      *(trio_intmax_t *)pointer = (trio_intmax_t)number;
6141
 
                    else
6142
 
#endif
6143
 
                    if (flags & FLAGS_QUAD)
6144
 
                      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
6145
 
                    else if (flags & FLAGS_LONG)
6146
 
                      *(long int *)pointer = (long int)number;
6147
 
                    else if (flags & FLAGS_SHORT)
6148
 
                      *(short int *)pointer = (short int)number;
6149
 
                    else
6150
 
                      *(int *)pointer = (int)number;
6151
 
                  }
6152
 
              }
6153
 
              break; /* FORMAT_INT */
6154
 
              
6155
 
            case FORMAT_STRING:
6156
 
#if TRIO_WIDECHAR
6157
 
              if (flags & FLAGS_WIDECHAR)
6158
 
                {
6159
 
                  if (!TrioReadWideString(data,
6160
 
                                          (flags & FLAGS_IGNORE)
6161
 
                                          ? NULL
6162
 
                                          : parameters[i].data.wstring,
6163
 
                                          flags,
6164
 
                                          width))
6165
 
                    return assignment;
 
6760
                {
 
6761
                  status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
6762
                  goto end;
 
6763
                }
 
6764
            }
 
6765
          else /* Not an % identifier */
 
6766
            {
 
6767
              if (isspace((int)format[offset]))
 
6768
                {
 
6769
                  /* Whitespaces may match any amount of whitespaces */
 
6770
                  ch = TrioSkipWhitespaces(data);
 
6771
                }
 
6772
              else if (ch == format[offset])
 
6773
                {
 
6774
                  data->InStream(data, &ch);
6166
6775
                }
6167
6776
              else
6168
 
#endif
6169
6777
                {
6170
 
                  if (!TrioReadString(data,
 
6778
                  status = assignment;
 
6779
                  goto end;
 
6780
                }
 
6781
 
 
6782
              offset++;
 
6783
            }
 
6784
        }
 
6785
 
 
6786
      if (parameters[i].type == FORMAT_SENTINEL)
 
6787
        break;
 
6788
 
 
6789
      if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
 
6790
        {
 
6791
          status = (assignment > 0) ? assignment : EOF;
 
6792
          goto end;
 
6793
        }
 
6794
 
 
6795
      flags = parameters[i].flags;
 
6796
 
 
6797
      /* Find width */
 
6798
      width = parameters[i].width;
 
6799
      if (flags & FLAGS_WIDTH_PARAMETER)
 
6800
        {
 
6801
          /* Get width from parameter list */
 
6802
          width = (int)parameters[width].data.number.as_signed;
 
6803
        }
 
6804
 
 
6805
      /* Find base */
 
6806
      if (NO_BASE != parameters[i].baseSpecifier)
 
6807
        {
 
6808
          /* Base from specifier has priority */
 
6809
          base = parameters[i].baseSpecifier;
 
6810
        }
 
6811
      else if (flags & FLAGS_BASE_PARAMETER)
 
6812
        {
 
6813
          /* Get base from parameter list */
 
6814
          base = parameters[i].base;
 
6815
          base = (int)parameters[base].data.number.as_signed;
 
6816
        }
 
6817
      else
 
6818
        {
 
6819
          /* Use base from format string */
 
6820
          base = parameters[i].base;
 
6821
        }
 
6822
 
 
6823
      switch (parameters[i].type)
 
6824
        {
 
6825
        case FORMAT_INT:
 
6826
          {
 
6827
            trio_uintmax_t number;
 
6828
 
 
6829
            if (0 == base)
 
6830
              base = BASE_DECIMAL;
 
6831
 
 
6832
            if (!TrioReadNumber(data,
 
6833
                                &number,
 
6834
                                flags,
 
6835
                                width,
 
6836
                                base))
 
6837
              {
 
6838
                status = assignment;
 
6839
                goto end;
 
6840
              }
 
6841
 
 
6842
            if (!(flags & FLAGS_IGNORE))
 
6843
              {
 
6844
                assignment++;
 
6845
 
 
6846
                pointer = parameters[i].data.pointer;
 
6847
#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
 
6848
                if (flags & FLAGS_SIZE_T)
 
6849
                  *(size_t *)pointer = (size_t)number;
 
6850
                else
 
6851
#endif
 
6852
#if TRIO_FEATURE_PTRDIFF_T
 
6853
                if (flags & FLAGS_PTRDIFF_T)
 
6854
                  *(ptrdiff_t *)pointer = (ptrdiff_t)number;
 
6855
                else
 
6856
#endif
 
6857
#if TRIO_FEATURE_INTMAX_T
 
6858
                if (flags & FLAGS_INTMAX_T)
 
6859
                  *(trio_intmax_t *)pointer = (trio_intmax_t)number;
 
6860
                else
 
6861
#endif
 
6862
                if (flags & FLAGS_QUAD)
 
6863
                  *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
 
6864
                else if (flags & FLAGS_LONG)
 
6865
                  *(long int *)pointer = (long int)number;
 
6866
                else if (flags & FLAGS_SHORT)
 
6867
                  *(short int *)pointer = (short int)number;
 
6868
                else
 
6869
                  *(int *)pointer = (int)number;
 
6870
              }
 
6871
          }
 
6872
          break; /* FORMAT_INT */
 
6873
 
 
6874
        case FORMAT_STRING:
 
6875
#if TRIO_FEATURE_WIDECHAR
 
6876
          if (flags & FLAGS_WIDECHAR)
 
6877
            {
 
6878
              if (!TrioReadWideString(data,
6171
6879
                                      (flags & FLAGS_IGNORE)
6172
6880
                                      ? NULL
6173
 
                                      : parameters[i].data.string,
 
6881
                                      : parameters[i].data.wstring,
6174
6882
                                      flags,
6175
6883
                                      width))
6176
 
                    return assignment;
6177
 
                }
6178
 
              if (!(flags & FLAGS_IGNORE))
 
6884
                {
 
6885
                  status = assignment;
 
6886
                  goto end;
 
6887
                }
 
6888
            }
 
6889
          else
 
6890
#endif
 
6891
            {
 
6892
              if (!TrioReadString(data,
 
6893
                                  (flags & FLAGS_IGNORE)
 
6894
                                  ? NULL
 
6895
                                  : parameters[i].data.string,
 
6896
                                  flags,
 
6897
                                  width))
 
6898
                {
 
6899
                  status = assignment;
 
6900
                  goto end;
 
6901
                }
 
6902
            }
 
6903
          if (!(flags & FLAGS_IGNORE))
 
6904
            assignment++;
 
6905
          break; /* FORMAT_STRING */
 
6906
 
 
6907
#if TRIO_FEATURE_FLOAT
 
6908
        case FORMAT_DOUBLE:
 
6909
          {
 
6910
            if (flags & FLAGS_IGNORE)
 
6911
              {
 
6912
                pointer = NULL;
 
6913
              }
 
6914
            else
 
6915
              {
 
6916
                pointer = (flags & FLAGS_LONGDOUBLE)
 
6917
                  ? (trio_pointer_t)parameters[i].data.longdoublePointer
 
6918
                  : (trio_pointer_t)parameters[i].data.doublePointer;
 
6919
              }
 
6920
            if (!TrioReadDouble(data, pointer, flags, width))
 
6921
              {
 
6922
                status = assignment;
 
6923
                goto end;
 
6924
              }
 
6925
            if (!(flags & FLAGS_IGNORE))
 
6926
              {
6179
6927
                assignment++;
6180
 
              break; /* FORMAT_STRING */
6181
 
 
6182
 
            case FORMAT_DOUBLE:
6183
 
              {
6184
 
                trio_pointer_t pointer;
6185
 
 
6186
 
                if (flags & FLAGS_IGNORE)
6187
 
                  {
6188
 
                    pointer = NULL;
6189
 
                  }
6190
 
                else
6191
 
                  {
6192
 
                    pointer = (flags & FLAGS_LONGDOUBLE)
6193
 
                      ? (trio_pointer_t)parameters[i].data.longdoublePointer
6194
 
                      : (trio_pointer_t)parameters[i].data.doublePointer;
6195
 
                  }
6196
 
                if (!TrioReadDouble(data, pointer, flags, width))
6197
 
                  {
6198
 
                    return assignment;
6199
 
                  }
6200
 
                if (!(flags & FLAGS_IGNORE))
6201
 
                  {
6202
 
                    assignment++;
6203
 
                  }
6204
 
                break; /* FORMAT_DOUBLE */
6205
 
              }
6206
 
            case FORMAT_GROUP:
6207
 
              {
6208
 
                int characterclass[MAX_CHARACTER_CLASS + 1];
6209
 
                int rc;
6210
 
 
6211
 
                /* Skip over modifiers */
6212
 
                while (format[index] != SPECIFIER_GROUP)
6213
 
                  {
6214
 
                    index++;
6215
 
                  }
6216
 
                /* Skip over group specifier */
6217
 
                index++;
6218
 
                
6219
 
                memset(characterclass, 0, sizeof(characterclass));
6220
 
                rc = TrioGetCharacterClass(format,
6221
 
                                           &index,
 
6928
              }
 
6929
            break; /* FORMAT_DOUBLE */
 
6930
          }
 
6931
#endif
 
6932
 
 
6933
        case FORMAT_GROUP:
 
6934
          {
 
6935
            int characterclass[MAX_CHARACTER_CLASS + 1];
 
6936
 
 
6937
            /* Skip over modifiers */
 
6938
            while (format[offset] != SPECIFIER_GROUP)
 
6939
              {
 
6940
                offset++;
 
6941
              }
 
6942
            /* Skip over group specifier */
 
6943
            offset++;
 
6944
 
 
6945
            memset(characterclass, 0, sizeof(characterclass));
 
6946
            status = TrioGetCharacterClass(format,
 
6947
                                           &offset,
6222
6948
                                           &flags,
6223
6949
                                           characterclass);
6224
 
                if (rc < 0)
6225
 
                  return rc;
 
6950
            if (status < 0)
 
6951
              goto end;
6226
6952
 
6227
 
                if (!TrioReadGroup(data,
6228
 
                                   (flags & FLAGS_IGNORE)
6229
 
                                   ? NULL
6230
 
                                   : parameters[i].data.string,
6231
 
                                   characterclass,
6232
 
                                   flags,
6233
 
                                   parameters[i].width))
6234
 
                  return assignment;
6235
 
                if (!(flags & FLAGS_IGNORE))
6236
 
                  assignment++;
 
6953
            if (!TrioReadGroup(data,
 
6954
                               (flags & FLAGS_IGNORE)
 
6955
                               ? NULL
 
6956
                               : parameters[i].data.string,
 
6957
                               characterclass,
 
6958
                               flags,
 
6959
                               parameters[i].width))
 
6960
              {
 
6961
                status = assignment;
 
6962
                goto end;
6237
6963
              }
6238
 
              break; /* FORMAT_GROUP */
6239
 
 
6240
 
            case FORMAT_COUNT:
6241
 
              pointer = parameters[i].data.pointer;
6242
 
              if (NULL != pointer)
6243
 
                {
6244
 
                  int count = data->committed;
6245
 
                  if (ch != EOF)
6246
 
                    count--; /* a character is read, but is not consumed yet */
6247
 
#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
6248
 
                  if (flags & FLAGS_SIZE_T)
6249
 
                    *(size_t *)pointer = (size_t)count;
6250
 
                  else
6251
 
#endif
6252
 
#if defined(QUALIFIER_PTRDIFF_T)
6253
 
                  if (flags & FLAGS_PTRDIFF_T)
6254
 
                    *(ptrdiff_t *)pointer = (ptrdiff_t)count;
6255
 
                  else
6256
 
#endif
6257
 
#if defined(QUALIFIER_INTMAX_T)
6258
 
                  if (flags & FLAGS_INTMAX_T)
6259
 
                    *(trio_intmax_t *)pointer = (trio_intmax_t)count;
6260
 
                  else
6261
 
#endif
6262
 
                  if (flags & FLAGS_QUAD)
6263
 
                    {
6264
 
                      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
6265
 
                    }
6266
 
                  else if (flags & FLAGS_LONG)
6267
 
                    {
6268
 
                      *(long int *)pointer = (long int)count;
6269
 
                    }
6270
 
                  else if (flags & FLAGS_SHORT)
6271
 
                    {
6272
 
                      *(short int *)pointer = (short int)count;
6273
 
                    }
6274
 
                  else
6275
 
                    {
6276
 
                      *(int *)pointer = (int)count;
6277
 
                    }
6278
 
                }
6279
 
              break; /* FORMAT_COUNT */
6280
 
              
6281
 
            case FORMAT_CHAR:
6282
 
#if TRIO_WIDECHAR
6283
 
              if (flags & FLAGS_WIDECHAR)
6284
 
                {
6285
 
                  if (TrioReadWideChar(data,
6286
 
                                       (flags & FLAGS_IGNORE)
6287
 
                                       ? NULL
6288
 
                                       : parameters[i].data.wstring,
6289
 
                                       flags,
6290
 
                                       (width == NO_WIDTH) ? 1 : width) == 0)
6291
 
                    return assignment;
6292
 
                }
6293
 
              else
6294
 
#endif
6295
 
                {
6296
 
                  if (TrioReadChar(data,
 
6964
            if (!(flags & FLAGS_IGNORE))
 
6965
              assignment++;
 
6966
          }
 
6967
          break; /* FORMAT_GROUP */
 
6968
 
 
6969
        case FORMAT_COUNT:
 
6970
          pointer = parameters[i].data.pointer;
 
6971
          if (NULL != pointer)
 
6972
            {
 
6973
              int count = data->processed;
 
6974
              if (ch != EOF)
 
6975
                count--; /* a character is read, but is not consumed yet */
 
6976
#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
 
6977
              if (flags & FLAGS_SIZE_T)
 
6978
                *(size_t *)pointer = (size_t)count;
 
6979
              else
 
6980
#endif
 
6981
#if TRIO_FEATURE_PTRDIFF_T
 
6982
              if (flags & FLAGS_PTRDIFF_T)
 
6983
                *(ptrdiff_t *)pointer = (ptrdiff_t)count;
 
6984
              else
 
6985
#endif
 
6986
#if TRIO_FEATURE_INTMAX_T
 
6987
              if (flags & FLAGS_INTMAX_T)
 
6988
                *(trio_intmax_t *)pointer = (trio_intmax_t)count;
 
6989
              else
 
6990
#endif
 
6991
              if (flags & FLAGS_QUAD)
 
6992
                {
 
6993
                  *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
 
6994
                }
 
6995
              else if (flags & FLAGS_LONG)
 
6996
                {
 
6997
                  *(long int *)pointer = (long int)count;
 
6998
                }
 
6999
              else if (flags & FLAGS_SHORT)
 
7000
                {
 
7001
                  *(short int *)pointer = (short int)count;
 
7002
                }
 
7003
              else
 
7004
                {
 
7005
                  *(int *)pointer = (int)count;
 
7006
                }
 
7007
            }
 
7008
          break; /* FORMAT_COUNT */
 
7009
 
 
7010
        case FORMAT_CHAR:
 
7011
#if TRIO_FEATURE_WIDECHAR
 
7012
          if (flags & FLAGS_WIDECHAR)
 
7013
            {
 
7014
              if (TrioReadWideChar(data,
6297
7015
                                   (flags & FLAGS_IGNORE)
6298
7016
                                   ? NULL
6299
 
                                   : parameters[i].data.string,
 
7017
                                   : parameters[i].data.wstring,
6300
7018
                                   flags,
6301
7019
                                   (width == NO_WIDTH) ? 1 : width) == 0)
6302
 
                    return assignment;
 
7020
                {
 
7021
                  status = assignment;
 
7022
                  goto end;
6303
7023
                }
6304
 
              if (!(flags & FLAGS_IGNORE))
6305
 
                assignment++;
6306
 
              break; /* FORMAT_CHAR */
6307
 
 
6308
 
            case FORMAT_POINTER:
6309
 
              if (!TrioReadPointer(data,
6310
 
                                   (flags & FLAGS_IGNORE)
6311
 
                                   ? NULL
6312
 
                                   : (trio_pointer_t *)parameters[i].data.pointer,
6313
 
                                   flags))
6314
 
                return assignment;
6315
 
              if (!(flags & FLAGS_IGNORE))
6316
 
                assignment++;
6317
 
              break; /* FORMAT_POINTER */
6318
 
 
6319
 
            case FORMAT_PARAMETER:
6320
 
              break; /* FORMAT_PARAMETER */
6321
 
 
6322
 
            default:
6323
 
              return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
6324
 
            }
6325
 
          ch = data->current;
6326
 
          index = parameters[i].indexAfterSpecifier;
6327
 
          i++;
6328
 
        }
6329
 
      else /* Not an % identifier */
6330
 
        {
6331
 
          if (isspace((int)format[index]))
6332
 
            {
6333
 
              /* Whitespaces may match any amount of whitespaces */
6334
 
              ch = TrioSkipWhitespaces(data);
6335
 
            }
6336
 
          else if (ch == format[index])
6337
 
            {
6338
 
              data->InStream(data, &ch);
6339
7024
            }
6340
7025
          else
6341
 
            return assignment;
6342
 
          
6343
 
          index++;
 
7026
#endif
 
7027
            {
 
7028
              if (TrioReadChar(data,
 
7029
                               (flags & FLAGS_IGNORE)
 
7030
                               ? NULL
 
7031
                               : parameters[i].data.string,
 
7032
                               flags,
 
7033
                               (width == NO_WIDTH) ? 1 : width) == 0)
 
7034
                {
 
7035
                  status = assignment;
 
7036
                  goto end;
 
7037
                }
 
7038
            }
 
7039
          if (!(flags & FLAGS_IGNORE))
 
7040
            assignment++;
 
7041
          break; /* FORMAT_CHAR */
 
7042
 
 
7043
        case FORMAT_POINTER:
 
7044
          if (!TrioReadPointer(data,
 
7045
                               (flags & FLAGS_IGNORE)
 
7046
                               ? NULL
 
7047
                               : (trio_pointer_t *)parameters[i].data.pointer,
 
7048
                               flags))
 
7049
            {
 
7050
              status = assignment;
 
7051
              goto end;
 
7052
            }
 
7053
          if (!(flags & FLAGS_IGNORE))
 
7054
            assignment++;
 
7055
          break; /* FORMAT_POINTER */
 
7056
 
 
7057
        case FORMAT_PARAMETER:
 
7058
          break; /* FORMAT_PARAMETER */
 
7059
 
 
7060
        default:
 
7061
          status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
 
7062
          goto end;
6344
7063
        }
 
7064
 
 
7065
      ch = data->current;
 
7066
      offset = parameters[i].endOffset;
 
7067
      i++;
6345
7068
    }
6346
 
  return assignment;
 
7069
 
 
7070
  status = assignment;
 
7071
 end:
 
7072
  if (data->UndoStream)
 
7073
    data->UndoStream(data);
 
7074
  return status;
6347
7075
}
6348
7076
 
6349
7077
/*************************************************************************
6351
7079
 */
6352
7080
TRIO_PRIVATE int
6353
7081
TrioScan
6354
 
TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
 
7082
TRIO_ARGS7((source, sourceSize, InStream, UndoStream, format, arglist, argarray),
6355
7083
           trio_pointer_t source,
6356
7084
           size_t sourceSize,
6357
7085
           void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
 
7086
           void (*UndoStream) TRIO_PROTO((trio_class_t *)),
6358
7087
           TRIO_CONST char *format,
6359
 
           va_list *arglist,
 
7088
           va_list arglist,
6360
7089
           trio_pointer_t *argarray)
6361
7090
{
6362
7091
  int status;
6368
7097
 
6369
7098
  memset(&data, 0, sizeof(data));
6370
7099
  data.InStream = InStream;
 
7100
  data.UndoStream = UndoStream;
6371
7101
  data.location = (trio_pointer_t)source;
6372
7102
  data.max = sourceSize;
6373
7103
  data.error = 0;
6378
7108
      TrioSetLocale();
6379
7109
    }
6380
7110
#endif
6381
 
  
 
7111
 
6382
7112
  status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
6383
7113
  if (status < 0)
6384
7114
    return status;
6394
7124
/*************************************************************************
6395
7125
 * TrioInStreamFile
6396
7126
 */
 
7127
#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
6397
7128
TRIO_PRIVATE void
6398
7129
TrioInStreamFile
6399
7130
TRIO_ARGS2((self, intPointer),
6405
7136
  assert(VALID(self));
6406
7137
  assert(VALID(file));
6407
7138
 
6408
 
  self->current = fgetc(file);
 
7139
  self->actually.cached = 0;
 
7140
 
 
7141
  /* The initial value of self->current is zero */
6409
7142
  if (self->current == EOF)
6410
7143
    {
6411
7144
      self->error = (ferror(file))
6415
7148
  else
6416
7149
    {
6417
7150
      self->processed++;
6418
 
      self->committed++;
 
7151
      self->actually.cached++;
6419
7152
    }
6420
 
  
 
7153
 
 
7154
  self->current = fgetc(file);
 
7155
 
6421
7156
  if (VALID(intPointer))
6422
7157
    {
6423
7158
      *intPointer = self->current;
6424
7159
    }
6425
7160
}
 
7161
#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
 
7162
 
 
7163
/*************************************************************************
 
7164
 * TrioUndoStreamFile
 
7165
 */
 
7166
#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
 
7167
TRIO_PRIVATE void
 
7168
TrioUndoStreamFile
 
7169
TRIO_ARGS1((self),
 
7170
           trio_class_t *self)
 
7171
{
 
7172
  FILE *file = (FILE *)self->location;
 
7173
 
 
7174
  assert(VALID(self));
 
7175
  assert(VALID(file));
 
7176
 
 
7177
  if (self->actually.cached > 0)
 
7178
    {
 
7179
      assert(self->actually.cached == 1);
 
7180
 
 
7181
      self->current = ungetc(self->current, file);
 
7182
      self->actually.cached = 0;
 
7183
    }
 
7184
}
 
7185
#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
6426
7186
 
6427
7187
/*************************************************************************
6428
7188
 * TrioInStreamFileDescriptor
6429
7189
 */
 
7190
#if TRIO_FEATURE_FD
6430
7191
TRIO_PRIVATE void
6431
7192
TrioInStreamFileDescriptor
6432
7193
TRIO_ARGS2((self, intPointer),
6439
7200
 
6440
7201
  assert(VALID(self));
6441
7202
 
 
7203
  self->actually.cached = 0;
 
7204
 
6442
7205
  size = read(fd, &input, sizeof(char));
6443
7206
  if (size == -1)
6444
7207
    {
6451
7214
    }
6452
7215
  if (self->current != EOF)
6453
7216
    {
6454
 
      self->committed++;
 
7217
      self->actually.cached++;
6455
7218
      self->processed++;
6456
7219
    }
6457
 
  
 
7220
 
6458
7221
  if (VALID(intPointer))
6459
7222
    {
6460
7223
      *intPointer = self->current;
6461
7224
    }
6462
7225
}
 
7226
#endif /* TRIO_FEATURE_FD */
6463
7227
 
6464
7228
/*************************************************************************
6465
7229
 * TrioInStreamCustom
6466
7230
 */
 
7231
#if TRIO_FEATURE_CLOSURE
6467
7232
TRIO_PRIVATE void
6468
7233
TrioInStreamCustom
6469
7234
TRIO_ARGS2((self, intPointer),
6471
7236
           int *intPointer)
6472
7237
{
6473
7238
  trio_custom_t *data;
6474
 
  
 
7239
 
6475
7240
  assert(VALID(self));
6476
7241
  assert(VALID(self->location));
6477
7242
 
 
7243
  self->actually.cached = 0;
 
7244
 
6478
7245
  data = (trio_custom_t *)self->location;
6479
7246
 
6480
7247
  self->current = (data->stream.in == NULL)
6481
7248
    ? NIL
6482
7249
    : (data->stream.in)(data->closure);
6483
 
  
 
7250
 
6484
7251
  if (self->current == NIL)
6485
7252
    {
6486
7253
      self->current = EOF;
6488
7255
  else
6489
7256
    {
6490
7257
      self->processed++;
6491
 
      self->committed++;
 
7258
      self->actually.cached++;
6492
7259
    }
6493
 
  
 
7260
 
6494
7261
  if (VALID(intPointer))
6495
7262
    {
6496
7263
      *intPointer = self->current;
6497
7264
    }
6498
7265
}
 
7266
#endif /* TRIO_FEATURE_CLOSURE */
6499
7267
 
6500
7268
/*************************************************************************
6501
7269
 * TrioInStreamString
6511
7279
  assert(VALID(self));
6512
7280
  assert(VALID(self->location));
6513
7281
 
 
7282
  self->actually.cached = 0;
 
7283
 
6514
7284
  buffer = (unsigned char **)self->location;
6515
7285
  self->current = (*buffer)[0];
6516
7286
  if (self->current == NIL)
6521
7291
    {
6522
7292
      (*buffer)++;
6523
7293
      self->processed++;
6524
 
      self->committed++;
 
7294
      self->actually.cached++;
6525
7295
    }
6526
 
  
 
7296
 
6527
7297
  if (VALID(intPointer))
6528
7298
    {
6529
7299
      *intPointer = self->current;
6554
7324
   @param ... Arguments.
6555
7325
   @return Number of scanned characters.
6556
7326
 */
 
7327
#if TRIO_FEATURE_STDIO
6557
7328
TRIO_PUBLIC int
6558
7329
trio_scanf
6559
7330
TRIO_VARGS2((format, va_alist),
6568
7339
  TRIO_VA_START(args, format);
6569
7340
  status = TrioScan((trio_pointer_t)stdin, 0,
6570
7341
                    TrioInStreamFile,
6571
 
                    format, &args, NULL);
 
7342
                    TrioUndoStreamFile,
 
7343
                    format, args, NULL);
6572
7344
  TRIO_VA_END(args);
6573
7345
  return status;
6574
7346
}
6575
 
 
 
7347
#endif /* TRIO_FEATURE_STDIO */
 
7348
 
 
7349
/**
 
7350
   Scan characters from standard input stream.
 
7351
 
 
7352
   @param format Formatting string.
 
7353
   @param args Arguments.
 
7354
   @return Number of scanned characters.
 
7355
 */
 
7356
#if TRIO_FEATURE_STDIO
6576
7357
TRIO_PUBLIC int
6577
7358
trio_vscanf
6578
7359
TRIO_ARGS2((format, args),
6583
7364
  
6584
7365
  return TrioScan((trio_pointer_t)stdin, 0,
6585
7366
                  TrioInStreamFile,
6586
 
                  format, &args, NULL);
 
7367
                  TrioUndoStreamFile,
 
7368
                  format, args, NULL);
6587
7369
}
6588
 
 
 
7370
#endif /* TRIO_FEATURE_STDIO */
 
7371
 
 
7372
/**
 
7373
   Scan characters from standard input stream.
 
7374
 
 
7375
   @param format Formatting string.
 
7376
   @param args Arguments.
 
7377
   @return Number of scanned characters.
 
7378
 */
 
7379
#if TRIO_FEATURE_STDIO
6589
7380
TRIO_PUBLIC int
6590
7381
trio_scanfv
6591
7382
TRIO_ARGS2((format, args),
6592
7383
           TRIO_CONST char *format,
6593
7384
           trio_pointer_t *args)
6594
7385
{
 
7386
  static va_list unused;
 
7387
  
6595
7388
  assert(VALID(format));
6596
7389
  
6597
7390
  return TrioScan((trio_pointer_t)stdin, 0,
6598
7391
                  TrioInStreamFile,
6599
 
                  format, NULL, args);
 
7392
                  TrioUndoStreamFile,
 
7393
                  format, unused, args);
6600
7394
}
 
7395
#endif /* TRIO_FEATURE_STDIO */
6601
7396
 
6602
7397
/*************************************************************************
6603
7398
 * fscanf
6604
7399
 */
 
7400
 
 
7401
/**
 
7402
   Scan characters from file.
 
7403
 
 
7404
   @param file File pointer.
 
7405
   @param format Formatting string.
 
7406
   @param ... Arguments.
 
7407
   @return Number of scanned characters.
 
7408
 */
 
7409
#if TRIO_FEATURE_FILE
6605
7410
TRIO_PUBLIC int
6606
7411
trio_fscanf
6607
7412
TRIO_VARGS3((file, format, va_alist),
6618
7423
  TRIO_VA_START(args, format);
6619
7424
  status = TrioScan((trio_pointer_t)file, 0,
6620
7425
                    TrioInStreamFile,
6621
 
                    format, &args, NULL);
 
7426
                    TrioUndoStreamFile,
 
7427
                    format, args, NULL);
6622
7428
  TRIO_VA_END(args);
6623
7429
  return status;
6624
7430
}
6625
 
 
 
7431
#endif /* TRIO_FEATURE_FILE */
 
7432
 
 
7433
/**
 
7434
   Scan characters from file.
 
7435
 
 
7436
   @param file File pointer.
 
7437
   @param format Formatting string.
 
7438
   @param args Arguments.
 
7439
   @return Number of scanned characters.
 
7440
 */
 
7441
#if TRIO_FEATURE_FILE
6626
7442
TRIO_PUBLIC int
6627
7443
trio_vfscanf
6628
7444
TRIO_ARGS3((file, format, args),
6635
7451
  
6636
7452
  return TrioScan((trio_pointer_t)file, 0,
6637
7453
                  TrioInStreamFile,
6638
 
                  format, &args, NULL);
 
7454
                  TrioUndoStreamFile,
 
7455
                  format, args, NULL);
6639
7456
}
6640
 
 
 
7457
#endif /* TRIO_FEATURE_FILE */
 
7458
 
 
7459
/**
 
7460
   Scan characters from file.
 
7461
 
 
7462
   @param file File pointer.
 
7463
   @param format Formatting string.
 
7464
   @param args Arguments.
 
7465
   @return Number of scanned characters.
 
7466
 */
 
7467
#if TRIO_FEATURE_FILE
6641
7468
TRIO_PUBLIC int
6642
7469
trio_fscanfv
6643
7470
TRIO_ARGS3((file, format, args),
6645
7472
           TRIO_CONST char *format,
6646
7473
           trio_pointer_t *args)
6647
7474
{
 
7475
  static va_list unused;
 
7476
  
6648
7477
  assert(VALID(file));
6649
7478
  assert(VALID(format));
6650
7479
  
6651
7480
  return TrioScan((trio_pointer_t)file, 0,
6652
7481
                  TrioInStreamFile,
6653
 
                  format, NULL, args);
 
7482
                  TrioUndoStreamFile,
 
7483
                  format, unused, args);
6654
7484
}
 
7485
#endif /* TRIO_FEATURE_FILE */
6655
7486
 
6656
7487
/*************************************************************************
6657
7488
 * dscanf
6658
7489
 */
 
7490
 
 
7491
/**
 
7492
   Scan characters from file descriptor.
 
7493
 
 
7494
   @param fd File descriptor.
 
7495
   @param format Formatting string.
 
7496
   @param ... Arguments.
 
7497
   @return Number of scanned characters.
 
7498
 */
 
7499
#if TRIO_FEATURE_FD
6659
7500
TRIO_PUBLIC int
6660
7501
trio_dscanf
6661
7502
TRIO_VARGS3((fd, format, va_alist),
6671
7512
  TRIO_VA_START(args, format);
6672
7513
  status = TrioScan((trio_pointer_t)&fd, 0,
6673
7514
                    TrioInStreamFileDescriptor,
6674
 
                    format, &args, NULL);
 
7515
                    NULL,
 
7516
                    format, args, NULL);
6675
7517
  TRIO_VA_END(args);
6676
7518
  return status;
6677
7519
}
6678
 
 
 
7520
#endif /* TRIO_FEATURE_FD */
 
7521
 
 
7522
/**
 
7523
   Scan characters from file descriptor.
 
7524
 
 
7525
   @param fd File descriptor.
 
7526
   @param format Formatting string.
 
7527
   @param args Arguments.
 
7528
   @return Number of scanned characters.
 
7529
 */
 
7530
#if TRIO_FEATURE_FD
6679
7531
TRIO_PUBLIC int
6680
7532
trio_vdscanf
6681
7533
TRIO_ARGS3((fd, format, args),
6687
7539
  
6688
7540
  return TrioScan((trio_pointer_t)&fd, 0,
6689
7541
                  TrioInStreamFileDescriptor,
6690
 
                  format, &args, NULL);
 
7542
                  NULL,
 
7543
                  format, args, NULL);
6691
7544
}
6692
 
 
 
7545
#endif /* TRIO_FEATURE_FD */
 
7546
 
 
7547
/**
 
7548
   Scan characters from file descriptor.
 
7549
 
 
7550
   @param fd File descriptor.
 
7551
   @param format Formatting string.
 
7552
   @param args Arguments.
 
7553
   @return Number of scanned characters.
 
7554
 */
 
7555
#if TRIO_FEATURE_FD
6693
7556
TRIO_PUBLIC int
6694
7557
trio_dscanfv
6695
7558
TRIO_ARGS3((fd, format, args),
6697
7560
           TRIO_CONST char *format,
6698
7561
           trio_pointer_t *args)
6699
7562
{
 
7563
  static va_list unused;
 
7564
  
6700
7565
  assert(VALID(format));
6701
7566
  
6702
7567
  return TrioScan((trio_pointer_t)&fd, 0,
6703
7568
                  TrioInStreamFileDescriptor,
6704
 
                  format, NULL, args);
 
7569
                  NULL,
 
7570
                  format, unused, args);
6705
7571
}
 
7572
#endif /* TRIO_FEATURE_FD */
6706
7573
 
6707
7574
/*************************************************************************
6708
7575
 * cscanf
6709
7576
 */
 
7577
#if TRIO_FEATURE_CLOSURE
6710
7578
TRIO_PUBLIC int
6711
7579
trio_cscanf
6712
7580
TRIO_VARGS4((stream, closure, format, va_alist),
6725
7593
  TRIO_VA_START(args, format);
6726
7594
  data.stream.in = stream;
6727
7595
  data.closure = closure;
6728
 
  status = TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
 
7596
  status = TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
6729
7597
  TRIO_VA_END(args);
6730
7598
  return status;
6731
7599
}
 
7600
#endif /* TRIO_FEATURE_CLOSURE */
6732
7601
 
 
7602
#if TRIO_FEATURE_CLOSURE
6733
7603
TRIO_PUBLIC int
6734
7604
trio_vcscanf
6735
7605
TRIO_ARGS4((stream, closure, format, args),
6745
7615
 
6746
7616
  data.stream.in = stream;
6747
7617
  data.closure = closure;
6748
 
  return TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
 
7618
  return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
6749
7619
}
 
7620
#endif /* TRIO_FEATURE_CLOSURE */
6750
7621
 
 
7622
#if TRIO_FEATURE_CLOSURE
6751
7623
TRIO_PUBLIC int
6752
7624
trio_cscanfv
6753
7625
TRIO_ARGS4((stream, closure, format, args),
6756
7628
           TRIO_CONST char *format,
6757
7629
           trio_pointer_t *args)
6758
7630
{
 
7631
  static va_list unused;
6759
7632
  trio_custom_t data;
6760
7633
  
6761
7634
  assert(VALID(stream));
6763
7636
 
6764
7637
  data.stream.in = stream;
6765
7638
  data.closure = closure;
6766
 
  return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args);
 
7639
  return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, unused, args);
6767
7640
}
 
7641
#endif /* TRIO_FEATURE_CLOSURE */
6768
7642
 
6769
7643
/*************************************************************************
6770
7644
 * sscanf
6771
7645
 */
 
7646
 
 
7647
/**
 
7648
   Scan characters from string.
 
7649
 
 
7650
   @param buffer Input string.
 
7651
   @param format Formatting string.
 
7652
   @param ... Arguments.
 
7653
   @return Number of scanned characters.
 
7654
 */
6772
7655
TRIO_PUBLIC int
6773
7656
trio_sscanf
6774
7657
TRIO_VARGS3((buffer, format, va_alist),
6785
7668
  TRIO_VA_START(args, format);
6786
7669
  status = TrioScan((trio_pointer_t)&buffer, 0,
6787
7670
                    TrioInStreamString,
6788
 
                    format, &args, NULL);
 
7671
                    NULL,
 
7672
                    format, args, NULL);
6789
7673
  TRIO_VA_END(args);
6790
7674
  return status;
6791
7675
}
6792
7676
 
 
7677
/**
 
7678
   Scan characters from string.
 
7679
 
 
7680
   @param buffer Input string.
 
7681
   @param format Formatting string.
 
7682
   @param args Arguments.
 
7683
   @return Number of scanned characters.
 
7684
 */
6793
7685
TRIO_PUBLIC int
6794
7686
trio_vsscanf
6795
7687
TRIO_ARGS3((buffer, format, args),
6802
7694
  
6803
7695
  return TrioScan((trio_pointer_t)&buffer, 0,
6804
7696
                  TrioInStreamString,
6805
 
                  format, &args, NULL);
 
7697
                  NULL,
 
7698
                  format, args, NULL);
6806
7699
}
6807
7700
 
 
7701
/**
 
7702
   Scan characters from string.
 
7703
 
 
7704
   @param buffer Input string.
 
7705
   @param format Formatting string.
 
7706
   @param args Arguments.
 
7707
   @return Number of scanned characters.
 
7708
 */
6808
7709
TRIO_PUBLIC int
6809
7710
trio_sscanfv
6810
7711
TRIO_ARGS3((buffer, format, args),
6812
7713
           TRIO_CONST char *format,
6813
7714
           trio_pointer_t *args)
6814
7715
{
 
7716
  static va_list unused;
 
7717
  
6815
7718
  assert(VALID(buffer));
6816
7719
  assert(VALID(format));
6817
7720
  
6818
7721
  return TrioScan((trio_pointer_t)&buffer, 0,
6819
7722
                  TrioInStreamString,
6820
 
                  format, NULL, args);
 
7723
                  NULL,
 
7724
                  format, unused, args);
6821
7725
}
6822
7726
 
 
7727
#endif /* TRIO_FEATURE_SCANF */
 
7728
 
6823
7729
/** @} End of Scanf documentation module */
6824
7730
 
6825
7731
/*************************************************************************
6830
7736
TRIO_ARGS1((errorcode),
6831
7737
           int errorcode)
6832
7738
{
 
7739
#if TRIO_FEATURE_STRERR
6833
7740
  /* Textual versions of the error codes */
6834
7741
  switch (TRIO_ERROR_CODE(errorcode))
6835
7742
    {
6852
7759
    default:
6853
7760
      return "Unknown";
6854
7761
    }
 
7762
#else
 
7763
  return "Unknown";
 
7764
#endif
6855
7765
}