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 int
25 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 void
46 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 */
103 c = Bgetc(b);
104 if(c != '\n') /* oops! not good */
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;
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;
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;
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;
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++;
155 if(c == ']'){
156 if(nbr > 0)
157 nbr--;
158 else
159 break;
161 s = erealloc(s, len+1);
162 s[len++] = c;
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;
175 int
176 sxfmt(Fmt *fmt)
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]);
202 if(paren)
203 return fmtrune(fmt, ')');
204 return 0;
206 default:
207 return fmtstrcpy(fmt, "?");
211 int
212 oksx(Sx *sx)
214 return sx->nsx >= 2
215 && sx->sx[1]->type == SxAtom
216 && cistrcmp(sx->sx[1]->data, "OK") == 0;