Bgetfield.c (2887B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include "../common/common.h" 5 #include "tr2post.h" 6 7 #undef isspace 8 #define isspace risspace 9 10 int 11 isspace(Rune r) 12 { 13 return(r==' ' || r=='\t' || r=='\n' || r == '\r' || r=='\f'); 14 } 15 16 int 17 Bskipws(Biobuf *bp) { 18 int r; 19 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 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 } 42 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 } 47 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 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; 68 69 r = 0; 70 71 /* skip over initial white space */ 72 if (Bskipws(bp) < 0) 73 return(-1); 74 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); 101 } 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; 113 } 114 break; 115 case 1: 116 if ((r == 'x' || r == 'X') && base == 8) { 117 base = 16; 118 continue; 119 } 120 } 121 if ((dig = asc2dig(r, base)) == -1) bailout = TRUE; 122 else u = dig + (n * base); 123 } 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++; 135 } 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); 145 } 146 if (r <= 0) return(-1); 147 Bungetrune(bp); 148 break; 149 default: 150 return(-2); 151 } 152 if (r < 0 && sindex == 0) 153 return(r); 154 else if (bailout && sindex == 1) { 155 return(0); 156 } else 157 return(sindex); 158 }