1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
23 #include "FEATURE/float"
25 /* Dealing with $ argument addressing stuffs.
27 ** Written by Kiem-Phong Vo.
31 static char* sffmtint(const char* str
, int* v
)
33 static char* sffmtint(str
, v
)
38 for(*v
= 0; isdigit(*str
); ++str
)
39 *v
= *v
* 10 + (*str
- '0');
45 static Fmtpos_t
* sffmtpos(Sfio_t
* f
,const char* form
,va_list args
,Sffmt_t
* ft
,int type
)
47 static Fmtpos_t
* sffmtpos(f
,form
,args
,ft
,type
)
52 int type
; /* >0: scanf, =0: printf, -1: internal */
55 int base
, fmt
, flags
, dot
, width
, precis
;
58 int v
, n
, skip
, dollar
, decimal
, thousand
;
60 Fmtpos_t
* fp
; /* position array of arguments */
61 int argp
, argn
, maxp
, need
[FP_INDEX
];
68 else if(!(fp
= sffmtpos(f
,form
,args
,ft
,-1)) )
69 return NIL(Fmtpos_t
*);
71 dollar
= decimal
= thousand
= 0; argn
= maxp
= -1;
74 { if(n
!= '%') /* collect the non-pattern chars */
77 { form
+= SFMBLEN(form
, &fmbs
);
78 if(*form
== 0 || *form
== '%')
91 if(*form
== '*' && type
> 0) /* skip in scanning */
96 else /* get the position of this argument */
98 sp
= sffmtint(form
,&argp
);
107 t_str
= NIL(char*); n_str
= 0;
108 size
= width
= precis
= base
= -1;
109 for(n
= 0; n
< FP_INDEX
; ++n
)
112 loop_flags
: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
113 switch((fmt
= *form
++) )
115 case LEFTP
: /* get the type enclosed in balanced parens */
120 case 0 : /* not balancable, retract */
125 case LEFTP
: /* increasing nested level */
128 case RIGHTP
: /* decreasing nested level */
133 { t_str
= sffmtint(t_str
+1,&n
);
137 if((n
= FP_SET(n
,argn
)) > maxp
)
139 if(fp
&& fp
[n
].ft
.fmt
== 0)
140 { fp
[n
].ft
.fmt
= LEFTP
;
141 fp
[n
].ft
.form
= (char*)form
;
151 flags
&= ~SFFMT_ZERO
;
154 if(!(flags
&SFFMT_LEFT
) )
158 if(!(flags
&SFFMT_SIGN
) )
159 flags
|= SFFMT_BLANK
;
163 flags
&= ~SFFMT_BLANK
;
166 flags
|= SFFMT_ALTER
;
169 SFSETLOCALE(&decimal
,&thousand
);
171 flags
|= SFFMT_THOUSAND
;
176 base
= 0; /* for %s,%c */
181 else if(*form
!= '*')
183 else form
+= 1; /* drop thru below */
186 form
= sffmtint(form
,&n
);
192 if((n
= FP_SET(n
,argn
)) > maxp
)
194 if(fp
&& fp
[n
].ft
.fmt
== 0)
195 { fp
[n
].ft
.fmt
= '.';
197 fp
[n
].ft
.form
= (char*)form
;
203 case '1' : case '2' : case '3' :
204 case '4' : case '5' : case '6' :
205 case '7' : case '8' : case '9' :
207 for(v
= fmt
- '0', fmt
= *form
; isdigit(fmt
); fmt
= *++form
)
208 v
= v
*10 + (fmt
- '0');
217 case 'I' : /* object length */
218 size
= -1; flags
= (flags
& ~SFFMT_TYPES
) | SFFMT_IFLAG
;
220 { for(size
= 0, n
= *form
; isdigit(n
); n
= *++form
)
221 size
= size
*10 + (n
- '0');
223 else if(*form
== '*')
224 { form
= sffmtint(form
+1,&n
);
230 if((n
= FP_SET(n
,argn
)) > maxp
)
232 if(fp
&& fp
[n
].ft
.fmt
== 0)
233 { fp
[n
].ft
.fmt
= 'I';
234 fp
[n
].ft
.size
= sizeof(int);
235 fp
[n
].ft
.form
= (char*)form
;
242 size
= -1; flags
&= ~SFFMT_TYPES
;
245 flags
|= SFFMT_LLONG
;
247 else flags
|= SFFMT_LONG
;
250 size
= -1; flags
&= ~SFFMT_TYPES
;
253 flags
|= SFFMT_SSHORT
;
255 else flags
|= SFFMT_SHORT
;
258 size
= -1; flags
= (flags
& ~SFFMT_TYPES
) | SFFMT_LDOUBLE
;
262 /* set object size for scalars */
263 if(flags
& SFFMT_TYPES
)
264 { if((_Sftype
[fmt
]&(SFFMT_INT
|SFFMT_UINT
)) || fmt
== 'n')
265 { if(flags
&SFFMT_LONG
)
267 else if(flags
&SFFMT_SHORT
)
268 size
= sizeof(short);
269 else if(flags
&SFFMT_SSHORT
)
271 else if(flags
&SFFMT_TFLAG
)
272 size
= sizeof(ptrdiff_t);
273 else if(flags
&SFFMT_ZFLAG
)
274 size
= sizeof(size_t);
275 else if(flags
&(SFFMT_LLONG
|SFFMT_JFLAG
) )
276 size
= sizeof(Sflong_t
);
277 else if(flags
&SFFMT_IFLAG
)
279 size
== sizeof(Sflong_t
)*CHAR_BIT
)
280 size
= sizeof(Sflong_t
);
285 else if(_Sftype
[fmt
]&SFFMT_FLOAT
)
286 { if(flags
&(SFFMT_LONG
|SFFMT_LLONG
))
287 size
= sizeof(double);
288 else if(flags
&SFFMT_LDOUBLE
)
289 size
= sizeof(Sfdouble_t
);
290 else if(flags
&SFFMT_IFLAG
)
292 size
= sizeof(Sfdouble_t
);
295 size
= sizeof(float);
297 else if(_Sftype
[fmt
]&SFFMT_CHAR
)
300 if((flags
&SFFMT_LONG
) || fmt
== 'C')
301 { size
= sizeof(wchar_t) > sizeof(int) ?
302 sizeof(wchar_t) : sizeof(int);
313 if((argp
= FP_SET(argp
,argn
)) > maxp
)
316 if(dollar
&& fmt
== '!')
317 return NIL(Fmtpos_t
*);
319 if(fp
&& fp
[argp
].ft
.fmt
== 0)
320 { fp
[argp
].ft
.form
= (char*)form
;
321 fp
[argp
].ft
.fmt
= fp
[argp
].fmt
= fmt
;
322 fp
[argp
].ft
.size
= size
;
323 fp
[argp
].ft
.flags
= flags
;
324 fp
[argp
].ft
.width
= width
;
325 fp
[argp
].ft
.precis
= precis
;
326 fp
[argp
].ft
.base
= base
;
327 fp
[argp
].ft
.t_str
= t_str
;
328 fp
[argp
].ft
.n_str
= n_str
;
329 for(n
= 0; n
< FP_INDEX
; ++n
)
330 fp
[argp
].need
[n
] = need
[n
];
334 if(!fp
) /* constructing position array only */
335 { if(!dollar
|| !(fp
= (Fmtpos_t
*)malloc((maxp
+1)*sizeof(Fmtpos_t
))) )
336 return NIL(Fmtpos_t
*);
337 for(n
= 0; n
<= maxp
; ++n
)
342 /* get value for positions */
344 memcpy(&savft
, ft
, sizeof(*ft
));
345 for(n
= 0; n
<= maxp
; ++n
)
346 { if(fp
[n
].ft
.fmt
== 0) /* gap: pretend it's a 'd' pattern */
347 { fp
[n
].ft
.fmt
= 'd';
355 for(v
= 0; v
< FP_INDEX
; ++v
)
360 { fp
[n
].ft
.version
= ft
->version
;
361 fp
[n
].ft
.extf
= ft
->extf
;
362 fp
[n
].ft
.eventf
= ft
->eventf
;
363 if((v
= fp
[n
].need
[FP_WIDTH
]) >= 0 && v
< n
)
364 fp
[n
].ft
.width
= fp
[v
].argv
.i
;
365 if((v
= fp
[n
].need
[FP_PRECIS
]) >= 0 && v
< n
)
366 fp
[n
].ft
.precis
= fp
[v
].argv
.i
;
367 if((v
= fp
[n
].need
[FP_BASE
]) >= 0 && v
< n
)
368 fp
[n
].ft
.base
= fp
[v
].argv
.i
;
369 if((v
= fp
[n
].need
[FP_STR
]) >= 0 && v
< n
)
370 fp
[n
].ft
.t_str
= fp
[v
].argv
.s
;
371 if((v
= fp
[n
].need
[FP_SIZE
]) >= 0 && v
< n
)
372 fp
[n
].ft
.size
= fp
[v
].argv
.i
;
374 memcpy(ft
,&fp
[n
].ft
,sizeof(Sffmt_t
));
375 va_copy(ft
->args
,args
);
376 ft
->flags
|= SFFMT_ARGPOS
;
377 v
= (*ft
->extf
)(f
, (Void_t
*)(&fp
[n
].argv
), ft
);
378 va_copy(args
,ft
->args
);
379 memcpy(&fp
[n
].ft
,ft
,sizeof(Sffmt_t
));
381 { memcpy(ft
,&savft
,sizeof(Sffmt_t
));
385 if(!(fp
[n
].ft
.flags
&SFFMT_VALUE
) )
387 else if(_Sftype
[fp
[n
].ft
.fmt
]&(SFFMT_INT
|SFFMT_UINT
) )
388 { if(fp
[n
].ft
.size
== sizeof(short))
389 { if(_Sftype
[fp
[n
].ft
.fmt
]&SFFMT_INT
)
390 fp
[n
].argv
.i
= fp
[n
].argv
.h
;
391 else fp
[n
].argv
.i
= fp
[n
].argv
.uh
;
393 else if(fp
[n
].ft
.size
== sizeof(char))
394 { if(_Sftype
[fp
[n
].ft
.fmt
]&SFFMT_INT
)
395 fp
[n
].argv
.i
= fp
[n
].argv
.c
;
396 else fp
[n
].argv
.i
= fp
[n
].argv
.uc
;
399 else if(_Sftype
[fp
[n
].ft
.fmt
]&SFFMT_FLOAT
)
400 { if(fp
[n
].ft
.size
== sizeof(float) )
401 fp
[n
].argv
.d
= fp
[n
].argv
.f
;
406 if(fp
[n
].ft
.fmt
== LEFTP
)
407 { fp
[n
].argv
.s
= va_arg(args
, char*);
408 fp
[n
].ft
.size
= strlen(fp
[n
].argv
.s
);
410 else if(fp
[n
].ft
.fmt
== '.' || fp
[n
].ft
.fmt
== 'I')
411 fp
[n
].argv
.i
= va_arg(args
, int);
412 else if(fp
[n
].ft
.fmt
== '!')
414 memcpy(ft
,&savft
,sizeof(Sffmt_t
));
415 fp
[n
].argv
.ft
= ft
= va_arg(args
, Sffmt_t
*);
419 memcpy(&savft
,ft
,sizeof(Sffmt_t
));
421 else if(type
> 0) /* from sfvscanf */
422 fp
[n
].argv
.vp
= va_arg(args
, Void_t
*);
423 else switch(_Sftype
[fp
[n
].ft
.fmt
])
426 #if !_ast_intmax_long
427 if(size
== sizeof(Sflong_t
) )
428 fp
[n
].argv
.ll
= va_arg(args
, Sflong_t
);
431 if(size
== sizeof(long) )
432 fp
[n
].argv
.l
= va_arg(args
, long);
433 else fp
[n
].argv
.i
= va_arg(args
, int);
436 #if !_ast_fltmax_double
437 if(size
== sizeof(Sfdouble_t
) )
438 fp
[n
].argv
.ld
= va_arg(args
,Sfdouble_t
);
441 fp
[n
].argv
.d
= va_arg(args
,double);
444 fp
[n
].argv
.vp
= va_arg(args
,Void_t
*);
447 if(fp
[n
].ft
.base
>= 0)
448 fp
[n
].argv
.s
= va_arg(args
,char*);
450 else if((fp
[n
].ft
.flags
& SFFMT_LONG
) ||
451 fp
[n
].ft
.fmt
== 'C' )
452 { if(sizeof(wchar_t) <= sizeof(int) )
453 fp
[n
].argv
.wc
= (wchar_t)va_arg(args
,int);
454 else fp
[n
].argv
.wc
= va_arg(args
,wchar_t);
457 /* observe promotion rule */
458 else fp
[n
].argv
.i
= va_arg(args
,int);
460 default: /* unknown pattern */
467 memcpy(ft
,&savft
,sizeof(Sffmt_t
));
471 static const unsigned char flt_nan
[] = { _ast_flt_nan_init
};
472 static const unsigned char flt_inf
[] = { _ast_flt_inf_init
};
473 static const unsigned char dbl_nan
[] = { _ast_dbl_nan_init
};
474 static const unsigned char dbl_inf
[] = { _ast_dbl_inf_init
};
475 #ifdef _ast_ldbl_nan_init
476 static const unsigned char ldbl_nan
[] = { _ast_ldbl_nan_init
};
477 static const unsigned char ldbl_inf
[] = { _ast_ldbl_inf_init
};
480 /* function to initialize conversion tables */
481 static int sfcvinit()
484 for(d
= 0; d
<= SF_MAXCHAR
; ++d
)
485 { _Sfcv36
[d
] = SF_RADIX
;
486 _Sfcv64
[d
] = SF_RADIX
;
490 for(d
= 0; d
< 10; ++d
)
491 { _Sfcv36
[(uchar
)_Sfdigits
[d
]] = d
;
492 _Sfcv64
[(uchar
)_Sfdigits
[d
]] = d
;
497 { _Sfcv36
[(uchar
)_Sfdigits
[d
]] = d
;
498 _Sfcv64
[(uchar
)_Sfdigits
[d
]] = d
;
502 for(l
= 10; d
< 62; ++l
, ++d
)
503 { _Sfcv36
[(uchar
)_Sfdigits
[d
]] = l
;
504 _Sfcv64
[(uchar
)_Sfdigits
[d
]] = d
;
507 /* remaining digits */
508 for(; d
< SF_RADIX
; ++d
)
509 { _Sfcv36
[(uchar
)_Sfdigits
[d
]] = d
;
510 _Sfcv64
[(uchar
)_Sfdigits
[d
]] = d
;
513 _Sftype
['d'] = _Sftype
['i'] = SFFMT_INT
;
514 _Sftype
['u'] = _Sftype
['o'] = _Sftype
['x'] = _Sftype
['X'] = SFFMT_UINT
;
515 _Sftype
['e'] = _Sftype
['E'] = _Sftype
['a'] = _Sftype
['A'] =
516 _Sftype
['g'] = _Sftype
['G'] = _Sftype
['f'] = SFFMT_FLOAT
;
517 _Sftype
['s'] = _Sftype
['n'] = _Sftype
['p'] = _Sftype
['!'] = SFFMT_POINTER
;
518 _Sftype
['c'] = SFFMT_CHAR
;
519 _Sftype
['['] = SFFMT_CLASS
;
521 _Sftype
['S'] = SFFMT_POINTER
;
522 _Sftype
['C'] = SFFMT_CHAR
;
525 /* IEEE floating point computed constants */
527 memcpy((char*)&_Sffnan
, (char*)flt_nan
, sizeof(_Sffnan
));
528 memcpy((char*)&_Sffinf
, (char*)flt_inf
, sizeof(_Sffinf
));
529 memcpy((char*)&_Sfdnan
, (char*)dbl_nan
, sizeof(_Sfdnan
));
530 memcpy((char*)&_Sfdinf
, (char*)dbl_inf
, sizeof(_Sfdinf
));
531 #ifdef _ast_ldbl_nan_init
532 memcpy((char*)&_Sflnan
, (char*)ldbl_nan
, sizeof(_Sflnan
));
533 memcpy((char*)&_Sflinf
, (char*)ldbl_inf
, sizeof(_Sflinf
));
535 memcpy((char*)&_Sflnan
, (char*)dbl_nan
, sizeof(_Sfdnan
));
536 memcpy((char*)&_Sflinf
, (char*)dbl_inf
, sizeof(_Sfdinf
));
542 /* table for floating point and integer conversions */
543 #include "FEATURE/sfinit"