URI:
       tsx.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tsx.c (3316B)
       ---
            1 #include "a.h"
            2 
            3 Sx *Brdsx1(Biobuf*);
            4 
            5 Sx*
            6 Brdsx(Biobuf *b)
            7 {
            8         Sx **sx, *x;
            9         int nsx;
           10 
           11         nsx = 0;
           12         sx = nil;
           13         while((x = Brdsx1(b)) != nil){
           14                 sx = erealloc(sx, (nsx+1)*sizeof sx[0]);
           15                 sx[nsx++] = x;
           16         }
           17         x = emalloc(sizeof *x);
           18         x->sx = sx;
           19         x->nsx = nsx;
           20         x->type = SxList;
           21         return x;
           22 }
           23 
           24 int
           25 sxwalk(Sx *sx)
           26 {
           27         int i, n;
           28 
           29         if(sx == nil)
           30                 return 1;
           31         switch(sx->type){
           32         default:
           33         case SxAtom:
           34         case SxString:
           35         case SxNumber:
           36                 return 1;
           37         case SxList:
           38                 n = 0;
           39                 for(i=0; i<sx->nsx; i++)
           40                         n += sxwalk(sx->sx[i]);
           41                 return n;
           42         }
           43 }
           44 
           45 void
           46 freesx(Sx *sx)
           47 {
           48         int i;
           49 
           50         if(sx == nil)
           51                 return;
           52         switch(sx->type){
           53         case SxAtom:
           54         case SxString:
           55                 free(sx->data);
           56                 break;
           57         case SxList:
           58                 for(i=0; i<sx->nsx; i++)
           59                         freesx(sx->sx[i]);
           60                 free(sx->sx);
           61                 break;
           62         }
           63         free(sx);
           64 }
           65 
           66 Sx*
           67 Brdsx1(Biobuf *b)
           68 {
           69         int c, len, nbr;
           70         char *s;
           71         vlong n;
           72         Sx *x;
           73 
           74         c = Bgetc(b);
           75         if(c == ' ')
           76                 c = Bgetc(b);
           77         if(c < 0)
           78                 return nil;
           79         if(c == '\r')
           80                 c = Bgetc(b);
           81         if(c == '\n')
           82                 return nil;
           83         if(c == ')'){        /* end of list */
           84                 Bungetc(b);
           85                 return nil;
           86         }
           87         if(c == '('){        /* parenthesized list */
           88                 x = Brdsx(b);
           89                 c = Bgetc(b);
           90                 if(c != ')')        /* oops! not good */
           91                         Bungetc(b);
           92                 return x;
           93         }
           94         if(c == '{'){        /* length-prefixed string */
           95                 len = 0;
           96                 while((c = Bgetc(b)) >= 0 && isdigit(c))
           97                         len = len*10 + c-'0';
           98                 if(c != '}')        /* oops! not good */
           99                         Bungetc(b);
          100                 c = Bgetc(b);
          101                 if(c != '\r')        /* oops! not good */
          102                         ;
          103                 c = Bgetc(b);
          104                 if(c != '\n')        /* oops! not good */
          105                         ;
          106                 x = emalloc(sizeof *x);
          107                 x->data = emalloc(len+1);
          108                 if(Bread(b, x->data, len) != len)
          109                         ;        /* oops! */
          110                 x->data[len] = 0;
          111                 x->ndata = len;
          112                 x->type = SxString;
          113                 return x;
          114         }
          115         if(c == '"'){        /* quoted string */
          116                 s = nil;
          117                 len = 0;
          118                 while((c = Bgetc(b)) >= 0 && c != '"'){
          119                         if(c == '\\')
          120                                 c = Bgetc(b);
          121                         s = erealloc(s, len+1);
          122                         s[len++] = c;
          123                 }
          124                 s = erealloc(s, len+1);
          125                 s[len] = 0;
          126                 x = emalloc(sizeof *x);
          127                 x->data = s;
          128                 x->ndata = len;
          129                 x->type = SxString;
          130                 return x;
          131         }
          132         if(isdigit(c)){        /* number */
          133                 n = c-'0';;
          134                 while((c = Bgetc(b)) >= 0 && isdigit(c))
          135                         n = n*10 + c-'0';
          136                 Bungetc(b);
          137                 x = emalloc(sizeof *x);
          138                 x->number = n;
          139                 x->type = SxNumber;
          140                 return x;
          141         }
          142         /* atom */
          143         len = 1;
          144         s = emalloc(1);
          145         s[0] = c;
          146         nbr = 0;
          147         while((c = Bgetc(b)) >= 0 && c > ' ' && !strchr("(){}", c)){
          148                 /* allow embedded brackets as in BODY[] */
          149                 if(c == '['){
          150                         if(s[0] == '[')
          151                                 break;
          152                         else
          153                                 nbr++;
          154                 }
          155                 if(c == ']'){
          156                         if(nbr > 0)
          157                                 nbr--;
          158                         else
          159                                 break;
          160                 }
          161                 s = erealloc(s, len+1);
          162                 s[len++] = c;
          163         }
          164         if(c != ' ')
          165                 Bungetc(b);
          166         s = erealloc(s, len+1);
          167         s[len] = 0;
          168         x = emalloc(sizeof *x);
          169         x->type = SxAtom;
          170         x->data = s;
          171         x->ndata = len;
          172         return x;
          173 }
          174 
          175 int
          176 sxfmt(Fmt *fmt)
          177 {
          178         int i, paren;
          179         Sx *sx;
          180 
          181         sx = va_arg(fmt->args, Sx*);
          182         if(sx == nil)
          183                 return 0;
          184 
          185         switch(sx->type){
          186         case SxAtom:
          187         case SxString:
          188                 return fmtprint(fmt, "%q", sx->data);
          189 
          190         case SxNumber:
          191                 return fmtprint(fmt, "%lld", sx->number);
          192 
          193         case SxList:
          194                 paren = !(fmt->flags&FmtSharp);
          195                 if(paren)
          196                         fmtrune(fmt, '(');
          197                 for(i=0; i<sx->nsx; i++){
          198                         if(i)
          199                                 fmtrune(fmt, ' ');
          200                         fmtprint(fmt, "%$", sx->sx[i]);
          201                 }
          202                 if(paren)
          203                         return fmtrune(fmt, ')');
          204                 return 0;
          205 
          206         default:
          207                 return fmtstrcpy(fmt, "?");
          208         }
          209 }
          210 
          211 int
          212 oksx(Sx *sx)
          213 {
          214         return sx->nsx >= 2
          215                 && sx->sx[1]->type == SxAtom
          216                 && cistrcmp(sx->sx[1]->data, "OK") == 0;
          217 }