csh and tcsh work

Sources of csh/sh.parse.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
    /*
  9. 9
     * Perform aliasing on the word list lex
  10. 10
     * Do a (very rudimentary) parse to separate into commands.
  11. 11
     * If word 0 of a command has an alias, do it.
  12. 12
     * Repeat a maximum of 20 times.
  13. 13
     */
  14. 14
    alias(lex)
  15. 15
    	register struct wordent *lex;
  16. 16
    {
  17. 17
    	int aleft = 21;
  18. 18
    	jmp_buf osetexit;
  19. 19
  20. 20
    	getexit(osetexit);
  21. 21
    	setexit();
  22. 22
    	if (haderr) {
  23. 23
    		resexit(osetexit);
  24. 24
    		reset();
  25. 25
    	}
  26. 26
    	if (--aleft == 0)
  27. 27
    		error("Alias loop");
  28. 28
    	asyntax(lex->next, lex);
  29. 29
    	resexit(osetexit);
  30. 30
    }
  31. 31
  32. 32
    asyntax(p1, p2)
  33. 33
    	register struct wordent *p1, *p2;
  34. 34
    {
  35. 35
  36. 36
    	while (p1 != p2)
  37. 37
    		if (any(p1->word[0], ";&\n"))
  38. 38
    			p1 = p1->next;
  39. 39
    		else {
  40. 40
    			asyn0(p1, p2);
  41. 41
    			return;
  42. 42
    		}
  43. 43
    }
  44. 44
  45. 45
    asyn0(p1, p2)
  46. 46
    	struct wordent *p1;
  47. 47
    	register struct wordent *p2;
  48. 48
    {
  49. 49
    	register struct wordent *p;
  50. 50
    	register int l = 0;
  51. 51
  52. 52
    	for (p = p1; p != p2; p = p->next)
  53. 53
    		switch (p->word[0]) {
  54. 54
  55. 55
    		case '(':
  56. 56
    			l++;
  57. 57
    			continue;
  58. 58
  59. 59
    		case ')':
  60. 60
    			l--;
  61. 61
    			if (l < 0)
  62. 62
    				error("Too many )'s");
  63. 63
    			continue;
  64. 64
  65. 65
    		case '>':
  66. 66
    			if (p->next != p2 && eq(p->next->word, "&"))
  67. 67
    				p = p->next;
  68. 68
    			continue;
  69. 69
  70. 70
    		case '&':
  71. 71
    		case '|':
  72. 72
    		case ';':
  73. 73
    		case '\n':
  74. 74
    			if (l != 0)
  75. 75
    				continue;
  76. 76
    			asyn3(p1, p);
  77. 77
    			asyntax(p->next, p2);
  78. 78
    			return;
  79. 79
    		}
  80. 80
    	if (l == 0)
  81. 81
    		asyn3(p1, p2);
  82. 82
    }
  83. 83
  84. 84
    asyn3(p1, p2)
  85. 85
    	struct wordent *p1;
  86. 86
    	register struct wordent *p2;
  87. 87
    {
  88. 88
    	register struct varent *ap;
  89. 89
    	struct wordent alout;
  90. 90
    	register bool redid;
  91. 91
  92. 92
    	if (p1 == p2)
  93. 93
    		return;
  94. 94
    	if (p1->word[0] == '(') {
  95. 95
    		for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
  96. 96
    			if (p2 == p1)
  97. 97
    				return;
  98. 98
    		if (p2 == p1->next)
  99. 99
    			return;
  100. 100
    		asyn0(p1->next, p2);
  101. 101
    		return;
  102. 102
    	}
  103. 103
    	ap = adrof1(p1->word, &aliases);
  104. 104
    	if (ap == 0)
  105. 105
    		return;
  106. 106
    	alhistp = p1->prev;
  107. 107
    	alhistt = p2;
  108. 108
    	alvec = ap->vec;
  109. 109
    	redid = lex(&alout);
  110. 110
    	alhistp = alhistt = 0;
  111. 111
    	alvec = 0;
  112. 112
    	if (err) {
  113. 113
    		freelex(&alout);
  114. 114
    		error(err);
  115. 115
    	}
  116. 116
    	if (p1->word[0] && eq(p1->word, alout.next->word)) {
  117. 117
    		char *cp = alout.next->word;
  118. 118
  119. 119
    		alout.next->word = strspl("\200", cp);
  120. 120
    		xfree(cp);
  121. 121
    	}
  122. 122
    	p1 = freenod(p1, redid ? p2 : p1->next);
  123. 123
    	if (alout.next != &alout) {
  124. 124
    		p1->next->prev = alout.prev->prev;
  125. 125
    		alout.prev->prev->next = p1->next;
  126. 126
    		alout.next->prev = p1;
  127. 127
    		p1->next = alout.next;
  128. 128
    		xfree(alout.prev->word);
  129. 129
    		xfree(alout.prev);
  130. 130
    	}
  131. 131
    	reset();		/* throw! */
  132. 132
    }
  133. 133
  134. 134
    struct wordent *
  135. 135
    freenod(p1, p2)
  136. 136
    	register struct wordent *p1, *p2;
  137. 137
    {
  138. 138
    	register struct wordent *retp = p1->prev;
  139. 139
  140. 140
    	while (p1 != p2) {
  141. 141
    		xfree(p1->word);
  142. 142
    		p1 = p1->next;
  143. 143
    		xfree(p1->prev);
  144. 144
    	}
  145. 145
    	retp->next = p2;
  146. 146
    	p2->prev = retp;
  147. 147
    	return (retp);
  148. 148
    }
  149. 149
  150. 150
    #define	PHERE	1
  151. 151
    #define	PIN	2
  152. 152
    #define	POUT	4
  153. 153
    #define	PDIAG	8
  154. 154
  155. 155
    /*
  156. 156
     * syntax
  157. 157
     *	empty
  158. 158
     *	syn0
  159. 159
     */
  160. 160
    struct command *
  161. 161
    syntax(p1, p2, flags)
  162. 162
    	register struct wordent *p1, *p2;
  163. 163
    	int flags;
  164. 164
    {
  165. 165
  166. 166
    	while (p1 != p2)
  167. 167
    		if (any(p1->word[0], ";&\n"))
  168. 168
    			p1 = p1->next;
  169. 169
    		else
  170. 170
    			return (syn0(p1, p2, flags));
  171. 171
    	return (0);
  172. 172
    }
  173. 173
  174. 174
    /*
  175. 175
     * syn0
  176. 176
     *	syn1
  177. 177
     *	syn1 & syntax
  178. 178
     */
  179. 179
    struct command *
  180. 180
    syn0(p1, p2, flags)
  181. 181
    	struct wordent *p1, *p2;
  182. 182
    	int flags;
  183. 183
    {
  184. 184
    	register struct wordent *p;
  185. 185
    	register struct command *t, *t1;
  186. 186
    	int l;
  187. 187
  188. 188
    	l = 0;
  189. 189
    	for (p = p1; p != p2; p = p->next)
  190. 190
    		switch (p->word[0]) {
  191. 191
  192. 192
    		case '(':
  193. 193
    			l++;
  194. 194
    			continue;
  195. 195
  196. 196
    		case ')':
  197. 197
    			l--;
  198. 198
    			if (l < 0)
  199. 199
    				seterr("Too many )'s");
  200. 200
    			continue;
  201. 201
  202. 202
    		case '|':
  203. 203
    			if (p->word[1] == '|')
  204. 204
    				continue;
  205. 205
    			/* fall into ... */
  206. 206
  207. 207
    		case '>':
  208. 208
    			if (p->next != p2 && eq(p->next->word, "&"))
  209. 209
    				p = p->next;
  210. 210
    			continue;
  211. 211
  212. 212
    		case '&':
  213. 213
    			if (l != 0)
  214. 214
    				break;
  215. 215
    			if (p->word[1] == '&')
  216. 216
    				continue;
  217. 217
    			t1 = syn1(p1, p, flags);
  218. 218
    			if (t1->t_dtyp == TLST) {
  219. 219
    				t = (struct command *) calloc(1, sizeof (*t));
  220. 220
    				t->t_dtyp = TPAR;
  221. 221
    				t->t_dflg = FAND|FPRS|FINT;
  222. 222
    				t->t_dspr = t1;
  223. 223
    				t1 = t;
  224. 224
    			} else
  225. 225
    				t1->t_dflg |= FAND|FPRS|FINT;
  226. 226
    			t = (struct command *) calloc(1, sizeof (*t));
  227. 227
    			t->t_dtyp = TLST;
  228. 228
    			t->t_dflg = 0;
  229. 229
    			t->t_dcar = t1;
  230. 230
    			t->t_dcdr = syntax(p, p2, flags);
  231. 231
    			return(t);
  232. 232
    		}
  233. 233
    	if (l == 0)
  234. 234
    		return (syn1(p1, p2, flags));
  235. 235
    	seterr("Too many ('s");
  236. 236
    	return (0);
  237. 237
    }
  238. 238
  239. 239
    /*
  240. 240
     * syn1
  241. 241
     *	syn1a
  242. 242
     *	syn1a ; syntax
  243. 243
     */
  244. 244
    struct command *
  245. 245
    syn1(p1, p2, flags)
  246. 246
    	struct wordent *p1, *p2;
  247. 247
    	int flags;
  248. 248
    {
  249. 249
    	register struct wordent *p;
  250. 250
    	register struct command *t;
  251. 251
    	int l;
  252. 252
  253. 253
    	l = 0;
  254. 254
    	for (p = p1; p != p2; p = p->next)
  255. 255
    		switch (p->word[0]) {
  256. 256
  257. 257
    		case '(':
  258. 258
    			l++;
  259. 259
    			continue;
  260. 260
  261. 261
    		case ')':
  262. 262
    			l--;
  263. 263
    			continue;
  264. 264
  265. 265
    		case ';':
  266. 266
    		case '\n':
  267. 267
    			if (l != 0)
  268. 268
    				break;
  269. 269
    			t = (struct command *) calloc(1, sizeof (*t));
  270. 270
    			t->t_dtyp = TLST;
  271. 271
    			t->t_dcar = syn1a(p1, p, flags);
  272. 272
    			t->t_dcdr = syntax(p->next, p2, flags);
  273. 273
    			if (t->t_dcdr == 0)
  274. 274
    				t->t_dcdr = t->t_dcar, t->t_dcar = 0;
  275. 275
    			return (t);
  276. 276
    		}
  277. 277
    	return (syn1a(p1, p2, flags));
  278. 278
    }
  279. 279
  280. 280
    /*
  281. 281
     * syn1a
  282. 282
     *	syn1b
  283. 283
     *	syn1b || syn1a
  284. 284
     */
  285. 285
    struct command *
  286. 286
    syn1a(p1, p2, flags)
  287. 287
    	struct wordent *p1, *p2;
  288. 288
    	int flags;
  289. 289
    {
  290. 290
    	register struct wordent *p;
  291. 291
    	register struct command *t;
  292. 292
    	register int l = 0;
  293. 293
  294. 294
    	for (p = p1; p != p2; p = p->next)
  295. 295
    		switch (p->word[0]) {
  296. 296
  297. 297
    		case '(':
  298. 298
    			l++;
  299. 299
    			continue;
  300. 300
  301. 301
    		case ')':
  302. 302
    			l--;
  303. 303
    			continue;
  304. 304
  305. 305
    		case '|':
  306. 306
    			if (p->word[1] != '|')
  307. 307
    				continue;
  308. 308
    			if (l == 0) {
  309. 309
    				t = (struct command *) calloc(1, sizeof (*t));
  310. 310
    				t->t_dtyp = TOR;
  311. 311
    				t->t_dcar = syn1b(p1, p, flags);
  312. 312
    				t->t_dcdr = syn1a(p->next, p2, flags);
  313. 313
    				t->t_dflg = 0;
  314. 314
    				return (t);
  315. 315
    			}
  316. 316
    			continue;
  317. 317
    		}
  318. 318
    	return (syn1b(p1, p2, flags));
  319. 319
    }
  320. 320
  321. 321
    /*
  322. 322
     * syn1b
  323. 323
     *	syn2
  324. 324
     *	syn2 && syn1b
  325. 325
     */
  326. 326
    struct command *
  327. 327
    syn1b(p1, p2, flags)
  328. 328
    	struct wordent *p1, *p2;
  329. 329
    	int flags;
  330. 330
    {
  331. 331
    	register struct wordent *p;
  332. 332
    	register struct command *t;
  333. 333
    	register int l = 0;
  334. 334
  335. 335
    	l = 0;
  336. 336
    	for (p = p1; p != p2; p = p->next)
  337. 337
    		switch (p->word[0]) {
  338. 338
  339. 339
    		case '(':
  340. 340
    			l++;
  341. 341
    			continue;
  342. 342
  343. 343
    		case ')':
  344. 344
    			l--;
  345. 345
    			continue;
  346. 346
  347. 347
    		case '&':
  348. 348
    			if (p->word[1] == '&' && l == 0) {
  349. 349
    				t = (struct command *) calloc(1, sizeof (*t));
  350. 350
    				t->t_dtyp = TAND;
  351. 351
    				t->t_dcar = syn2(p1, p, flags);
  352. 352
    				t->t_dcdr = syn1b(p->next, p2, flags);
  353. 353
    				t->t_dflg = 0;
  354. 354
    				return (t);
  355. 355
    			}
  356. 356
    			continue;
  357. 357
    		}
  358. 358
    	return (syn2(p1, p2, flags));
  359. 359
    }
  360. 360
  361. 361
    /*
  362. 362
     * syn2
  363. 363
     *	syn3
  364. 364
     *	syn3 | syn2
  365. 365
     *	syn3 |& syn2
  366. 366
     */
  367. 367
    struct command *
  368. 368
    syn2(p1, p2, flags)
  369. 369
    	struct wordent *p1, *p2;
  370. 370
    	int flags;
  371. 371
    {
  372. 372
    	register struct wordent *p, *pn;
  373. 373
    	register struct command *t;
  374. 374
    	register int l = 0;
  375. 375
    	int f;
  376. 376
  377. 377
    	for (p = p1; p != p2; p = p->next)
  378. 378
    		switch (p->word[0]) {
  379. 379
  380. 380
    		case '(':
  381. 381
    			l++;
  382. 382
    			continue;
  383. 383
  384. 384
    		case ')':
  385. 385
    			l--;
  386. 386
    			continue;
  387. 387
  388. 388
    		case '|':
  389. 389
    			if (l != 0)
  390. 390
    				continue;
  391. 391
    			t = (struct command *) calloc(1, sizeof (*t));
  392. 392
    			f = flags | POUT;
  393. 393
    			pn = p->next;
  394. 394
    			if (pn != p2 && pn->word[0] == '&') {
  395. 395
    				f |= PDIAG;
  396. 396
    				t->t_dflg |= FDIAG;
  397. 397
    			}
  398. 398
    			t->t_dtyp = TFIL;
  399. 399
    			t->t_dcar = syn3(p1, p, f);
  400. 400
    			if (pn != p2 && pn->word[0] == '&')
  401. 401
    				p = pn;
  402. 402
    			t->t_dcdr = syn2(p->next, p2, flags | PIN);
  403. 403
    			return (t);
  404. 404
    		}
  405. 405
    	return (syn3(p1, p2, flags));
  406. 406
    }
  407. 407
  408. 408
    char	*RELPAR =	"<>()";
  409. 409
  410. 410
    /*
  411. 411
     * syn3
  412. 412
     *	( syn0 ) [ < in  ] [ > out ]
  413. 413
     *	word word* [ < in ] [ > out ]
  414. 414
     *	KEYWORD ( word* ) word* [ < in ] [ > out ]
  415. 415
     *
  416. 416
     *	KEYWORD = (@ exit foreach if set switch test while)
  417. 417
     */
  418. 418
    struct command *
  419. 419
    syn3(p1, p2, flags)
  420. 420
    	struct wordent *p1, *p2;
  421. 421
    	int flags;
  422. 422
    {
  423. 423
    	register struct wordent *p;
  424. 424
    	struct wordent *lp, *rp;
  425. 425
    	register struct command *t;
  426. 426
    	register int l;
  427. 427
    	char **av;
  428. 428
    	int n, c;
  429. 429
    	bool specp = 0;
  430. 430
  431. 431
    	if (p1 != p2) {
  432. 432
    		p = p1;
  433. 433
    again:
  434. 434
    		switch (srchx(p->word)) {
  435. 435
  436. 436
    		case ZELSE:
  437. 437
    			p = p->next;
  438. 438
    			if (p != p2)
  439. 439
    				goto again;
  440. 440
    			break;
  441. 441
  442. 442
    		case ZEXIT:
  443. 443
    		case ZFOREACH:
  444. 444
    		case ZIF:
  445. 445
    		case ZLET:
  446. 446
    		case ZSET:
  447. 447
    		case ZSWITCH:
  448. 448
    		case ZWHILE:
  449. 449
    			specp = 1;
  450. 450
    			break;
  451. 451
    		}
  452. 452
    	}
  453. 453
    	n = 0;
  454. 454
    	l = 0;
  455. 455
    	for (p = p1; p != p2; p = p->next)
  456. 456
    		switch (p->word[0]) {
  457. 457
  458. 458
    		case '(':
  459. 459
    			if (specp)
  460. 460
    				n++;
  461. 461
    			l++;
  462. 462
    			continue;
  463. 463
  464. 464
    		case ')':
  465. 465
    			if (specp)
  466. 466
    				n++;
  467. 467
    			l--;
  468. 468
    			continue;
  469. 469
  470. 470
    		case '>':
  471. 471
    		case '<':
  472. 472
    			if (l != 0) {
  473. 473
    				if (specp)
  474. 474
    					n++;
  475. 475
    				continue;
  476. 476
    			}
  477. 477
    			if (p->next == p2)
  478. 478
    				continue;
  479. 479
    			if (any(p->next->word[0], RELPAR))
  480. 480
    				continue;
  481. 481
    			n--;
  482. 482
    			continue;
  483. 483
  484. 484
    		default:
  485. 485
    			if (!specp && l != 0)
  486. 486
    				continue;
  487. 487
    			n++;
  488. 488
    			continue;
  489. 489
    		}
  490. 490
    	if (n < 0)
  491. 491
    		n = 0;
  492. 492
    	t = (struct command *) calloc(1, sizeof (*t));
  493. 493
    	av = (char **) calloc(n + 1, sizeof (char **));
  494. 494
    	t->t_dcom = av;
  495. 495
    	n = 0;
  496. 496
    	if (p2->word[0] == ')')
  497. 497
    		t->t_dflg = FPAR;
  498. 498
    	lp = 0;
  499. 499
    	rp = 0;
  500. 500
    	l = 0;
  501. 501
    	for (p = p1; p != p2; p = p->next) {
  502. 502
    		c = p->word[0];
  503. 503
    		switch (c) {
  504. 504
  505. 505
    		case '(':
  506. 506
    			if (l == 0) {
  507. 507
    				if (lp != 0 && !specp)
  508. 508
    					seterr("Badly placed (");
  509. 509
    				lp = p->next;
  510. 510
    			}
  511. 511
    			l++;
  512. 512
    			goto savep;
  513. 513
  514. 514
    		case ')':
  515. 515
    			l--;
  516. 516
    			if (l == 0)
  517. 517
    				rp = p;
  518. 518
    			goto savep;
  519. 519
  520. 520
    		case '>':
  521. 521
    			if (l != 0)
  522. 522
    				goto savep;
  523. 523
    			if (p->word[1] == '>')
  524. 524
    				t->t_dflg |= FCAT;
  525. 525
    			if (p->next != p2 && eq(p->next->word, "&")) {
  526. 526
    				t->t_dflg |= FDIAG, p = p->next;
  527. 527
    				if (flags & (POUT|PDIAG))
  528. 528
    					goto badout;
  529. 529
    			}
  530. 530
    			if (p->next != p2 && eq(p->next->word, "!"))
  531. 531
    				t->t_dflg |= FANY, p = p->next;
  532. 532
    			if (p->next == p2) {
  533. 533
    missfile:
  534. 534
    				seterr("Missing name for redirect");
  535. 535
    				continue;
  536. 536
    			}
  537. 537
    			p = p->next;
  538. 538
    			if (any(p->word[0], RELPAR))
  539. 539
    				goto missfile;
  540. 540
    			if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
  541. 541
    badout:
  542. 542
    				seterr("Ambiguous output redirect");
  543. 543
    			else
  544. 544
    				t->t_drit = savestr(p->word);
  545. 545
    			continue;
  546. 546
  547. 547
    		case '<':
  548. 548
    			if (l != 0)
  549. 549
    				goto savep;
  550. 550
    			if (p->word[1] == '<')
  551. 551
    				t->t_dflg |= FHERE;
  552. 552
    			if (p->next == p2)
  553. 553
    				goto missfile;
  554. 554
    			p = p->next;
  555. 555
    			if (any(p->word[0], RELPAR))
  556. 556
    				goto missfile;
  557. 557
    			if ((flags & PHERE) && (t->t_dflg & FHERE))
  558. 558
    				seterr("Can't << within ()'s");
  559. 559
    			else if ((flags & PIN) || t->t_dlef)
  560. 560
    				seterr("Ambiguous input redirect");
  561. 561
    			else
  562. 562
    				t->t_dlef = savestr(p->word);
  563. 563
    			continue;
  564. 564
  565. 565
    savep:
  566. 566
    			if (!specp)
  567. 567
    				continue;
  568. 568
    		default:
  569. 569
    			if (l != 0 && !specp)
  570. 570
    				continue;
  571. 571
    			if (err == 0)
  572. 572
    				av[n] = savestr(p->word);
  573. 573
    			n++;
  574. 574
    			continue;
  575. 575
    		}
  576. 576
    	}
  577. 577
    	if (lp != 0 && !specp) {
  578. 578
    		if (n != 0)
  579. 579
    			seterr("Badly placed ()'s");
  580. 580
    		t->t_dtyp = TPAR;
  581. 581
    		t->t_dspr = syn0(lp, rp, PHERE);
  582. 582
    	} else {
  583. 583
    		if (n == 0)
  584. 584
    			seterr("Invalid null command");
  585. 585
    		t->t_dtyp = TCOM;
  586. 586
    	}
  587. 587
    	return (t);
  588. 588
    }
  589. 589
  590. 590
    freesyn(t)
  591. 591
    	register struct command *t;
  592. 592
    {
  593. 593
    	register char **v;
  594. 594
  595. 595
    	if (t == 0)
  596. 596
    		return;
  597. 597
    	switch (t->t_dtyp) {
  598. 598
  599. 599
    	case TCOM:
  600. 600
    		for (v = t->t_dcom; *v; v++)
  601. 601
    			xfree(*v);
  602. 602
    		xfree(t->t_dcom);
  603. 603
    		goto lr;
  604. 604
  605. 605
    	case TPAR:
  606. 606
    		freesyn(t->t_dspr);
  607. 607
    		/* fall into ... */
  608. 608
  609. 609
    lr:
  610. 610
    		xfree(t->t_dlef), xfree(t->t_drit);
  611. 611
    		break;
  612. 612
  613. 613
    	case TAND:
  614. 614
    	case TOR:
  615. 615
    	case TFIL:
  616. 616
    	case TLST:
  617. 617
    		freesyn(t->t_dcar), freesyn(t->t_dcdr);
  618. 618
    		break;
  619. 619
    	}
  620. 620
    	xfree(t);
  621. 621
    }

To the top of this page