plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }