|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 5833 (0x16c9) Types: TextFile Notes: UNIX file Names: »sh.y«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/rsh/sh.y« └─⟦this⟧ »cmd/sh/sh.y«
/* * The Bourne shell. * This shell is dedicated to Ciaran Gerald Aidan O'Donnell. * May he live a thousand minutes. (long enough to fix up YACC). * It is also dedicated to Steve Bourne. * May he live a thousand seconds. */ %{ #include "sh.h" #define YYERROR {yyerrflag=1; goto YYerract; } extern NODE *node(); %} %union { NODE *yu_node; char *yu_strp; int yu_nval; } %token _NULL _DSEMI _ANDF _ORF _NAME _IORS _ASGN %token _CASE _DO _DONE _ELIF _ELSE _ESAC _FI _FOR _IF _IN _THEN %token _UNTIL _WHILE _OBRAC _CBRAC %type <yu_node> command_line command_list logical_command %type <yu_node> pipe_command command argument_list %type <yu_node> argument control in_name_list %type <yu_node> name_list case_list case_line %type <yu_node> pattern_list do_list else_part %type <yu_node> command_sequence opt_command_sequence %type <yu_node> sub_shell %type <yu_strp> redirect name asgn %type <yu_nval> whuntile %% session: session command_line | ; command_line: '\n' { sesp->s_node = NULL; reset(RCMD); NOTREACHED; } | command_list '\n' { sesp->s_node = $1; reset(errflag ? RERR : RCMD); NOTREACHED; } | error '\n' { keyflush(); keyflag = 1; reset(RERR); NOTREACHED; } ; if: _IF optnls ; then: _THEN optnls ; elif: _ELIF optnls ; else: _ELSE optnls ; whuntile: _WHILE optnls { $$ = NWHILE; } | _UNTIL optnls { $$ = NUNTIL; } ; do: _DO optnls | _DO ';' optnls ; oror: _ORF optnls; andand: _ANDF optnls; or: '|' optnls; oparen: '(' optnls ; obrack: _OBRAC optnls ; cparen: ')' optnls ; dsemi: _DSEMI optnls ; command_list: logical_command { $$ = $1; } | logical_command '&' { $$ = node(NBACK, $1, NULL); } | logical_command ';' { $$ = $1; } | logical_command '&' command_list { $$ = node(NBACK, $1, $3); } | logical_command ';' command_list { $$ = node(NLIST, $1, $3); } ; logical_command: pipe_command { $$ = $1; } | pipe_command oror logical_command { $$ = node(NORF, $1, $3); } | pipe_command andand logical_command { $$ = node(NANDF, $1, $3); } ; pipe_command: command or pipe_command { $$ = node(NPIPE, $1, $3); } | command { $$ = $1; } ; command: argument_list_init argument_list { $$ = node(NCOMS, $2, NULL); keypop(); } ; argument_list_init: { keypush(); keyflag = 1; } ; argument_list: argument argument_list { if (($1->n_type == NCTRL && $2->n_type == NARGS) || ($1->n_type == NARGS && $2->n_type == NCTRL)) { YYERROR; } ($$ = $1)->n_next = $2; } | argument { $$ = $1; } ; argument: redirect { $$ = node(NIORS, $1, NULL); } | name { $$ = node(NARGS, $1, NULL); keyflag = 0; } | asgn { $$ = node(NASSG, $1, NULL); } | control { if ( ! keyflag) { YYERROR; } $$ = node(NCTRL, $1, NULL); keyflag = 0; } ; redirect: _IORS { $$ = duplstr(strt, 0); } ; name: _NAME { $$ = duplstr(strt, 0); } ; asgn: _ASGN { $$ = duplstr(strt, 0); } ; control: _FOR name in_name_list sep do_list _DONE { $$ = node(NFOR, $2, node(NFOR2, $3, node(NLIST, $5, NULL))); $$->n_next->n_next->n_next = $$->n_next; } | _CASE name _IN sep case_list _ESAC { $$ = node(NCASE, $2, $5); } | whuntile command_sequence do_list _DONE { $$ = node($1, $2, node(NLIST, $3, NULL)); $$->n_next->n_next = $$; } | if command_sequence then opt_command_sequence else_part _FI { $$ = node(NIF, node(NNULL, $2, $4), $5); } | oparen opt_command_sequence ')' { $$ = node(NPARN, $2, NULL); } | obrack opt_command_sequence _CBRAC { $$ = node(NBRAC, $2, NULL); } ; in_name_list: _IN name_list { $$ = $2; } | { $$ = node(NARGS, "\"$@\"", NULL); } ; name_list: name name_list { $$ = node(NARGS, $1, $2); } | { $$ = NULL; } ; case_list: case_line dsemi case_list { register NODE *np; for (np=$1; np->n_next; np=np->n_next); np->n_next = $3; $$ = $1; } | case_line { $$ = $1; } | { $$ = NULL; } ; case_line: pattern_list cparen opt_command_sequence { $$ = node(NCASE2, $3, $1); } ; pattern_list: name '|' pattern_list { $$ = node(NCASE3, $1, $3); } | name { $$ = node(NCASE3, $1, NULL); } ; do_list: do opt_command_sequence { $$ = $2; } | { $$ = NULL; } ; else_part: elif command_sequence then opt_command_sequence else_part { $$ = node(NIF, node(NULL, $2, $4), $5); } | else opt_command_sequence { $$ = node(NELSE, $2, NULL); } | { $$ = NULL; } ; opt_command_sequence: command_sequence { $$ = $1; } | { $$ = NULL; } ; command_sequence: command_list nls command_sequence { $$ = node(NLIST, $1, $3); } | command_list optnls { $$ = $1; } ; sep: nls | ';' | ';' nls ; optnls: nls | ; nls: '\n' | nls '\n' ; %% /* * Create a node. */ NODE * node(type, auxp, next) NODE *auxp, *next; { register NODE *np; np = (NODE *) balloc(sizeof (NODE)); np->n_type = type; np->n_auxp = auxp; np->n_next = next; return (np); } #define NBPC 8 #define NKEY 8 static char keys[NKEY] = { 0 }; static int keyi = NKEY * NBPC; keyflush() { register char *kp; for (kp = keys+NKEY; kp > keys; *--kp = 0); keyi = NKEY * NBPC; } keypop() { register char *kp; register int km; if ((km = keyi++) >= NKEY * NBPC) { panic(); NOTREACHED; } kp = keys + (km / NBPC); km = 1 << (km %= NBPC); keyflag = (*kp & km) ? 1 : 0; *kp &= ~km; } keypush() { register char *kp; register int km; if ((km = --keyi) < 0) { panic(); NOTREACHED; } if (keyflag) { kp = keys + (km / NBPC); km = 1 << (km %= NBPC); *kp |= km; } } /* * The following fragments might implement named pipes. * The token declaration goes in the header. * The nopen production should go with the others of its ilk. * The production fragment goes into argument: %token _NOPEN _NCLOSE nopen: _NOPEN optnls ; | nopen pipe_command ')' { $$ = node(NRPIPE, $2, NULL); } | oparen pipe_command _NCLOSE { $$ = node(NWPIPE, $2, NULL); } * */