Bugfix for echo * `echo`, fglag would get overwritten
[unix-history] / usr / src / bin / csh / glob.c
CommitLineData
ecc449eb
KB
1/*-
2 * Copyright (c) 1980, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
b79f4fa9
DF
6 */
7
35371dec 8#ifndef lint
4aad0a53 9static char sccsid[] = "@(#)glob.c 5.24 (Berkeley) %G%";
ecc449eb 10#endif /* not lint */
9363f20d 11
b9c4f741
KB
12#include <sys/param.h>
13#include <glob.h>
14#include <errno.h>
15#include <stdlib.h>
16#include <string.h>
17#include <unistd.h>
4df6491c
CZ
18#if __STDC__
19# include <stdarg.h>
20#else
21# include <varargs.h>
22#endif
23
4d7b2685
KB
24#include "csh.h"
25#include "extern.h"
b6e604fd 26
454c2aa3 27static int noglob;
c8fda9bd 28static int pargsiz, gargsiz;
6e37afca 29
b6e604fd 30/*
c8fda9bd 31 * Values for gflag
b6e604fd 32 */
6e37afca
KB
33#define G_NONE 0 /* No globbing needed */
34#define G_GLOB 1 /* string contains *?[] characters */
35#define G_CSH 2 /* string contains ~`{ characters */
36
37#define GLOBSPACE 100 /* Alloc increment */
b6e604fd 38
c8fda9bd
KB
39#define LBRC '{'
40#define RBRC '}'
41#define LBRK '['
42#define RBRK ']'
c8fda9bd 43#define EOS '\0'
6e37afca 44
0aec749d 45Char **gargv = NULL;
6e37afca 46long gargc = 0;
0aec749d 47Char **pargv = NULL;
6e37afca 48long pargc = 0;
b6e604fd 49
291a8333 50/*
c8fda9bd 51 * globbing is now done in two stages. In the first pass we expand
6e37afca 52 * csh globbing idioms ~`{ and then we proceed doing the normal
c8fda9bd
KB
53 * globbing if needed ?*[
54 *
55 * Csh type globbing is handled in globexpand() and the rest is
1fedb07b 56 * handled in glob() which is part of the 4.4BSD libc.
6e37afca 57 *
291a8333 58 */
0aec749d
CZ
59static Char *globtilde __P((Char **, Char *));
60static Char **libglob __P((Char **));
61static Char **globexpand __P((Char **));
62static int globbrace __P((Char *, Char *, Char ***));
63static void pword __P((void));
64static void psave __P((int));
65static void backeval __P((Char *, bool));
6a422336 66
b6e604fd 67
6e37afca 68static Char *
1fedb07b 69globtilde(nv, s)
6e37afca 70 Char **nv, *s;
b6e604fd 71{
6e37afca
KB
72 Char gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
73
74 gstart = gbuf;
75 *gstart++ = *s++;
76 u = s;
77 for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; *s && *s != '/' && b < e;
78 *b++ = *s++);
79 *b = EOS;
80 if (gethdir(gstart)) {
81 blkfree(nv);
82 if (*gstart)
83 stderror(ERR_UNKUSER, short2str(gstart));
84 else
85 stderror(ERR_NOHOME);
86 }
87 b = &gstart[Strlen(gstart)];
88 while (*s)
89 *b++ = *s++;
90 *b = EOS;
91 --u;
92 xfree((ptr_t) u);
93 return (Strsave(gstart));
b6e604fd
BJ
94}
95
c8fda9bd
KB
96static int
97globbrace(s, p, bl)
6e37afca 98 Char *s, *p, ***bl;
b6e604fd 99{
6e37afca
KB
100 int i, len;
101 Char *pm, *pe, *lm, *pl;
102 Char **nv, **vl;
103 Char gbuf[MAXPATHLEN];
104 int size = GLOBSPACE;
105
106 nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
0aec749d 107 *vl = NULL;
6e37afca
KB
108
109 len = 0;
110 /* copy part up to the brace */
111 for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
112 continue;
113
114 /* check for balanced braces */
115 for (i = 0, pe = ++p; *pe; pe++)
116 if (*pe == LBRK) {
117 /* Ignore everything between [] */
118 for (++pe; *pe != RBRK && *pe != EOS; pe++)
b6e604fd 119 continue;
6e37afca 120 if (*pe == EOS) {
c8fda9bd 121 blkfree(nv);
6e37afca
KB
122 return (-LBRK);
123 }
124 }
125 else if (*pe == LBRC)
126 i++;
127 else if (*pe == RBRC) {
128 if (i == 0)
129 break;
130 i--;
b6e604fd 131 }
b6e604fd 132
2f3717d9 133 if (i != 0 || *pe == '\0') {
6e37afca 134 blkfree(nv);
2f3717d9 135 return (-RBRC);
6e37afca
KB
136 }
137
138 for (i = 0, pl = pm = p; pm <= pe; pm++)
c8fda9bd
KB
139 switch (*pm) {
140 case LBRK:
6e37afca
KB
141 for (++pm; *pm != RBRK && *pm != EOS; pm++)
142 continue;
143 if (*pm == EOS) {
0aec749d 144 *vl = NULL;
6e37afca
KB
145 blkfree(nv);
146 return (-RBRK);
147 }
148 break;
c8fda9bd 149 case LBRC:
6e37afca
KB
150 i++;
151 break;
c8fda9bd 152 case RBRC:
6e37afca
KB
153 if (i) {
154 i--;
155 break;
156 }
157 /* FALLTHROUGH */
b6e604fd 158 case ',':
6e37afca 159 if (i && *pm == ',')
c8fda9bd 160 break;
6e37afca
KB
161 else {
162 Char savec = *pm;
163
164 *pm = EOS;
165 (void) Strcpy(lm, pl);
166 (void) Strcat(gbuf, pe + 1);
167 *pm = savec;
168 *vl++ = Strsave(gbuf);
169 len++;
170 pl = pm + 1;
171 if (vl == &nv[size]) {
172 size += GLOBSPACE;
173 nv = (Char **) xrealloc((ptr_t) nv, (size_t)
174 size * sizeof(Char *));
175 vl = &nv[size - GLOBSPACE];
176 }
177 }
178 break;
b6e604fd 179 }
0aec749d 180 *vl = NULL;
6e37afca
KB
181 *bl = nv;
182 return (len);
b6e604fd
BJ
183}
184
6e37afca 185static Char **
c8fda9bd 186globexpand(v)
6e37afca 187 Char **v;
b6e604fd 188{
6e37afca
KB
189 Char *s;
190 Char **nv, **vl, **el;
191 int size = GLOBSPACE;
192
193
194 nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
0aec749d 195 *vl = NULL;
6e37afca
KB
196
197 /*
198 * Step 1: expand backquotes.
199 */
200 while (s = *v++) {
201 if (Strchr(s, '`')) {
202 int i;
203
204 (void) dobackp(s, 0);
205 for (i = 0; i < pargc; i++) {
206 *vl++ = pargv[i];
207 if (vl == &nv[size]) {
208 size += GLOBSPACE;
209 nv = (Char **) xrealloc((ptr_t) nv,
210 (size_t) size * sizeof(Char *));
211 vl = &nv[size - GLOBSPACE];
212 }
213 }
214 xfree((ptr_t) pargv);
0aec749d 215 pargv = NULL;
6e37afca
KB
216 }
217 else {
218 *vl++ = Strsave(s);
219 if (vl == &nv[size]) {
220 size += GLOBSPACE;
221 nv = (Char **) xrealloc((ptr_t) nv, (size_t)
222 size * sizeof(Char *));
223 vl = &nv[size - GLOBSPACE];
224 }
225 }
226 }
0aec749d 227 *vl = NULL;
6e37afca
KB
228
229 if (noglob)
230 return (nv);
231
232 /*
233 * Step 2: expand braces
234 */
235 el = vl;
236 vl = nv;
237 for (s = *vl; s; s = *++vl) {
238 Char *b;
239 Char **vp, **bp;
240
454c2aa3 241 if ((b = Strchr(s, LBRC)) != NULL && b[1] != '\0') {
6e37afca
KB
242 Char **bl;
243 int len;
244
245 if ((len = globbrace(s, b, &bl)) < 0) {
246 blkfree(nv);
247 stderror(ERR_MISSING, -len);
248 }
249 xfree((ptr_t) s);
250 if (len == 1) {
251 *vl-- = *bl;
252 xfree((ptr_t) bl);
253 continue;
254 }
255 len = blklen(bl);
256 if (&el[len] >= &nv[size]) {
257 int l, e;
258
259 l = &el[len] - &nv[size];
260 size += GLOBSPACE > l ? GLOBSPACE : l;
261 l = vl - nv;
262 e = el - nv;
263 nv = (Char **) xrealloc((ptr_t) nv, (size_t)
264 size * sizeof(Char *));
265 vl = nv + l;
266 el = nv + e;
267 }
268 vp = vl--;
269 *vp = *bl;
270 len--;
271 for (bp = el; bp != vp; bp--)
272 bp[len] = *bp;
273 el += len;
274 vp++;
275 for (bp = bl + 1; *bp; *vp++ = *bp++)
276 continue;
277 xfree((ptr_t) bl);
278 }
b6e604fd 279
6e37afca
KB
280 }
281
282 /*
283 * Step 3: expand ~
284 */
285 vl = nv;
286 for (s = *vl; s; s = *++vl)
287 if (*s == '~')
288 *vl = globtilde(nv, s);
289 vl = nv;
290 return (vl);
291}
b6e604fd 292
6e37afca
KB
293static Char *
294handleone(str, vl, action)
295 Char *str, **vl;
296 int action;
297{
b6e604fd 298
6e37afca
KB
299 Char *cp, **vlp = vl;
300
301 switch (action) {
302 case G_ERROR:
303 setname(short2str(str));
304 blkfree(vl);
305 stderror(ERR_NAME | ERR_AMBIG);
306 break;
307 case G_APPEND:
308 trim(vlp);
309 str = Strsave(*vlp++);
310 do {
311 cp = Strspl(str, STRspace);
312 xfree((ptr_t) str);
313 str = Strspl(cp, *vlp);
314 xfree((ptr_t) cp);
c8fda9bd 315 }
6e37afca
KB
316 while (*++vlp);
317 blkfree(vl);
318 break;
319 case G_IGNORE:
320 str = Strsave(strip(*vlp));
321 blkfree(vl);
322 break;
323 }
324 return (str);
325}
b6e604fd 326
6e37afca
KB
327static Char **
328libglob(vl)
329 Char **vl;
330{
454c2aa3 331 int gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
6e37afca
KB
332 glob_t globv;
333 char *ptr;
454c2aa3 334 int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
6e37afca
KB
335
336 globv.gl_offs = 0;
337 globv.gl_pathv = 0;
338 globv.gl_pathc = 0;
454c2aa3
CZ
339
340 if (nonomatch)
341 gflgs |= GLOB_NOCHECK;
342
6e37afca
KB
343 do {
344 ptr = short2qstr(*vl);
345 switch (glob(ptr, gflgs, 0, &globv)) {
346 case GLOB_ABEND:
347 setname(ptr);
348 stderror(ERR_NAME | ERR_GLOB);
349 /* NOTREACHED */
350 case GLOB_NOSPACE:
351 stderror(ERR_NOMEM);
352 /* NOTREACHED */
353 default:
354 break;
b6e604fd 355 }
454c2aa3
CZ
356 if (globv.gl_flags & GLOB_MAGCHAR) {
357 match |= (globv.gl_matchc != 0);
358 magic = 1;
6e37afca
KB
359 }
360 gflgs |= GLOB_APPEND;
361 }
362 while (*++vl);
454c2aa3
CZ
363 vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
364 NULL : blk2short(globv.gl_pathv);
6e37afca
KB
365 globfree(&globv);
366 return (vl);
b6e604fd
BJ
367}
368
6e37afca
KB
369Char *
370globone(str, action)
371 Char *str;
372 int action;
b6e604fd 373{
6e37afca 374 Char *v[2], **vl, **vo;
4aad0a53 375 int gflg;
b6e604fd 376
6e37afca
KB
377 noglob = adrof(STRnoglob) != 0;
378 gflag = 0;
379 v[0] = str;
380 v[1] = 0;
381 tglob(v);
4aad0a53
CZ
382 gflg = gflag;
383 if (gflg == G_NONE)
6e37afca 384 return (strip(Strsave(str)));
b6e604fd 385
4aad0a53 386 if (gflg & G_CSH) {
6e37afca
KB
387 /*
388 * Expand back-quote, tilde and brace
389 */
390 vo = globexpand(v);
4aad0a53 391 if (noglob || (gflg & G_GLOB) == 0) {
6cc6e21d
CZ
392 if (vo[0] == NULL) {
393 xfree((ptr_t) vo);
394 return (Strsave(STRNULL));
395 }
0aec749d 396 if (vo[1] != NULL)
6e37afca
KB
397 return (handleone(str, vo, action));
398 else {
399 str = strip(vo[0]);
400 xfree((ptr_t) vo);
401 return (str);
402 }
c8fda9bd 403 }
6e37afca 404 }
4aad0a53 405 else if (noglob || (gflg & G_GLOB) == 0)
6e37afca
KB
406 return (strip(Strsave(str)));
407 else
408 vo = v;
409
410 vl = libglob(vo);
4aad0a53 411 if (gflg & G_CSH)
6e37afca 412 blkfree(vo);
0aec749d 413 if (vl == NULL) {
6e37afca
KB
414 setname(short2str(str));
415 stderror(ERR_NAME | ERR_NOMATCH);
416 }
6cc6e21d
CZ
417 if (vl[0] == NULL) {
418 xfree((ptr_t) vl);
419 return (Strsave(STRNULL));
420 }
421 if (vl[1] != NULL)
6e37afca
KB
422 return (handleone(str, vl, action));
423 else {
424 str = strip(*vl);
425 xfree((ptr_t) vl);
6cc6e21d 426 return (str);
6e37afca 427 }
b6e604fd
BJ
428}
429
6e37afca 430Char **
c8fda9bd 431globall(v)
6e37afca 432 Char **v;
b6e604fd 433{
6e37afca 434 Char **vl, **vo;
4aad0a53 435 int gflg = gflag;
35371dec 436
6e37afca
KB
437 if (!v || !v[0]) {
438 gargv = saveblk(v);
439 gargc = blklen(gargv);
440 return (gargv);
441 }
b6e604fd 442
6e37afca 443 noglob = adrof(STRnoglob) != 0;
b6e604fd 444
4aad0a53 445 if (gflg & G_CSH)
6e37afca
KB
446 /*
447 * Expand back-quote, tilde and brace
448 */
449 vl = vo = globexpand(v);
450 else
451 vl = vo = saveblk(v);
452
4aad0a53 453 if (!noglob && (gflg & G_GLOB)) {
6e37afca 454 vl = libglob(vo);
4aad0a53 455 if (gflg & G_CSH)
6e37afca
KB
456 blkfree(vo);
457 }
458
459 gargc = vl ? blklen(vl) : 0;
460 return (gargv = vl);
c8fda9bd 461}
6e37afca
KB
462
463void
c8fda9bd
KB
464ginit()
465{
6e37afca
KB
466 gargsiz = GLOBSPACE;
467 gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
468 gargv[0] = 0;
469 gargc = 0;
b6e604fd
BJ
470}
471
6e37afca 472void
b6e604fd 473rscan(t, f)
6e37afca
KB
474 register Char **t;
475 void (*f) ();
b6e604fd 476{
6e37afca 477 register Char *p;
b6e604fd 478
6e37afca
KB
479 while (p = *t++)
480 while (*p)
481 (*f) (*p++);
b6e604fd
BJ
482}
483
6e37afca 484void
35371dec 485trim(t)
6e37afca 486 register Char **t;
b6e604fd 487{
6e37afca 488 register Char *p;
b6e604fd 489
6e37afca
KB
490 while (p = *t++)
491 while (*p)
492 *p++ &= TRIM;
b6e604fd
BJ
493}
494
6e37afca 495void
35371dec 496tglob(t)
6e37afca 497 register Char **t;
b6e604fd 498{
6e37afca
KB
499 register Char *p, c;
500
501 while (p = *t++) {
502 if (*p == '~' || *p == '=')
503 gflag |= G_CSH;
504 else if (*p == '{' &&
505 (p[1] == '\0' || p[1] == '}' && p[2] == '\0'))
506 continue;
507 while (c = *p++)
508 if (isglob(c))
509 gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB;
510 }
b6e604fd
BJ
511}
512
b6e604fd 513/*
c8fda9bd
KB
514 * Command substitute cp. If literal, then this is a substitution from a
515 * << redirection, and so we should not crunch blanks and tabs, separating
516 * words only at newlines.
b6e604fd 517 */
6e37afca 518Char **
b6e604fd 519dobackp(cp, literal)
6e37afca
KB
520 Char *cp;
521 bool literal;
b6e604fd 522{
6e37afca
KB
523 register Char *lp, *rp;
524 Char *ep, word[MAXPATHLEN];
525
526 if (pargv) {
527 abort();
528 blkfree(pargv);
529 }
530 pargsiz = GLOBSPACE;
531 pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
532 pargv[0] = NULL;
533 pargcp = pargs = word;
534 pargc = 0;
535 pnleft = MAXPATHLEN - 4;
536 for (;;) {
537 for (lp = cp; *lp != '`'; lp++) {
538 if (*lp == 0) {
539 if (pargcp != pargs)
540 pword();
541 return (pargv);
542 }
543 psave(*lp);
b6e604fd 544 }
6e37afca
KB
545 lp++;
546 for (rp = lp; *rp && *rp != '`'; rp++)
547 if (*rp == '\\') {
548 rp++;
b6e604fd 549 if (!*rp)
6e37afca
KB
550 goto oops;
551 }
552 if (!*rp)
553 oops: stderror(ERR_UNMATCHED, '`');
554 ep = Strsave(lp);
555 ep[rp - lp] = 0;
556 backeval(ep, literal);
557 cp = rp + 1;
558 }
b6e604fd
BJ
559}
560
6e37afca 561static void
b6e604fd 562backeval(cp, literal)
6e37afca
KB
563 Char *cp;
564 bool literal;
b6e604fd 565{
6e37afca
KB
566 register int icnt, c;
567 register Char *ip;
568 struct command faket;
569 bool hadnl;
570 int pvec[2], quoted;
571 Char *fakecom[2], ibuf[BUFSIZ];
572 char tibuf[BUFSIZ];
573
574 hadnl = 0;
575 icnt = 0;
576 quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
577 faket.t_dtyp = NODE_COMMAND;
578 faket.t_dflg = 0;
579 faket.t_dlef = 0;
580 faket.t_drit = 0;
581 faket.t_dspr = 0;
582 faket.t_dcom = fakecom;
583 fakecom[0] = STRfakecom1;
584 fakecom[1] = 0;
585
586 /*
587 * We do the psave job to temporarily change the current job so that the
588 * following fork is considered a separate job. This is so that when
589 * backquotes are used in a builtin function that calls glob the "current
590 * job" is not corrupted. We only need one level of pushed jobs as long as
591 * we are sure to fork here.
592 */
593 psavejob();
594
595 /*
596 * It would be nicer if we could integrate this redirection more with the
597 * routines in sh.sem.c by doing a fake execute on a builtin function that
598 * was piped out.
599 */
600 mypipe(pvec);
601 if (pfork(&faket, -1) == 0) {
602 struct wordent paraml;
603 struct command *t;
c8fda9bd 604
6e37afca
KB
605 (void) close(pvec[0]);
606 (void) dmove(pvec[1], 1);
454c2aa3 607 (void) dmove(SHERR, 2);
6e37afca 608 initdesc();
b6e604fd 609 /*
6e37afca
KB
610 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
611 * posted to comp.bugs.4bsd 12 Sep. 1989.
b6e604fd 612 */
6e37afca
KB
613 if (pargv) /* mg, 21.dec.88 */
614 blkfree(pargv), pargv = 0, pargsiz = 0;
615 /* mg, 21.dec.88 */
616 arginp = cp;
617 while (*cp)
618 *cp++ &= TRIM;
619 (void) lex(&paraml);
620 if (seterr)
621 stderror(ERR_OLD);
622 alias(&paraml);
623 t = syntax(paraml.next, &paraml, 0);
624 if (seterr)
625 stderror(ERR_OLD);
626 if (t)
627 t->t_dflg |= F_NOFORK;
628 (void) signal(SIGTSTP, SIG_IGN);
629 (void) signal(SIGTTIN, SIG_IGN);
630 (void) signal(SIGTTOU, SIG_IGN);
4d7b2685 631 execute(t, -1, NULL, NULL);
6e37afca
KB
632 exitstat();
633 }
634 xfree((ptr_t) cp);
635 (void) close(pvec[1]);
636 c = 0;
0aec749d 637 ip = NULL;
6e37afca
KB
638 do {
639 int cnt = 0;
c8fda9bd 640
6e37afca
KB
641 for (;;) {
642 if (icnt == 0) {
643 int i;
644
645 ip = ibuf;
646 do
647 icnt = read(pvec[0], tibuf, BUFSIZ);
648 while (icnt == -1 && errno == EINTR);
649 if (icnt <= 0) {
650 c = -1;
651 break;
b6e604fd 652 }
6e37afca
KB
653 for (i = 0; i < icnt; i++)
654 ip[i] = (unsigned char) tibuf[i];
655 }
656 if (hadnl)
657 break;
658 --icnt;
659 c = (*ip++ & TRIM);
660 if (c == 0)
661 break;
662 if (c == '\n') {
b6e604fd 663 /*
6e37afca
KB
664 * Continue around the loop one more time, so that we can eat
665 * the last newline without terminating this word.
b6e604fd 666 */
6e37afca
KB
667 hadnl = 1;
668 continue;
669 }
670 if (!quoted && (c == ' ' || c == '\t'))
671 break;
672 cnt++;
673 psave(c | quoted);
674 }
675 /*
676 * Unless at end-of-file, we will form a new word here if there were
677 * characters in the word, or in any case when we take text literally.
678 * If we didn't make empty words here when literal was set then we
679 * would lose blank lines.
680 */
681 if (c != -1 && (cnt || literal))
682 pword();
683 hadnl = 0;
684 } while (c >= 0);
685 (void) close(pvec[0]);
686 pwait();
687 prestjob();
b6e604fd
BJ
688}
689
6e37afca 690static void
b6e604fd 691psave(c)
0aec749d 692 int c;
b6e604fd 693{
6e37afca
KB
694 if (--pnleft <= 0)
695 stderror(ERR_WTOOLONG);
696 *pargcp++ = c;
b6e604fd
BJ
697}
698
6e37afca 699static void
b6e604fd
BJ
700pword()
701{
6e37afca
KB
702 psave(0);
703 if (pargc == pargsiz - 1) {
704 pargsiz += GLOBSPACE;
705 pargv = (Char **) xrealloc((ptr_t) pargv,
706 (size_t) pargsiz * sizeof(Char *));
707 }
708 pargv[pargc++] = Strsave(pargs);
709 pargv[pargc] = NULL;
710 pargcp = pargs;
711 pnleft = MAXPATHLEN - 4;
c8fda9bd
KB
712}
713
6e37afca 714int
c8fda9bd 715Gmatch(string, pattern)
6e37afca 716 register Char *string, *pattern;
c8fda9bd 717{
6e37afca
KB
718 register Char stringc, patternc;
719 int match;
720 Char rangec;
721
722 for (;; ++string) {
723 stringc = *string & TRIM;
724 patternc = *pattern++;
725 switch (patternc) {
726 case 0:
727 return (stringc == 0);
728 case '?':
729 if (stringc == 0)
730 return (0);
731 break;
732 case '*':
733 if (!*pattern)
734 return (1);
735 while (*string)
736 if (Gmatch(string++, pattern))
737 return (1);
738 return (0);
739 case '[':
740 match = 0;
741 while (rangec = *pattern++) {
742 if (rangec == ']')
743 if (match)
c8fda9bd 744 break;
6e37afca 745 else
c8fda9bd 746 return (0);
6e37afca
KB
747 if (match)
748 continue;
2b00e1e7
CZ
749 if (rangec == '-' && *(pattern - 2) != '[' && *pattern != ']') {
750 match = (stringc <= (*pattern & TRIM) &&
751 (*(pattern - 2) & TRIM) <= stringc);
6e37afca 752 pattern++;
c8fda9bd 753 }
6e37afca
KB
754 else
755 match = (stringc == rangec);
756 }
757 if (rangec == 0)
758 stderror(ERR_NAME | ERR_MISSING, ']');
759 break;
760 default:
761 if ((patternc & TRIM) != stringc)
762 return (0);
763 break;
764
c8fda9bd 765 }
6e37afca 766 }
c8fda9bd
KB
767}
768
6e37afca 769void
c8fda9bd 770Gcat(s1, s2)
6e37afca 771 Char *s1, *s2;
c8fda9bd 772{
6e37afca
KB
773 register Char *p, *q;
774 int n;
775
776 for (p = s1; *p++;);
777 for (q = s2; *q++;);
778 n = (p - s1) + (q - s2) - 1;
779 if (++gargc >= gargsiz) {
780 gargsiz += GLOBSPACE;
781 gargv = (Char **) xrealloc((ptr_t) gargv,
782 (size_t) gargsiz * sizeof(Char *));
783 }
784 gargv[gargc] = 0;
785 p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
786 for (q = s1; *p++ = *q++;);
787 for (p--, q = s2; *p++ = *q++;);
c8fda9bd
KB
788}
789
6e37afca 790#ifdef FILEC
c8fda9bd 791int
6e37afca
KB
792sortscmp(a, b)
793 register Char **a, **b;
c8fda9bd 794{
6e37afca
KB
795#if defined(NLS) && !defined(NOSTRCOLL)
796 char buf[2048];
797
798#endif
799
800 if (!a) /* check for NULL */
801 return (b ? 1 : 0);
802 if (!b)
803 return (-1);
804
805 if (!*a) /* check for NULL */
806 return (*b ? 1 : 0);
807 if (!*b)
808 return (-1);
809
810#if defined(NLS) && !defined(NOSTRCOLL)
811 (void) strcpy(buf, short2str(*a));
812 return ((int) strcoll(buf, short2str(*b)));
813#else
814 return ((int) Strcmp(*a, *b));
815#endif
b6e604fd 816}
6e37afca 817#endif /* FILEC */