~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qtcsh/sh.glob.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

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