xref: /minix3/usr.bin/sort/init.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: init.c,v 1.29 2013/10/18 20:47:06 christos Exp $	*/
20fbbaa43SLionel Sambuc 
30fbbaa43SLionel Sambuc /*-
40fbbaa43SLionel Sambuc  * Copyright (c) 2000-2003 The NetBSD Foundation, Inc.
50fbbaa43SLionel Sambuc  * All rights reserved.
60fbbaa43SLionel Sambuc  *
70fbbaa43SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
80fbbaa43SLionel Sambuc  * by Ben Harris and Jaromir Dolecek.
90fbbaa43SLionel Sambuc  *
100fbbaa43SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
110fbbaa43SLionel Sambuc  * modification, are permitted provided that the following conditions
120fbbaa43SLionel Sambuc  * are met:
130fbbaa43SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
140fbbaa43SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
150fbbaa43SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
160fbbaa43SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
170fbbaa43SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
180fbbaa43SLionel Sambuc  *
190fbbaa43SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
200fbbaa43SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
210fbbaa43SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220fbbaa43SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
230fbbaa43SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
240fbbaa43SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
250fbbaa43SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
260fbbaa43SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
270fbbaa43SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
280fbbaa43SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
290fbbaa43SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
300fbbaa43SLionel Sambuc  */
310fbbaa43SLionel Sambuc 
320fbbaa43SLionel Sambuc /*-
330fbbaa43SLionel Sambuc  * Copyright (c) 1993
340fbbaa43SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
350fbbaa43SLionel Sambuc  *
360fbbaa43SLionel Sambuc  * This code is derived from software contributed to Berkeley by
370fbbaa43SLionel Sambuc  * Peter McIlroy.
380fbbaa43SLionel Sambuc  *
390fbbaa43SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
400fbbaa43SLionel Sambuc  * modification, are permitted provided that the following conditions
410fbbaa43SLionel Sambuc  * are met:
420fbbaa43SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
430fbbaa43SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
440fbbaa43SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
450fbbaa43SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
460fbbaa43SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
470fbbaa43SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
480fbbaa43SLionel Sambuc  *    may be used to endorse or promote products derived from this software
490fbbaa43SLionel Sambuc  *    without specific prior written permission.
500fbbaa43SLionel Sambuc  *
510fbbaa43SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
520fbbaa43SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
530fbbaa43SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
540fbbaa43SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
550fbbaa43SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
560fbbaa43SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
570fbbaa43SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
580fbbaa43SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
590fbbaa43SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
600fbbaa43SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
610fbbaa43SLionel Sambuc  * SUCH DAMAGE.
620fbbaa43SLionel Sambuc  */
630fbbaa43SLionel Sambuc 
640fbbaa43SLionel Sambuc #include "sort.h"
650fbbaa43SLionel Sambuc 
66*84d9c625SLionel Sambuc __RCSID("$NetBSD: init.c,v 1.29 2013/10/18 20:47:06 christos Exp $");
670fbbaa43SLionel Sambuc 
680fbbaa43SLionel Sambuc #include <ctype.h>
690fbbaa43SLionel Sambuc #include <string.h>
700fbbaa43SLionel Sambuc 
710fbbaa43SLionel Sambuc static void insertcol(struct field *);
720fbbaa43SLionel Sambuc static const char *setcolumn(const char *, struct field *);
730fbbaa43SLionel Sambuc 
740fbbaa43SLionel Sambuc /*
750fbbaa43SLionel Sambuc  * masks of ignored characters.
760fbbaa43SLionel Sambuc  */
770fbbaa43SLionel Sambuc static u_char dtable[NBINS], itable[NBINS];
780fbbaa43SLionel Sambuc 
790fbbaa43SLionel Sambuc /*
800fbbaa43SLionel Sambuc  * parsed key options
810fbbaa43SLionel Sambuc  */
820fbbaa43SLionel Sambuc struct coldesc *clist = NULL;
830fbbaa43SLionel Sambuc int ncols = 0;
840fbbaa43SLionel Sambuc 
850fbbaa43SLionel Sambuc /*
860fbbaa43SLionel Sambuc  * clist (list of columns which correspond to one or more icol or tcol)
870fbbaa43SLionel Sambuc  * is in increasing order of columns.
880fbbaa43SLionel Sambuc  * Fields are kept in increasing order of fields.
890fbbaa43SLionel Sambuc  */
900fbbaa43SLionel Sambuc 
910fbbaa43SLionel Sambuc /*
920fbbaa43SLionel Sambuc  * keep clist in order--inserts a column in a sorted array
930fbbaa43SLionel Sambuc  */
940fbbaa43SLionel Sambuc static void
insertcol(struct field * field)950fbbaa43SLionel Sambuc insertcol(struct field *field)
960fbbaa43SLionel Sambuc {
970fbbaa43SLionel Sambuc 	int i;
980fbbaa43SLionel Sambuc 	struct coldesc *p;
990fbbaa43SLionel Sambuc 
1000fbbaa43SLionel Sambuc 	/* Make space for new item */
1010fbbaa43SLionel Sambuc 	p = realloc(clist, (ncols + 2) * sizeof(*clist));
1020fbbaa43SLionel Sambuc 	if (!p)
1030fbbaa43SLionel Sambuc 		err(1, "realloc");
1040fbbaa43SLionel Sambuc 	clist = p;
1050fbbaa43SLionel Sambuc 	memset(&clist[ncols], 0, sizeof(clist[ncols]));
1060fbbaa43SLionel Sambuc 
1070fbbaa43SLionel Sambuc 	for (i = 0; i < ncols; i++)
1080fbbaa43SLionel Sambuc 		if (field->icol.num <= clist[i].num)
1090fbbaa43SLionel Sambuc 			break;
1100fbbaa43SLionel Sambuc 	if (field->icol.num != clist[i].num) {
1110fbbaa43SLionel Sambuc 		memmove(clist+i+1, clist+i, sizeof(COLDESC)*(ncols-i));
1120fbbaa43SLionel Sambuc 		clist[i].num = field->icol.num;
1130fbbaa43SLionel Sambuc 		ncols++;
1140fbbaa43SLionel Sambuc 	}
1150fbbaa43SLionel Sambuc 	if (field->tcol.num && field->tcol.num != field->icol.num) {
1160fbbaa43SLionel Sambuc 		for (i = 0; i < ncols; i++)
1170fbbaa43SLionel Sambuc 			if (field->tcol.num <= clist[i].num)
1180fbbaa43SLionel Sambuc 				break;
1190fbbaa43SLionel Sambuc 		if (field->tcol.num != clist[i].num) {
1200fbbaa43SLionel Sambuc 			memmove(clist+i+1, clist+i,sizeof(COLDESC)*(ncols-i));
1210fbbaa43SLionel Sambuc 			clist[i].num = field->tcol.num;
1220fbbaa43SLionel Sambuc 			ncols++;
1230fbbaa43SLionel Sambuc 		}
1240fbbaa43SLionel Sambuc 	}
1250fbbaa43SLionel Sambuc }
1260fbbaa43SLionel Sambuc 
1270fbbaa43SLionel Sambuc /*
1280fbbaa43SLionel Sambuc  * matches fields with the appropriate columns--n^2 but who cares?
1290fbbaa43SLionel Sambuc  */
1300fbbaa43SLionel Sambuc void
fldreset(struct field * fldtab)1310fbbaa43SLionel Sambuc fldreset(struct field *fldtab)
1320fbbaa43SLionel Sambuc {
1330fbbaa43SLionel Sambuc 	int i;
1340fbbaa43SLionel Sambuc 
1350fbbaa43SLionel Sambuc 	fldtab[0].tcol.p = clist + ncols - 1;
1360fbbaa43SLionel Sambuc 	for (++fldtab; fldtab->icol.num; ++fldtab) {
1370fbbaa43SLionel Sambuc 		for (i = 0; fldtab->icol.num != clist[i].num; i++)
1380fbbaa43SLionel Sambuc 			;
1390fbbaa43SLionel Sambuc 		fldtab->icol.p = clist + i;
1400fbbaa43SLionel Sambuc 		if (!fldtab->tcol.num)
1410fbbaa43SLionel Sambuc 			continue;
1420fbbaa43SLionel Sambuc 		for (i = 0; fldtab->tcol.num != clist[i].num; i++)
1430fbbaa43SLionel Sambuc 			;
1440fbbaa43SLionel Sambuc 		fldtab->tcol.p = clist + i;
1450fbbaa43SLionel Sambuc 	}
1460fbbaa43SLionel Sambuc }
1470fbbaa43SLionel Sambuc 
1480fbbaa43SLionel Sambuc /*
1490fbbaa43SLionel Sambuc  * interprets a column in a -k field
1500fbbaa43SLionel Sambuc  */
1510fbbaa43SLionel Sambuc static const char *
setcolumn(const char * pos,struct field * cur_fld)1520fbbaa43SLionel Sambuc setcolumn(const char *pos, struct field *cur_fld)
1530fbbaa43SLionel Sambuc {
1540fbbaa43SLionel Sambuc 	struct column *col;
1550fbbaa43SLionel Sambuc 	char *npos;
1560fbbaa43SLionel Sambuc 	int tmp;
1570fbbaa43SLionel Sambuc 	col = cur_fld->icol.num ? (&cur_fld->tcol) : (&cur_fld->icol);
1580fbbaa43SLionel Sambuc 	col->num = (int) strtol(pos, &npos, 10);
1590fbbaa43SLionel Sambuc 	pos = npos;
1600fbbaa43SLionel Sambuc 	if (col->num <= 0 && !(col->num == 0 && col == &(cur_fld->tcol)))
1610fbbaa43SLionel Sambuc 		errx(2, "field numbers must be positive");
1620fbbaa43SLionel Sambuc 	if (*pos == '.') {
1630fbbaa43SLionel Sambuc 		if (!col->num)
1640fbbaa43SLionel Sambuc 			errx(2, "cannot indent end of line");
1650fbbaa43SLionel Sambuc 		++pos;
1660fbbaa43SLionel Sambuc 		col->indent = (int) strtol(pos, &npos, 10);
1670fbbaa43SLionel Sambuc 		pos = npos;
1680fbbaa43SLionel Sambuc 		if (&cur_fld->icol == col)
1690fbbaa43SLionel Sambuc 			col->indent--;
1700fbbaa43SLionel Sambuc 		if (col->indent < 0)
1710fbbaa43SLionel Sambuc 			errx(2, "illegal offset");
1720fbbaa43SLionel Sambuc 	}
1730fbbaa43SLionel Sambuc 	for(; (tmp = optval(*pos, cur_fld->tcol.num)); pos++)
1740fbbaa43SLionel Sambuc 		cur_fld->flags |= tmp;
1750fbbaa43SLionel Sambuc 	if (cur_fld->icol.num == 0)
1760fbbaa43SLionel Sambuc 		cur_fld->icol.num = 1;
1770fbbaa43SLionel Sambuc 	return (pos);
1780fbbaa43SLionel Sambuc }
1790fbbaa43SLionel Sambuc 
1800fbbaa43SLionel Sambuc int
setfield(const char * pos,struct field * cur_fld,int gflag)1810fbbaa43SLionel Sambuc setfield(const char *pos, struct field *cur_fld, int gflag)
1820fbbaa43SLionel Sambuc {
1830fbbaa43SLionel Sambuc 	cur_fld->mask = NULL;
1840fbbaa43SLionel Sambuc 
1850fbbaa43SLionel Sambuc 	pos = setcolumn(pos, cur_fld);
1860fbbaa43SLionel Sambuc 	if (*pos == '\0')			/* key extends to EOL. */
1870fbbaa43SLionel Sambuc 		cur_fld->tcol.num = 0;
1880fbbaa43SLionel Sambuc 	else {
1890fbbaa43SLionel Sambuc 		if (*pos != ',')
1900fbbaa43SLionel Sambuc 			errx(2, "illegal field descriptor");
1910fbbaa43SLionel Sambuc 		setcolumn((++pos), cur_fld);
1920fbbaa43SLionel Sambuc 	}
1930fbbaa43SLionel Sambuc 	if (!cur_fld->flags)
1940fbbaa43SLionel Sambuc 		cur_fld->flags = gflag;
1950fbbaa43SLionel Sambuc 	if (REVERSE)
1960fbbaa43SLionel Sambuc 		/* A local 'r' doesn't invert the global one */
1970fbbaa43SLionel Sambuc 		cur_fld->flags &= ~R;
1980fbbaa43SLionel Sambuc 
1990fbbaa43SLionel Sambuc 	/* Assign appropriate mask table and weight table. */
2000fbbaa43SLionel Sambuc 	cur_fld->weights = weight_tables[cur_fld->flags & (R | F)];
2010fbbaa43SLionel Sambuc 	if (cur_fld->flags & I)
2020fbbaa43SLionel Sambuc 		cur_fld->mask = itable;
2030fbbaa43SLionel Sambuc 	else if (cur_fld->flags & D)
2040fbbaa43SLionel Sambuc 		cur_fld->mask = dtable;
2050fbbaa43SLionel Sambuc 
2060fbbaa43SLionel Sambuc 	cur_fld->flags |= (gflag & (BI | BT));
2070fbbaa43SLionel Sambuc 	if (!cur_fld->tcol.indent)	/* BT has no meaning at end of field */
2080fbbaa43SLionel Sambuc 		cur_fld->flags &= ~BT;
2090fbbaa43SLionel Sambuc 
2100fbbaa43SLionel Sambuc 	if (cur_fld->tcol.num
2110fbbaa43SLionel Sambuc 	    && !(!(cur_fld->flags & BI) && cur_fld->flags & BT)
2120fbbaa43SLionel Sambuc 	    && (cur_fld->tcol.num <= cur_fld->icol.num
2130fbbaa43SLionel Sambuc 		    /* indent if 0 -> end of field, i.e. okay */
2140fbbaa43SLionel Sambuc 		    && cur_fld->tcol.indent != 0
2150fbbaa43SLionel Sambuc 		    && cur_fld->tcol.indent < cur_fld->icol.indent))
2160fbbaa43SLionel Sambuc 		errx(2, "fields out of order");
2170fbbaa43SLionel Sambuc 
2180fbbaa43SLionel Sambuc 	insertcol(cur_fld);
2190fbbaa43SLionel Sambuc 	return (cur_fld->tcol.num);
2200fbbaa43SLionel Sambuc }
2210fbbaa43SLionel Sambuc 
2220fbbaa43SLionel Sambuc int
optval(int desc,int tcolflag)2230fbbaa43SLionel Sambuc optval(int desc, int tcolflag)
2240fbbaa43SLionel Sambuc {
2250fbbaa43SLionel Sambuc 	switch(desc) {
2260fbbaa43SLionel Sambuc 	case 'b':
2270fbbaa43SLionel Sambuc 		if (!tcolflag)
2280fbbaa43SLionel Sambuc 			return BI;
2290fbbaa43SLionel Sambuc 		else
2300fbbaa43SLionel Sambuc 			return BT;
2310fbbaa43SLionel Sambuc 	case 'd': return D;
2320fbbaa43SLionel Sambuc 	case 'f': return F;
2330fbbaa43SLionel Sambuc 	case 'i': return I;
2340fbbaa43SLionel Sambuc 	case 'l': return L;
2350fbbaa43SLionel Sambuc 	case 'n': return N;
236*84d9c625SLionel Sambuc #if defined(__minix)
237e286ccc0SBen Gras 	case 'x': return X;
238*84d9c625SLionel Sambuc #endif /* defined(__minix) */
2390fbbaa43SLionel Sambuc 	case 'r': return R;
2400fbbaa43SLionel Sambuc 	default:  return 0;
2410fbbaa43SLionel Sambuc 	}
2420fbbaa43SLionel Sambuc }
2430fbbaa43SLionel Sambuc 
2440fbbaa43SLionel Sambuc /*
2450fbbaa43SLionel Sambuc  * Return true if the options found in ARG, according to the getopt
2460fbbaa43SLionel Sambuc  * spec in OPTS, require an additional argv word as an option
2470fbbaa43SLionel Sambuc  * argument.
2480fbbaa43SLionel Sambuc  */
2490fbbaa43SLionel Sambuc static int
options_need_argument(const char * arg,const char * opts)2500fbbaa43SLionel Sambuc options_need_argument(const char *arg, const char *opts)
2510fbbaa43SLionel Sambuc {
2520fbbaa43SLionel Sambuc 	size_t pos;
2530fbbaa43SLionel Sambuc 	const char *s;
2540fbbaa43SLionel Sambuc 
2550fbbaa43SLionel Sambuc 	/*assert(arg[0] == '-');*/
2560fbbaa43SLionel Sambuc 
2570fbbaa43SLionel Sambuc 	pos = 1;
2580fbbaa43SLionel Sambuc 	while (arg[pos]) {
2590fbbaa43SLionel Sambuc 		s = strchr(opts, arg[pos]);
2600fbbaa43SLionel Sambuc 		if (s == NULL) {
2610fbbaa43SLionel Sambuc 			/* invalid option */
2620fbbaa43SLionel Sambuc 			return 0;
2630fbbaa43SLionel Sambuc 		}
2640fbbaa43SLionel Sambuc 		if (s[1] == ':') {
2650fbbaa43SLionel Sambuc 			/* option requires argument */
2660fbbaa43SLionel Sambuc 			if (arg[pos+1] == '\0') {
2670fbbaa43SLionel Sambuc 				/* no argument in this arg */
2680fbbaa43SLionel Sambuc 				return 1;
2690fbbaa43SLionel Sambuc 			}
2700fbbaa43SLionel Sambuc 			else {
2710fbbaa43SLionel Sambuc 				/* argument is in this arg; no more options */
2720fbbaa43SLionel Sambuc 				return 0;
2730fbbaa43SLionel Sambuc 			}
2740fbbaa43SLionel Sambuc 		}
2750fbbaa43SLionel Sambuc 		pos++;
2760fbbaa43SLionel Sambuc 	}
2770fbbaa43SLionel Sambuc 	return 0;
2780fbbaa43SLionel Sambuc }
2790fbbaa43SLionel Sambuc 
2800fbbaa43SLionel Sambuc /*
2810fbbaa43SLionel Sambuc  * Replace historic +SPEC arguments with appropriate -kSPEC.
2820fbbaa43SLionel Sambuc  *
2830fbbaa43SLionel Sambuc  * The form can be either a single +SPEC or a pair +SPEC -SPEC.
2840fbbaa43SLionel Sambuc  * The following -SPEC is not recognized unless it follows
2850fbbaa43SLionel Sambuc  * immediately.
2860fbbaa43SLionel Sambuc  */
2870fbbaa43SLionel Sambuc void
fixit(int * argc,char ** argv,const char * opts)2880fbbaa43SLionel Sambuc fixit(int *argc, char **argv, const char *opts)
2890fbbaa43SLionel Sambuc {
2900fbbaa43SLionel Sambuc 	int i, j, sawplus;
2910fbbaa43SLionel Sambuc 	char *vpos, *tpos, spec[20];
2920fbbaa43SLionel Sambuc 	int col, indent;
2930fbbaa43SLionel Sambuc 
2940fbbaa43SLionel Sambuc 	sawplus = 0;
2950fbbaa43SLionel Sambuc 	for (i = 1; i < *argc; i++) {
2960fbbaa43SLionel Sambuc 		/*
2970fbbaa43SLionel Sambuc 		 * This loop must stop exactly where getopt will stop.
2980fbbaa43SLionel Sambuc 		 * Otherwise it turns e.g. "sort x +3" into "sort x
2990fbbaa43SLionel Sambuc 		 * -k4.1", which will croak if +3 was in fact really a
3000fbbaa43SLionel Sambuc 		 * file name. In order to do this reliably we need to
3010fbbaa43SLionel Sambuc 		 * be able to identify argv words that are option
3020fbbaa43SLionel Sambuc 		 * arguments.
3030fbbaa43SLionel Sambuc 		 */
3040fbbaa43SLionel Sambuc 
3050fbbaa43SLionel Sambuc 		if (!strcmp(argv[i], "--")) {
3060fbbaa43SLionel Sambuc 			/* End of options; stop. */
3070fbbaa43SLionel Sambuc 			break;
3080fbbaa43SLionel Sambuc 		}
3090fbbaa43SLionel Sambuc 
3100fbbaa43SLionel Sambuc 		if (argv[i][0] == '+') {
3110fbbaa43SLionel Sambuc 			/* +POS argument */
3120fbbaa43SLionel Sambuc 			sawplus = 1;
3130fbbaa43SLionel Sambuc 		} else if (argv[i][0] == '-' && sawplus &&
3140fbbaa43SLionel Sambuc 			   isdigit((unsigned char)argv[i][1])) {
3150fbbaa43SLionel Sambuc 			/* -POS argument */
3160fbbaa43SLionel Sambuc 			sawplus = 0;
3170fbbaa43SLionel Sambuc 		} else if (argv[i][0] == '-') {
3180fbbaa43SLionel Sambuc 			/* other option */
3190fbbaa43SLionel Sambuc 			sawplus = 0;
3200fbbaa43SLionel Sambuc 			if (options_need_argument(argv[i], opts)) {
3210fbbaa43SLionel Sambuc 				/* skip over the argument */
3220fbbaa43SLionel Sambuc 				i++;
3230fbbaa43SLionel Sambuc 			}
3240fbbaa43SLionel Sambuc 			continue;
3250fbbaa43SLionel Sambuc 		} else {
3260fbbaa43SLionel Sambuc 			/* not an option at all; stop */
3270fbbaa43SLionel Sambuc 			sawplus = 0;
3280fbbaa43SLionel Sambuc 			break;
3290fbbaa43SLionel Sambuc 		}
3300fbbaa43SLionel Sambuc 
3310fbbaa43SLionel Sambuc 		/*
3320fbbaa43SLionel Sambuc 		 * At this point argv[i] is an old-style spec. The
3330fbbaa43SLionel Sambuc 		 * sawplus flag used by the above loop logic also
3340fbbaa43SLionel Sambuc 		 * tells us if it's a +SPEC or -SPEC.
3350fbbaa43SLionel Sambuc 		 */
3360fbbaa43SLionel Sambuc 
3370fbbaa43SLionel Sambuc 		/* parse spec */
3380fbbaa43SLionel Sambuc 		tpos = argv[i]+1;
3390fbbaa43SLionel Sambuc 		col = (int)strtol(tpos, &tpos, 10);
3400fbbaa43SLionel Sambuc 		if (*tpos == '.') {
3410fbbaa43SLionel Sambuc 			++tpos;
3420fbbaa43SLionel Sambuc 			indent = (int) strtol(tpos, &tpos, 10);
3430fbbaa43SLionel Sambuc 		} else
3440fbbaa43SLionel Sambuc 			indent = 0;
3450fbbaa43SLionel Sambuc 		/* tpos now points to the optional flags */
3460fbbaa43SLionel Sambuc 
3470fbbaa43SLionel Sambuc 		/*
3480fbbaa43SLionel Sambuc 		 * In the traditional form, x.0 means beginning of line;
3490fbbaa43SLionel Sambuc 		 * in the new form, x.0 means end of line. Adjust the
3500fbbaa43SLionel Sambuc 		 * value of INDENT accordingly.
3510fbbaa43SLionel Sambuc 		 */
3520fbbaa43SLionel Sambuc 		if (sawplus) {
3530fbbaa43SLionel Sambuc 			/* +POS */
3540fbbaa43SLionel Sambuc 			col += 1;
3550fbbaa43SLionel Sambuc 			indent += 1;
3560fbbaa43SLionel Sambuc 		} else {
3570fbbaa43SLionel Sambuc 			/* -POS */
3580fbbaa43SLionel Sambuc 			if (indent > 0)
3590fbbaa43SLionel Sambuc 				col += 1;
3600fbbaa43SLionel Sambuc 		}
3610fbbaa43SLionel Sambuc 
3620fbbaa43SLionel Sambuc 		/* make the new style spec */
363*84d9c625SLionel Sambuc 		(void)snprintf(spec, sizeof(spec), "%d.%d%s", col, indent,
3640fbbaa43SLionel Sambuc 		    tpos);
3650fbbaa43SLionel Sambuc 
3660fbbaa43SLionel Sambuc 		if (sawplus) {
3670fbbaa43SLionel Sambuc 			/* Replace the +POS argument with new-style -kSPEC */
3680fbbaa43SLionel Sambuc 			asprintf(&vpos, "-k%s", spec);
3690fbbaa43SLionel Sambuc 			argv[i] = vpos;
3700fbbaa43SLionel Sambuc 		} else {
3710fbbaa43SLionel Sambuc 			/*
3720fbbaa43SLionel Sambuc 			 * Append the spec to the one from the
3730fbbaa43SLionel Sambuc 			 * preceding +POS argument, and remove the
3740fbbaa43SLionel Sambuc 			 * current argv element entirely.
3750fbbaa43SLionel Sambuc 			 */
3760fbbaa43SLionel Sambuc 			asprintf(&vpos, "%s,%s", argv[i-1], spec);
3770fbbaa43SLionel Sambuc 			free(argv[i-1]);
3780fbbaa43SLionel Sambuc 			argv[i-1] = vpos;
3790fbbaa43SLionel Sambuc 			for (j=i; j < *argc; j++)
3800fbbaa43SLionel Sambuc 				argv[j] = argv[j+1];
3810fbbaa43SLionel Sambuc 			*argc -= 1;
3820fbbaa43SLionel Sambuc 			i--;
3830fbbaa43SLionel Sambuc 		}
3840fbbaa43SLionel Sambuc 	}
3850fbbaa43SLionel Sambuc }
3860fbbaa43SLionel Sambuc 
3870fbbaa43SLionel Sambuc /*
3880fbbaa43SLionel Sambuc  * ascii, Rascii, Ftable, and RFtable map
3890fbbaa43SLionel Sambuc  *
3900fbbaa43SLionel Sambuc  * Sorting 'weight' tables.
3910fbbaa43SLionel Sambuc  * Convert 'ascii' characters into their sort order.
3920fbbaa43SLionel Sambuc  * The 'F' variants fold lower case to upper equivalent
3930fbbaa43SLionel Sambuc  * The 'R' variants are for reverse sorting.
3940fbbaa43SLionel Sambuc  *
3950fbbaa43SLionel Sambuc  * The record separator (REC_D) never needs a weight, this frees one
3960fbbaa43SLionel Sambuc  * byte value as an 'end of key' marker. This must be 0 for normal
3970fbbaa43SLionel Sambuc  * weight tables, and 0xff for reverse weight tables - and is used
3980fbbaa43SLionel Sambuc  * to terminate keys so that short keys sort before (after if reverse)
3990fbbaa43SLionel Sambuc  * longer keys.
4000fbbaa43SLionel Sambuc  *
4010fbbaa43SLionel Sambuc  * The field separator has a normal weight - although it cannot occur
4020fbbaa43SLionel Sambuc  * within a key unless it is the default (space+tab).
4030fbbaa43SLionel Sambuc  *
4040fbbaa43SLionel Sambuc  * All other bytes map to the appropriate value for the sort order.
4050fbbaa43SLionel Sambuc  * Numeric sorts don't need any tables, they are reversed by negation.
4060fbbaa43SLionel Sambuc  *
4070fbbaa43SLionel Sambuc  * Global reverse sorts are done by writing the sorted keys in reverse
4080fbbaa43SLionel Sambuc  * order - the sort itself is stil forwards.
4090fbbaa43SLionel Sambuc  * This means that weights are only ever used when generating keys, any
4100fbbaa43SLionel Sambuc  * sort of the original data bytes is always forwards and unweighted.
4110fbbaa43SLionel Sambuc  *
4120fbbaa43SLionel Sambuc  * Note: this is only good for ASCII sorting.  For different LC 's,
4130fbbaa43SLionel Sambuc  * all bets are off.
4140fbbaa43SLionel Sambuc  *
4150fbbaa43SLionel Sambuc  * itable[] and dtable[] are the masks for -i (ignore non-printables)
4160fbbaa43SLionel Sambuc  * and -d (only sort blank and alphanumerics).
4170fbbaa43SLionel Sambuc  */
4180fbbaa43SLionel Sambuc void
settables(void)4190fbbaa43SLionel Sambuc settables(void)
4200fbbaa43SLionel Sambuc {
4210fbbaa43SLionel Sambuc 	int i;
4220fbbaa43SLionel Sambuc 	int next_weight = 1;
4230fbbaa43SLionel Sambuc 	int rev_weight = 254;
4240fbbaa43SLionel Sambuc 
4250fbbaa43SLionel Sambuc 	ascii[REC_D] = 0;
4260fbbaa43SLionel Sambuc 	Rascii[REC_D] = 255;
4270fbbaa43SLionel Sambuc 	Ftable[REC_D] = 0;
4280fbbaa43SLionel Sambuc 	RFtable[REC_D] = 255;
4290fbbaa43SLionel Sambuc 
4300fbbaa43SLionel Sambuc 	for (i = 0; i < 256; i++) {
4310fbbaa43SLionel Sambuc 		if (i == REC_D)
4320fbbaa43SLionel Sambuc 			continue;
4330fbbaa43SLionel Sambuc 		ascii[i] = next_weight;
4340fbbaa43SLionel Sambuc 		Rascii[i] = rev_weight;
4350fbbaa43SLionel Sambuc 		if (Ftable[i] == 0) {
4360fbbaa43SLionel Sambuc 			Ftable[i] = next_weight;
4370fbbaa43SLionel Sambuc 			RFtable[i] = rev_weight;
4380fbbaa43SLionel Sambuc 			Ftable[tolower(i)] = next_weight;
4390fbbaa43SLionel Sambuc 			RFtable[tolower(i)] = rev_weight;
4400fbbaa43SLionel Sambuc 		}
4410fbbaa43SLionel Sambuc 		next_weight++;
4420fbbaa43SLionel Sambuc 		rev_weight--;
4430fbbaa43SLionel Sambuc 
4440fbbaa43SLionel Sambuc 		if (i == '\n' || isprint(i))
4450fbbaa43SLionel Sambuc 			itable[i] = 1;
4460fbbaa43SLionel Sambuc 
4470fbbaa43SLionel Sambuc 		if (i == '\n' || i == '\t' || i == ' ' || isalnum(i))
4480fbbaa43SLionel Sambuc 			dtable[i] = 1;
4490fbbaa43SLionel Sambuc 	}
4500fbbaa43SLionel Sambuc }
451