[BACK]Return to init.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sort

Annotation of src/usr.bin/sort/init.c, Revision 1.3

1.3     ! millert     1: /*     $OpenBSD$       */
1.1       millert     2:
                      3: /*-
                      4:  * Copyright (c) 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Peter McIlroy.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
                     22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  */
                     38:
                     39: #ifndef lint
                     40: #if 0
                     41: static char sccsid[] = "@(#)init.c     8.1 (Berkeley) 6/6/93";
                     42: #else
1.3     ! millert    43: static char rcsid[] = "$OpenBSD: init.c,v 1.2 1997/06/16 02:21:56 millert Exp $";
1.1       millert    44: #endif
                     45: #endif /* not lint */
                     46:
                     47: #include "sort.h"
                     48:
                     49: #include <ctype.h>
                     50: #include <string.h>
                     51:
1.3     ! millert    52: extern struct coldesc *clist;
1.1       millert    53: extern int ncols;
                     54: u_char gweights[NBINS];
                     55:
                     56: /*
                     57:  * clist (list of columns which correspond to one or more icol or tcol)
                     58:  * is in increasing order of columns.
                     59:  * Fields are kept in increasing order of fields.
                     60:  */
                     61:
                     62: /*
                     63:  * keep clist in order--inserts a column in a sorted array
                     64:  */
                     65: static void
                     66: insertcol(field)
                     67:        struct field *field;
                     68: {
                     69:        int i;
                     70:        for (i = 0; i < ncols; i++)
                     71:                if (field->icol.num <= clist[i].num)
                     72:                        break;
                     73:        if (field->icol.num != clist[i].num) {
                     74:                memmove(clist+i+1, clist+i, sizeof(COLDESC)*(ncols-i));
                     75:                clist[i].num = field->icol.num;
                     76:                ncols++;
                     77:        }
                     78:        if (field->tcol.num && field->tcol.num != field->icol.num) {
                     79:                for (i = 0; i < ncols; i++)
                     80:                        if (field->tcol.num <= clist[i].num)
                     81:                                break;
                     82:                if (field->tcol.num != clist[i].num) {
                     83:                        memmove(clist+i+1, clist+i,sizeof(COLDESC)*(ncols-i));
                     84:                        clist[i].num = field->tcol.num;
                     85:                        ncols++;
                     86:                }
                     87:        }
                     88: }
                     89:
                     90: /*
                     91:  * matches fields with the appropriate columns--n^2 but who cares?
                     92:  */
                     93: void
                     94: fldreset(fldtab)
                     95:        struct field *fldtab;
                     96: {
                     97:        int i;
                     98:        fldtab[0].tcol.p = clist+ncols-1;
                     99:        for (++fldtab; fldtab->icol.num; ++fldtab) {
1.2       millert   100:                for (i = 0; fldtab->icol.num != clist[i].num; i++)
                    101:                        ;
1.1       millert   102:                fldtab->icol.p = clist + i;
                    103:                if (!fldtab->tcol.num)
                    104:                        continue;
1.2       millert   105:                for (i = 0; fldtab->tcol.num != clist[i].num; i++)
                    106:                        ;
1.1       millert   107:                fldtab->tcol.p = clist + i;
                    108:        }
                    109: }
                    110:
                    111: /*
                    112:  * interprets a column in a -k field
                    113:  */
                    114: char *
                    115: setcolumn(pos, cur_fld, gflag)
                    116:        char *pos;
                    117:        struct field *cur_fld;
                    118:        int gflag;
                    119: {
                    120:        struct column *col;
                    121:        int tmp;
1.2       millert   122:
1.1       millert   123:        col = cur_fld->icol.num ? (&(*cur_fld).tcol) : (&(*cur_fld).icol);
                    124:        pos += sscanf(pos, "%d", &(col->num));
                    125:        while (isdigit(*pos))
                    126:                pos++;
                    127:        if (col->num <= 0 && !(col->num == 0 && col == &(cur_fld->tcol)))
                    128:                errx(2, "field numbers must be positive");
                    129:        if (*pos == '.') {
                    130:                if (!col->num)
                    131:                        errx(2, "cannot indent end of line");
                    132:                pos += sscanf(++pos, "%d", &(col->indent));
                    133:                while (isdigit(*pos))
                    134:                        pos++;
                    135:                if (&cur_fld->icol == col)
                    136:                        col->indent--;
                    137:                if (col->indent < 0)
                    138:                        errx(2, "illegal offset");
                    139:        }
                    140:        if (optval(*pos, cur_fld->tcol.num))
                    141:                while ((tmp = optval(*pos, cur_fld->tcol.num))) {
                    142:                        cur_fld->flags |= tmp;
                    143:                        pos++;
                    144:        }
                    145:        if (cur_fld->icol.num == 0)
                    146:                cur_fld->icol.num = 1;
                    147:        return (pos);
                    148: }
                    149:
                    150: int
                    151: setfield(pos, cur_fld, gflag)
                    152:        char *pos;
                    153:        struct field *cur_fld;
                    154:        int gflag;
                    155: {
                    156:        int tmp;
                    157:        char *setcolumn();
                    158:        cur_fld->weights = ascii;
                    159:        cur_fld->mask = alltable;
                    160:        pos = setcolumn(pos, cur_fld, gflag);
                    161:        if (*pos == '\0')                       /* key extends to EOL. */
                    162:                cur_fld->tcol.num = 0;
                    163:        else {
                    164:                if (*pos != ',')
                    165:                        errx(2, "illegal field descriptor");
                    166:                setcolumn((++pos), cur_fld, gflag);
                    167:        }
                    168:        if (!cur_fld->flags)
                    169:                cur_fld->flags = gflag;
                    170:        tmp = cur_fld->flags;
                    171:
                    172:        /*
                    173:         * Assign appropriate mask table and weight table.
                    174:         * If the global weights are reversed, the local field
                    175:         * must be "re-reversed".
                    176:         */
                    177:        if (((tmp & R) ^ (gflag & R)) && tmp & F)
                    178:                cur_fld->weights = RFtable;
                    179:        else if (tmp & F)
                    180:                cur_fld->weights = Ftable;
                    181:        else if ((tmp & R) ^ (gflag & R))
                    182:                cur_fld->weights = Rascii;
                    183:        if (tmp & I)
                    184:                cur_fld->mask = itable;
                    185:        else if (tmp & D)
                    186:                cur_fld->mask = dtable;
                    187:        cur_fld->flags |= (gflag & (BI | BT));
                    188:        if (!cur_fld->tcol.indent)      /* BT has no meaning at end of field */
                    189:                cur_fld->flags &= (D|F|I|N|R|BI);
                    190:        if (cur_fld->tcol.num && !(!(cur_fld->flags & BI)
                    191:            && cur_fld->flags & BT) && (cur_fld->tcol.num <= cur_fld->icol.num
                    192:            && cur_fld->tcol.indent < cur_fld->icol.indent))
                    193:                errx(2, "fields out of order");
                    194:        insertcol(cur_fld);
                    195:        return (cur_fld->tcol.num);
                    196: }
                    197:
                    198: int
                    199: optval(desc, tcolflag)
                    200:        int desc, tcolflag;
                    201: {
                    202:        switch(desc) {
                    203:                case 'b':
                    204:                        if (!tcolflag)
1.2       millert   205:                                return (BI);
1.1       millert   206:                        else
1.2       millert   207:                                return (BT);
                    208:                case 'd': return (D);
                    209:                case 'f': return (F);
                    210:                case 'i': return (I);
                    211:                case 'n': return (N);
                    212:                case 'r': return (R);
                    213:                default:  return (0);
1.1       millert   214:        }
                    215: }
                    216:
                    217: void
                    218: fixit(argc, argv)
                    219:        int *argc;
                    220:        char **argv;
                    221: {
                    222:        int i, j, v, w, x;
1.3     ! millert   223:        static char *vbuf, *vpos, *tpos;
        !           224:
        !           225:        if ((vpos = vbuf = calloc(ND*20, sizeof(char))) == NULL)
        !           226:                errx(2, "cannot allocate memory");
1.1       millert   227:
                    228:        for (i = 1; i < *argc; i++) {
                    229:                if (argv[i][0] == '+') {
                    230:                        tpos = argv[i]+1;
                    231:                        argv[i] = vpos;
                    232:                        vpos += sprintf(vpos, "-k");
                    233:                        tpos += sscanf(tpos, "%d", &v);
                    234:                        while (isdigit(*tpos))
                    235:                                tpos++;
                    236:                        vpos += sprintf(vpos, "%d", v+1);
                    237:                        if (*tpos == '.') {
                    238:                                tpos += sscanf(++tpos, "%d", &x);
                    239:                                vpos += sprintf(vpos, ".%d", x+1);
                    240:                        }
                    241:                        while (*tpos)
                    242:                                *vpos++ = *tpos++;
                    243:                        vpos += sprintf(vpos, ",");
                    244:                        if (argv[i+1] &&
                    245:                            argv[i+1][0] == '-' && isdigit(argv[i+1][1])) {
                    246:                                tpos = argv[i+1] + 1;
                    247:                                tpos += sscanf(tpos, "%d", &w);
                    248:                                while (isdigit(*tpos))
                    249:                                        tpos++;
                    250:                                x = 0;
                    251:                                if (*tpos == '.') {
                    252:                                        tpos += sscanf(++tpos, "%d", &x);
                    253:                                        while (isdigit(*tpos))
                    254:                                                tpos++;
                    255:                                }
                    256:                                if (x) {
                    257:                                        vpos += sprintf(vpos, "%d", w+1);
                    258:                                        vpos += sprintf(vpos, ".%d", x);
                    259:                                } else
                    260:                                        vpos += sprintf(vpos, "%d", w);
                    261:                                while (*tpos)
                    262:                                        *vpos++ = *tpos++;
                    263:                                for (j= i+1; j < *argc; j++)
                    264:                                        argv[j] = argv[j+1];
                    265:                                *argc -= 1;
                    266:                        }
                    267:                }
                    268:        }
                    269: }
                    270:
                    271: /*
                    272:  * ascii, Rascii, Ftable, and RFtable map
                    273:  * REC_D -> REC_D;  {not REC_D} -> {not REC_D}.
                    274:  * gweights maps REC_D -> (0 or 255); {not REC_D} -> {not gweights[REC_D]}.
                    275:  * Note: when sorting in forward order, to encode character zero in a key,
                    276:  * use \001\001; character 1 becomes \001\002.  In this case, character 0
                    277:  * is reserved for the field delimiter.  Analagously for -r (fld_d = 255).
                    278:  * Note: this is only good for ASCII sorting.  For different LC 's,
                    279:  * all bets are off.  See also num_init in number.c
                    280:  */
                    281: void
                    282: settables(gflags)
                    283:        int gflags;
                    284: {
                    285:        u_char *wts;
                    286:        int i, incr;
                    287:        for (i=0; i < 256; i++) {
                    288:                ascii[i] = i;
                    289:                if (i > REC_D && i < 255 - REC_D+1)
                    290:                        Rascii[i] = 255 - i + 1;
                    291:                else
                    292:                        Rascii[i] = 255 - i;
                    293:                if (islower(i)) {
                    294:                        Ftable[i] = Ftable[i- ('a' -'A')];
                    295:                        RFtable[i] = RFtable[i - ('a' - 'A')];
                    296:                } else if (REC_D>= 'A' && REC_D < 'Z' && i < 'a' && i > REC_D) {
                    297:                        Ftable[i] = i + 1;
                    298:                        RFtable[i] = Rascii[i] - 1;
                    299:                } else {
                    300:                        Ftable[i] = i;
                    301:                        RFtable[i] = Rascii[i];
                    302:                }
                    303:                alltable[i] = 1;
                    304:                if (i == '\n' || isprint(i))
                    305:                        itable[i] = 1;
                    306:                else itable[i] = 0;
                    307:                if (i == '\n' || i == '\t' || i == ' ' || isalnum(i))
                    308:                        dtable[i] = 1;
                    309:                else dtable[i] = 0;
                    310:        }
                    311:        Rascii[REC_D] = RFtable[REC_D] = REC_D;
                    312:        if (REC_D >= 'A' && REC_D < 'Z')
1.2       millert   313:                Ftable[REC_D + ('a' - 'A')]++;
1.1       millert   314:        if (gflags & R && (!(gflags & F) || !SINGL_FLD))
                    315:                wts = Rascii;
                    316:        else if (!(gflags & F) || !SINGL_FLD)
                    317:                wts = ascii;
                    318:        else if (gflags & R)
                    319:                wts = RFtable;
                    320:        else
                    321:                wts = Ftable;
                    322:        memmove(gweights, wts, sizeof(gweights));
                    323:        incr = (gflags & R) ? -1 : 1;
                    324:        for (i = 0; i < REC_D; i++)
                    325:                gweights[i] += incr;
                    326:        gweights[REC_D] = ((gflags & R) ? 255 : 0);
                    327:        if (SINGL_FLD && gflags & F) {
                    328:                for (i = 0; i < REC_D; i++) {
                    329:                        ascii[i] += incr;
                    330:                        Rascii[i] += incr;
                    331:                }
                    332:                ascii[REC_D] = Rascii[REC_D] = gweights[REC_D];
                    333:        }
                    334: }