t40c term[] count fix
[minix.git] / usr.bin / m4 / eval.c
blob4b5340e3f83ba866a5d530792c00a75f050b4f71
1 /* $OpenBSD: eval.c,v 1.66 2008/08/21 21:01:47 espie Exp $ */
2 /* $NetBSD: eval.c,v 1.22 2011/08/21 23:38:43 dholland 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.22 2011/08/21 23:38:43 dholland 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 <stdint.h>
56 #include <string.h>
57 #include <fcntl.h>
58 #include "mdef.h"
59 #include "stdd.h"
60 #include "extern.h"
61 #include "pathnames.h"
63 static void dodefn(const char *);
64 static void dopushdef(const char *, const char *);
65 static void dodump(const char *[], int);
66 static void dotrace(const char *[], int, int);
67 static void doifelse(const char *[], int);
68 static int doincl(const char *);
69 static int dopaste(const char *);
70 static void dochq(const char *[], int);
71 static void dochc(const char *[], int);
72 static void dom4wrap(const char *);
73 static void dodiv(int);
74 static void doundiv(const char *[], int);
75 static void dosub(const char *[], int);
76 static void map(char *, const char *, const char *, const char *);
77 static const char *handledash(char *, char *, const char *);
78 static void expand_builtin(const char *[], int, int);
79 static void expand_macro(const char *[], int);
80 static void dump_one_def(const char *, struct macro_definition *);
82 unsigned long expansion_id;
85 * eval - eval all macros and builtins calls
86 * argc - number of elements in argv.
87 * argv - element vector :
88 * argv[0] = definition of a user
89 * macro or NULL if built-in.
90 * argv[1] = name of the macro or
91 * built-in.
92 * argv[2] = parameters to user-defined
93 * . macro or built-in.
94 * .
96 * A call in the form of macro-or-builtin() will result in:
97 * argv[0] = nullstr
98 * argv[1] = macro-or-builtin
99 * argv[2] = nullstr
101 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
103 void
104 eval(const char *argv[], int argc, int td, int is_traced)
106 size_t mark = SIZE_MAX;
108 expansion_id++;
109 if (td & RECDEF)
110 m4errx(1, "expanding recursive definition for %s.", argv[1]);
111 if (is_traced)
112 mark = trace(argv, argc, infile+ilevel);
113 if (td == MACRTYPE)
114 expand_macro(argv, argc);
115 else
116 expand_builtin(argv, argc, td);
117 if (mark != SIZE_MAX)
118 finish_trace(mark);
122 * expand_builtin - evaluate built-in macros.
124 void
125 expand_builtin(const char *argv[], int argc, int td)
127 int c, n;
128 int ac;
129 static int sysval = 0;
131 #ifdef DEBUG
132 printf("argc = %d\n", argc);
133 for (n = 0; n < argc; n++)
134 printf("argv[%d] = %s\n", n, argv[n]);
135 fflush(stdout);
136 #endif
139 * if argc == 3 and argv[2] is null, then we
140 * have macro-or-builtin() type call. We adjust
141 * argc to avoid further checking..
143 /* we keep the initial value for those built-ins that differentiate
144 * between builtin() and builtin.
146 ac = argc;
148 if (argc == 3 && !*(argv[2]) && !mimic_gnu)
149 argc--;
151 switch (td & TYPEMASK) {
153 case DEFITYPE:
154 if (argc > 2)
155 dodefine(argv[2], (argc > 3) ? argv[3] : null);
156 break;
158 case PUSDTYPE:
159 if (argc > 2)
160 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
161 break;
163 case DUMPTYPE:
164 dodump(argv, argc);
165 break;
167 case TRACEONTYPE:
168 dotrace(argv, argc, 1);
169 break;
171 case TRACEOFFTYPE:
172 dotrace(argv, argc, 0);
173 break;
175 case EXPRTYPE:
177 * doexpr - evaluate arithmetic
178 * expression
181 int base = 10;
182 int maxdigits = 0;
183 const char *errstr;
185 if (argc > 3) {
186 base = strtonum(argv[3], 2, 36, &errstr);
187 if (errstr) {
188 m4errx(1, "expr: base %s invalid.", argv[3]);
191 if (argc > 4) {
192 maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
193 if (errstr) {
194 m4errx(1, "expr: maxdigits %s invalid.", argv[4]);
197 if (argc > 2)
198 pbnumbase(expr(argv[2]), base, maxdigits);
199 break;
202 case IFELTYPE:
203 if (argc > 4)
204 doifelse(argv, argc);
205 break;
207 case IFDFTYPE:
209 * doifdef - select one of two
210 * alternatives based on the existence of
211 * another definition
213 if (argc > 3) {
214 if (lookup_macro_definition(argv[2]) != NULL)
215 pbstr(argv[3]);
216 else if (argc > 4)
217 pbstr(argv[4]);
219 break;
221 case LENGTYPE:
223 * dolen - find the length of the
224 * argument
226 pbnum((argc > 2) ? strlen(argv[2]) : 0);
227 break;
229 case INCRTYPE:
231 * doincr - increment the value of the
232 * argument
234 if (argc > 2)
235 pbnum(atoi(argv[2]) + 1);
236 break;
238 case DECRTYPE:
240 * dodecr - decrement the value of the
241 * argument
243 if (argc > 2)
244 pbnum(atoi(argv[2]) - 1);
245 break;
247 case SYSCTYPE:
249 * dosys - execute system command
251 if (argc > 2) {
252 fflush(stdout);
253 sysval = system(argv[2]);
255 break;
257 case SYSVTYPE:
259 * dosysval - return value of the last
260 * system call.
263 pbnum(sysval);
264 break;
266 case ESYSCMDTYPE:
267 if (argc > 2)
268 doesyscmd(argv[2]);
269 break;
270 case INCLTYPE:
271 if (argc > 2)
272 if (!doincl(argv[2]))
273 err(1, "%s at line %lu: include(%s)",
274 CURRENT_NAME, CURRENT_LINE, argv[2]);
275 break;
277 case SINCTYPE:
278 if (argc > 2)
279 (void) doincl(argv[2]);
280 break;
281 #ifdef EXTENDED
282 case PASTTYPE:
283 if (argc > 2)
284 if (!dopaste(argv[2]))
285 err(1, "%s at line %lu: paste(%s)",
286 CURRENT_NAME, CURRENT_LINE, argv[2]);
287 break;
289 case SPASTYPE:
290 if (argc > 2)
291 (void) dopaste(argv[2]);
292 break;
293 case FORMATTYPE:
294 doformat(argv, argc);
295 break;
296 #endif
297 case CHNQTYPE:
298 dochq(argv, ac);
299 break;
301 case CHNCTYPE:
302 dochc(argv, argc);
303 break;
305 case SUBSTYPE:
307 * dosub - select substring
310 if (argc > 3)
311 dosub(argv, argc);
312 break;
314 case SHIFTYPE:
316 * doshift - push back all arguments
317 * except the first one (i.e. skip
318 * argv[2])
320 if (argc > 3) {
321 for (n = argc - 1; n > 3; n--) {
322 pbstr(rquote);
323 pbstr(argv[n]);
324 pbstr(lquote);
325 pushback(COMMA);
327 pbstr(rquote);
328 pbstr(argv[3]);
329 pbstr(lquote);
331 break;
333 case DIVRTYPE:
334 if (argc > 2 && (n = atoi(argv[2])) != 0)
335 dodiv(n);
336 else {
337 active = stdout;
338 oindex = 0;
340 break;
342 case UNDVTYPE:
343 doundiv(argv, argc);
344 break;
346 case DIVNTYPE:
348 * dodivnum - return the number of
349 * current output diversion
351 pbnum(oindex);
352 break;
354 case UNDFTYPE:
356 * doundefine - undefine a previously
357 * defined macro(s) or m4 keyword(s).
359 if (argc > 2)
360 for (n = 2; n < argc; n++)
361 macro_undefine(argv[n]);
362 break;
364 case POPDTYPE:
366 * dopopdef - remove the topmost
367 * definitions of macro(s) or m4
368 * keyword(s).
370 if (argc > 2)
371 for (n = 2; n < argc; n++)
372 macro_popdef(argv[n]);
373 break;
375 case MKTMTYPE:
377 * dotemp - create a temporary file
379 if (argc > 2) {
380 int fd;
381 char *temp;
383 temp = xstrdup(argv[2]);
385 fd = mkstemp(temp);
386 if (fd == -1)
387 err(1,
388 "%s at line %lu: couldn't make temp file %s",
389 CURRENT_NAME, CURRENT_LINE, argv[2]);
390 close(fd);
391 pbstr(temp);
392 free(temp);
394 break;
396 case TRNLTYPE:
398 * dotranslit - replace all characters in
399 * the source string that appears in the
400 * "from" string with the corresponding
401 * characters in the "to" string.
403 if (argc > 3) {
404 char *temp;
406 temp = xalloc(strlen(argv[2])+1, NULL);
407 if (argc > 4)
408 map(temp, argv[2], argv[3], argv[4]);
409 else
410 map(temp, argv[2], argv[3], null);
411 pbstr(temp);
412 free(temp);
413 } else if (argc > 2)
414 pbstr(argv[2]);
415 break;
417 case INDXTYPE:
419 * doindex - find the index of the second
420 * argument string in the first argument
421 * string. -1 if not present.
423 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
424 break;
426 case ERRPTYPE:
428 * doerrp - print the arguments to stderr
429 * file
431 if (argc > 2) {
432 for (n = 2; n < argc; n++)
433 fprintf(stderr, "%s%s",
434 mimic_gnu && n == 2 ? "" : " ",
435 argv[n]);
436 if (!mimic_gnu)
437 fprintf(stderr, "\n");
439 break;
441 case DNLNTYPE:
443 * dodnl - eat-up-to and including
444 * newline
446 while ((c = gpbc()) != '\n' && c != EOF)
448 break;
450 case M4WRTYPE:
452 * dom4wrap - set up for
453 * wrap-up/wind-down activity
455 if (argc > 2)
456 dom4wrap(argv[2]);
457 break;
459 case EXITTYPE:
461 * doexit - immediate exit from m4.
463 killdiv();
464 exit((argc > 2) ? atoi(argv[2]) : 0);
465 break;
467 case DEFNTYPE:
468 if (argc > 2)
469 for (n = 2; n < argc; n++)
470 dodefn(argv[n]);
471 break;
473 case INDIRTYPE: /* Indirect call */
474 if (argc > 2)
475 doindir(argv, argc);
476 break;
478 case BUILTINTYPE: /* Builtins only */
479 if (argc > 2)
480 dobuiltin(argv, argc);
481 break;
483 case PATSTYPE:
484 if (argc > 2)
485 dopatsubst(argv, argc);
486 break;
487 case REGEXPTYPE:
488 if (argc > 2)
489 doregexp(argv, argc);
490 break;
491 case LINETYPE:
492 doprintlineno(infile+ilevel);
493 break;
494 case FILENAMETYPE:
495 doprintfilename(infile+ilevel);
496 break;
497 case SELFTYPE:
498 pbstr(rquote);
499 pbstr(argv[1]);
500 pbstr(lquote);
501 break;
502 default:
503 m4errx(1, "eval: major botch.");
504 break;
509 * expand_macro - user-defined macro expansion
511 void
512 expand_macro(const char *argv[], int argc)
514 const char *t;
515 const char *p;
516 int n;
517 int argno;
519 t = argv[0]; /* defn string as a whole */
520 p = t;
521 while (*p)
522 p++;
523 p--; /* last character of defn */
524 while (p > t) {
525 if (*(p - 1) != ARGFLAG)
526 PUSHBACK(*p);
527 else {
528 switch (*p) {
530 case '#':
531 pbnum(argc - 2);
532 break;
533 case '0':
534 case '1':
535 case '2':
536 case '3':
537 case '4':
538 case '5':
539 case '6':
540 case '7':
541 case '8':
542 case '9':
543 if ((argno = *p - '0') < argc - 1)
544 pbstr(argv[argno + 1]);
545 break;
546 case '*':
547 if (argc > 2) {
548 for (n = argc - 1; n > 2; n--) {
549 pbstr(argv[n]);
550 pushback(COMMA);
552 pbstr(argv[2]);
554 break;
555 case '@':
556 if (argc > 2) {
557 for (n = argc - 1; n > 2; n--) {
558 pbstr(rquote);
559 pbstr(argv[n]);
560 pbstr(lquote);
561 pushback(COMMA);
563 pbstr(rquote);
564 pbstr(argv[2]);
565 pbstr(lquote);
567 break;
568 default:
569 PUSHBACK(*p);
570 PUSHBACK('$');
571 break;
573 p--;
575 p--;
577 if (p == t) /* do last character */
578 PUSHBACK(*p);
583 * dodefine - install definition in the table
585 void
586 dodefine(const char *name, const char *defn)
588 if (!*name && !mimic_gnu)
589 m4errx(1, "null definition.");
590 else
591 macro_define(name, defn);
595 * dodefn - push back a quoted definition of
596 * the given name.
598 static void
599 dodefn(const char *name)
601 struct macro_definition *p;
603 if ((p = lookup_macro_definition(name)) != NULL) {
604 if ((p->type & TYPEMASK) == MACRTYPE) {
605 pbstr(rquote);
606 pbstr(p->defn);
607 pbstr(lquote);
608 } else {
609 pbstr(p->defn);
610 pbstr(BUILTIN_MARKER);
616 * dopushdef - install a definition in the hash table
617 * without removing a previous definition. Since
618 * each new entry is entered in *front* of the
619 * hash bucket, it hides a previous definition from
620 * lookup.
622 static void
623 dopushdef(const char *name, const char *defn)
625 if (!*name && !mimic_gnu)
626 m4errx(1, "null definition.");
627 else
628 macro_pushdef(name, defn);
632 * dump_one_def - dump the specified definition.
634 static void
635 dump_one_def(const char *name, struct macro_definition *p)
637 if (!traceout)
638 traceout = stderr;
639 if (mimic_gnu) {
640 if ((p->type & TYPEMASK) == MACRTYPE)
641 fprintf(traceout, "%s:\t%s\n", name, p->defn);
642 else {
643 fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
645 } else
646 fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
650 * dodumpdef - dump the specified definitions in the hash
651 * table to stderr. If nothing is specified, the entire
652 * hash table is dumped.
654 static void
655 dodump(const char *argv[], int argc)
657 int n;
658 struct macro_definition *p;
660 if (argc > 2) {
661 for (n = 2; n < argc; n++)
662 if ((p = lookup_macro_definition(argv[n])) != NULL)
663 dump_one_def(argv[n], p);
664 } else
665 macro_for_all(dump_one_def);
669 * dotrace - mark some macros as traced/untraced depending upon on.
671 static void
672 dotrace(const char *argv[], int argc, int on)
674 int n;
676 if (argc > 2) {
677 for (n = 2; n < argc; n++)
678 mark_traced(argv[n], on);
679 } else
680 mark_traced(NULL, on);
684 * doifelse - select one of two alternatives - loop.
686 static void
687 doifelse(const char *argv[], int argc)
689 cycle {
690 if (STREQ(argv[2], argv[3]))
691 pbstr(argv[4]);
692 else if (argc == 6)
693 pbstr(argv[5]);
694 else if (argc > 6) {
695 argv += 3;
696 argc -= 3;
697 continue;
699 break;
704 * doinclude - include a given file.
706 static int
707 doincl(const char *ifile)
709 if (ilevel + 1 == MAXINP)
710 m4errx(1, "too many include files.");
711 if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
712 ilevel++;
713 bbase[ilevel] = bufbase = bp;
714 return (1);
715 } else
716 return (0);
719 #ifdef EXTENDED
721 * dopaste - include a given file without any
722 * macro processing.
724 static int
725 dopaste(const char *pfile)
727 FILE *pf;
728 int c;
730 if ((pf = fopen(pfile, "r")) != NULL) {
731 if (synch_lines)
732 fprintf(active, "#line 1 \"%s\"\n", pfile);
733 while ((c = getc(pf)) != EOF)
734 putc(c, active);
735 (void) fclose(pf);
736 emit_synchline();
737 return (1);
738 } else
739 return (0);
741 #endif
744 * dochq - change quote characters
746 static void
747 dochq(const char *argv[], int ac)
749 if (ac == 2) {
750 lquote[0] = LQUOTE; lquote[1] = EOS;
751 rquote[0] = RQUOTE; rquote[1] = EOS;
752 } else {
753 strlcpy(lquote, argv[2], sizeof(lquote));
754 if (ac > 3) {
755 strlcpy(rquote, argv[3], sizeof(rquote));
756 } else {
757 rquote[0] = ECOMMT; rquote[1] = EOS;
763 * dochc - change comment characters
765 static void
766 dochc(const char *argv[], int argc)
768 /* XXX Note that there is no difference between no argument and a single
769 * empty argument.
771 if (argc == 2) {
772 scommt[0] = EOS;
773 ecommt[0] = EOS;
774 } else {
775 strlcpy(scommt, argv[2], sizeof(scommt));
776 if (argc == 3) {
777 ecommt[0] = ECOMMT; ecommt[1] = EOS;
778 } else {
779 strlcpy(ecommt, argv[3], sizeof(ecommt));
785 * dom4wrap - expand text at EOF
787 static void
788 dom4wrap(const char *text)
790 if (wrapindex >= maxwraps) {
791 if (maxwraps == 0)
792 maxwraps = 16;
793 else
794 maxwraps *= 2;
795 m4wraps = xrealloc(m4wraps, maxwraps * sizeof(*m4wraps),
796 "too many m4wraps");
798 m4wraps[wrapindex++] = xstrdup(text);
802 * dodivert - divert the output to a temporary file
804 static void
805 dodiv(int n)
807 int fd;
809 oindex = n;
810 if (n >= maxout) {
811 if (mimic_gnu)
812 resizedivs(n + 10);
813 else
814 n = 0; /* bitbucket */
817 if (n < 0)
818 n = 0; /* bitbucket */
819 if (outfile[n] == NULL) {
820 char fname[] = _PATH_DIVNAME;
822 if ((fd = mkstemp(fname)) < 0 ||
823 (outfile[n] = fdopen(fd, "w+")) == NULL)
824 err(1, "%s: cannot divert", fname);
825 if (unlink(fname) == -1)
826 err(1, "%s: cannot unlink", fname);
828 active = outfile[n];
832 * doundivert - undivert a specified output, or all
833 * other outputs, in numerical order.
835 static void
836 doundiv(const char *argv[], int argc)
838 int ind;
839 int n;
841 if (argc > 2) {
842 for (ind = 2; ind < argc; ind++) {
843 const char *errstr;
844 n = strtonum(argv[ind], 1, INT_MAX, &errstr);
845 if (errstr) {
846 if (errno == EINVAL && mimic_gnu)
847 getdivfile(argv[ind]);
848 } else {
849 if (n < maxout && outfile[n] != NULL)
850 getdiv(n);
854 else
855 for (n = 1; n < maxout; n++)
856 if (outfile[n] != NULL)
857 getdiv(n);
861 * dosub - select substring
863 static void
864 dosub(const char *argv[], int argc)
866 const char *ap, *fc, *k;
867 int nc;
869 ap = argv[2]; /* target string */
870 #ifdef EXPR
871 fc = ap + expr(argv[3]); /* first char */
872 #else
873 fc = ap + atoi(argv[3]); /* first char */
874 #endif
875 nc = strlen(fc);
876 if (argc >= 5)
877 #ifdef EXPR
878 nc = min(nc, expr(argv[4]));
879 #else
880 nc = min(nc, atoi(argv[4]));
881 #endif
882 if (fc >= ap && fc < ap + strlen(ap))
883 for (k = fc + nc - 1; k >= fc; k--)
884 pushback(*k);
888 * map:
889 * map every character of s1 that is specified in from
890 * into s3 and replace in s. (source s1 remains untouched)
892 * This is a standard implementation of map(s,from,to) function of ICON
893 * language. Within mapvec, we replace every character of "from" with
894 * the corresponding character in "to". If "to" is shorter than "from",
895 * than the corresponding entries are null, which means that those
896 * characters dissapear altogether. Furthermore, imagine
897 * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
898 * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
899 * ultimately maps to `*'. In order to achieve this effect in an efficient
900 * manner (i.e. without multiple passes over the destination string), we
901 * loop over mapvec, starting with the initial source character. if the
902 * character value (dch) in this location is different than the source
903 * character (sch), sch becomes dch, once again to index into mapvec, until
904 * the character value stabilizes (i.e. sch = dch, in other words
905 * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
906 * character, it will stabilize, since mapvec[0] == 0 at all times. At the
907 * end, we restore mapvec* back to normal where mapvec[n] == n for
908 * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
909 * about 5 times faster than any algorithm that makes multiple passes over
910 * destination string.
912 static void
913 map(char *dest, const char *src, const char *from, const char *to)
915 const char *tmp;
916 unsigned char sch, dch;
917 static char frombis[257];
918 static char tobis[257];
919 static unsigned char mapvec[256] = {
920 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
921 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
922 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
923 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
924 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
925 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
926 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
927 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
928 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
929 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
930 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
931 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
932 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
933 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
934 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
935 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
936 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
937 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
940 if (*src) {
941 if (mimic_gnu) {
943 * expand character ranges on the fly
945 from = handledash(frombis, frombis + 256, from);
946 to = handledash(tobis, tobis + 256, to);
948 tmp = from;
950 * create a mapping between "from" and
951 * "to"
953 while (*from)
954 mapvec[(unsigned char)(*from++)] = (*to) ?
955 (unsigned char)(*to++) : 0;
957 while (*src) {
958 sch = (unsigned char)(*src++);
959 dch = mapvec[sch];
960 while (dch != sch) {
961 sch = dch;
962 dch = mapvec[sch];
964 if ((*dest = (char)dch))
965 dest++;
968 * restore all the changed characters
970 while (*tmp) {
971 mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
972 tmp++;
975 *dest = '\0';
980 * handledash:
981 * use buffer to copy the src string, expanding character ranges
982 * on the way.
984 static const char *
985 handledash(char *buffer, char *end, const char *src)
987 char *p;
989 p = buffer;
990 while(*src) {
991 if (src[1] == '-' && src[2]) {
992 unsigned char i;
993 if ((unsigned char)src[0] <= (unsigned char)src[2]) {
994 for (i = (unsigned char)src[0];
995 i <= (unsigned char)src[2]; i++) {
996 *p++ = i;
997 if (p == end) {
998 *p = '\0';
999 return buffer;
1002 } else {
1003 for (i = (unsigned char)src[0];
1004 i >= (unsigned char)src[2]; i--) {
1005 *p++ = i;
1006 if (p == end) {
1007 *p = '\0';
1008 return buffer;
1012 src += 3;
1013 } else
1014 *p++ = *src++;
1015 if (p == end)
1016 break;
1018 *p = '\0';
1019 return buffer;