diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/sfio/sftable.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/sfio/sftable.c')
-rw-r--r-- | src/lib/libast/sfio/sftable.c | 543 |
1 files changed, 543 insertions, 0 deletions
diff --git a/src/lib/libast/sfio/sftable.c b/src/lib/libast/sfio/sftable.c new file mode 100644 index 0000000..c165bae --- /dev/null +++ b/src/lib/libast/sfio/sftable.c @@ -0,0 +1,543 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#include "sfhdr.h" +#include "FEATURE/float" + +/* Dealing with $ argument addressing stuffs. +** +** Written by Kiem-Phong Vo. +*/ + +#if __STD_C +static char* sffmtint(const char* str, int* v) +#else +static char* sffmtint(str, v) +char* str; +int* v; +#endif +{ + for(*v = 0; isdigit(*str); ++str) + *v = *v * 10 + (*str - '0'); + *v -= 1; + return (char*)str; +} + +#if __STD_C +static Fmtpos_t* sffmtpos(Sfio_t* f,const char* form,va_list args,Sffmt_t* ft,int type) +#else +static Fmtpos_t* sffmtpos(f,form,args,ft,type) +Sfio_t* f; +char* form; +va_list args; +Sffmt_t* ft; +int type; /* >0: scanf, =0: printf, -1: internal */ +#endif +{ + int base, fmt, flags, dot, width, precis; + ssize_t n_str, size; + char *t_str, *sp; + int v, n, skip, dollar, decimal, thousand; + Sffmt_t savft; + Fmtpos_t* fp; /* position array of arguments */ + int argp, argn, maxp, need[FP_INDEX]; +#if _has_multibyte + SFMBDCL(fmbs) +#endif + + if(type < 0) + fp = NIL(Fmtpos_t*); + else if(!(fp = sffmtpos(f,form,args,ft,-1)) ) + return NIL(Fmtpos_t*); + + dollar = decimal = thousand = 0; argn = maxp = -1; + SFMBCLR(&fmbs); + while((n = *form) ) + { if(n != '%') /* collect the non-pattern chars */ + { sp = (char*)form; + for(;;) + { form += SFMBLEN(form, &fmbs); + if(*form == 0 || *form == '%') + break; + } + continue; + } + else form += 1; + if(*form == 0) + break; + else if(*form == '%') + { form += 1; + continue; + } + + if(*form == '*' && type > 0) /* skip in scanning */ + { skip = 1; + form += 1; + argp = -1; + } + else /* get the position of this argument */ + { skip = 0; + sp = sffmtint(form,&argp); + if(*sp == '$') + { dollar = 1; + form = sp+1; + } + else argp = -1; + } + + flags = dot = 0; + t_str = NIL(char*); n_str = 0; + size = width = precis = base = -1; + for(n = 0; n < FP_INDEX; ++n) + need[n] = -1; + + loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */ + switch((fmt = *form++) ) + { + case LEFTP : /* get the type enclosed in balanced parens */ + t_str = (char*)form; + for(v = 1;;) + { switch(*form++) + { + case 0 : /* not balancable, retract */ + form = t_str; + t_str = NIL(char*); + n_str = 0; + goto loop_flags; + case LEFTP : /* increasing nested level */ + v += 1; + continue; + case RIGHTP : /* decreasing nested level */ + if((v -= 1) != 0) + continue; + n_str = form-t_str; + if(*t_str == '*') + { t_str = sffmtint(t_str+1,&n); + if(*t_str == '$') + dollar = 1; + else n = -1; + if((n = FP_SET(n,argn)) > maxp) + maxp = n; + if(fp && fp[n].ft.fmt == 0) + { fp[n].ft.fmt = LEFTP; + fp[n].ft.form = (char*)form; + } + need[FP_STR] = n; + } + goto loop_flags; + } + } + + case '-' : + flags |= SFFMT_LEFT; + flags &= ~SFFMT_ZERO; + goto loop_flags; + case '0' : + if(!(flags&SFFMT_LEFT) ) + flags |= SFFMT_ZERO; + goto loop_flags; + case ' ' : + if(!(flags&SFFMT_SIGN) ) + flags |= SFFMT_BLANK; + goto loop_flags; + case '+' : + flags |= SFFMT_SIGN; + flags &= ~SFFMT_BLANK; + goto loop_flags; + case '#' : + flags |= SFFMT_ALTER; + goto loop_flags; + case QUOTE: + SFSETLOCALE(&decimal,&thousand); + if(thousand > 0) + flags |= SFFMT_THOUSAND; + goto loop_flags; + + case '.' : + if((dot += 1) == 2) + base = 0; /* for %s,%c */ + if(isdigit(*form)) + { fmt = *form++; + goto dot_size; + } + else if(*form != '*') + goto loop_flags; + else form += 1; /* drop thru below */ + + case '*' : + form = sffmtint(form,&n); + if(*form == '$' ) + { dollar = 1; + form += 1; + } + else n = -1; + if((n = FP_SET(n,argn)) > maxp) + maxp = n; + if(fp && fp[n].ft.fmt == 0) + { fp[n].ft.fmt = '.'; + fp[n].ft.size = dot; + fp[n].ft.form = (char*)form; + } + if(dot <= 2) + need[dot] = n; + goto loop_flags; + + case '1' : case '2' : case '3' : + case '4' : case '5' : case '6' : + case '7' : case '8' : case '9' : + dot_size : + for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form) + v = v*10 + (fmt - '0'); + if(dot == 0) + width = v; + else if(dot == 1) + precis = v; + else if(dot == 2) + base = v; + goto loop_flags; + + case 'I' : /* object length */ + size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG; + if(isdigit(*form) ) + { for(size = 0, n = *form; isdigit(n); n = *++form) + size = size*10 + (n - '0'); + } + else if(*form == '*') + { form = sffmtint(form+1,&n); + if(*form == '$' ) + { dollar = 1; + form += 1; + } + else n = -1; + if((n = FP_SET(n,argn)) > maxp) + maxp = n; + if(fp && fp[n].ft.fmt == 0) + { fp[n].ft.fmt = 'I'; + fp[n].ft.size = sizeof(int); + fp[n].ft.form = (char*)form; + } + need[FP_SIZE] = n; + } + goto loop_flags; + + case 'l' : + size = -1; flags &= ~SFFMT_TYPES; + if(*form == 'l') + { form += 1; + flags |= SFFMT_LLONG; + } + else flags |= SFFMT_LONG; + goto loop_flags; + case 'h' : + size = -1; flags &= ~SFFMT_TYPES; + if(*form == 'h') + { form += 1; + flags |= SFFMT_SSHORT; + } + else flags |= SFFMT_SHORT; + goto loop_flags; + case 'L' : + size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE; + goto loop_flags; + } + + /* set object size for scalars */ + if(flags & SFFMT_TYPES) + { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n') + { if(flags&SFFMT_LONG) + size = sizeof(long); + else if(flags&SFFMT_SHORT) + size = sizeof(short); + else if(flags&SFFMT_SSHORT) + size = sizeof(char); + else if(flags&SFFMT_TFLAG) + size = sizeof(ptrdiff_t); + else if(flags&SFFMT_ZFLAG) + size = sizeof(size_t); + else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) ) + size = sizeof(Sflong_t); + else if(flags&SFFMT_IFLAG) + { if(size <= 0 || + size == sizeof(Sflong_t)*CHAR_BIT ) + size = sizeof(Sflong_t); + } + else if(size < 0) + size = sizeof(int); + } + else if(_Sftype[fmt]&SFFMT_FLOAT) + { if(flags&(SFFMT_LONG|SFFMT_LLONG)) + size = sizeof(double); + else if(flags&SFFMT_LDOUBLE) + size = sizeof(Sfdouble_t); + else if(flags&SFFMT_IFLAG) + { if(size <= 0) + size = sizeof(Sfdouble_t); + } + else if(size < 0) + size = sizeof(float); + } + else if(_Sftype[fmt]&SFFMT_CHAR) + { +#if _has_multibyte + if((flags&SFFMT_LONG) || fmt == 'C') + { size = sizeof(wchar_t) > sizeof(int) ? + sizeof(wchar_t) : sizeof(int); + } else +#endif + if(size < 0) + size = sizeof(int); + } + } + + if(skip) + continue; + + if((argp = FP_SET(argp,argn)) > maxp) + maxp = argp; + + if(dollar && fmt == '!') + return NIL(Fmtpos_t*); + + if(fp && fp[argp].ft.fmt == 0) + { fp[argp].ft.form = (char*)form; + fp[argp].ft.fmt = fp[argp].fmt = fmt; + fp[argp].ft.size = size; + fp[argp].ft.flags = flags; + fp[argp].ft.width = width; + fp[argp].ft.precis = precis; + fp[argp].ft.base = base; + fp[argp].ft.t_str = t_str; + fp[argp].ft.n_str = n_str; + for(n = 0; n < FP_INDEX; ++n) + fp[argp].need[n] = need[n]; + } + } + + if(!fp) /* constructing position array only */ + { if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) ) + return NIL(Fmtpos_t*); + for(n = 0; n <= maxp; ++n) + fp[n].ft.fmt = 0; + return fp; + } + + /* get value for positions */ + if(ft) + memcpy(&savft, ft, sizeof(*ft)); + for(n = 0; n <= maxp; ++n) + { if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */ + { fp[n].ft.fmt = 'd'; + fp[n].ft.width = 0; + fp[n].ft.precis = 0; + fp[n].ft.base = 0; + fp[n].ft.size = 0; + fp[n].ft.t_str = 0; + fp[n].ft.n_str = 0; + fp[n].ft.flags = 0; + for(v = 0; v < FP_INDEX; ++v) + fp[n].need[v] = -1; + } + + if(ft && ft->extf) + { fp[n].ft.version = ft->version; + fp[n].ft.extf = ft->extf; + fp[n].ft.eventf = ft->eventf; + if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n) + fp[n].ft.width = fp[v].argv.i; + if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n) + fp[n].ft.precis = fp[v].argv.i; + if((v = fp[n].need[FP_BASE]) >= 0 && v < n) + fp[n].ft.base = fp[v].argv.i; + if((v = fp[n].need[FP_STR]) >= 0 && v < n) + fp[n].ft.t_str = fp[v].argv.s; + if((v = fp[n].need[FP_SIZE]) >= 0 && v < n) + fp[n].ft.size = fp[v].argv.i; + + memcpy(ft,&fp[n].ft,sizeof(Sffmt_t)); + va_copy(ft->args,args); + ft->flags |= SFFMT_ARGPOS; + v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft); + va_copy(args,ft->args); + memcpy(&fp[n].ft,ft,sizeof(Sffmt_t)); + if(v < 0) + { memcpy(ft,&savft,sizeof(Sffmt_t)); + ft = NIL(Sffmt_t*); + } + + if(!(fp[n].ft.flags&SFFMT_VALUE) ) + goto arg_list; + else if(_Sftype[fp[n].ft.fmt]&(SFFMT_INT|SFFMT_UINT) ) + { if(fp[n].ft.size == sizeof(short)) + { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT) + fp[n].argv.i = fp[n].argv.h; + else fp[n].argv.i = fp[n].argv.uh; + } + else if(fp[n].ft.size == sizeof(char)) + { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT) + fp[n].argv.i = fp[n].argv.c; + else fp[n].argv.i = fp[n].argv.uc; + } + } + else if(_Sftype[fp[n].ft.fmt]&SFFMT_FLOAT ) + { if(fp[n].ft.size == sizeof(float) ) + fp[n].argv.d = fp[n].argv.f; + } + } + else + { arg_list: + if(fp[n].ft.fmt == LEFTP) + { fp[n].argv.s = va_arg(args, char*); + fp[n].ft.size = strlen(fp[n].argv.s); + } + else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I') + fp[n].argv.i = va_arg(args, int); + else if(fp[n].ft.fmt == '!') + { if(ft) + memcpy(ft,&savft,sizeof(Sffmt_t)); + fp[n].argv.ft = ft = va_arg(args, Sffmt_t*); + if(ft->form) + ft = NIL(Sffmt_t*); + if(ft) + memcpy(&savft,ft,sizeof(Sffmt_t)); + } + else if(type > 0) /* from sfvscanf */ + fp[n].argv.vp = va_arg(args, Void_t*); + else switch(_Sftype[fp[n].ft.fmt]) + { case SFFMT_INT: + case SFFMT_UINT: +#if !_ast_intmax_long + if(size == sizeof(Sflong_t) ) + fp[n].argv.ll = va_arg(args, Sflong_t); + else +#endif + if(size == sizeof(long) ) + fp[n].argv.l = va_arg(args, long); + else fp[n].argv.i = va_arg(args, int); + break; + case SFFMT_FLOAT: +#if !_ast_fltmax_double + if(size == sizeof(Sfdouble_t) ) + fp[n].argv.ld = va_arg(args,Sfdouble_t); + else +#endif + fp[n].argv.d = va_arg(args,double); + break; + case SFFMT_POINTER: + fp[n].argv.vp = va_arg(args,Void_t*); + break; + case SFFMT_CHAR: + if(fp[n].ft.base >= 0) + fp[n].argv.s = va_arg(args,char*); +#if _has_multibyte + else if((fp[n].ft.flags & SFFMT_LONG) || + fp[n].ft.fmt == 'C' ) + { if(sizeof(wchar_t) <= sizeof(int) ) + fp[n].argv.wc = (wchar_t)va_arg(args,int); + else fp[n].argv.wc = va_arg(args,wchar_t); + } +#endif + /* observe promotion rule */ + else fp[n].argv.i = va_arg(args,int); + break; + default: /* unknown pattern */ + break; + } + } + } + + if(ft) + memcpy(ft,&savft,sizeof(Sffmt_t)); + return fp; +} + +static const unsigned char flt_nan[] = { _ast_flt_nan_init }; +static const unsigned char flt_inf[] = { _ast_flt_inf_init }; +static const unsigned char dbl_nan[] = { _ast_dbl_nan_init }; +static const unsigned char dbl_inf[] = { _ast_dbl_inf_init }; +#ifdef _ast_ldbl_nan_init +static const unsigned char ldbl_nan[] = { _ast_ldbl_nan_init }; +static const unsigned char ldbl_inf[] = { _ast_ldbl_inf_init }; +#endif + +/* function to initialize conversion tables */ +static int sfcvinit() +{ reg int d, l; + + for(d = 0; d <= SF_MAXCHAR; ++d) + { _Sfcv36[d] = SF_RADIX; + _Sfcv64[d] = SF_RADIX; + } + + /* [0-9] */ + for(d = 0; d < 10; ++d) + { _Sfcv36[(uchar)_Sfdigits[d]] = d; + _Sfcv64[(uchar)_Sfdigits[d]] = d; + } + + /* [a-z] */ + for(; d < 36; ++d) + { _Sfcv36[(uchar)_Sfdigits[d]] = d; + _Sfcv64[(uchar)_Sfdigits[d]] = d; + } + + /* [A-Z] */ + for(l = 10; d < 62; ++l, ++d) + { _Sfcv36[(uchar)_Sfdigits[d]] = l; + _Sfcv64[(uchar)_Sfdigits[d]] = d; + } + + /* remaining digits */ + for(; d < SF_RADIX; ++d) + { _Sfcv36[(uchar)_Sfdigits[d]] = d; + _Sfcv64[(uchar)_Sfdigits[d]] = d; + } + + _Sftype['d'] = _Sftype['i'] = SFFMT_INT; + _Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT; + _Sftype['e'] = _Sftype['E'] = _Sftype['a'] = _Sftype['A'] = + _Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT; + _Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER; + _Sftype['c'] = SFFMT_CHAR; + _Sftype['['] = SFFMT_CLASS; +#if _has_multibyte + _Sftype['S'] = SFFMT_POINTER; + _Sftype['C'] = SFFMT_CHAR; +#endif + + /* IEEE floating point computed constants */ + + memcpy((char*)&_Sffnan, (char*)flt_nan, sizeof(_Sffnan)); + memcpy((char*)&_Sffinf, (char*)flt_inf, sizeof(_Sffinf)); + memcpy((char*)&_Sfdnan, (char*)dbl_nan, sizeof(_Sfdnan)); + memcpy((char*)&_Sfdinf, (char*)dbl_inf, sizeof(_Sfdinf)); +#ifdef _ast_ldbl_nan_init + memcpy((char*)&_Sflnan, (char*)ldbl_nan, sizeof(_Sflnan)); + memcpy((char*)&_Sflinf, (char*)ldbl_inf, sizeof(_Sflinf)); +#else + memcpy((char*)&_Sflnan, (char*)dbl_nan, sizeof(_Sfdnan)); + memcpy((char*)&_Sflinf, (char*)dbl_inf, sizeof(_Sfdinf)); +#endif + + return 1; +} + +/* table for floating point and integer conversions */ +#include "FEATURE/sfinit" |