Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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);
}