3
/* Dealing with $ argument addressing stuffs.
5
** Written by Kiem-Phong Vo.
9
static char* sffmtint(const char* str, int* v)
11
static char* sffmtint(str, v)
16
for(*v = 0; isdigit(*str); ++str)
17
*v = *v * 10 + (*str - '0');
23
static Fmtpos_t* sffmtpos(Sfio_t* f, const char* form, va_list args, int type)
25
static Fmtpos_t* sffmtpos(f,form,args,type)
32
int base, fmt, flags, dot, width, precis;
35
int v, n, skip, dollar, decimal, thousand;
37
Fmtpos_t* fp; /* position array of arguments */
38
int argp, argn, maxp, need[FP_INDEX];
42
else if(!(fp = sffmtpos(f,form,args,-1)) )
43
return NIL(Fmtpos_t*);
45
dollar = decimal = thousand = 0; argn = maxp = -1;
47
{ if(n != '%') /* collect the non-pattern chars */
49
while(*form && *form != '%')
61
if(*form == '*' && type > 0) /* skip in scanning */
66
else /* get the position of this argument */
68
sp = sffmtint(form,&argp);
77
t_str = NIL(char*); n_str = 0;
78
size = width = precis = base = -1;
79
for(n = 0; n < FP_INDEX; ++n)
82
loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
83
switch((fmt = *form++) )
85
case LEFTP : /* get the type enclosed in balanced parens */
90
case 0 : /* not balancable, retract */
95
case LEFTP : /* increasing nested level */
98
case RIGHTP : /* decreasing nested level */
103
{ t_str = sffmtint(t_str+1,&n);
107
if((n = FP_SET(n,argn)) > maxp)
109
if(fp && fp[n].ft.fmt == 0)
110
{ fp[n].ft.fmt = LEFTP;
111
fp[n].ft.form = (char*)form;
121
flags &= ~SFFMT_ZERO;
124
if(!(flags&SFFMT_LEFT) )
128
if(!(flags&SFFMT_SIGN) )
129
flags |= SFFMT_BLANK;
133
flags &= ~SFFMT_BLANK;
136
flags |= SFFMT_ALTER;
139
SFSETLOCALE(&decimal,&thousand);
141
flags |= SFFMT_THOUSAND;
146
base = 0; /* for %s,%c */
151
else if(*form != '*')
153
else form += 1; /* drop thru below */
156
form = sffmtint(form,&n);
162
if((n = FP_SET(n,argn)) > maxp)
164
if(fp && fp[n].ft.fmt == 0)
165
{ fp[n].ft.fmt = '.';
167
fp[n].ft.form = (char*)form;
173
case '1' : case '2' : case '3' :
174
case '4' : case '5' : case '6' :
175
case '7' : case '8' : case '9' :
177
for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form)
178
v = v*10 + (fmt - '0');
187
case 'I' : /* object length */
189
flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
191
{ for(n = *form; isdigit(n); n = *++form)
192
size = size*10 + (n - '0');
194
else if(*form == '*')
195
{ form = sffmtint(form+1,&n);
201
if((n = FP_SET(n,argn)) > maxp)
203
if(fp && fp[n].ft.fmt == 0)
204
{ fp[n].ft.fmt = 'I';
205
fp[n].ft.size = sizeof(int);
206
fp[n].ft.form = (char*)form;
214
flags &= ~SFFMT_TYPES;
217
flags |= SFFMT_LLONG;
219
else flags |= SFFMT_LONG;
223
flags &= ~SFFMT_TYPES;
226
flags |= SFFMT_SSHORT;
228
else flags |= SFFMT_SHORT;
232
flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
236
if(flags & (SFFMT_TYPES & ~SFFMT_IFLAG) )
237
{ if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
238
{ size = (flags&SFFMT_LLONG) ? sizeof(Sflong_t) :
239
(flags&SFFMT_LONG) ? sizeof(long) :
240
(flags&SFFMT_SHORT) ? sizeof(short) :
241
(flags&SFFMT_SSHORT) ? sizeof(char) :
242
(flags&SFFMT_JFLAG) ? sizeof(Sflong_t) :
243
(flags&SFFMT_TFLAG) ? sizeof(ptrdiff_t) :
244
(flags&SFFMT_ZFLAG) ? sizeof(size_t) :
247
else if(_Sftype[fmt]&SFFMT_FLOAT)
248
{ size = (flags&SFFMT_LDOUBLE) ? sizeof(Sfdouble_t) :
249
(flags&(SFFMT_LONG|SFFMT_LLONG)) ?
257
if((argp = FP_SET(argp,argn)) > maxp)
260
if(dollar && fmt == '!')
261
return NIL(Fmtpos_t*);
263
if(fp && fp[argp].ft.fmt == 0)
264
{ fp[argp].ft.form = (char*)form;
265
fp[argp].ft.fmt = fp[argp].fmt = fmt;
266
fp[argp].ft.size = size;
267
fp[argp].ft.flags = flags;
268
fp[argp].ft.width = width;
269
fp[argp].ft.precis = precis;
270
fp[argp].ft.base = base;
271
fp[argp].ft.t_str = t_str;
272
fp[argp].ft.n_str = n_str;
273
for(n = 0; n < FP_INDEX; ++n)
274
fp[argp].need[n] = need[n];
278
if(!fp) /* constructing position array only */
279
{ if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) )
280
return NIL(Fmtpos_t*);
281
for(n = 0; n <= maxp; ++n)
286
/* get value for positions */
287
for(n = 0, ft = NIL(Sffmt_t*); n <= maxp; ++n)
288
{ if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */
289
{ fp[n].ft.fmt = 'd';
297
for(v = 0; v < FP_INDEX; ++v)
302
{ fp[n].ft.version = ft->version;
303
fp[n].ft.extf = ft->extf;
304
fp[n].ft.eventf = ft->eventf;
305
if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n)
306
fp[n].ft.width = fp[v].argv.i;
307
if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n)
308
fp[n].ft.precis = fp[v].argv.i;
309
if((v = fp[n].need[FP_BASE]) >= 0 && v < n)
310
fp[n].ft.base = fp[v].argv.i;
311
if((v = fp[n].need[FP_STR]) >= 0 && v < n)
312
fp[n].ft.t_str = fp[v].argv.s;
313
if((v = fp[n].need[FP_SIZE]) >= 0 && v < n)
314
fp[n].ft.size = fp[v].argv.i;
316
memcpy(ft,&fp[n].ft,sizeof(Sffmt_t));
317
va_copy(ft->args,args);
318
ft->flags |= SFFMT_ARGPOS;
319
v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft);
320
va_copy(args,ft->args);
321
memcpy(&fp[n].ft,ft,sizeof(Sffmt_t));
323
{ memcpy(ft,&savft,sizeof(Sffmt_t));
327
if(!(fp[n].ft.flags&SFFMT_VALUE) )
332
if(fp[n].ft.fmt == LEFTP)
333
{ fp[n].argv.s = va_arg(args, char*);
334
fp[n].ft.size = strlen(fp[n].argv.s);
336
else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I')
337
fp[n].argv.i = va_arg(args, int);
338
else if(fp[n].ft.fmt == '!')
340
memcpy(ft,&savft,sizeof(Sffmt_t));
341
fp[n].argv.ft = ft = va_arg(args, Sffmt_t*);
345
memcpy(&savft,ft,sizeof(Sffmt_t));
347
else if(type > 0) /* from sfvscanf */
348
fp[n].argv.vp = va_arg(args, Void_t*);
349
else switch(_Sftype[fp[n].ft.fmt])
352
#if !_ast_intmax_long
353
if(FMTCMP(size, Sflong_t, Sflong_t))
354
fp[n].argv.ll = va_arg(args, Sflong_t);
357
if(FMTCMP(size, long, Sflong_t) )
358
fp[n].argv.l = va_arg(args, long);
359
else fp[n].argv.i = va_arg(args, int);
362
#if !_ast_fltmax_double
363
if(FMTCMP(size, Sfdouble_t, Sfdouble_t))
364
fp[n].argv.ld = va_arg(args,Sfdouble_t);
367
fp[n].argv.d = va_arg(args,double);
370
fp[n].argv.vp = va_arg(args,Void_t*);
373
if(fp[n].ft.base >= 0)
374
fp[n].argv.s = va_arg(args,char*);
375
else fp[n].argv.c = (char)va_arg(args,int);
377
default: /* unknown pattern */
384
memcpy(ft,&savft,sizeof(Sffmt_t));
389
/* function to initialize conversion tables */
390
static int sfcvinit()
393
for(d = 0; d <= SF_MAXCHAR; ++d)
394
{ _Sfcv36[d] = SF_RADIX;
395
_Sfcv64[d] = SF_RADIX;
399
for(d = 0; d < 10; ++d)
400
{ _Sfcv36[(uchar)_Sfdigits[d]] = d;
401
_Sfcv64[(uchar)_Sfdigits[d]] = d;
406
{ _Sfcv36[(uchar)_Sfdigits[d]] = d;
407
_Sfcv64[(uchar)_Sfdigits[d]] = d;
411
for(l = 10; d < 62; ++l, ++d)
412
{ _Sfcv36[(uchar)_Sfdigits[d]] = l;
413
_Sfcv64[(uchar)_Sfdigits[d]] = d;
416
/* remaining digits */
417
for(; d < SF_RADIX; ++d)
418
{ _Sfcv36[(uchar)_Sfdigits[d]] = d;
419
_Sfcv64[(uchar)_Sfdigits[d]] = d;
422
_Sftype['d'] = _Sftype['i'] = SFFMT_INT;
423
_Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT;
424
_Sftype['e'] = _Sftype['E'] =
425
_Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT;
426
_Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER;
427
_Sftype['c'] = SFFMT_BYTE;
428
_Sftype['['] = SFFMT_CLASS;
433
/* table for floating point and integer conversions */
436
{ 1e1, 1e2, 1e4, 1e8, 1e16, 1e32 }, /* _Sfpos10 */
438
{ 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32 }, /* _Sfneg10 */
440
{ '0','0', '0','1', '0','2', '0','3', '0','4', /* _Sfdec */
441
'0','5', '0','6', '0','7', '0','8', '0','9',
442
'1','0', '1','1', '1','2', '1','3', '1','4',
443
'1','5', '1','6', '1','7', '1','8', '1','9',
444
'2','0', '2','1', '2','2', '2','3', '2','4',
445
'2','5', '2','6', '2','7', '2','8', '2','9',
446
'3','0', '3','1', '3','2', '3','3', '3','4',
447
'3','5', '3','6', '3','7', '3','8', '3','9',
448
'4','0', '4','1', '4','2', '4','3', '4','4',
449
'4','5', '4','6', '4','7', '4','8', '4','9',
450
'5','0', '5','1', '5','2', '5','3', '5','4',
451
'5','5', '5','6', '5','7', '5','8', '5','9',
452
'6','0', '6','1', '6','2', '6','3', '6','4',
453
'6','5', '6','6', '6','7', '6','8', '6','9',
454
'7','0', '7','1', '7','2', '7','3', '7','4',
455
'7','5', '7','6', '7','7', '7','8', '7','9',
456
'8','0', '8','1', '8','2', '8','3', '8','4',
457
'8','5', '8','6', '8','7', '8','8', '8','9',
458
'9','0', '9','1', '9','2', '9','3', '9','4',
459
'9','5', '9','6', '9','7', '9','8', '9','9',
462
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_",