#include <u.h>
#include <libc.h>
#include <bio.h>
#include "../common/common.h"
#include "tr2post.h"
int
isspace(Rune r)
{
return r==' ' || r=='\t' || r=='\n' || r=='\r' || r=='\f';
}
int
Bskipws(Biobufhdr *bp) {
int r, sindex = 0;
/* skip over initial white space */
do {
r = Bgetrune(bp);
if (r == '\n')
inputlineno++;
sindex++;
} while (r>=0 && isspace(r));
if (r<0)
return(-1);
else if (!isspace(r)) {
Bungetrune(bp);
--sindex;
}
return sindex;
}
int
asc2dig(char c, int base) {
if (c >= '0' && c <= '9')
if (base == 8 && c > '7')
return(-1);
else
return(c - '0');
if (base == 16)
if (c >= 'a' && c <= 'f')
return(10 + c - 'a');
else if (c >= 'A' && c <= 'F')
return(10 + c - 'A');
return(-1);
}
/*
* get a string of type: "d" for decimal integer, "u" for unsigned,
* "s" for string", "c" for char,
* return the number of characters gotten for the field. If nothing
* was gotten and the end of file was reached, a negative value
* from the Bgetrune is returned.
*/
int
Bgetfield(Biobufhdr *bp, int type, void *thing, int size) {
int base = 10;
int dig;
int negate = 0;
int sindex = 0, i, j, n = 0;
long r;
Rune R;
unsigned u = 0;
BOOLEAN bailout = FALSE;
char c[UTFmax];
/* skip over initial white space */
if (Bskipws(bp) < 0)
return(-1);
r = 0;
switch (type) {
case 'd':
while (!bailout && (r = Bgetrune(bp))>=0) {
switch (sindex++) {
case 0:
switch (r) {
case '-':
negate = 1;
continue;
case '+':
continue;
case '0':
base = 8;
continue;
default:
break;
}
break;
case 1:
if ((r == 'x' || r == 'X') && base == 8) {
base = 16;
continue;
}
break;
}
if ((dig = asc2dig(r, base)) == -1)
bailout = TRUE;
else
n = dig + (n * base);
}
if (r < 0)
return(-1);
*(int *)thing = (negate)?-n:n;
Bungetrune(bp);
break;
case 'u':
while (!bailout && (r = Bgetrune(bp))>=0) {
switch (sindex++) {
case 0:
if (*c == '0') {
base = 8;
continue;
}
break;
case 1:
if ((r == 'x' || r == 'X') && base == 8) {
base = 16;
continue;
}
break;
}
if ((dig = asc2dig(r, base)) == -1)
bailout = TRUE;
else
u = dig + (n * base);
}
*(int *)thing = u;
if (r < 0)
return(-1);
Bungetrune(bp);
break;
case 's':
j = 0;
while (size > j+UTFmax && (r = Bgetrune(bp)) >= 0 &&
!isspace(r)) {
R = r;
i = runetochar(&(((char *)thing)[j]), &R);
j += i;
sindex++;
}
((char *)thing)[j] = '\0';
if (r < 0)
return(-1);
Bungetrune(bp);
break;
case 'r':
if ((r = Bgetrune(bp))>=0) {
*(Rune *)thing = r;
sindex++;
return(sindex);
}
if (r <= 0)
return(-1);
Bungetrune(bp);
break;
default:
return(-2);
}
if (r < 0 && sindex == 0)
return(r);
else if (bailout && sindex == 1) {
return(0);
} else
return(sindex);
}
|