xref: /plan9/sys/src/cmd/postscript/tr2post/Bgetfield.c (revision 456a8764e4ea95d7aa2c2cf34e5112293070bc84)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include "../common/common.h"
5219b2ee8SDavid du Colombier #include "tr2post.h"
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier int
isspace(Rune r)8219b2ee8SDavid du Colombier isspace(Rune r)
9219b2ee8SDavid du Colombier {
10*456a8764SDavid du Colombier  	return r==' ' || r=='\t' || r=='\n' || r=='\r' || r=='\f';
11219b2ee8SDavid du Colombier }
12219b2ee8SDavid du Colombier 
13219b2ee8SDavid du Colombier int
Bskipws(Biobufhdr * bp)14219b2ee8SDavid du Colombier Bskipws(Biobufhdr *bp) {
15*456a8764SDavid du Colombier 	int r, sindex = 0;
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier 	/* skip over initial white space */
18219b2ee8SDavid du Colombier 	do {
19219b2ee8SDavid du Colombier 		r = Bgetrune(bp);
20*456a8764SDavid du Colombier 		if (r == '\n')
21*456a8764SDavid du Colombier 			inputlineno++;
22219b2ee8SDavid du Colombier 		sindex++;
23219b2ee8SDavid du Colombier 	} while (r>=0 && isspace(r));
24*456a8764SDavid du Colombier 	if (r<0)
25219b2ee8SDavid du Colombier 		return(-1);
26*456a8764SDavid du Colombier 	else if (!isspace(r)) {
27219b2ee8SDavid du Colombier 		Bungetrune(bp);
28219b2ee8SDavid du Colombier 		--sindex;
29219b2ee8SDavid du Colombier 	}
30*456a8764SDavid du Colombier 	return sindex;
31219b2ee8SDavid du Colombier }
32219b2ee8SDavid du Colombier 
33219b2ee8SDavid du Colombier int
asc2dig(char c,int base)34219b2ee8SDavid du Colombier asc2dig(char c, int base) {
35219b2ee8SDavid du Colombier 	if (c >= '0' && c <= '9')
36*456a8764SDavid du Colombier 		if (base == 8 && c > '7')
37*456a8764SDavid du Colombier 			return(-1);
38*456a8764SDavid du Colombier 		else
39*456a8764SDavid du Colombier 			return(c - '0');
40219b2ee8SDavid du Colombier 	if (base == 16)
41*456a8764SDavid du Colombier 		if (c >= 'a' && c <= 'f')
42*456a8764SDavid du Colombier 			return(10 + c - 'a');
43*456a8764SDavid du Colombier 		else if (c >= 'A' && c <= 'F')
44*456a8764SDavid du Colombier 			return(10 + c - 'A');
45219b2ee8SDavid du Colombier 	return(-1);
46219b2ee8SDavid du Colombier }
47219b2ee8SDavid du Colombier 
48*456a8764SDavid du Colombier /*
49*456a8764SDavid du Colombier  * get a string of type: "d" for decimal integer, "u" for unsigned,
50219b2ee8SDavid du Colombier  * "s" for string", "c" for char,
51219b2ee8SDavid du Colombier  * return the number of characters gotten for the field.  If nothing
52219b2ee8SDavid du Colombier  * was gotten and the end of file was reached, a negative value
53219b2ee8SDavid du Colombier  * from the Bgetrune is returned.
54219b2ee8SDavid du Colombier  */
55219b2ee8SDavid du Colombier 
56219b2ee8SDavid du Colombier int
Bgetfield(Biobufhdr * bp,int type,void * thing,int size)57219b2ee8SDavid du Colombier Bgetfield(Biobufhdr *bp, int type, void *thing, int size) {
58219b2ee8SDavid du Colombier 	int base = 10;
59219b2ee8SDavid du Colombier 	int dig;
60*456a8764SDavid du Colombier 	int negate = 0;
61*456a8764SDavid du Colombier 	int sindex = 0, i, j, n = 0;
62*456a8764SDavid du Colombier 	long r;
63*456a8764SDavid du Colombier 	Rune R;
64*456a8764SDavid du Colombier 	unsigned u = 0;
65*456a8764SDavid du Colombier 	BOOLEAN bailout = FALSE;
66*456a8764SDavid du Colombier 	char c[UTFmax];
67219b2ee8SDavid du Colombier 
68219b2ee8SDavid du Colombier 	/* skip over initial white space */
69219b2ee8SDavid du Colombier 	if (Bskipws(bp) < 0)
70219b2ee8SDavid du Colombier 		return(-1);
71219b2ee8SDavid du Colombier 
72*456a8764SDavid du Colombier 	r = 0;
73219b2ee8SDavid du Colombier 	switch (type) {
74219b2ee8SDavid du Colombier 	case 'd':
75219b2ee8SDavid du Colombier 		while (!bailout && (r = Bgetrune(bp))>=0) {
76219b2ee8SDavid du Colombier 			switch (sindex++) {
77219b2ee8SDavid du Colombier 			case 0:
78219b2ee8SDavid du Colombier 				switch (r) {
79219b2ee8SDavid du Colombier 				case '-':
80219b2ee8SDavid du Colombier 					negate = 1;
81219b2ee8SDavid du Colombier 					continue;
82219b2ee8SDavid du Colombier 				case '+':
83219b2ee8SDavid du Colombier 					continue;
84219b2ee8SDavid du Colombier 				case '0':
85219b2ee8SDavid du Colombier 					base = 8;
86219b2ee8SDavid du Colombier 					continue;
87219b2ee8SDavid du Colombier 				default:
88219b2ee8SDavid du Colombier 					break;
89219b2ee8SDavid du Colombier 				}
90219b2ee8SDavid du Colombier 				break;
91219b2ee8SDavid du Colombier 			case 1:
92219b2ee8SDavid du Colombier 				if ((r == 'x' || r == 'X') && base == 8) {
93219b2ee8SDavid du Colombier 					base = 16;
94219b2ee8SDavid du Colombier 					continue;
95219b2ee8SDavid du Colombier 				}
96*456a8764SDavid du Colombier 				break;
97219b2ee8SDavid du Colombier 			}
98*456a8764SDavid du Colombier 			if ((dig = asc2dig(r, base)) == -1)
99*456a8764SDavid du Colombier 				bailout = TRUE;
100*456a8764SDavid du Colombier 			else
101*456a8764SDavid du Colombier 				n = dig + (n * base);
102219b2ee8SDavid du Colombier 		}
103*456a8764SDavid du Colombier 		if (r < 0)
104*456a8764SDavid du Colombier 			return(-1);
105219b2ee8SDavid du Colombier 		*(int *)thing = (negate)?-n:n;
106219b2ee8SDavid du Colombier 		Bungetrune(bp);
107219b2ee8SDavid du Colombier 		break;
108219b2ee8SDavid du Colombier 	case 'u':
109219b2ee8SDavid du Colombier 		while (!bailout && (r = Bgetrune(bp))>=0) {
110219b2ee8SDavid du Colombier 			switch (sindex++) {
111219b2ee8SDavid du Colombier 			case 0:
112219b2ee8SDavid du Colombier 				if (*c == '0') {
113219b2ee8SDavid du Colombier 					base = 8;
114219b2ee8SDavid du Colombier 					continue;
115219b2ee8SDavid du Colombier 				}
116219b2ee8SDavid du Colombier 				break;
117219b2ee8SDavid du Colombier 			case 1:
118219b2ee8SDavid du Colombier 				if ((r == 'x' || r == 'X') && base == 8) {
119219b2ee8SDavid du Colombier 					base = 16;
120219b2ee8SDavid du Colombier 					continue;
121219b2ee8SDavid du Colombier 				}
122*456a8764SDavid du Colombier 				break;
123219b2ee8SDavid du Colombier 			}
124*456a8764SDavid du Colombier 			if ((dig = asc2dig(r, base)) == -1)
125*456a8764SDavid du Colombier 				bailout = TRUE;
126*456a8764SDavid du Colombier 			else
127*456a8764SDavid du Colombier 				u = dig + (n * base);
128219b2ee8SDavid du Colombier 		}
129219b2ee8SDavid du Colombier 		*(int *)thing = u;
130*456a8764SDavid du Colombier 		if (r < 0)
131*456a8764SDavid du Colombier 			return(-1);
132219b2ee8SDavid du Colombier 		Bungetrune(bp);
133219b2ee8SDavid du Colombier 		break;
134219b2ee8SDavid du Colombier 	case 's':
135219b2ee8SDavid du Colombier 		j = 0;
136*456a8764SDavid du Colombier 		while (size > j+UTFmax && (r = Bgetrune(bp)) >= 0 &&
137*456a8764SDavid du Colombier 		    !isspace(r)) {
138219b2ee8SDavid du Colombier 			R = r;
139219b2ee8SDavid du Colombier 			i = runetochar(&(((char *)thing)[j]), &R);
140219b2ee8SDavid du Colombier 			j += i;
141219b2ee8SDavid du Colombier 			sindex++;
142219b2ee8SDavid du Colombier 		}
143*456a8764SDavid du Colombier 		((char *)thing)[j] = '\0';
144*456a8764SDavid du Colombier 		if (r < 0)
145*456a8764SDavid du Colombier 			return(-1);
146219b2ee8SDavid du Colombier 		Bungetrune(bp);
147219b2ee8SDavid du Colombier 		break;
148219b2ee8SDavid du Colombier 	case 'r':
149219b2ee8SDavid du Colombier 		if ((r = Bgetrune(bp))>=0) {
150219b2ee8SDavid du Colombier 			*(Rune *)thing = r;
151219b2ee8SDavid du Colombier 			sindex++;
152219b2ee8SDavid du Colombier 			return(sindex);
153219b2ee8SDavid du Colombier 		}
154*456a8764SDavid du Colombier 		if (r <= 0)
155*456a8764SDavid du Colombier 			return(-1);
156219b2ee8SDavid du Colombier 		Bungetrune(bp);
157219b2ee8SDavid du Colombier 		break;
158219b2ee8SDavid du Colombier 	default:
159219b2ee8SDavid du Colombier 		return(-2);
160219b2ee8SDavid du Colombier 	}
161219b2ee8SDavid du Colombier 	if (r < 0 && sindex == 0)
162219b2ee8SDavid du Colombier 		return(r);
163219b2ee8SDavid du Colombier 	else if (bailout && sindex == 1) {
164219b2ee8SDavid du Colombier 		return(0);
165219b2ee8SDavid du Colombier 	} else
166219b2ee8SDavid du Colombier 		return(sindex);
167219b2ee8SDavid du Colombier }
168