Annotation of researchv9/libc/stdio/getflds.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     getflds - break a line into fields
                      3:  *
                      4:  *     General strategy: ptrs is a pointer to an array of
                      5:  *     character pointers.  This array is used to hold the
                      6:  *     results of each call to getflds.  Expandptrs() uses
                      7:  *     realloc to grow this array as needed.  Each pointer in
                      8:  *     the array points into the buffer addressed by str,
                      9:  *     so all the strings returned by getflds are really
                     10:  *     contiguous.  Expandstr() uses realloc to grow this buffer
                     11:  *     as needed; after it has done so it must relocate all
                     12:  *     the pointers into the buffer because it may have moved.
                     13:  *
                     14:  *     Both expandstrs and expandptrs return nonzero for failure.
                     15:  *
                     16:  *     Ptrs and str are initially null.  In the (unlikely)
                     17:  *     event that an attempt to grow one of them fails, the
                     18:  *     corresponding pointer is set back to null.
                     19:  */
                     20: 
                     21: #include <stdio.h>
                     22: #include <setjmp.h>
                     23: 
                     24: /* how many elements to expand str and ptrs at a time */
                     25: #define STRCHUNK 512
                     26: #define PTRCHUNK 128
                     27: 
                     28: char *malloc(), *realloc();
                     29: static char **ptrs = NULL, *str = NULL;
                     30: static unsigned ptrsize = 0, strsize = 0;
                     31: 
                     32: static
                     33: expandptrs()
                     34: {
                     35:        ptrsize += PTRCHUNK;
                     36:        ptrs = (char **) (ptrs? realloc (ptrs, ptrsize * sizeof (char *)):
                     37:                                malloc (ptrsize * sizeof (char *)));
                     38:        if (ptrs == NULL) {
                     39:                ptrsize = 0;
                     40:                return 1;
                     41:        }
                     42:        return 0;
                     43: }
                     44: 
                     45: static
                     46: expandstr()
                     47: {
                     48:        register char *newstr;
                     49:        register unsigned n;
                     50: 
                     51:        strsize += STRCHUNK;
                     52:        newstr = str? realloc (str, strsize): malloc (strsize);
                     53:        if (newstr == NULL) {
                     54:                str = NULL;
                     55:                strsize = 0;
                     56:                return 1;
                     57:        }
                     58: 
                     59:        /* relocate the ptrs array */
                     60:        for (n = 0; n < ptrsize; n++)
                     61:                ptrs[n] = newstr + (ptrs[n] - str);
                     62: 
                     63:        str = newstr;
                     64:        return 0;
                     65: }
                     66: 
                     67: char **
                     68: getflds (f)
                     69:        register FILE *f;
                     70: {
                     71:        register int c;
                     72:        register unsigned nptr = 0, nstr = 0;
                     73: 
                     74:        /* try to read the first character of the line */
                     75:        c = getc (f);
                     76: 
                     77:        /* a line beginning with # is a comment */
                     78:        while (c == '#') {
                     79:                do c = getc (f);
                     80:                while (c != '\n' && c != EOF);
                     81:                if (c == '\n')
                     82:                        c = getc (f);
                     83:        }
                     84: 
                     85:        /* EOF at the beginning of the line is real */
                     86:        if (c == EOF)
                     87:                return NULL;
                     88: 
                     89:        /* one iteration per field */
                     90:        do {
                     91:                /* 0 outside a quoted string, otherwise the type of quote */
                     92:                register quote = 0;
                     93: 
                     94:                /* skip leading white space */
                     95:                while (c == ' ' || c == '\t')
                     96:                        c = getc (f);
                     97: 
                     98:                /* maybe it wan't a field after all */
                     99:                if (c == '\n' || c == EOF)
                    100:                        break;
                    101: 
                    102:                /* make room for the field pointer and plant it */
                    103:                if (nptr >= ptrsize)
                    104:                        if (expandptrs())
                    105:                                return NULL;
                    106:                ptrs[nptr++] = str + nstr;
                    107: 
                    108:                /* one iteration per character or escape sequence */
                    109:                while ((c != ' ' && c != '\t' || quote) && c != '\n' && c != EOF) {
                    110: 
                    111:                        /* check for escape sequence */
                    112:                        if (c == '\\') {
                    113:                                c = getc (f);
                    114:                                switch (c) {
                    115: 
                    116:                                /* C escapes for newline, etc. */
                    117:                                case 'b': c = '\b'; break;
                    118:                                case 'f': c = '\f'; break;
                    119:                                case 'n': c = '\n'; break;
                    120:                                case 'r': c = '\r'; break;
                    121:                                case 't': c = '\t'; break;
                    122:                                case 'v': c = '\v'; break;
                    123: 
                    124:                                /* these characters stand for themselves */
                    125:                                case '\'': case '"': case '#':
                    126:                                case ' ': case '\t': case '\\':
                    127:                                        break;
                    128: 
                    129:                                /* backslash, newline is ignored */
                    130:                                case '\n':
                    131:                                        c = getc (f);
                    132:                                        continue;
                    133: 
                    134:                                /* backslash, octal digits */
                    135:                                case '0': case '1': case '2': case '3':
                    136:                                case '4': case '5': case '6': case '7':
                    137:                                        {
                    138:                                                register r = c - '0';
                    139:                                                register n = 2;
                    140:                                                do {
                    141:                                                        c = getc (f);
                    142:                                                        if (c < '0' || c > '7') {
                    143:                                                                ungetc (c, f);
                    144:                                                                break;
                    145:                                                        }
                    146:                                                        r = (r<<3) + c - '0';
                    147:                                                } while (--n > 0);
                    148:                                                c = r;
                    149:                                        }
                    150:                                        break;
                    151: 
                    152:                                /* else treat the backslash as an ordinary char */
                    153:                                default:
                    154:                                        ungetc (c, f);
                    155:                                        c = '\\';
                    156:                                        break;
                    157:                                }
                    158: 
                    159:                        /* not a backslash, check for a quote */
                    160:                        } else if (c == '\'' || c == '"') {
                    161: 
                    162:                                /* beginning of a quoted string */
                    163:                                if (!quote) {
                    164:                                        quote = c;
                    165:                                        c = getc (f);
                    166:                                        continue;
                    167: 
                    168:                                /* end of a quoted string */
                    169:                                } else if (c == quote) {
                    170:                                        quote = 0;
                    171:                                        c = getc (f);
                    172:                                        continue;
                    173:                                }
                    174: 
                    175:                                /*
                    176:                                 * otherwise we're inside a quoted string
                    177:                                 * and we've seen the "other" quote, which
                    178:                                 * is now just an ordinary character.
                    179:                                 */
                    180:                        }
                    181: 
                    182:                        /* we have a character; put it in the string */
                    183:                        if (nstr >= strsize)
                    184:                                if (expandstr())
                    185:                                        return NULL;
                    186:                        str[nstr++] = c;
                    187:                        c = getc (f);
                    188:                }
                    189: 
                    190:                /* end of field; plant a null char at the end of the string */
                    191:                if (nstr >= strsize)
                    192:                        if (expandstr())
                    193:                                return NULL;
                    194:                str[nstr++] = '\0';
                    195: 
                    196:        } while (c != '\n' && c != EOF);
                    197: 
                    198:        /* end of line; put a null pointer at the end of the array */
                    199:        if (nptr >= ptrsize)
                    200:                if (expandptrs())
                    201:                        return NULL;
                    202:        ptrs[nptr++] = NULL;
                    203: 
                    204:        return ptrs;
                    205: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.