13b6eaa7bSAndrey A. Chernov /* $Header: /src/pub/tcsh/sh.glob.c,v 3.47 2000/11/11 23:03:37 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * sh.glob.c: Regular expression expansion 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 17c80476e4SDavid E. O'Brien * 3. All advertising materials mentioning features or use of this software 18c80476e4SDavid E. O'Brien * must display the following acknowledgement: 19c80476e4SDavid E. O'Brien * This product includes software developed by the University of 20c80476e4SDavid E. O'Brien * California, Berkeley and its contributors. 21c80476e4SDavid E. O'Brien * 4. Neither the name of the University nor the names of its contributors 22c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 23c80476e4SDavid E. O'Brien * without specific prior written permission. 24c80476e4SDavid E. O'Brien * 25c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35c80476e4SDavid E. O'Brien * SUCH DAMAGE. 36c80476e4SDavid E. O'Brien */ 37c80476e4SDavid E. O'Brien #include "sh.h" 38c80476e4SDavid E. O'Brien 393b6eaa7bSAndrey A. Chernov RCSID("$Id: sh.glob.c,v 3.47 2000/11/11 23:03:37 christos Exp $") 40c80476e4SDavid E. O'Brien 41c80476e4SDavid E. O'Brien #include "tc.h" 42c80476e4SDavid E. O'Brien 43c80476e4SDavid E. O'Brien #include "glob.h" 44c80476e4SDavid E. O'Brien 45c80476e4SDavid E. O'Brien static int noglob; 46c80476e4SDavid E. O'Brien static int pargsiz, gargsiz; 47c80476e4SDavid E. O'Brien 48c80476e4SDavid E. O'Brien /* 49c80476e4SDavid E. O'Brien * Values for gflag 50c80476e4SDavid E. O'Brien */ 51c80476e4SDavid E. O'Brien #define G_NONE 0 /* No globbing needed */ 52c80476e4SDavid E. O'Brien #define G_GLOB 1 /* string contains *?[] characters */ 53c80476e4SDavid E. O'Brien #define G_CSH 2 /* string contains ~`{ characters */ 54c80476e4SDavid E. O'Brien 55c80476e4SDavid E. O'Brien #define GLOBSPACE 100 /* Alloc increment */ 56c80476e4SDavid E. O'Brien #define LONGBSIZE 10240 /* Backquote expansion buffer size */ 57c80476e4SDavid E. O'Brien 58c80476e4SDavid E. O'Brien 59c80476e4SDavid E. O'Brien #define LBRC '{' 60c80476e4SDavid E. O'Brien #define RBRC '}' 61c80476e4SDavid E. O'Brien #define LBRK '[' 62c80476e4SDavid E. O'Brien #define RBRK ']' 63c80476e4SDavid E. O'Brien #define EOS '\0' 64c80476e4SDavid E. O'Brien 65c80476e4SDavid E. O'Brien Char **gargv = NULL; 66c80476e4SDavid E. O'Brien int gargc = 0; 67c80476e4SDavid E. O'Brien Char **pargv = NULL; 68c80476e4SDavid E. O'Brien static int pargc = 0; 69c80476e4SDavid E. O'Brien 70c80476e4SDavid E. O'Brien /* 71c80476e4SDavid E. O'Brien * globbing is now done in two stages. In the first pass we expand 72c80476e4SDavid E. O'Brien * csh globbing idioms ~`{ and then we proceed doing the normal 73c80476e4SDavid E. O'Brien * globbing if needed ?*[ 74c80476e4SDavid E. O'Brien * 75c80476e4SDavid E. O'Brien * Csh type globbing is handled in globexpand() and the rest is 76c80476e4SDavid E. O'Brien * handled in glob() which is part of the 4.4BSD libc. 77c80476e4SDavid E. O'Brien * 78c80476e4SDavid E. O'Brien */ 79c80476e4SDavid E. O'Brien static Char *globtilde __P((Char **, Char *)); 80c80476e4SDavid E. O'Brien static Char *handleone __P((Char *, Char **, int)); 81c80476e4SDavid E. O'Brien static Char **libglob __P((Char **)); 82c80476e4SDavid E. O'Brien static Char **globexpand __P((Char **)); 83c80476e4SDavid E. O'Brien static int globbrace __P((Char *, Char *, Char ***)); 84c80476e4SDavid E. O'Brien static void expbrace __P((Char ***, Char ***, int)); 85c80476e4SDavid E. O'Brien static int pmatch __P((Char *, Char *, Char **)); 86c80476e4SDavid E. O'Brien static void pword __P((int)); 87c80476e4SDavid E. O'Brien static void psave __P((int)); 88c80476e4SDavid E. O'Brien static void backeval __P((Char *, bool)); 89c80476e4SDavid E. O'Brien 90c80476e4SDavid E. O'Brien static Char * 91c80476e4SDavid E. O'Brien globtilde(nv, s) 92c80476e4SDavid E. O'Brien Char **nv, *s; 93c80476e4SDavid E. O'Brien { 94c80476e4SDavid E. O'Brien Char gbuf[BUFSIZE], *gstart, *b, *u, *e; 95c80476e4SDavid E. O'Brien #ifdef apollo 96c80476e4SDavid E. O'Brien int slash; 97c80476e4SDavid E. O'Brien #endif 98c80476e4SDavid E. O'Brien 99c80476e4SDavid E. O'Brien gstart = gbuf; 100c80476e4SDavid E. O'Brien *gstart++ = *s++; 101c80476e4SDavid E. O'Brien u = s; 102c80476e4SDavid E. O'Brien for (b = gstart, e = &gbuf[BUFSIZE - 1]; 103c80476e4SDavid E. O'Brien *s && *s != '/' && *s != ':' && b < e; 104c80476e4SDavid E. O'Brien *b++ = *s++) 105c80476e4SDavid E. O'Brien continue; 106c80476e4SDavid E. O'Brien *b = EOS; 107c80476e4SDavid E. O'Brien if (gethdir(gstart)) { 108c80476e4SDavid E. O'Brien if (adrof(STRnonomatch)) 109c80476e4SDavid E. O'Brien return (--u); 110c80476e4SDavid E. O'Brien blkfree(nv); 111c80476e4SDavid E. O'Brien if (*gstart) 112c80476e4SDavid E. O'Brien stderror(ERR_UNKUSER, short2str(gstart)); 113c80476e4SDavid E. O'Brien else 114c80476e4SDavid E. O'Brien stderror(ERR_NOHOME); 115c80476e4SDavid E. O'Brien } 116c80476e4SDavid E. O'Brien b = &gstart[Strlen(gstart)]; 117c80476e4SDavid E. O'Brien #ifdef apollo 118c80476e4SDavid E. O'Brien slash = gstart[0] == '/' && gstart[1] == '\0'; 119c80476e4SDavid E. O'Brien #endif 120c80476e4SDavid E. O'Brien while (*s) 121c80476e4SDavid E. O'Brien *b++ = *s++; 122c80476e4SDavid E. O'Brien *b = EOS; 123c80476e4SDavid E. O'Brien --u; 124c80476e4SDavid E. O'Brien xfree((ptr_t) u); 125c80476e4SDavid E. O'Brien #ifdef apollo 126c80476e4SDavid E. O'Brien if (slash && gstart[1] == '/') 127c80476e4SDavid E. O'Brien gstart++; 128c80476e4SDavid E. O'Brien #endif 129c80476e4SDavid E. O'Brien return (Strsave(gstart)); 130c80476e4SDavid E. O'Brien } 131c80476e4SDavid E. O'Brien 132c80476e4SDavid E. O'Brien Char * 133c80476e4SDavid E. O'Brien globequal(new, old) 134c80476e4SDavid E. O'Brien Char *new, *old; 135c80476e4SDavid E. O'Brien { 136c80476e4SDavid E. O'Brien int dig; 137c80476e4SDavid E. O'Brien Char *b, *d; 138c80476e4SDavid E. O'Brien 139c80476e4SDavid E. O'Brien /* 140c80476e4SDavid E. O'Brien * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names 141c80476e4SDavid E. O'Brien * in stack. PWP: let =foobar pass through (for X windows) 142c80476e4SDavid E. O'Brien */ 143c80476e4SDavid E. O'Brien if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) { 144c80476e4SDavid E. O'Brien /* =- */ 145c80476e4SDavid E. O'Brien dig = -1; 146c80476e4SDavid E. O'Brien b = &old[2]; 147c80476e4SDavid E. O'Brien } 148c80476e4SDavid E. O'Brien else if (Isdigit(old[1])) { 149c80476e4SDavid E. O'Brien /* =<number> */ 150c80476e4SDavid E. O'Brien dig = old[1] - '0'; 151c80476e4SDavid E. O'Brien for (b = &old[2]; Isdigit(*b); b++) 152c80476e4SDavid E. O'Brien dig = dig * 10 + (*b - '0'); 153c80476e4SDavid E. O'Brien if (*b != '\0' && *b != '/') 154c80476e4SDavid E. O'Brien /* =<number>foobar */ 155c80476e4SDavid E. O'Brien return old; 156c80476e4SDavid E. O'Brien } 157c80476e4SDavid E. O'Brien else 158c80476e4SDavid E. O'Brien /* =foobar */ 159c80476e4SDavid E. O'Brien return old; 160c80476e4SDavid E. O'Brien 161c80476e4SDavid E. O'Brien if (!getstakd(new, dig)) 162c80476e4SDavid E. O'Brien return NULL; 163c80476e4SDavid E. O'Brien 164c80476e4SDavid E. O'Brien /* Copy the rest of the string */ 165c80476e4SDavid E. O'Brien for (d = &new[Strlen(new)]; 166c80476e4SDavid E. O'Brien d < &new[BUFSIZE - 1] && (*d++ = *b++) != '\0';) 167c80476e4SDavid E. O'Brien continue; 168c80476e4SDavid E. O'Brien *d = '\0'; 169c80476e4SDavid E. O'Brien 170c80476e4SDavid E. O'Brien return new; 171c80476e4SDavid E. O'Brien } 172c80476e4SDavid E. O'Brien 173c80476e4SDavid E. O'Brien static int 174c80476e4SDavid E. O'Brien globbrace(s, p, bl) 175c80476e4SDavid E. O'Brien Char *s, *p, ***bl; 176c80476e4SDavid E. O'Brien { 177c80476e4SDavid E. O'Brien int i, len; 178c80476e4SDavid E. O'Brien Char *pm, *pe, *lm, *pl; 179c80476e4SDavid E. O'Brien Char **nv, **vl; 180c80476e4SDavid E. O'Brien Char gbuf[BUFSIZE]; 181c80476e4SDavid E. O'Brien int size = GLOBSPACE; 182c80476e4SDavid E. O'Brien 183c80476e4SDavid E. O'Brien nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); 184c80476e4SDavid E. O'Brien *vl = NULL; 185c80476e4SDavid E. O'Brien 186c80476e4SDavid E. O'Brien len = 0; 187c80476e4SDavid E. O'Brien /* copy part up to the brace */ 188c80476e4SDavid E. O'Brien for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) 189c80476e4SDavid E. O'Brien continue; 190c80476e4SDavid E. O'Brien 191c80476e4SDavid E. O'Brien /* check for balanced braces */ 192c80476e4SDavid E. O'Brien for (i = 0, pe = ++p; *pe; pe++) 1938e66bd9eSDavid E. O'Brien #ifdef DSPMBYTE 1948e66bd9eSDavid E. O'Brien if (Ismbyte1(*pe) && *(pe + 1) != EOS) 1958e66bd9eSDavid E. O'Brien pe ++; 1968e66bd9eSDavid E. O'Brien else 1978e66bd9eSDavid E. O'Brien #endif /* DSPMBYTE */ 198c80476e4SDavid E. O'Brien if (*pe == LBRK) { 199c80476e4SDavid E. O'Brien /* Ignore everything between [] */ 200c80476e4SDavid E. O'Brien for (++pe; *pe != RBRK && *pe != EOS; pe++) 2018e66bd9eSDavid E. O'Brien #ifdef DSPMBYTE 2028e66bd9eSDavid E. O'Brien if (Ismbyte1(*pe) && *(pe + 1) != EOS) 2038e66bd9eSDavid E. O'Brien pe ++; 2048e66bd9eSDavid E. O'Brien else 2058e66bd9eSDavid E. O'Brien #endif /* DSPMBYTE */ 206c80476e4SDavid E. O'Brien continue; 207c80476e4SDavid E. O'Brien if (*pe == EOS) { 208c80476e4SDavid E. O'Brien blkfree(nv); 209c80476e4SDavid E. O'Brien return (-RBRK); 210c80476e4SDavid E. O'Brien } 211c80476e4SDavid E. O'Brien } 212c80476e4SDavid E. O'Brien else if (*pe == LBRC) 213c80476e4SDavid E. O'Brien i++; 214c80476e4SDavid E. O'Brien else if (*pe == RBRC) { 215c80476e4SDavid E. O'Brien if (i == 0) 216c80476e4SDavid E. O'Brien break; 217c80476e4SDavid E. O'Brien i--; 218c80476e4SDavid E. O'Brien } 219c80476e4SDavid E. O'Brien 220c80476e4SDavid E. O'Brien if (i != 0 || *pe == '\0') { 221c80476e4SDavid E. O'Brien blkfree(nv); 222c80476e4SDavid E. O'Brien return (-RBRC); 223c80476e4SDavid E. O'Brien } 224c80476e4SDavid E. O'Brien 225c80476e4SDavid E. O'Brien for (i = 0, pl = pm = p; pm <= pe; pm++) 2268e66bd9eSDavid E. O'Brien #ifdef DSPMBYTE 2278e66bd9eSDavid E. O'Brien if (Ismbyte1(*pm) && pm + 1 <= pe) 2288e66bd9eSDavid E. O'Brien pm ++; 2298e66bd9eSDavid E. O'Brien else 2308e66bd9eSDavid E. O'Brien #endif /* DSPMBYTE */ 231c80476e4SDavid E. O'Brien switch (*pm) { 232c80476e4SDavid E. O'Brien case LBRK: 233c80476e4SDavid E. O'Brien for (++pm; *pm != RBRK && *pm != EOS; pm++) 2348e66bd9eSDavid E. O'Brien #ifdef DSPMBYTE 2358e66bd9eSDavid E. O'Brien if (Ismbyte1(*pm) && *(pm + 1) != EOS) 2368e66bd9eSDavid E. O'Brien pm ++; 2378e66bd9eSDavid E. O'Brien else 2388e66bd9eSDavid E. O'Brien #endif /* DSPMBYTE */ 239c80476e4SDavid E. O'Brien continue; 240c80476e4SDavid E. O'Brien if (*pm == EOS) { 241c80476e4SDavid E. O'Brien *vl = NULL; 242c80476e4SDavid E. O'Brien blkfree(nv); 243c80476e4SDavid E. O'Brien return (-RBRK); 244c80476e4SDavid E. O'Brien } 245c80476e4SDavid E. O'Brien break; 246c80476e4SDavid E. O'Brien case LBRC: 247c80476e4SDavid E. O'Brien i++; 248c80476e4SDavid E. O'Brien break; 249c80476e4SDavid E. O'Brien case RBRC: 250c80476e4SDavid E. O'Brien if (i) { 251c80476e4SDavid E. O'Brien i--; 252c80476e4SDavid E. O'Brien break; 253c80476e4SDavid E. O'Brien } 254c80476e4SDavid E. O'Brien /* FALLTHROUGH */ 255c80476e4SDavid E. O'Brien case ',': 256c80476e4SDavid E. O'Brien if (i && *pm == ',') 257c80476e4SDavid E. O'Brien break; 258c80476e4SDavid E. O'Brien else { 259c80476e4SDavid E. O'Brien Char savec = *pm; 260c80476e4SDavid E. O'Brien 261c80476e4SDavid E. O'Brien *pm = EOS; 262c80476e4SDavid E. O'Brien (void) Strcpy(lm, pl); 263c80476e4SDavid E. O'Brien (void) Strcat(gbuf, pe + 1); 264c80476e4SDavid E. O'Brien *pm = savec; 265c80476e4SDavid E. O'Brien *vl++ = Strsave(gbuf); 266c80476e4SDavid E. O'Brien len++; 267c80476e4SDavid E. O'Brien pl = pm + 1; 268c80476e4SDavid E. O'Brien if (vl == &nv[size]) { 269c80476e4SDavid E. O'Brien size += GLOBSPACE; 270c80476e4SDavid E. O'Brien nv = (Char **) xrealloc((ptr_t) nv, 271c80476e4SDavid E. O'Brien (size_t) (size * sizeof(Char *))); 272c80476e4SDavid E. O'Brien vl = &nv[size - GLOBSPACE]; 273c80476e4SDavid E. O'Brien } 274c80476e4SDavid E. O'Brien } 275c80476e4SDavid E. O'Brien break; 276c80476e4SDavid E. O'Brien default: 277c80476e4SDavid E. O'Brien break; 278c80476e4SDavid E. O'Brien } 279c80476e4SDavid E. O'Brien *vl = NULL; 280c80476e4SDavid E. O'Brien *bl = nv; 281c80476e4SDavid E. O'Brien return (len); 282c80476e4SDavid E. O'Brien } 283c80476e4SDavid E. O'Brien 284c80476e4SDavid E. O'Brien 285c80476e4SDavid E. O'Brien static void 286c80476e4SDavid E. O'Brien expbrace(nvp, elp, size) 287c80476e4SDavid E. O'Brien Char ***nvp, ***elp; 288c80476e4SDavid E. O'Brien int size; 289c80476e4SDavid E. O'Brien { 290c80476e4SDavid E. O'Brien Char **vl, **el, **nv, *s; 291c80476e4SDavid E. O'Brien 292c80476e4SDavid E. O'Brien vl = nv = *nvp; 293c80476e4SDavid E. O'Brien if (elp != NULL) 294c80476e4SDavid E. O'Brien el = *elp; 295c80476e4SDavid E. O'Brien else 296c80476e4SDavid E. O'Brien for (el = vl; *el; el++) 297c80476e4SDavid E. O'Brien continue; 298c80476e4SDavid E. O'Brien 299c80476e4SDavid E. O'Brien for (s = *vl; s; s = *++vl) { 300c80476e4SDavid E. O'Brien Char *b; 301c80476e4SDavid E. O'Brien Char **vp, **bp; 302c80476e4SDavid E. O'Brien 303c80476e4SDavid E. O'Brien /* leave {} untouched for find */ 304c80476e4SDavid E. O'Brien if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0'))) 305c80476e4SDavid E. O'Brien continue; 306c80476e4SDavid E. O'Brien if ((b = Strchr(s, '{')) != NULL) { 307c80476e4SDavid E. O'Brien Char **bl; 308c80476e4SDavid E. O'Brien int len; 309c80476e4SDavid E. O'Brien 3108e66bd9eSDavid E. O'Brien #if defined (DSPMBYTE) 3118e66bd9eSDavid E. O'Brien if (b != s && Ismbyte2(*b) && Ismbyte1(*(b-1))) { 3128e66bd9eSDavid E. O'Brien /* The "{" is the 2nd byte of a MB character */ 3138e66bd9eSDavid E. O'Brien continue; 3148e66bd9eSDavid E. O'Brien } 3158e66bd9eSDavid E. O'Brien #endif /* DSPMBYTE */ 316c80476e4SDavid E. O'Brien if ((len = globbrace(s, b, &bl)) < 0) { 317c80476e4SDavid E. O'Brien xfree((ptr_t) nv); 318c80476e4SDavid E. O'Brien stderror(ERR_MISSING, -len); 319c80476e4SDavid E. O'Brien } 320c80476e4SDavid E. O'Brien xfree((ptr_t) s); 321c80476e4SDavid E. O'Brien if (len == 1) { 322c80476e4SDavid E. O'Brien *vl-- = *bl; 323c80476e4SDavid E. O'Brien xfree((ptr_t) bl); 324c80476e4SDavid E. O'Brien continue; 325c80476e4SDavid E. O'Brien } 326c80476e4SDavid E. O'Brien if (&el[len] >= &nv[size]) { 327c80476e4SDavid E. O'Brien int l, e; 328c80476e4SDavid E. O'Brien l = (int) (&el[len] - &nv[size]); 329c80476e4SDavid E. O'Brien size += GLOBSPACE > l ? GLOBSPACE : l; 330c80476e4SDavid E. O'Brien l = (int) (vl - nv); 331c80476e4SDavid E. O'Brien e = (int) (el - nv); 332c80476e4SDavid E. O'Brien nv = (Char **) xrealloc((ptr_t) nv, 333c80476e4SDavid E. O'Brien (size_t) (size * sizeof(Char *))); 334c80476e4SDavid E. O'Brien vl = nv + l; 335c80476e4SDavid E. O'Brien el = nv + e; 336c80476e4SDavid E. O'Brien } 337c80476e4SDavid E. O'Brien /* nv vl el bl 338c80476e4SDavid E. O'Brien * | | | | 339c80476e4SDavid E. O'Brien * -.--..-- x-- 340c80476e4SDavid E. O'Brien * | len 341c80476e4SDavid E. O'Brien * vp 342c80476e4SDavid E. O'Brien */ 343c80476e4SDavid E. O'Brien vp = vl--; 344c80476e4SDavid E. O'Brien *vp = *bl; 345c80476e4SDavid E. O'Brien len--; 346c80476e4SDavid E. O'Brien for (bp = el; bp != vp; bp--) 347c80476e4SDavid E. O'Brien bp[len] = *bp; 348c80476e4SDavid E. O'Brien el += len; 349c80476e4SDavid E. O'Brien /* nv vl el bl 350c80476e4SDavid E. O'Brien * | | | | 351c80476e4SDavid E. O'Brien * -.-x --- -- 352c80476e4SDavid E. O'Brien * |len 353c80476e4SDavid E. O'Brien * vp 354c80476e4SDavid E. O'Brien */ 355c80476e4SDavid E. O'Brien vp++; 356c80476e4SDavid E. O'Brien for (bp = bl + 1; *bp; *vp++ = *bp++) 357c80476e4SDavid E. O'Brien continue; 358c80476e4SDavid E. O'Brien xfree((ptr_t) bl); 359c80476e4SDavid E. O'Brien } 360c80476e4SDavid E. O'Brien 361c80476e4SDavid E. O'Brien } 362c80476e4SDavid E. O'Brien if (elp != NULL) 363c80476e4SDavid E. O'Brien *elp = el; 364c80476e4SDavid E. O'Brien *nvp = nv; 365c80476e4SDavid E. O'Brien } 366c80476e4SDavid E. O'Brien 367c80476e4SDavid E. O'Brien static Char ** 368c80476e4SDavid E. O'Brien globexpand(v) 369c80476e4SDavid E. O'Brien Char **v; 370c80476e4SDavid E. O'Brien { 371c80476e4SDavid E. O'Brien Char *s; 372c80476e4SDavid E. O'Brien Char **nv, **vl, **el; 373c80476e4SDavid E. O'Brien int size = GLOBSPACE; 374c80476e4SDavid E. O'Brien 375c80476e4SDavid E. O'Brien 376c80476e4SDavid E. O'Brien nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); 377c80476e4SDavid E. O'Brien *vl = NULL; 378c80476e4SDavid E. O'Brien 379c80476e4SDavid E. O'Brien /* 380c80476e4SDavid E. O'Brien * Step 1: expand backquotes. 381c80476e4SDavid E. O'Brien */ 382c80476e4SDavid E. O'Brien while ((s = *v++) != '\0') { 383c80476e4SDavid E. O'Brien if (Strchr(s, '`')) { 384c80476e4SDavid E. O'Brien int i; 385c80476e4SDavid E. O'Brien 386c80476e4SDavid E. O'Brien (void) dobackp(s, 0); 387c80476e4SDavid E. O'Brien for (i = 0; i < pargc; i++) { 388c80476e4SDavid E. O'Brien *vl++ = pargv[i]; 389c80476e4SDavid E. O'Brien if (vl == &nv[size]) { 390c80476e4SDavid E. O'Brien size += GLOBSPACE; 391c80476e4SDavid E. O'Brien nv = (Char **) xrealloc((ptr_t) nv, 392c80476e4SDavid E. O'Brien (size_t) (size * sizeof(Char *))); 393c80476e4SDavid E. O'Brien vl = &nv[size - GLOBSPACE]; 394c80476e4SDavid E. O'Brien } 395c80476e4SDavid E. O'Brien } 396c80476e4SDavid E. O'Brien xfree((ptr_t) pargv); 397c80476e4SDavid E. O'Brien pargv = NULL; 398c80476e4SDavid E. O'Brien } 399c80476e4SDavid E. O'Brien else { 400c80476e4SDavid E. O'Brien *vl++ = Strsave(s); 401c80476e4SDavid E. O'Brien if (vl == &nv[size]) { 402c80476e4SDavid E. O'Brien size += GLOBSPACE; 403c80476e4SDavid E. O'Brien nv = (Char **) xrealloc((ptr_t) nv, 404c80476e4SDavid E. O'Brien (size_t) (size * sizeof(Char *))); 405c80476e4SDavid E. O'Brien vl = &nv[size - GLOBSPACE]; 406c80476e4SDavid E. O'Brien } 407c80476e4SDavid E. O'Brien } 408c80476e4SDavid E. O'Brien } 409c80476e4SDavid E. O'Brien *vl = NULL; 410c80476e4SDavid E. O'Brien 411c80476e4SDavid E. O'Brien if (noglob) 412c80476e4SDavid E. O'Brien return (nv); 413c80476e4SDavid E. O'Brien 414c80476e4SDavid E. O'Brien /* 415c80476e4SDavid E. O'Brien * Step 2: expand braces 416c80476e4SDavid E. O'Brien */ 417c80476e4SDavid E. O'Brien el = vl; 418c80476e4SDavid E. O'Brien expbrace(&nv, &el, size); 419c80476e4SDavid E. O'Brien 420c80476e4SDavid E. O'Brien 421c80476e4SDavid E. O'Brien /* 422c80476e4SDavid E. O'Brien * Step 3: expand ~ = 423c80476e4SDavid E. O'Brien */ 424c80476e4SDavid E. O'Brien vl = nv; 425c80476e4SDavid E. O'Brien for (s = *vl; s; s = *++vl) 426c80476e4SDavid E. O'Brien switch (*s) { 427c80476e4SDavid E. O'Brien Char gp[BUFSIZE], *ns; 428c80476e4SDavid E. O'Brien case '~': 429c80476e4SDavid E. O'Brien *vl = globtilde(nv, s); 430c80476e4SDavid E. O'Brien break; 431c80476e4SDavid E. O'Brien case '=': 432c80476e4SDavid E. O'Brien if ((ns = globequal(gp, s)) == NULL) { 433c80476e4SDavid E. O'Brien if (!adrof(STRnonomatch)) { 434c80476e4SDavid E. O'Brien /* Error */ 435c80476e4SDavid E. O'Brien blkfree(nv); 436c80476e4SDavid E. O'Brien stderror(ERR_DEEP); 437c80476e4SDavid E. O'Brien } 438c80476e4SDavid E. O'Brien } 439c80476e4SDavid E. O'Brien if (ns && ns != s) { 440c80476e4SDavid E. O'Brien /* Expansion succeeded */ 441c80476e4SDavid E. O'Brien xfree((ptr_t) s); 442c80476e4SDavid E. O'Brien *vl = Strsave(gp); 443c80476e4SDavid E. O'Brien } 444c80476e4SDavid E. O'Brien break; 445c80476e4SDavid E. O'Brien default: 446c80476e4SDavid E. O'Brien break; 447c80476e4SDavid E. O'Brien } 448c80476e4SDavid E. O'Brien vl = nv; 449c80476e4SDavid E. O'Brien 450c80476e4SDavid E. O'Brien /* 451c80476e4SDavid E. O'Brien * Step 4: expand .. if the variable symlinks==expand is set 452c80476e4SDavid E. O'Brien */ 453c80476e4SDavid E. O'Brien if ( symlinks == SYM_EXPAND ) 454c80476e4SDavid E. O'Brien for (s = *vl; s; s = *++vl) { 4553b6eaa7bSAndrey A. Chernov char *path = short2str(s); 4563b6eaa7bSAndrey A. Chernov if (strstr(path, "..") != NULL && access(path, F_OK) == 0) { 457c80476e4SDavid E. O'Brien *vl = dnormalize(s, 1); 458c80476e4SDavid E. O'Brien xfree((ptr_t) s); 459c80476e4SDavid E. O'Brien } 4603b6eaa7bSAndrey A. Chernov } 461c80476e4SDavid E. O'Brien vl = nv; 462c80476e4SDavid E. O'Brien 463c80476e4SDavid E. O'Brien return (vl); 464c80476e4SDavid E. O'Brien } 465c80476e4SDavid E. O'Brien 466c80476e4SDavid E. O'Brien static Char * 467c80476e4SDavid E. O'Brien handleone(str, vl, action) 468c80476e4SDavid E. O'Brien Char *str, **vl; 469c80476e4SDavid E. O'Brien int action; 470c80476e4SDavid E. O'Brien { 471c80476e4SDavid E. O'Brien 472c80476e4SDavid E. O'Brien Char **vlp = vl; 473c80476e4SDavid E. O'Brien int chars; 474c80476e4SDavid E. O'Brien Char **t, *p, *strp; 475c80476e4SDavid E. O'Brien 476c80476e4SDavid E. O'Brien switch (action) { 477c80476e4SDavid E. O'Brien case G_ERROR: 478c80476e4SDavid E. O'Brien setname(short2str(str)); 479c80476e4SDavid E. O'Brien blkfree(vl); 480c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_AMBIG); 481c80476e4SDavid E. O'Brien break; 482c80476e4SDavid E. O'Brien case G_APPEND: 483c80476e4SDavid E. O'Brien chars = 0; 484c80476e4SDavid E. O'Brien for (t = vlp; (p = *t++) != '\0'; chars++) 485c80476e4SDavid E. O'Brien while (*p++) 486c80476e4SDavid E. O'Brien chars++; 487c80476e4SDavid E. O'Brien str = (Char *)xmalloc((size_t)(chars * sizeof(Char))); 488c80476e4SDavid E. O'Brien for (t = vlp, strp = str; (p = *t++) != '\0'; chars++) { 489c80476e4SDavid E. O'Brien while (*p) 490c80476e4SDavid E. O'Brien *strp++ = *p++ & TRIM; 491c80476e4SDavid E. O'Brien *strp++ = ' '; 492c80476e4SDavid E. O'Brien } 493c80476e4SDavid E. O'Brien *--strp = '\0'; 494c80476e4SDavid E. O'Brien blkfree(vl); 495c80476e4SDavid E. O'Brien break; 496c80476e4SDavid E. O'Brien case G_IGNORE: 497c80476e4SDavid E. O'Brien str = Strsave(strip(*vlp)); 498c80476e4SDavid E. O'Brien blkfree(vl); 499c80476e4SDavid E. O'Brien break; 500c80476e4SDavid E. O'Brien default: 501c80476e4SDavid E. O'Brien break; 502c80476e4SDavid E. O'Brien } 503c80476e4SDavid E. O'Brien return (str); 504c80476e4SDavid E. O'Brien } 505c80476e4SDavid E. O'Brien 506c80476e4SDavid E. O'Brien static Char ** 507c80476e4SDavid E. O'Brien libglob(vl) 508c80476e4SDavid E. O'Brien Char **vl; 509c80476e4SDavid E. O'Brien { 510c80476e4SDavid E. O'Brien int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT; 511c80476e4SDavid E. O'Brien glob_t globv; 512c80476e4SDavid E. O'Brien char *ptr; 513c80476e4SDavid E. O'Brien int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; 514c80476e4SDavid E. O'Brien 515c80476e4SDavid E. O'Brien if (!vl || !vl[0]) 516c80476e4SDavid E. O'Brien return(vl); 517c80476e4SDavid E. O'Brien 518c80476e4SDavid E. O'Brien globv.gl_offs = 0; 519c80476e4SDavid E. O'Brien globv.gl_pathv = 0; 520c80476e4SDavid E. O'Brien globv.gl_pathc = 0; 521c80476e4SDavid E. O'Brien 522c80476e4SDavid E. O'Brien if (nonomatch) 523c80476e4SDavid E. O'Brien gflgs |= GLOB_NOCHECK; 524c80476e4SDavid E. O'Brien 525c80476e4SDavid E. O'Brien do { 526c80476e4SDavid E. O'Brien ptr = short2qstr(*vl); 527c80476e4SDavid E. O'Brien switch (glob(ptr, gflgs, 0, &globv)) { 528c80476e4SDavid E. O'Brien case GLOB_ABEND: 529c80476e4SDavid E. O'Brien globfree(&globv); 530c80476e4SDavid E. O'Brien setname(ptr); 531c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_GLOB); 532c80476e4SDavid E. O'Brien /* NOTREACHED */ 533c80476e4SDavid E. O'Brien case GLOB_NOSPACE: 534c80476e4SDavid E. O'Brien globfree(&globv); 535c80476e4SDavid E. O'Brien stderror(ERR_NOMEM); 536c80476e4SDavid E. O'Brien /* NOTREACHED */ 537c80476e4SDavid E. O'Brien default: 538c80476e4SDavid E. O'Brien break; 539c80476e4SDavid E. O'Brien } 540c80476e4SDavid E. O'Brien if (globv.gl_flags & GLOB_MAGCHAR) { 541c80476e4SDavid E. O'Brien match |= (globv.gl_matchc != 0); 542c80476e4SDavid E. O'Brien magic = 1; 543c80476e4SDavid E. O'Brien } 544c80476e4SDavid E. O'Brien gflgs |= GLOB_APPEND; 545c80476e4SDavid E. O'Brien } 546c80476e4SDavid E. O'Brien while (*++vl); 547c80476e4SDavid E. O'Brien vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? 548c80476e4SDavid E. O'Brien NULL : blk2short(globv.gl_pathv); 549c80476e4SDavid E. O'Brien globfree(&globv); 550c80476e4SDavid E. O'Brien return (vl); 551c80476e4SDavid E. O'Brien } 552c80476e4SDavid E. O'Brien 553c80476e4SDavid E. O'Brien Char * 554c80476e4SDavid E. O'Brien globone(str, action) 555c80476e4SDavid E. O'Brien Char *str; 556c80476e4SDavid E. O'Brien int action; 557c80476e4SDavid E. O'Brien { 558c80476e4SDavid E. O'Brien 559c80476e4SDavid E. O'Brien Char *v[2], **vl, **vo; 560c80476e4SDavid E. O'Brien int gflg; 561c80476e4SDavid E. O'Brien 562c80476e4SDavid E. O'Brien noglob = adrof(STRnoglob) != 0; 563c80476e4SDavid E. O'Brien gflag = 0; 564c80476e4SDavid E. O'Brien v[0] = str; 565c80476e4SDavid E. O'Brien v[1] = 0; 566c80476e4SDavid E. O'Brien tglob(v); 567c80476e4SDavid E. O'Brien gflg = gflag; 568c80476e4SDavid E. O'Brien if (gflg == G_NONE) 569c80476e4SDavid E. O'Brien return (strip(Strsave(str))); 570c80476e4SDavid E. O'Brien 571c80476e4SDavid E. O'Brien if (gflg & G_CSH) { 572c80476e4SDavid E. O'Brien /* 573c80476e4SDavid E. O'Brien * Expand back-quote, tilde and brace 574c80476e4SDavid E. O'Brien */ 575c80476e4SDavid E. O'Brien vo = globexpand(v); 576c80476e4SDavid E. O'Brien if (noglob || (gflg & G_GLOB) == 0) { 577c80476e4SDavid E. O'Brien if (vo[0] == NULL) { 578c80476e4SDavid E. O'Brien xfree((ptr_t) vo); 579c80476e4SDavid E. O'Brien return (Strsave(STRNULL)); 580c80476e4SDavid E. O'Brien } 581c80476e4SDavid E. O'Brien if (vo[1] != NULL) 582c80476e4SDavid E. O'Brien return (handleone(str, vo, action)); 583c80476e4SDavid E. O'Brien else { 584c80476e4SDavid E. O'Brien str = strip(vo[0]); 585c80476e4SDavid E. O'Brien xfree((ptr_t) vo); 586c80476e4SDavid E. O'Brien return (str); 587c80476e4SDavid E. O'Brien } 588c80476e4SDavid E. O'Brien } 589c80476e4SDavid E. O'Brien } 590c80476e4SDavid E. O'Brien else if (noglob || (gflg & G_GLOB) == 0) 591c80476e4SDavid E. O'Brien return (strip(Strsave(str))); 592c80476e4SDavid E. O'Brien else 593c80476e4SDavid E. O'Brien vo = v; 594c80476e4SDavid E. O'Brien 595c80476e4SDavid E. O'Brien vl = libglob(vo); 596c80476e4SDavid E. O'Brien if ((gflg & G_CSH) && vl != vo) 597c80476e4SDavid E. O'Brien blkfree(vo); 598c80476e4SDavid E. O'Brien if (vl == NULL) { 599c80476e4SDavid E. O'Brien setname(short2str(str)); 600c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_NOMATCH); 601c80476e4SDavid E. O'Brien } 602c80476e4SDavid E. O'Brien if (vl[0] == NULL) { 603c80476e4SDavid E. O'Brien xfree((ptr_t) vl); 604c80476e4SDavid E. O'Brien return (Strsave(STRNULL)); 605c80476e4SDavid E. O'Brien } 606c80476e4SDavid E. O'Brien if (vl[1]) 607c80476e4SDavid E. O'Brien return (handleone(str, vl, action)); 608c80476e4SDavid E. O'Brien else { 609c80476e4SDavid E. O'Brien str = strip(*vl); 610c80476e4SDavid E. O'Brien xfree((ptr_t) vl); 611c80476e4SDavid E. O'Brien return (str); 612c80476e4SDavid E. O'Brien } 613c80476e4SDavid E. O'Brien } 614c80476e4SDavid E. O'Brien 615c80476e4SDavid E. O'Brien Char ** 616c80476e4SDavid E. O'Brien globall(v) 617c80476e4SDavid E. O'Brien Char **v; 618c80476e4SDavid E. O'Brien { 619c80476e4SDavid E. O'Brien Char **vl, **vo; 620c80476e4SDavid E. O'Brien int gflg = gflag; 621c80476e4SDavid E. O'Brien 622c80476e4SDavid E. O'Brien if (!v || !v[0]) { 623c80476e4SDavid E. O'Brien gargv = saveblk(v); 624c80476e4SDavid E. O'Brien gargc = blklen(gargv); 625c80476e4SDavid E. O'Brien return (gargv); 626c80476e4SDavid E. O'Brien } 627c80476e4SDavid E. O'Brien 628c80476e4SDavid E. O'Brien noglob = adrof(STRnoglob) != 0; 629c80476e4SDavid E. O'Brien 630c80476e4SDavid E. O'Brien if (gflg & G_CSH) 631c80476e4SDavid E. O'Brien /* 632c80476e4SDavid E. O'Brien * Expand back-quote, tilde and brace 633c80476e4SDavid E. O'Brien */ 634c80476e4SDavid E. O'Brien vl = vo = globexpand(v); 635c80476e4SDavid E. O'Brien else 636c80476e4SDavid E. O'Brien vl = vo = saveblk(v); 637c80476e4SDavid E. O'Brien 638c80476e4SDavid E. O'Brien if (!noglob && (gflg & G_GLOB)) { 639c80476e4SDavid E. O'Brien vl = libglob(vo); 640c80476e4SDavid E. O'Brien if (vl != vo) 641c80476e4SDavid E. O'Brien blkfree(vo); 642c80476e4SDavid E. O'Brien } 643c80476e4SDavid E. O'Brien else 644c80476e4SDavid E. O'Brien trim(vl); 645c80476e4SDavid E. O'Brien 646c80476e4SDavid E. O'Brien gargc = vl ? blklen(vl) : 0; 647c80476e4SDavid E. O'Brien return (gargv = vl); 648c80476e4SDavid E. O'Brien } 649c80476e4SDavid E. O'Brien 650c80476e4SDavid E. O'Brien void 651c80476e4SDavid E. O'Brien ginit() 652c80476e4SDavid E. O'Brien { 653c80476e4SDavid E. O'Brien gargsiz = GLOBSPACE; 654c80476e4SDavid E. O'Brien gargv = (Char **) xmalloc((size_t) (sizeof(Char *) * gargsiz)); 655c80476e4SDavid E. O'Brien gargv[0] = 0; 656c80476e4SDavid E. O'Brien gargc = 0; 657c80476e4SDavid E. O'Brien } 658c80476e4SDavid E. O'Brien 659c80476e4SDavid E. O'Brien void 660c80476e4SDavid E. O'Brien rscan(t, f) 661c80476e4SDavid E. O'Brien register Char **t; 662c80476e4SDavid E. O'Brien void (*f) __P((int)); 663c80476e4SDavid E. O'Brien { 664c80476e4SDavid E. O'Brien register Char *p; 665c80476e4SDavid E. O'Brien 666c80476e4SDavid E. O'Brien while ((p = *t++) != '\0') 667c80476e4SDavid E. O'Brien while (*p) 668c80476e4SDavid E. O'Brien (*f) (*p++); 669c80476e4SDavid E. O'Brien } 670c80476e4SDavid E. O'Brien 671c80476e4SDavid E. O'Brien void 672c80476e4SDavid E. O'Brien trim(t) 673c80476e4SDavid E. O'Brien register Char **t; 674c80476e4SDavid E. O'Brien { 675c80476e4SDavid E. O'Brien register Char *p; 676c80476e4SDavid E. O'Brien 677c80476e4SDavid E. O'Brien while ((p = *t++) != '\0') 678c80476e4SDavid E. O'Brien while (*p) 679c80476e4SDavid E. O'Brien *p++ &= TRIM; 680c80476e4SDavid E. O'Brien } 681c80476e4SDavid E. O'Brien 682c80476e4SDavid E. O'Brien void 683c80476e4SDavid E. O'Brien tglob(t) 684c80476e4SDavid E. O'Brien register Char **t; 685c80476e4SDavid E. O'Brien { 686c80476e4SDavid E. O'Brien register Char *p, *c; 687c80476e4SDavid E. O'Brien 688c80476e4SDavid E. O'Brien while ((p = *t++) != '\0') { 689c80476e4SDavid E. O'Brien if (*p == '~' || *p == '=') 690c80476e4SDavid E. O'Brien gflag |= G_CSH; 691c80476e4SDavid E. O'Brien else if (*p == '{' && 692c80476e4SDavid E. O'Brien (p[1] == '\0' || (p[1] == '}' && p[2] == '\0'))) 693c80476e4SDavid E. O'Brien continue; 694c80476e4SDavid E. O'Brien /* 695c80476e4SDavid E. O'Brien * The following line used to be *(c = p++), but hp broke their 696c80476e4SDavid E. O'Brien * optimizer in 9.01, so we break the assignment into two pieces 697c80476e4SDavid E. O'Brien * The careful reader here will note that *most* compiler workarounds 698c80476e4SDavid E. O'Brien * in tcsh are either for apollo/DomainOS or hpux. Is it a coincidence? 699c80476e4SDavid E. O'Brien */ 700c80476e4SDavid E. O'Brien while ( *(c = p) != '\0') { 701c80476e4SDavid E. O'Brien p++; 702c80476e4SDavid E. O'Brien if (*c == '`') { 703c80476e4SDavid E. O'Brien gflag |= G_CSH; 704c80476e4SDavid E. O'Brien #ifdef notdef 705c80476e4SDavid E. O'Brien /* 706c80476e4SDavid E. O'Brien * We do want to expand echo `echo '*'`, so we don't\ 707c80476e4SDavid E. O'Brien * use this piece of code anymore. 708c80476e4SDavid E. O'Brien */ 709c80476e4SDavid E. O'Brien while (*p && *p != '`') 710c80476e4SDavid E. O'Brien if (*p++ == '\\') { 711c80476e4SDavid E. O'Brien if (*p) /* Quoted chars */ 712c80476e4SDavid E. O'Brien p++; 713c80476e4SDavid E. O'Brien else 714c80476e4SDavid E. O'Brien break; 715c80476e4SDavid E. O'Brien } 716c80476e4SDavid E. O'Brien if (*p) /* The matching ` */ 717c80476e4SDavid E. O'Brien p++; 718c80476e4SDavid E. O'Brien else 719c80476e4SDavid E. O'Brien break; 720c80476e4SDavid E. O'Brien #endif 721c80476e4SDavid E. O'Brien } 722c80476e4SDavid E. O'Brien else if (*c == '{') 723c80476e4SDavid E. O'Brien gflag |= G_CSH; 724c80476e4SDavid E. O'Brien else if (isglob(*c)) 725c80476e4SDavid E. O'Brien gflag |= G_GLOB; 726c80476e4SDavid E. O'Brien else if (symlinks == SYM_EXPAND && 727c80476e4SDavid E. O'Brien *p && ISDOTDOT(c) && (c == *(t-1) || *(c-1) == '/') ) 728c80476e4SDavid E. O'Brien gflag |= G_CSH; 729c80476e4SDavid E. O'Brien } 730c80476e4SDavid E. O'Brien } 731c80476e4SDavid E. O'Brien } 732c80476e4SDavid E. O'Brien 733c80476e4SDavid E. O'Brien /* 734c80476e4SDavid E. O'Brien * Command substitute cp. If literal, then this is a substitution from a 735c80476e4SDavid E. O'Brien * << redirection, and so we should not crunch blanks and tabs, separating 736c80476e4SDavid E. O'Brien * words only at newlines. 737c80476e4SDavid E. O'Brien */ 738c80476e4SDavid E. O'Brien Char ** 739c80476e4SDavid E. O'Brien dobackp(cp, literal) 740c80476e4SDavid E. O'Brien Char *cp; 741c80476e4SDavid E. O'Brien bool literal; 742c80476e4SDavid E. O'Brien { 743c80476e4SDavid E. O'Brien register Char *lp, *rp; 744c80476e4SDavid E. O'Brien Char *ep, word[LONGBSIZE]; 745c80476e4SDavid E. O'Brien 746c80476e4SDavid E. O'Brien if (pargv) { 747c80476e4SDavid E. O'Brien #ifdef notdef 748c80476e4SDavid E. O'Brien abort(); 749c80476e4SDavid E. O'Brien #endif 750c80476e4SDavid E. O'Brien blkfree(pargv); 751c80476e4SDavid E. O'Brien } 752c80476e4SDavid E. O'Brien pargsiz = GLOBSPACE; 753c80476e4SDavid E. O'Brien pargv = (Char **) xmalloc((size_t) (sizeof(Char *) * pargsiz)); 754c80476e4SDavid E. O'Brien pargv[0] = NULL; 755c80476e4SDavid E. O'Brien pargcp = pargs = word; 756c80476e4SDavid E. O'Brien pargc = 0; 757c80476e4SDavid E. O'Brien pnleft = LONGBSIZE - 4; 758c80476e4SDavid E. O'Brien for (;;) { 7598e66bd9eSDavid E. O'Brien #if defined(DSPMBYTE) 7608e66bd9eSDavid E. O'Brien for (lp = cp;; lp++) { 7618e66bd9eSDavid E. O'Brien if (*lp == '`' && 7628e66bd9eSDavid E. O'Brien (lp-1 < cp || !Ismbyte2(*lp) || !Ismbyte1(*(lp-1)))) { 7638e66bd9eSDavid E. O'Brien break; 7648e66bd9eSDavid E. O'Brien } 7658e66bd9eSDavid E. O'Brien #else /* DSPMBYTE */ 766c80476e4SDavid E. O'Brien for (lp = cp; *lp != '`'; lp++) { 7678e66bd9eSDavid E. O'Brien #endif /* DSPMBYTE */ 768c80476e4SDavid E. O'Brien if (*lp == 0) { 769c80476e4SDavid E. O'Brien if (pargcp != pargs) 770c80476e4SDavid E. O'Brien pword(LONGBSIZE); 771c80476e4SDavid E. O'Brien return (pargv); 772c80476e4SDavid E. O'Brien } 773c80476e4SDavid E. O'Brien psave(*lp); 774c80476e4SDavid E. O'Brien } 775c80476e4SDavid E. O'Brien lp++; 776c80476e4SDavid E. O'Brien for (rp = lp; *rp && *rp != '`'; rp++) 777c80476e4SDavid E. O'Brien if (*rp == '\\') { 778c80476e4SDavid E. O'Brien rp++; 779c80476e4SDavid E. O'Brien if (!*rp) 780c80476e4SDavid E. O'Brien goto oops; 781c80476e4SDavid E. O'Brien } 782c80476e4SDavid E. O'Brien if (!*rp) 783c80476e4SDavid E. O'Brien oops: stderror(ERR_UNMATCHED, '`'); 784c80476e4SDavid E. O'Brien ep = Strsave(lp); 785c80476e4SDavid E. O'Brien ep[rp - lp] = 0; 786c80476e4SDavid E. O'Brien backeval(ep, literal); 787c80476e4SDavid E. O'Brien cp = rp + 1; 788c80476e4SDavid E. O'Brien } 789c80476e4SDavid E. O'Brien } 790c80476e4SDavid E. O'Brien 791c80476e4SDavid E. O'Brien 792c80476e4SDavid E. O'Brien static void 793c80476e4SDavid E. O'Brien backeval(cp, literal) 794c80476e4SDavid E. O'Brien Char *cp; 795c80476e4SDavid E. O'Brien bool literal; 796c80476e4SDavid E. O'Brien { 797c80476e4SDavid E. O'Brien register int icnt, c; 798c80476e4SDavid E. O'Brien register Char *ip; 799c80476e4SDavid E. O'Brien struct command faket; 800c80476e4SDavid E. O'Brien bool hadnl; 801c80476e4SDavid E. O'Brien int pvec[2], quoted; 802c80476e4SDavid E. O'Brien Char *fakecom[2], ibuf[BUFSIZE]; 803c80476e4SDavid E. O'Brien char tibuf[BUFSIZE]; 804c80476e4SDavid E. O'Brien 805c80476e4SDavid E. O'Brien hadnl = 0; 806c80476e4SDavid E. O'Brien icnt = 0; 807c80476e4SDavid E. O'Brien quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 808c80476e4SDavid E. O'Brien faket.t_dtyp = NODE_COMMAND; 809c80476e4SDavid E. O'Brien faket.t_dflg = F_BACKQ; 810c80476e4SDavid E. O'Brien faket.t_dlef = 0; 811c80476e4SDavid E. O'Brien faket.t_drit = 0; 812c80476e4SDavid E. O'Brien faket.t_dspr = 0; 813c80476e4SDavid E. O'Brien faket.t_dcom = fakecom; 814c80476e4SDavid E. O'Brien fakecom[0] = STRfakecom1; 815c80476e4SDavid E. O'Brien fakecom[1] = 0; 816c80476e4SDavid E. O'Brien 817c80476e4SDavid E. O'Brien /* 818c80476e4SDavid E. O'Brien * We do the psave job to temporarily change the current job so that the 819c80476e4SDavid E. O'Brien * following fork is considered a separate job. This is so that when 820c80476e4SDavid E. O'Brien * backquotes are used in a builtin function that calls glob the "current 821c80476e4SDavid E. O'Brien * job" is not corrupted. We only need one level of pushed jobs as long as 822c80476e4SDavid E. O'Brien * we are sure to fork here. 823c80476e4SDavid E. O'Brien */ 824c80476e4SDavid E. O'Brien psavejob(); 825c80476e4SDavid E. O'Brien 826c80476e4SDavid E. O'Brien /* 827c80476e4SDavid E. O'Brien * It would be nicer if we could integrate this redirection more with the 828c80476e4SDavid E. O'Brien * routines in sh.sem.c by doing a fake execute on a builtin function that 829c80476e4SDavid E. O'Brien * was piped out. 830c80476e4SDavid E. O'Brien */ 831c80476e4SDavid E. O'Brien mypipe(pvec); 832c80476e4SDavid E. O'Brien if (pfork(&faket, -1) == 0) { 833c80476e4SDavid E. O'Brien struct command *t; 834c80476e4SDavid E. O'Brien 835c80476e4SDavid E. O'Brien (void) close(pvec[0]); 836c80476e4SDavid E. O'Brien (void) dmove(pvec[1], 1); 837c80476e4SDavid E. O'Brien (void) dmove(SHDIAG, 2); 838c80476e4SDavid E. O'Brien initdesc(); 839c80476e4SDavid E. O'Brien /* 840c80476e4SDavid E. O'Brien * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>, 841c80476e4SDavid E. O'Brien * posted to comp.bugs.4bsd 12 Sep. 1989. 842c80476e4SDavid E. O'Brien */ 843c80476e4SDavid E. O'Brien if (pargv) /* mg, 21.dec.88 */ 844c80476e4SDavid E. O'Brien blkfree(pargv), pargv = 0, pargsiz = 0; 845c80476e4SDavid E. O'Brien /* mg, 21.dec.88 */ 846c80476e4SDavid E. O'Brien arginp = cp; 847c80476e4SDavid E. O'Brien while (*cp) 848c80476e4SDavid E. O'Brien *cp++ &= TRIM; 849c80476e4SDavid E. O'Brien 850c80476e4SDavid E. O'Brien /* 851c80476e4SDavid E. O'Brien * In the child ``forget'' everything about current aliases or 852c80476e4SDavid E. O'Brien * eval vectors. 853c80476e4SDavid E. O'Brien */ 854c80476e4SDavid E. O'Brien alvec = NULL; 855c80476e4SDavid E. O'Brien evalvec = NULL; 856c80476e4SDavid E. O'Brien alvecp = NULL; 857c80476e4SDavid E. O'Brien evalp = NULL; 858c80476e4SDavid E. O'Brien (void) lex(¶ml); 859c80476e4SDavid E. O'Brien if (seterr) 860c80476e4SDavid E. O'Brien stderror(ERR_OLD); 861c80476e4SDavid E. O'Brien alias(¶ml); 862c80476e4SDavid E. O'Brien t = syntax(paraml.next, ¶ml, 0); 863c80476e4SDavid E. O'Brien if (seterr) 864c80476e4SDavid E. O'Brien stderror(ERR_OLD); 865c80476e4SDavid E. O'Brien if (t) 866c80476e4SDavid E. O'Brien t->t_dflg |= F_NOFORK; 867c80476e4SDavid E. O'Brien #ifdef SIGTSTP 868c80476e4SDavid E. O'Brien (void) sigignore(SIGTSTP); 869c80476e4SDavid E. O'Brien #endif 870c80476e4SDavid E. O'Brien #ifdef SIGTTIN 871c80476e4SDavid E. O'Brien (void) sigignore(SIGTTIN); 872c80476e4SDavid E. O'Brien #endif 873c80476e4SDavid E. O'Brien #ifdef SIGTTOU 874c80476e4SDavid E. O'Brien (void) sigignore(SIGTTOU); 875c80476e4SDavid E. O'Brien #endif 876c80476e4SDavid E. O'Brien execute(t, -1, NULL, NULL); 877c80476e4SDavid E. O'Brien exitstat(); 878c80476e4SDavid E. O'Brien } 879c80476e4SDavid E. O'Brien xfree((ptr_t) cp); 880c80476e4SDavid E. O'Brien (void) close(pvec[1]); 881c80476e4SDavid E. O'Brien c = 0; 882c80476e4SDavid E. O'Brien ip = NULL; 883c80476e4SDavid E. O'Brien do { 884c80476e4SDavid E. O'Brien int cnt = 0; 885c80476e4SDavid E. O'Brien 886c80476e4SDavid E. O'Brien for (;;) { 887c80476e4SDavid E. O'Brien if (icnt == 0) { 888c80476e4SDavid E. O'Brien int i; 889c80476e4SDavid E. O'Brien 890c80476e4SDavid E. O'Brien ip = ibuf; 891c80476e4SDavid E. O'Brien do 892c80476e4SDavid E. O'Brien icnt = read(pvec[0], tibuf, BUFSIZE); 893c80476e4SDavid E. O'Brien while (icnt == -1 && errno == EINTR); 894c80476e4SDavid E. O'Brien if (icnt <= 0) { 895c80476e4SDavid E. O'Brien c = -1; 896c80476e4SDavid E. O'Brien break; 897c80476e4SDavid E. O'Brien } 898c80476e4SDavid E. O'Brien for (i = 0; i < icnt; i++) 899c80476e4SDavid E. O'Brien ip[i] = (unsigned char) tibuf[i]; 900c80476e4SDavid E. O'Brien } 901c80476e4SDavid E. O'Brien if (hadnl) 902c80476e4SDavid E. O'Brien break; 903c80476e4SDavid E. O'Brien --icnt; 904c80476e4SDavid E. O'Brien c = (*ip++ & TRIM); 905c80476e4SDavid E. O'Brien if (c == 0) 906c80476e4SDavid E. O'Brien break; 9073b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 908c80476e4SDavid E. O'Brien if (c == '\r') 909c80476e4SDavid E. O'Brien c = ' '; 9103b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 911c80476e4SDavid E. O'Brien if (c == '\n') { 912c80476e4SDavid E. O'Brien /* 913c80476e4SDavid E. O'Brien * Continue around the loop one more time, so that we can eat 914c80476e4SDavid E. O'Brien * the last newline without terminating this word. 915c80476e4SDavid E. O'Brien */ 916c80476e4SDavid E. O'Brien hadnl = 1; 917c80476e4SDavid E. O'Brien continue; 918c80476e4SDavid E. O'Brien } 919c80476e4SDavid E. O'Brien if (!quoted && (c == ' ' || c == '\t')) 920c80476e4SDavid E. O'Brien break; 921c80476e4SDavid E. O'Brien cnt++; 922c80476e4SDavid E. O'Brien psave(c | quoted); 923c80476e4SDavid E. O'Brien } 924c80476e4SDavid E. O'Brien /* 925c80476e4SDavid E. O'Brien * Unless at end-of-file, we will form a new word here if there were 926c80476e4SDavid E. O'Brien * characters in the word, or in any case when we take text literally. 927c80476e4SDavid E. O'Brien * If we didn't make empty words here when literal was set then we 928c80476e4SDavid E. O'Brien * would lose blank lines. 929c80476e4SDavid E. O'Brien */ 930c80476e4SDavid E. O'Brien if (c != -1 && (cnt || literal)) 931c80476e4SDavid E. O'Brien pword(BUFSIZE); 932c80476e4SDavid E. O'Brien hadnl = 0; 933c80476e4SDavid E. O'Brien } while (c >= 0); 934c80476e4SDavid E. O'Brien (void) close(pvec[0]); 935c80476e4SDavid E. O'Brien pwait(); 936c80476e4SDavid E. O'Brien prestjob(); 937c80476e4SDavid E. O'Brien } 938c80476e4SDavid E. O'Brien 939c80476e4SDavid E. O'Brien static void 940c80476e4SDavid E. O'Brien psave(c) 941c80476e4SDavid E. O'Brien int c; 942c80476e4SDavid E. O'Brien { 943c80476e4SDavid E. O'Brien if (--pnleft <= 0) 944c80476e4SDavid E. O'Brien stderror(ERR_WTOOLONG); 945c80476e4SDavid E. O'Brien *pargcp++ = (Char) c; 946c80476e4SDavid E. O'Brien } 947c80476e4SDavid E. O'Brien 948c80476e4SDavid E. O'Brien static void 949c80476e4SDavid E. O'Brien pword(bufsiz) 950c80476e4SDavid E. O'Brien int bufsiz; 951c80476e4SDavid E. O'Brien { 952c80476e4SDavid E. O'Brien psave(0); 953c80476e4SDavid E. O'Brien if (pargc == pargsiz - 1) { 954c80476e4SDavid E. O'Brien pargsiz += GLOBSPACE; 955c80476e4SDavid E. O'Brien pargv = (Char **) xrealloc((ptr_t) pargv, 956c80476e4SDavid E. O'Brien (size_t) (pargsiz * sizeof(Char *))); 957c80476e4SDavid E. O'Brien } 958c80476e4SDavid E. O'Brien pargv[pargc++] = Strsave(pargs); 959c80476e4SDavid E. O'Brien pargv[pargc] = NULL; 960c80476e4SDavid E. O'Brien pargcp = pargs; 961c80476e4SDavid E. O'Brien pnleft = bufsiz - 4; 962c80476e4SDavid E. O'Brien } 963c80476e4SDavid E. O'Brien 964c80476e4SDavid E. O'Brien int 965c80476e4SDavid E. O'Brien Gmatch(string, pattern) 966c80476e4SDavid E. O'Brien Char *string, *pattern; 967c80476e4SDavid E. O'Brien { 968c80476e4SDavid E. O'Brien return Gnmatch(string, pattern, NULL); 969c80476e4SDavid E. O'Brien } 970c80476e4SDavid E. O'Brien 971c80476e4SDavid E. O'Brien int 972c80476e4SDavid E. O'Brien Gnmatch(string, pattern, endstr) 973c80476e4SDavid E. O'Brien Char *string, *pattern, **endstr; 974c80476e4SDavid E. O'Brien { 975c80476e4SDavid E. O'Brien Char **blk, **p, *tstring = string; 976c80476e4SDavid E. O'Brien int gpol = 1, gres = 0; 977c80476e4SDavid E. O'Brien 978c80476e4SDavid E. O'Brien if (*pattern == '^') { 979c80476e4SDavid E. O'Brien gpol = 0; 980c80476e4SDavid E. O'Brien pattern++; 981c80476e4SDavid E. O'Brien } 982c80476e4SDavid E. O'Brien 983c80476e4SDavid E. O'Brien blk = (Char **) xmalloc((size_t) (GLOBSPACE * sizeof(Char *))); 984c80476e4SDavid E. O'Brien blk[0] = Strsave(pattern); 985c80476e4SDavid E. O'Brien blk[1] = NULL; 986c80476e4SDavid E. O'Brien 987c80476e4SDavid E. O'Brien expbrace(&blk, NULL, GLOBSPACE); 988c80476e4SDavid E. O'Brien 989c80476e4SDavid E. O'Brien if (endstr == NULL) 990c80476e4SDavid E. O'Brien /* Exact matches only */ 991c80476e4SDavid E. O'Brien for (p = blk; *p; p++) 992c80476e4SDavid E. O'Brien gres |= pmatch(string, *p, &tstring) == 2 ? 1 : 0; 993c80476e4SDavid E. O'Brien else { 994c80476e4SDavid E. O'Brien /* partial matches */ 995c80476e4SDavid E. O'Brien int minc = 0x7fffffff; 996c80476e4SDavid E. O'Brien for (p = blk; *p; p++) 997c80476e4SDavid E. O'Brien if (pmatch(string, *p, &tstring) != 0) { 998c80476e4SDavid E. O'Brien int t = (int) (tstring - string); 999c80476e4SDavid E. O'Brien gres |= 1; 1000c80476e4SDavid E. O'Brien if (minc == -1 || minc > t) 1001c80476e4SDavid E. O'Brien minc = t; 1002c80476e4SDavid E. O'Brien } 1003c80476e4SDavid E. O'Brien *endstr = string + minc; 1004c80476e4SDavid E. O'Brien } 1005c80476e4SDavid E. O'Brien 1006c80476e4SDavid E. O'Brien blkfree(blk); 1007c80476e4SDavid E. O'Brien return(gres == gpol); 1008c80476e4SDavid E. O'Brien } 1009c80476e4SDavid E. O'Brien 1010c80476e4SDavid E. O'Brien /* pmatch(): 1011c80476e4SDavid E. O'Brien * Return 2 on exact match, 1012c80476e4SDavid E. O'Brien * Return 1 on substring match. 1013c80476e4SDavid E. O'Brien * Return 0 on no match. 1014c80476e4SDavid E. O'Brien * *estr will point to the end of the longest exact or substring match. 1015c80476e4SDavid E. O'Brien */ 1016c80476e4SDavid E. O'Brien static int 1017c80476e4SDavid E. O'Brien pmatch(string, pattern, estr) 1018c80476e4SDavid E. O'Brien register Char *string, *pattern, **estr; 1019c80476e4SDavid E. O'Brien { 1020c80476e4SDavid E. O'Brien register Char stringc, patternc; 1021c80476e4SDavid E. O'Brien int match, negate_range; 1022c80476e4SDavid E. O'Brien Char rangec, *oestr, *pestr; 1023c80476e4SDavid E. O'Brien 1024c80476e4SDavid E. O'Brien for (;; ++string) { 1025c80476e4SDavid E. O'Brien stringc = *string & TRIM; 1026c80476e4SDavid E. O'Brien /* 1027c80476e4SDavid E. O'Brien * apollo compiler bug: switch (patternc = *pattern++) dies 1028c80476e4SDavid E. O'Brien */ 1029c80476e4SDavid E. O'Brien patternc = *pattern++; 1030c80476e4SDavid E. O'Brien switch (patternc) { 1031c80476e4SDavid E. O'Brien case 0: 1032c80476e4SDavid E. O'Brien *estr = string; 1033c80476e4SDavid E. O'Brien return (stringc == 0 ? 2 : 1); 1034c80476e4SDavid E. O'Brien case '?': 1035c80476e4SDavid E. O'Brien if (stringc == 0) 1036c80476e4SDavid E. O'Brien return (0); 1037c80476e4SDavid E. O'Brien *estr = string; 1038c80476e4SDavid E. O'Brien break; 1039c80476e4SDavid E. O'Brien case '*': 1040c80476e4SDavid E. O'Brien if (!*pattern) { 1041c80476e4SDavid E. O'Brien while (*string) string++; 1042c80476e4SDavid E. O'Brien *estr = string; 1043c80476e4SDavid E. O'Brien return (2); 1044c80476e4SDavid E. O'Brien } 1045c80476e4SDavid E. O'Brien oestr = *estr; 1046c80476e4SDavid E. O'Brien pestr = NULL; 1047c80476e4SDavid E. O'Brien 1048c80476e4SDavid E. O'Brien do { 1049c80476e4SDavid E. O'Brien switch(pmatch(string, pattern, estr)) { 1050c80476e4SDavid E. O'Brien case 0: 1051c80476e4SDavid E. O'Brien break; 1052c80476e4SDavid E. O'Brien case 1: 1053c80476e4SDavid E. O'Brien pestr = *estr; 1054c80476e4SDavid E. O'Brien break; 1055c80476e4SDavid E. O'Brien case 2: 1056c80476e4SDavid E. O'Brien return 2; 1057c80476e4SDavid E. O'Brien default: 1058c80476e4SDavid E. O'Brien abort(); /* Cannot happen */ 1059c80476e4SDavid E. O'Brien } 1060c80476e4SDavid E. O'Brien *estr = string; 1061c80476e4SDavid E. O'Brien } 1062c80476e4SDavid E. O'Brien while (*string++); 1063c80476e4SDavid E. O'Brien 1064c80476e4SDavid E. O'Brien if (pestr) { 1065c80476e4SDavid E. O'Brien *estr = pestr; 1066c80476e4SDavid E. O'Brien return 1; 1067c80476e4SDavid E. O'Brien } 1068c80476e4SDavid E. O'Brien else { 1069c80476e4SDavid E. O'Brien *estr = oestr; 1070c80476e4SDavid E. O'Brien return 0; 1071c80476e4SDavid E. O'Brien } 1072c80476e4SDavid E. O'Brien 1073c80476e4SDavid E. O'Brien case '[': 1074c80476e4SDavid E. O'Brien match = 0; 1075c80476e4SDavid E. O'Brien if ((negate_range = (*pattern == '^')) != 0) 1076c80476e4SDavid E. O'Brien pattern++; 1077c80476e4SDavid E. O'Brien while ((rangec = *pattern++) != '\0') { 1078c80476e4SDavid E. O'Brien if (rangec == ']') 1079c80476e4SDavid E. O'Brien break; 1080c80476e4SDavid E. O'Brien if (match) 1081c80476e4SDavid E. O'Brien continue; 1082c80476e4SDavid E. O'Brien if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') { 1083c80476e4SDavid E. O'Brien match = (globcharcoll(stringc, *pattern & TRIM) <= 0 && 1084c80476e4SDavid E. O'Brien globcharcoll(*(pattern-2) & TRIM, stringc) <= 0); 1085c80476e4SDavid E. O'Brien pattern++; 1086c80476e4SDavid E. O'Brien } 1087c80476e4SDavid E. O'Brien else 1088c80476e4SDavid E. O'Brien match = (stringc == (rangec & TRIM)); 1089c80476e4SDavid E. O'Brien } 1090c80476e4SDavid E. O'Brien if (rangec == 0) 1091c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_MISSING, ']'); 1092c80476e4SDavid E. O'Brien if (match == negate_range) 1093c80476e4SDavid E. O'Brien return (0); 1094c80476e4SDavid E. O'Brien *estr = string; 1095c80476e4SDavid E. O'Brien break; 1096c80476e4SDavid E. O'Brien default: 1097c80476e4SDavid E. O'Brien if ((patternc & TRIM) != stringc) 1098c80476e4SDavid E. O'Brien return (0); 1099c80476e4SDavid E. O'Brien *estr = string; 1100c80476e4SDavid E. O'Brien break; 1101c80476e4SDavid E. O'Brien } 1102c80476e4SDavid E. O'Brien } 1103c80476e4SDavid E. O'Brien } 1104c80476e4SDavid E. O'Brien 1105c80476e4SDavid E. O'Brien void 1106c80476e4SDavid E. O'Brien Gcat(s1, s2) 1107c80476e4SDavid E. O'Brien Char *s1, *s2; 1108c80476e4SDavid E. O'Brien { 1109c80476e4SDavid E. O'Brien register Char *p, *q; 1110c80476e4SDavid E. O'Brien int n; 1111c80476e4SDavid E. O'Brien 1112c80476e4SDavid E. O'Brien for (p = s1; *p++;) 1113c80476e4SDavid E. O'Brien continue; 1114c80476e4SDavid E. O'Brien for (q = s2; *q++;) 1115c80476e4SDavid E. O'Brien continue; 1116c80476e4SDavid E. O'Brien n = (int) ((p - s1) + (q - s2) - 1); 1117c80476e4SDavid E. O'Brien if (++gargc >= gargsiz) { 1118c80476e4SDavid E. O'Brien gargsiz += GLOBSPACE; 1119c80476e4SDavid E. O'Brien gargv = (Char **) xrealloc((ptr_t) gargv, 1120c80476e4SDavid E. O'Brien (size_t) (gargsiz * sizeof(Char *))); 1121c80476e4SDavid E. O'Brien } 1122c80476e4SDavid E. O'Brien gargv[gargc] = 0; 1123c80476e4SDavid E. O'Brien p = gargv[gargc - 1] = (Char *) xmalloc((size_t) (n * sizeof(Char))); 1124c80476e4SDavid E. O'Brien for (q = s1; (*p++ = *q++) != '\0';) 1125c80476e4SDavid E. O'Brien continue; 1126c80476e4SDavid E. O'Brien for (p--, q = s2; (*p++ = *q++) != '\0';) 1127c80476e4SDavid E. O'Brien continue; 1128c80476e4SDavid E. O'Brien } 1129c80476e4SDavid E. O'Brien 1130c80476e4SDavid E. O'Brien #ifdef FILEC 1131c80476e4SDavid E. O'Brien int 1132c80476e4SDavid E. O'Brien sortscmp(a, b) 1133c80476e4SDavid E. O'Brien register Char **a, **b; 1134c80476e4SDavid E. O'Brien { 1135c80476e4SDavid E. O'Brien if (!a) /* check for NULL */ 1136c80476e4SDavid E. O'Brien return (b ? 1 : 0); 1137c80476e4SDavid E. O'Brien if (!b) 1138c80476e4SDavid E. O'Brien return (-1); 1139c80476e4SDavid E. O'Brien 1140c80476e4SDavid E. O'Brien if (!*a) /* check for NULL */ 1141c80476e4SDavid E. O'Brien return (*b ? 1 : 0); 1142c80476e4SDavid E. O'Brien if (!*b) 1143c80476e4SDavid E. O'Brien return (-1); 1144c80476e4SDavid E. O'Brien 1145c80476e4SDavid E. O'Brien return (int) collate(*a, *b); 1146c80476e4SDavid E. O'Brien } 1147c80476e4SDavid E. O'Brien 1148c80476e4SDavid E. O'Brien #endif 1149