Annotation of src/usr.bin/sort/init.c, Revision 1.1
1.1 ! millert 1: /* OpenBSD$ */
! 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
! 43: static char rcsid[] = "$OpenBSD: $";
! 44: #endif
! 45: #endif /* not lint */
! 46:
! 47: #include "sort.h"
! 48:
! 49: #include <ctype.h>
! 50: #include <string.h>
! 51:
! 52: extern struct coldesc clist[(ND+1)*2];
! 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) {
! 100: for (i = 0; fldtab->icol.num != clist[i].num; i++);
! 101: fldtab->icol.p = clist + i;
! 102: if (!fldtab->tcol.num)
! 103: continue;
! 104: for (i = 0; fldtab->tcol.num != clist[i].num; i++);
! 105: fldtab->tcol.p = clist + i;
! 106: }
! 107: }
! 108:
! 109: /*
! 110: * interprets a column in a -k field
! 111: */
! 112: char *
! 113: setcolumn(pos, cur_fld, gflag)
! 114: char *pos;
! 115: struct field *cur_fld;
! 116: int gflag;
! 117: {
! 118: struct column *col;
! 119: int tmp;
! 120: col = cur_fld->icol.num ? (&(*cur_fld).tcol) : (&(*cur_fld).icol);
! 121: pos += sscanf(pos, "%d", &(col->num));
! 122: while (isdigit(*pos))
! 123: pos++;
! 124: if (col->num <= 0 && !(col->num == 0 && col == &(cur_fld->tcol)))
! 125: errx(2, "field numbers must be positive");
! 126: if (*pos == '.') {
! 127: if (!col->num)
! 128: errx(2, "cannot indent end of line");
! 129: pos += sscanf(++pos, "%d", &(col->indent));
! 130: while (isdigit(*pos))
! 131: pos++;
! 132: if (&cur_fld->icol == col)
! 133: col->indent--;
! 134: if (col->indent < 0)
! 135: errx(2, "illegal offset");
! 136: }
! 137: if (optval(*pos, cur_fld->tcol.num))
! 138: while ((tmp = optval(*pos, cur_fld->tcol.num))) {
! 139: cur_fld->flags |= tmp;
! 140: pos++;
! 141: }
! 142: if (cur_fld->icol.num == 0)
! 143: cur_fld->icol.num = 1;
! 144: return (pos);
! 145: }
! 146:
! 147: int
! 148: setfield(pos, cur_fld, gflag)
! 149: char *pos;
! 150: struct field *cur_fld;
! 151: int gflag;
! 152: {
! 153: static int nfields = 0;
! 154: int tmp;
! 155: char *setcolumn();
! 156: if (++nfields == ND)
! 157: errx(2, "too many sort keys. (Limit is %d)", ND-1);
! 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)
! 205: return(BI);
! 206: else
! 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);
! 214: }
! 215: }
! 216:
! 217: void
! 218: fixit(argc, argv)
! 219: int *argc;
! 220: char **argv;
! 221: {
! 222: int i, j, v, w, x;
! 223: static char vbuf[ND*20], *vpos, *tpos;
! 224: vpos = vbuf;
! 225:
! 226: for (i = 1; i < *argc; i++) {
! 227: if (argv[i][0] == '+') {
! 228: tpos = argv[i]+1;
! 229: argv[i] = vpos;
! 230: vpos += sprintf(vpos, "-k");
! 231: tpos += sscanf(tpos, "%d", &v);
! 232: while (isdigit(*tpos))
! 233: tpos++;
! 234: vpos += sprintf(vpos, "%d", v+1);
! 235: if (*tpos == '.') {
! 236: tpos += sscanf(++tpos, "%d", &x);
! 237: vpos += sprintf(vpos, ".%d", x+1);
! 238: }
! 239: while (*tpos)
! 240: *vpos++ = *tpos++;
! 241: vpos += sprintf(vpos, ",");
! 242: if (argv[i+1] &&
! 243: argv[i+1][0] == '-' && isdigit(argv[i+1][1])) {
! 244: tpos = argv[i+1] + 1;
! 245: tpos += sscanf(tpos, "%d", &w);
! 246: while (isdigit(*tpos))
! 247: tpos++;
! 248: x = 0;
! 249: if (*tpos == '.') {
! 250: tpos += sscanf(++tpos, "%d", &x);
! 251: while (isdigit(*tpos))
! 252: tpos++;
! 253: }
! 254: if (x) {
! 255: vpos += sprintf(vpos, "%d", w+1);
! 256: vpos += sprintf(vpos, ".%d", x);
! 257: } else
! 258: vpos += sprintf(vpos, "%d", w);
! 259: while (*tpos)
! 260: *vpos++ = *tpos++;
! 261: for (j= i+1; j < *argc; j++)
! 262: argv[j] = argv[j+1];
! 263: *argc -= 1;
! 264: }
! 265: }
! 266: }
! 267: }
! 268:
! 269: /*
! 270: * ascii, Rascii, Ftable, and RFtable map
! 271: * REC_D -> REC_D; {not REC_D} -> {not REC_D}.
! 272: * gweights maps REC_D -> (0 or 255); {not REC_D} -> {not gweights[REC_D]}.
! 273: * Note: when sorting in forward order, to encode character zero in a key,
! 274: * use \001\001; character 1 becomes \001\002. In this case, character 0
! 275: * is reserved for the field delimiter. Analagously for -r (fld_d = 255).
! 276: * Note: this is only good for ASCII sorting. For different LC 's,
! 277: * all bets are off. See also num_init in number.c
! 278: */
! 279: void
! 280: settables(gflags)
! 281: int gflags;
! 282: {
! 283: u_char *wts;
! 284: int i, incr;
! 285: for (i=0; i < 256; i++) {
! 286: ascii[i] = i;
! 287: if (i > REC_D && i < 255 - REC_D+1)
! 288: Rascii[i] = 255 - i + 1;
! 289: else
! 290: Rascii[i] = 255 - i;
! 291: if (islower(i)) {
! 292: Ftable[i] = Ftable[i- ('a' -'A')];
! 293: RFtable[i] = RFtable[i - ('a' - 'A')];
! 294: } else if (REC_D>= 'A' && REC_D < 'Z' && i < 'a' && i > REC_D) {
! 295: Ftable[i] = i + 1;
! 296: RFtable[i] = Rascii[i] - 1;
! 297: } else {
! 298: Ftable[i] = i;
! 299: RFtable[i] = Rascii[i];
! 300: }
! 301: alltable[i] = 1;
! 302: if (i == '\n' || isprint(i))
! 303: itable[i] = 1;
! 304: else itable[i] = 0;
! 305: if (i == '\n' || i == '\t' || i == ' ' || isalnum(i))
! 306: dtable[i] = 1;
! 307: else dtable[i] = 0;
! 308: }
! 309: Rascii[REC_D] = RFtable[REC_D] = REC_D;
! 310: if (REC_D >= 'A' && REC_D < 'Z')
! 311: ++Ftable[REC_D + ('a' - 'A')];
! 312: if (gflags & R && (!(gflags & F) || !SINGL_FLD))
! 313: wts = Rascii;
! 314: else if (!(gflags & F) || !SINGL_FLD)
! 315: wts = ascii;
! 316: else if (gflags & R)
! 317: wts = RFtable;
! 318: else
! 319: wts = Ftable;
! 320: memmove(gweights, wts, sizeof(gweights));
! 321: incr = (gflags & R) ? -1 : 1;
! 322: for (i = 0; i < REC_D; i++)
! 323: gweights[i] += incr;
! 324: gweights[REC_D] = ((gflags & R) ? 255 : 0);
! 325: if (SINGL_FLD && gflags & F) {
! 326: for (i = 0; i < REC_D; i++) {
! 327: ascii[i] += incr;
! 328: Rascii[i] += incr;
! 329: }
! 330: ascii[REC_D] = Rascii[REC_D] = gweights[REC_D];
! 331: }
! 332: }