gww@marduk.UUCP (Gary Winiger) (09/05/87)
Subject: The else clause of an if within a for does not get executed. +Fix Index: bin/make 4.3BSD +Fix Index: bin/sh 4.3BSD +Fix Description: The following Makefile rule succeed will succeed and the rule fail will fail. The bugs section in make(1) suggests using the ``-i'' flag to avoid such problems. Makefile: # # files /a, /b, /c, /d, /e exist. # files /f, /g, /h, /i, /j do not exist # succeed: -for i in a b c d e f g h i j; do \ echo "/$$i for"; \ if [ -f /$$i ]; then \ echo "/$$i exists"; \ else \ echo "/$$i does not exist"; \ fi; \ done fail: for i in a b c d e f g h i j; do \ echo "/$$i for"; \ if [ -f /$$i ]; then \ echo "/$$i exists"; \ else \ echo "/$$i does not exist"; \ fi; \ done Repeat-By: Creating files /a, /b, /c, /d, /e and running make succeed: for i in a b c d e f g h i j; do echo "/$i for"; if [ -f /$i ]; then echo "/$i exists"; else echo "/$i does not exist"; fi; done /a for /a exists /b for /b exists /c for /c exists /d for /d exists /e for /e exists /f for /f does not exist /g for /g does not exist /h for /h does not exist /i for /i does not exist /j for /j does not exist make fail: for i in a b c d e f g h i j; do echo "/$i for"; if [ -f /$i ]; then echo "/$i exists"; else echo "/$i does not exist"; fi; done /a for /a exists /b for /b exists /c for /c exists /d for /d exists /e for /e exists /f for *** Exit 1 Stop. and make -i fail: for i in a b c d e f g h i j; do echo "/$i for"; if [ -f /$i ]; then echo "/$i exists"; else echo "/$i does not exist"; fi; done /a for /a exists /b for /b exists /c for /c exists /d for /d exists /e for /e exists /f for /f does not exist /g for /g does not exist /h for /h does not exist /i for /i does not exist /j for /j does not exist Fix: I believe the problem does not exist in make(1), but in sh(1). It is true that make(1) may still require ``-i'' in some cases, but sh(1) is inappropriately reporting errors. The enclosed fixes to sh(1) eliminate this problem at Elxsi. The files effected are: bin/sh/{args.c defs.h error.c macro.c main.c service.c xec.c} Gary.. {ucbvax!sun,lll-lcc!lll-tis,amdahl!altos86,bridge2}!elxsi!gww --------- cut --------- snip --------- :.,$w diff ------------- RCS file: /RCS/usr/src/bin/sh/args.c,v retrieving revision 1.1 diff -c -r1.1 args.c *** /tmp/,RCSt1001416 Mon Dec 15 12:05:57 1986 --- args.c Mon Dec 15 11:54:29 1986 *************** *** 1,9 **** #ifndef lint ! static char *ERcsId = "$Header: args.c,v 1.1 86/12/10 17:37:50 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)args.c 4.4 7/31/85"; #endif /* * $Log: args.c,v $ * Revision 1.1 86/12/10 17:37:50 gww * Initial revision * --- 1,17 ---- #ifndef lint ! static char *ERcsId = "$Header: args.c,v 1.2 86/12/15 11:49:52 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)args.c 4.4 7/31/85"; #endif /* * $Log: args.c,v $ + * Revision 1.2 86/12/15 11:49:52 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * * Revision 1.1 86/12/10 17:37:50 gww * Initial revision * *************** *** 53,58 **** --- 61,69 ---- WHILE *flagc ANDF *flagc != *cp DO flagc++ OD IF *cp == *flagc THEN flags |= flagval[flagc-flagchar]; + IF flags & errflg + THEN eflag = errflg + FI ELIF *cp=='c' ANDF argc>2 ANDF comdiv==0 THEN comdiv=argp[2]; argp[1]=argp[0]; argp++; argc--; =================================================================== RCS file: /RCS/usr/src/bin/sh/defs.h,v retrieving revision 1.1 diff -c -r1.1 defs.h *** /tmp/,RCSt1001444 Mon Dec 15 12:09:03 1986 --- defs.h Mon Dec 15 11:55:07 1986 *************** *** 1,6 **** ! /* $Header: defs.h,v 1.1 86/12/10 17:38:02 gww Exp $ ENIX BSD * * $Log: defs.h,v $ * Revision 1.1 86/12/10 17:38:02 gww * Initial revision * --- 1,18 ---- ! /* $Header: defs.h,v 1.3 86/12/15 11:54:31 gww Exp $ ENIX BSD * * $Log: defs.h,v $ + * Revision 1.3 86/12/15 11:54:31 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * + * Revision 1.2 86/12/10 18:25:23 gww + * Declare environ external so it gets linked correctly. + * Probably a typo in 4.3 code. + * * Revision 1.1 86/12/10 17:38:02 gww * Initial revision * *************** *** 225,230 **** --- 237,243 ---- #define keyflg 020000 #define batchflg 040000 INT flags; + INT eflag; /* error exits from various parts of shell */ #include <setjmp.h> *************** *** 255,261 **** BOOL trapjmp[]; /* name tree and words */ ! STRING *environ; CHAR numbuf[]; MSG export; MSG readonly; --- 268,274 ---- BOOL trapjmp[]; /* name tree and words */ ! extern STRING *environ; CHAR numbuf[]; MSG export; MSG readonly; =================================================================== RCS file: /RCS/usr/src/bin/sh/error.c,v retrieving revision 1.1 diff -c -r1.1 error.c *** /tmp/,RCSt1001416 Mon Dec 15 12:05:59 1986 --- error.c Mon Dec 15 11:55:37 1986 *************** *** 1,9 **** #ifndef lint ! static char *ERcsId = "$Header: error.c,v 1.1 86/12/10 17:38:04 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)error.c 4.2 8/11/83"; #endif /* * $Log: error.c,v $ * Revision 1.1 86/12/10 17:38:04 gww * Initial revision * --- 1,17 ---- #ifndef lint ! static char *ERcsId = "$Header: error.c,v 1.2 86/12/15 11:55:08 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)error.c 4.2 8/11/83"; #endif /* * $Log: error.c,v $ + * Revision 1.2 86/12/15 11:55:08 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * * Revision 1.1 86/12/10 17:38:04 gww * Initial revision * *************** *** 66,71 **** --- 74,80 ---- * Action is to return to command level or exit. */ exitval=xno; + flags |= eflag; IF (flags & (forked|errflg|ttyflg)) != ttyflg THEN done(); ELSE clearup(); =================================================================== RCS file: /RCS/usr/src/bin/sh/macro.c,v retrieving revision 1.1 diff -c -r1.1 macro.c *** /tmp/,RCSt1001416 Mon Dec 15 12:06:01 1986 --- macro.c Mon Dec 15 11:55:41 1986 *************** *** 1,9 **** #ifndef lint ! static char *ERcsId = "$Header: macro.c,v 1.1 86/12/10 17:38:11 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)macro.c 4.3 8/11/83"; #endif /* * $Log: macro.c,v $ * Revision 1.1 86/12/10 17:38:11 gww * Initial revision * --- 1,17 ---- #ifndef lint ! static char *ERcsId = "$Header: macro.c,v 1.2 86/12/15 11:55:38 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)macro.c 4.3 8/11/83"; #endif /* * $Log: macro.c,v $ + * Revision 1.2 86/12/15 11:55:38 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * * Revision 1.1 86/12/10 17:38:11 gww * Initial revision * *************** *** 201,207 **** */ chkpipe(pv); initf(pv[INPIPE]); ! execute(t, 0, 0, pv); close(pv[OTPIPE]); END tdystak(savptr); staktop=movstr(savptr,stakbot); --- 209,215 ---- */ chkpipe(pv); initf(pv[INPIPE]); ! execute(t, 0, (int)(flags & errflg), 0, pv); close(pv[OTPIPE]); END tdystak(savptr); staktop=movstr(savptr,stakbot); =================================================================== RCS file: /RCS/usr/src/bin/sh/main.c,v retrieving revision 1.1 diff -c -r1.1 main.c *** /tmp/,RCSt1001416 Mon Dec 15 12:06:03 1986 --- main.c Mon Dec 15 11:55:45 1986 *************** *** 1,9 **** #ifndef lint ! static char *ERcsId = "$Header: main.c,v 1.1 86/12/10 17:38:12 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)main.c 4.3 3/19/85"; #endif /* * $Log: main.c,v $ * Revision 1.1 86/12/10 17:38:12 gww * Initial revision * --- 1,17 ---- #ifndef lint ! static char *ERcsId = "$Header: main.c,v 1.2 86/12/15 11:55:42 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)main.c 4.3 3/19/85"; #endif /* * $Log: main.c,v $ + * Revision 1.2 86/12/15 11:55:42 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * * Revision 1.1 86/12/10 17:38:12 gww * Initial revision * *************** *** 168,174 **** IF eof THEN return; FI ! execute(cmd(NL,MTFLG),0); eof |= (flags&oneflg); POOL } --- 176,182 ---- IF eof THEN return; FI ! execute(cmd(NL, MTFLG), 0, eflag); eof |= (flags&oneflg); POOL } =================================================================== RCS file: /RCS/usr/src/bin/sh/service.c,v retrieving revision 1.1 diff -c -r1.1 service.c *** /tmp/,RCSt1001416 Mon Dec 15 12:06:07 1986 --- service.c Mon Dec 15 11:55:49 1986 *************** *** 1,9 **** #ifndef lint ! static char *ERcsId = "$Header: service.c,v 1.1 86/12/10 17:38:21 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)service.c 4.4 3/19/85"; #endif /* * $Log: service.c,v $ * Revision 1.1 86/12/10 17:38:21 gww * Initial revision * --- 1,17 ---- #ifndef lint ! static char *ERcsId = "$Header: service.c,v 1.2 86/12/15 11:55:46 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)service.c 4.4 3/19/85"; #endif /* * $Log: service.c,v $ + * Revision 1.2 86/12/15 11:55:46 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * * Revision 1.1 86/12/10 17:38:21 gww * Initial revision * *************** *** 288,293 **** --- 296,302 ---- IF wx ANDF flags&errflg THEN exitsh(rc); FI + flags |= eflag; exitval=rc; exitset(); } =================================================================== RCS file: /RCS/usr/src/bin/sh/xec.c,v retrieving revision 1.1 diff -c -r1.1 xec.c *** /tmp/,RCSt1001416 Mon Dec 15 12:06:12 1986 --- xec.c Mon Dec 15 11:55:54 1986 *************** *** 1,9 **** #ifndef lint ! static char *ERcsId = "$Header: xec.c,v 1.1 86/12/10 17:38:31 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)xec.c 4.3 8/11/83"; #endif /* * $Log: xec.c,v $ * Revision 1.1 86/12/10 17:38:31 gww * Initial revision * --- 1,20 ---- #ifndef lint ! static char *ERcsId = "$Header: xec.c,v 1.3 86/12/15 11:55:49 gww Exp $ ENIX BSD"; static char sccsid[] = "@(#)xec.c 4.3 8/11/83"; #endif /* * $Log: xec.c,v $ + * Revision 1.3 86/12/15 11:55:49 gww + * Add an error flag to support correct processing of such constructs as + * an if within a for. If there is an else, it should be executed and the + * if should not report failure to the for. The is especially noticable + * in Makefiles. Make has a comment to use ``-i'' in this case. This + * mod may infact fix the need to use ``-i'' when the shell should have + * handled the error response. + * + * Revision 1.2 86/12/10 18:24:36 gww + * Fix typo-s in 4.3 code. + * * Revision 1.1 86/12/10 17:38:31 gww * Initial revision * *************** *** 30,36 **** /* ======== command execution ========*/ ! execute(argt, execflg, pf1, pf2) TREPTR argt; INT *pf1, *pf2; { --- 41,47 ---- /* ======== command execution ========*/ ! execute(argt, execflg, errorflg, pf1, pf2) TREPTR argt; INT *pf1, *pf2; { *************** *** 38,43 **** --- 49,57 ---- REG TREPTR t; STKPTR sav=savstak(); + IF !errorflg + THEN flags &= ~errflg; + FI sigchk(); IF (t=argt) ANDF execbrk==0 *************** *** 213,219 **** case SYSUMASK: if (a1) { ! int c, i i = 0; while ((c = *a1++) >= '0' && c <= '7') --- 227,233 ---- case SYSUMASK: if (a1) { ! int c, i; i = 0; while ((c = *a1++) >= '0' && c <= '7') *************** *** 300,308 **** /* 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); FI done(); --- 314,323 ---- /* io redirection */ initio(t->treio); IF type!=TCOM ! THEN execute(t->forktre,1,errorflg); ELIF com[0]!=ENDARGS ! THEN eflag = 0; ! setlist(t->comset,N_EXPORT); execa(com); FI done(); *************** *** 310,323 **** case TPAR: rename(dup(2),output); ! execute(t->partre,execflg); done(); 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 --- 325,338 ---- case TPAR: rename(dup(2),output); ! execute(t->partre,execflg,errorflg); done(); 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 *************** *** 324,342 **** break; case TLST: ! execute(t->lstlef,0); ! execute(t->lstrit,execflg); break; case TAND: ! IF execute(t->lstlef,0)==0 ! THEN execute(t->lstrit,execflg); FI break; case TORF: ! IF execute(t->lstlef,0)!=0 ! THEN execute(t->lstrit,execflg); FI break; --- 339,357 ---- break; case TLST: ! execute(t->lstlef,0,errorflg); ! execute(t->lstrit,execflg,errorflg); break; case TAND: ! IF execute(t->lstlef,0,0)==0 ! THEN execute(t->lstrit,execflg,errorflg); FI break; case TORF: ! IF execute(t->lstlef,0,0)!=0 ! THEN execute(t->lstrit,execflg,errorflg); FI break; *************** *** 357,363 **** 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 --- 372,378 ---- loopcnt++; WHILE *args!=ENDARGS ANDF execbrk==0 DO assign(n,*args++); ! execute(t->fortre,0,errorflg); IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI *************** *** 372,379 **** 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 --- 387,395 ---- 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<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI *************** *** 382,390 **** break; case TIF: ! IF execute(t->iftre,0)==0 ! THEN execute(t->thtre,execflg); ! ELSE execute(t->eltre,execflg); FI break; --- 398,408 ---- 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; *************** *** 397,403 **** 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 --- 415,421 ---- 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 *************** *** 412,417 **** --- 430,436 ---- sigchk(); tdystak(sav); + flags |= eflag; return(exitval); } *************** *** 427,432 **** ELIF f>=0 THEN initf(f); FI ! execute(cmd(NL, NLFLG|MTFLG),0); pop(); } --- 446,451 ---- ELIF f>=0 THEN initf(f); FI ! execute(cmd(NL, NLFLG|MTFLG),0,(int)(flags & errflg)); pop(); }