1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 23*0Sstevel@tonic-gate /* All Rights Reserved */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate /* 27*0Sstevel@tonic-gate * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 28*0Sstevel@tonic-gate * Use is subject to license terms. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <signal.h> 34*0Sstevel@tonic-gate #include <unistd.h> 35*0Sstevel@tonic-gate #include <fcntl.h> 36*0Sstevel@tonic-gate #include "m4.h" 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #define match(c, s) (c == *s && (!s[1] || inpmatch(s+1))) 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate static char tmp_name[] = "/tmp/m4aXXXXX"; 41*0Sstevel@tonic-gate static wchar_t prev_char; 42*0Sstevel@tonic-gate static int mb_cur_max; 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate static void getflags(int *, char ***, int *); 45*0Sstevel@tonic-gate static void initalloc(void); 46*0Sstevel@tonic-gate static void expand(wchar_t **, int); 47*0Sstevel@tonic-gate static void lnsync(FILE *); 48*0Sstevel@tonic-gate static void fpath(FILE *); 49*0Sstevel@tonic-gate static void puttok(wchar_t *); 50*0Sstevel@tonic-gate static void error3(void); 51*0Sstevel@tonic-gate static wchar_t itochr(int); 52*0Sstevel@tonic-gate static wchar_t *chkbltin(wchar_t *); 53*0Sstevel@tonic-gate static wchar_t *inpmatch(wchar_t *); 54*0Sstevel@tonic-gate static void chkspace(char **, int *, char ***); 55*0Sstevel@tonic-gate static void catchsig(int); 56*0Sstevel@tonic-gate static FILE *m4open(char ***, char *, int *); 57*0Sstevel@tonic-gate static void showwrap(void); 58*0Sstevel@tonic-gate static void sputchr(wchar_t, FILE *); 59*0Sstevel@tonic-gate static void putchr(wchar_t); 60*0Sstevel@tonic-gate static void *xcalloc(size_t, size_t); 61*0Sstevel@tonic-gate static wint_t myfgetwc(FILE *, int); 62*0Sstevel@tonic-gate static wint_t myfputwc(wchar_t, FILE *); 63*0Sstevel@tonic-gate static int myfeof(int); 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate main(argc, argv) 66*0Sstevel@tonic-gate int argc; 67*0Sstevel@tonic-gate char **argv; 68*0Sstevel@tonic-gate { 69*0Sstevel@tonic-gate wchar_t t; 70*0Sstevel@tonic-gate int i, opt_end = 0; 71*0Sstevel@tonic-gate int sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0}; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate for (i = 0; sigs[i]; ++i) { 74*0Sstevel@tonic-gate if (signal(sigs[i], SIG_IGN) != SIG_IGN) 75*0Sstevel@tonic-gate (void) signal(sigs[i], catchsig); 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate tempfile = mktemp(tmp_name); 78*0Sstevel@tonic-gate (void) close(creat(tempfile, 0)); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 83*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 84*0Sstevel@tonic-gate #endif 85*0Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate if ((mb_cur_max = MB_CUR_MAX) > 1) 88*0Sstevel@tonic-gate wide = 1; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate procnam = argv[0]; 91*0Sstevel@tonic-gate getflags(&argc, &argv, &opt_end); 92*0Sstevel@tonic-gate initalloc(); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate setfname("-"); 95*0Sstevel@tonic-gate if (argc > 1) { 96*0Sstevel@tonic-gate --argc; 97*0Sstevel@tonic-gate ++argv; 98*0Sstevel@tonic-gate if (strcmp(argv[0], "-")) { 99*0Sstevel@tonic-gate ifile[ifx] = m4open(&argv, "r", &argc); 100*0Sstevel@tonic-gate setfname(argv[0]); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate for (;;) { 105*0Sstevel@tonic-gate token[0] = t = getchr(); 106*0Sstevel@tonic-gate token[1] = EOS; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate if (t == WEOF) { 109*0Sstevel@tonic-gate if (ifx > 0) { 110*0Sstevel@tonic-gate (void) fclose(ifile[ifx]); 111*0Sstevel@tonic-gate ipflr = ipstk[--ifx]; 112*0Sstevel@tonic-gate continue; 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate getflags(&argc, &argv, &opt_end); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (argc <= 1) 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * If dowrap() has been called, the m4wrap 120*0Sstevel@tonic-gate * macro has been processed, and a linked 121*0Sstevel@tonic-gate * list of m4wrap strings has been created. 122*0Sstevel@tonic-gate * The list starts at wrapstart. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate if (wrapstart) { 125*0Sstevel@tonic-gate /* 126*0Sstevel@tonic-gate * Now that EOF has been processed, 127*0Sstevel@tonic-gate * display the m4wrap strings. 128*0Sstevel@tonic-gate */ 129*0Sstevel@tonic-gate showwrap(); 130*0Sstevel@tonic-gate continue; 131*0Sstevel@tonic-gate } else 132*0Sstevel@tonic-gate break; 133*0Sstevel@tonic-gate --argc; 134*0Sstevel@tonic-gate ++argv; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate if (ifile[ifx] != stdin) 137*0Sstevel@tonic-gate (void) fclose(ifile[ifx]); 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate if (strcmp(argv[0], "-")) 140*0Sstevel@tonic-gate ifile[ifx] = m4open(&argv, "r", &argc); 141*0Sstevel@tonic-gate else 142*0Sstevel@tonic-gate ifile[ifx] = stdin; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate setfname(argv[0]); 145*0Sstevel@tonic-gate continue; 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (is_alpha(t) || t == '_') { 149*0Sstevel@tonic-gate wchar_t *tp = token+1; 150*0Sstevel@tonic-gate int tlim = toksize; 151*0Sstevel@tonic-gate struct nlist *macadd; /* temp variable */ 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate while ((*tp = getchr()) != WEOF && 154*0Sstevel@tonic-gate (is_alnum(*tp) || *tp == '_')) { 155*0Sstevel@tonic-gate tp++; 156*0Sstevel@tonic-gate if (--tlim <= 0) 157*0Sstevel@tonic-gate error2(gettext( 158*0Sstevel@tonic-gate "more than %d chars in word"), 159*0Sstevel@tonic-gate toksize); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate putbak(*tp); 162*0Sstevel@tonic-gate *tp = EOS; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate macadd = lookup(token); 165*0Sstevel@tonic-gate *Ap = (wchar_t *)macadd; 166*0Sstevel@tonic-gate if (macadd->def) { 167*0Sstevel@tonic-gate if ((wchar_t *)(++Ap) >= astklm) { 168*0Sstevel@tonic-gate --Ap; 169*0Sstevel@tonic-gate error2(gettext( 170*0Sstevel@tonic-gate "more than %d items on argument stack"), 171*0Sstevel@tonic-gate stksize); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate if (Cp++ == NULL) 175*0Sstevel@tonic-gate Cp = callst; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate Cp->argp = Ap; 178*0Sstevel@tonic-gate *Ap++ = op; 179*0Sstevel@tonic-gate puttok(token); 180*0Sstevel@tonic-gate stkchr(EOS); 181*0Sstevel@tonic-gate t = getchr(); 182*0Sstevel@tonic-gate putbak(t); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate if (t != '(') 185*0Sstevel@tonic-gate pbstr(L"()"); 186*0Sstevel@tonic-gate else /* try to fix arg count */ 187*0Sstevel@tonic-gate *Ap++ = op; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate Cp->plev = 0; 190*0Sstevel@tonic-gate } else { 191*0Sstevel@tonic-gate puttok(token); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate } else if (match(t, lquote)) { 194*0Sstevel@tonic-gate register qlev = 1; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate for (;;) { 197*0Sstevel@tonic-gate token[0] = t = getchr(); 198*0Sstevel@tonic-gate token[1] = EOS; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if (match(t, rquote)) { 201*0Sstevel@tonic-gate if (--qlev > 0) 202*0Sstevel@tonic-gate puttok(token); 203*0Sstevel@tonic-gate else 204*0Sstevel@tonic-gate break; 205*0Sstevel@tonic-gate } else if (match(t, lquote)) { 206*0Sstevel@tonic-gate ++qlev; 207*0Sstevel@tonic-gate puttok(token); 208*0Sstevel@tonic-gate } else { 209*0Sstevel@tonic-gate if (t == WEOF) 210*0Sstevel@tonic-gate error(gettext( 211*0Sstevel@tonic-gate "EOF in quote")); 212*0Sstevel@tonic-gate putchr(t); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate } else if (match(t, lcom) && 216*0Sstevel@tonic-gate ((lcom[0] != L'#' || lcom[1] != L'\0') || 217*0Sstevel@tonic-gate prev_char != '$')) { 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Don't expand commented macro (between lcom and 221*0Sstevel@tonic-gate * rcom). 222*0Sstevel@tonic-gate * What we know so far is that we have found the 223*0Sstevel@tonic-gate * left comment char (lcom). 224*0Sstevel@tonic-gate * Make sure we haven't found '#' (lcom) immediately 225*0Sstevel@tonic-gate * preceded by '$' because we want to expand "$#". 226*0Sstevel@tonic-gate */ 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate puttok(token); 229*0Sstevel@tonic-gate for (;;) { 230*0Sstevel@tonic-gate token[0] = t = getchr(); 231*0Sstevel@tonic-gate token[1] = EOS; 232*0Sstevel@tonic-gate if (match(t, rcom)) { 233*0Sstevel@tonic-gate puttok(token); 234*0Sstevel@tonic-gate break; 235*0Sstevel@tonic-gate } else { 236*0Sstevel@tonic-gate if (t == WEOF) 237*0Sstevel@tonic-gate error(gettext( 238*0Sstevel@tonic-gate "EOF in comment")); 239*0Sstevel@tonic-gate putchr(t); 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate } else if (Cp == NULL) { 243*0Sstevel@tonic-gate putchr(t); 244*0Sstevel@tonic-gate } else if (t == '(') { 245*0Sstevel@tonic-gate if (Cp->plev) 246*0Sstevel@tonic-gate stkchr(t); 247*0Sstevel@tonic-gate else { 248*0Sstevel@tonic-gate /* skip white before arg */ 249*0Sstevel@tonic-gate while ((t = getchr()) != WEOF && is_space(t)) 250*0Sstevel@tonic-gate ; 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate putbak(t); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate ++Cp->plev; 256*0Sstevel@tonic-gate } else if (t == ')') { 257*0Sstevel@tonic-gate --Cp->plev; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate if (Cp->plev == 0) { 260*0Sstevel@tonic-gate stkchr(EOS); 261*0Sstevel@tonic-gate expand(Cp->argp, Ap-Cp->argp-1); 262*0Sstevel@tonic-gate op = *Cp->argp; 263*0Sstevel@tonic-gate Ap = Cp->argp-1; 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate if (--Cp < callst) 266*0Sstevel@tonic-gate Cp = NULL; 267*0Sstevel@tonic-gate } else 268*0Sstevel@tonic-gate stkchr(t); 269*0Sstevel@tonic-gate } else if (t == ',' && Cp->plev <= 1) { 270*0Sstevel@tonic-gate stkchr(EOS); 271*0Sstevel@tonic-gate *Ap = op; 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate if ((wchar_t *)(++Ap) >= astklm) { 274*0Sstevel@tonic-gate --Ap; 275*0Sstevel@tonic-gate error2(gettext( 276*0Sstevel@tonic-gate "more than %d items on argument stack"), 277*0Sstevel@tonic-gate stksize); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate while ((t = getchr()) != WEOF && is_space(t)) 281*0Sstevel@tonic-gate ; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate putbak(t); 284*0Sstevel@tonic-gate } else { 285*0Sstevel@tonic-gate stkchr(t); 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate if (Cp != NULL) 290*0Sstevel@tonic-gate error(gettext( 291*0Sstevel@tonic-gate "EOF in argument list")); 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate delexit(exitstat, 1); 294*0Sstevel@tonic-gate return (0); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate static wchar_t * 298*0Sstevel@tonic-gate inpmatch(wchar_t *s) 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate wchar_t *tp = token+1; 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate while (*s) { 303*0Sstevel@tonic-gate *tp = getchr(); 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate if (*tp++ != *s++) { 306*0Sstevel@tonic-gate *tp = EOS; 307*0Sstevel@tonic-gate pbstr(token+1); 308*0Sstevel@tonic-gate return (0); 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate *tp = EOS; 313*0Sstevel@tonic-gate return (token); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate static void 317*0Sstevel@tonic-gate getflags(int *xargc, char ***xargv, int *option_end) 318*0Sstevel@tonic-gate { 319*0Sstevel@tonic-gate char *arg; 320*0Sstevel@tonic-gate char *t; 321*0Sstevel@tonic-gate wchar_t *s[3]; 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate while (*xargc > 1) { 324*0Sstevel@tonic-gate arg = (*xargv)[1]; /* point arg to current argument */ 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * This argument is not an option if it equals "-" or if 328*0Sstevel@tonic-gate * "--" has already been parsed. 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate if (arg[0] != '-' || arg[1] == EOS || *option_end) 331*0Sstevel@tonic-gate break; 332*0Sstevel@tonic-gate if (arg[0] == '-' && arg[1] == '-' && arg[2] == '\0') { 333*0Sstevel@tonic-gate *option_end = 1; 334*0Sstevel@tonic-gate } else { 335*0Sstevel@tonic-gate switch (arg[1]) { 336*0Sstevel@tonic-gate case 'B': 337*0Sstevel@tonic-gate chkspace(&arg, xargc, xargv); 338*0Sstevel@tonic-gate bufsize = atoi(&arg[2]); 339*0Sstevel@tonic-gate break; 340*0Sstevel@tonic-gate case 'D': 341*0Sstevel@tonic-gate initalloc(); 342*0Sstevel@tonic-gate chkspace(&arg, xargc, xargv); 343*0Sstevel@tonic-gate for (t = &arg[2]; *t; t++) { 344*0Sstevel@tonic-gate if (*t == '=') { 345*0Sstevel@tonic-gate *t++ = EOS; 346*0Sstevel@tonic-gate break; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate s[1] = str2wstr(&arg[2], 1); 350*0Sstevel@tonic-gate s[2] = str2wstr(t, 1); 351*0Sstevel@tonic-gate dodef(&s[0], 2); 352*0Sstevel@tonic-gate free(s[1]); 353*0Sstevel@tonic-gate free(s[2]); 354*0Sstevel@tonic-gate break; 355*0Sstevel@tonic-gate case 'H': 356*0Sstevel@tonic-gate chkspace(&arg, xargc, xargv); 357*0Sstevel@tonic-gate hshsize = atoi(&arg[2]); 358*0Sstevel@tonic-gate break; 359*0Sstevel@tonic-gate case 'S': 360*0Sstevel@tonic-gate chkspace(&arg, xargc, xargv); 361*0Sstevel@tonic-gate stksize = atoi(&arg[2]); 362*0Sstevel@tonic-gate break; 363*0Sstevel@tonic-gate case 'T': 364*0Sstevel@tonic-gate chkspace(&arg, xargc, xargv); 365*0Sstevel@tonic-gate toksize = atoi(&arg[2]); 366*0Sstevel@tonic-gate break; 367*0Sstevel@tonic-gate case 'U': 368*0Sstevel@tonic-gate initalloc(); 369*0Sstevel@tonic-gate chkspace(&arg, xargc, xargv); 370*0Sstevel@tonic-gate s[1] = str2wstr(&arg[2], 1); 371*0Sstevel@tonic-gate doundef(&s[0], 1); 372*0Sstevel@tonic-gate free(s[1]); 373*0Sstevel@tonic-gate break; 374*0Sstevel@tonic-gate case 'e': 375*0Sstevel@tonic-gate setbuf(stdout, NULL); 376*0Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 377*0Sstevel@tonic-gate break; 378*0Sstevel@tonic-gate case 's': 379*0Sstevel@tonic-gate /* turn on line sync */ 380*0Sstevel@tonic-gate sflag = 1; 381*0Sstevel@tonic-gate break; 382*0Sstevel@tonic-gate default: 383*0Sstevel@tonic-gate (void) fprintf(stderr, 384*0Sstevel@tonic-gate gettext("%s: bad option: %s\n"), 385*0Sstevel@tonic-gate procnam, arg); 386*0Sstevel@tonic-gate delexit(NOT_OK, 0); 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate } /* end else not "--" */ 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate (*xargv)++; 391*0Sstevel@tonic-gate --(*xargc); 392*0Sstevel@tonic-gate } /* end while options to process */ 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate /* 396*0Sstevel@tonic-gate * Function: chkspace 397*0Sstevel@tonic-gate * 398*0Sstevel@tonic-gate * If there is a space between the option and its argument, 399*0Sstevel@tonic-gate * adjust argptr so that &arg[2] will point to beginning of the option argument. 400*0Sstevel@tonic-gate * This will ensure that processing in getflags() will work, because &arg[2] 401*0Sstevel@tonic-gate * will point to the beginning of the option argument whether or not we have 402*0Sstevel@tonic-gate * a space between the option and its argument. If there is a space between 403*0Sstevel@tonic-gate * the option and its argument, also adjust xargv and xargc because we are 404*0Sstevel@tonic-gate * processing the next argument. 405*0Sstevel@tonic-gate */ 406*0Sstevel@tonic-gate static void 407*0Sstevel@tonic-gate chkspace(char **argptr, int *xargc, char ***xargv) 408*0Sstevel@tonic-gate { 409*0Sstevel@tonic-gate if ((*argptr)[2] == EOS) { 410*0Sstevel@tonic-gate /* there is a space between the option and its argument */ 411*0Sstevel@tonic-gate (*xargv)++; /* look at the next argument */ 412*0Sstevel@tonic-gate --(*xargc); 413*0Sstevel@tonic-gate /* 414*0Sstevel@tonic-gate * Adjust argptr if the option is followed by an 415*0Sstevel@tonic-gate * option argument. 416*0Sstevel@tonic-gate */ 417*0Sstevel@tonic-gate if (*xargc > 1) { 418*0Sstevel@tonic-gate *argptr = (*xargv)[1]; 419*0Sstevel@tonic-gate /* point &arg[2] to beginning of option argument */ 420*0Sstevel@tonic-gate *argptr -= 2; 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate static void 426*0Sstevel@tonic-gate initalloc() 427*0Sstevel@tonic-gate { 428*0Sstevel@tonic-gate static done = 0; 429*0Sstevel@tonic-gate register t; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate if (done++) 432*0Sstevel@tonic-gate return; 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate hshtab = xcalloc(hshsize, sizeof (struct nlist *)); 435*0Sstevel@tonic-gate callst = xcalloc(stksize/3+1, sizeof (struct call)); 436*0Sstevel@tonic-gate Ap = argstk = xcalloc(stksize+3, sizeof (wchar_t *)); 437*0Sstevel@tonic-gate ipstk[0] = ipflr = ip = ibuf = xcalloc(bufsize+1, sizeof (wchar_t)); 438*0Sstevel@tonic-gate op = obuf = xcalloc(bufsize+1, sizeof (wchar_t)); 439*0Sstevel@tonic-gate token = xcalloc(toksize+1, sizeof (wchar_t)); 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate astklm = (wchar_t *)(&argstk[stksize]); 442*0Sstevel@tonic-gate ibuflm = &ibuf[bufsize]; 443*0Sstevel@tonic-gate obuflm = &obuf[bufsize]; 444*0Sstevel@tonic-gate toklm = &token[toksize]; 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate for (t = 0; barray[t].bname; ++t) { 447*0Sstevel@tonic-gate wchar_t p[2] = {0, EOS}; 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate p[0] = builtin(t); 450*0Sstevel@tonic-gate install(barray[t].bname, p, NOPUSH); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate install(L"unix", nullstr, NOPUSH); 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate void 456*0Sstevel@tonic-gate install(wchar_t *nam, wchar_t *val, int mode) 457*0Sstevel@tonic-gate { 458*0Sstevel@tonic-gate register struct nlist *np; 459*0Sstevel@tonic-gate wchar_t *cp; 460*0Sstevel@tonic-gate int l; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate if (mode == PUSH) 463*0Sstevel@tonic-gate (void) lookup(nam); /* lookup sets hshval */ 464*0Sstevel@tonic-gate else 465*0Sstevel@tonic-gate while (undef(nam)) /* undef calls lookup */ 466*0Sstevel@tonic-gate ; 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate np = xcalloc(1, sizeof (*np)); 469*0Sstevel@tonic-gate np->name = wstrdup(nam); 470*0Sstevel@tonic-gate np->next = hshtab[hshval]; 471*0Sstevel@tonic-gate hshtab[hshval] = np; 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate cp = xcalloc((l = wcslen(val))+1, sizeof (*val)); 474*0Sstevel@tonic-gate np->def = cp; 475*0Sstevel@tonic-gate cp = &cp[l]; 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate while (*val) 478*0Sstevel@tonic-gate *--cp = *val++; 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate struct nlist * 482*0Sstevel@tonic-gate lookup(wchar_t *str) 483*0Sstevel@tonic-gate { 484*0Sstevel@tonic-gate wchar_t *s1; 485*0Sstevel@tonic-gate register struct nlist *np; 486*0Sstevel@tonic-gate static struct nlist nodef; 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate s1 = str; 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate for (hshval = 0; *s1; ) 491*0Sstevel@tonic-gate hshval += *s1++; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate hshval %= hshsize; 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate for (np = hshtab[hshval]; np != NULL; np = np->next) { 496*0Sstevel@tonic-gate if (*str == *np->name && wcscmp(str, np->name) == 0) 497*0Sstevel@tonic-gate return (np); 498*0Sstevel@tonic-gate } 499*0Sstevel@tonic-gate return (&nodef); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate static void 503*0Sstevel@tonic-gate expand(wchar_t **a1, int c) 504*0Sstevel@tonic-gate { 505*0Sstevel@tonic-gate wchar_t *dp; 506*0Sstevel@tonic-gate register struct nlist *sp; 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate sp = (struct nlist *)a1[-1]; 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate if (sp->tflag || trace) { 511*0Sstevel@tonic-gate int i; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate (void) fprintf(stderr, 514*0Sstevel@tonic-gate "Trace(%d): %ws", Cp-callst, a1[0]); 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate if (c > 0) { 517*0Sstevel@tonic-gate (void) fprintf(stderr, "(%ws", chkbltin(a1[1])); 518*0Sstevel@tonic-gate for (i = 2; i <= c; ++i) 519*0Sstevel@tonic-gate (void) fprintf(stderr, ",%ws", chkbltin(a1[i])); 520*0Sstevel@tonic-gate (void) fprintf(stderr, ")"); 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate dp = sp->def; 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate for (; *dp; ++dp) { 528*0Sstevel@tonic-gate if (is_builtin(*dp)) { 529*0Sstevel@tonic-gate (*barray[builtin_idx(*dp)].bfunc)(a1, c); 530*0Sstevel@tonic-gate } else if (dp[1] == '$') { 531*0Sstevel@tonic-gate if (is_digit(*dp)) { 532*0Sstevel@tonic-gate register n; 533*0Sstevel@tonic-gate if ((n = *dp-'0') <= c) 534*0Sstevel@tonic-gate pbstr(a1[n]); 535*0Sstevel@tonic-gate ++dp; 536*0Sstevel@tonic-gate } else if (*dp == '#') { 537*0Sstevel@tonic-gate pbnum((long)c); 538*0Sstevel@tonic-gate ++dp; 539*0Sstevel@tonic-gate } else if (*dp == '*' || *dp == '@') { 540*0Sstevel@tonic-gate register i = c; 541*0Sstevel@tonic-gate wchar_t **a = a1; 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate if (i > 0) 544*0Sstevel@tonic-gate for (;;) { 545*0Sstevel@tonic-gate if (*dp == '@') 546*0Sstevel@tonic-gate pbstr(rquote); 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate pbstr(a[i--]); 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate if (*dp == '@') 551*0Sstevel@tonic-gate pbstr(lquote); 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate if (i <= 0) 554*0Sstevel@tonic-gate break; 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate pbstr(L","); 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate ++dp; 559*0Sstevel@tonic-gate } else 560*0Sstevel@tonic-gate putbak(*dp); 561*0Sstevel@tonic-gate } else 562*0Sstevel@tonic-gate putbak(*dp); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate void 567*0Sstevel@tonic-gate setfname(char *s) 568*0Sstevel@tonic-gate { 569*0Sstevel@tonic-gate if (fname[ifx]) 570*0Sstevel@tonic-gate free(fname[ifx]); 571*0Sstevel@tonic-gate if ((fname[ifx] = strdup(s)) == NULL) 572*0Sstevel@tonic-gate error(gettext("out of storage")); 573*0Sstevel@tonic-gate fline[ifx] = 1; 574*0Sstevel@tonic-gate nflag = 1; 575*0Sstevel@tonic-gate lnsync(stdout); 576*0Sstevel@tonic-gate } 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate static void 579*0Sstevel@tonic-gate lnsync(FILE *iop) 580*0Sstevel@tonic-gate { 581*0Sstevel@tonic-gate static int cline = 0; 582*0Sstevel@tonic-gate static int cfile = 0; 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate if (!sflag || iop != stdout) 585*0Sstevel@tonic-gate return; 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate if (nflag || ifx != cfile) { 588*0Sstevel@tonic-gate nflag = 0; 589*0Sstevel@tonic-gate cfile = ifx; 590*0Sstevel@tonic-gate (void) fprintf(iop, "#line %d \"", cline = fline[ifx]); 591*0Sstevel@tonic-gate fpath(iop); 592*0Sstevel@tonic-gate (void) fprintf(iop, "\"\n"); 593*0Sstevel@tonic-gate } else if (++cline != fline[ifx]) 594*0Sstevel@tonic-gate (void) fprintf(iop, "#line %d\n", cline = fline[ifx]); 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate static void 598*0Sstevel@tonic-gate fpath(FILE *iop) 599*0Sstevel@tonic-gate { 600*0Sstevel@tonic-gate register i; 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate if (fname[0] == NULL) 603*0Sstevel@tonic-gate return; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate (void) fprintf(iop, "%s", fname[0]); 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate for (i = 1; i <= ifx; ++i) 608*0Sstevel@tonic-gate (void) fprintf(iop, ":%s", fname[i]); 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate /* ARGSUSED */ 612*0Sstevel@tonic-gate static void 613*0Sstevel@tonic-gate catchsig(int i) 614*0Sstevel@tonic-gate { 615*0Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); 616*0Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 617*0Sstevel@tonic-gate delexit(NOT_OK, 0); 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate void 621*0Sstevel@tonic-gate delexit(int code, int flushio) 622*0Sstevel@tonic-gate { 623*0Sstevel@tonic-gate register i; 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate cf = stdout; 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate /* 628*0Sstevel@tonic-gate * if (ofx != 0) { 629*0Sstevel@tonic-gate * ofx = 0; 630*0Sstevel@tonic-gate * code = NOT_OK; 631*0Sstevel@tonic-gate * } 632*0Sstevel@tonic-gate */ 633*0Sstevel@tonic-gate ofx = 0; /* ensure that everything comes out */ 634*0Sstevel@tonic-gate for (i = 1; i < 10; i++) 635*0Sstevel@tonic-gate undiv(i, code); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate tempfile[7] = 'a'; 638*0Sstevel@tonic-gate (void) unlink(tempfile); 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate /* flush standard I/O buffers, ie: call exit() not _exit() */ 641*0Sstevel@tonic-gate if (flushio) 642*0Sstevel@tonic-gate exit(code); 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate _exit(code); 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate static void 648*0Sstevel@tonic-gate puttok(wchar_t *tp) 649*0Sstevel@tonic-gate { 650*0Sstevel@tonic-gate if (Cp) { 651*0Sstevel@tonic-gate while (*tp) 652*0Sstevel@tonic-gate stkchr(*tp++); 653*0Sstevel@tonic-gate } else if (cf) { 654*0Sstevel@tonic-gate while (*tp) { 655*0Sstevel@tonic-gate sputchr(*tp++, cf); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate void 661*0Sstevel@tonic-gate pbstr(wchar_t *str) 662*0Sstevel@tonic-gate { 663*0Sstevel@tonic-gate wchar_t *p; 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate for (p = str + wcslen(str); --p >= str; ) 666*0Sstevel@tonic-gate putbak(*p); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate void 670*0Sstevel@tonic-gate undiv(int i, int code) 671*0Sstevel@tonic-gate { 672*0Sstevel@tonic-gate register FILE *fp; 673*0Sstevel@tonic-gate wint_t c; 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate if (i < 1 || i > 9 || i == ofx || !ofile[i]) 676*0Sstevel@tonic-gate return; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate (void) fclose(ofile[i]); 679*0Sstevel@tonic-gate tempfile[7] = 'a'+i; 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate if (code == OK && cf) { 682*0Sstevel@tonic-gate fp = xfopen(tempfile, "r"); 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate if (wide) { 685*0Sstevel@tonic-gate while ((c = myfgetwc(fp, -1)) != WEOF) 686*0Sstevel@tonic-gate sputchr((wchar_t)c, cf); 687*0Sstevel@tonic-gate } else { 688*0Sstevel@tonic-gate while ((c = (wint_t)getc(fp)) != WEOF) 689*0Sstevel@tonic-gate sputchr((wchar_t)c, cf); 690*0Sstevel@tonic-gate } 691*0Sstevel@tonic-gate 692*0Sstevel@tonic-gate (void) fclose(fp); 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate (void) unlink(tempfile); 696*0Sstevel@tonic-gate ofile[i] = NULL; 697*0Sstevel@tonic-gate } 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate void 700*0Sstevel@tonic-gate pbnum(long num) 701*0Sstevel@tonic-gate { 702*0Sstevel@tonic-gate pbnbr(num, 10, 1); 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate void 706*0Sstevel@tonic-gate pbnbr(long nbr, int base, int len) 707*0Sstevel@tonic-gate { 708*0Sstevel@tonic-gate register neg = 0; 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate if (base <= 0) 711*0Sstevel@tonic-gate return; 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate if (nbr < 0) 714*0Sstevel@tonic-gate neg = 1; 715*0Sstevel@tonic-gate else 716*0Sstevel@tonic-gate nbr = -nbr; 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate while (nbr < 0) { 719*0Sstevel@tonic-gate register int i; 720*0Sstevel@tonic-gate if (base > 1) { 721*0Sstevel@tonic-gate i = nbr%base; 722*0Sstevel@tonic-gate nbr /= base; 723*0Sstevel@tonic-gate #if (-3 % 2) != -1 724*0Sstevel@tonic-gate while (i > 0) { 725*0Sstevel@tonic-gate i -= base; 726*0Sstevel@tonic-gate ++nbr; 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate #endif 729*0Sstevel@tonic-gate i = -i; 730*0Sstevel@tonic-gate } else { 731*0Sstevel@tonic-gate i = 1; 732*0Sstevel@tonic-gate ++nbr; 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate putbak(itochr(i)); 735*0Sstevel@tonic-gate --len; 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate while (--len >= 0) 739*0Sstevel@tonic-gate putbak('0'); 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate if (neg) 742*0Sstevel@tonic-gate putbak('-'); 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate static wchar_t 746*0Sstevel@tonic-gate itochr(int i) 747*0Sstevel@tonic-gate { 748*0Sstevel@tonic-gate if (i > 9) 749*0Sstevel@tonic-gate return ((wchar_t)(i-10+'A')); 750*0Sstevel@tonic-gate else 751*0Sstevel@tonic-gate return ((wchar_t)(i+'0')); 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate long 755*0Sstevel@tonic-gate ctol(wchar_t *str) 756*0Sstevel@tonic-gate { 757*0Sstevel@tonic-gate register sign; 758*0Sstevel@tonic-gate long num; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate while (is_space(*str)) 761*0Sstevel@tonic-gate ++str; 762*0Sstevel@tonic-gate num = 0; 763*0Sstevel@tonic-gate if (*str == '-') { 764*0Sstevel@tonic-gate sign = -1; 765*0Sstevel@tonic-gate ++str; 766*0Sstevel@tonic-gate } else 767*0Sstevel@tonic-gate sign = 1; 768*0Sstevel@tonic-gate while (is_digit(*str)) 769*0Sstevel@tonic-gate num = num*10 + *str++ - '0'; 770*0Sstevel@tonic-gate return (sign * num); 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate int 774*0Sstevel@tonic-gate min(int a, int b) 775*0Sstevel@tonic-gate { 776*0Sstevel@tonic-gate if (a > b) 777*0Sstevel@tonic-gate return (b); 778*0Sstevel@tonic-gate return (a); 779*0Sstevel@tonic-gate } 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate FILE * 782*0Sstevel@tonic-gate xfopen(char *name, char *mode) 783*0Sstevel@tonic-gate { 784*0Sstevel@tonic-gate FILE *fp; 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate if ((fp = fopen(name, mode)) == NULL) 787*0Sstevel@tonic-gate error(gettext("can't open file")); 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate return (fp); 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate /* 793*0Sstevel@tonic-gate * m4open 794*0Sstevel@tonic-gate * 795*0Sstevel@tonic-gate * Continue processing files when unable to open the given file argument. 796*0Sstevel@tonic-gate */ 797*0Sstevel@tonic-gate FILE * 798*0Sstevel@tonic-gate m4open(char ***argvec, char *mode, int *argcnt) 799*0Sstevel@tonic-gate { 800*0Sstevel@tonic-gate FILE *fp; 801*0Sstevel@tonic-gate char *arg; 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate while (*argcnt > 0) { 804*0Sstevel@tonic-gate arg = (*argvec)[0]; /* point arg to current file name */ 805*0Sstevel@tonic-gate if (arg[0] == '-' && arg[1] == EOS) 806*0Sstevel@tonic-gate return (stdin); 807*0Sstevel@tonic-gate else { 808*0Sstevel@tonic-gate if ((fp = fopen(arg, mode)) == NULL) { 809*0Sstevel@tonic-gate (void) fprintf(stderr, gettext( 810*0Sstevel@tonic-gate "m4: cannot open %s: "), arg); 811*0Sstevel@tonic-gate perror(""); 812*0Sstevel@tonic-gate if (*argcnt == 1) { 813*0Sstevel@tonic-gate /* last arg therefore exit */ 814*0Sstevel@tonic-gate error3(); 815*0Sstevel@tonic-gate } else { 816*0Sstevel@tonic-gate exitstat = 1; 817*0Sstevel@tonic-gate (*argvec)++; /* try next arg */ 818*0Sstevel@tonic-gate (*argcnt)--; 819*0Sstevel@tonic-gate } 820*0Sstevel@tonic-gate } else 821*0Sstevel@tonic-gate break; 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate return (fp); 825*0Sstevel@tonic-gate } 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate void * 828*0Sstevel@tonic-gate xmalloc(size_t size) 829*0Sstevel@tonic-gate { 830*0Sstevel@tonic-gate void *ptr; 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate if ((ptr = malloc(size)) == NULL) 833*0Sstevel@tonic-gate error(gettext("out of storage")); 834*0Sstevel@tonic-gate return (ptr); 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate static void * 838*0Sstevel@tonic-gate xcalloc(size_t nbr, size_t size) 839*0Sstevel@tonic-gate { 840*0Sstevel@tonic-gate register void *ptr; 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate ptr = xmalloc(nbr * size); 843*0Sstevel@tonic-gate (void) memset(ptr, '\0', nbr * size); 844*0Sstevel@tonic-gate return (ptr); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate void 848*0Sstevel@tonic-gate error2(char *str, int num) 849*0Sstevel@tonic-gate { 850*0Sstevel@tonic-gate char buf[500]; 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), str, num); 853*0Sstevel@tonic-gate error(buf); 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate void 857*0Sstevel@tonic-gate error(char *str) 858*0Sstevel@tonic-gate { 859*0Sstevel@tonic-gate (void) fprintf(stderr, "\n%s:", procnam); 860*0Sstevel@tonic-gate fpath(stderr); 861*0Sstevel@tonic-gate (void) fprintf(stderr, ":%d %s\n", fline[ifx], str); 862*0Sstevel@tonic-gate error3(); 863*0Sstevel@tonic-gate } 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate static void 866*0Sstevel@tonic-gate error3() 867*0Sstevel@tonic-gate { 868*0Sstevel@tonic-gate if (Cp) { 869*0Sstevel@tonic-gate register struct call *mptr; 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* fix limit */ 872*0Sstevel@tonic-gate *op = EOS; 873*0Sstevel@tonic-gate (Cp+1)->argp = Ap+1; 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate for (mptr = callst; mptr <= Cp; ++mptr) { 876*0Sstevel@tonic-gate wchar_t **aptr, **lim; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate aptr = mptr->argp; 879*0Sstevel@tonic-gate lim = (mptr+1)->argp-1; 880*0Sstevel@tonic-gate if (mptr == callst) 881*0Sstevel@tonic-gate (void) fputws(*aptr, stderr); 882*0Sstevel@tonic-gate ++aptr; 883*0Sstevel@tonic-gate (void) fputs("(", stderr); 884*0Sstevel@tonic-gate if (aptr < lim) 885*0Sstevel@tonic-gate for (;;) { 886*0Sstevel@tonic-gate (void) fputws(*aptr++, stderr); 887*0Sstevel@tonic-gate if (aptr >= lim) 888*0Sstevel@tonic-gate break; 889*0Sstevel@tonic-gate (void) fputs(",", stderr); 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate } 892*0Sstevel@tonic-gate while (--mptr >= callst) 893*0Sstevel@tonic-gate (void) fputs(")", stderr); 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate (void) fputs("\n", stderr); 896*0Sstevel@tonic-gate } 897*0Sstevel@tonic-gate delexit(NOT_OK, 1); 898*0Sstevel@tonic-gate } 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate static wchar_t * 901*0Sstevel@tonic-gate chkbltin(wchar_t *s) 902*0Sstevel@tonic-gate { 903*0Sstevel@tonic-gate static wchar_t buf[24]; 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate if (is_builtin(*s)) { 906*0Sstevel@tonic-gate (void) swprintf(buf, sizeof (buf)/sizeof (wchar_t), L"<%ls>", 907*0Sstevel@tonic-gate barray[builtin_idx(*s)].bname); 908*0Sstevel@tonic-gate return (buf); 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate return (s); 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate wchar_t 914*0Sstevel@tonic-gate getchr() 915*0Sstevel@tonic-gate { 916*0Sstevel@tonic-gate static wchar_t C; 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate prev_char = C; 919*0Sstevel@tonic-gate if (ip > ipflr) 920*0Sstevel@tonic-gate return (*--ip); 921*0Sstevel@tonic-gate if (wide) { 922*0Sstevel@tonic-gate C = (wchar_t)(myfeof(ifx) ? WEOF : myfgetwc(NULL, ifx)); 923*0Sstevel@tonic-gate } else { 924*0Sstevel@tonic-gate C = (wchar_t)(feof(ifile[ifx]) ? 925*0Sstevel@tonic-gate WEOF : (wint_t)getc(ifile[ifx])); 926*0Sstevel@tonic-gate } 927*0Sstevel@tonic-gate if (C == '\n') 928*0Sstevel@tonic-gate fline[ifx]++; 929*0Sstevel@tonic-gate return (C); 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate /* 933*0Sstevel@tonic-gate * showwrap 934*0Sstevel@tonic-gate * 935*0Sstevel@tonic-gate * Loop through the list of m4wrap strings. Call pbstr() so that the 936*0Sstevel@tonic-gate * string will be displayed, then delete the list entry and free the memory 937*0Sstevel@tonic-gate * allocated for it. 938*0Sstevel@tonic-gate */ 939*0Sstevel@tonic-gate static void 940*0Sstevel@tonic-gate showwrap() 941*0Sstevel@tonic-gate { 942*0Sstevel@tonic-gate struct Wrap *prev; 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate while (wrapstart) { 945*0Sstevel@tonic-gate pbstr(wrapstart->wrapstr); 946*0Sstevel@tonic-gate free(wrapstart->wrapstr); 947*0Sstevel@tonic-gate prev = wrapstart; 948*0Sstevel@tonic-gate wrapstart = wrapstart->nxt; 949*0Sstevel@tonic-gate free(prev); 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate static void 954*0Sstevel@tonic-gate sputchr(wchar_t c, FILE *f) 955*0Sstevel@tonic-gate { 956*0Sstevel@tonic-gate wint_t ret; 957*0Sstevel@tonic-gate 958*0Sstevel@tonic-gate if (is_builtin(c)) 959*0Sstevel@tonic-gate return; 960*0Sstevel@tonic-gate if (wide) 961*0Sstevel@tonic-gate ret = myfputwc(c, f); 962*0Sstevel@tonic-gate else 963*0Sstevel@tonic-gate ret = (wint_t)putc((int)c, f); 964*0Sstevel@tonic-gate if (ret == WEOF) 965*0Sstevel@tonic-gate error(gettext("output error")); 966*0Sstevel@tonic-gate if (ret == '\n') 967*0Sstevel@tonic-gate lnsync(f); 968*0Sstevel@tonic-gate } 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate static void 971*0Sstevel@tonic-gate putchr(wchar_t c) 972*0Sstevel@tonic-gate { 973*0Sstevel@tonic-gate wint_t ret; 974*0Sstevel@tonic-gate 975*0Sstevel@tonic-gate if (Cp) 976*0Sstevel@tonic-gate stkchr(c); 977*0Sstevel@tonic-gate else if (cf) { 978*0Sstevel@tonic-gate if (sflag) 979*0Sstevel@tonic-gate sputchr(c, cf); 980*0Sstevel@tonic-gate else { 981*0Sstevel@tonic-gate if (is_builtin(c)) 982*0Sstevel@tonic-gate return; 983*0Sstevel@tonic-gate if (wide) 984*0Sstevel@tonic-gate ret = myfputwc(c, cf); 985*0Sstevel@tonic-gate else 986*0Sstevel@tonic-gate ret = (wint_t)putc((int)c, cf); 987*0Sstevel@tonic-gate if (ret == WEOF) { 988*0Sstevel@tonic-gate error(gettext("output error")); 989*0Sstevel@tonic-gate } 990*0Sstevel@tonic-gate } 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate } 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate wchar_t * 995*0Sstevel@tonic-gate wstrdup(wchar_t *p) 996*0Sstevel@tonic-gate { 997*0Sstevel@tonic-gate size_t len = wcslen(p); 998*0Sstevel@tonic-gate wchar_t *ret; 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate ret = xmalloc((len + 1) * sizeof (wchar_t)); 1001*0Sstevel@tonic-gate (void) wcscpy(ret, p); 1002*0Sstevel@tonic-gate return (ret); 1003*0Sstevel@tonic-gate } 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gate int 1006*0Sstevel@tonic-gate wstoi(wchar_t *p) 1007*0Sstevel@tonic-gate { 1008*0Sstevel@tonic-gate return ((int)wcstol(p, NULL, 10)); 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate char * 1012*0Sstevel@tonic-gate wstr2str(wchar_t *from, int alloc) 1013*0Sstevel@tonic-gate { 1014*0Sstevel@tonic-gate static char *retbuf; 1015*0Sstevel@tonic-gate static size_t bsiz; 1016*0Sstevel@tonic-gate char *p, *ret; 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate if (alloc) { 1019*0Sstevel@tonic-gate ret = p = xmalloc(wcslen(from) * mb_cur_max + 1); 1020*0Sstevel@tonic-gate } else { 1021*0Sstevel@tonic-gate while (bsiz < (wcslen(from) * mb_cur_max + 1)) { 1022*0Sstevel@tonic-gate if ((p = realloc(retbuf, bsiz + 256)) == NULL) 1023*0Sstevel@tonic-gate error(gettext("out of storage")); 1024*0Sstevel@tonic-gate bsiz += 256; 1025*0Sstevel@tonic-gate retbuf = p; 1026*0Sstevel@tonic-gate } 1027*0Sstevel@tonic-gate ret = p = retbuf; 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate 1030*0Sstevel@tonic-gate if (wide) { 1031*0Sstevel@tonic-gate while (*from) { 1032*0Sstevel@tonic-gate int len; 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate if (*from & INVALID_CHAR) { 1035*0Sstevel@tonic-gate *p = (char)(*from & ~INVALID_CHAR); 1036*0Sstevel@tonic-gate len = 1; 1037*0Sstevel@tonic-gate } else { 1038*0Sstevel@tonic-gate if ((len = wctomb(p, *from)) == -1) { 1039*0Sstevel@tonic-gate *p = (char)*from; 1040*0Sstevel@tonic-gate len = 1; 1041*0Sstevel@tonic-gate } 1042*0Sstevel@tonic-gate } 1043*0Sstevel@tonic-gate p += len; 1044*0Sstevel@tonic-gate from++; 1045*0Sstevel@tonic-gate } 1046*0Sstevel@tonic-gate } else { 1047*0Sstevel@tonic-gate while (*from) 1048*0Sstevel@tonic-gate *p++ = (char)*from++; 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate *p = '\0'; 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate return (ret); 1053*0Sstevel@tonic-gate } 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate wchar_t * 1056*0Sstevel@tonic-gate str2wstr(char *from, int alloc) 1057*0Sstevel@tonic-gate { 1058*0Sstevel@tonic-gate static wchar_t *retbuf; 1059*0Sstevel@tonic-gate static size_t bsiz; 1060*0Sstevel@tonic-gate wchar_t *p, *ret; 1061*0Sstevel@tonic-gate 1062*0Sstevel@tonic-gate if (alloc) { 1063*0Sstevel@tonic-gate ret = p = xmalloc((strlen(from) + 1) * sizeof (wchar_t)); 1064*0Sstevel@tonic-gate } else { 1065*0Sstevel@tonic-gate while (bsiz < (strlen(from) + 1)) { 1066*0Sstevel@tonic-gate if ((p = realloc(retbuf, 1067*0Sstevel@tonic-gate (bsiz + 256) * sizeof (wchar_t))) == NULL) { 1068*0Sstevel@tonic-gate error(gettext("out of storage")); 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate bsiz += 256; 1071*0Sstevel@tonic-gate retbuf = p; 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate ret = p = retbuf; 1074*0Sstevel@tonic-gate } 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate if (wide) { 1077*0Sstevel@tonic-gate while (*from) { 1078*0Sstevel@tonic-gate int len; 1079*0Sstevel@tonic-gate wchar_t wc; 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate if ((len = mbtowc(&wc, from, mb_cur_max)) <= 0) { 1082*0Sstevel@tonic-gate wc = *from | INVALID_CHAR; 1083*0Sstevel@tonic-gate len = 1; 1084*0Sstevel@tonic-gate } 1085*0Sstevel@tonic-gate *p++ = wc; 1086*0Sstevel@tonic-gate from += len; 1087*0Sstevel@tonic-gate } 1088*0Sstevel@tonic-gate } else { 1089*0Sstevel@tonic-gate while (*from) 1090*0Sstevel@tonic-gate *p++ = (unsigned char) *from++; 1091*0Sstevel@tonic-gate } 1092*0Sstevel@tonic-gate *p = 0; 1093*0Sstevel@tonic-gate 1094*0Sstevel@tonic-gate return (ret); 1095*0Sstevel@tonic-gate } 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate static wint_t 1098*0Sstevel@tonic-gate myfgetwc(FILE *fp, int idx) 1099*0Sstevel@tonic-gate { 1100*0Sstevel@tonic-gate int i, c, len, nb; 1101*0Sstevel@tonic-gate wchar_t wc; 1102*0Sstevel@tonic-gate unsigned char *buf; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate if (fp == NULL) 1105*0Sstevel@tonic-gate fp = ifile[idx]; 1106*0Sstevel@tonic-gate else 1107*0Sstevel@tonic-gate idx = 10; /* extra slot */ 1108*0Sstevel@tonic-gate buf = ibuffer[idx].buffer; 1109*0Sstevel@tonic-gate nb = ibuffer[idx].nbytes; 1110*0Sstevel@tonic-gate len = 0; 1111*0Sstevel@tonic-gate for (i = 1; i <= mb_cur_max; i++) { 1112*0Sstevel@tonic-gate if (nb < i) { 1113*0Sstevel@tonic-gate c = getc(fp); 1114*0Sstevel@tonic-gate if (c == EOF) { 1115*0Sstevel@tonic-gate if (nb == 0) 1116*0Sstevel@tonic-gate return (WEOF); 1117*0Sstevel@tonic-gate else 1118*0Sstevel@tonic-gate break; 1119*0Sstevel@tonic-gate } 1120*0Sstevel@tonic-gate buf[nb++] = (unsigned char)c; 1121*0Sstevel@tonic-gate } 1122*0Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)buf, i)) >= 0) 1123*0Sstevel@tonic-gate break; 1124*0Sstevel@tonic-gate } 1125*0Sstevel@tonic-gate if (len <= 0) { 1126*0Sstevel@tonic-gate wc = buf[0] | INVALID_CHAR; 1127*0Sstevel@tonic-gate len = 1; 1128*0Sstevel@tonic-gate } 1129*0Sstevel@tonic-gate nb -= len; 1130*0Sstevel@tonic-gate if (nb > 0) { 1131*0Sstevel@tonic-gate for (i = 0; i < nb; i++) 1132*0Sstevel@tonic-gate buf[i] = buf[i + len]; 1133*0Sstevel@tonic-gate } 1134*0Sstevel@tonic-gate ibuffer[idx].nbytes = nb; 1135*0Sstevel@tonic-gate return (wc); 1136*0Sstevel@tonic-gate } 1137*0Sstevel@tonic-gate 1138*0Sstevel@tonic-gate static wint_t 1139*0Sstevel@tonic-gate myfputwc(wchar_t wc, FILE *fp) 1140*0Sstevel@tonic-gate { 1141*0Sstevel@tonic-gate if (wc & INVALID_CHAR) { 1142*0Sstevel@tonic-gate wc &= ~INVALID_CHAR; 1143*0Sstevel@tonic-gate return (fputc((int)wc, fp)); 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate return (fputwc(wc, fp)); 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate static int 1149*0Sstevel@tonic-gate myfeof(int idx) 1150*0Sstevel@tonic-gate { 1151*0Sstevel@tonic-gate return (ibuffer[idx].nbytes == 0 && feof(ifile[idx])); 1152*0Sstevel@tonic-gate } 1153