1*99f77b33Sespie /* $OpenBSD: eval.c,v 1.34 2001/09/18 14:43:22 espie Exp $ */ 2aa676ce1Smillert /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /* 5df930be7Sderaadt * Copyright (c) 1989, 1993 6df930be7Sderaadt * The Regents of the University of California. All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * This code is derived from software contributed to Berkeley by 9df930be7Sderaadt * Ozan Yigit at York University. 10df930be7Sderaadt * 11df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 12df930be7Sderaadt * modification, are permitted provided that the following conditions 13df930be7Sderaadt * are met: 14df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 15df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 16df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 17df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 18df930be7Sderaadt * documentation and/or other materials provided with the distribution. 19df930be7Sderaadt * 3. All advertising materials mentioning features or use of this software 20df930be7Sderaadt * must display the following acknowledgement: 21df930be7Sderaadt * This product includes software developed by the University of 22df930be7Sderaadt * California, Berkeley and its contributors. 23df930be7Sderaadt * 4. Neither the name of the University nor the names of its contributors 24df930be7Sderaadt * may be used to endorse or promote products derived from this software 25df930be7Sderaadt * without specific prior written permission. 26df930be7Sderaadt * 27df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37df930be7Sderaadt * SUCH DAMAGE. 38df930be7Sderaadt */ 39df930be7Sderaadt 40df930be7Sderaadt #ifndef lint 41df930be7Sderaadt #if 0 42df930be7Sderaadt static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95"; 43df930be7Sderaadt #else 44*99f77b33Sespie static char rcsid[] = "$OpenBSD: eval.c,v 1.34 2001/09/18 14:43:22 espie Exp $"; 45df930be7Sderaadt #endif 46df930be7Sderaadt #endif /* not lint */ 47df930be7Sderaadt 48df930be7Sderaadt /* 49df930be7Sderaadt * eval.c 50df930be7Sderaadt * Facility: m4 macro processor 51df930be7Sderaadt * by: oz 52df930be7Sderaadt */ 53df930be7Sderaadt 54df930be7Sderaadt #include <sys/types.h> 55df930be7Sderaadt #include <errno.h> 56df930be7Sderaadt #include <unistd.h> 57df930be7Sderaadt #include <stdio.h> 58df930be7Sderaadt #include <stdlib.h> 593f42598dSespie #include <stddef.h> 60df930be7Sderaadt #include <string.h> 61445b77f7Smillert #include <fcntl.h> 6281c2181eSespie #include <err.h> 63df930be7Sderaadt #include "mdef.h" 64df930be7Sderaadt #include "stdd.h" 65df930be7Sderaadt #include "extern.h" 66df930be7Sderaadt #include "pathnames.h" 67df930be7Sderaadt 68f8b42d48Sespie #define BUILTIN_MARKER "__builtin_" 69f8b42d48Sespie 70bb34cd6cSespie static void dodefn __P((const char *)); 71bb34cd6cSespie static void dopushdef __P((const char *, const char *)); 72bb34cd6cSespie static void dodump __P((const char *[], int)); 73bb34cd6cSespie static void doifelse __P((const char *[], int)); 74bb34cd6cSespie static int doincl __P((const char *)); 75bb34cd6cSespie static int dopaste __P((const char *)); 76bb34cd6cSespie static void dochq __P((const char *[], int)); 77bb34cd6cSespie static void dochc __P((const char *[], int)); 78bb34cd6cSespie static void dodiv __P((int)); 79bb34cd6cSespie static void doundiv __P((const char *[], int)); 80bb34cd6cSespie static void dosub __P((const char *[], int)); 81bb34cd6cSespie static void map __P((char *, const char *, const char *, const char *)); 8287c5c065Sespie static const char *handledash __P((char *, char *, const char *)); 8308f7f207Sespie static void expand_builtin __P((const char *[], int, int)); 8408f7f207Sespie static void expand_macro __P((const char *[], int)); 85dd0682a2Sespie static void dump_one_def __P((ndptr)); 8608f7f207Sespie 87*99f77b33Sespie unsigned long expansion_id; 8808f7f207Sespie 89df930be7Sderaadt /* 9008f7f207Sespie * eval - eval all macros and builtins calls 9108f7f207Sespie */ 9208f7f207Sespie void 9308f7f207Sespie eval(argv, argc, td) 9408f7f207Sespie const char *argv[]; 9508f7f207Sespie int argc; 9608f7f207Sespie int td; 9708f7f207Sespie { 98*99f77b33Sespie expansion_id++; 9908f7f207Sespie if (td & RECDEF) 10008f7f207Sespie errx(1, "%s at line %lu: expanding recursive definition for %s", 10108f7f207Sespie CURRENT_NAME, CURRENT_LINE, argv[1]); 10208f7f207Sespie if (td == MACRTYPE) 10308f7f207Sespie expand_macro(argv, argc); 10408f7f207Sespie else 10508f7f207Sespie expand_builtin(argv, argc, td); 10608f7f207Sespie } 10708f7f207Sespie 10808f7f207Sespie /* 10908f7f207Sespie * expand_builtin - evaluate built-in macros. 110df930be7Sderaadt * argc - number of elements in argv. 111df930be7Sderaadt * argv - element vector : 112df930be7Sderaadt * argv[0] = definition of a user 113df930be7Sderaadt * macro or nil if built-in. 114df930be7Sderaadt * argv[1] = name of the macro or 115df930be7Sderaadt * built-in. 116df930be7Sderaadt * argv[2] = parameters to user-defined 117df930be7Sderaadt * . macro or built-in. 118df930be7Sderaadt * . 119df930be7Sderaadt * 120df930be7Sderaadt * Note that the minimum value for argc is 3. A call in the form 121df930be7Sderaadt * of macro-or-builtin() will result in: 122df930be7Sderaadt * argv[0] = nullstr 123df930be7Sderaadt * argv[1] = macro-or-builtin 124df930be7Sderaadt * argv[2] = nullstr 125df930be7Sderaadt */ 126df930be7Sderaadt 127df930be7Sderaadt void 12808f7f207Sespie expand_builtin(argv, argc, td) 129bb34cd6cSespie const char *argv[]; 13053f6f6bfSespie int argc; 13153f6f6bfSespie int td; 132df930be7Sderaadt { 13353f6f6bfSespie int c, n; 134df930be7Sderaadt static int sysval = 0; 135df930be7Sderaadt 136df930be7Sderaadt #ifdef DEBUG 137df930be7Sderaadt printf("argc = %d\n", argc); 138df930be7Sderaadt for (n = 0; n < argc; n++) 139df930be7Sderaadt printf("argv[%d] = %s\n", n, argv[n]); 140df930be7Sderaadt #endif 141718b194dSespie 142df930be7Sderaadt /* 143df930be7Sderaadt * if argc == 3 and argv[2] is null, then we 144df930be7Sderaadt * have macro-or-builtin() type call. We adjust 145df930be7Sderaadt * argc to avoid further checking.. 146df930be7Sderaadt */ 147df930be7Sderaadt if (argc == 3 && !*(argv[2])) 148df930be7Sderaadt argc--; 149df930be7Sderaadt 150718b194dSespie switch (td & TYPEMASK) { 151df930be7Sderaadt 152df930be7Sderaadt case DEFITYPE: 153df930be7Sderaadt if (argc > 2) 154df930be7Sderaadt dodefine(argv[2], (argc > 3) ? argv[3] : null); 155df930be7Sderaadt break; 156df930be7Sderaadt 157df930be7Sderaadt case PUSDTYPE: 158df930be7Sderaadt if (argc > 2) 159df930be7Sderaadt dopushdef(argv[2], (argc > 3) ? argv[3] : null); 160df930be7Sderaadt break; 161df930be7Sderaadt 162df930be7Sderaadt case DUMPTYPE: 163df930be7Sderaadt dodump(argv, argc); 164df930be7Sderaadt break; 165df930be7Sderaadt 166df930be7Sderaadt case EXPRTYPE: 167df930be7Sderaadt /* 168df930be7Sderaadt * doexpr - evaluate arithmetic 169df930be7Sderaadt * expression 170df930be7Sderaadt */ 171df930be7Sderaadt if (argc > 2) 172df930be7Sderaadt pbnum(expr(argv[2])); 173df930be7Sderaadt break; 174df930be7Sderaadt 175df930be7Sderaadt case IFELTYPE: 176df930be7Sderaadt if (argc > 4) 177df930be7Sderaadt doifelse(argv, argc); 178df930be7Sderaadt break; 179df930be7Sderaadt 180df930be7Sderaadt case IFDFTYPE: 181df930be7Sderaadt /* 182df930be7Sderaadt * doifdef - select one of two 183df930be7Sderaadt * alternatives based on the existence of 184df930be7Sderaadt * another definition 185df930be7Sderaadt */ 186df930be7Sderaadt if (argc > 3) { 187df930be7Sderaadt if (lookup(argv[2]) != nil) 188df930be7Sderaadt pbstr(argv[3]); 189df930be7Sderaadt else if (argc > 4) 190df930be7Sderaadt pbstr(argv[4]); 191df930be7Sderaadt } 192df930be7Sderaadt break; 193df930be7Sderaadt 194df930be7Sderaadt case LENGTYPE: 195df930be7Sderaadt /* 196df930be7Sderaadt * dolen - find the length of the 197df930be7Sderaadt * argument 198df930be7Sderaadt */ 199df930be7Sderaadt pbnum((argc > 2) ? strlen(argv[2]) : 0); 200df930be7Sderaadt break; 201df930be7Sderaadt 202df930be7Sderaadt case INCRTYPE: 203df930be7Sderaadt /* 204df930be7Sderaadt * doincr - increment the value of the 205df930be7Sderaadt * argument 206df930be7Sderaadt */ 207df930be7Sderaadt if (argc > 2) 208df930be7Sderaadt pbnum(atoi(argv[2]) + 1); 209df930be7Sderaadt break; 210df930be7Sderaadt 211df930be7Sderaadt case DECRTYPE: 212df930be7Sderaadt /* 213df930be7Sderaadt * dodecr - decrement the value of the 214df930be7Sderaadt * argument 215df930be7Sderaadt */ 216df930be7Sderaadt if (argc > 2) 217df930be7Sderaadt pbnum(atoi(argv[2]) - 1); 218df930be7Sderaadt break; 219df930be7Sderaadt 220df930be7Sderaadt case SYSCTYPE: 221df930be7Sderaadt /* 222df930be7Sderaadt * dosys - execute system command 223df930be7Sderaadt */ 224df930be7Sderaadt if (argc > 2) 225df930be7Sderaadt sysval = system(argv[2]); 226df930be7Sderaadt break; 227df930be7Sderaadt 228df930be7Sderaadt case SYSVTYPE: 229df930be7Sderaadt /* 230df930be7Sderaadt * dosysval - return value of the last 231df930be7Sderaadt * system call. 232df930be7Sderaadt * 233df930be7Sderaadt */ 234df930be7Sderaadt pbnum(sysval); 235df930be7Sderaadt break; 236df930be7Sderaadt 237c91edbbbSespie case ESYSCMDTYPE: 238c91edbbbSespie if (argc > 2) 239c91edbbbSespie doesyscmd(argv[2]); 240c91edbbbSespie break; 241df930be7Sderaadt case INCLTYPE: 242df930be7Sderaadt if (argc > 2) 243df930be7Sderaadt if (!doincl(argv[2])) 2440d3ffe1dSespie err(1, "%s at line %lu: include(%s)", 2450d3ffe1dSespie CURRENT_NAME, CURRENT_LINE, argv[2]); 246df930be7Sderaadt break; 247df930be7Sderaadt 248df930be7Sderaadt case SINCTYPE: 249df930be7Sderaadt if (argc > 2) 250df930be7Sderaadt (void) doincl(argv[2]); 251df930be7Sderaadt break; 252df930be7Sderaadt #ifdef EXTENDED 253df930be7Sderaadt case PASTTYPE: 254df930be7Sderaadt if (argc > 2) 255df930be7Sderaadt if (!dopaste(argv[2])) 2560d3ffe1dSespie err(1, "%s at line %lu: paste(%s)", 2570d3ffe1dSespie CURRENT_NAME, CURRENT_LINE, argv[2]); 258df930be7Sderaadt break; 259df930be7Sderaadt 260df930be7Sderaadt case SPASTYPE: 261df930be7Sderaadt if (argc > 2) 262df930be7Sderaadt (void) dopaste(argv[2]); 263df930be7Sderaadt break; 264df930be7Sderaadt #endif 265df930be7Sderaadt case CHNQTYPE: 266df930be7Sderaadt dochq(argv, argc); 267df930be7Sderaadt break; 268df930be7Sderaadt 269df930be7Sderaadt case CHNCTYPE: 270df930be7Sderaadt dochc(argv, argc); 271df930be7Sderaadt break; 272df930be7Sderaadt 273df930be7Sderaadt case SUBSTYPE: 274df930be7Sderaadt /* 275df930be7Sderaadt * dosub - select substring 276df930be7Sderaadt * 277df930be7Sderaadt */ 278df930be7Sderaadt if (argc > 3) 279df930be7Sderaadt dosub(argv, argc); 280df930be7Sderaadt break; 281df930be7Sderaadt 282df930be7Sderaadt case SHIFTYPE: 283df930be7Sderaadt /* 284df930be7Sderaadt * doshift - push back all arguments 285df930be7Sderaadt * except the first one (i.e. skip 286df930be7Sderaadt * argv[2]) 287df930be7Sderaadt */ 288df930be7Sderaadt if (argc > 3) { 289df930be7Sderaadt for (n = argc - 1; n > 3; n--) { 2903a73db8cSderaadt pbstr(rquote); 291df930be7Sderaadt pbstr(argv[n]); 2923a73db8cSderaadt pbstr(lquote); 293aa676ce1Smillert putback(COMMA); 294df930be7Sderaadt } 2953a73db8cSderaadt pbstr(rquote); 296df930be7Sderaadt pbstr(argv[3]); 2973a73db8cSderaadt pbstr(lquote); 298df930be7Sderaadt } 299df930be7Sderaadt break; 300df930be7Sderaadt 301df930be7Sderaadt case DIVRTYPE: 302df930be7Sderaadt if (argc > 2 && (n = atoi(argv[2])) != 0) 303df930be7Sderaadt dodiv(n); 304df930be7Sderaadt else { 305df930be7Sderaadt active = stdout; 306df930be7Sderaadt oindex = 0; 307df930be7Sderaadt } 308df930be7Sderaadt break; 309df930be7Sderaadt 310df930be7Sderaadt case UNDVTYPE: 311df930be7Sderaadt doundiv(argv, argc); 312df930be7Sderaadt break; 313df930be7Sderaadt 314df930be7Sderaadt case DIVNTYPE: 315df930be7Sderaadt /* 316df930be7Sderaadt * dodivnum - return the number of 317df930be7Sderaadt * current output diversion 318df930be7Sderaadt */ 319df930be7Sderaadt pbnum(oindex); 320df930be7Sderaadt break; 321df930be7Sderaadt 322df930be7Sderaadt case UNDFTYPE: 323df930be7Sderaadt /* 324df930be7Sderaadt * doundefine - undefine a previously 325df930be7Sderaadt * defined macro(s) or m4 keyword(s). 326df930be7Sderaadt */ 327df930be7Sderaadt if (argc > 2) 328df930be7Sderaadt for (n = 2; n < argc; n++) 329df930be7Sderaadt remhash(argv[n], ALL); 330df930be7Sderaadt break; 331df930be7Sderaadt 332df930be7Sderaadt case POPDTYPE: 333df930be7Sderaadt /* 334df930be7Sderaadt * dopopdef - remove the topmost 335df930be7Sderaadt * definitions of macro(s) or m4 336df930be7Sderaadt * keyword(s). 337df930be7Sderaadt */ 338df930be7Sderaadt if (argc > 2) 339df930be7Sderaadt for (n = 2; n < argc; n++) 340df930be7Sderaadt remhash(argv[n], TOP); 341df930be7Sderaadt break; 342df930be7Sderaadt 343df930be7Sderaadt case MKTMTYPE: 344df930be7Sderaadt /* 345df930be7Sderaadt * dotemp - create a temporary file 346df930be7Sderaadt */ 34701e71e69Sespie if (argc > 2) { 34801e71e69Sespie int fd; 349bb34cd6cSespie char *temp; 35001e71e69Sespie 351bb34cd6cSespie temp = xstrdup(argv[2]); 352bb34cd6cSespie 353bb34cd6cSespie fd = mkstemp(temp); 35401e71e69Sespie if (fd == -1) 3550d3ffe1dSespie err(1, 3560d3ffe1dSespie "%s at line %lu: couldn't make temp file %s", 3570d3ffe1dSespie CURRENT_NAME, CURRENT_LINE, argv[2]); 35801e71e69Sespie close(fd); 359bb34cd6cSespie pbstr(temp); 360bb34cd6cSespie free(temp); 36101e71e69Sespie } 362df930be7Sderaadt break; 363df930be7Sderaadt 364df930be7Sderaadt case TRNLTYPE: 365df930be7Sderaadt /* 366df930be7Sderaadt * dotranslit - replace all characters in 367df930be7Sderaadt * the source string that appears in the 368df930be7Sderaadt * "from" string with the corresponding 369df930be7Sderaadt * characters in the "to" string. 370df930be7Sderaadt */ 371df930be7Sderaadt if (argc > 3) { 3727d3e0b6bSderaadt char temp[STRSPMAX+1]; 373df930be7Sderaadt if (argc > 4) 374df930be7Sderaadt map(temp, argv[2], argv[3], argv[4]); 375df930be7Sderaadt else 376df930be7Sderaadt map(temp, argv[2], argv[3], null); 377df930be7Sderaadt pbstr(temp); 3787d3e0b6bSderaadt } else if (argc > 2) 379df930be7Sderaadt pbstr(argv[2]); 380df930be7Sderaadt break; 381df930be7Sderaadt 382df930be7Sderaadt case INDXTYPE: 383df930be7Sderaadt /* 384df930be7Sderaadt * doindex - find the index of the second 385df930be7Sderaadt * argument string in the first argument 386df930be7Sderaadt * string. -1 if not present. 387df930be7Sderaadt */ 388df930be7Sderaadt pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 389df930be7Sderaadt break; 390df930be7Sderaadt 391df930be7Sderaadt case ERRPTYPE: 392df930be7Sderaadt /* 393df930be7Sderaadt * doerrp - print the arguments to stderr 394df930be7Sderaadt * file 395df930be7Sderaadt */ 396df930be7Sderaadt if (argc > 2) { 397df930be7Sderaadt for (n = 2; n < argc; n++) 398df930be7Sderaadt fprintf(stderr, "%s ", argv[n]); 399df930be7Sderaadt fprintf(stderr, "\n"); 400df930be7Sderaadt } 401df930be7Sderaadt break; 402df930be7Sderaadt 403df930be7Sderaadt case DNLNTYPE: 404df930be7Sderaadt /* 405df930be7Sderaadt * dodnl - eat-up-to and including 406df930be7Sderaadt * newline 407df930be7Sderaadt */ 408df930be7Sderaadt while ((c = gpbc()) != '\n' && c != EOF) 409df930be7Sderaadt ; 410df930be7Sderaadt break; 411df930be7Sderaadt 412df930be7Sderaadt case M4WRTYPE: 413df930be7Sderaadt /* 414df930be7Sderaadt * dom4wrap - set up for 415df930be7Sderaadt * wrap-up/wind-down activity 416df930be7Sderaadt */ 417df930be7Sderaadt m4wraps = (argc > 2) ? xstrdup(argv[2]) : null; 418df930be7Sderaadt break; 419df930be7Sderaadt 420df930be7Sderaadt case EXITTYPE: 421df930be7Sderaadt /* 422df930be7Sderaadt * doexit - immediate exit from m4. 423df930be7Sderaadt */ 424df930be7Sderaadt killdiv(); 425df930be7Sderaadt exit((argc > 2) ? atoi(argv[2]) : 0); 426df930be7Sderaadt break; 427df930be7Sderaadt 428df930be7Sderaadt case DEFNTYPE: 429df930be7Sderaadt if (argc > 2) 430df930be7Sderaadt for (n = 2; n < argc; n++) 431df930be7Sderaadt dodefn(argv[n]); 432df930be7Sderaadt break; 433df930be7Sderaadt 434b8161682Sespie case INDIRTYPE: /* Indirect call */ 435b8161682Sespie if (argc > 2) 436b8161682Sespie doindir(argv, argc); 437b8161682Sespie break; 438b8161682Sespie 439b8161682Sespie case BUILTINTYPE: /* Builtins only */ 440b8161682Sespie if (argc > 2) 441b8161682Sespie dobuiltin(argv, argc); 442b8161682Sespie break; 443b8161682Sespie 444b8161682Sespie case PATSTYPE: 445b8161682Sespie if (argc > 2) 446b8161682Sespie dopatsubst(argv, argc); 447b8161682Sespie break; 448b8161682Sespie case REGEXPTYPE: 449b8161682Sespie if (argc > 2) 450b8161682Sespie doregexp(argv, argc); 451b8161682Sespie break; 452b8161682Sespie case LINETYPE: 453b8161682Sespie doprintlineno(infile+ilevel); 454b8161682Sespie break; 455b8161682Sespie case FILENAMETYPE: 456b8161682Sespie doprintfilename(infile+ilevel); 457b8161682Sespie break; 458423624b7Sespie case SELFTYPE: 459423624b7Sespie pbstr(rquote); 460423624b7Sespie pbstr(argv[1]); 461423624b7Sespie pbstr(lquote); 462423624b7Sespie break; 463df930be7Sderaadt default: 4640d3ffe1dSespie errx(1, "%s at line %lu: eval: major botch.", 4650d3ffe1dSespie CURRENT_NAME, CURRENT_LINE); 466df930be7Sderaadt break; 467df930be7Sderaadt } 468df930be7Sderaadt } 469df930be7Sderaadt 470df930be7Sderaadt /* 47108f7f207Sespie * expand_macro - user-defined macro expansion 472df930be7Sderaadt */ 473df930be7Sderaadt void 47408f7f207Sespie expand_macro(argv, argc) 475bb34cd6cSespie const char *argv[]; 47653f6f6bfSespie int argc; 477df930be7Sderaadt { 478bb34cd6cSespie const char *t; 479bb34cd6cSespie const char *p; 48053f6f6bfSespie int n; 48153f6f6bfSespie int argno; 482df930be7Sderaadt 483df930be7Sderaadt t = argv[0]; /* defn string as a whole */ 484df930be7Sderaadt p = t; 485df930be7Sderaadt while (*p) 486df930be7Sderaadt p++; 487df930be7Sderaadt p--; /* last character of defn */ 488df930be7Sderaadt while (p > t) { 489df930be7Sderaadt if (*(p - 1) != ARGFLAG) 490df930be7Sderaadt putback(*p); 491df930be7Sderaadt else { 492df930be7Sderaadt switch (*p) { 493df930be7Sderaadt 494df930be7Sderaadt case '#': 495df930be7Sderaadt pbnum(argc - 2); 496df930be7Sderaadt break; 497df930be7Sderaadt case '0': 498df930be7Sderaadt case '1': 499df930be7Sderaadt case '2': 500df930be7Sderaadt case '3': 501df930be7Sderaadt case '4': 502df930be7Sderaadt case '5': 503df930be7Sderaadt case '6': 504df930be7Sderaadt case '7': 505df930be7Sderaadt case '8': 506df930be7Sderaadt case '9': 507df930be7Sderaadt if ((argno = *p - '0') < argc - 1) 508df930be7Sderaadt pbstr(argv[argno + 1]); 509df930be7Sderaadt break; 510df930be7Sderaadt case '*': 511df930be7Sderaadt for (n = argc - 1; n > 2; n--) { 512df930be7Sderaadt pbstr(argv[n]); 513aa676ce1Smillert putback(COMMA); 514df930be7Sderaadt } 515df930be7Sderaadt pbstr(argv[2]); 516df930be7Sderaadt break; 517aa676ce1Smillert case '@': 518aa676ce1Smillert for (n = argc - 1; n > 2; n--) { 519aa676ce1Smillert pbstr(rquote); 520aa676ce1Smillert pbstr(argv[n]); 521aa676ce1Smillert pbstr(lquote); 522aa676ce1Smillert putback(COMMA); 523aa676ce1Smillert } 524aa676ce1Smillert pbstr(rquote); 525aa676ce1Smillert pbstr(argv[2]); 526aa676ce1Smillert pbstr(lquote); 527aa676ce1Smillert break; 528df930be7Sderaadt default: 529df930be7Sderaadt putback(*p); 530df930be7Sderaadt putback('$'); 531df930be7Sderaadt break; 532df930be7Sderaadt } 533df930be7Sderaadt p--; 534df930be7Sderaadt } 535df930be7Sderaadt p--; 536df930be7Sderaadt } 537df930be7Sderaadt if (p == t) /* do last character */ 538df930be7Sderaadt putback(*p); 539df930be7Sderaadt } 540df930be7Sderaadt 541df930be7Sderaadt /* 542df930be7Sderaadt * dodefine - install definition in the table 543df930be7Sderaadt */ 544df930be7Sderaadt void 545df930be7Sderaadt dodefine(name, defn) 546bb34cd6cSespie const char *name; 547bb34cd6cSespie const char *defn; 548df930be7Sderaadt { 54953f6f6bfSespie ndptr p; 550f8b42d48Sespie int n; 551df930be7Sderaadt 552df930be7Sderaadt if (!*name) 5530d3ffe1dSespie errx(1, "%s at line %lu: null definition.", CURRENT_NAME, 5540d3ffe1dSespie CURRENT_LINE); 555df930be7Sderaadt if ((p = lookup(name)) == nil) 556df930be7Sderaadt p = addent(name); 557df930be7Sderaadt else if (p->defn != null) 558df930be7Sderaadt free((char *) p->defn); 559f8b42d48Sespie if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) { 560f8b42d48Sespie n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1); 561f8b42d48Sespie if (n != -1) { 562f8b42d48Sespie p->type = n; 563f8b42d48Sespie p->defn = null; 564f8b42d48Sespie return; 565f8b42d48Sespie } 566f8b42d48Sespie } 567df930be7Sderaadt if (!*defn) 568df930be7Sderaadt p->defn = null; 569df930be7Sderaadt else 570df930be7Sderaadt p->defn = xstrdup(defn); 571df930be7Sderaadt p->type = MACRTYPE; 572718b194dSespie if (STREQ(name, defn)) 573718b194dSespie p->type |= RECDEF; 574df930be7Sderaadt } 575df930be7Sderaadt 576df930be7Sderaadt /* 577df930be7Sderaadt * dodefn - push back a quoted definition of 578df930be7Sderaadt * the given name. 579df930be7Sderaadt */ 580bb34cd6cSespie static void 581df930be7Sderaadt dodefn(name) 582bb34cd6cSespie const char *name; 583df930be7Sderaadt { 58453f6f6bfSespie ndptr p; 585f8b42d48Sespie char *real; 586df930be7Sderaadt 587f8b42d48Sespie if ((p = lookup(name)) != nil) { 588f8b42d48Sespie if (p->defn != null) { 5893a73db8cSderaadt pbstr(rquote); 590df930be7Sderaadt pbstr(p->defn); 5913a73db8cSderaadt pbstr(lquote); 592f8b42d48Sespie } else if ((real = builtin_realname(p->type)) != NULL) { 593f8b42d48Sespie pbstr(real); 594f8b42d48Sespie pbstr(BUILTIN_MARKER); 595f8b42d48Sespie } 596df930be7Sderaadt } 597df930be7Sderaadt } 598df930be7Sderaadt 599df930be7Sderaadt /* 600df930be7Sderaadt * dopushdef - install a definition in the hash table 601df930be7Sderaadt * without removing a previous definition. Since 602df930be7Sderaadt * each new entry is entered in *front* of the 603df930be7Sderaadt * hash bucket, it hides a previous definition from 604df930be7Sderaadt * lookup. 605df930be7Sderaadt */ 606bb34cd6cSespie static void 607df930be7Sderaadt dopushdef(name, defn) 608bb34cd6cSespie const char *name; 609bb34cd6cSespie const char *defn; 610df930be7Sderaadt { 61153f6f6bfSespie ndptr p; 612df930be7Sderaadt 613df930be7Sderaadt if (!*name) 6140d3ffe1dSespie errx(1, "%s at line %lu: null definition", CURRENT_NAME, 6150d3ffe1dSespie CURRENT_LINE); 616df930be7Sderaadt p = addent(name); 617df930be7Sderaadt if (!*defn) 618df930be7Sderaadt p->defn = null; 619df930be7Sderaadt else 620df930be7Sderaadt p->defn = xstrdup(defn); 621df930be7Sderaadt p->type = MACRTYPE; 622718b194dSespie if (STREQ(name, defn)) 623718b194dSespie p->type |= RECDEF; 624df930be7Sderaadt } 625df930be7Sderaadt 626df930be7Sderaadt /* 627dd0682a2Sespie * dump_one_def - dump the specified definition. 628dd0682a2Sespie */ 629dd0682a2Sespie static void 630dd0682a2Sespie dump_one_def(p) 631dd0682a2Sespie ndptr p; 632dd0682a2Sespie { 6335191fa0aSespie char *real; 6345191fa0aSespie 6355191fa0aSespie if (mimic_gnu) { 6365191fa0aSespie if ((p->type & TYPEMASK) == MACRTYPE) 6375191fa0aSespie fprintf(stderr, "%s:\t%s\n", p->name, p->defn); 6385191fa0aSespie else { 6395191fa0aSespie real = builtin_realname(p->type); 6405191fa0aSespie if (real == NULL) 6415191fa0aSespie real = null; 6425191fa0aSespie fprintf(stderr, "%s:\t<%s>\n", p->name, real); 6435191fa0aSespie } 6445191fa0aSespie } else 645dd0682a2Sespie fprintf(stderr, "`%s'\t`%s'\n", p->name, p->defn); 646dd0682a2Sespie } 647dd0682a2Sespie 648dd0682a2Sespie /* 649df930be7Sderaadt * dodumpdef - dump the specified definitions in the hash 650df930be7Sderaadt * table to stderr. If nothing is specified, the entire 651df930be7Sderaadt * hash table is dumped. 652df930be7Sderaadt */ 653bb34cd6cSespie static void 654df930be7Sderaadt dodump(argv, argc) 655bb34cd6cSespie const char *argv[]; 65653f6f6bfSespie int argc; 657df930be7Sderaadt { 65853f6f6bfSespie int n; 659df930be7Sderaadt ndptr p; 660df930be7Sderaadt 661df930be7Sderaadt if (argc > 2) { 662df930be7Sderaadt for (n = 2; n < argc; n++) 663df930be7Sderaadt if ((p = lookup(argv[n])) != nil) 664dd0682a2Sespie dump_one_def(p); 6657d3e0b6bSderaadt } else { 666df930be7Sderaadt for (n = 0; n < HASHSIZE; n++) 667df930be7Sderaadt for (p = hashtab[n]; p != nil; p = p->nxtptr) 668dd0682a2Sespie dump_one_def(p); 669df930be7Sderaadt } 670df930be7Sderaadt } 671df930be7Sderaadt 672df930be7Sderaadt /* 673df930be7Sderaadt * doifelse - select one of two alternatives - loop. 674df930be7Sderaadt */ 675bb34cd6cSespie static void 676df930be7Sderaadt doifelse(argv, argc) 677bb34cd6cSespie const char *argv[]; 67853f6f6bfSespie int argc; 679df930be7Sderaadt { 680df930be7Sderaadt cycle { 681df930be7Sderaadt if (STREQ(argv[2], argv[3])) 682df930be7Sderaadt pbstr(argv[4]); 683df930be7Sderaadt else if (argc == 6) 684df930be7Sderaadt pbstr(argv[5]); 685df930be7Sderaadt else if (argc > 6) { 686df930be7Sderaadt argv += 3; 687df930be7Sderaadt argc -= 3; 688df930be7Sderaadt continue; 689df930be7Sderaadt } 690df930be7Sderaadt break; 691df930be7Sderaadt } 692df930be7Sderaadt } 693df930be7Sderaadt 694df930be7Sderaadt /* 695df930be7Sderaadt * doinclude - include a given file. 696df930be7Sderaadt */ 697bb34cd6cSespie static int 698df930be7Sderaadt doincl(ifile) 699bb34cd6cSespie const char *ifile; 700df930be7Sderaadt { 701df930be7Sderaadt if (ilevel + 1 == MAXINP) 7020d3ffe1dSespie errx(1, "%s at line %lu: too many include files.", 7030d3ffe1dSespie CURRENT_NAME, CURRENT_LINE); 7040d3ffe1dSespie if (fopen_trypath(infile+ilevel+1, ifile) != NULL) { 705df930be7Sderaadt ilevel++; 706df930be7Sderaadt bbase[ilevel] = bufbase = bp; 707df930be7Sderaadt return (1); 7087d3e0b6bSderaadt } else 709df930be7Sderaadt return (0); 710df930be7Sderaadt } 711df930be7Sderaadt 712df930be7Sderaadt #ifdef EXTENDED 713df930be7Sderaadt /* 714df930be7Sderaadt * dopaste - include a given file without any 715df930be7Sderaadt * macro processing. 716df930be7Sderaadt */ 717bb34cd6cSespie static int 718df930be7Sderaadt dopaste(pfile) 719bb34cd6cSespie const char *pfile; 720df930be7Sderaadt { 721df930be7Sderaadt FILE *pf; 72253f6f6bfSespie int c; 723df930be7Sderaadt 724df930be7Sderaadt if ((pf = fopen(pfile, "r")) != NULL) { 725df930be7Sderaadt while ((c = getc(pf)) != EOF) 726df930be7Sderaadt putc(c, active); 727df930be7Sderaadt (void) fclose(pf); 728df930be7Sderaadt return (1); 7297d3e0b6bSderaadt } else 730df930be7Sderaadt return (0); 731df930be7Sderaadt } 732df930be7Sderaadt #endif 733df930be7Sderaadt 734df930be7Sderaadt /* 735df930be7Sderaadt * dochq - change quote characters 736df930be7Sderaadt */ 737bb34cd6cSespie static void 738df930be7Sderaadt dochq(argv, argc) 739bb34cd6cSespie const char *argv[]; 74053f6f6bfSespie int argc; 741df930be7Sderaadt { 74287c5c065Sespie /* In gnu-m4 mode, having two empty arguments means no quotes at 74387c5c065Sespie * all. */ 74487c5c065Sespie if (mimic_gnu) { 74587c5c065Sespie if (argc > 3 && !*argv[2] && !*argv[3]) { 74687c5c065Sespie lquote[0] = EOS; 74787c5c065Sespie rquote[0] = EOS; 74887c5c065Sespie return; 74987c5c065Sespie } 75087c5c065Sespie } 751df930be7Sderaadt if (argc > 2) { 75218a1973bSderaadt if (*argv[2]) 753b81b15b2Sespie strlcpy(lquote, argv[2], sizeof(lquote)); 75418a1973bSderaadt else { 75518a1973bSderaadt lquote[0] = LQUOTE; 756f0484631Sespie lquote[1] = EOS; 75718a1973bSderaadt } 758df930be7Sderaadt if (argc > 3) { 759df930be7Sderaadt if (*argv[3]) 760b81b15b2Sespie strlcpy(rquote, argv[3], sizeof(rquote)); 7617d3e0b6bSderaadt } else 76229a0bfdcSderaadt strcpy(rquote, lquote); 7637d3e0b6bSderaadt } else { 764f0484631Sespie lquote[0] = LQUOTE, lquote[1] = EOS; 765f0484631Sespie rquote[0] = RQUOTE, rquote[1] = EOS; 766df930be7Sderaadt } 767df930be7Sderaadt } 768df930be7Sderaadt 769df930be7Sderaadt /* 770df930be7Sderaadt * dochc - change comment characters 771df930be7Sderaadt */ 772bb34cd6cSespie static void 773df930be7Sderaadt dochc(argv, argc) 774bb34cd6cSespie const char *argv[]; 77553f6f6bfSespie int argc; 776df930be7Sderaadt { 777df930be7Sderaadt if (argc > 2) { 778df930be7Sderaadt if (*argv[2]) 779b81b15b2Sespie strlcpy(scommt, argv[2], sizeof(scommt)); 780df930be7Sderaadt if (argc > 3) { 781df930be7Sderaadt if (*argv[3]) 782b81b15b2Sespie strlcpy(ecommt, argv[3], sizeof(ecommt)); 783df930be7Sderaadt } 784df930be7Sderaadt else 785f0484631Sespie ecommt[0] = ECOMMT, ecommt[1] = EOS; 786df930be7Sderaadt } 787df930be7Sderaadt else { 788f0484631Sespie scommt[0] = SCOMMT, scommt[1] = EOS; 789f0484631Sespie ecommt[0] = ECOMMT, ecommt[1] = EOS; 790df930be7Sderaadt } 791df930be7Sderaadt } 792df930be7Sderaadt 793df930be7Sderaadt /* 794df930be7Sderaadt * dodivert - divert the output to a temporary file 795df930be7Sderaadt */ 796bb34cd6cSespie static void 797df930be7Sderaadt dodiv(n) 79853f6f6bfSespie int n; 799df930be7Sderaadt { 800445b77f7Smillert int fd; 801445b77f7Smillert 8027d3e0b6bSderaadt oindex = n; 80325afcddbSespie if (n >= maxout) { 80425afcddbSespie if (mimic_gnu) 80525afcddbSespie resizedivs(n + 10); 80625afcddbSespie else 80725afcddbSespie n = 0; /* bitbucket */ 80825afcddbSespie } 80925afcddbSespie 81025afcddbSespie if (n < 0) 811df930be7Sderaadt n = 0; /* bitbucket */ 812df930be7Sderaadt if (outfile[n] == NULL) { 8133f42598dSespie char fname[] = _PATH_DIVNAME; 8143f42598dSespie 8153f42598dSespie if ((fd = mkstemp(fname)) < 0 || 8163f42598dSespie (outfile[n] = fdopen(fd, "w+")) == NULL) 8173f42598dSespie err(1, "%s: cannot divert", fname); 8183f42598dSespie if (unlink(fname) == -1) 8193f42598dSespie err(1, "%s: cannot unlink", fname); 820df930be7Sderaadt } 821df930be7Sderaadt active = outfile[n]; 822df930be7Sderaadt } 823df930be7Sderaadt 824df930be7Sderaadt /* 825df930be7Sderaadt * doundivert - undivert a specified output, or all 826df930be7Sderaadt * other outputs, in numerical order. 827df930be7Sderaadt */ 828bb34cd6cSespie static void 829df930be7Sderaadt doundiv(argv, argc) 830bb34cd6cSespie const char *argv[]; 83153f6f6bfSespie int argc; 832df930be7Sderaadt { 83353f6f6bfSespie int ind; 83453f6f6bfSespie int n; 835df930be7Sderaadt 836df930be7Sderaadt if (argc > 2) { 837df930be7Sderaadt for (ind = 2; ind < argc; ind++) { 838df930be7Sderaadt n = atoi(argv[ind]); 83925afcddbSespie if (n > 0 && n < maxout && outfile[n] != NULL) 840df930be7Sderaadt getdiv(n); 841df930be7Sderaadt 842df930be7Sderaadt } 843df930be7Sderaadt } 844df930be7Sderaadt else 84525afcddbSespie for (n = 1; n < maxout; n++) 846df930be7Sderaadt if (outfile[n] != NULL) 847df930be7Sderaadt getdiv(n); 848df930be7Sderaadt } 849df930be7Sderaadt 850df930be7Sderaadt /* 851df930be7Sderaadt * dosub - select substring 852df930be7Sderaadt */ 853bb34cd6cSespie static void 854df930be7Sderaadt dosub(argv, argc) 855bb34cd6cSespie const char *argv[]; 85653f6f6bfSespie int argc; 857df930be7Sderaadt { 858bb34cd6cSespie const char *ap, *fc, *k; 85953f6f6bfSespie int nc; 860df930be7Sderaadt 861df930be7Sderaadt ap = argv[2]; /* target string */ 862df930be7Sderaadt #ifdef EXPR 863df930be7Sderaadt fc = ap + expr(argv[3]); /* first char */ 864df930be7Sderaadt #else 865df930be7Sderaadt fc = ap + atoi(argv[3]); /* first char */ 866df930be7Sderaadt #endif 867bee8364eSespie nc = strlen(fc); 868bee8364eSespie if (argc >= 5) 869bee8364eSespie #ifdef EXPR 870bee8364eSespie nc = min(nc, expr(argv[4])); 871bee8364eSespie #else 872bee8364eSespie nc = min(nc, atoi(argv[4])); 873bee8364eSespie #endif 874df930be7Sderaadt if (fc >= ap && fc < ap + strlen(ap)) 875bee8364eSespie for (k = fc + nc - 1; k >= fc; k--) 876df930be7Sderaadt putback(*k); 877df930be7Sderaadt } 878df930be7Sderaadt 879df930be7Sderaadt /* 880df930be7Sderaadt * map: 881df930be7Sderaadt * map every character of s1 that is specified in from 882df930be7Sderaadt * into s3 and replace in s. (source s1 remains untouched) 883df930be7Sderaadt * 884df930be7Sderaadt * This is a standard implementation of map(s,from,to) function of ICON 885df930be7Sderaadt * language. Within mapvec, we replace every character of "from" with 886df930be7Sderaadt * the corresponding character in "to". If "to" is shorter than "from", 887df930be7Sderaadt * than the corresponding entries are null, which means that those 888df930be7Sderaadt * characters dissapear altogether. Furthermore, imagine 889df930be7Sderaadt * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 890df930be7Sderaadt * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 891df930be7Sderaadt * ultimately maps to `*'. In order to achieve this effect in an efficient 892df930be7Sderaadt * manner (i.e. without multiple passes over the destination string), we 893df930be7Sderaadt * loop over mapvec, starting with the initial source character. if the 894df930be7Sderaadt * character value (dch) in this location is different than the source 895df930be7Sderaadt * character (sch), sch becomes dch, once again to index into mapvec, until 896df930be7Sderaadt * the character value stabilizes (i.e. sch = dch, in other words 897df930be7Sderaadt * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 898df930be7Sderaadt * character, it will stabilize, since mapvec[0] == 0 at all times. At the 899df930be7Sderaadt * end, we restore mapvec* back to normal where mapvec[n] == n for 900df930be7Sderaadt * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 901df930be7Sderaadt * about 5 times faster than any algorithm that makes multiple passes over 902df930be7Sderaadt * destination string. 903df930be7Sderaadt */ 904bb34cd6cSespie static void 905df930be7Sderaadt map(dest, src, from, to) 90653f6f6bfSespie char *dest; 907bb34cd6cSespie const char *src; 908bb34cd6cSespie const char *from; 909bb34cd6cSespie const char *to; 910df930be7Sderaadt { 911bb34cd6cSespie const char *tmp; 912ee3599c7Sespie unsigned char sch, dch; 91387c5c065Sespie static char frombis[257]; 91487c5c065Sespie static char tobis[257]; 915ee3599c7Sespie static unsigned char mapvec[256] = { 916ee3599c7Sespie 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 917ee3599c7Sespie 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 918ee3599c7Sespie 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 919ee3599c7Sespie 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 920ee3599c7Sespie 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 921ee3599c7Sespie 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 922ee3599c7Sespie 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 923ee3599c7Sespie 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 924ee3599c7Sespie 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 925ee3599c7Sespie 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 926ee3599c7Sespie 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 927ee3599c7Sespie 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 928ee3599c7Sespie 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 929ee3599c7Sespie 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 930ee3599c7Sespie 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 931ee3599c7Sespie 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 932ee3599c7Sespie 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 933ee3599c7Sespie 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 934df930be7Sderaadt }; 935df930be7Sderaadt 936df930be7Sderaadt if (*src) { 93787c5c065Sespie if (mimic_gnu) { 93887c5c065Sespie /* 93987c5c065Sespie * expand character ranges on the fly 94087c5c065Sespie */ 94187c5c065Sespie from = handledash(frombis, frombis + 256, from); 94287c5c065Sespie to = handledash(tobis, tobis + 256, to); 94387c5c065Sespie } 944df930be7Sderaadt tmp = from; 945df930be7Sderaadt /* 946df930be7Sderaadt * create a mapping between "from" and 947df930be7Sderaadt * "to" 948df930be7Sderaadt */ 949df930be7Sderaadt while (*from) 950ee3599c7Sespie mapvec[(unsigned char)(*from++)] = (*to) ? 951ee3599c7Sespie (unsigned char)(*to++) : 0; 952df930be7Sderaadt 953df930be7Sderaadt while (*src) { 954ee3599c7Sespie sch = (unsigned char)(*src++); 955df930be7Sderaadt dch = mapvec[sch]; 956df930be7Sderaadt while (dch != sch) { 957df930be7Sderaadt sch = dch; 958df930be7Sderaadt dch = mapvec[sch]; 959df930be7Sderaadt } 960ee3599c7Sespie if ((*dest = (char)dch)) 961df930be7Sderaadt dest++; 962df930be7Sderaadt } 963df930be7Sderaadt /* 964df930be7Sderaadt * restore all the changed characters 965df930be7Sderaadt */ 966df930be7Sderaadt while (*tmp) { 967ee3599c7Sespie mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp); 968df930be7Sderaadt tmp++; 969df930be7Sderaadt } 970df930be7Sderaadt } 971ee3599c7Sespie *dest = '\0'; 972df930be7Sderaadt } 97387c5c065Sespie 97487c5c065Sespie 97587c5c065Sespie /* 97687c5c065Sespie * handledash: 97787c5c065Sespie * use buffer to copy the src string, expanding character ranges 97887c5c065Sespie * on the way. 97987c5c065Sespie */ 98087c5c065Sespie static const char * 98187c5c065Sespie handledash(buffer, end, src) 98287c5c065Sespie char *buffer; 98387c5c065Sespie char *end; 98487c5c065Sespie const char *src; 98587c5c065Sespie { 98687c5c065Sespie char *p; 98787c5c065Sespie 98887c5c065Sespie p = buffer; 98987c5c065Sespie while(*src) { 99087c5c065Sespie if (src[1] == '-' && src[2]) { 99187c5c065Sespie unsigned char i; 99287c5c065Sespie for (i = (unsigned char)src[0]; 99387c5c065Sespie i <= (unsigned char)src[2]; i++) { 99487c5c065Sespie *p++ = i; 99587c5c065Sespie if (p == end) { 99687c5c065Sespie *p = '\0'; 99787c5c065Sespie return buffer; 99887c5c065Sespie } 99987c5c065Sespie } 100087c5c065Sespie src += 3; 100187c5c065Sespie } else 100287c5c065Sespie *p++ = *src++; 100387c5c065Sespie if (p == end) 100487c5c065Sespie break; 100587c5c065Sespie } 100687c5c065Sespie *p = '\0'; 100787c5c065Sespie return buffer; 100887c5c065Sespie } 100987c5c065Sespie 1010