summaryrefslogtreecommitdiff
path: root/src/lib/libast/sfio/sftable.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/sfio/sftable.c
downloadksh-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.c543
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"