Annotation of researchv9/libc/stdio/getflds.c, revision 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.