1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include "../common/common.h" 5 #include "tr2post.h" 6 7 int 8 isspace(Rune r) 9 { 10 return r==' ' || r=='\t' || r=='\n' || r=='\r' || r=='\f'; 11 } 12 13 int 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 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 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