1*c1d86c14Sandvar /* $NetBSD: init.c,v 1.30 2021/09/19 11:37:01 andvar Exp $ */
2f84513a7Sjdolecek
3f84513a7Sjdolecek /*-
4f84513a7Sjdolecek * Copyright (c) 2000-2003 The NetBSD Foundation, Inc.
5f84513a7Sjdolecek * All rights reserved.
6f84513a7Sjdolecek *
7f84513a7Sjdolecek * This code is derived from software contributed to The NetBSD Foundation
8f84513a7Sjdolecek * by Ben Harris and Jaromir Dolecek.
9f84513a7Sjdolecek *
10f84513a7Sjdolecek * Redistribution and use in source and binary forms, with or without
11f84513a7Sjdolecek * modification, are permitted provided that the following conditions
12f84513a7Sjdolecek * are met:
13f84513a7Sjdolecek * 1. Redistributions of source code must retain the above copyright
14f84513a7Sjdolecek * notice, this list of conditions and the following disclaimer.
15f84513a7Sjdolecek * 2. Redistributions in binary form must reproduce the above copyright
16f84513a7Sjdolecek * notice, this list of conditions and the following disclaimer in the
17f84513a7Sjdolecek * documentation and/or other materials provided with the distribution.
18f84513a7Sjdolecek *
19f84513a7Sjdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20f84513a7Sjdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21f84513a7Sjdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f84513a7Sjdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23f84513a7Sjdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24f84513a7Sjdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25f84513a7Sjdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26f84513a7Sjdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27f84513a7Sjdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28f84513a7Sjdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29f84513a7Sjdolecek * POSSIBILITY OF SUCH DAMAGE.
30f84513a7Sjdolecek */
316029888aSbjh21
321d5d9b5bSbjh21 /*-
331d5d9b5bSbjh21 * Copyright (c) 1993
341d5d9b5bSbjh21 * The Regents of the University of California. All rights reserved.
351d5d9b5bSbjh21 *
361d5d9b5bSbjh21 * This code is derived from software contributed to Berkeley by
371d5d9b5bSbjh21 * Peter McIlroy.
381d5d9b5bSbjh21 *
391d5d9b5bSbjh21 * Redistribution and use in source and binary forms, with or without
401d5d9b5bSbjh21 * modification, are permitted provided that the following conditions
411d5d9b5bSbjh21 * are met:
421d5d9b5bSbjh21 * 1. Redistributions of source code must retain the above copyright
431d5d9b5bSbjh21 * notice, this list of conditions and the following disclaimer.
441d5d9b5bSbjh21 * 2. Redistributions in binary form must reproduce the above copyright
451d5d9b5bSbjh21 * notice, this list of conditions and the following disclaimer in the
461d5d9b5bSbjh21 * documentation and/or other materials provided with the distribution.
4789aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
481d5d9b5bSbjh21 * may be used to endorse or promote products derived from this software
491d5d9b5bSbjh21 * without specific prior written permission.
501d5d9b5bSbjh21 *
511d5d9b5bSbjh21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
521d5d9b5bSbjh21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
531d5d9b5bSbjh21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
541d5d9b5bSbjh21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
551d5d9b5bSbjh21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
561d5d9b5bSbjh21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
571d5d9b5bSbjh21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
581d5d9b5bSbjh21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
591d5d9b5bSbjh21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
601d5d9b5bSbjh21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
611d5d9b5bSbjh21 * SUCH DAMAGE.
621d5d9b5bSbjh21 */
631d5d9b5bSbjh21
641d5d9b5bSbjh21 #include "sort.h"
651d5d9b5bSbjh21
66*c1d86c14Sandvar __RCSID("$NetBSD: init.c,v 1.30 2021/09/19 11:37:01 andvar Exp $");
676029888aSbjh21
681d5d9b5bSbjh21 #include <ctype.h>
691d5d9b5bSbjh21 #include <string.h>
701d5d9b5bSbjh21
712a0ab276Sdsl static void insertcol(struct field *);
721310aa04Sdsl static const char *setcolumn(const char *, struct field *);
736029888aSbjh21
741d5d9b5bSbjh21 /*
757b4a02beSdsl * masks of ignored characters.
76adefa598Sjdolecek */
777b4a02beSdsl static u_char dtable[NBINS], itable[NBINS];
78adefa598Sjdolecek
79adefa598Sjdolecek /*
809f774323Sjdolecek * parsed key options
819f774323Sjdolecek */
829f774323Sjdolecek struct coldesc *clist = NULL;
839f774323Sjdolecek int ncols = 0;
849f774323Sjdolecek
859f774323Sjdolecek /*
861d5d9b5bSbjh21 * clist (list of columns which correspond to one or more icol or tcol)
871d5d9b5bSbjh21 * is in increasing order of columns.
881d5d9b5bSbjh21 * Fields are kept in increasing order of fields.
891d5d9b5bSbjh21 */
901d5d9b5bSbjh21
911d5d9b5bSbjh21 /*
921d5d9b5bSbjh21 * keep clist in order--inserts a column in a sorted array
931d5d9b5bSbjh21 */
941d5d9b5bSbjh21 static void
insertcol(struct field * field)952a0ab276Sdsl insertcol(struct field *field)
961d5d9b5bSbjh21 {
971d5d9b5bSbjh21 int i;
98909cd63cSitojun struct coldesc *p;
999f774323Sjdolecek
1009f774323Sjdolecek /* Make space for new item */
101de243242Sjdolecek p = realloc(clist, (ncols + 2) * sizeof(*clist));
102909cd63cSitojun if (!p)
103909cd63cSitojun err(1, "realloc");
104909cd63cSitojun clist = p;
105909cd63cSitojun memset(&clist[ncols], 0, sizeof(clist[ncols]));
1069f774323Sjdolecek
1071d5d9b5bSbjh21 for (i = 0; i < ncols; i++)
1081d5d9b5bSbjh21 if (field->icol.num <= clist[i].num)
1091d5d9b5bSbjh21 break;
1101d5d9b5bSbjh21 if (field->icol.num != clist[i].num) {
1111d5d9b5bSbjh21 memmove(clist+i+1, clist+i, sizeof(COLDESC)*(ncols-i));
1121d5d9b5bSbjh21 clist[i].num = field->icol.num;
1131d5d9b5bSbjh21 ncols++;
1141d5d9b5bSbjh21 }
1151d5d9b5bSbjh21 if (field->tcol.num && field->tcol.num != field->icol.num) {
1161d5d9b5bSbjh21 for (i = 0; i < ncols; i++)
1171d5d9b5bSbjh21 if (field->tcol.num <= clist[i].num)
1181d5d9b5bSbjh21 break;
1191d5d9b5bSbjh21 if (field->tcol.num != clist[i].num) {
1201d5d9b5bSbjh21 memmove(clist+i+1, clist+i,sizeof(COLDESC)*(ncols-i));
1211d5d9b5bSbjh21 clist[i].num = field->tcol.num;
1221d5d9b5bSbjh21 ncols++;
1231d5d9b5bSbjh21 }
1241d5d9b5bSbjh21 }
1251d5d9b5bSbjh21 }
1261d5d9b5bSbjh21
1271d5d9b5bSbjh21 /*
1281d5d9b5bSbjh21 * matches fields with the appropriate columns--n^2 but who cares?
1291d5d9b5bSbjh21 */
1301d5d9b5bSbjh21 void
fldreset(struct field * fldtab)1312a0ab276Sdsl fldreset(struct field *fldtab)
1321d5d9b5bSbjh21 {
1331d5d9b5bSbjh21 int i;
134909cd63cSitojun
1351d5d9b5bSbjh21 fldtab[0].tcol.p = clist + ncols - 1;
1361d5d9b5bSbjh21 for (++fldtab; fldtab->icol.num; ++fldtab) {
137affba8f2Sjdolecek for (i = 0; fldtab->icol.num != clist[i].num; i++)
138affba8f2Sjdolecek ;
1391d5d9b5bSbjh21 fldtab->icol.p = clist + i;
1401d5d9b5bSbjh21 if (!fldtab->tcol.num)
1411d5d9b5bSbjh21 continue;
142affba8f2Sjdolecek for (i = 0; fldtab->tcol.num != clist[i].num; i++)
143affba8f2Sjdolecek ;
1441d5d9b5bSbjh21 fldtab->tcol.p = clist + i;
1451d5d9b5bSbjh21 }
1461d5d9b5bSbjh21 }
1471d5d9b5bSbjh21
1481d5d9b5bSbjh21 /*
1491d5d9b5bSbjh21 * interprets a column in a -k field
1501d5d9b5bSbjh21 */
151a65a3ad7Sjdolecek static const char *
setcolumn(const char * pos,struct field * cur_fld)1521310aa04Sdsl setcolumn(const char *pos, struct field *cur_fld)
1531d5d9b5bSbjh21 {
1541d5d9b5bSbjh21 struct column *col;
155afac62bcSjdolecek char *npos;
1561d5d9b5bSbjh21 int tmp;
157afac62bcSjdolecek col = cur_fld->icol.num ? (&cur_fld->tcol) : (&cur_fld->icol);
158afac62bcSjdolecek col->num = (int) strtol(pos, &npos, 10);
159afac62bcSjdolecek pos = npos;
1601d5d9b5bSbjh21 if (col->num <= 0 && !(col->num == 0 && col == &(cur_fld->tcol)))
1611d5d9b5bSbjh21 errx(2, "field numbers must be positive");
1621d5d9b5bSbjh21 if (*pos == '.') {
1631d5d9b5bSbjh21 if (!col->num)
1641d5d9b5bSbjh21 errx(2, "cannot indent end of line");
1652aa37f4aSthorpej ++pos;
166afac62bcSjdolecek col->indent = (int) strtol(pos, &npos, 10);
167afac62bcSjdolecek pos = npos;
1681d5d9b5bSbjh21 if (&cur_fld->icol == col)
1691d5d9b5bSbjh21 col->indent--;
1701d5d9b5bSbjh21 if (col->indent < 0)
1711d5d9b5bSbjh21 errx(2, "illegal offset");
1721d5d9b5bSbjh21 }
173afac62bcSjdolecek for(; (tmp = optval(*pos, cur_fld->tcol.num)); pos++)
1741d5d9b5bSbjh21 cur_fld->flags |= tmp;
1751d5d9b5bSbjh21 if (cur_fld->icol.num == 0)
1761d5d9b5bSbjh21 cur_fld->icol.num = 1;
1771d5d9b5bSbjh21 return (pos);
1781d5d9b5bSbjh21 }
1791d5d9b5bSbjh21
1801d5d9b5bSbjh21 int
setfield(const char * pos,struct field * cur_fld,int gflag)1812a0ab276Sdsl setfield(const char *pos, struct field *cur_fld, int gflag)
1821d5d9b5bSbjh21 {
1837b4a02beSdsl cur_fld->mask = NULL;
184adefa598Sjdolecek
1851310aa04Sdsl pos = setcolumn(pos, cur_fld);
1861d5d9b5bSbjh21 if (*pos == '\0') /* key extends to EOL. */
1871d5d9b5bSbjh21 cur_fld->tcol.num = 0;
1881d5d9b5bSbjh21 else {
1891d5d9b5bSbjh21 if (*pos != ',')
1901d5d9b5bSbjh21 errx(2, "illegal field descriptor");
1911310aa04Sdsl setcolumn((++pos), cur_fld);
1921d5d9b5bSbjh21 }
1931d5d9b5bSbjh21 if (!cur_fld->flags)
1941d5d9b5bSbjh21 cur_fld->flags = gflag;
1951310aa04Sdsl if (REVERSE)
1961310aa04Sdsl /* A local 'r' doesn't invert the global one */
1971310aa04Sdsl cur_fld->flags &= ~R;
1981d5d9b5bSbjh21
1997b4a02beSdsl /* Assign appropriate mask table and weight table. */
2001310aa04Sdsl cur_fld->weights = weight_tables[cur_fld->flags & (R | F)];
2011310aa04Sdsl if (cur_fld->flags & I)
2021d5d9b5bSbjh21 cur_fld->mask = itable;
2031310aa04Sdsl else if (cur_fld->flags & D)
2041d5d9b5bSbjh21 cur_fld->mask = dtable;
205adefa598Sjdolecek
2061d5d9b5bSbjh21 cur_fld->flags |= (gflag & (BI | BT));
2071d5d9b5bSbjh21 if (!cur_fld->tcol.indent) /* BT has no meaning at end of field */
208adefa598Sjdolecek cur_fld->flags &= ~BT;
209adefa598Sjdolecek
2104611f32cSdsl if (cur_fld->tcol.num
2114611f32cSdsl && !(!(cur_fld->flags & BI) && cur_fld->flags & BT)
2124611f32cSdsl && (cur_fld->tcol.num <= cur_fld->icol.num
2134611f32cSdsl /* indent if 0 -> end of field, i.e. okay */
2144611f32cSdsl && cur_fld->tcol.indent != 0
2151d5d9b5bSbjh21 && cur_fld->tcol.indent < cur_fld->icol.indent))
2161d5d9b5bSbjh21 errx(2, "fields out of order");
2171310aa04Sdsl
2181d5d9b5bSbjh21 insertcol(cur_fld);
2191d5d9b5bSbjh21 return (cur_fld->tcol.num);
2201d5d9b5bSbjh21 }
2211d5d9b5bSbjh21
2221d5d9b5bSbjh21 int
optval(int desc,int tcolflag)2232a0ab276Sdsl optval(int desc, int tcolflag)
2241d5d9b5bSbjh21 {
2251d5d9b5bSbjh21 switch(desc) {
2261d5d9b5bSbjh21 case 'b':
2271d5d9b5bSbjh21 if (!tcolflag)
2287e6e5c1fSchristos return BI;
2291d5d9b5bSbjh21 else
2307e6e5c1fSchristos return BT;
2317e6e5c1fSchristos case 'd': return D;
2327e6e5c1fSchristos case 'f': return F;
2337e6e5c1fSchristos case 'i': return I;
2347e6e5c1fSchristos case 'l': return L;
2357e6e5c1fSchristos case 'n': return N;
2367e6e5c1fSchristos case 'r': return R;
2377e6e5c1fSchristos default: return 0;
2381d5d9b5bSbjh21 }
2391d5d9b5bSbjh21 }
2401d5d9b5bSbjh21
24187c48f11Sjdolecek /*
242fcf4d3f7Sdholland * Return true if the options found in ARG, according to the getopt
243fcf4d3f7Sdholland * spec in OPTS, require an additional argv word as an option
244fcf4d3f7Sdholland * argument.
245fcf4d3f7Sdholland */
246fcf4d3f7Sdholland static int
options_need_argument(const char * arg,const char * opts)247fcf4d3f7Sdholland options_need_argument(const char *arg, const char *opts)
248fcf4d3f7Sdholland {
249fcf4d3f7Sdholland size_t pos;
250fcf4d3f7Sdholland const char *s;
251fcf4d3f7Sdholland
252fcf4d3f7Sdholland /*assert(arg[0] == '-');*/
253fcf4d3f7Sdholland
254fcf4d3f7Sdholland pos = 1;
255fcf4d3f7Sdholland while (arg[pos]) {
256fcf4d3f7Sdholland s = strchr(opts, arg[pos]);
257fcf4d3f7Sdholland if (s == NULL) {
258fcf4d3f7Sdholland /* invalid option */
259fcf4d3f7Sdholland return 0;
260fcf4d3f7Sdholland }
261fcf4d3f7Sdholland if (s[1] == ':') {
262fcf4d3f7Sdholland /* option requires argument */
263fcf4d3f7Sdholland if (arg[pos+1] == '\0') {
264fcf4d3f7Sdholland /* no argument in this arg */
265fcf4d3f7Sdholland return 1;
266fcf4d3f7Sdholland }
267fcf4d3f7Sdholland else {
268fcf4d3f7Sdholland /* argument is in this arg; no more options */
269fcf4d3f7Sdholland return 0;
270fcf4d3f7Sdholland }
271fcf4d3f7Sdholland }
272fcf4d3f7Sdholland pos++;
273fcf4d3f7Sdholland }
274fcf4d3f7Sdholland return 0;
275fcf4d3f7Sdholland }
276fcf4d3f7Sdholland
277fcf4d3f7Sdholland /*
27887c48f11Sjdolecek * Replace historic +SPEC arguments with appropriate -kSPEC.
279fcf4d3f7Sdholland *
280fcf4d3f7Sdholland * The form can be either a single +SPEC or a pair +SPEC -SPEC.
28190abead5Swiz * The following -SPEC is not recognized unless it follows
282fcf4d3f7Sdholland * immediately.
28387c48f11Sjdolecek */
2841d5d9b5bSbjh21 void
fixit(int * argc,char ** argv,const char * opts)285fcf4d3f7Sdholland fixit(int *argc, char **argv, const char *opts)
2861d5d9b5bSbjh21 {
287fcf4d3f7Sdholland int i, j, sawplus;
28887c48f11Sjdolecek char *vpos, *tpos, spec[20];
28987c48f11Sjdolecek int col, indent;
2901d5d9b5bSbjh21
291fcf4d3f7Sdholland sawplus = 0;
2921d5d9b5bSbjh21 for (i = 1; i < *argc; i++) {
293b6360c7fSdholland /*
294fcf4d3f7Sdholland * This loop must stop exactly where getopt will stop.
295fcf4d3f7Sdholland * Otherwise it turns e.g. "sort x +3" into "sort x
296fcf4d3f7Sdholland * -k4.1", which will croak if +3 was in fact really a
297fcf4d3f7Sdholland * file name. In order to do this reliably we need to
298fcf4d3f7Sdholland * be able to identify argv words that are option
299fcf4d3f7Sdholland * arguments.
300b6360c7fSdholland */
301b6360c7fSdholland
302fcf4d3f7Sdholland if (!strcmp(argv[i], "--")) {
303fcf4d3f7Sdholland /* End of options; stop. */
304fcf4d3f7Sdholland break;
305fcf4d3f7Sdholland }
30687c48f11Sjdolecek
307fcf4d3f7Sdholland if (argv[i][0] == '+') {
308fcf4d3f7Sdholland /* +POS argument */
309fcf4d3f7Sdholland sawplus = 1;
310fcf4d3f7Sdholland } else if (argv[i][0] == '-' && sawplus &&
311fcf4d3f7Sdholland isdigit((unsigned char)argv[i][1])) {
312fcf4d3f7Sdholland /* -POS argument */
313fcf4d3f7Sdholland sawplus = 0;
314fcf4d3f7Sdholland } else if (argv[i][0] == '-') {
315fcf4d3f7Sdholland /* other option */
316fcf4d3f7Sdholland sawplus = 0;
317fcf4d3f7Sdholland if (options_need_argument(argv[i], opts)) {
318fcf4d3f7Sdholland /* skip over the argument */
319fcf4d3f7Sdholland i++;
320fcf4d3f7Sdholland }
32187c48f11Sjdolecek continue;
322fcf4d3f7Sdholland } else {
323fcf4d3f7Sdholland /* not an option at all; stop */
324fcf4d3f7Sdholland sawplus = 0;
325fcf4d3f7Sdholland break;
32687c48f11Sjdolecek }
327fcf4d3f7Sdholland
328fcf4d3f7Sdholland /*
329fcf4d3f7Sdholland * At this point argv[i] is an old-style spec. The
330fcf4d3f7Sdholland * sawplus flag used by the above loop logic also
331fcf4d3f7Sdholland * tells us if it's a +SPEC or -SPEC.
332fcf4d3f7Sdholland */
33387c48f11Sjdolecek
33487c48f11Sjdolecek /* parse spec */
3351d5d9b5bSbjh21 tpos = argv[i]+1;
33687c48f11Sjdolecek col = (int)strtol(tpos, &tpos, 10);
3371d5d9b5bSbjh21 if (*tpos == '.') {
3382aa37f4aSthorpej ++tpos;
33987c48f11Sjdolecek indent = (int) strtol(tpos, &tpos, 10);
3401d5d9b5bSbjh21 } else
34187c48f11Sjdolecek indent = 0;
342fcf4d3f7Sdholland /* tpos now points to the optional flags */
34387c48f11Sjdolecek
34487c48f11Sjdolecek /*
345fcf4d3f7Sdholland * In the traditional form, x.0 means beginning of line;
346fcf4d3f7Sdholland * in the new form, x.0 means end of line. Adjust the
347fcf4d3f7Sdholland * value of INDENT accordingly.
34887c48f11Sjdolecek */
349fcf4d3f7Sdholland if (sawplus) {
35087c48f11Sjdolecek /* +POS */
35187c48f11Sjdolecek col += 1;
35287c48f11Sjdolecek indent += 1;
35387c48f11Sjdolecek } else {
35487c48f11Sjdolecek /* -POS */
35587c48f11Sjdolecek if (indent > 0)
35687c48f11Sjdolecek col += 1;
35787c48f11Sjdolecek }
35887c48f11Sjdolecek
359fcf4d3f7Sdholland /* make the new style spec */
3606e28978dSchristos (void)snprintf(spec, sizeof(spec), "%d.%d%s", col, indent,
36187c48f11Sjdolecek tpos);
36287c48f11Sjdolecek
363fcf4d3f7Sdholland if (sawplus) {
36487c48f11Sjdolecek /* Replace the +POS argument with new-style -kSPEC */
36587c48f11Sjdolecek asprintf(&vpos, "-k%s", spec);
36687c48f11Sjdolecek argv[i] = vpos;
36787c48f11Sjdolecek } else {
36887c48f11Sjdolecek /*
369fcf4d3f7Sdholland * Append the spec to the one from the
370fcf4d3f7Sdholland * preceding +POS argument, and remove the
371fcf4d3f7Sdholland * current argv element entirely.
37287c48f11Sjdolecek */
37387c48f11Sjdolecek asprintf(&vpos, "%s,%s", argv[i-1], spec);
37487c48f11Sjdolecek free(argv[i-1]);
37587c48f11Sjdolecek argv[i-1] = vpos;
37687c48f11Sjdolecek for (j=i; j < *argc; j++)
3771d5d9b5bSbjh21 argv[j] = argv[j+1];
3781d5d9b5bSbjh21 *argc -= 1;
379c8e0ab67Sjdolecek i--;
3801d5d9b5bSbjh21 }
3811d5d9b5bSbjh21 }
3821d5d9b5bSbjh21 }
3831d5d9b5bSbjh21
3841d5d9b5bSbjh21 /*
3851d5d9b5bSbjh21 * ascii, Rascii, Ftable, and RFtable map
3867b4a02beSdsl *
3877b4a02beSdsl * Sorting 'weight' tables.
3887b4a02beSdsl * Convert 'ascii' characters into their sort order.
3897b4a02beSdsl * The 'F' variants fold lower case to upper equivalent
3907b4a02beSdsl * The 'R' variants are for reverse sorting.
3911310aa04Sdsl *
3921310aa04Sdsl * The record separator (REC_D) never needs a weight, this frees one
3931310aa04Sdsl * byte value as an 'end of key' marker. This must be 0 for normal
3941310aa04Sdsl * weight tables, and 0xff for reverse weight tables - and is used
3951310aa04Sdsl * to terminate keys so that short keys sort before (after if reverse)
3961310aa04Sdsl * longer keys.
3971310aa04Sdsl *
3981310aa04Sdsl * The field separator has a normal weight - although it cannot occur
3991310aa04Sdsl * within a key unless it is the default (space+tab).
4001310aa04Sdsl *
4017b4a02beSdsl * All other bytes map to the appropriate value for the sort order.
4027b4a02beSdsl * Numeric sorts don't need any tables, they are reversed by negation.
4037b4a02beSdsl *
4041310aa04Sdsl * Global reverse sorts are done by writing the sorted keys in reverse
405*c1d86c14Sandvar * order - the sort itself is still forwards.
4061310aa04Sdsl * This means that weights are only ever used when generating keys, any
4071310aa04Sdsl * sort of the original data bytes is always forwards and unweighted.
4081310aa04Sdsl *
4091d5d9b5bSbjh21 * Note: this is only good for ASCII sorting. For different LC 's,
4107b4a02beSdsl * all bets are off.
4117b4a02beSdsl *
4127b4a02beSdsl * itable[] and dtable[] are the masks for -i (ignore non-printables)
4137b4a02beSdsl * and -d (only sort blank and alphanumerics).
4141d5d9b5bSbjh21 */
4151d5d9b5bSbjh21 void
settables(void)4164611f32cSdsl settables(void)
4171d5d9b5bSbjh21 {
4187b4a02beSdsl int i;
4191310aa04Sdsl int next_weight = 1;
4201310aa04Sdsl int rev_weight = 254;
4211310aa04Sdsl
4221310aa04Sdsl ascii[REC_D] = 0;
4231310aa04Sdsl Rascii[REC_D] = 255;
4241310aa04Sdsl Ftable[REC_D] = 0;
4251310aa04Sdsl RFtable[REC_D] = 255;
4267b4a02beSdsl
4271d5d9b5bSbjh21 for (i = 0; i < 256; i++) {
4281310aa04Sdsl if (i == REC_D)
4297b4a02beSdsl continue;
4307b4a02beSdsl ascii[i] = next_weight;
4317b4a02beSdsl Rascii[i] = rev_weight;
4327b4a02beSdsl if (Ftable[i] == 0) {
4337b4a02beSdsl Ftable[i] = next_weight;
4347b4a02beSdsl RFtable[i] = rev_weight;
4357b4a02beSdsl Ftable[tolower(i)] = next_weight;
4367b4a02beSdsl RFtable[tolower(i)] = rev_weight;
4377b4a02beSdsl }
4387b4a02beSdsl next_weight++;
4397b4a02beSdsl rev_weight--;
440adefa598Sjdolecek
4411d5d9b5bSbjh21 if (i == '\n' || isprint(i))
4421d5d9b5bSbjh21 itable[i] = 1;
443adefa598Sjdolecek
4441d5d9b5bSbjh21 if (i == '\n' || i == '\t' || i == ' ' || isalnum(i))
4451d5d9b5bSbjh21 dtable[i] = 1;
4461d5d9b5bSbjh21 }
4471d5d9b5bSbjh21 }
448