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