plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

sx.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 }