Logo Search packages:      
Sourcecode: ksh version File versions  Download package

sftable.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1985-2009 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              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 */
      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"

Generated by  Doxygen 1.6.0   Back to index