"Fossies" - the Fresh Open Source Software Archive

Member "teapot-2.3.0/scanner.c" (6 Feb 2012, 8207 Bytes) of package /linux/privat/old/teapot-2.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "scanner.c" see the Fossies "Dox" file reference documentation.

    1 /* #includes */ /*{{{C}}}*//*{{{*/
    2 #ifndef NO_POSIX_SOURCE
    3 #undef _POSIX_SOURCE
    4 #define _POSIX_SOURCE   1
    5 #undef _POSIX_C_SOURCE
    6 #define _POSIX_C_SOURCE 2
    7 #endif
    8 
    9 #ifdef DMALLOC
   10 #include "dmalloc.h"
   11 #endif
   12 
   13 #include <assert.h>
   14 #include <ctype.h>
   15 #include <float.h>
   16 #include <limits.h>
   17 #include <stdio.h>
   18 #include <stdlib.h>
   19 extern double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
   20 #include <string.h>
   21 
   22 
   23 #include "default.h"
   24 #include "func.h"
   25 #include "main.h"
   26 #include "misc.h"
   27 #include "scanner.h"
   28 /*}}}*/
   29 
   30 /* identcode  -- return number of identifier */ /*{{{*/
   31 int identcode(const char *s, size_t len)
   32 {
   33   Tfunc *p;
   34   int fident;
   35   
   36   for (p=tfunc,fident=0; p->name[0]!='\0' && (len!=strlen(p->name) || strncmp(s,p->name,len)); ++p,++fident);
   37   if (p->name[0]=='\0') return -1;
   38   else return fident;
   39 }
   40 /*}}}*/
   41 
   42 /* charstring -- match quoted string and return token */ /*{{{*/
   43 static Token *charstring(const char **s)
   44 {
   45   const char *r;
   46 
   47   r=*s;
   48   if (**s=='"')
   49   {
   50     ++(*s);
   51     while (**s!='\0' && **s!='"') if (**s=='\\' && *((*s)+1)!='\0') (*s)+=2; else ++(*s);
   52     if (**s=='\0') { *s=r; return 0; }
   53     else 
   54     {
   55       Token *n;
   56       char *t;
   57 
   58       ++(*s);
   59       n=malloc(sizeof(Token));
   60       n->type=STRING;
   61       t=n->u.string=malloc((size_t)(*s-r));
   62       /* Clean string of quotes.  This may waste a few bytes, so? */
   63       ++r;
   64       while (r<(*s-1)) if (*r=='\\') { *t++=*(r+1); r+=2; } else *t++=*r++;
   65       *t='\0';
   66       return n;
   67     }
   68   }
   69   else return (Token*)0;
   70 }
   71 /*}}}*/
   72 /* integer    -- match an unsigned integer and return token */ /*{{{*/
   73 static Token *integer(const char **s)
   74 {
   75   const char *r;
   76   long i;
   77 
   78   r=*s;
   79   i=posnumber(r,s);
   80   if (*s!=r && **s!='.' && **s!='e')
   81   {
   82     Token *n;
   83 
   84     n=malloc(sizeof(Token));
   85     n->type=INT;
   86     n->u.integer=i;
   87     return n;
   88   }
   89   else { *s=r; return (Token*)0; }
   90 }
   91 /*}}}*/
   92 /* flt        -- match a floating point number */ /*{{{*/
   93 static Token *flt(const char **s)
   94 {
   95   /* variables */ /*{{{*/
   96   const char *t;
   97   char *end;
   98   Token *n;
   99   double x;
  100   /*}}}*/
  101 
  102   t=*s;
  103   x=strtod(t,&end);
  104   *s = end;
  105   if (t!=*s && dblfinite(x)==(const char*)0)
  106   {
  107     n=malloc(sizeof(Token));
  108     n->type=FLOAT;
  109     n->u.flt=x;
  110     return n;
  111   }
  112   else
  113   {
  114     *s=t;
  115     return (Token*)0;
  116   }
  117 }
  118 /*}}}*/
  119 /* op   -- match an op and return token */ /*{{{*/
  120 static Token *op(const char **s)
  121 {
  122   Token *n;
  123   Operator op;
  124 
  125   switch (**s)
  126   {
  127     case '+': op=PLUS; break;
  128     case '-': op=MINUS; break;
  129     case '*': op=MUL; break;
  130     case '/': op=DIV; break;
  131     case '%': op=MOD; break;
  132     case '(': op=OP; break;
  133     case ')': op=CP; break;
  134     case ',': op=COMMA; break;
  135     case '^': op=POW; break;
  136     case '<': if (*(*s+1)=='=') { ++(*s); op=LE; } else op=LT; break;
  137     case '>': if (*(*s+1)=='=') { ++(*s); op=GE; } else op=GT; break;
  138     case '=': if (*(*s+1)=='=') { ++(*s); op=ISEQUAL; } else return (Token*)0; break;
  139     case '~': if (*(*s+1)=='=') { ++(*s); op=ABOUTEQ; } else return (Token*)0; break;
  140     case '!': if (*(*s+1)=='=') { ++(*s); op=NE; } else return (Token*)0; break;
  141     default: return (Token*)0;
  142   }
  143   n=malloc(sizeof(Token));
  144   n->type=OPERATOR;
  145   n->u.op=op;
  146   ++(*s);
  147   return n;
  148 }
  149 /*}}}*/
  150 /* ident      -- match an identifier and return token */ /*{{{*/
  151 static Token *ident(const char **s)
  152 {
  153   const char *begin;
  154   Token *result;
  155   
  156   if (isalpha((int)**s) || **s=='_' || **s=='@' || **s=='&' || **s=='.' || **s=='$')
  157   {
  158     int fident;
  159 
  160     begin=*s; ++(*s);
  161     while (isalpha((int)**s) || **s=='_' || **s=='@' || **s=='&' || **s=='.' || **s=='$' || isdigit((int)**s)) ++(*s);
  162     result=malloc(sizeof(Token));
  163     if ((fident=identcode(begin,(size_t)(*s-begin)))==-1)
  164     {
  165       result->type=LIDENT;
  166       result->u.lident=malloc((size_t)(*s-begin+1));
  167       (void)strncpy(result->u.lident,begin,(size_t)(*s-begin));
  168       result->u.lident[*s-begin]='\0';
  169     }
  170     else
  171     {
  172       result->type=FIDENT;
  173       result->u.fident=fident;
  174     }
  175     return result;
  176   }
  177   return (Token*)0;
  178 }
  179 /*}}}*/
  180 
  181 /* scan       -- scan string into tokens */ /*{{{*/
  182 Token **scan(const char **s)
  183 {
  184   /* variables */ /*{{{*/
  185   Token **na,*n;
  186   const char *r;
  187   int i,j;
  188   /*}}}*/
  189 
  190   /* compute number of tokens */ /*{{{*/
  191   r=*s;
  192   while (*r==' ') ++r;
  193   for (i=0; *r!='\0'; ++i)
  194   {
  195     const char *or;
  196 
  197     or=r;
  198     while (*r==' ') ++r;  
  199     n=charstring(&r);
  200     if (n==(Token*)0) n=op(&r);
  201     if (n==(Token*)0) n=integer(&r);
  202     if (n==(Token*)0) n=flt(&r);
  203     if (n==(Token*)0) n=ident(&r);
  204     if (or==r) { *s=r; return (Token**)0; }
  205   }
  206   /*}}}*/
  207   /* allocate token space */ /*{{{*/
  208   na=malloc(sizeof(Token*)*(i+1));
  209   /*}}}*/
  210   /* store tokens */ /*{{{*/
  211   r=*s;
  212   while (*r==' ') ++r;
  213   for (j=0; j<i; ++j) 
  214   {
  215     while (*r==' ') ++r;    
  216     n=charstring(&r);
  217     if (n==(Token*)0) n=op(&r);  
  218     if (n==(Token*)0) n=integer(&r);
  219     if (n==(Token*)0) n=flt(&r);
  220     if (n==(Token*)0) n=ident(&r);
  221     na[j]=n;
  222   }
  223   na[j]=(Token*)0;
  224   /*}}}*/
  225   return na;
  226 }
  227 /*}}}*/
  228 /* print      -- print token sequence */ /*{{{*/
  229 void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n)
  230 {
  231   size_t cur;
  232   
  233   cur=0;
  234   if (n!=(Token**)0) for (; cur<size-1 && (*n)!=(Token*)0; ++n) switch ((*n)->type)
  235   {
  236     /* EMPTY */ /*{{{*/
  237     case EMPTY: assert(cur==0); *(s+cur)='\0'; ++cur; break;
  238     /*}}}*/
  239     /* STRING */ /*{{{*/
  240     case STRING:
  241     {
  242       char *str=(*n)->u.string;
  243 
  244       if (quote)
  245       {
  246         *(s+cur)='"';
  247         ++cur;
  248       }
  249       while (cur<size && *str!='\0') 
  250       {
  251         if (quote) if (*str=='"' || *str=='\\') *(s+cur++)='\\';
  252         if (cur<size) *(s+cur++)=*str;
  253         ++str;
  254       }
  255       if (quote)
  256       {
  257         if (cur<size) *(s+cur)='"';
  258         ++cur;
  259       }
  260       break;
  261     }
  262     /*}}}*/
  263     /* INT */ /*{{{*/
  264     case INT:
  265     {
  266       char buf[20];
  267       size_t buflen;
  268 
  269       buflen=sprintf(buf,"%ld",(*n)->u.integer);
  270       assert(buflen<sizeof(buf));
  271       (void)strncpy(s+cur,buf,size-cur-1);
  272       cur+=buflen;
  273       break;
  274     }  
  275     /*}}}*/
  276     /* FLOAT */ /*{{{*/
  277     case FLOAT:
  278     {
  279       /* variables */ /*{{{*/
  280       char buf[1024],*p;
  281       size_t len;
  282       /*}}}*/
  283 
  284       len=sprintf(buf,scientific ? "%.*e" : "%.*f",precision==-1 ? DBL_DIG-2 : precision, (*n)->u.flt);
  285       assert(len<sizeof(buf));
  286       if (!scientific && precision==-1)
  287       {
  288         p=&buf[len-1];
  289         while (p>buf && *p=='0' && *(p-1)!='.') { *p='\0'; --p; --len; }
  290       }
  291       p=buf+len;
  292       while (*--p==' ') { *p='\0'; --len; }
  293       (void)strncpy(s+cur,buf,size-cur-1);
  294       cur+=len;
  295       break;
  296     }
  297     /*}}}*/
  298     /* OPERATOR */ /*{{{*/
  299     case OPERATOR:
  300     {
  301       static const char *ops[]={ "+", "-", "*", "/", "(", ")", ",", "<", "<=", ">=", ">", "==", "~=", "!=", "^", "%" };
  302       
  303       if ((size-cur)>1) *(s+cur++)=*ops[(*n)->u.op];
  304       if (*(ops[(*n)->u.op]+1) && (size-cur)>1) *(s+cur++)=*(ops[(*n)->u.op]+1);
  305       break;
  306     }
  307     /*}}}*/
  308     /* LIDENT */ /*{{{*/
  309     case LIDENT:
  310     {
  311       size_t identlen;
  312 
  313       identlen=strlen((*n)->u.lident);
  314       if ((cur+identlen+1)<=size) strcpy(s+cur,(*n)->u.lident);
  315       else (void)strncpy(s+cur,(*n)->u.lident,size-cur-1);  
  316       cur+=identlen;
  317       break;
  318     }
  319     /*}}}*/
  320     /* FIDENT */ /*{{{*/
  321     case FIDENT:
  322     {
  323       size_t identlen;
  324 
  325       identlen=strlen(tfunc[(*n)->u.fident].name);
  326       if ((cur+identlen+1)<=size) strcpy(s+cur,tfunc[(*n)->u.fident].name);
  327       else (void)strncpy(s+cur,tfunc[(*n)->u.fident].name,size-cur-1);  
  328       cur+=identlen;
  329       break;
  330     }
  331     /*}}}*/
  332     /* LOCATION */ /*{{{*/
  333     case LOCATION:
  334     {
  335       char buf[60];
  336 
  337       sprintf(buf,"&(%d,%d,%d)",(*n)->u.location[0],(*n)->u.location[1],(*n)->u.location[2]);
  338       (void)strncpy(s+cur,buf,size-cur-1);
  339       cur+=strlen(buf);
  340       break;
  341     }
  342     /*}}}*/
  343     /* EEK */ /*{{{*/
  344     case EEK:
  345     {
  346       (void)strncpy(s+cur,_("ERROR"),size-cur-1);
  347       cur+=5;
  348       break;
  349     }
  350     /*}}}*/
  351     /* default */ /*{{{*/
  352     default: assert(0);
  353     /*}}}*/
  354   }
  355   if (cur<size) s[cur] = 0;
  356   else s[size-1] = 0;
  357   if (chars && mbslen(s) > chars) {
  358     for (cur=0; cur < chars; ++cur) s[cur] = '#';
  359     s[cur] = 0;
  360   }
  361 }
  362 /*}}}*/