summaryrefslogtreecommitdiff
path: root/usr.bin/m4/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/m4/eval.c')
-rw-r--r--usr.bin/m4/eval.c1050
1 files changed, 0 insertions, 1050 deletions
diff --git a/usr.bin/m4/eval.c b/usr.bin/m4/eval.c
deleted file mode 100644
index 5af3c8774c415..0000000000000
--- a/usr.bin/m4/eval.c
+++ /dev/null
@@ -1,1050 +0,0 @@
-/* $OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $ */
-/* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ozan Yigit at York University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95";
-#else
-static char rcsid[] = "$OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $";
-#endif
-#endif /* not lint */
-
-/*
- * eval.c
- * Facility: m4 macro processor
- * by: oz
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <fcntl.h>
-#include <err.h>
-#include "mdef.h"
-#include "stdd.h"
-#include "extern.h"
-#include "pathnames.h"
-
-#define BUILTIN_MARKER "__builtin_"
-
-static void dodefn(const char *);
-static void dopushdef(const char *, const char *);
-static void dodump(const char *[], int);
-static void dotrace(const char *[], int, int);
-static void doifelse(const char *[], int);
-static int doincl(const char *);
-static int dopaste(const char *);
-static void gnu_dochq(const char *[], int);
-static void dochq(const char *[], int);
-static void gnu_dochc(const char *[], int);
-static void dochc(const char *[], int);
-static void dodiv(int);
-static void doundiv(const char *[], int);
-static void dosub(const char *[], int);
-static void map(char *, const char *, const char *, const char *);
-static const char *handledash(char *, char *, const char *);
-static void expand_builtin(const char *[], int, int);
-static void expand_macro(const char *[], int);
-static void dump_one_def(ndptr);
-
-unsigned long expansion_id;
-
-/*
- * eval - eval all macros and builtins calls
- * argc - number of elements in argv.
- * argv - element vector :
- * argv[0] = definition of a user
- * macro or nil if built-in.
- * argv[1] = name of the macro or
- * built-in.
- * argv[2] = parameters to user-defined
- * . macro or built-in.
- * .
- *
- * A call in the form of macro-or-builtin() will result in:
- * argv[0] = nullstr
- * argv[1] = macro-or-builtin
- * argv[2] = nullstr
- *
- * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
- */
-void
-eval(const char *argv[], int argc, int td)
-{
- ssize_t mark = -1;
-
- expansion_id++;
- if (td & RECDEF)
- errx(1, "%s at line %lu: expanding recursive definition for %s",
- CURRENT_NAME, CURRENT_LINE, argv[1]);
- if (traced_macros && is_traced(argv[1]))
- mark = trace(argv, argc, infile+ilevel);
- if (td == MACRTYPE)
- expand_macro(argv, argc);
- else
- expand_builtin(argv, argc, td);
- if (mark != -1)
- finish_trace(mark);
-}
-
-/*
- * expand_builtin - evaluate built-in macros.
- */
-void
-expand_builtin(const char *argv[], int argc, int td)
-{
- int c, n;
- int ac;
- static int sysval = 0;
-
-#ifdef DEBUG
- printf("argc = %d\n", argc);
- for (n = 0; n < argc; n++)
- printf("argv[%d] = %s\n", n, argv[n]);
- fflush(stdout);
-#endif
-
- /*
- * if argc == 3 and argv[2] is null, then we
- * have macro-or-builtin() type call. We adjust
- * argc to avoid further checking..
- */
- ac = argc;
-
- if (argc == 3 && !*(argv[2]))
- argc--;
-
- switch (td & TYPEMASK) {
-
- case DEFITYPE:
- if (argc > 2)
- dodefine(argv[2], (argc > 3) ? argv[3] : null);
- break;
-
- case PUSDTYPE:
- if (argc > 2)
- dopushdef(argv[2], (argc > 3) ? argv[3] : null);
- break;
-
- case DUMPTYPE:
- dodump(argv, argc);
- break;
-
- case TRACEONTYPE:
- dotrace(argv, argc, 1);
- break;
-
- case TRACEOFFTYPE:
- dotrace(argv, argc, 0);
- break;
-
- case EXPRTYPE:
- /*
- * doexpr - evaluate arithmetic
- * expression
- */
- if (argc > 2)
- pbnum(expr(argv[2]));
- break;
-
- case IFELTYPE:
- if (argc > 4)
- doifelse(argv, argc);
- break;
-
- case IFDFTYPE:
- /*
- * doifdef - select one of two
- * alternatives based on the existence of
- * another definition
- */
- if (argc > 3) {
- if (lookup(argv[2]) != nil)
- pbstr(argv[3]);
- else if (argc > 4)
- pbstr(argv[4]);
- }
- break;
-
- case LENGTYPE:
- /*
- * dolen - find the length of the
- * argument
- */
- pbnum((argc > 2) ? strlen(argv[2]) : 0);
- break;
-
- case INCRTYPE:
- /*
- * doincr - increment the value of the
- * argument
- */
- if (argc > 2)
- pbnum(atoi(argv[2]) + 1);
- break;
-
- case DECRTYPE:
- /*
- * dodecr - decrement the value of the
- * argument
- */
- if (argc > 2)
- pbnum(atoi(argv[2]) - 1);
- break;
-
- case SYSCTYPE:
- /*
- * dosys - execute system command
- */
- if (argc > 2)
- sysval = system(argv[2]);
- break;
-
- case SYSVTYPE:
- /*
- * dosysval - return value of the last
- * system call.
- *
- */
- pbnum(sysval);
- break;
-
- case ESYSCMDTYPE:
- if (argc > 2)
- doesyscmd(argv[2]);
- break;
- case INCLTYPE:
- if (argc > 2)
- if (!doincl(argv[2]))
- err(1, "%s at line %lu: include(%s)",
- CURRENT_NAME, CURRENT_LINE, argv[2]);
- break;
-
- case SINCTYPE:
- if (argc > 2)
- (void) doincl(argv[2]);
- break;
-#ifdef EXTENDED
- case PASTTYPE:
- if (argc > 2)
- if (!dopaste(argv[2]))
- err(1, "%s at line %lu: paste(%s)",
- CURRENT_NAME, CURRENT_LINE, argv[2]);
- break;
-
- case SPASTYPE:
- if (argc > 2)
- (void) dopaste(argv[2]);
- break;
-#endif
- case CHNQTYPE:
- if (mimic_gnu)
- gnu_dochq(argv, ac);
- else
- dochq(argv, argc);
- break;
-
- case CHNCTYPE:
- if (mimic_gnu)
- gnu_dochc(argv, ac);
- else
- dochc(argv, argc);
- break;
-
- case SUBSTYPE:
- /*
- * dosub - select substring
- *
- */
- if (argc > 3)
- dosub(argv, argc);
- break;
-
- case SHIFTYPE:
- /*
- * doshift - push back all arguments
- * except the first one (i.e. skip
- * argv[2])
- */
- if (argc > 3) {
- for (n = argc - 1; n > 3; n--) {
- pbstr(rquote);
- pbstr(argv[n]);
- pbstr(lquote);
- putback(COMMA);
- }
- pbstr(rquote);
- pbstr(argv[3]);
- pbstr(lquote);
- }
- break;
-
- case DIVRTYPE:
- if (argc > 2 && (n = atoi(argv[2])) != 0)
- dodiv(n);
- else {
- active = stdout;
- oindex = 0;
- }
- break;
-
- case UNDVTYPE:
- doundiv(argv, argc);
- break;
-
- case DIVNTYPE:
- /*
- * dodivnum - return the number of
- * current output diversion
- */
- pbnum(oindex);
- break;
-
- case UNDFTYPE:
- /*
- * doundefine - undefine a previously
- * defined macro(s) or m4 keyword(s).
- */
- if (argc > 2)
- for (n = 2; n < argc; n++)
- remhash(argv[n], ALL);
- break;
-
- case POPDTYPE:
- /*
- * dopopdef - remove the topmost
- * definitions of macro(s) or m4
- * keyword(s).
- */
- if (argc > 2)
- for (n = 2; n < argc; n++)
- remhash(argv[n], TOP);
- break;
-
- case MKTMTYPE:
- /*
- * dotemp - create a temporary file
- */
- if (argc > 2) {
- int fd;
- char *temp;
-
- temp = xstrdup(argv[2]);
-
- fd = mkstemp(temp);
- if (fd == -1)
- err(1,
- "%s at line %lu: couldn't make temp file %s",
- CURRENT_NAME, CURRENT_LINE, argv[2]);
- close(fd);
- pbstr(temp);
- free(temp);
- }
- break;
-
- case TRNLTYPE:
- /*
- * dotranslit - replace all characters in
- * the source string that appears in the
- * "from" string with the corresponding
- * characters in the "to" string.
- */
- if (argc > 3) {
- char *temp;
-
- temp = xalloc(strlen(argv[2])+1);
- if (argc > 4)
- map(temp, argv[2], argv[3], argv[4]);
- else
- map(temp, argv[2], argv[3], null);
- pbstr(temp);
- free(temp);
- } else if (argc > 2)
- pbstr(argv[2]);
- break;
-
- case INDXTYPE:
- /*
- * doindex - find the index of the second
- * argument string in the first argument
- * string. -1 if not present.
- */
- pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
- break;
-
- case ERRPTYPE:
- /*
- * doerrp - print the arguments to stderr
- * file
- */
- if (argc > 2) {
- for (n = 2; n < argc; n++)
- fprintf(stderr, "%s ", argv[n]);
- fprintf(stderr, "\n");
- }
- break;
-
- case DNLNTYPE:
- /*
- * dodnl - eat-up-to and including
- * newline
- */
- while ((c = gpbc()) != '\n' && c != EOF)
- ;
- break;
-
- case M4WRTYPE:
- /*
- * dom4wrap - set up for
- * wrap-up/wind-down activity
- */
- m4wraps = (argc > 2) ? xstrdup(argv[2]) : null;
- break;
-
- case EXITTYPE:
- /*
- * doexit - immediate exit from m4.
- */
- killdiv();
- exit((argc > 2) ? atoi(argv[2]) : 0);
- break;
-
- case DEFNTYPE:
- if (argc > 2)
- for (n = 2; n < argc; n++)
- dodefn(argv[n]);
- break;
-
- case INDIRTYPE: /* Indirect call */
- if (argc > 2)
- doindir(argv, argc);
- break;
-
- case BUILTINTYPE: /* Builtins only */
- if (argc > 2)
- dobuiltin(argv, argc);
- break;
-
- case PATSTYPE:
- if (argc > 2)
- dopatsubst(argv, argc);
- break;
- case REGEXPTYPE:
- if (argc > 2)
- doregexp(argv, argc);
- break;
- case LINETYPE:
- doprintlineno(infile+ilevel);
- break;
- case FILENAMETYPE:
- doprintfilename(infile+ilevel);
- break;
- case SELFTYPE:
- pbstr(rquote);
- pbstr(argv[1]);
- pbstr(lquote);
- break;
- default:
- errx(1, "%s at line %lu: eval: major botch.",
- CURRENT_NAME, CURRENT_LINE);
- break;
- }
-}
-
-/*
- * expand_macro - user-defined macro expansion
- */
-void
-expand_macro(const char *argv[], int argc)
-{
- const char *t;
- const char *p;
- int n;
- int argno;
-
- t = argv[0]; /* defn string as a whole */
- p = t;
- while (*p)
- p++;
- p--; /* last character of defn */
- while (p > t) {
- if (*(p - 1) != ARGFLAG)
- PUTBACK(*p);
- else {
- switch (*p) {
-
- case '#':
- pbnum(argc - 2);
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if ((argno = *p - '0') < argc - 1)
- pbstr(argv[argno + 1]);
- break;
- case '*':
- if (argc > 2) {
- for (n = argc - 1; n > 2; n--) {
- pbstr(argv[n]);
- putback(COMMA);
- }
- pbstr(argv[2]);
- }
- break;
- case '@':
- if (argc > 2) {
- for (n = argc - 1; n > 2; n--) {
- pbstr(rquote);
- pbstr(argv[n]);
- pbstr(lquote);
- putback(COMMA);
- }
- pbstr(rquote);
- pbstr(argv[2]);
- pbstr(lquote);
- }
- break;
- default:
- PUTBACK(*p);
- PUTBACK('$');
- break;
- }
- p--;
- }
- p--;
- }
- if (p == t) /* do last character */
- PUTBACK(*p);
-}
-
-/*
- * dodefine - install definition in the table
- */
-void
-dodefine(const char *name, const char *defn)
-{
- ndptr p;
- int n;
-
- if (!*name)
- errx(1, "%s at line %lu: null definition.", CURRENT_NAME,
- CURRENT_LINE);
- if ((p = lookup(name)) == nil)
- p = addent(name);
- else if (p->defn != null)
- free((char *) p->defn);
- if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) {
- n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1);
- if (n != -1) {
- p->type = n & TYPEMASK;
- if ((n & NOARGS) == 0)
- p->type |= NEEDARGS;
- p->defn = null;
- return;
- }
- }
- if (!*defn)
- p->defn = null;
- else
- p->defn = xstrdup(defn);
- p->type = MACRTYPE;
- if (STREQ(name, defn))
- p->type |= RECDEF;
-}
-
-/*
- * dodefn - push back a quoted definition of
- * the given name.
- */
-static void
-dodefn(const char *name)
-{
- ndptr p;
- char *real;
-
- if ((p = lookup(name)) != nil) {
- if (p->defn != null) {
- pbstr(rquote);
- pbstr(p->defn);
- pbstr(lquote);
- } else if ((real = builtin_realname(p->type)) != NULL) {
- pbstr(real);
- pbstr(BUILTIN_MARKER);
- }
- }
-}
-
-/*
- * dopushdef - install a definition in the hash table
- * without removing a previous definition. Since
- * each new entry is entered in *front* of the
- * hash bucket, it hides a previous definition from
- * lookup.
- */
-static void
-dopushdef(const char *name, const char *defn)
-{
- ndptr p;
-
- if (!*name)
- errx(1, "%s at line %lu: null definition", CURRENT_NAME,
- CURRENT_LINE);
- p = addent(name);
- if (!*defn)
- p->defn = null;
- else
- p->defn = xstrdup(defn);
- p->type = MACRTYPE;
- if (STREQ(name, defn))
- p->type |= RECDEF;
-}
-
-/*
- * dump_one_def - dump the specified definition.
- */
-static void
-dump_one_def(ndptr p)
-{
- char *real;
-
- if (mimic_gnu) {
- if ((p->type & TYPEMASK) == MACRTYPE)
- fprintf(traceout, "%s:\t%s\n", p->name, p->defn);
- else {
- real = builtin_realname(p->type);
- if (real == NULL)
- real = null;
- fprintf(traceout, "%s:\t<%s>\n", p->name, real);
- }
- } else
- fprintf(traceout, "`%s'\t`%s'\n", p->name, p->defn);
-}
-
-/*
- * dodumpdef - dump the specified definitions in the hash
- * table to stderr. If nothing is specified, the entire
- * hash table is dumped.
- */
-static void
-dodump(const char *argv[], int argc)
-{
- int n;
- ndptr p;
-
- if (argc > 2) {
- for (n = 2; n < argc; n++)
- if ((p = lookup(argv[n])) != nil)
- dump_one_def(p);
- } else {
- for (n = 0; n < HASHSIZE; n++)
- for (p = hashtab[n]; p != nil; p = p->nxtptr)
- dump_one_def(p);
- }
-}
-
-/*
- * dotrace - mark some macros as traced/untraced depending upon on.
- */
-static void
-dotrace(const char *argv[], int argc, int on)
-{
- int n;
-
- if (argc > 2) {
- for (n = 2; n < argc; n++)
- mark_traced(argv[n], on);
- } else
- mark_traced(NULL, on);
-}
-
-/*
- * doifelse - select one of two alternatives - loop.
- */
-static void
-doifelse(const char *argv[], int argc)
-{
- cycle {
- if (STREQ(argv[2], argv[3]))
- pbstr(argv[4]);
- else if (argc == 6)
- pbstr(argv[5]);
- else if (argc > 6) {
- argv += 3;
- argc -= 3;
- continue;
- }
- break;
- }
-}
-
-/*
- * doinclude - include a given file.
- */
-static int
-doincl(const char *ifile)
-{
- if (ilevel + 1 == MAXINP)
- errx(1, "%s at line %lu: too many include files.",
- CURRENT_NAME, CURRENT_LINE);
- if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
- ilevel++;
- bbase[ilevel] = bufbase = bp;
- return (1);
- } else
- return (0);
-}
-
-#ifdef EXTENDED
-/*
- * dopaste - include a given file without any
- * macro processing.
- */
-static int
-dopaste(const char *pfile)
-{
- FILE *pf;
- int c;
-
- if ((pf = fopen(pfile, "r")) != NULL) {
- while ((c = getc(pf)) != EOF)
- putc(c, active);
- (void) fclose(pf);
- return (1);
- } else
- return (0);
-}
-#endif
-
-static void
-gnu_dochq(const char *argv[], int ac)
-{
- /* In gnu-m4 mode, the only way to restore quotes is to have no
- * arguments at all. */
- if (ac == 2) {
- lquote[0] = LQUOTE, lquote[1] = EOS;
- rquote[0] = RQUOTE, rquote[1] = EOS;
- } else {
- strlcpy(lquote, argv[2], sizeof(lquote));
- if(ac > 3)
- strlcpy(rquote, argv[3], sizeof(rquote));
- else
- rquote[0] = EOS;
- }
-}
-
-/*
- * dochq - change quote characters
- */
-static void
-dochq(const char *argv[], int argc)
-{
- if (argc > 2) {
- if (*argv[2])
- strlcpy(lquote, argv[2], sizeof(lquote));
- else {
- lquote[0] = LQUOTE;
- lquote[1] = EOS;
- }
- if (argc > 3) {
- if (*argv[3])
- strlcpy(rquote, argv[3], sizeof(rquote));
- } else
- strcpy(rquote, lquote);
- } else {
- lquote[0] = LQUOTE, lquote[1] = EOS;
- rquote[0] = RQUOTE, rquote[1] = EOS;
- }
-}
-
-static void
-gnu_dochc(const char *argv[], int ac)
-{
- /* In gnu-m4 mode, no arguments mean no comment
- * arguments at all. */
- if (ac == 2) {
- scommt[0] = EOS;
- ecommt[0] = EOS;
- } else {
- if (*argv[2])
- strlcpy(scommt, argv[2], sizeof(scommt));
- else
- scommt[0] = SCOMMT, scommt[1] = EOS;
- if(ac > 3 && *argv[3])
- strlcpy(ecommt, argv[3], sizeof(ecommt));
- else
- ecommt[0] = ECOMMT, ecommt[1] = EOS;
- }
-}
-/*
- * dochc - change comment characters
- */
-static void
-dochc(const char *argv[], int argc)
-{
- if (argc > 2) {
- if (*argv[2])
- strlcpy(scommt, argv[2], sizeof(scommt));
- if (argc > 3) {
- if (*argv[3])
- strlcpy(ecommt, argv[3], sizeof(ecommt));
- }
- else
- ecommt[0] = ECOMMT, ecommt[1] = EOS;
- }
- else {
- scommt[0] = SCOMMT, scommt[1] = EOS;
- ecommt[0] = ECOMMT, ecommt[1] = EOS;
- }
-}
-
-/*
- * dodivert - divert the output to a temporary file
- */
-static void
-dodiv(int n)
-{
- int fd;
-
- oindex = n;
- if (n >= maxout) {
- if (mimic_gnu)
- resizedivs(n + 10);
- else
- n = 0; /* bitbucket */
- }
-
- if (n < 0)
- n = 0; /* bitbucket */
- if (outfile[n] == NULL) {
- char fname[] = _PATH_DIVNAME;
-
- if ((fd = mkstemp(fname)) < 0 ||
- (outfile[n] = fdopen(fd, "w+")) == NULL)
- err(1, "%s: cannot divert", fname);
- if (unlink(fname) == -1)
- err(1, "%s: cannot unlink", fname);
- }
- active = outfile[n];
-}
-
-/*
- * doundivert - undivert a specified output, or all
- * other outputs, in numerical order.
- */
-static void
-doundiv(const char *argv[], int argc)
-{
- int ind;
- int n;
-
- if (argc > 2) {
- for (ind = 2; ind < argc; ind++) {
- n = atoi(argv[ind]);
- if (n > 0 && n < maxout && outfile[n] != NULL)
- getdiv(n);
-
- }
- }
- else
- for (n = 1; n < maxout; n++)
- if (outfile[n] != NULL)
- getdiv(n);
-}
-
-/*
- * dosub - select substring
- */
-static void
-dosub(const char *argv[], int argc)
-{
- const char *ap, *fc, *k;
- int nc;
-
- ap = argv[2]; /* target string */
-#ifdef EXPR
- fc = ap + expr(argv[3]); /* first char */
-#else
- fc = ap + atoi(argv[3]); /* first char */
-#endif
- nc = strlen(fc);
- if (argc >= 5)
-#ifdef EXPR
- nc = min(nc, expr(argv[4]));
-#else
- nc = min(nc, atoi(argv[4]));
-#endif
- if (fc >= ap && fc < ap + strlen(ap))
- for (k = fc + nc - 1; k >= fc; k--)
- putback(*k);
-}
-
-/*
- * map:
- * map every character of s1 that is specified in from
- * into s3 and replace in s. (source s1 remains untouched)
- *
- * This is a standard implementation of map(s,from,to) function of ICON
- * language. Within mapvec, we replace every character of "from" with
- * the corresponding character in "to". If "to" is shorter than "from",
- * than the corresponding entries are null, which means that those
- * characters dissapear altogether. Furthermore, imagine
- * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
- * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
- * ultimately maps to `*'. In order to achieve this effect in an efficient
- * manner (i.e. without multiple passes over the destination string), we
- * loop over mapvec, starting with the initial source character. if the
- * character value (dch) in this location is different than the source
- * character (sch), sch becomes dch, once again to index into mapvec, until
- * the character value stabilizes (i.e. sch = dch, in other words
- * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
- * character, it will stabilize, since mapvec[0] == 0 at all times. At the
- * end, we restore mapvec* back to normal where mapvec[n] == n for
- * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
- * about 5 times faster than any algorithm that makes multiple passes over
- * destination string.
- */
-static void
-map(char *dest, const char *src, const char *from, const char *to)
-{
- const char *tmp;
- unsigned char sch, dch;
- static char frombis[257];
- static char tobis[257];
- static unsigned char mapvec[256] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
- 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
- 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
- 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
- 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
- 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
- 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
- 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
- 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
- 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
- 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
- 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
- };
-
- if (*src) {
- if (mimic_gnu) {
- /*
- * expand character ranges on the fly
- */
- from = handledash(frombis, frombis + 256, from);
- to = handledash(tobis, tobis + 256, to);
- }
- tmp = from;
- /*
- * create a mapping between "from" and
- * "to"
- */
- while (*from)
- mapvec[(unsigned char)(*from++)] = (*to) ?
- (unsigned char)(*to++) : 0;
-
- while (*src) {
- sch = (unsigned char)(*src++);
- dch = mapvec[sch];
- while (dch != sch) {
- sch = dch;
- dch = mapvec[sch];
- }
- if ((*dest = (char)dch))
- dest++;
- }
- /*
- * restore all the changed characters
- */
- while (*tmp) {
- mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
- tmp++;
- }
- }
- *dest = '\0';
-}
-
-
-/*
- * handledash:
- * use buffer to copy the src string, expanding character ranges
- * on the way.
- */
-static const char *
-handledash(char *buffer, char *end, const char *src)
-{
- char *p;
-
- p = buffer;
- while(*src) {
- if (src[1] == '-' && src[2]) {
- unsigned char i;
- for (i = (unsigned char)src[0];
- i <= (unsigned char)src[2]; i++) {
- *p++ = i;
- if (p == end) {
- *p = '\0';
- return buffer;
- }
- }
- src += 3;
- } else
- *p++ = *src++;
- if (p == end)
- break;
- }
- *p = '\0';
- return buffer;
-}