Blob
1 #include "a.h"3 Sx *Brdsx1(Biobuf*);5 Sx*6 Brdsx(Biobuf *b)7 {8 Sx **sx, *x;9 int nsx;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 }24 int25 sxwalk(Sx *sx)26 {27 int i, n;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 }45 void46 freesx(Sx *sx)47 {48 int i;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 }66 Sx*67 Brdsx1(Biobuf *b)68 {69 int c, len, nbr;70 char *s;71 vlong n;72 Sx *x;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 else153 nbr++;154 }155 if(c == ']'){156 if(nbr > 0)157 nbr--;158 else159 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 }175 int176 sxfmt(Fmt *fmt)177 {178 int i, paren;179 Sx *sx;181 sx = va_arg(fmt->args, Sx*);182 if(sx == nil)183 return 0;185 switch(sx->type){186 case SxAtom:187 case SxString:188 return fmtprint(fmt, "%q", sx->data);190 case SxNumber:191 return fmtprint(fmt, "%lld", sx->number);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;206 default:207 return fmtstrcpy(fmt, "?");208 }209 }211 int212 oksx(Sx *sx)213 {214 return sx->nsx >= 2215 && sx->sx[1]->type == SxAtom216 && cistrcmp(sx->sx[1]->data, "OK") == 0;217 }