Last change: 2014-12-30
Bournegol???
... To fix it, first get the source, and then change it in the obvious three places in xec.c. You will have to learn Bournegol [the ALGOL-like dialect of C that Steve Bourne used to write the original Bourne shell-JP ]. Another alternative is to replace /bin/sh with one of the free sh look-alikes... (CT in comp.unix.questions on Usenet, 20 February 1990)
(many years later I found this paper, A Partial Tour Through the UNIX Shell, which makes for very nice reading). Ok, without any further ado, here is an excerpt of the file xec.c , referenced above, supposedly from the 7th Edition UNIX, that gives you an impression of bournegol:
LOCAL INT parent; SYSTAB commands; /* ======== command execution ========*/ execute(argt, execflg, pf1, pf2) TREPTR argt; INT *pf1, *pf2; { /* `stakbot' is preserved by this routine */ REG TREPTR t; STKPTR sav=savstak(); sigchk(); IF (t=argt) ANDF execbrk==0 THEN REG INT treeflgs; INT oldexit, type; REG STRING *com; treeflgs = t->tretyp; type = treeflgs&COMMSK; oldexit=exitval; exitval=0; SWITCH type IN case TCOM: BEGIN STRING a1; INT argn, internal; ARGPTR schain=gchain; IOPTR io=t->treio; gchain=0; argn = getarg(t); com=scan(argn); a1=com[1]; gchain=schain; IF (internal=syslook(com[0],commands)) ORF argn==0 THEN setlist(t->comset, 0); FI IF argn ANDF (flags&noexec)==0 THEN /* print command if execpr */ IF flags&execpr THEN argn=0; prs(execpmsg); WHILE com[argn]!=ENDARGS DO prs(com[argn++]); blank() OD newline(); FI SWITCH internal IN case SYSDOT: IF a1 THEN REG INT f; IF (f=pathopen(getpath(a1), a1)) < 0 THEN failed(a1,notfound); ELSE execexp(0,f); FI FI break; case SYSTIMES: { L_INT t[4]; times(t); prt(t[2]); blank(); prt(t[3]); newline(); } break; case SYSEXIT: exitsh(a1?stoi(a1):oldexit);
case SYSTRAP: IF a1 THEN BOOL clear; IF (clear=digit(*a1))==0 THEN ++com; FI WHILE *++com DO INT i; IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP THEN failed(*com,badtrap); ELIF clear THEN clrsig(i); ELSE replace(&trapcom[i],a1); IF *a1 THEN getsig(i); ELSE ignsig(i); FI FI OD ELSE /* print out current traps */ INT i; FOR i=0; i<MAXTRAP; i++ DO IF trapcom[i] THEN prn(i); prs(colon); prs(trapcom[i]); newline(); FI OD FI break;
case TFORK: IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 THEN parent=0; ELSE WHILE (parent=fork()) == -1 DO sigchk(); alarm(10); pause() OD FI IF parent THEN /* This is the parent branch of fork; */ /* it may or may not wait for the child. */ IF treeflgs&FPRS ANDF flags&ttyflg THEN prn(parent); newline(); FI IF treeflgs&FPCL THEN closepipe(pf1) FI IF (treeflgs&(FAMP|FPOU))==0 THEN await(parent); ELIF (treeflgs&FAMP)==0 THEN post(parent); ELSE assnum(&pcsadr, parent); FI chktrap(); break;
(Note the single use of curly braces after case SYSTIMES . This and the lowercase case let me believe this segment might have been added at a later stage). The necesssary macro definitions to understand (if you dare to try) the above excerpt can be found in the file mac.h :
/* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #define LOCAL static #define PROC extern #define TYPE typedef #define STRUCT TYPE struct #define UNION TYPE union #define REG register #define IF if( #define THEN ){ #define ELSE } else { #define ELIF } else if ( #define FI ;} #define BEGIN { #define END } #define SWITCH switch( #define IN ){ #define ENDSW } #define FOR for( #define WHILE while( #define DO ){ #define OD ;} #define REP do_lbr #define PER }while( #define DONE ); #define LOOP for(;;){ #define POOL } #define SKIP ; #define DIV / #define REM % #define NEQ ^ #define ANDF && #define ORF || #define TRUE (-1) #define FALSE 0 #define LOBYTE 0377 #define STRIP 0177 #define QUOTE 0200 #define EOF 0 #define NL '
' #define SP ' ' #define LQ '`' #define RQ '\'' #define MINUS '-' #define COLON ':' #define MAX(a,b) ((a)>(b)?(a):(b))
... continue reading