xref: /plan9/sys/src/cmd/postscript/tr2post/Bgetfield.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include <u.h>
2*219b2ee8SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <bio.h>
4*219b2ee8SDavid du Colombier #include "../common/common.h"
5*219b2ee8SDavid du Colombier #include "tr2post.h"
6*219b2ee8SDavid du Colombier 
7*219b2ee8SDavid du Colombier int
8*219b2ee8SDavid du Colombier isspace(Rune r)
9*219b2ee8SDavid du Colombier {
10*219b2ee8SDavid du Colombier 	return(r==' ' || r=='\t' || r=='\n' || r == '\r' || r=='\f');
11*219b2ee8SDavid du Colombier }
12*219b2ee8SDavid du Colombier 
13*219b2ee8SDavid du Colombier int
14*219b2ee8SDavid du Colombier Bskipws(Biobufhdr *bp) {
15*219b2ee8SDavid du Colombier 	int r;
16*219b2ee8SDavid du Colombier 	char c[UTFmax];
17*219b2ee8SDavid du Colombier 	int sindex = 0;
18*219b2ee8SDavid du Colombier 
19*219b2ee8SDavid du Colombier 	/* skip over initial white space */
20*219b2ee8SDavid du Colombier 	do {
21*219b2ee8SDavid du Colombier 		r = Bgetrune(bp);
22*219b2ee8SDavid du Colombier 		if (r == '\n') inputlineno++;
23*219b2ee8SDavid du Colombier 		sindex++;
24*219b2ee8SDavid du Colombier 	} while (r>=0 && isspace(r));
25*219b2ee8SDavid du Colombier 	if (r<0) {
26*219b2ee8SDavid du Colombier 		return(-1);
27*219b2ee8SDavid du Colombier 	} else if (!isspace(r)) {
28*219b2ee8SDavid du Colombier 		Bungetrune(bp);
29*219b2ee8SDavid du Colombier 		--sindex;
30*219b2ee8SDavid du Colombier 	}
31*219b2ee8SDavid du Colombier 	return(sindex);
32*219b2ee8SDavid du Colombier }
33*219b2ee8SDavid du Colombier 
34*219b2ee8SDavid du Colombier int
35*219b2ee8SDavid du Colombier asc2dig(char c, int base) {
36*219b2ee8SDavid du Colombier 	if (c >= '0' && c <= '9')
37*219b2ee8SDavid du Colombier 		if (base == 8 && c > '7') return(-1);
38*219b2ee8SDavid du Colombier 		else return(c - '0');
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier 	if (base == 16)
41*219b2ee8SDavid du Colombier 		if (c >= 'a' && c <= 'f') return(10 + c - 'a');
42*219b2ee8SDavid du Colombier 		else if (c >= 'A' && c <= 'F') return(10 + c - 'A');
43*219b2ee8SDavid du Colombier 
44*219b2ee8SDavid du Colombier 	return(-1);
45*219b2ee8SDavid du Colombier }
46*219b2ee8SDavid du Colombier 
47*219b2ee8SDavid du Colombier /* get a string of type: "d" for decimal integer, "u" for unsigned,
48*219b2ee8SDavid du Colombier  * "s" for string", "c" for char,
49*219b2ee8SDavid du Colombier  * return the number of characters gotten for the field.  If nothing
50*219b2ee8SDavid du Colombier  * was gotten and the end of file was reached, a negative value
51*219b2ee8SDavid du Colombier  * from the Bgetrune is returned.
52*219b2ee8SDavid du Colombier  */
53*219b2ee8SDavid du Colombier 
54*219b2ee8SDavid du Colombier int
55*219b2ee8SDavid du Colombier Bgetfield(Biobufhdr *bp, int type, void *thing, int size) {
56*219b2ee8SDavid du Colombier 	int r;
57*219b2ee8SDavid du Colombier 	Rune R;
58*219b2ee8SDavid du Colombier 	char c[UTFmax];
59*219b2ee8SDavid du Colombier 	int sindex = 0, i, j, n = 0;
60*219b2ee8SDavid du Colombier 	int negate = 0;
61*219b2ee8SDavid du Colombier 	int base = 10;
62*219b2ee8SDavid du Colombier 	BOOLEAN bailout = FALSE;
63*219b2ee8SDavid du Colombier 	int dig;
64*219b2ee8SDavid du Colombier 	unsigned int u = 0;
65*219b2ee8SDavid du Colombier 
66*219b2ee8SDavid du Colombier 	/* skip over initial white space */
67*219b2ee8SDavid du Colombier 	if (Bskipws(bp) < 0)
68*219b2ee8SDavid du Colombier 		return(-1);
69*219b2ee8SDavid du Colombier 
70*219b2ee8SDavid du Colombier 	switch (type) {
71*219b2ee8SDavid du Colombier 	case 'd':
72*219b2ee8SDavid du Colombier 		while (!bailout && (r = Bgetrune(bp))>=0) {
73*219b2ee8SDavid du Colombier 			switch (sindex++) {
74*219b2ee8SDavid du Colombier 			case 0:
75*219b2ee8SDavid du Colombier 				switch (r) {
76*219b2ee8SDavid du Colombier 				case '-':
77*219b2ee8SDavid du Colombier 					negate = 1;
78*219b2ee8SDavid du Colombier 					continue;
79*219b2ee8SDavid du Colombier 				case '+':
80*219b2ee8SDavid du Colombier 					continue;
81*219b2ee8SDavid du Colombier 				case '0':
82*219b2ee8SDavid du Colombier 					base = 8;
83*219b2ee8SDavid du Colombier 					continue;
84*219b2ee8SDavid du Colombier 				default:
85*219b2ee8SDavid du Colombier 					break;
86*219b2ee8SDavid du Colombier 				}
87*219b2ee8SDavid du Colombier 				break;
88*219b2ee8SDavid du Colombier 			case 1:
89*219b2ee8SDavid du Colombier 				if ((r == 'x' || r == 'X') && base == 8) {
90*219b2ee8SDavid du Colombier 					base = 16;
91*219b2ee8SDavid du Colombier 					continue;
92*219b2ee8SDavid du Colombier 				}
93*219b2ee8SDavid du Colombier 			}
94*219b2ee8SDavid du Colombier 			if ((dig = asc2dig(r, base)) == -1) bailout = TRUE;
95*219b2ee8SDavid du Colombier 			else n = dig + (n * base);
96*219b2ee8SDavid du Colombier 		}
97*219b2ee8SDavid du Colombier 		if (r < 0) return(-1);
98*219b2ee8SDavid du Colombier 		*(int *)thing = (negate)?-n:n;
99*219b2ee8SDavid du Colombier 		Bungetrune(bp);
100*219b2ee8SDavid du Colombier 		break;
101*219b2ee8SDavid du Colombier 	case 'u':
102*219b2ee8SDavid du Colombier 		while (!bailout && (r = Bgetrune(bp))>=0) {
103*219b2ee8SDavid du Colombier 			switch (sindex++) {
104*219b2ee8SDavid du Colombier 			case 0:
105*219b2ee8SDavid du Colombier 				if (*c == '0') {
106*219b2ee8SDavid du Colombier 					base = 8;
107*219b2ee8SDavid du Colombier 					continue;
108*219b2ee8SDavid du Colombier 				}
109*219b2ee8SDavid du Colombier 				break;
110*219b2ee8SDavid du Colombier 			case 1:
111*219b2ee8SDavid du Colombier 				if ((r == 'x' || r == 'X') && base == 8) {
112*219b2ee8SDavid du Colombier 					base = 16;
113*219b2ee8SDavid du Colombier 					continue;
114*219b2ee8SDavid du Colombier 				}
115*219b2ee8SDavid du Colombier 			}
116*219b2ee8SDavid du Colombier 			if ((dig = asc2dig(r, base)) == -1) bailout = TRUE;
117*219b2ee8SDavid du Colombier 			else u = dig + (n * base);
118*219b2ee8SDavid du Colombier 		}
119*219b2ee8SDavid du Colombier 		*(int *)thing = u;
120*219b2ee8SDavid du Colombier 		if (r < 0) return(-1);
121*219b2ee8SDavid du Colombier 		Bungetrune(bp);
122*219b2ee8SDavid du Colombier 		break;
123*219b2ee8SDavid du Colombier 	case 's':
124*219b2ee8SDavid du Colombier 		j = 0;
125*219b2ee8SDavid du Colombier 		while ((size>j+UTFmax) && (r = Bgetrune(bp))>=0 && !isspace(r)) {
126*219b2ee8SDavid du Colombier 			R = r;
127*219b2ee8SDavid du Colombier 			i = runetochar(&(((char *)thing)[j]), &R);
128*219b2ee8SDavid du Colombier 			j += i;
129*219b2ee8SDavid du Colombier 			sindex++;
130*219b2ee8SDavid du Colombier 		}
131*219b2ee8SDavid du Colombier 		((char *)thing)[j++] = '\0';
132*219b2ee8SDavid du Colombier 		if (r < 0) return(-1);
133*219b2ee8SDavid du Colombier 		Bungetrune(bp);
134*219b2ee8SDavid du Colombier 		break;
135*219b2ee8SDavid du Colombier 	case 'r':
136*219b2ee8SDavid du Colombier 		if ((r = Bgetrune(bp))>=0) {
137*219b2ee8SDavid du Colombier 			*(Rune *)thing = r;
138*219b2ee8SDavid du Colombier 			sindex++;
139*219b2ee8SDavid du Colombier 			return(sindex);
140*219b2ee8SDavid du Colombier 		}
141*219b2ee8SDavid du Colombier 		if (r <= 0) return(-1);
142*219b2ee8SDavid du Colombier 		Bungetrune(bp);
143*219b2ee8SDavid du Colombier 		break;
144*219b2ee8SDavid du Colombier 	default:
145*219b2ee8SDavid du Colombier 		return(-2);
146*219b2ee8SDavid du Colombier 	}
147*219b2ee8SDavid du Colombier 	if (r < 0 && sindex == 0)
148*219b2ee8SDavid du Colombier 		return(r);
149*219b2ee8SDavid du Colombier 	else if (bailout && sindex == 1) {
150*219b2ee8SDavid du Colombier 		return(0);
151*219b2ee8SDavid du Colombier 	} else
152*219b2ee8SDavid du Colombier 		return(sindex);
153*219b2ee8SDavid du Colombier }
154