mkfs: move directory entry manipulation
[minix.git] / usr.bin / m4 / eval.c
blob591b1944c3a8d5c40e281f7213e77a48d69aae1a
1 /* $OpenBSD: eval.c,v 1.66 2008/08/21 21:01:47 espie Exp $ */
2 /* $NetBSD: eval.c,v 1.20 2009/10/26 21:11:28 christos Exp $ */
4 /*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Ozan Yigit at York University.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
37 * eval.c
38 * Facility: m4 macro processor
39 * by: oz
41 #if HAVE_NBTOOL_CONFIG_H
42 #include "nbtool_config.h"
43 #endif
44 #include <sys/cdefs.h>
45 __RCSID("$NetBSD: eval.c,v 1.20 2009/10/26 21:11:28 christos Exp $");
47 #include <sys/types.h>
48 #include <err.h>
49 #include <errno.h>
50 #include <limits.h>
51 #include <unistd.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <stddef.h>
55 #include <string.h>
56 #include <fcntl.h>
57 #include "mdef.h"
58 #include "stdd.h"
59 #include "extern.h"
60 #include "pathnames.h"
62 static void dodefn(const char *);
63 static void dopushdef(const char *, const char *);
64 static void dodump(const char *[], int);
65 static void dotrace(const char *[], int, int);
66 static void doifelse(const char *[], int);
67 static int doincl(const char *);
68 static int dopaste(const char *);
69 static void dochq(const char *[], int);
70 static void dochc(const char *[], int);
71 static void dom4wrap(const char *);
72 static void dodiv(int);
73 static void doundiv(const char *[], int);
74 static void dosub(const char *[], int);
75 static void map(char *, const char *, const char *, const char *);
76 static const char *handledash(char *, char *, const char *);
77 static void expand_builtin(const char *[], int, int);
78 static void expand_macro(const char *[], int);
79 static void dump_one_def(const char *, struct macro_definition *);
81 unsigned long expansion_id;
84 * eval - eval all macros and builtins calls
85 * argc - number of elements in argv.
86 * argv - element vector :
87 * argv[0] = definition of a user
88 * macro or NULL if built-in.
89 * argv[1] = name of the macro or
90 * built-in.
91 * argv[2] = parameters to user-defined
92 * . macro or built-in.
93 * .
95 * A call in the form of macro-or-builtin() will result in:
96 * argv[0] = nullstr
97 * argv[1] = macro-or-builtin
98 * argv[2] = nullstr
100 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
102 void
103 eval(const char *argv[], int argc, int td, int is_traced)
105 size_t mark = SIZE_MAX;
107 expansion_id++;
108 if (td & RECDEF)
109 m4errx(1, "expanding recursive definition for %s.", argv[1]);
110 if (is_traced)
111 mark = trace(argv, argc, infile+ilevel);
112 if (td == MACRTYPE)
113 expand_macro(argv, argc);
114 else
115 expand_builtin(argv, argc, td);
116 if (mark != SIZE_MAX)
117 finish_trace(mark);
121 * expand_builtin - evaluate built-in macros.
123 void
124 expand_builtin(const char *argv[], int argc, int td)
126 int c, n;
127 int ac;
128 static int sysval = 0;
130 #ifdef DEBUG
131 printf("argc = %d\n", argc);
132 for (n = 0; n < argc; n++)
133 printf("argv[%d] = %s\n", n, argv[n]);
134 fflush(stdout);
135 #endif
138 * if argc == 3 and argv[2] is null, then we
139 * have macro-or-builtin() type call. We adjust
140 * argc to avoid further checking..
142 /* we keep the initial value for those built-ins that differentiate
143 * between builtin() and builtin.
145 ac = argc;
147 if (argc == 3 && !*(argv[2]) && !mimic_gnu)
148 argc--;
150 switch (td & TYPEMASK) {
152 case DEFITYPE:
153 if (argc > 2)
154 dodefine(argv[2], (argc > 3) ? argv[3] : null);
155 break;
157 case PUSDTYPE:
158 if (argc > 2)
159 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
160 break;
162 case DUMPTYPE:
163 dodump(argv, argc);
164 break;
166 case TRACEONTYPE:
167 dotrace(argv, argc, 1);
168 break;
170 case TRACEOFFTYPE:
171 dotrace(argv, argc, 0);
172 break;
174 case EXPRTYPE:
176 * doexpr - evaluate arithmetic
177 * expression
180 int base = 10;
181 int maxdigits = 0;
182 const char *errstr;
184 if (argc > 3) {
185 base = strtonum(argv[3], 2, 36, &errstr);
186 if (errstr) {
187 m4errx(1, "expr: base %s invalid.", argv[3]);
190 if (argc > 4) {
191 maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
192 if (errstr) {
193 m4errx(1, "expr: maxdigits %s invalid.", argv[4]);
196 if (argc > 2)
197 pbnumbase(expr(argv[2]), base, maxdigits);
198 break;
201 case IFELTYPE:
202 if (argc > 4)
203 doifelse(argv, argc);
204 break;
206 case IFDFTYPE:
208 * doifdef - select one of two
209 * alternatives based on the existence of
210 * another definition
212 if (argc > 3) {
213 if (lookup_macro_definition(argv[2]) != NULL)
214 pbstr(argv[3]);
215 else if (argc > 4)
216 pbstr(argv[4]);
218 break;
220 case LENGTYPE:
222 * dolen - find the length of the
223 * argument
225 pbnum((argc > 2) ? strlen(argv[2]) : 0);
226 break;
228 case INCRTYPE:
230 * doincr - increment the value of the
231 * argument
233 if (argc > 2)
234 pbnum(atoi(argv[2]) + 1);
235 break;
237 case DECRTYPE:
239 * dodecr - decrement the value of the
240 * argument
242 if (argc > 2)
243 pbnum(atoi(argv[2]) - 1);
244 break;
246 case SYSCTYPE:
248 * dosys - execute system command
250 if (argc > 2) {
251 fflush(stdout);
252 sysval = system(argv[2]);
254 break;
256 case SYSVTYPE:
258 * dosysval - return value of the last
259 * system call.
262 pbnum(sysval);
263 break;
265 case ESYSCMDTYPE:
266 if (argc > 2)
267 doesyscmd(argv[2]);
268 break;
269 case INCLTYPE:
270 if (argc > 2)
271 if (!doincl(argv[2]))
272 err(1, "%s at line %lu: include(%s)",
273 CURRENT_NAME, CURRENT_LINE, argv[2]);
274 break;
276 case SINCTYPE:
277 if (argc > 2)
278 (void) doincl(argv[2]);
279 break;
280 #ifdef EXTENDED
281 case PASTTYPE:
282 if (argc > 2)
283 if (!dopaste(argv[2]))
284 err(1, "%s at line %lu: paste(%s)",
285 CURRENT_NAME, CURRENT_LINE, argv[2]);
286 break;
288 case SPASTYPE:
289 if (argc > 2)
290 (void) dopaste(argv[2]);
291 break;
292 case FORMATTYPE:
293 doformat(argv, argc);
294 break;
295 #endif
296 case CHNQTYPE:
297 dochq(argv, ac);
298 break;
300 case CHNCTYPE:
301 dochc(argv, argc);
302 break;
304 case SUBSTYPE:
306 * dosub - select substring
309 if (argc > 3)
310 dosub(argv, argc);
311 break;
313 case SHIFTYPE:
315 * doshift - push back all arguments
316 * except the first one (i.e. skip
317 * argv[2])
319 if (argc > 3) {
320 for (n = argc - 1; n > 3; n--) {
321 pbstr(rquote);
322 pbstr(argv[n]);
323 pbstr(lquote);
324 pushback(COMMA);
326 pbstr(rquote);
327 pbstr(argv[3]);
328 pbstr(lquote);
330 break;
332 case DIVRTYPE:
333 if (argc > 2 && (n = atoi(argv[2])) != 0)
334 dodiv(n);
335 else {
336 active = stdout;
337 oindex = 0;
339 break;
341 case UNDVTYPE:
342 doundiv(argv, argc);
343 break;
345 case DIVNTYPE:
347 * dodivnum - return the number of
348 * current output diversion
350 pbnum(oindex);
351 break;
353 case UNDFTYPE:
355 * doundefine - undefine a previously
356 * defined macro(s) or m4 keyword(s).
358 if (argc > 2)
359 for (n = 2; n < argc; n++)
360 macro_undefine(argv[n]);
361 break;
363 case POPDTYPE:
365 * dopopdef - remove the topmost
366 * definitions of macro(s) or m4
367 * keyword(s).
369 if (argc > 2)
370 for (n = 2; n < argc; n++)
371 macro_popdef(argv[n]);
372 break;
374 case MKTMTYPE:
376 * dotemp - create a temporary file
378 if (argc > 2) {
379 int fd;
380 char *temp;
382 temp = xstrdup(argv[2]);
384 fd = mkstemp(temp);
385 if (fd == -1)
386 err(1,
387 "%s at line %lu: couldn't make temp file %s",
388 CURRENT_NAME, CURRENT_LINE, argv[2]);
389 close(fd);
390 pbstr(temp);
391 free(temp);
393 break;
395 case TRNLTYPE:
397 * dotranslit - replace all characters in
398 * the source string that appears in the
399 * "from" string with the corresponding
400 * characters in the "to" string.
402 if (argc > 3) {
403 char *temp;
405 temp = xalloc(strlen(argv[2])+1, NULL);
406 if (argc > 4)
407 map(temp, argv[2], argv[3], argv[4]);
408 else
409 map(temp, argv[2], argv[3], null);
410 pbstr(temp);
411 free(temp);
412 } else if (argc > 2)
413 pbstr(argv[2]);
414 break;
416 case INDXTYPE:
418 * doindex - find the index of the second
419 * argument string in the first argument
420 * string. -1 if not present.
422 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
423 break;
425 case ERRPTYPE:
427 * doerrp - print the arguments to stderr
428 * file
430 if (argc > 2) {
431 for (n = 2; n < argc; n++)
432 fprintf(stderr, "%s ", argv[n]);
433 fprintf(stderr, "\n");
435 break;
437 case DNLNTYPE:
439 * dodnl - eat-up-to and including
440 * newline
442 while ((c = gpbc()) != '\n' && c != EOF)
444 break;
446 case M4WRTYPE:
448 * dom4wrap - set up for
449 * wrap-up/wind-down activity
451 if (argc > 2)
452 dom4wrap(argv[2]);
453 break;
455 case EXITTYPE:
457 * doexit - immediate exit from m4.
459 killdiv();
460 exit((argc > 2) ? atoi(argv[2]) : 0);
461 break;
463 case DEFNTYPE:
464 if (argc > 2)
465 for (n = 2; n < argc; n++)
466 dodefn(argv[n]);
467 break;
469 case INDIRTYPE: /* Indirect call */
470 if (argc > 2)
471 doindir(argv, argc);
472 break;
474 case BUILTINTYPE: /* Builtins only */
475 if (argc > 2)
476 dobuiltin(argv, argc);
477 break;
479 case PATSTYPE:
480 if (argc > 2)
481 dopatsubst(argv, argc);
482 break;
483 case REGEXPTYPE:
484 if (argc > 2)
485 doregexp(argv, argc);
486 break;
487 case LINETYPE:
488 doprintlineno(infile+ilevel);
489 break;
490 case FILENAMETYPE:
491 doprintfilename(infile+ilevel);
492 break;
493 case SELFTYPE:
494 pbstr(rquote);
495 pbstr(argv[1]);
496 pbstr(lquote);
497 break;
498 default:
499 m4errx(1, "eval: major botch.");
500 break;
505 * expand_macro - user-defined macro expansion
507 void
508 expand_macro(const char *argv[], int argc)
510 const char *t;
511 const char *p;
512 int n;
513 int argno;
515 t = argv[0]; /* defn string as a whole */
516 p = t;
517 while (*p)
518 p++;
519 p--; /* last character of defn */
520 while (p > t) {
521 if (*(p - 1) != ARGFLAG)
522 PUSHBACK(*p);
523 else {
524 switch (*p) {
526 case '#':
527 pbnum(argc - 2);
528 break;
529 case '0':
530 case '1':
531 case '2':
532 case '3':
533 case '4':
534 case '5':
535 case '6':
536 case '7':
537 case '8':
538 case '9':
539 if ((argno = *p - '0') < argc - 1)
540 pbstr(argv[argno + 1]);
541 break;
542 case '*':
543 if (argc > 2) {
544 for (n = argc - 1; n > 2; n--) {
545 pbstr(argv[n]);
546 pushback(COMMA);
548 pbstr(argv[2]);
550 break;
551 case '@':
552 if (argc > 2) {
553 for (n = argc - 1; n > 2; n--) {
554 pbstr(rquote);
555 pbstr(argv[n]);
556 pbstr(lquote);
557 pushback(COMMA);
559 pbstr(rquote);
560 pbstr(argv[2]);
561 pbstr(lquote);
563 break;
564 default:
565 PUSHBACK(*p);
566 PUSHBACK('$');
567 break;
569 p--;
571 p--;
573 if (p == t) /* do last character */
574 PUSHBACK(*p);
579 * dodefine - install definition in the table
581 void
582 dodefine(const char *name, const char *defn)
584 if (!*name && !mimic_gnu)
585 m4errx(1, "null definition.");
586 else
587 macro_define(name, defn);
591 * dodefn - push back a quoted definition of
592 * the given name.
594 static void
595 dodefn(const char *name)
597 struct macro_definition *p;
599 if ((p = lookup_macro_definition(name)) != NULL) {
600 if ((p->type & TYPEMASK) == MACRTYPE) {
601 pbstr(rquote);
602 pbstr(p->defn);
603 pbstr(lquote);
604 } else {
605 pbstr(p->defn);
606 pbstr(BUILTIN_MARKER);
612 * dopushdef - install a definition in the hash table
613 * without removing a previous definition. Since
614 * each new entry is entered in *front* of the
615 * hash bucket, it hides a previous definition from
616 * lookup.
618 static void
619 dopushdef(const char *name, const char *defn)
621 if (!*name && !mimic_gnu)
622 m4errx(1, "null definition.");
623 else
624 macro_pushdef(name, defn);
628 * dump_one_def - dump the specified definition.
630 static void
631 dump_one_def(const char *name, struct macro_definition *p)
633 if (!traceout)
634 traceout = stderr;
635 if (mimic_gnu) {
636 if ((p->type & TYPEMASK) == MACRTYPE)
637 fprintf(traceout, "%s:\t%s\n", name, p->defn);
638 else {
639 fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
641 } else
642 fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
646 * dodumpdef - dump the specified definitions in the hash
647 * table to stderr. If nothing is specified, the entire
648 * hash table is dumped.
650 static void
651 dodump(const char *argv[], int argc)
653 int n;
654 struct macro_definition *p;
656 if (argc > 2) {
657 for (n = 2; n < argc; n++)
658 if ((p = lookup_macro_definition(argv[n])) != NULL)
659 dump_one_def(argv[n], p);
660 } else
661 macro_for_all(dump_one_def);
665 * dotrace - mark some macros as traced/untraced depending upon on.
667 static void
668 dotrace(const char *argv[], int argc, int on)
670 int n;
672 if (argc > 2) {
673 for (n = 2; n < argc; n++)
674 mark_traced(argv[n], on);
675 } else
676 mark_traced(NULL, on);
680 * doifelse - select one of two alternatives - loop.
682 static void
683 doifelse(const char *argv[], int argc)
685 cycle {
686 if (STREQ(argv[2], argv[3]))
687 pbstr(argv[4]);
688 else if (argc == 6)
689 pbstr(argv[5]);
690 else if (argc > 6) {
691 argv += 3;
692 argc -= 3;
693 continue;
695 break;
700 * doinclude - include a given file.
702 static int
703 doincl(const char *ifile)
705 if (ilevel + 1 == MAXINP)
706 m4errx(1, "too many include files.");
707 if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
708 ilevel++;
709 bbase[ilevel] = bufbase = bp;
710 return (1);
711 } else
712 return (0);
715 #ifdef EXTENDED
717 * dopaste - include a given file without any
718 * macro processing.
720 static int
721 dopaste(const char *pfile)
723 FILE *pf;
724 int c;
726 if ((pf = fopen(pfile, "r")) != NULL) {
727 if (synch_lines)
728 fprintf(active, "#line 1 \"%s\"\n", pfile);
729 while ((c = getc(pf)) != EOF)
730 putc(c, active);
731 (void) fclose(pf);
732 emit_synchline();
733 return (1);
734 } else
735 return (0);
737 #endif
740 * dochq - change quote characters
742 static void
743 dochq(const char *argv[], int ac)
745 if (ac == 2) {
746 lquote[0] = LQUOTE; lquote[1] = EOS;
747 rquote[0] = RQUOTE; rquote[1] = EOS;
748 } else {
749 strlcpy(lquote, argv[2], sizeof(lquote));
750 if (ac > 3) {
751 strlcpy(rquote, argv[3], sizeof(rquote));
752 } else {
753 rquote[0] = ECOMMT; rquote[1] = EOS;
759 * dochc - change comment characters
761 static void
762 dochc(const char *argv[], int argc)
764 /* XXX Note that there is no difference between no argument and a single
765 * empty argument.
767 if (argc == 2) {
768 scommt[0] = EOS;
769 ecommt[0] = EOS;
770 } else {
771 strlcpy(scommt, argv[2], sizeof(scommt));
772 if (argc == 3) {
773 ecommt[0] = ECOMMT; ecommt[1] = EOS;
774 } else {
775 strlcpy(ecommt, argv[3], sizeof(ecommt));
781 * dom4wrap - expand text at EOF
783 static void
784 dom4wrap(const char *text)
786 if (wrapindex >= maxwraps) {
787 if (maxwraps == 0)
788 maxwraps = 16;
789 else
790 maxwraps *= 2;
791 m4wraps = xrealloc(m4wraps, maxwraps * sizeof(*m4wraps),
792 "too many m4wraps");
794 m4wraps[wrapindex++] = xstrdup(text);
798 * dodivert - divert the output to a temporary file
800 static void
801 dodiv(int n)
803 int fd;
805 oindex = n;
806 if (n >= maxout) {
807 if (mimic_gnu)
808 resizedivs(n + 10);
809 else
810 n = 0; /* bitbucket */
813 if (n < 0)
814 n = 0; /* bitbucket */
815 if (outfile[n] == NULL) {
816 char fname[] = _PATH_DIVNAME;
818 if ((fd = mkstemp(fname)) < 0 ||
819 (outfile[n] = fdopen(fd, "w+")) == NULL)
820 err(1, "%s: cannot divert", fname);
821 if (unlink(fname) == -1)
822 err(1, "%s: cannot unlink", fname);
824 active = outfile[n];
828 * doundivert - undivert a specified output, or all
829 * other outputs, in numerical order.
831 static void
832 doundiv(const char *argv[], int argc)
834 int ind;
835 int n;
837 if (argc > 2) {
838 for (ind = 2; ind < argc; ind++) {
839 const char *errstr;
840 n = strtonum(argv[ind], 1, INT_MAX, &errstr);
841 if (errstr) {
842 if (errno == EINVAL && mimic_gnu)
843 getdivfile(argv[ind]);
844 } else {
845 if (n < maxout && outfile[n] != NULL)
846 getdiv(n);
850 else
851 for (n = 1; n < maxout; n++)
852 if (outfile[n] != NULL)
853 getdiv(n);
857 * dosub - select substring
859 static void
860 dosub(const char *argv[], int argc)
862 const char *ap, *fc, *k;
863 int nc;
865 ap = argv[2]; /* target string */
866 #ifdef EXPR
867 fc = ap + expr(argv[3]); /* first char */
868 #else
869 fc = ap + atoi(argv[3]); /* first char */
870 #endif
871 nc = strlen(fc);
872 if (argc >= 5)
873 #ifdef EXPR
874 nc = min(nc, expr(argv[4]));
875 #else
876 nc = min(nc, atoi(argv[4]));
877 #endif
878 if (fc >= ap && fc < ap + strlen(ap))
879 for (k = fc + nc - 1; k >= fc; k--)
880 pushback(*k);
884 * map:
885 * map every character of s1 that is specified in from
886 * into s3 and replace in s. (source s1 remains untouched)
888 * This is a standard implementation of map(s,from,to) function of ICON
889 * language. Within mapvec, we replace every character of "from" with
890 * the corresponding character in "to". If "to" is shorter than "from",
891 * than the corresponding entries are null, which means that those
892 * characters dissapear altogether. Furthermore, imagine
893 * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
894 * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
895 * ultimately maps to `*'. In order to achieve this effect in an efficient
896 * manner (i.e. without multiple passes over the destination string), we
897 * loop over mapvec, starting with the initial source character. if the
898 * character value (dch) in this location is different than the source
899 * character (sch), sch becomes dch, once again to index into mapvec, until
900 * the character value stabilizes (i.e. sch = dch, in other words
901 * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
902 * character, it will stabilize, since mapvec[0] == 0 at all times. At the
903 * end, we restore mapvec* back to normal where mapvec[n] == n for
904 * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
905 * about 5 times faster than any algorithm that makes multiple passes over
906 * destination string.
908 static void
909 map(char *dest, const char *src, const char *from, const char *to)
911 const char *tmp;
912 unsigned char sch, dch;
913 static char frombis[257];
914 static char tobis[257];
915 static unsigned char mapvec[256] = {
916 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
917 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
918 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
919 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
920 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
921 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
922 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
923 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
924 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
925 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
926 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
927 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
928 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
929 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
930 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
931 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
932 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
933 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
936 if (*src) {
937 if (mimic_gnu) {
939 * expand character ranges on the fly
941 from = handledash(frombis, frombis + 256, from);
942 to = handledash(tobis, tobis + 256, to);
944 tmp = from;
946 * create a mapping between "from" and
947 * "to"
949 while (*from)
950 mapvec[(unsigned char)(*from++)] = (*to) ?
951 (unsigned char)(*to++) : 0;
953 while (*src) {
954 sch = (unsigned char)(*src++);
955 dch = mapvec[sch];
956 while (dch != sch) {
957 sch = dch;
958 dch = mapvec[sch];
960 if ((*dest = (char)dch))
961 dest++;
964 * restore all the changed characters
966 while (*tmp) {
967 mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
968 tmp++;
971 *dest = '\0';
976 * handledash:
977 * use buffer to copy the src string, expanding character ranges
978 * on the way.
980 static const char *
981 handledash(char *buffer, char *end, const char *src)
983 char *p;
985 p = buffer;
986 while(*src) {
987 if (src[1] == '-' && src[2]) {
988 unsigned char i;
989 if ((unsigned char)src[0] <= (unsigned char)src[2]) {
990 for (i = (unsigned char)src[0];
991 i <= (unsigned char)src[2]; i++) {
992 *p++ = i;
993 if (p == end) {
994 *p = '\0';
995 return buffer;
998 } else {
999 for (i = (unsigned char)src[0];
1000 i >= (unsigned char)src[2]; i--) {
1001 *p++ = i;
1002 if (p == end) {
1003 *p = '\0';
1004 return buffer;
1008 src += 3;
1009 } else
1010 *p++ = *src++;
1011 if (p == end)
1012 break;
1014 *p = '\0';
1015 return buffer;