From sources-request@genrad.UUCP Mon Jun 10 07:12:40 1985 Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site seismo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: seismo!cbosgd!ulysses!allegra!mit-eddie!genrad!sources-request From: sources-request@genrad.UUCP Newsgroups: mod.sources Subject: Bourne shell history + tilde + job control + more (Part 3 of 9) Message-ID: <881@genrad.UUCP> Date: 10 Jun 85 11:12:40 GMT Date-Received: 10 Jun 85 23:11:40 GMT Sender: john@genrad.UUCP Lines: 2391 Approved: john@genrad.UUCP From: Arnold Robbins This is part 3 of 9. It contains the second set of code diffs for the BSD Bourne shell. Arnold Robbins arnold@gatech.{UUCP, CSNET} ------------------- tear here -------------------- :::::::: name.c ::::::: *** ../orig.u/name.c Wed May 15 17:13:45 1985 --- name.c Tue Jun 4 14:43:24 1985 *************** *** 16,21 PROC BOOL chkid(); NAMNOD ps2nod = { NIL, NIL, ps2name}, fngnod = { NIL, NIL, fngname}, pathnod = { NIL, NIL, pathname}, --- 16,25 ----- PROC BOOL chkid(); + #if pyr + NAMNOD ps2nod = { NIL, &univnod, ps2name}, + univnod = { NIL, NIL, univname}, + #else NAMNOD ps2nod = { NIL, NIL, ps2name}, #endif fngnod = { NIL, NIL, fngname}, *************** *** 17,22 NAMNOD ps2nod = { NIL, NIL, ps2name}, fngnod = { NIL, NIL, fngname}, pathnod = { NIL, NIL, pathname}, ifsnod = { NIL, NIL, ifsname}, --- 21,27 ----- univnod = { NIL, NIL, univname}, #else NAMNOD ps2nod = { NIL, NIL, ps2name}, + #endif fngnod = { NIL, NIL, fngname}, pathnod = { NIL, NIL, pathname}, ifsnod = { NIL, NIL, ifsname}, *************** *** 21,28 pathnod = { NIL, NIL, pathname}, ifsnod = { NIL, NIL, ifsname}, ps1nod = { &pathnod, &ps2nod, ps1name}, ! homenod = { &fngnod, &ifsnod, homename}, ! mailnod = { &homenod, &ps1nod, mailname}; NAMPTR namep = &mailnod; --- 26,34 ----- pathnod = { NIL, NIL, pathname}, ifsnod = { NIL, NIL, ifsname}, ps1nod = { &pathnod, &ps2nod, ps1name}, ! homenod = { &histfnod, &ifsnod, homename}, ! mailnod = { &homenod, &ps1nod, mailname}, ! histfnod = { &fngnod, NIL, histfilename}; NAMPTR namep = &mailnod; *************** *** 38,43 REG SYSPTR syscan; syscan=syswds; first = *w; WHILE s=syscan->sysnam DO IF first == *s --- 44,50 ----- REG SYSPTR syscan; syscan=syswds; first = *w; + IF *w == 0 THEN return (0) FI WHILE s=syscan->sysnam DO IF first == *s *************** *** 129,135 THEN f->fsiz=1; FI ! LOOP c=nextc(0); IF (*names ANDF any(c, ifsnod.namval)) ORF eolchar(c) THEN zerostak(); assign(n,absstak(rel)); setstak(rel); --- 136,145 ----- THEN f->fsiz=1; FI ! ! /* strip any leading IFS characters */ ! WHILE (any((c=nextc(0)), ifsnod.namval)) ANDF !(eolchar(c)) DONE ! LOOP IF (*names ANDF any(c, ifsnod.namval)) ORF eolchar(c) THEN zerostak(); assign(n,absstak(rel)); setstak(rel); *************** *** 139,144 FI IF eolchar(c) THEN break; FI ELSE pushstak(c); FI --- 149,157 ----- FI IF eolchar(c) THEN break; + ELSE /* strip imbedded IFS characters */ + WHILE (any((c=nextc(0)), ifsnod.namval)) ANDF + !(eolchar(c)) DONE FI ELSE pushstak(c); c = nextc(0); *************** *** 141,146 THEN break; FI ELSE pushstak(c); FI POOL WHILE n --- 154,166 ----- !(eolchar(c)) DONE FI ELSE pushstak(c); + c = nextc(0); + IF eolchar(c) + THEN + STKPTR top = staktop; + WHILE any (*(--top), ifsnod.namval) DONE + staktop = top + 1; + FI FI POOL WHILE n :::::::: name.h ::::::: No differences encountered :::::::: print.c ::::::: *** ../orig.u/print.c Wed May 15 17:13:45 1985 --- print.c Mon Jun 3 11:05:42 1985 *************** *** 15,20 CHAR numbuf[6]; /* printing and io conversion */ --- 15,27 ----- CHAR numbuf[6]; + #ifndef TAB + /* emulate buffered i/o in later versions of the shell (sigh) */ + prc_buff(c) + char c; + { + prc(c); + } prs_buff (s) char *s; *************** *** 16,21 CHAR numbuf[6]; /* printing and io conversion */ newline() --- 23,45 ----- prc(c); } + prs_buff (s) + char *s; + { + prs (s); + } + + prn_buff (n) + int n; + { + prn (n); + } + + flushb () + { + } + #endif + /* printing and io conversion */ newline() *************** *** 99,101 FI } --- 123,229 ----- FI } + void + pr_prompt (str) + register char *str; + { + for (; *str; str++) + { + if (*str != '%') + prc_buff (*str); + #ifdef notdef + /* BSD does not have pwd built in, sorry */ + else if (*(str+1) == 'd') + { + /* current directory */ + str++; + prs_buff (retcwd()); + } + #endif + else if (*(str+1) == 'e') + { + /* event count */ + str++; + if ((flags & nohistflg) == 0) + prn_buff (event_count); + } + else if (*(str+1) == 'h') + { + /* hostname */ + static char *cp = 0; + static int didhost = FALSE; + static int didgt = FALSE; + static char buf[257]; + + if (! didhost) + { + gethostname (buf, sizeof buf); + didhost = TRUE; + cp = buf; + } + #ifdef GATECH + /* + * this is to get rid of the dumb gt- convention. + * a gt w/out the - is also removed. + */ + if (! didgt) + { + didgt = TRUE; + if (cp[0] == 'g' && cp[1] == 't' && cp[2]) + { + cp += 2; + if (cp[0] == '-' && cp[1]) + cp++; + } + } + #endif + prs_buff (cp); + str++; + } + else if (*(str+1) == 'l') + { + /* login name */ + static char *cp = 0; + static int didname = FALSE; + + str++; + if (! didname) + { + cp = username (); + didname = TRUE; + } + + if (cp) + prs_buff (cp); + } + else if (*(str+1) == 't') + { + /* current time, HH:MM */ + long l; + char *cp, *ctime (); + + str++; + time (& l); + cp = ctime (& l); + cp[16] = '\0'; + cp += 11; + prs_buff (cp); + } + #if pyr + else if (*(str+1) == 'u') + { + /* current univeserse */ + str++; + prs_buff (univ_name[cur_univ-1]); + } + #endif + else if (*(str+1) == '\0') /* % was last char in string */ + { + prc_buff (*str); + continue; + } + else + prc_buff (*(++str)); + } + flushb(); + } :::::::: service.c ::::::: *** ../orig.u/service.c Wed May 15 17:13:46 1985 --- service.c Tue Jun 4 15:06:44 1985 *************** *** 12,17 */ #include "defs.h" PROC VOID gsort(); --- 12,20 ----- */ #include "defs.h" + #if JOBS + #include + #endif PROC VOID gsort(); *************** *** 43,50 ion=mactrim(iop->ioname); IF *ion ANDF (flags&noexec)==0 THEN IF iof&IODOC ! THEN subst(chkopen(ion),(fd=tmpfil())); ! close(fd); fd=chkopen(tmpout); unlink(tmpout); ELIF iof&IOMOV THEN IF eq(minus,ion) THEN fd = -1; --- 46,57 ----- ion=mactrim(iop->ioname); IF *ion ANDF (flags&noexec)==0 THEN IF iof&IODOC ! THEN TEMPBLK tb; ! subst(chkopen(ion),(fd=tmpfil(&tb))); ! poptemp(); /* pushed in tmpfil -- ! bug fix for problems with ! in-line scripts */ ! fd=chkopen(tmpout); unlink(tmpout); ELIF iof&IOMOV THEN IF eq(minus,ion) THEN fd = -1; *************** *** 53,58 THEN failed(ion,badfile); ELSE fd=dup(fd); FI ELIF (iof&IOPUT)==0 THEN fd=chkopen(ion); ELIF flags&rshflg --- 60,69 ----- THEN failed(ion,badfile); ELSE fd=dup(fd); FI + ELIF iof&IORDW + THEN IF (fd=open(ion, 2)) < 0 + THEN failed(ion, badopen); + FI ELIF (iof&IOPUT)==0 THEN fd=chkopen(ion); ELIF flags&rshflg *************** *** 69,74 FI } STRING getpath(s) STRING s; { --- 80,96 ----- FI } + STRING simple (s) + REG STRING s; + { + STRING save = s; + + FOR ; *s; s++ + DO IF *s == '/' THEN save = s; FI + OD + return (*save == '/' ? ++save : save); + } + STRING getpath(s) STRING s; { *************** *** 73,79 STRING s; { REG STRING path; ! IF any('/',s) THEN IF flags&rshflg THEN failed(s, restricted); ELSE return(nullstr); --- 95,101 ----- STRING s; { REG STRING path; ! IF any('/',s) ORF any(('/'|QUOTE), s) THEN IF flags&rshflg THEN failed(s, restricted); ELSE return(nullstr); *************** *** 101,106 /* leaves result on top of stack */ REG STRING scanp = path, argp = locstak(); WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD IF scanp!=path THEN *argp++='/' FI --- 123,129 ----- /* leaves result on top of stack */ REG STRING scanp = path, argp = locstak(); + STRING save = argp, cp; WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD *argp = '\0'; *************** *** 103,108 argp = locstak(); WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD IF scanp!=path THEN *argp++='/' FI IF *scanp==COLON THEN scanp++ FI path=(*scanp ? scanp : 0); scanp=name; --- 126,137 ----- STRING save = argp, cp; WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD + *argp = '\0'; + /* try a tilde expansion */ + IF *save == SQUIGGLE ANDF (cp = homedir(save+1)) != nullstr + THEN movstr(cp, save); + argp = save + length (save) - 1; + FI IF scanp!=path THEN *argp++='/' FI IF *scanp==COLON THEN scanp++ FI path=(*scanp ? scanp : 0); scanp=name; *************** *** 149,165 close(output); output=2; input=chkopen(p); - /* band aid to get csh... 2/26/79 */ - { - char c; - if (!isatty(input)) { - read(input, &c, 1); - if (c == '#') - gocsh(t, p, xecenv); - lseek(input, (long) 0, 0); - } - } - /* set up new args */ setargs(t); longjmp(subshell,1); --- 178,183 ----- close(output); output=2; input=chkopen(p); /* set up new args */ setargs(t); longjmp(subshell,1); *************** *** 180,200 ENDSW } - gocsh(t, cp, xecenv) - register char **t, *cp, **xecenv; - { - char **newt[1000]; - register char **p; - register int i; - - for (i = 0; t[i]; i++) - newt[i+1] = t[i]; - newt[i+1] = 0; - newt[0] = "/bin/csh"; - newt[1] = cp; - execve("/bin/csh", newt, xecenv); - } - /* for processes to be waited for */ #define MAXP 20 LOCAL INT pwlist[MAXP]; --- 198,203 ----- ENDSW } /* for processes to be waited for */ #define MAXP 20 LOCAL INT pwlist[MAXP]; *************** *** 200,205 LOCAL INT pwlist[MAXP]; LOCAL INT pwc; postclr() { REG INT *pw = pwlist; --- 203,247 ----- LOCAL INT pwlist[MAXP]; LOCAL INT pwc; + #if JOBS + LOCAL INT *wf_pwlist; + LOCAL INT wf_pwc; + + VOID set_wfence() + { + wf_pwlist = &pwlist[pwc]; + wf_pwc = 0; + } + + BOOL unpost (pcsid) + INT pcsid; + { + REG INT *pw = pwlist; + + IF pcsid + THEN WHILE pw <= &pwlist[pwc] + DO IF pcsid == *pw + THEN + IF pw >= wf_pwlist + THEN wf_pwc--; /* DAG -- bug fix */ + ELSE wf_pwlist--; + FI + WHILE pw <= &pwlist[pwc] + DO *pw = pw[1]; + pw++; + OD + pw[pwc] = 0; + pwc--; + return TRUE; + FI + pw++; + OD + return FALSE; + ELSE return TRUE; + FI + } + #endif + postclr() { REG INT *pw = pwlist; *************** *** 205,211 REG INT *pw = pwlist; WHILE pw <= &pwlist[pwc] ! DO *pw++ = 0 OD pwc=0; } --- 247,258 ----- REG INT *pw = pwlist; WHILE pw <= &pwlist[pwc] ! DO ! #if JOBS ! j_child_clear(*pw); ! #endif ! *pw++ = 0; ! OD pwc=0; } *************** *** 215,221 REG INT *pw = pwlist; IF pcsid ! THEN WHILE *pw DO pw++ OD IF pwc >= MAXP-1 THEN pw--; ELSE pwc++; --- 262,274 ----- REG INT *pw = pwlist; IF pcsid ! THEN WHILE *pw ! DO ! #if JOBS ! IF pcsid == *pw THEN return FI ! #endif ! pw++; ! OD IF pwc >= MAXP-1 THEN pw--; ELSE pwc++; *************** *** 219,224 IF pwc >= MAXP-1 THEN pw--; ELSE pwc++; FI *pw = pcsid; FI --- 272,280 ----- IF pwc >= MAXP-1 THEN pw--; ELSE pwc++; + #if JOBS + wf_pwc++; + #endif FI *pw = pcsid; FI *************** *** 224,231 FI } ! VOID await(i) ! INT i; { INT rc=0, wx=0; INT w; --- 280,287 ----- FI } ! VOID await(i, bckg) ! INT i, bckg; { #if JOBS #include *************** *** 227,232 VOID await(i) INT i; { INT rc=0, wx=0; INT w; INT ipwc = pwc; --- 283,293 ----- VOID await(i, bckg) INT i, bckg; { + #if JOBS + #include + #include + struct rusage ru; + #endif INT rc=0, wx=0; INT w; INT ipwc = pwc; *************** *** 230,235 INT rc=0, wx=0; INT w; INT ipwc = pwc; post(i); WHILE pwc --- 291,298 ----- INT rc=0, wx=0; INT w; INT ipwc = pwc; + #if JOBS + BOOL update_only = i == -2; IF update_only THEN i = -1 FI IF (flags&jobflg) == 0 ORF i != -1 *************** *** 231,236 INT w; INT ipwc = pwc; post(i); WHILE pwc DO REG INT p; --- 294,303 ----- #if JOBS BOOL update_only = i == -2; + IF update_only THEN i = -1 FI + IF (flags&jobflg) == 0 ORF i != -1 + THEN + #endif post(i); #if JOBS FI *************** *** 232,237 INT ipwc = pwc; post(i); WHILE pwc DO REG INT p; REG INT sig; --- 299,308 ----- THEN #endif post(i); + #if JOBS + FI + #endif + WHILE pwc #if JOBS ORF (flags&jobflg) *************** *** 233,238 post(i); WHILE pwc DO REG INT p; REG INT sig; INT w_hi; --- 304,312 ----- #endif WHILE pwc + #if JOBS + ORF (flags&jobflg) + #endif DO REG INT p; REG INT sig; INT w_hi; *************** *** 236,241 DO REG INT p; REG INT sig; INT w_hi; BEGIN REG INT *pw=pwlist; --- 310,316 ----- DO REG INT p; REG INT sig; INT w_hi; + INT found = 0; BEGIN #ifndef JOBS *************** *** 238,243 INT w_hi; BEGIN REG INT *pw=pwlist; IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; p=wait(&w); --- 313,319 ----- INT found = 0; BEGIN + #ifndef JOBS REG INT *pw=pwlist; #else IF (i == 0) ANDF (flags & jobflg) ANDF wf_pwc == 0 *************** *** 239,249 BEGIN REG INT *pw=pwlist; ! IF setjmp(INTbuf) == 0 ! THEN trapjmp[INTR] = 1; p=wait(&w); ! ELSE p = -1; ! FI ! trapjmp[INTR] = 0; WHILE pw <= &pwlist[ipwc] DO IF *pw==p THEN *pw=0; pwc--; --- 315,346 ----- BEGIN #ifndef JOBS REG INT *pw=pwlist; ! #else ! IF (i == 0) ANDF (flags & jobflg) ANDF wf_pwc == 0 ! THEN break; ! FI ! IF (pwc == 0 ANDF (flags&jobflg)) ORF update_only ! THEN IF (p = wait3(&w, WUNTRACED|WNOHANG, &ru)) == 0 ! THEN unpost(i); ! break; ! FI ! IF pwc == 0 ANDF p == -1 THEN break FI ! ELSE ! #endif ! p = wait3(&w, WUNTRACED, &ru); ! #if JOBS ! FI ! #endif ! ! IF wasintr THEN ! wasintr = 0; ! IF bckg THEN ! break; ! FI ! FI ! #if JOBS ! IF unpost(p) THEN found++ FI ! #else WHILE pw <= &pwlist[ipwc] DO IF *pw==p THEN *pw=0; pwc--; *************** *** 247,252 WHILE pw <= &pwlist[ipwc] DO IF *pw==p THEN *pw=0; pwc--; ELSE pw++; FI OD --- 344,350 ----- WHILE pw <= &pwlist[ipwc] DO IF *pw==p THEN *pw=0; pwc--; + found++; ELSE pw++; FI OD *************** *** 250,255 ELSE pw++; FI OD END IF p == -1 THEN continue FI --- 348,354 ----- ELSE pw++; FI OD + #endif END IF p == -1 THEN *************** *** 252,258 OD END ! IF p == -1 THEN continue FI w_hi = (w>>8)&LOBYTE; --- 351,370 ----- #endif END ! IF p == -1 THEN ! IF bckg THEN ! #if JOBS ! j_child_clear(i); ! unpost(i); ! #else ! REG INT *pw=pwlist; ! WHILE pw <= &pwlist[ipwc] ANDF i != *pw ! DO pw++; OD ! IF i == *pw THEN *pw = 0; pwc-- FI ! #endif ! FI ! continue; ! FI w_hi = (w>>8)&LOBYTE; *************** *** 258,265 IF sig = w&0177 THEN IF sig == 0177 /* ptrace! return */ ! THEN prs("ptrace: "); ! sig = w_hi; FI IF sysmsg[sig] THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI --- 370,384 ----- IF sig = w&0177 THEN IF sig == 0177 /* ptrace! return */ ! THEN sig = w_hi; ! #if JOBS ! IF (flags&jobflg) ANDF ! (sig==STOP ORF sig==TSTP ORF sig==TTOU ORF sig==TTIN) ! THEN j_child_stop(p, sig); ! goto j_bypass; ! FI ! #endif ! prs("ptrace: "); FI IF sysmsg[sig] THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI *************** *** 269,275 newline(); FI ! IF rc==0 THEN rc = (sig ? sig|SIGFLG : w_hi); FI wx |= w; --- 388,425 ----- newline(); FI ! #if JOBS ! IF flags&infoflg ! THEN ! register int k; ! long l; ! ! prc('['); ! l = ru.ru_utime.tv_sec * 1000000L + ru.ru_utime.tv_usec ! + ru.ru_stime.tv_sec * 1000000L + ru.ru_stime.tv_usec; ! prn((int)(l / 1000000)); /* integral seconds */ ! k = (int)(l % 1000000L) / 1000; /* thousandths */ ! prc('.'); ! if (k < 100) ! prc('0'); ! if (k < 10) ! prc('0'); ! prn(k); ! blank(); ! prn((int)ru.ru_inblock); ! blank(); ! prn((int)ru.ru_oublock); ! blank(); ! prn((int)ru.ru_minflt); ! blank(); ! prn((int)ru.ru_majflt); ! prc(']'); ! newline(); ! FI ! j_child_die(p); ! j_bypass: ! #endif ! IF rc == 0 ANDF found != 0 THEN rc = (sig ? sig|SIGFLG : w_hi); FI wx |= w; *************** *** 273,278 THEN rc = (sig ? sig|SIGFLG : w_hi); FI wx |= w; OD IF wx ANDF flags&errflg --- 423,429 ----- THEN rc = (sig ? sig|SIGFLG : w_hi); FI wx |= w; + IF p == i THEN break FI OD IF wx ANDF flags&errflg *************** *** 278,283 IF wx ANDF flags&errflg THEN exitsh(rc); FI exitval=rc; exitset(); } --- 429,435 ----- IF wx ANDF flags&errflg THEN exitsh(rc); FI + flags |= eflag; exitval=rc; exitset(); } :::::::: setbrk.c ::::::: No differences encountered :::::::: stak.c ::::::: No differences encountered :::::::: stak.h ::::::: No differences encountered :::::::: string.c ::::::: No differences encountered :::::::: sym.h ::::::: *** ../orig.u/sym.h Wed May 15 17:13:46 1985 --- sym.h Mon Jun 3 12:51:24 1985 *************** *** 46,48 #define DOLLAR '$' #define ESCAPE '\\' #define BRACE '{' --- 46,51 ----- #define DOLLAR '$' #define ESCAPE '\\' #define BRACE '{' + #if JOBS + #define PERCENT '%' + #endif :::::::: timeout.h ::::::: No differences encountered :::::::: word.c ::::::: *** ../orig.u/word.c Wed May 15 17:13:46 1985 --- word.c Thu Jun 6 14:38:18 1985 *************** *** 23,28 REG CHAR c, d; REG CHAR *argp=locstak()+BYTESPERWORD; INT alpha=1; wdnum=0; wdset=0; --- 23,29 ----- REG CHAR c, d; REG CHAR *argp=locstak()+BYTESPERWORD; INT alpha=1; + STRING save; wdnum=0; wdset=0; *************** *** 26,32 wdnum=0; wdset=0; ! WHILE (c=nextc(0), space(c)) DONE IF c=='#' THEN WHILE (c=readc()) ANDF c!=NL DONE --- 27,43 ----- wdnum=0; wdset=0; ! catcheof = TRUE; ! WHILE TRUE ! DO ! WHILE (c=nextc(0), space(c)) DONE ! IF c=='#' ! THEN WHILE (c=nextc(0)) !=NL ANDF c != EOF DONE ! peekc = c; ! ELSE break; /* out of comment - white space loop */ ! FI ! OD ! save = argp; IF !eofmeta(c) THEN REP IF c==LITERAL *************** *** 28,37 WHILE (c=nextc(0), space(c)) DONE - IF c=='#' - THEN WHILE (c=readc()) ANDF c!=NL DONE - FI - IF !eofmeta(c) THEN REP IF c==LITERAL THEN *argp++=(DQUOTE); --- 39,44 ----- OD save = argp; IF !eofmeta(c) THEN REP IF c==LITERAL THEN *argp++=(DQUOTE); *************** *** 46,51 THEN d=c; WHILE (*argp++=(c=nextc(d))) ANDF c!=d DO chkpr(c) OD FI FI PER (c=nextc(0), !eofmeta(c)) DONE --- 53,73 ----- THEN d=c; WHILE (*argp++=(c=nextc(d))) ANDF c!=d DO chkpr(c) OD + ELIF c == SQUIGGLE + THEN /* try ~login name */ + STRING name, home; + + name = argp; + WHILE (c = nextc(0)) != '/' ANDF + !eofmeta(c) + DO + *name++ = c; + OD + peekc = c; + *name = '\0'; + home = homedir(argp); + IF *home THEN movstr(home, --argp) FI + argp += length(argp) - 1; FI FI PER (c=nextc(0), !eofmeta(c)) DONE *************** *** 64,69 ELIF dipchar(c) THEN IF (d=nextc(0))==c THEN wdval = c|SYMREP; ELSE peekc = d|MARK; wdval = c; FI ELSE IF (wdval=c)==EOF --- 86,97 ----- ELIF dipchar(c) THEN IF (d=nextc(0))==c THEN wdval = c|SYMREP; + IF c == '<' + THEN IF (d=nextc(0))=='-' + THEN stripflg++; + ELSE peekc = d|MARK; + FI + FI ELSE peekc = d|MARK; wdval = c; FI ELSE IF (wdval=c)==EOF *************** *** 70,76 THEN wdval=EOFSYM; FI IF iopend ANDF eolchar(c) ! THEN copy(iopend); iopend=0; FI FI reserv=FALSE; --- 98,109 ----- THEN wdval=EOFSYM; FI IF iopend ANDF eolchar(c) ! THEN INT histon = (flags&nohistflg) == 0; ! ! flags |= nohistflg; /* no history for here docs */ ! copy(iopend); ! IF histon THEN flags &= ~nohistflg FI /* restore */ ! iopend=0; FI FI catcheof = FALSE; *************** *** 73,78 THEN copy(iopend); iopend=0; FI FI reserv=FALSE; return(wdval); } --- 106,112 ----- iopend=0; FI FI + catcheof = FALSE; reserv=FALSE; return(wdval); } *************** *** 94,99 readc() { REG CHAR c; REG INT len; REG FILE f; --- 128,134 ----- readc() { + LOCAL INT eofcount = 0; /* to break endless catcheof loop */ REG CHAR c; REG INT len; REG FILE f; *************** *** 116,123 ELIF f->feof ORF f->fdes<0 THEN c=EOF; f->feof++; ELIF (len=readb())<=0 ! THEN close(f->fdes); f->fdes = -1; c=EOF; f->feof++; ! ELSE f->fend = (f->fnxt = f->fbuf)+len; goto retry; FI return(c); --- 151,185 ----- ELIF f->feof ORF f->fdes<0 THEN c=EOF; f->feof++; ELIF (len=readb())<=0 ! THEN ! IF catcheof ! #if JOBS ! ANDF (flags&(ttyflg|prompt|dotflg)) == (ttyflg|prompt) ! ANDF ( (flags&noeotflg) ORF j_finish(FALSE) ) ! #else ! ANDF (flags&(ttyflg|prompt|noeotflg|dotflg)) == (ttyflg|prompt|noeotflg) ! #endif ! ANDF ++eofcount < 10 /* in case terminal is disconnected */ ! THEN ! #if JOBS ! IF (flags&(ttyflg|prompt|noeotflg)) == (ttyflg|prompt|noeotflg) ! THEN ! #endif ! prs("use \"exit\"\n"); ! #if JOBS ! /* else "there are stopped jobs" was printed */ ! FI ! #endif ! c = NL; ! ELSE ! close(f->fdes); f->fdes = -1; c=EOF; f->feof++; ! #if JOBS ! j_finish(TRUE); ! #endif ! FI ! ELSE f->fend = f->fnxt+len; ! /* was f->fend = (f->fnxt = f->fbuf) + len */ ! eofcount = 0; goto retry; FI return(c); *************** *** 123,129 return(c); } ! LOCAL readb() { REG FILE f=standin; REG INT len; --- 185,191 ----- return(c); } ! LOCAL readblock() /* ADR --- changed the name */ { REG FILE f=standin; REG INT len; *************** *** 128,135 REG FILE f=standin; REG INT len; ! IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI ! REP IF trapnote&SIGSET THEN newline(); sigchk() FI PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE trapjmp[INTR] = 0; return(len); --- 190,201 ----- REG FILE f=standin; REG INT len; ! REP ! IF trapnote&SIGSET ! THEN newline(); sigchk(); ! ELIF (trapnote&TRAPSET) ANDF (rwait>0) ! THEN newline(); chktrap(); clearup(); ! FI PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE return(len); } *************** *** 131,136 IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI REP IF trapnote&SIGSET THEN newline(); sigchk() FI PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE - trapjmp[INTR] = 0; return(len); } --- 197,202 ----- THEN newline(); chktrap(); clearup(); FI PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE return(len); } *************** *** 133,136 PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE trapjmp[INTR] = 0; return(len); } --- 198,398 ----- FI PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE return(len); + } + + /* readb --- read a block from the outside world, and history process it */ + + /* + * In BSD systems, using the literal next capability of the tty driver, it + * is actually possible to put a newline in the middle of the input line, + * and then hit return, so that the shell sees two lines of input. + * + * As a design decision, if there is a \n in the middle of what we've read + * from a terminal, treat the commands as two separately typed commands. I.e. + * + * echo hi ^J echo there + * + * is the same as + * + * echo hi + * echo there + * + * The major reason for doing it this way is that the history mechanism knows + * that a \n is the end of a line. + * + * Finally, on USG systems, we just leave this code alone, since it won't + * get executed anyway. + */ + + /* + * In word.c, the readc() function keeps a pointer to what standin pointed to + * when readc first gets called. Therefore, where standin points to can not + * not change across calls to readb(). To get around this, we change the + * contents of the structure pointed to by standin, saving and restoring + * it as necessary. + */ + + #define LARGEBUF (HISTSIZE / 2) /* size of expanded history */ + + static + readb() + { + int ilen, i, j; + char ibuf[BUFSIZ]; /* input into scratch area, pass to history */ + static char expansion[LARGEBUF]; + static int moreinbuf = FALSE; + static int saved_ilen = 0; + static int start_here = 0; + static struct fileblk *f = 0; + auto int gotoutofbuf = 0; + + if (expanded) /* just did a history substitution */ + expanded = 0; + + if ((flags & nohistflg) || (flags & prompt) == 0 || ! isatty (input) + || standin->fstak != 0) + { + ilen = readblock (); + if (ilen > 0) + standin->fnxt = standin->fbuf; + return (ilen); + /* not doing history expansion at all */ + } + + if (f == 0) + f = standin; + + ilen = 0; + + /* + * First, if there was more stuff in the last buffer, go and get it. + * If not get some more from the outside world. + * + * Then, make sure we've read up to a newline. + * This is basically in case someone has done something bizarre + * like 'stty raw', and input is coming in one character at a time. + * + * We use a heuristic. If amount read is just 1, keep reading till + * we get a newline. Else, read in a complete line from the terminal. + * Once we're in raw mode, can't reset it until a newline is typed. + * + * If not reading one character at a time, then do the stuff for + * embedded newlines. + */ + + if (moreinbuf) + { + for (i = 0, j = start_here; f->fbuf[j] != NL && j < saved_ilen; i++, j++) + ibuf[i] = f->fbuf[j]; + + #ifdef notdef + if (f->fbuf[j] != NL) + { + prs ("internal i/o error C in readb\n"); + return (0); + } + #endif + + if (f->fbuf[j] == NL) + ibuf[i++] = NL; + ibuf[i] = '\0'; + ilen = i; + /* embedded newline */ + moreinbuf = (++j < saved_ilen - 1); + if (moreinbuf) + start_here = j; /* where to start next time */ + gotoutofbuf = 1; + } + else /* wasn't an embedded \n last time */ + { + ilen = readblock (); + + if (ilen <= 0) /* EOF or error */ + return (ilen); + + if (ilen == 1) /* either in raw mode, or an empty line */ + { + i = 0; + ibuf[i++] = f->fbuf[0]; + if (f->fbuf[0] == NL) + { + ibuf[i] = '\0'; + goto dohist; + } + + while ((ilen = readblock()) > 0) + { + if (ilen != 1) + { + prs ("internal i/o error A in readb\n"); + return (0); + } + ibuf[i++] = f->fbuf[0]; + if (f->fbuf[0] == NL) + { + ibuf[i] = '\0'; + break; /* while */ + } + } + ilen = i; + gotoutofbuf = TRUE; + /* force code below to use collected string */ + } + else + { + /* reading bunches of characters at once */ + for (i = 0; f->fbuf[i] != NL && i < ilen; i++) + ibuf[i] = f->fbuf[i]; + + #ifdef notdef + if (f->fbuf[i] != NL) + { + prs ("internal i/o error B in readb\n"); + return (0); + } + #endif + + ibuf[i++] = NL; + ibuf[i] = '\0'; + /* ilen was set by readblock() */ + /* embedded newline */ + moreinbuf = (i < ilen - 1); + if (moreinbuf) + { + saved_ilen = ilen; + start_here = i; + /* where to start next time */ + gotoutofbuf = 1; + } + } + } + + dohist: + /* quick heuristic */ + if (! gotoutofbuf && ilen == 1 && f->fbuf[0] == NL) + { + f->fnxt = f->fbuf; + return (ilen); + } + + if (histsub (ibuf, expansion, sizeof expansion)) + { + int olen = length (expansion) - 1; + if (! expanded && ! gotoutofbuf) + { + standin->fnxt = standin->fbuf; + return (ilen); + } + /* else + expanded == TRUE or from buffer */ + standin->fnxt = expansion; + return (olen); + } + else + { + /* hist expansion failed, return an empty line */ + standin->fnxt = standin->fbuf; + standin->fbuf[0] = NL; + return (1); + } } :::::::: xec.c ::::::: *** ../orig.u/xec.c Wed May 15 17:13:46 1985 --- xec.c Tue Jun 4 17:58:16 1985 *************** *** 12,17 */ #include "defs.h" #include "sym.h" LOCAL INT parent; --- 12,18 ----- */ #include "defs.h" + #include #include "sym.h" LOCAL INT parent; *************** *** 23,29 /* ======== command execution ========*/ ! execute(argt, execflg, pf1, pf2) TREPTR argt; INT *pf1, *pf2; { --- 24,30 ----- /* ======== command execution ========*/ ! execute(argt, execflg, errorflg, pf1, pf2) TREPTR argt; INT *pf1, *pf2; { *************** *** 30,35 /* `stakbot' is preserved by this routine */ REG TREPTR t; STKPTR sav=savstak(); sigchk(); --- 31,46 ----- /* `stakbot' is preserved by this routine */ REG TREPTR t; STKPTR sav=savstak(); + #if pyr + auto INT change_univ = FALSE; + auto INT new_univ = 0; + /* + * universes run from 1 to NUMUNIV: We start out at 0 + * and increment new_univ in the swtich for internal + * commands, below. new_univ nust *not* be assigned to, directly + * or via side effects, any place else + */ + #endif sigchk(); *************** *** 33,38 sigchk(); IF (t=argt) ANDF execbrk==0 THEN REG INT treeflgs; INT oldexit, type; --- 44,50 ----- sigchk(); + IF ! errorflg THEN flags &= ~errflg FI IF (t=argt) ANDF execbrk==0 THEN REG INT treeflgs; INT oldexit, type; *************** *** 54,60 com=scan(argn); a1=com[1]; gchain=schain; ! IF argn==0 ORF (internal=syslook(com[0],commands)) THEN setlist(t->comset, 0); FI --- 66,72 ----- com=scan(argn); a1=com[1]; gchain=schain; ! IF (internal=syslook(com[0],commands)) ORF argn==0 THEN setlist(t->comset, 0); FI *************** *** 75,81 IF (f=pathopen(getpath(a1), a1)) < 0 THEN failed(a1,notfound); ! ELSE execexp(0,f); FI FI break; --- 87,99 ----- IF (f=pathopen(getpath(a1), a1)) < 0 THEN failed(a1,notfound); ! ELSE ! INT savedot = flags&dotflg; ! ! flags |= dotflg; ! execexp(0,f); ! flags &= ~dotflg; ! flags |= savedot; FI FI break; *************** *** 88,93 break; case SYSEXIT: exitsh(a1?stoi(a1):oldexit); case SYSNULL: --- 106,116 ----- break; case SYSEXIT: + #if JOBS + IF j_finish(FALSE) THEN break; FI + #endif + histsave (histfnod.namval); + flags |= forked; /* force exit */ exitsh(a1?stoi(a1):oldexit); case SYSNULL: *************** *** 95,101 break; case SYSCONT: ! execbrk = -loopcnt; break; case SYSBREAK: IF (execbrk=loopcnt) ANDF a1 --- 118,127 ----- break; case SYSCONT: ! IF (execbrk = -loopcnt) ANDF a1 ! THEN breakcnt = stoi (a1); ! FI ! break; case SYSBREAK: IF (execbrk=loopcnt) ANDF a1 *************** *** 139,144 IF a1==0 THEN break FI case SYSLOGIN: flags |= forked; oldsigs(); execa(com); done(); --- 165,171 ----- IF a1==0 THEN break FI case SYSLOGIN: + histsave (histfnod.namval); flags |= forked; oldsigs(); execa(com); done(); *************** *** 151,160 break; case SYSSHFT: ! IF dolc<1 ! THEN error(badshift); ! ELSE dolv++; dolc--; ! FI assnum(&dolladr, dolc); break; --- 178,193 ----- break; case SYSSHFT: ! BEGIN ! INT places; ! places = a1 ? stoi(a1) : 1; ! FOR ; places--; ! DO IF dolc<1 ! THEN error(badshift); ! ELSE dolv++; dolc--; ! FI ! OD ! END assnum(&dolladr, dolc); break; *************** *** 159,164 break; case SYSWAIT: await(-1); break; --- 192,198 ----- break; case SYSWAIT: + /* await(-1); */ await(a1?stoi(a1):-1,1); *************** *** 160,165 case SYSWAIT: await(-1); break; case SYSREAD: --- 194,201 ----- case SYSWAIT: /* await(-1); + */ + await(a1?stoi(a1):-1,1); break; case SYSREAD: *************** *** 163,168 break; case SYSREAD: exitval=readvar(&com[1]); break; --- 199,205 ----- break; case SYSREAD: + rwait=1; exitval=readvar(&com[1]); break; *************** *** 222,227 } break; default: internal=builtin(argn,com); --- 259,327 ----- } break; + #if JOBS + case SYSJOBS: + + j_print(); + break; + + case SYSFG: + + j_resume(a1, FALSE); + break; + + case SYSBG: + + j_resume(a1, TRUE); + break; + + case SYSSUSPEND: + exitval = 1; + IF getppid() == 1 + THEN prs (nosusp); + ELSE exitval = 0; + kill (getpid(), STOP); + FI + break; + #endif + + #if pyr + /* + * UCB is Universe 2 + * ATT is Universe 1 + * new_univ == 0 + */ + case SYSUCB: + new_univ++; + /* fall thru */ + case SYSATT: + new_univ++; + IF argn > 1 + THEN + change_univ = TRUE; + com++; + goto doit; + ELSE + setuniverse (cur_univ = new_univ); + univnod.namflg &= ~N_RDONLY; + assign (& univnod, univ_name[cur_univ - 1]); + attrib ((& univnod), N_RDONLY); + break; + FI + + case SYSUNIVERSE: + IF eq(com[1], dashl) + THEN prs_buff (univ_longname[cur_univ - 1]); + ELSE prs_buff (univ_name[cur_univ - 1]); + FI + prc_buff (NL); + break; + #endif + + case SYSHISTORY: + exitval = history (argn, com); + break; + default: internal=builtin(argn,com); *************** *** 233,239 break; FI ELIF t->treio==0 ! THEN break; FI END --- 333,340 ----- break; FI ELIF t->treio==0 ! THEN chktrap(); ! break; FI END *************** *** 238,243 END case TFORK: IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 THEN parent=0; ELSE WHILE (parent=fork()) == -1 --- 339,347 ----- END case TFORK: + #if pyr + doit: + #endif IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 THEN parent=0; ELSE WHILE (parent=fork()) == -1 *************** *** 242,247 THEN parent=0; ELSE WHILE (parent=fork()) == -1 DO sigchk(); alarm(10); pause() OD FI IF parent --- 346,354 ----- THEN parent=0; ELSE WHILE (parent=fork()) == -1 DO sigchk(); alarm(10); pause() OD + #if JOBS + IF parent == 0 THEN j_top_level = FALSE; FI + #endif FI IF parent *************** *** 248,253 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 --- 355,363 ----- THEN /* This is the parent branch of fork; */ /* it may or may not wait for the child. */ IF treeflgs&FPRS ANDF flags&ttyflg + #if JOBS + ANDF (flags&jobflg) == 0 + #endif THEN prn(parent); newline(); FI IF treeflgs&FPCL THEN closepipe(pf1) FI *************** *** 251,256 THEN prn(parent); newline(); FI IF treeflgs&FPCL THEN closepipe(pf1) FI IF (treeflgs&(FAMP|FPOU))==0 THEN await(parent); ELIF (treeflgs&FAMP)==0 --- 361,369 ----- THEN prn(parent); newline(); FI IF treeflgs&FPCL THEN closepipe(pf1) FI + #if JOBS + j_child_post(parent, treeflgs&FAMP, treeflgs&FPIN, t); + #endif IF (treeflgs&(FAMP|FPOU))==0 THEN await(parent, 0); #if JOBS *************** *** 252,258 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); --- 365,374 ----- j_child_post(parent, treeflgs&FAMP, treeflgs&FPIN, t); #endif IF (treeflgs&(FAMP|FPOU))==0 ! THEN await(parent, 0); ! #if JOBS ! j_reset_pg(); ! #endif ELIF (treeflgs&FAMP)==0 THEN post(parent); ELSE assnum(&pcsadr, parent); *************** *** 263,268 ELSE /* this is the forked branch (child) of execute */ flags |= forked; iotemp=0; postclr(); settmp(); --- 379,393 ----- ELSE /* this is the forked branch (child) of execute */ + #if pyr + IF change_univ + THEN setuniverse (new_univ); + univnod.namflg &= ~N_RDONLY; + assign (&univnod, univ_name[cur_univ - 1]); + attrib ((&univnod), N_RDONLY); + FI + #endif + flags |= forked; iotemp=0; postclr(); settmp(); *************** *** 268,274 settmp(); /* Turn off INTR and QUIT if `FINT' */ ! /* Reset ramaining signals to parent */ /* except for those `lost' by trap */ oldsigs(); IF treeflgs&FINT --- 393,399 ----- settmp(); /* Turn off INTR and QUIT if `FINT' */ ! /* Reset remaining signals to parent */ /* except for those `lost' by trap */ oldsigs(); IF treeflgs&FINT *************** *** 272,277 /* except for those `lost' by trap */ oldsigs(); IF treeflgs&FINT THEN signal(INTR,1); signal(QUIT,1); FI --- 397,405 ----- /* except for those `lost' by trap */ oldsigs(); IF treeflgs&FINT + #if JOBS + ANDF (flags&jobflg) == 0 + #endif THEN signal(INTR,1); signal(QUIT,1); FI *************** *** 287,292 /* default std input for & */ IF treeflgs&FINT ANDF ioset==0 THEN rename(chkopen(devnull),0); FI --- 415,423 ----- /* default std input for & */ IF treeflgs&FINT ANDF ioset==0 + #if JOBS + ANDF (flags&jobflg) == 0 + #endif THEN rename(chkopen(devnull),0); FI *************** *** 293,299 /* io redirection */ initio(t->treio); IF type!=TCOM ! THEN execute(t->forktre,1); ELIF com[0]!=ENDARGS THEN setlist(t->comset,N_EXPORT); execa(com); --- 424,430 ----- /* io redirection */ initio(t->treio); IF type!=TCOM ! THEN execute(t->forktre,1, errorflg); ELIF com[0]!=ENDARGS THEN eflag = 0; *************** *** 295,301 IF type!=TCOM THEN execute(t->forktre,1); ELIF com[0]!=ENDARGS ! THEN setlist(t->comset,N_EXPORT); execa(com); FI done(); --- 426,438 ----- IF type!=TCOM THEN execute(t->forktre,1, errorflg); ELIF com[0]!=ENDARGS ! THEN ! eflag = 0; ! /* eflag must be set to zero so commands ! implemented as shell scripts do not ! exit if set -e and some command in ! the script returns non zero */ ! setlist(t->comset,N_EXPORT); execa(com); FI done(); *************** *** 303,309 case TPAR: rename(dup(2),output); ! execute(t->partre,execflg); done(); case TFIL: --- 440,446 ----- case TPAR: rename(dup(2),output); ! execute(t->partre,execflg, errorflg); done(); case TFIL: *************** *** 309,316 case TFIL: BEGIN INT pv[2]; chkpipe(pv); ! IF execute(t->lstlef, 0, pf1, pv)==0 ! THEN execute(t->lstrit, execflg, pv, pf2); ELSE closepipe(pv); FI END --- 446,453 ----- case TFIL: BEGIN INT pv[2]; chkpipe(pv); ! IF execute(t->lstlef, 0, errorflg, pf1, pv)==0 ! THEN execute(t->lstrit, execflg, errorflg, pv, pf2); ELSE closepipe(pv); FI END *************** *** 317,324 break; case TLST: ! execute(t->lstlef,0); ! execute(t->lstrit,execflg); break; case TAND: --- 454,461 ----- break; case TLST: ! execute(t->lstlef,0, errorflg); ! execute(t->lstrit,execflg, errorflg); break; case TAND: *************** *** 322,329 break; case TAND: ! IF execute(t->lstlef,0)==0 ! THEN execute(t->lstrit,execflg); FI break; --- 459,466 ----- break; case TAND: ! IF execute(t->lstlef,0, 0)==0 ! THEN execute(t->lstrit,execflg, errorflg); FI break; *************** *** 328,335 break; case TORF: ! IF execute(t->lstlef,0)!=0 ! THEN execute(t->lstrit,execflg); FI break; --- 465,472 ----- break; case TORF: ! IF execute(t->lstlef,0, 0)!=0 ! THEN execute(t->lstrit,execflg, errorflg); FI break; *************** *** 350,357 loopcnt++; WHILE *args!=ENDARGS ANDF execbrk==0 DO assign(n,*args++); ! execute(t->fortre,0); ! IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI execbrk=breakcnt; loopcnt--; --- 487,499 ----- loopcnt++; WHILE *args!=ENDARGS ANDF execbrk==0 DO assign(n,*args++); ! execute(t->fortre,0, errorflg); ! IF execbrk ! THEN IF breakcnt > 1 ORF execbrk > 0 ! THEN break; ! ELSE execbrk = breakcnt = 0; ! FI ! FI OD IF breakcnt THEN breakcnt-- FI execbrk = (execbrk < 0 ? -breakcnt : breakcnt); *************** *** 354,360 IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI ! execbrk=breakcnt; loopcnt--; argfor=freeargs(argsav); END break; --- 496,503 ----- FI OD IF breakcnt THEN breakcnt-- FI ! execbrk = (execbrk < 0 ? -breakcnt : breakcnt); ! loopcnt--; argfor=freeargs(argsav); END break; *************** *** 365,373 INT i=0; loopcnt++; ! WHILE execbrk==0 ANDF (execute(t->whtre,0)==0)==(type==TWH) ! DO i=execute(t->dotre,0); ! IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI execbrk=breakcnt; loopcnt--; exitval=i; --- 508,521 ----- INT i=0; loopcnt++; ! WHILE execbrk<=0 ANDF (execute(t->whtre,0,0)==0)==(type==TWH) ! DO i=execute(t->dotre,0, errorflg); ! IF execbrk ! THEN IF breakcnt > 1 ORF execbrk > 0 ! THEN break; ! ELSE execbrk = breakcnt = 0; ! FI ! FI OD IF breakcnt THEN breakcnt-- FI execbrk=(execbrk < 0 ? -breakcnt : breakcnt); *************** *** 370,376 IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI ! execbrk=breakcnt; loopcnt--; exitval=i; END break; --- 518,525 ----- FI OD IF breakcnt THEN breakcnt-- FI ! execbrk=(execbrk < 0 ? -breakcnt : breakcnt); ! loopcnt--; exitval=i; END break; *************** *** 375,383 break; case TIF: ! IF execute(t->iftre,0)==0 ! THEN execute(t->thtre,execflg); ! ELSE execute(t->eltre,execflg); FI break; --- 524,534 ----- break; case TIF: ! IF execute(t->iftre,0,0)==0 ! THEN execute(t->thtre,execflg, errorflg); ! ELIF t->eltre ! THEN execute(t->eltre,execflg, errorflg); ! ELSE exitval = 0; /* force zero exit for if-then-fi */ FI break; *************** *** 390,396 WHILE rex DO REG STRING s; IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s)) ! THEN execute(t->regcom,0); t=0; break; ELSE rex=rex->argnxt; FI --- 541,547 ----- WHILE rex DO REG STRING s; IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s)) ! THEN execute(t->regcom,0,errorflg); t=0; break; ELSE rex=rex->argnxt; FI *************** *** 405,410 sigchk(); tdystak(sav); return(exitval); } --- 556,562 ----- sigchk(); tdystak(sav); + flags |= eflag; return(exitval); } *************** *** 420,425 ELIF f>=0 THEN initf(f); FI ! execute(cmd(NL, NLFLG|MTFLG),0); pop(); } --- 572,577 ----- ELIF f>=0 THEN initf(f); FI ! execute(cmd(NL, NLFLG|MTFLG),0, flags&errflg); pop(); }