csh and tcsh work

Sources of csh/sh.exp.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
    #define	ADDOP	1
  9. 9
    #define	MULOP	2
  10. 10
    #define	EQOP	4
  11. 11
    #define	RELOP	8
  12. 12
    #define	RESTOP	16
  13. 13
    #define	ANYOP	31
  14. 14
  15. 15
    #define	EQEQ	1
  16. 16
    #define	GTR	2
  17. 17
    #define	LSS	4
  18. 18
    #define	NOTEQ	6
  19. 19
  20. 20
    exp(vp)
  21. 21
    	register char ***vp;
  22. 22
    {
  23. 23
  24. 24
    	return (exp0(vp, 0));
  25. 25
    }
  26. 26
  27. 27
    exp0(vp, ignore)
  28. 28
    	register char ***vp;
  29. 29
    	bool ignore;
  30. 30
    {
  31. 31
    	register int p1 = exp1(vp, ignore);
  32. 32
  33. 33
    #ifdef EDEBUG
  34. 34
    	etraci("exp0 p1", p1, vp);
  35. 35
    #endif
  36. 36
    	if (**vp && eq(**vp, "||")) {
  37. 37
    		register int p2;
  38. 38
  39. 39
    		(*vp)++;
  40. 40
    		p2 = exp0(vp, ignore || p1);
  41. 41
    #ifdef EDEBUG
  42. 42
    		etraci("exp0 p2", p2, vp);
  43. 43
    #endif
  44. 44
    		return (p1 || p2);
  45. 45
    	}
  46. 46
    	return (p1);
  47. 47
    }
  48. 48
  49. 49
    exp1(vp, ignore)
  50. 50
    	register char ***vp;
  51. 51
    {
  52. 52
    	register int p1 = exp2(vp, ignore);
  53. 53
  54. 54
    #ifdef EDEBUG
  55. 55
    	etraci("exp1 p1", p1, vp);
  56. 56
    #endif
  57. 57
    	if (**vp && eq(**vp, "&&")) {
  58. 58
    		register int p2;
  59. 59
  60. 60
    		(*vp)++;
  61. 61
    		p2 = exp1(vp, ignore || !p1);
  62. 62
    #ifdef EDEBUG
  63. 63
    		etraci("exp1 p2", p2, vp);
  64. 64
    #endif
  65. 65
    		return (p1 && p2);
  66. 66
    	}
  67. 67
    	return (p1);
  68. 68
    }
  69. 69
  70. 70
    exp2(vp, ignore)
  71. 71
    	register char ***vp;
  72. 72
    	bool ignore;
  73. 73
    {
  74. 74
    	register int p1 = exp2a(vp, ignore);
  75. 75
  76. 76
    #ifdef EDEBUG
  77. 77
    	etraci("exp3 p1", p1, vp);
  78. 78
    #endif
  79. 79
    	if (**vp && eq(**vp, "|")) {
  80. 80
    		register int p2;
  81. 81
  82. 82
    		(*vp)++;
  83. 83
    		p2 = exp2(vp, ignore);
  84. 84
    #ifdef EDEBUG
  85. 85
    		etraci("exp3 p2", p2, vp);
  86. 86
    #endif
  87. 87
    		return (p1 | p2);
  88. 88
    	}
  89. 89
    	return (p1);
  90. 90
    }
  91. 91
  92. 92
    exp2a(vp, ignore)
  93. 93
    	register char ***vp;
  94. 94
    	bool ignore;
  95. 95
    {
  96. 96
    	register int p1 = exp2b(vp, ignore);
  97. 97
  98. 98
    #ifdef EDEBUG
  99. 99
    	etraci("exp2a p1", p1, vp);
  100. 100
    #endif
  101. 101
    	if (**vp && eq(**vp, "^")) {
  102. 102
    		register int p2;
  103. 103
  104. 104
    		(*vp)++;
  105. 105
    		p2 = exp2a(vp, ignore);
  106. 106
    #ifdef EDEBUG
  107. 107
    		etraci("exp2a p2", p2, vp);
  108. 108
    #endif
  109. 109
    		return (p1 ^ p2);
  110. 110
    	}
  111. 111
    	return (p1);
  112. 112
    }
  113. 113
  114. 114
    exp2b(vp, ignore)
  115. 115
    	register char ***vp;
  116. 116
    	bool ignore;
  117. 117
    {
  118. 118
    	register int p1 = exp2c(vp, ignore);
  119. 119
  120. 120
    #ifdef EDEBUG
  121. 121
    	etraci("exp2b p1", p1, vp);
  122. 122
    #endif
  123. 123
    	if (**vp && eq(**vp, "&")) {
  124. 124
    		register int p2;
  125. 125
  126. 126
    		(*vp)++;
  127. 127
    		p2 = exp2b(vp, ignore);
  128. 128
    #ifdef EDEBUG
  129. 129
    		etraci("exp2b p2", p2, vp);
  130. 130
    #endif
  131. 131
    		return (p1 & p2);
  132. 132
    	}
  133. 133
    	return (p1);
  134. 134
    }
  135. 135
  136. 136
    exp2c(vp, ignore)
  137. 137
    	register char ***vp;
  138. 138
    	bool ignore;
  139. 139
    {
  140. 140
    	register char *p1 = exp3(vp, ignore);
  141. 141
    	register char *p2;
  142. 142
    	register int i;
  143. 143
  144. 144
    #ifdef EDEBUG
  145. 145
    	etracc("exp2c p1", p1, vp);
  146. 146
    #endif
  147. 147
    	if (i = isa(**vp, EQOP)) {
  148. 148
    		(*vp)++;
  149. 149
    		p2 = exp3(vp, ignore);
  150. 150
    #ifdef EDEBUG
  151. 151
    		etracc("exp2c p2", p2, vp);
  152. 152
    #endif
  153. 153
    		if (!ignore) switch (i) {
  154. 154
  155. 155
    		case EQEQ:
  156. 156
    			i = eq(p1, p2);
  157. 157
    			break;
  158. 158
  159. 159
    		case NOTEQ:
  160. 160
    			i = !eq(p1, p2);
  161. 161
    			break;
  162. 162
    		}
  163. 163
    		xfree(p1), xfree(p2);
  164. 164
    		return (i);
  165. 165
    	}
  166. 166
    	i = egetn(p1);
  167. 167
    	xfree(p1);
  168. 168
    	return (i);
  169. 169
    }
  170. 170
  171. 171
    char *
  172. 172
    exp3(vp, ignore)
  173. 173
    	register char ***vp;
  174. 174
    	bool ignore;
  175. 175
    {
  176. 176
    	register char *p1, *p2;
  177. 177
    	register int i;
  178. 178
  179. 179
    	p1 = exp3a(vp, ignore);
  180. 180
    #ifdef EDEBUG
  181. 181
    	etracc("exp3 p1", p1, vp);
  182. 182
    #endif
  183. 183
    	if (i = isa(**vp, RELOP)) {
  184. 184
    		(*vp)++;
  185. 185
    		if (**vp && eq(**vp, "="))
  186. 186
    			i |= 1, (*vp)++;
  187. 187
    		p2 = exp3(vp, ignore);
  188. 188
    #ifdef EDEBUG
  189. 189
    		etracc("exp3 p2", p2, vp);
  190. 190
    #endif
  191. 191
    		if (!ignore) switch (i) {
  192. 192
  193. 193
    		case GTR:
  194. 194
    			i = egetn(p1) > egetn(p2);
  195. 195
    			break;
  196. 196
  197. 197
    		case GTR|1:
  198. 198
    			i = egetn(p1) >= egetn(p2);
  199. 199
    			break;
  200. 200
  201. 201
    		case LSS:
  202. 202
    			i = egetn(p1) < egetn(p2);
  203. 203
    			break;
  204. 204
  205. 205
    		case LSS|1:
  206. 206
    			i = egetn(p1) <= egetn(p2);
  207. 207
    			break;
  208. 208
    		}
  209. 209
    		xfree(p1), xfree(p2);
  210. 210
    		return (putn(i));
  211. 211
    	}
  212. 212
    	return (p1);
  213. 213
    }
  214. 214
  215. 215
    char *
  216. 216
    exp3a(vp, ignore)
  217. 217
    	register char ***vp;
  218. 218
    	bool ignore;
  219. 219
    {
  220. 220
    	register char *p1, *p2, *op;
  221. 221
    	register int i;
  222. 222
  223. 223
    	p1 = exp4(vp, ignore);
  224. 224
    #ifdef EDEBUG
  225. 225
    	etracc("exp3a p1", p1, vp);
  226. 226
    #endif
  227. 227
    	op = **vp;
  228. 228
    	if (op && any(op[0], "<>") && op[0] == op[1]) {
  229. 229
    		(*vp)++;
  230. 230
    		p2 = exp3a(vp, ignore);
  231. 231
    #ifdef EDEBUG
  232. 232
    		etracc("exp3a p2", p2, vp);
  233. 233
    #endif
  234. 234
    		if (op[0] == '<')
  235. 235
    			i = egetn(p1) << egetn(p2);
  236. 236
    		else
  237. 237
    			i = egetn(p1) >> egetn(p2);
  238. 238
    		xfree(p1), xfree(p2);
  239. 239
    		return (putn(i));
  240. 240
    	}
  241. 241
    	return (p1);
  242. 242
    }
  243. 243
  244. 244
    char *
  245. 245
    exp4(vp, ignore)
  246. 246
    	register char ***vp;
  247. 247
    	bool ignore;
  248. 248
    {
  249. 249
    	register char *p1, *p2;
  250. 250
    	register int i = 0;
  251. 251
  252. 252
    	p1 = exp5(vp, ignore);
  253. 253
    #ifdef EDEBUG
  254. 254
    	etracc("exp4 p1", p1, vp);
  255. 255
    #endif
  256. 256
    	if (isa(**vp, ADDOP)) {
  257. 257
    		register char *op = *(*vp)++;
  258. 258
  259. 259
    		p2 = exp4(vp, ignore);
  260. 260
    #ifdef EDEBUG
  261. 261
    		etracc("exp4 p2", p2, vp);
  262. 262
    #endif
  263. 263
    		if (!ignore) switch (op[0]) {
  264. 264
  265. 265
    		case '+':
  266. 266
    			i = egetn(p1) + egetn(p2);
  267. 267
    			break;
  268. 268
  269. 269
    		case '-':
  270. 270
    			i = egetn(p1) - egetn(p2);
  271. 271
    			break;
  272. 272
    		}
  273. 273
    		xfree(p1), xfree(p2);
  274. 274
    		return (putn(i));
  275. 275
    	}
  276. 276
    	return (p1);
  277. 277
    }
  278. 278
  279. 279
    char *
  280. 280
    exp5(vp, ignore)
  281. 281
    	register char ***vp;
  282. 282
    	bool ignore;
  283. 283
    {
  284. 284
    	register char *p1, *p2;
  285. 285
    	register int i = 0;
  286. 286
  287. 287
    	p1 = exp6(vp, ignore);
  288. 288
    #ifdef EDEBUG
  289. 289
    	etracc("exp5 p1", p1, vp);
  290. 290
    #endif
  291. 291
    	if (isa(**vp, MULOP)) {
  292. 292
    		register char *op = *(*vp)++;
  293. 293
  294. 294
    		p2 = exp5(vp, ignore);
  295. 295
    #ifdef EDEBUG
  296. 296
    		etracc("exp5 p2", p2, vp);
  297. 297
    #endif
  298. 298
    		if (!ignore) switch (op[0]) {
  299. 299
  300. 300
    		case '*':
  301. 301
    			i = egetn(p1) * egetn(p2);
  302. 302
    			break;
  303. 303
  304. 304
    		case '/':
  305. 305
    			i = egetn(p2);
  306. 306
    			if (i == 0)
  307. 307
    				error("Divide by 0");
  308. 308
    			i = egetn(p1) / i;
  309. 309
    			break;
  310. 310
  311. 311
    		case '%':
  312. 312
    			i = egetn(p2);
  313. 313
    			if (i == 0)
  314. 314
    				error("Mod by 0");
  315. 315
    			i = egetn(p1) % i;
  316. 316
    			break;
  317. 317
    		}
  318. 318
    		xfree(p1), xfree(p2);
  319. 319
    		return (putn(i));
  320. 320
    	}
  321. 321
    	return (p1);
  322. 322
    }
  323. 323
  324. 324
    char *
  325. 325
    exp6(vp, ignore)
  326. 326
    	register char ***vp;
  327. 327
    {
  328. 328
    	int ccode, i;
  329. 329
    	register char *cp, *dp, *ep;
  330. 330
  331. 331
    	if (eq(**vp, "!")) {
  332. 332
    		(*vp)++;
  333. 333
    		cp = exp6(vp, ignore);
  334. 334
    #ifdef EDEBUG
  335. 335
    		etracc("exp6 ! cp", cp, vp);
  336. 336
    #endif
  337. 337
    		i = egetn(cp);
  338. 338
    		xfree(cp);
  339. 339
    		return (putn(!i));
  340. 340
    	}
  341. 341
    	if (eq(**vp, "~")) {
  342. 342
    		(*vp)++;
  343. 343
    		cp = exp6(vp, ignore);
  344. 344
    #ifdef EDEBUG
  345. 345
    		etracc("exp6 ~ cp", cp, vp);
  346. 346
    #endif
  347. 347
    		i = egetn(cp);
  348. 348
    		xfree(cp);
  349. 349
    		return (putn(~i));
  350. 350
    	}
  351. 351
    	if (eq(**vp, "(")) {
  352. 352
    		(*vp)++;
  353. 353
    		ccode = exp0(vp, ignore);
  354. 354
    #ifdef EDEBUG
  355. 355
    		etraci("exp6 () ccode", ccode, vp);
  356. 356
    #endif
  357. 357
    		if (*vp == 0 || **vp == 0 || ***vp != ')')
  358. 358
    			bferr("Expression syntax");
  359. 359
    		(*vp)++;
  360. 360
    		return (putn(ccode));
  361. 361
    	}
  362. 362
    	if (eq(**vp, "{")) {
  363. 363
    		int pid;
  364. 364
    		register char **v;
  365. 365
  366. 366
    		(*vp)++;
  367. 367
    		v = *vp;
  368. 368
    		for (;;) {
  369. 369
    			if (!**vp)
  370. 370
    				bferr("Missing }");
  371. 371
    			if (eq(*(*vp)++, "}"))
  372. 372
    				break;
  373. 373
    		}
  374. 374
    		if (ignore)
  375. 375
    			return ("");
  376. 376
    		pid = fork();
  377. 377
    		if (pid < 0)
  378. 378
    			Perror("fork");
  379. 379
    		if (pid == 0) {
  380. 380
    			if (setintr)
  381. 381
    				signal(SIGINT, SIG_DFL);
  382. 382
    			*--(*vp) = 0;
  383. 383
    			evalav(v);
  384. 384
    			exitstat();
  385. 385
    		}
  386. 386
    		cadd(pid, "{}");
  387. 387
    		pwait(pid);
  388. 388
    #ifdef EDEBUG
  389. 389
    		etraci("exp6 {} status", egetn(value("status")), vp);
  390. 390
    #endif
  391. 391
    		return (putn(egetn(value("status")) == 0));
  392. 392
    	}
  393. 393
    	if (isa(**vp, ANYOP))
  394. 394
    		return ("");
  395. 395
    	cp = *(*vp)++;
  396. 396
    	if (*cp == '-' && any(cp[1], "erwxfdzo")) {
  397. 397
    		struct stat stb;
  398. 398
  399. 399
    		if (isa(**vp, ANYOP))
  400. 400
    			bferr("Missing file name");
  401. 401
    		dp = *(*vp)++;
  402. 402
    		if (ignore)
  403. 403
    			return ("");
  404. 404
    		ep = globone(dp);
  405. 405
    		switch (cp[1]) {
  406. 406
  407. 407
    		case 'r':
  408. 408
    			i = !access(ep, 4);
  409. 409
    			break;
  410. 410
  411. 411
    		case 'w':
  412. 412
    			i = !access(ep, 2);
  413. 413
    			break;
  414. 414
  415. 415
    		case 'x':
  416. 416
    			i = !access(ep, 1);
  417. 417
    			break;
  418. 418
  419. 419
    		default:
  420. 420
    			if (stat(ep, &stb)) {
  421. 421
    				xfree(ep);
  422. 422
    				return ("0");
  423. 423
    			}
  424. 424
    			switch (cp[1]) {
  425. 425
  426. 426
    			case 'f':
  427. 427
    				i = (stb.st_mode & S_IFMT) == S_IFREG;
  428. 428
    				break;
  429. 429
  430. 430
    			case 'd':
  431. 431
    				i = (stb.st_mode & S_IFMT) == S_IFDIR;
  432. 432
    				break;
  433. 433
  434. 434
    			case 'z':
  435. 435
    				i = stb.st_size == 0;
  436. 436
    				break;
  437. 437
  438. 438
    			case 'e':
  439. 439
    				i = 1;
  440. 440
    				break;
  441. 441
  442. 442
    			case 'o':
  443. 443
    				i = stb.st_uid == uid;
  444. 444
    				break;
  445. 445
    			}
  446. 446
    		}
  447. 447
    #ifdef EDEBUG
  448. 448
    		etraci("exp6 -? i", i, vp);
  449. 449
    #endif
  450. 450
    		xfree(ep);
  451. 451
    		return (putn(i));
  452. 452
    	}
  453. 453
    #ifdef EDEBUG
  454. 454
    	etracc("exp6 default", cp, vp);
  455. 455
    #endif
  456. 456
    	return (globone(cp));
  457. 457
    }
  458. 458
  459. 459
    evalav(v)
  460. 460
    	register char **v;
  461. 461
    {
  462. 462
    	struct wordent paraml;
  463. 463
    	register struct wordent *hp = ¶ml;
  464. 464
    	struct command *t;
  465. 465
    	register struct wordent *wdp = hp;
  466. 466
  467. 467
    	child++;
  468. 468
    	set("status", "0");
  469. 469
    	hp->prev = hp->next = hp;
  470. 470
    	hp->word = "";
  471. 471
    	while (*v) {
  472. 472
    		register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
  473. 473
  474. 474
    		new->prev = wdp;
  475. 475
    		new->next = hp;
  476. 476
    		wdp->next = new;
  477. 477
    		wdp = new;
  478. 478
    		wdp->word = savestr(*v++);
  479. 479
    	}
  480. 480
    	hp->prev = wdp;
  481. 481
    	alias(¶ml);
  482. 482
    	t = syntax(paraml.next, ¶ml);
  483. 483
    	if (err)
  484. 484
    		error(err);
  485. 485
    	execute(t);
  486. 486
    	freelex(¶ml), freesyn(t);
  487. 487
    }
  488. 488
  489. 489
    isa(cp, what)
  490. 490
    	register char *cp;
  491. 491
    	register int what;
  492. 492
    {
  493. 493
  494. 494
    	if (cp == 0)
  495. 495
    		return ((what & RESTOP) != 0);
  496. 496
    	if (cp[1] == 0) {
  497. 497
    		if ((what & ADDOP) && any(cp[0], "+-"))
  498. 498
    			return (1);
  499. 499
    		if ((what & MULOP) && any(cp[0], "*/%"))
  500. 500
    			return (1);
  501. 501
    		if ((what & RESTOP) && any(cp[0], "()!~^"))
  502. 502
    			return (1);
  503. 503
    	}
  504. 504
    	if ((what & RESTOP) && (any(cp[0], "|&") || eq(cp, "<<") || eq(cp, ">>")))
  505. 505
    		return (1);
  506. 506
    	if (what & EQOP) {
  507. 507
    		if (eq(cp, "=="))
  508. 508
    			return (EQEQ);
  509. 509
    		if (eq(cp, "!="))
  510. 510
    			return (NOTEQ);
  511. 511
    	}
  512. 512
    	if (!(what & RELOP))
  513. 513
    		return (0);
  514. 514
    	if (*cp == '<')
  515. 515
    		return (LSS);
  516. 516
    	if (*cp == '>')
  517. 517
    		return (GTR);
  518. 518
    	return (0);
  519. 519
    }
  520. 520
  521. 521
    egetn(cp)
  522. 522
    	register char *cp;
  523. 523
    {
  524. 524
  525. 525
    	if (*cp && *cp != '-' && !digit(*cp))
  526. 526
    		bferr("Expression syntax");
  527. 527
    	return (getn(cp));
  528. 528
    }
  529. 529
  530. 530
    /* Phew! */
  531. 531
  532. 532
    #ifdef EDEBUG
  533. 533
    etraci(str, i, vp)
  534. 534
    	char *str;
  535. 535
    	int i;
  536. 536
    	char ***vp;
  537. 537
    {
  538. 538
  539. 539
    	printf("%s=%d\t", str, i);
  540. 540
    	blkpr(*vp);
  541. 541
    	printf("\n");
  542. 542
    }
  543. 543
  544. 544
    etracc(str, cp, vp)
  545. 545
    	char *str, *cp;
  546. 546
    	char ***vp;
  547. 547
    {
  548. 548
  549. 549
    	printf("%s=%s\t", str, cp);
  550. 550
    	blkpr(*vp);
  551. 551
    	printf("\n");
  552. 552
    }
  553. 553
    #endif

To the top of this page