csh and tcsh work

Sources of csh/sh.glob.c

csh と tcsh のソース

Bill Joy

First published: October, 1978.

Copyright © 1979 Regents of the University of California.

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

To the top of this page