[9] | 1 | #define Extern extern
|
---|
| 2 | #include <sys/types.h>
|
---|
| 3 | #include <signal.h>
|
---|
| 4 | #include <errno.h>
|
---|
| 5 | #include <setjmp.h>
|
---|
| 6 | #include "sh.h"
|
---|
| 7 |
|
---|
| 8 | /* -------- csyn.c -------- */
|
---|
| 9 | /*
|
---|
| 10 | * shell: syntax (C version)
|
---|
| 11 | */
|
---|
| 12 |
|
---|
| 13 | typedef union {
|
---|
| 14 | char *cp;
|
---|
| 15 | char **wp;
|
---|
| 16 | int i;
|
---|
| 17 | struct op *o;
|
---|
| 18 | } YYSTYPE;
|
---|
| 19 | #define WORD 256
|
---|
| 20 | #define LOGAND 257
|
---|
| 21 | #define LOGOR 258
|
---|
| 22 | #define BREAK 259
|
---|
| 23 | #define IF 260
|
---|
| 24 | #define THEN 261
|
---|
| 25 | #define ELSE 262
|
---|
| 26 | #define ELIF 263
|
---|
| 27 | #define FI 264
|
---|
| 28 | #define CASE 265
|
---|
| 29 | #define ESAC 266
|
---|
| 30 | #define FOR 267
|
---|
| 31 | #define WHILE 268
|
---|
| 32 | #define UNTIL 269
|
---|
| 33 | #define DO 270
|
---|
| 34 | #define DONE 271
|
---|
| 35 | #define IN 272
|
---|
| 36 | #define YYERRCODE 300
|
---|
| 37 |
|
---|
| 38 | /* flags to yylex */
|
---|
| 39 | #define CONTIN 01 /* skip new lines to complete command */
|
---|
| 40 |
|
---|
| 41 | /* #include "sh.h" */
|
---|
| 42 | #define SYNTAXERR zzerr()
|
---|
| 43 | static int startl;
|
---|
| 44 | static int peeksym;
|
---|
| 45 | static int nlseen;
|
---|
| 46 | static int iounit = IODEFAULT;
|
---|
| 47 |
|
---|
| 48 | static YYSTYPE yylval;
|
---|
| 49 |
|
---|
| 50 | _PROTOTYPE(static struct op *pipeline, (int cf ));
|
---|
| 51 | _PROTOTYPE(static struct op *andor, (void));
|
---|
| 52 | _PROTOTYPE(static struct op *c_list, (void));
|
---|
| 53 | _PROTOTYPE(static int synio, (int cf ));
|
---|
| 54 | _PROTOTYPE(static void musthave, (int c, int cf ));
|
---|
| 55 | _PROTOTYPE(static struct op *simple, (void));
|
---|
| 56 | _PROTOTYPE(static struct op *nested, (int type, int mark ));
|
---|
| 57 | _PROTOTYPE(static struct op *command, (int cf ));
|
---|
| 58 | _PROTOTYPE(static struct op *dogroup, (int onlydone ));
|
---|
| 59 | _PROTOTYPE(static struct op *thenpart, (void));
|
---|
| 60 | _PROTOTYPE(static struct op *elsepart, (void));
|
---|
| 61 | _PROTOTYPE(static struct op *caselist, (void));
|
---|
| 62 | _PROTOTYPE(static struct op *casepart, (void));
|
---|
| 63 | _PROTOTYPE(static char **pattern, (void));
|
---|
| 64 | _PROTOTYPE(static char **wordlist, (void));
|
---|
| 65 | _PROTOTYPE(static struct op *list, (struct op *t1, struct op *t2 ));
|
---|
| 66 | _PROTOTYPE(static struct op *block, (int type, struct op *t1, struct op *t2, char **wp ));
|
---|
| 67 | _PROTOTYPE(static struct op *newtp, (void));
|
---|
| 68 | _PROTOTYPE(static struct op *namelist, (struct op *t ));
|
---|
| 69 | _PROTOTYPE(static char **copyw, (void));
|
---|
| 70 | _PROTOTYPE(static void word, (char *cp ));
|
---|
| 71 | _PROTOTYPE(static struct ioword **copyio, (void));
|
---|
| 72 | _PROTOTYPE(static struct ioword *io, (int u, int f, char *cp ));
|
---|
| 73 | _PROTOTYPE(static void zzerr, (void));
|
---|
| 74 | _PROTOTYPE(void yyerror, (char *s ));
|
---|
| 75 | _PROTOTYPE(static int yylex, (int cf ));
|
---|
| 76 | _PROTOTYPE(int collect, (int c, int c1 ));
|
---|
| 77 | _PROTOTYPE(int dual, (int c ));
|
---|
| 78 | _PROTOTYPE(static void diag, (int ec ));
|
---|
| 79 | _PROTOTYPE(static char *tree, (unsigned size ));
|
---|
| 80 | _PROTOTYPE(void printf, (char *s ));
|
---|
| 81 |
|
---|
| 82 | int
|
---|
| 83 | yyparse()
|
---|
| 84 | {
|
---|
| 85 | startl = 1;
|
---|
| 86 | peeksym = 0;
|
---|
| 87 | yynerrs = 0;
|
---|
| 88 | outtree = c_list();
|
---|
| 89 | musthave('\n', 0);
|
---|
| 90 | return(yynerrs!=0);
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | static struct op *
|
---|
| 94 | pipeline(cf)
|
---|
| 95 | int cf;
|
---|
| 96 | {
|
---|
| 97 | register struct op *t, *p;
|
---|
| 98 | register int c;
|
---|
| 99 |
|
---|
| 100 | t = command(cf);
|
---|
| 101 | if (t != NULL) {
|
---|
| 102 | while ((c = yylex(0)) == '|') {
|
---|
| 103 | if ((p = command(CONTIN)) == NULL)
|
---|
| 104 | SYNTAXERR;
|
---|
| 105 | if (t->type != TPAREN && t->type != TCOM) {
|
---|
| 106 | /* shell statement */
|
---|
| 107 | t = block(TPAREN, t, NOBLOCK, NOWORDS);
|
---|
| 108 | }
|
---|
| 109 | t = block(TPIPE, t, p, NOWORDS);
|
---|
| 110 | }
|
---|
| 111 | peeksym = c;
|
---|
| 112 | }
|
---|
| 113 | return(t);
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | static struct op *
|
---|
| 117 | andor()
|
---|
| 118 | {
|
---|
| 119 | register struct op *t, *p;
|
---|
| 120 | register int c;
|
---|
| 121 |
|
---|
| 122 | t = pipeline(0);
|
---|
| 123 | if (t != NULL) {
|
---|
| 124 | while ((c = yylex(0)) == LOGAND || c == LOGOR) {
|
---|
| 125 | if ((p = pipeline(CONTIN)) == NULL)
|
---|
| 126 | SYNTAXERR;
|
---|
| 127 | t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
|
---|
| 128 | }
|
---|
| 129 | peeksym = c;
|
---|
| 130 | }
|
---|
| 131 | return(t);
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | static struct op *
|
---|
| 135 | c_list()
|
---|
| 136 | {
|
---|
| 137 | register struct op *t, *p;
|
---|
| 138 | register int c;
|
---|
| 139 |
|
---|
| 140 | t = andor();
|
---|
| 141 | if (t != NULL) {
|
---|
| 142 | if((peeksym = yylex(0)) == '&')
|
---|
| 143 | t = block(TASYNC, t, NOBLOCK, NOWORDS);
|
---|
| 144 | while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) {
|
---|
| 145 | if ((p = andor()) == NULL)
|
---|
| 146 | return(t);
|
---|
| 147 | if((peeksym = yylex(0)) == '&')
|
---|
| 148 | p = block(TASYNC, p, NOBLOCK, NOWORDS);
|
---|
| 149 | t = list(t, p);
|
---|
| 150 | }
|
---|
| 151 | peeksym = c;
|
---|
| 152 | }
|
---|
| 153 | return(t);
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 |
|
---|
| 157 | static int
|
---|
| 158 | synio(cf)
|
---|
| 159 | int cf;
|
---|
| 160 | {
|
---|
| 161 | register struct ioword *iop;
|
---|
| 162 | register int i;
|
---|
| 163 | register int c;
|
---|
| 164 |
|
---|
| 165 | if ((c = yylex(cf)) != '<' && c != '>') {
|
---|
| 166 | peeksym = c;
|
---|
| 167 | return(0);
|
---|
| 168 | }
|
---|
| 169 | i = yylval.i;
|
---|
| 170 | musthave(WORD, 0);
|
---|
| 171 | iop = io(iounit, i, yylval.cp);
|
---|
| 172 | iounit = IODEFAULT;
|
---|
| 173 | if (i & IOHERE)
|
---|
| 174 | markhere(yylval.cp, iop);
|
---|
| 175 | return(1);
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 | static void
|
---|
| 179 | musthave(c, cf)
|
---|
| 180 | int c, cf;
|
---|
| 181 | {
|
---|
| 182 | if ((peeksym = yylex(cf)) != c)
|
---|
| 183 | SYNTAXERR;
|
---|
| 184 | peeksym = 0;
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 | static struct op *
|
---|
| 188 | simple()
|
---|
| 189 | {
|
---|
| 190 | register struct op *t;
|
---|
| 191 |
|
---|
| 192 | t = NULL;
|
---|
| 193 | for (;;) {
|
---|
| 194 | switch (peeksym = yylex(0)) {
|
---|
| 195 | case '<':
|
---|
| 196 | case '>':
|
---|
| 197 | (void) synio(0);
|
---|
| 198 | break;
|
---|
| 199 |
|
---|
| 200 | case WORD:
|
---|
| 201 | if (t == NULL) {
|
---|
| 202 | t = newtp();
|
---|
| 203 | t->type = TCOM;
|
---|
| 204 | }
|
---|
| 205 | peeksym = 0;
|
---|
| 206 | word(yylval.cp);
|
---|
| 207 | break;
|
---|
| 208 |
|
---|
| 209 | default:
|
---|
| 210 | return(t);
|
---|
| 211 | }
|
---|
| 212 | }
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 | static struct op *
|
---|
| 216 | nested(type, mark)
|
---|
| 217 | int type, mark;
|
---|
| 218 | {
|
---|
| 219 | register struct op *t;
|
---|
| 220 |
|
---|
| 221 | multiline++;
|
---|
| 222 | t = c_list();
|
---|
| 223 | musthave(mark, 0);
|
---|
| 224 | multiline--;
|
---|
| 225 | return(block(type, t, NOBLOCK, NOWORDS));
|
---|
| 226 | }
|
---|
| 227 |
|
---|
| 228 | static struct op *
|
---|
| 229 | command(cf)
|
---|
| 230 | int cf;
|
---|
| 231 | {
|
---|
| 232 | register struct op *t;
|
---|
| 233 | struct wdblock *iosave;
|
---|
| 234 | register int c;
|
---|
| 235 |
|
---|
| 236 | iosave = iolist;
|
---|
| 237 | iolist = NULL;
|
---|
| 238 | if (multiline)
|
---|
| 239 | cf |= CONTIN;
|
---|
| 240 | while (synio(cf))
|
---|
| 241 | cf = 0;
|
---|
| 242 | switch (c = yylex(cf)) {
|
---|
| 243 | default:
|
---|
| 244 | peeksym = c;
|
---|
| 245 | if ((t = simple()) == NULL) {
|
---|
| 246 | if (iolist == NULL)
|
---|
| 247 | return((struct op *)NULL);
|
---|
| 248 | t = newtp();
|
---|
| 249 | t->type = TCOM;
|
---|
| 250 | }
|
---|
| 251 | break;
|
---|
| 252 |
|
---|
| 253 | case '(':
|
---|
| 254 | t = nested(TPAREN, ')');
|
---|
| 255 | break;
|
---|
| 256 |
|
---|
| 257 | case '{':
|
---|
| 258 | t = nested(TBRACE, '}');
|
---|
| 259 | break;
|
---|
| 260 |
|
---|
| 261 | case FOR:
|
---|
| 262 | t = newtp();
|
---|
| 263 | t->type = TFOR;
|
---|
| 264 | musthave(WORD, 0);
|
---|
| 265 | startl = 1;
|
---|
| 266 | t->str = yylval.cp;
|
---|
| 267 | multiline++;
|
---|
| 268 | t->words = wordlist();
|
---|
| 269 | if ((c = yylex(0)) != '\n' && c != ';')
|
---|
| 270 | peeksym = c;
|
---|
| 271 | t->left = dogroup(0);
|
---|
| 272 | multiline--;
|
---|
| 273 | break;
|
---|
| 274 |
|
---|
| 275 | case WHILE:
|
---|
| 276 | case UNTIL:
|
---|
| 277 | multiline++;
|
---|
| 278 | t = newtp();
|
---|
| 279 | t->type = c == WHILE? TWHILE: TUNTIL;
|
---|
| 280 | t->left = c_list();
|
---|
| 281 | t->right = dogroup(1);
|
---|
| 282 | t->words = NULL;
|
---|
| 283 | multiline--;
|
---|
| 284 | break;
|
---|
| 285 |
|
---|
| 286 | case CASE:
|
---|
| 287 | t = newtp();
|
---|
| 288 | t->type = TCASE;
|
---|
| 289 | musthave(WORD, 0);
|
---|
| 290 | t->str = yylval.cp;
|
---|
| 291 | startl++;
|
---|
| 292 | multiline++;
|
---|
| 293 | musthave(IN, CONTIN);
|
---|
| 294 | startl++;
|
---|
| 295 | t->left = caselist();
|
---|
| 296 | musthave(ESAC, 0);
|
---|
| 297 | multiline--;
|
---|
| 298 | break;
|
---|
| 299 |
|
---|
| 300 | case IF:
|
---|
| 301 | multiline++;
|
---|
| 302 | t = newtp();
|
---|
| 303 | t->type = TIF;
|
---|
| 304 | t->left = c_list();
|
---|
| 305 | t->right = thenpart();
|
---|
| 306 | musthave(FI, 0);
|
---|
| 307 | multiline--;
|
---|
| 308 | break;
|
---|
| 309 | }
|
---|
| 310 | while (synio(0))
|
---|
| 311 | ;
|
---|
| 312 | t = namelist(t);
|
---|
| 313 | iolist = iosave;
|
---|
| 314 | return(t);
|
---|
| 315 | }
|
---|
| 316 |
|
---|
| 317 | static struct op *
|
---|
| 318 | dogroup(onlydone)
|
---|
| 319 | int onlydone;
|
---|
| 320 | {
|
---|
| 321 | register int c;
|
---|
| 322 | register struct op *list;
|
---|
| 323 |
|
---|
| 324 | c = yylex(CONTIN);
|
---|
| 325 | if (c == DONE && onlydone)
|
---|
| 326 | return((struct op *)NULL);
|
---|
| 327 | if (c != DO)
|
---|
| 328 | SYNTAXERR;
|
---|
| 329 | list = c_list();
|
---|
| 330 | musthave(DONE, 0);
|
---|
| 331 | return(list);
|
---|
| 332 | }
|
---|
| 333 |
|
---|
| 334 | static struct op *
|
---|
| 335 | thenpart()
|
---|
| 336 | {
|
---|
| 337 | register int c;
|
---|
| 338 | register struct op *t;
|
---|
| 339 |
|
---|
| 340 | if ((c = yylex(0)) != THEN) {
|
---|
| 341 | peeksym = c;
|
---|
| 342 | return((struct op *)NULL);
|
---|
| 343 | }
|
---|
| 344 | t = newtp();
|
---|
| 345 | t->type = 0;
|
---|
| 346 | t->left = c_list();
|
---|
| 347 | if (t->left == NULL)
|
---|
| 348 | SYNTAXERR;
|
---|
| 349 | t->right = elsepart();
|
---|
| 350 | return(t);
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | static struct op *
|
---|
| 354 | elsepart()
|
---|
| 355 | {
|
---|
| 356 | register int c;
|
---|
| 357 | register struct op *t;
|
---|
| 358 |
|
---|
| 359 | switch (c = yylex(0)) {
|
---|
| 360 | case ELSE:
|
---|
| 361 | if ((t = c_list()) == NULL)
|
---|
| 362 | SYNTAXERR;
|
---|
| 363 | return(t);
|
---|
| 364 |
|
---|
| 365 | case ELIF:
|
---|
| 366 | t = newtp();
|
---|
| 367 | t->type = TELIF;
|
---|
| 368 | t->left = c_list();
|
---|
| 369 | t->right = thenpart();
|
---|
| 370 | return(t);
|
---|
| 371 |
|
---|
| 372 | default:
|
---|
| 373 | peeksym = c;
|
---|
| 374 | return((struct op *)NULL);
|
---|
| 375 | }
|
---|
| 376 | }
|
---|
| 377 |
|
---|
| 378 | static struct op *
|
---|
| 379 | caselist()
|
---|
| 380 | {
|
---|
| 381 | register struct op *t;
|
---|
| 382 |
|
---|
| 383 | t = NULL;
|
---|
| 384 | while ((peeksym = yylex(CONTIN)) != ESAC)
|
---|
| 385 | t = list(t, casepart());
|
---|
| 386 | return(t);
|
---|
| 387 | }
|
---|
| 388 |
|
---|
| 389 | static struct op *
|
---|
| 390 | casepart()
|
---|
| 391 | {
|
---|
| 392 | register struct op *t;
|
---|
| 393 |
|
---|
| 394 | t = newtp();
|
---|
| 395 | t->type = TPAT;
|
---|
| 396 | t->words = pattern();
|
---|
| 397 | musthave(')', 0);
|
---|
| 398 | t->left = c_list();
|
---|
| 399 | if ((peeksym = yylex(CONTIN)) != ESAC)
|
---|
| 400 | musthave(BREAK, CONTIN);
|
---|
| 401 | return(t);
|
---|
| 402 | }
|
---|
| 403 |
|
---|
| 404 | static char **
|
---|
| 405 | pattern()
|
---|
| 406 | {
|
---|
| 407 | register int c, cf;
|
---|
| 408 |
|
---|
| 409 | cf = CONTIN;
|
---|
| 410 | do {
|
---|
| 411 | musthave(WORD, cf);
|
---|
| 412 | word(yylval.cp);
|
---|
| 413 | cf = 0;
|
---|
| 414 | } while ((c = yylex(0)) == '|');
|
---|
| 415 | peeksym = c;
|
---|
| 416 | word(NOWORD);
|
---|
| 417 | return(copyw());
|
---|
| 418 | }
|
---|
| 419 |
|
---|
| 420 | static char **
|
---|
| 421 | wordlist()
|
---|
| 422 | {
|
---|
| 423 | register int c;
|
---|
| 424 |
|
---|
| 425 | if ((c = yylex(0)) != IN) {
|
---|
| 426 | peeksym = c;
|
---|
| 427 | return((char **)NULL);
|
---|
| 428 | }
|
---|
| 429 | startl = 0;
|
---|
| 430 | while ((c = yylex(0)) == WORD)
|
---|
| 431 | word(yylval.cp);
|
---|
| 432 | word(NOWORD);
|
---|
| 433 | peeksym = c;
|
---|
| 434 | return(copyw());
|
---|
| 435 | }
|
---|
| 436 |
|
---|
| 437 | /*
|
---|
| 438 | * supporting functions
|
---|
| 439 | */
|
---|
| 440 | static struct op *
|
---|
| 441 | list(t1, t2)
|
---|
| 442 | register struct op *t1, *t2;
|
---|
| 443 | {
|
---|
| 444 | if (t1 == NULL)
|
---|
| 445 | return(t2);
|
---|
| 446 | if (t2 == NULL)
|
---|
| 447 | return(t1);
|
---|
| 448 | return(block(TLIST, t1, t2, NOWORDS));
|
---|
| 449 | }
|
---|
| 450 |
|
---|
| 451 | static struct op *
|
---|
| 452 | block(type, t1, t2, wp)
|
---|
| 453 | int type;
|
---|
| 454 | struct op *t1, *t2;
|
---|
| 455 | char **wp;
|
---|
| 456 | {
|
---|
| 457 | register struct op *t;
|
---|
| 458 |
|
---|
| 459 | t = newtp();
|
---|
| 460 | t->type = type;
|
---|
| 461 | t->left = t1;
|
---|
| 462 | t->right = t2;
|
---|
| 463 | t->words = wp;
|
---|
| 464 | return(t);
|
---|
| 465 | }
|
---|
| 466 |
|
---|
| 467 | struct res {
|
---|
| 468 | char *r_name;
|
---|
| 469 | int r_val;
|
---|
| 470 | } restab[] = {
|
---|
| 471 | "for", FOR,
|
---|
| 472 | "case", CASE,
|
---|
| 473 | "esac", ESAC,
|
---|
| 474 | "while", WHILE,
|
---|
| 475 | "do", DO,
|
---|
| 476 | "done", DONE,
|
---|
| 477 | "if", IF,
|
---|
| 478 | "in", IN,
|
---|
| 479 | "then", THEN,
|
---|
| 480 | "else", ELSE,
|
---|
| 481 | "elif", ELIF,
|
---|
| 482 | "until", UNTIL,
|
---|
| 483 | "fi", FI,
|
---|
| 484 |
|
---|
| 485 | ";;", BREAK,
|
---|
| 486 | "||", LOGOR,
|
---|
| 487 | "&&", LOGAND,
|
---|
| 488 | "{", '{',
|
---|
| 489 | "}", '}',
|
---|
| 490 |
|
---|
| 491 | 0,
|
---|
| 492 | };
|
---|
| 493 |
|
---|
| 494 | int
|
---|
| 495 | rlookup(n)
|
---|
| 496 | register char *n;
|
---|
| 497 | {
|
---|
| 498 | register struct res *rp;
|
---|
| 499 |
|
---|
| 500 | for (rp = restab; rp->r_name; rp++)
|
---|
| 501 | if (strcmp(rp->r_name, n) == 0)
|
---|
| 502 | return(rp->r_val);
|
---|
| 503 | return(0);
|
---|
| 504 | }
|
---|
| 505 |
|
---|
| 506 | static struct op *
|
---|
| 507 | newtp()
|
---|
| 508 | {
|
---|
| 509 | register struct op *t;
|
---|
| 510 |
|
---|
| 511 | t = (struct op *)tree(sizeof(*t));
|
---|
| 512 | t->type = 0;
|
---|
| 513 | t->words = NULL;
|
---|
| 514 | t->ioact = NULL;
|
---|
| 515 | t->left = NULL;
|
---|
| 516 | t->right = NULL;
|
---|
| 517 | t->str = NULL;
|
---|
| 518 | return(t);
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 | static struct op *
|
---|
| 522 | namelist(t)
|
---|
| 523 | register struct op *t;
|
---|
| 524 | {
|
---|
| 525 | if (iolist) {
|
---|
| 526 | iolist = addword((char *)NULL, iolist);
|
---|
| 527 | t->ioact = copyio();
|
---|
| 528 | } else
|
---|
| 529 | t->ioact = NULL;
|
---|
| 530 | if (t->type != TCOM) {
|
---|
| 531 | if (t->type != TPAREN && t->ioact != NULL) {
|
---|
| 532 | t = block(TPAREN, t, NOBLOCK, NOWORDS);
|
---|
| 533 | t->ioact = t->left->ioact;
|
---|
| 534 | t->left->ioact = NULL;
|
---|
| 535 | }
|
---|
| 536 | return(t);
|
---|
| 537 | }
|
---|
| 538 | word(NOWORD);
|
---|
| 539 | t->words = copyw();
|
---|
| 540 | return(t);
|
---|
| 541 | }
|
---|
| 542 |
|
---|
| 543 | static char **
|
---|
| 544 | copyw()
|
---|
| 545 | {
|
---|
| 546 | register char **wd;
|
---|
| 547 |
|
---|
| 548 | wd = getwords(wdlist);
|
---|
| 549 | wdlist = 0;
|
---|
| 550 | return(wd);
|
---|
| 551 | }
|
---|
| 552 |
|
---|
| 553 | static void
|
---|
| 554 | word(cp)
|
---|
| 555 | char *cp;
|
---|
| 556 | {
|
---|
| 557 | wdlist = addword(cp, wdlist);
|
---|
| 558 | }
|
---|
| 559 |
|
---|
| 560 | static struct ioword **
|
---|
| 561 | copyio()
|
---|
| 562 | {
|
---|
| 563 | register struct ioword **iop;
|
---|
| 564 |
|
---|
| 565 | iop = (struct ioword **) getwords(iolist);
|
---|
| 566 | iolist = 0;
|
---|
| 567 | return(iop);
|
---|
| 568 | }
|
---|
| 569 |
|
---|
| 570 | static struct ioword *
|
---|
| 571 | io(u, f, cp)
|
---|
| 572 | int u;
|
---|
| 573 | int f;
|
---|
| 574 | char *cp;
|
---|
| 575 | {
|
---|
| 576 | register struct ioword *iop;
|
---|
| 577 |
|
---|
| 578 | iop = (struct ioword *) tree(sizeof(*iop));
|
---|
| 579 | iop->io_unit = u;
|
---|
| 580 | iop->io_flag = f;
|
---|
| 581 | iop->io_name = cp;
|
---|
| 582 | iolist = addword((char *)iop, iolist);
|
---|
| 583 | return(iop);
|
---|
| 584 | }
|
---|
| 585 |
|
---|
| 586 | static void
|
---|
| 587 | zzerr()
|
---|
| 588 | {
|
---|
| 589 | yyerror("syntax error");
|
---|
| 590 | }
|
---|
| 591 |
|
---|
| 592 | void
|
---|
| 593 | yyerror(s)
|
---|
| 594 | char *s;
|
---|
| 595 | {
|
---|
| 596 | yynerrs++;
|
---|
| 597 | if (talking && e.iop <= iostack) {
|
---|
| 598 | multiline = 0;
|
---|
| 599 | while (eofc() == 0 && yylex(0) != '\n')
|
---|
| 600 | ;
|
---|
| 601 | }
|
---|
| 602 | err(s);
|
---|
| 603 | fail();
|
---|
| 604 | }
|
---|
| 605 |
|
---|
| 606 | static int
|
---|
| 607 | yylex(cf)
|
---|
| 608 | int cf;
|
---|
| 609 | {
|
---|
| 610 | register int c, c1;
|
---|
| 611 | int atstart;
|
---|
| 612 |
|
---|
| 613 | if ((c = peeksym) > 0) {
|
---|
| 614 | peeksym = 0;
|
---|
| 615 | if (c == '\n')
|
---|
| 616 | startl = 1;
|
---|
| 617 | return(c);
|
---|
| 618 | }
|
---|
| 619 | nlseen = 0;
|
---|
| 620 | e.linep = line;
|
---|
| 621 | atstart = startl;
|
---|
| 622 | startl = 0;
|
---|
| 623 | yylval.i = 0;
|
---|
| 624 |
|
---|
| 625 | loop:
|
---|
| 626 | while ((c = getc(0)) == ' ' || c == '\t')
|
---|
| 627 | ;
|
---|
| 628 | switch (c) {
|
---|
| 629 | default:
|
---|
| 630 | if (any(c, "0123456789")) {
|
---|
| 631 | unget(c1 = getc(0));
|
---|
| 632 | if (c1 == '<' || c1 == '>') {
|
---|
| 633 | iounit = c - '0';
|
---|
| 634 | goto loop;
|
---|
| 635 | }
|
---|
| 636 | *e.linep++ = c;
|
---|
| 637 | c = c1;
|
---|
| 638 | }
|
---|
| 639 | break;
|
---|
| 640 |
|
---|
| 641 | case '#':
|
---|
| 642 | while ((c = getc(0)) != 0 && c != '\n')
|
---|
| 643 | ;
|
---|
| 644 | unget(c);
|
---|
| 645 | goto loop;
|
---|
| 646 |
|
---|
| 647 | case 0:
|
---|
| 648 | return(c);
|
---|
| 649 |
|
---|
| 650 | case '$':
|
---|
| 651 | *e.linep++ = c;
|
---|
| 652 | if ((c = getc(0)) == '{') {
|
---|
| 653 | if ((c = collect(c, '}')) != '\0')
|
---|
| 654 | return(c);
|
---|
| 655 | goto pack;
|
---|
| 656 | }
|
---|
| 657 | break;
|
---|
| 658 |
|
---|
| 659 | case '`':
|
---|
| 660 | case '\'':
|
---|
| 661 | case '"':
|
---|
| 662 | if ((c = collect(c, c)) != '\0')
|
---|
| 663 | return(c);
|
---|
| 664 | goto pack;
|
---|
| 665 |
|
---|
| 666 | case '|':
|
---|
| 667 | case '&':
|
---|
| 668 | case ';':
|
---|
| 669 | if ((c1 = dual(c)) != '\0') {
|
---|
| 670 | startl = 1;
|
---|
| 671 | return(c1);
|
---|
| 672 | }
|
---|
| 673 | startl = 1;
|
---|
| 674 | return(c);
|
---|
| 675 | case '^':
|
---|
| 676 | startl = 1;
|
---|
| 677 | return('|');
|
---|
| 678 | case '>':
|
---|
| 679 | case '<':
|
---|
| 680 | diag(c);
|
---|
| 681 | return(c);
|
---|
| 682 |
|
---|
| 683 | case '\n':
|
---|
| 684 | nlseen++;
|
---|
| 685 | gethere();
|
---|
| 686 | startl = 1;
|
---|
| 687 | if (multiline || cf & CONTIN) {
|
---|
| 688 | if (talking && e.iop <= iostack)
|
---|
| 689 | prs(cprompt->value);
|
---|
| 690 | if (cf & CONTIN)
|
---|
| 691 | goto loop;
|
---|
| 692 | }
|
---|
| 693 | return(c);
|
---|
| 694 |
|
---|
| 695 | case '(':
|
---|
| 696 | case ')':
|
---|
| 697 | startl = 1;
|
---|
| 698 | return(c);
|
---|
| 699 | }
|
---|
| 700 |
|
---|
| 701 | unget(c);
|
---|
| 702 |
|
---|
| 703 | pack:
|
---|
| 704 | while ((c = getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n"))
|
---|
| 705 | if (e.linep >= elinep)
|
---|
| 706 | err("word too long");
|
---|
| 707 | else
|
---|
| 708 | *e.linep++ = c;
|
---|
| 709 | unget(c);
|
---|
| 710 | if(any(c, "\"'`$"))
|
---|
| 711 | goto loop;
|
---|
| 712 | *e.linep++ = '\0';
|
---|
| 713 | if (atstart && (c = rlookup(line))!=0) {
|
---|
| 714 | startl = 1;
|
---|
| 715 | return(c);
|
---|
| 716 | }
|
---|
| 717 | yylval.cp = strsave(line, areanum);
|
---|
| 718 | return(WORD);
|
---|
| 719 | }
|
---|
| 720 |
|
---|
| 721 | int
|
---|
| 722 | collect(c, c1)
|
---|
| 723 | register c, c1;
|
---|
| 724 | {
|
---|
| 725 | char s[2];
|
---|
| 726 |
|
---|
| 727 | *e.linep++ = c;
|
---|
| 728 | while ((c = getc(c1)) != c1) {
|
---|
| 729 | if (c == 0) {
|
---|
| 730 | unget(c);
|
---|
| 731 | s[0] = c1;
|
---|
| 732 | s[1] = 0;
|
---|
| 733 | prs("no closing "); yyerror(s);
|
---|
| 734 | return(YYERRCODE);
|
---|
| 735 | }
|
---|
| 736 | if (talking && c == '\n' && e.iop <= iostack)
|
---|
| 737 | prs(cprompt->value);
|
---|
| 738 | *e.linep++ = c;
|
---|
| 739 | }
|
---|
| 740 | *e.linep++ = c;
|
---|
| 741 | return(0);
|
---|
| 742 | }
|
---|
| 743 |
|
---|
| 744 | int
|
---|
| 745 | dual(c)
|
---|
| 746 | register c;
|
---|
| 747 | {
|
---|
| 748 | char s[3];
|
---|
| 749 | register char *cp = s;
|
---|
| 750 |
|
---|
| 751 | *cp++ = c;
|
---|
| 752 | *cp++ = getc(0);
|
---|
| 753 | *cp = 0;
|
---|
| 754 | if ((c = rlookup(s)) == 0)
|
---|
| 755 | unget(*--cp);
|
---|
| 756 | return(c);
|
---|
| 757 | }
|
---|
| 758 |
|
---|
| 759 | static void
|
---|
| 760 | diag(ec)
|
---|
| 761 | register int ec;
|
---|
| 762 | {
|
---|
| 763 | register int c;
|
---|
| 764 |
|
---|
| 765 | c = getc(0);
|
---|
| 766 | if (c == '>' || c == '<') {
|
---|
| 767 | if (c != ec)
|
---|
| 768 | zzerr();
|
---|
| 769 | yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE;
|
---|
| 770 | c = getc(0);
|
---|
| 771 | } else
|
---|
| 772 | yylval.i = ec == '>'? IOWRITE: IOREAD;
|
---|
| 773 | if (c != '&' || yylval.i == IOHERE)
|
---|
| 774 | unget(c);
|
---|
| 775 | else
|
---|
| 776 | yylval.i |= IODUP;
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 | static char *
|
---|
| 780 | tree(size)
|
---|
| 781 | unsigned size;
|
---|
| 782 | {
|
---|
| 783 | register char *t;
|
---|
| 784 |
|
---|
| 785 | if ((t = getcell(size)) == NULL) {
|
---|
| 786 | prs("command line too complicated\n");
|
---|
| 787 | fail();
|
---|
| 788 | /* NOTREACHED */
|
---|
| 789 | }
|
---|
| 790 | return(t);
|
---|
| 791 | }
|
---|
| 792 |
|
---|
| 793 | /* VARARGS1 */
|
---|
| 794 | /* ARGSUSED */
|
---|
| 795 | void
|
---|
| 796 | printf(s) /* yyparse calls it */
|
---|
| 797 | char *s;
|
---|
| 798 | {
|
---|
| 799 | }
|
---|
| 800 |
|
---|