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();
}