blob: fc0dfc139520b0a5f16df61d024e172b4397967e [file] [log] [blame]
rsc61f5c352004-05-15 23:55:53 +00001#include <u.h>
2#include <libc.h>
3#include <bio.h>
4#include "../common/common.h"
5#include "tr2post.h"
6
wkje8fb1d32004-05-17 02:24:15 +00007#undef isspace
8#define isspace risspace
9
rsc61f5c352004-05-15 23:55:53 +000010int
11isspace(Rune r)
12{
13 return(r==' ' || r=='\t' || r=='\n' || r == '\r' || r=='\f');
14}
15
16int
wkje8fb1d32004-05-17 02:24:15 +000017Bskipws(Biobuf *bp) {
rsc61f5c352004-05-15 23:55:53 +000018 int r;
rsc61f5c352004-05-15 23:55:53 +000019 int sindex = 0;
20
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}
35
36int
37asc2dig(char c, int base) {
wkjb8551482004-05-16 07:54:22 +000038 if (c >= '0' && c <= '9'){
rsc61f5c352004-05-15 23:55:53 +000039 if (base == 8 && c > '7') return(-1);
40 else return(c - '0');
wkjb8551482004-05-16 07:54:22 +000041 }
rsc61f5c352004-05-15 23:55:53 +000042
wkjb8551482004-05-16 07:54:22 +000043 if (base == 16){
rsc61f5c352004-05-15 23:55:53 +000044 if (c >= 'a' && c <= 'f') return(10 + c - 'a');
45 else if (c >= 'A' && c <= 'F') return(10 + c - 'A');
wkjb8551482004-05-16 07:54:22 +000046 }
rsc61f5c352004-05-15 23:55:53 +000047
48 return(-1);
49}
50
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 */
57
58int
wkje8fb1d32004-05-17 02:24:15 +000059Bgetfield(Biobuf *bp, int type, void *thing, int size) {
rsc61f5c352004-05-15 23:55:53 +000060 int r;
61 Rune R;
62 char c[UTFmax];
63 int sindex = 0, i, j, n = 0;
64 int negate = 0;
65 int base = 10;
66 BOOLEAN bailout = FALSE;
67 int dig;
68 unsigned int u = 0;
69
wkje8fb1d32004-05-17 02:24:15 +000070 r = 0;
71
rsc61f5c352004-05-15 23:55:53 +000072 /* skip over initial white space */
73 if (Bskipws(bp) < 0)
74 return(-1);
75
76 switch (type) {
77 case 'd':
78 while (!bailout && (r = Bgetrune(bp))>=0) {
79 switch (sindex++) {
80 case 0:
81 switch (r) {
82 case '-':
83 negate = 1;
84 continue;
85 case '+':
86 continue;
87 case '0':
88 base = 8;
89 continue;
90 default:
91 break;
92 }
93 break;
94 case 1:
95 if ((r == 'x' || r == 'X') && base == 8) {
96 base = 16;
97 continue;
98 }
99 }
100 if ((dig = asc2dig(r, base)) == -1) bailout = TRUE;
101 else n = dig + (n * base);
102 }
103 if (r < 0) return(-1);
104 *(int *)thing = (negate)?-n:n;
105 Bungetrune(bp);
106 break;
107 case 'u':
108 while (!bailout && (r = Bgetrune(bp))>=0) {
109 switch (sindex++) {
110 case 0:
111 if (*c == '0') {
112 base = 8;
113 continue;
114 }
115 break;
116 case 1:
117 if ((r == 'x' || r == 'X') && base == 8) {
118 base = 16;
119 continue;
120 }
121 }
122 if ((dig = asc2dig(r, base)) == -1) bailout = TRUE;
123 else u = dig + (n * base);
124 }
125 *(int *)thing = u;
126 if (r < 0) return(-1);
127 Bungetrune(bp);
128 break;
129 case 's':
130 j = 0;
131 while ((size>j+UTFmax) && (r = Bgetrune(bp))>=0 && !isspace(r)) {
132 R = r;
133 i = runetochar(&(((char *)thing)[j]), &R);
134 j += i;
135 sindex++;
136 }
137 ((char *)thing)[j++] = '\0';
138 if (r < 0) return(-1);
139 Bungetrune(bp);
140 break;
141 case 'r':
142 if ((r = Bgetrune(bp))>=0) {
143 *(Rune *)thing = r;
144 sindex++;
145 return(sindex);
146 }
147 if (r <= 0) return(-1);
148 Bungetrune(bp);
149 break;
150 default:
151 return(-2);
152 }
153 if (r < 0 && sindex == 0)
154 return(r);
155 else if (bailout && sindex == 1) {
156 return(0);
157 } else
158 return(sindex);
159}