Commit | Line | Data |
---|---|---|
b79f4fa9 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
094e80ed | 3 | * All rights reserved. The Berkeley Software License Agreement |
b79f4fa9 DF |
4 | * specifies the terms and conditions for redistribution. |
5 | */ | |
6 | ||
35371dec | 7 | #ifndef lint |
b25aa57c | 8 | static char *sccsid = "@(#)glob.c 5.5 (Berkeley) %G%"; |
094e80ed | 9 | #endif |
9363f20d | 10 | |
b6e604fd | 11 | #include "sh.h" |
3ced312f | 12 | #include <sys/dir.h> |
b6e604fd BJ |
13 | |
14 | /* | |
15 | * C Shell | |
16 | */ | |
17 | ||
18 | int globcnt; | |
19 | ||
b6e604fd BJ |
20 | char *gpath, *gpathp, *lastgpathp; |
21 | int globbed; | |
22 | bool noglob; | |
23 | bool nonomatch; | |
24 | char *entp; | |
25 | char **sortbas; | |
291a8333 | 26 | int sortscmp(); |
6a422336 JL |
27 | |
28 | #define sort() qsort((char *)sortbas, &gargv[gargc] - sortbas, \ | |
291a8333 | 29 | sizeof(*sortbas), sortscmp), sortbas = &gargv[gargc] |
6a422336 | 30 | |
b6e604fd BJ |
31 | |
32 | char ** | |
33 | glob(v) | |
34 | register char **v; | |
35 | { | |
36 | char agpath[BUFSIZ]; | |
37 | char *agargv[GAVSIZ]; | |
38 | ||
39 | gpath = agpath; gpathp = gpath; *gpathp = 0; | |
40 | lastgpathp = &gpath[sizeof agpath - 2]; | |
41 | ginit(agargv); globcnt = 0; | |
42 | #ifdef GDEBUG | |
43 | printf("glob entered: "); blkpr(v); printf("\n"); | |
44 | #endif | |
45 | noglob = adrof("noglob") != 0; | |
46 | nonomatch = adrof("nonomatch") != 0; | |
47 | globcnt = noglob | nonomatch; | |
48 | while (*v) | |
49 | collect(*v++); | |
50 | #ifdef GDEBUG | |
51 | printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n"); | |
52 | #endif | |
53 | if (globcnt == 0 && (gflag&1)) { | |
54 | blkfree(gargv), gargv = 0; | |
55 | return (0); | |
56 | } else | |
57 | return (gargv = copyblk(gargv)); | |
58 | } | |
59 | ||
60 | ginit(agargv) | |
61 | char **agargv; | |
62 | { | |
63 | ||
64 | agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; | |
65 | gnleft = NCARGS - 4; | |
66 | } | |
67 | ||
68 | collect(as) | |
69 | register char *as; | |
70 | { | |
71 | register int i; | |
72 | ||
73 | if (any('`', as)) { | |
74 | #ifdef GDEBUG | |
75 | printf("doing backp of %s\n", as); | |
76 | #endif | |
35371dec | 77 | (void) dobackp(as, 0); |
b6e604fd BJ |
78 | #ifdef GDEBUG |
79 | printf("backp done, acollect'ing\n"); | |
80 | #endif | |
81 | for (i = 0; i < pargc; i++) | |
3ced312f | 82 | if (noglob) { |
b6e604fd | 83 | Gcat(pargv[i], ""); |
3ced312f SL |
84 | sortbas = &gargv[gargc]; |
85 | } else | |
b6e604fd BJ |
86 | acollect(pargv[i]); |
87 | if (pargv) | |
88 | blkfree(pargv), pargv = 0; | |
89 | #ifdef GDEBUG | |
90 | printf("acollect done\n"); | |
91 | #endif | |
401149be | 92 | } else if (noglob || eq(as, "{") || eq(as, "{}")) { |
b6e604fd | 93 | Gcat(as, ""); |
401149be BJ |
94 | sort(); |
95 | } else | |
b6e604fd BJ |
96 | acollect(as); |
97 | } | |
98 | ||
99 | acollect(as) | |
100 | register char *as; | |
101 | { | |
102 | register int ogargc = gargc; | |
103 | ||
104 | gpathp = gpath; *gpathp = 0; globbed = 0; | |
105 | expand(as); | |
106 | if (gargc == ogargc) { | |
107 | if (nonomatch) { | |
108 | Gcat(as, ""); | |
109 | sort(); | |
110 | } | |
111 | } else | |
112 | sort(); | |
113 | } | |
114 | ||
291a8333 JL |
115 | /* |
116 | * String compare for qsort. Also used by filec code in sh.file.c. | |
117 | */ | |
118 | sortscmp(a1, a2) | |
6a422336 | 119 | char **a1, **a2; |
b6e604fd | 120 | { |
6a422336 JL |
121 | |
122 | return (strcmp(*a1, *a2)); | |
b6e604fd BJ |
123 | } |
124 | ||
125 | expand(as) | |
126 | char *as; | |
127 | { | |
128 | register char *cs; | |
129 | register char *sgpathp, *oldcs; | |
130 | struct stat stb; | |
131 | ||
132 | sgpathp = gpathp; | |
133 | cs = as; | |
134 | if (*cs == '~' && gpathp == gpath) { | |
135 | addpath('~'); | |
136 | for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) | |
137 | addpath(*cs++); | |
138 | if (!*cs || *cs == '/') { | |
139 | if (gpathp != gpath + 1) { | |
140 | *gpathp = 0; | |
141 | if (gethdir(gpath + 1)) | |
142 | error("Unknown user: %s", gpath + 1); | |
35371dec | 143 | (void) strcpy(gpath, gpath + 1); |
b6e604fd | 144 | } else |
35371dec | 145 | (void) strcpy(gpath, value("home")); |
b6e604fd BJ |
146 | gpathp = strend(gpath); |
147 | } | |
148 | } | |
6a422336 | 149 | while (!isglob(*cs)) { |
b6e604fd BJ |
150 | if (*cs == 0) { |
151 | if (!globbed) | |
152 | Gcat(gpath, ""); | |
153 | else if (stat(gpath, &stb) >= 0) { | |
154 | Gcat(gpath, ""); | |
155 | globcnt++; | |
156 | } | |
157 | goto endit; | |
158 | } | |
159 | addpath(*cs++); | |
160 | } | |
161 | oldcs = cs; | |
162 | while (cs > as && *cs != '/') | |
163 | cs--, gpathp--; | |
164 | if (*cs == '/') | |
165 | cs++, gpathp++; | |
166 | *gpathp = 0; | |
167 | if (*oldcs == '{') { | |
35371dec | 168 | (void) execbrc(cs, NOSTR); |
b6e604fd BJ |
169 | return; |
170 | } | |
171 | matchdir(cs); | |
172 | endit: | |
173 | gpathp = sgpathp; | |
174 | *gpathp = 0; | |
175 | } | |
176 | ||
177 | matchdir(pattern) | |
178 | char *pattern; | |
179 | { | |
180 | struct stat stb; | |
9363f20d | 181 | register struct direct *dp; |
35371dec | 182 | register DIR *dirp; |
b6e604fd | 183 | |
9363f20d KM |
184 | dirp = opendir(gpath); |
185 | if (dirp == NULL) { | |
b6e604fd BJ |
186 | if (globbed) |
187 | return; | |
9363f20d | 188 | goto patherr2; |
b6e604fd | 189 | } |
9363f20d KM |
190 | if (fstat(dirp->dd_fd, &stb) < 0) |
191 | goto patherr1; | |
b6e604fd BJ |
192 | if (!isdir(stb)) { |
193 | errno = ENOTDIR; | |
9363f20d | 194 | goto patherr1; |
b6e604fd | 195 | } |
9363f20d KM |
196 | while ((dp = readdir(dirp)) != NULL) { |
197 | if (dp->d_ino == 0) | |
198 | continue; | |
199 | if (match(dp->d_name, pattern)) { | |
200 | Gcat(gpath, dp->d_name); | |
201 | globcnt++; | |
b6e604fd BJ |
202 | } |
203 | } | |
9363f20d | 204 | closedir(dirp); |
b6e604fd BJ |
205 | return; |
206 | ||
9363f20d KM |
207 | patherr1: |
208 | closedir(dirp); | |
209 | patherr2: | |
b6e604fd BJ |
210 | Perror(gpath); |
211 | } | |
212 | ||
b6e604fd BJ |
213 | execbrc(p, s) |
214 | char *p, *s; | |
215 | { | |
216 | char restbuf[BUFSIZ + 2]; | |
217 | register char *pe, *pm, *pl; | |
218 | int brclev = 0; | |
219 | char *lm, savec, *sgpathp; | |
220 | ||
221 | for (lm = restbuf; *p != '{'; *lm++ = *p++) | |
222 | continue; | |
223 | for (pe = ++p; *pe; pe++) | |
224 | switch (*pe) { | |
225 | ||
226 | case '{': | |
227 | brclev++; | |
228 | continue; | |
229 | ||
230 | case '}': | |
231 | if (brclev == 0) | |
232 | goto pend; | |
233 | brclev--; | |
234 | continue; | |
235 | ||
236 | case '[': | |
237 | for (pe++; *pe && *pe != ']'; pe++) | |
238 | continue; | |
239 | if (!*pe) | |
240 | error("Missing ]"); | |
241 | continue; | |
242 | } | |
243 | pend: | |
244 | if (brclev || !*pe) | |
245 | error("Missing }"); | |
246 | for (pl = pm = p; pm <= pe; pm++) | |
247 | switch (*pm & (QUOTE|TRIM)) { | |
248 | ||
249 | case '{': | |
250 | brclev++; | |
251 | continue; | |
252 | ||
253 | case '}': | |
254 | if (brclev) { | |
255 | brclev--; | |
256 | continue; | |
257 | } | |
258 | goto doit; | |
259 | ||
b6e604fd BJ |
260 | case ',': |
261 | if (brclev) | |
262 | continue; | |
263 | doit: | |
264 | savec = *pm; | |
265 | *pm = 0; | |
35371dec EW |
266 | (void) strcpy(lm, pl); |
267 | (void) strcat(restbuf, pe + 1); | |
b6e604fd BJ |
268 | *pm = savec; |
269 | if (s == 0) { | |
270 | sgpathp = gpathp; | |
271 | expand(restbuf); | |
272 | gpathp = sgpathp; | |
273 | *gpathp = 0; | |
274 | } else if (amatch(s, restbuf)) | |
275 | return (1); | |
276 | sort(); | |
277 | pl = pm + 1; | |
278 | continue; | |
279 | ||
280 | case '[': | |
281 | for (pm++; *pm && *pm != ']'; pm++) | |
282 | continue; | |
283 | if (!*pm) | |
284 | error("Missing ]"); | |
285 | continue; | |
286 | } | |
287 | return (0); | |
288 | } | |
289 | ||
290 | match(s, p) | |
291 | char *s, *p; | |
292 | { | |
293 | register int c; | |
294 | register char *sentp; | |
295 | char sglobbed = globbed; | |
296 | ||
297 | if (*s == '.' && *p != '.') | |
298 | return (0); | |
299 | sentp = entp; | |
300 | entp = s; | |
301 | c = amatch(s, p); | |
302 | entp = sentp; | |
303 | globbed = sglobbed; | |
304 | return (c); | |
305 | } | |
306 | ||
307 | amatch(s, p) | |
308 | register char *s, *p; | |
309 | { | |
310 | register int scc; | |
311 | int ok, lc; | |
312 | char *sgpathp; | |
313 | struct stat stb; | |
314 | int c, cc; | |
315 | ||
316 | globbed = 1; | |
317 | for (;;) { | |
318 | scc = *s++ & TRIM; | |
319 | switch (c = *p++) { | |
320 | ||
321 | case '{': | |
322 | return (execbrc(p - 1, s - 1)); | |
323 | ||
324 | case '[': | |
325 | ok = 0; | |
326 | lc = 077777; | |
327 | while (cc = *p++) { | |
328 | if (cc == ']') { | |
329 | if (ok) | |
330 | break; | |
331 | return (0); | |
332 | } | |
333 | if (cc == '-') { | |
334 | if (lc <= scc && scc <= *p++) | |
335 | ok++; | |
336 | } else | |
337 | if (scc == (lc = cc)) | |
338 | ok++; | |
339 | } | |
340 | if (cc == 0) | |
341 | error("Missing ]"); | |
342 | continue; | |
343 | ||
344 | case '*': | |
345 | if (!*p) | |
346 | return (1); | |
347 | if (*p == '/') { | |
348 | p++; | |
349 | goto slash; | |
350 | } | |
351 | for (s--; *s; s++) | |
352 | if (amatch(s, p)) | |
353 | return (1); | |
354 | return (0); | |
355 | ||
356 | case 0: | |
357 | return (scc == 0); | |
358 | ||
359 | default: | |
d33af40e | 360 | if ((c & TRIM) != scc) |
b6e604fd BJ |
361 | return (0); |
362 | continue; | |
363 | ||
364 | case '?': | |
365 | if (scc == 0) | |
366 | return (0); | |
367 | continue; | |
368 | ||
369 | case '/': | |
370 | if (scc) | |
371 | return (0); | |
372 | slash: | |
373 | s = entp; | |
374 | sgpathp = gpathp; | |
375 | while (*s) | |
376 | addpath(*s++); | |
377 | addpath('/'); | |
378 | if (stat(gpath, &stb) == 0 && isdir(stb)) | |
379 | if (*p == 0) { | |
380 | Gcat(gpath, ""); | |
381 | globcnt++; | |
382 | } else | |
383 | expand(p); | |
384 | gpathp = sgpathp; | |
385 | *gpathp = 0; | |
386 | return (0); | |
387 | } | |
388 | } | |
389 | } | |
390 | ||
391 | Gmatch(s, p) | |
392 | register char *s, *p; | |
393 | { | |
394 | register int scc; | |
395 | int ok, lc; | |
396 | int c, cc; | |
397 | ||
398 | for (;;) { | |
399 | scc = *s++ & TRIM; | |
400 | switch (c = *p++) { | |
401 | ||
402 | case '[': | |
403 | ok = 0; | |
404 | lc = 077777; | |
405 | while (cc = *p++) { | |
406 | if (cc == ']') { | |
407 | if (ok) | |
408 | break; | |
409 | return (0); | |
410 | } | |
411 | if (cc == '-') { | |
412 | if (lc <= scc && scc <= *p++) | |
413 | ok++; | |
414 | } else | |
415 | if (scc == (lc = cc)) | |
416 | ok++; | |
417 | } | |
418 | if (cc == 0) | |
419 | bferr("Missing ]"); | |
420 | continue; | |
421 | ||
422 | case '*': | |
423 | if (!*p) | |
424 | return (1); | |
425 | for (s--; *s; s++) | |
426 | if (Gmatch(s, p)) | |
427 | return (1); | |
428 | return (0); | |
429 | ||
430 | case 0: | |
431 | return (scc == 0); | |
432 | ||
433 | default: | |
434 | if ((c & TRIM) != scc) | |
435 | return (0); | |
436 | continue; | |
437 | ||
438 | case '?': | |
439 | if (scc == 0) | |
440 | return (0); | |
441 | continue; | |
442 | ||
443 | } | |
444 | } | |
445 | } | |
446 | ||
447 | Gcat(s1, s2) | |
35371dec | 448 | char *s1, *s2; |
b6e604fd | 449 | { |
35371dec EW |
450 | register char *p, *q; |
451 | int n; | |
452 | ||
453 | for (p = s1; *p++;) | |
454 | ; | |
455 | for (q = s2; *q++;) | |
456 | ; | |
457 | gnleft -= (n = (p - s1) + (q - s2) - 1); | |
b6e604fd BJ |
458 | if (gnleft <= 0 || ++gargc >= GAVSIZ) |
459 | error("Arguments too long"); | |
460 | gargv[gargc] = 0; | |
35371dec EW |
461 | p = gargv[gargc - 1] = xalloc((unsigned)n); |
462 | for (q = s1; *p++ = *q++;) | |
463 | ; | |
464 | for (p--, q = s2; *p++ = *q++;) | |
465 | ; | |
b6e604fd BJ |
466 | } |
467 | ||
468 | addpath(c) | |
469 | char c; | |
470 | { | |
471 | ||
472 | if (gpathp >= lastgpathp) | |
473 | error("Pathname too long"); | |
6795aa44 | 474 | *gpathp++ = c & TRIM; |
b6e604fd BJ |
475 | *gpathp = 0; |
476 | } | |
477 | ||
478 | rscan(t, f) | |
479 | register char **t; | |
480 | int (*f)(); | |
481 | { | |
35371dec | 482 | register char *p; |
b6e604fd | 483 | |
35371dec EW |
484 | while (p = *t++) |
485 | while (*p) | |
486 | (*f)(*p++); | |
b6e604fd BJ |
487 | } |
488 | ||
35371dec | 489 | trim(t) |
b6e604fd | 490 | register char **t; |
b6e604fd | 491 | { |
35371dec | 492 | register char *p; |
b6e604fd BJ |
493 | |
494 | while (p = *t++) | |
700d2436 JB |
495 | while (*p) |
496 | *p++ &= TRIM; | |
b6e604fd BJ |
497 | } |
498 | ||
35371dec EW |
499 | tglob(t) |
500 | register char **t; | |
b6e604fd | 501 | { |
35371dec | 502 | register char *p, c; |
b6e604fd | 503 | |
35371dec EW |
504 | while (p = *t++) { |
505 | if (*p == '~') | |
506 | gflag |= 2; | |
507 | else if (*p == '{' && (p[1] == '\0' || p[1] == '}' && p[2] == '\0')) | |
508 | continue; | |
509 | while (c = *p++) | |
6a422336 | 510 | if (isglob(c)) |
35371dec EW |
511 | gflag |= c == '{' ? 2 : 1; |
512 | } | |
b6e604fd BJ |
513 | } |
514 | ||
515 | char * | |
516 | globone(str) | |
517 | register char *str; | |
518 | { | |
519 | char *gv[2]; | |
520 | register char **gvp; | |
521 | register char *cp; | |
522 | ||
523 | gv[0] = str; | |
524 | gv[1] = 0; | |
525 | gflag = 0; | |
35371dec | 526 | tglob(gv); |
b6e604fd BJ |
527 | if (gflag) { |
528 | gvp = glob(gv); | |
529 | if (gvp == 0) { | |
530 | setname(str); | |
531 | bferr("No match"); | |
532 | } | |
533 | cp = *gvp++; | |
534 | if (cp == 0) | |
535 | cp = ""; | |
536 | else if (*gvp) { | |
537 | setname(str); | |
538 | bferr("Ambiguous"); | |
539 | } else | |
540 | cp = strip(cp); | |
541 | /* | |
542 | if (cp == 0 || *gvp) { | |
543 | setname(str); | |
544 | bferr(cp ? "Ambiguous" : "No output"); | |
545 | } | |
546 | */ | |
547 | xfree((char *)gargv); gargv = 0; | |
548 | } else { | |
35371dec | 549 | trim(gv); |
b6e604fd BJ |
550 | cp = savestr(gv[0]); |
551 | } | |
552 | return (cp); | |
553 | } | |
554 | ||
555 | /* | |
556 | * Command substitute cp. If literal, then this is | |
557 | * a substitution from a << redirection, and so we should | |
558 | * not crunch blanks and tabs, separating words only at newlines. | |
559 | */ | |
560 | char ** | |
561 | dobackp(cp, literal) | |
562 | char *cp; | |
563 | bool literal; | |
564 | { | |
565 | register char *lp, *rp; | |
566 | char *ep; | |
567 | char word[BUFSIZ]; | |
568 | char *apargv[GAVSIZ + 2]; | |
569 | ||
570 | if (pargv) { | |
571 | abort(); | |
572 | blkfree(pargv); | |
573 | } | |
574 | pargv = apargv; | |
575 | pargv[0] = NOSTR; | |
576 | pargcp = pargs = word; | |
577 | pargc = 0; | |
578 | pnleft = BUFSIZ - 4; | |
579 | for (;;) { | |
580 | for (lp = cp; *lp != '`'; lp++) { | |
581 | if (*lp == 0) { | |
582 | if (pargcp != pargs) | |
583 | pword(); | |
584 | #ifdef GDEBUG | |
585 | printf("leaving dobackp\n"); | |
586 | #endif | |
587 | return (pargv = copyblk(pargv)); | |
588 | } | |
589 | psave(*lp); | |
590 | } | |
591 | lp++; | |
592 | for (rp = lp; *rp && *rp != '`'; rp++) | |
593 | if (*rp == '\\') { | |
594 | rp++; | |
595 | if (!*rp) | |
596 | goto oops; | |
597 | } | |
598 | if (!*rp) | |
599 | oops: | |
600 | error("Unmatched `"); | |
601 | ep = savestr(lp); | |
602 | ep[rp - lp] = 0; | |
603 | backeval(ep, literal); | |
604 | #ifdef GDEBUG | |
605 | printf("back from backeval\n"); | |
606 | #endif | |
607 | cp = rp + 1; | |
608 | } | |
609 | } | |
610 | ||
611 | backeval(cp, literal) | |
612 | char *cp; | |
613 | bool literal; | |
614 | { | |
615 | int pvec[2]; | |
616 | int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; | |
617 | char ibuf[BUFSIZ]; | |
618 | register int icnt = 0, c; | |
619 | register char *ip; | |
620 | bool hadnl = 0; | |
621 | char *fakecom[2]; | |
622 | struct command faket; | |
623 | ||
624 | faket.t_dtyp = TCOM; | |
625 | faket.t_dflg = 0; | |
626 | faket.t_dlef = 0; | |
627 | faket.t_drit = 0; | |
628 | faket.t_dspr = 0; | |
629 | faket.t_dcom = fakecom; | |
630 | fakecom[0] = "` ... `"; | |
631 | fakecom[1] = 0; | |
632 | /* | |
633 | * We do the psave job to temporarily change the current job | |
634 | * so that the following fork is considered a separate job. | |
635 | * This is so that when backquotes are used in a | |
636 | * builtin function that calls glob the "current job" is not corrupted. | |
637 | * We only need one level of pushed jobs as long as we are sure to | |
638 | * fork here. | |
639 | */ | |
640 | psavejob(); | |
641 | /* | |
642 | * It would be nicer if we could integrate this redirection more | |
643 | * with the routines in sh.sem.c by doing a fake execute on a builtin | |
644 | * function that was piped out. | |
645 | */ | |
646 | mypipe(pvec); | |
647 | if (pfork(&faket, -1) == 0) { | |
648 | struct wordent paraml; | |
649 | struct command *t; | |
650 | ||
35371dec EW |
651 | (void) close(pvec[0]); |
652 | (void) dmove(pvec[1], 1); | |
653 | (void) dmove(SHDIAG, 2); | |
b6e604fd BJ |
654 | initdesc(); |
655 | arginp = cp; | |
656 | while (*cp) | |
657 | *cp++ &= TRIM; | |
35371dec | 658 | (void) lex(¶ml); |
b6e604fd BJ |
659 | if (err) |
660 | error(err); | |
661 | alias(¶ml); | |
662 | t = syntax(paraml.next, ¶ml, 0); | |
663 | if (err) | |
664 | error(err); | |
665 | if (t) | |
666 | t->t_dflg |= FPAR; | |
35371dec EW |
667 | (void) signal(SIGTSTP, SIG_IGN); |
668 | (void) signal(SIGTTIN, SIG_IGN); | |
669 | (void) signal(SIGTTOU, SIG_IGN); | |
b6e604fd BJ |
670 | execute(t, -1); |
671 | exitstat(); | |
672 | } | |
673 | xfree(cp); | |
35371dec | 674 | (void) close(pvec[1]); |
b6e604fd BJ |
675 | do { |
676 | int cnt = 0; | |
677 | for (;;) { | |
678 | if (icnt == 0) { | |
679 | ip = ibuf; | |
680 | icnt = read(pvec[0], ip, BUFSIZ); | |
681 | if (icnt <= 0) { | |
682 | c = -1; | |
683 | break; | |
684 | } | |
685 | } | |
686 | if (hadnl) | |
687 | break; | |
688 | --icnt; | |
689 | c = (*ip++ & TRIM); | |
690 | if (c == 0) | |
691 | break; | |
692 | if (c == '\n') { | |
693 | /* | |
694 | * Continue around the loop one | |
695 | * more time, so that we can eat | |
696 | * the last newline without terminating | |
697 | * this word. | |
698 | */ | |
699 | hadnl = 1; | |
700 | continue; | |
701 | } | |
702 | if (!quoted && (c == ' ' || c == '\t')) | |
703 | break; | |
704 | cnt++; | |
705 | psave(c | quoted); | |
706 | } | |
707 | /* | |
708 | * Unless at end-of-file, we will form a new word | |
709 | * here if there were characters in the word, or in | |
710 | * any case when we take text literally. If | |
711 | * we didn't make empty words here when literal was | |
712 | * set then we would lose blank lines. | |
713 | */ | |
714 | if (c != -1 && (cnt || literal)) | |
715 | pword(); | |
716 | hadnl = 0; | |
717 | } while (c >= 0); | |
718 | #ifdef GDEBUG | |
719 | printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); | |
720 | printf("also c = %c <%o>\n", c, c); | |
721 | #endif | |
35371dec | 722 | (void) close(pvec[0]); |
b6e604fd BJ |
723 | pwait(); |
724 | prestjob(); | |
725 | } | |
726 | ||
727 | psave(c) | |
728 | char c; | |
729 | { | |
730 | ||
731 | if (--pnleft <= 0) | |
732 | error("Word too long"); | |
733 | *pargcp++ = c; | |
734 | } | |
735 | ||
736 | pword() | |
737 | { | |
738 | ||
739 | psave(0); | |
740 | if (pargc == GAVSIZ) | |
741 | error("Too many words from ``"); | |
742 | pargv[pargc++] = savestr(pargs); | |
743 | pargv[pargc] = NOSTR; | |
744 | #ifdef GDEBUG | |
745 | printf("got word %s\n", pargv[pargc-1]); | |
746 | #endif | |
747 | pargcp = pargs; | |
748 | pnleft = BUFSIZ - 4; | |
749 | } |