Blob


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