Make(1) does not function in conjunction with RCS +Fix
Gary Winiger
gww at beatnix.UUCP
Sun Mar 13 07:34:40 AEST 1988
Subject: Make(1) does not function in conjunction with RCS +Fix
Index: bin/make/{Makefile,defs,doname.c,files.c,main.c,misc.c}, man1/make.1 4.3BSD
Description:
Make doesn't work in conjunction with RCS as System V works in
conjunction with SCCS.
Repeat-By:
Try to make a target when not all the files are checked out.
Fix:
In 1984 a rework of the 4.1 make by Charles LaBrec (crl at purdue) was
distributed on the Usenix 84.1 distribution tape. Over the years
I have pointed numerous people to this distribution when they
asked about a make that worked with RCS. There were two problems
with this: It is 4.1 make; It couldn't be distributed generally
because all of make was reformatted and that meant that diffs wouldn't
be of any use. When I faced the problem at Elxsi of not being able
to use make in conjunction with RCS files not checked out, I went to
the 84.1 tape and got Charles' work. Since I wanted to use 4.3 make
(with the Elxsi extension for include), I couldn't just take the
make from that tape. I decided that rather than put the 4.3 make
into Charles' make, I'd put Charles' work into 4.3 make. I preserved
the obnoxious formatting of 4.3 make and now offer those context
diffs for others to use.
The attached code solves this problem at Elxsi.
Gary..
{ucbvax!sun,uunet,lll-lcc!lll-tis,amdahl!altos86,bridge2}!elxsi!gww
--------- cut --------- snip --------- :.,$w diff -------------
Index: Makefile
*** /tmp/,RCSt1005798 Fri Aug 14 13:41:13 1987
--- Makefile Fri Aug 14 13:39:05 1987
***************
*** 1,6 ****
! # $Header: Makefile,v 1.2 87/08/07 14:05:43 gww Exp $ ENIX BSD
#
# $Log: Makefile,v $
# Revision 1.2 87/08/07 14:05:43 gww
# Add include Files feature.
#
--- 1,9 ----
! # $Header: Makefile,v 1.3 87/08/14 13:38:54 gww Exp $ ENIX BSD
#
# $Log: Makefile,v $
+ # Revision 1.3 87/08/14 13:38:54 gww
+ # Add RCS and RCSROOT support.
+ #
# Revision 1.2 87/08/07 14:05:43 gww
# Add include Files feature.
#
***************
*** 15,21 ****
OBJECTS=ident.o main.o doname.o misc.o files.o dosys.o gram.o
LIBES=
LINT= lint -ps
! DFLAGS= -DINCLUDES
CFLAGS= -O -DASCARCH ${DFLAGS} -I. -I/usr/src/bin/make
all: make
--- 18,24 ----
OBJECTS=ident.o main.o doname.o misc.o files.o dosys.o gram.o
LIBES=
LINT= lint -ps
! DFLAGS= -DINCLUDES -DRCS -DRCSROOT
CFLAGS= -O -DASCARCH ${DFLAGS} -I. -I/usr/src/bin/make
all: make
Index: defs
*** /tmp/,RCSt1005809 Fri Aug 14 13:41:31 1987
--- defs Fri Aug 14 13:39:09 1987
***************
*** 1,6 ****
! /* $Header: defs,v 1.2 87/08/07 14:05:58 gww Exp $ ENIX BSD
*
* $Log: defs,v $
* Revision 1.2 87/08/07 14:05:58 gww
* Add include Files feature.
*
--- 1,9 ----
! /* $Header: defs,v 1.3 87/08/14 13:39:07 gww Exp $ ENIX BSD
*
* $Log: defs,v $
+ * Revision 1.3 87/08/14 13:39:07 gww
+ * Add RCS and RCSROOT support.
+ *
* Revision 1.2 87/08/07 14:05:58 gww
* Add include Files feature.
*
***************
*** 69,74 ****
--- 72,91 ----
extern char *prompt;
extern int nopdir;
extern char junkname[ ];
+ #ifdef RCS
+ #define RCS_SUF ",v" /* suffix of RCS files */
+ extern int coflag; /* auto-checkout flag */
+ extern int rmflag; /* auto-remove flag */
+ extern struct shblock *co_cmd; /* auto-checkout shell command */
+ extern char RCSdir[BUFSIZ]; /* name of RCS dir */
+ extern char *RCSsuf; /* suffix of RCS files */
+ extern int dotRCS; /* true if ./RCS exists */
+ #ifdef RCSROOT
+ extern int rootRCS; /* true if RCSROOT exists */
+ #endif RCSROOT
+ extern int sighvalue; /* true if SIGHUP ignored */
+ extern int sigtvalue; /* true if SIGTERM ignored */
+ #endif RCS
***************
*** 80,85 ****
--- 97,105 ----
struct lineblock *linep;
int done:3;
int septype:3;
+ #ifdef RCS
+ char *RCSnamep; /* name of RCS file, if needed */
+ #endif RCS
TIMETYPE modtime;
};
***************
*** 138,143 ****
--- 158,167 ----
char *datap;
};
+ #ifdef RCS
+ extern struct chain *rmchain;
+ #endif RCS
+
char *copys(), *concat(), *subst();
int *ckalloc();
struct nameblock *srchname(), *makename();
***************
*** 155,157 ****
--- 179,185 ----
extern empty_stack();
extern FILE *pop();
#endif INCLUDES
+ #ifdef RCS
+ TIMETYPE getrcs();
+ char *ncat();
+ #endif RCS
Index: doname.c
*** /tmp/,RCSt1005815 Fri Aug 14 13:42:02 1987
--- doname.c Fri Aug 14 13:39:13 1987
***************
*** 1,10 ****
/*
* $Log: doname.c,v $
* Revision 1.1 86/12/11 12:53:12 gww
* Initial revision
*
*/
! static char *ERcsId = "$Header: doname.c,v 1.1 86/12/11 12:53:12 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)doname.c 4.8 (Berkeley) 85/09/18";
#include "defs"
#include <strings.h>
--- 1,13 ----
/*
* $Log: doname.c,v $
+ * Revision 1.2 87/08/14 13:39:10 gww
+ * Add RCS and RCSROOT support.
+ *
* Revision 1.1 86/12/11 12:53:12 gww
* Initial revision
*
*/
! static char *ERcsId = "$Header: doname.c,v 1.2 87/08/14 13:39:10 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)doname.c 4.8 (Berkeley) 85/09/18";
#include "defs"
#include <strings.h>
***************
*** 20,30 ****
--- 23,43 ----
*/
extern char *sys_siglist[];
+ #ifdef RCS
+ extern char *ctime();
+ #endif RCS
+ #ifndef RCS
doname(p, reclevel, tval)
+ #else
+ doname(p, reclevel, tval, ochain)
+ #endif !RCS
register struct nameblock *p;
int reclevel;
TIMETYPE *tval;
+ #ifdef RCS
+ struct chain **ochain;
+ #endif RCS
{
int errstat;
int okdel1;
***************
*** 40,45 ****
--- 53,62 ----
char *pnamep, *p1namep, *cp;
char *mkqlist();
struct chain *qchain, *appendq();
+ #ifdef RCS
+ struct chain *cochain;
+ int setimpl; /* set implicit vars */
+ #endif RCS
if(p == 0)
{
***************
*** 55,60 ****
--- 72,86 ----
if(p->done > 0)
{
+ #ifdef RCS
+ /*
+ * if we want to check-out RCS files, and we have previously
+ * determined that we can, then append it to the previous
+ * level's cochain.
+ */
+ if (p->RCSnamep)
+ *ochain = appendq(*ochain, p->namep);
+ #endif RCS
*tval = p->modtime;
return(p->done == 3);
}
***************
*** 63,69 ****
--- 89,100 ----
tdep = 0;
implcom = 0;
explcom = 0;
+ #ifndef RCS
ptime = exists(p);
+ #else
+ cochain = NULL;
+ ptime = exists(p, ochain);
+ #endif RCS
ptime1 = 0;
didwork = NO;
p->done = 1; /* avoid infinite loops */
***************
*** 86,94 ****
--- 117,131 ----
td = 0;
for(q = lp->depp ; q ; q = q->nxtdepblock)
{
+ #ifndef RCS
errstat += doname(q->depname, reclevel+1, &td1);
if(dbgflag)
printf("TIME(%s)=%ld\n", q->depname->namep, td1);
+ #else
+ errstat += doname(q->depname, reclevel+1, &td1, &cochain);
+ if(dbgflag)
+ printf("TIME(%s)=%s", q->depname->namep, ctime(&td1)+4);
+ #endif !RCS
if(td1 > td) td = td1;
if(ptime < td1)
qchain = appendq(qchain, q->depname->namep);
***************
*** 104,111 ****
--- 141,155 ----
setvar("?", mkqlist(qchain) );
qchain = NULL;
if( !questflag )
+ #ifdef RCS
+ if (cochain)
+ co(cochain);
+ #endif RCS
errstat += docom(lp->shp);
setvar("@", (char *) NULL);
+ #ifdef RCS
+ cochain = NULL;
+ #endif RCS
okdel = okdel1;
ptime1 = prestime();
didwork = YES;
***************
*** 127,132 ****
--- 171,179 ----
/* Look for implicit dependents, using suffix rules */
+ #ifdef RCS
+ setimpl = 0;
+ #endif RCS
for(lp = sufflist ; lp ; lp = lp->nxtlineblock)
for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock)
{
***************
*** 134,140 ****
--- 181,193 ----
if(suffix(p->namep , pnamep , prefix))
{
+ #ifndef RCS
srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL);
+ #else
+ srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL,
+ YES);
+ srchRCS(temp);
+ #endif !RCS
for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock)
for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock)
{
***************
*** 142,155 ****
--- 195,222 ----
if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
(p2=srchname(concat(prefix, p1namep ,sourcename))) )
{
+ #ifndef RCS
errstat += doname(p2, reclevel+1, &td);
+ #else
+ if (dbgflag)
+ printf("Found implicit match\n");
+ setimpl++;
+ errstat += doname(p2, reclevel+1, &td,
+ &cochain);
+ #endif !RCS
if(ptime < td)
qchain = appendq(qchain, p2->namep);
+ #ifndef RCS
if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
+ #else
+ if(dbgflag) printf("TIME(%s)=%s", p2->namep, ctime(&td)+4);
+ #endif !RCS
if(td > tdep) tdep = td;
+ #ifndef RCS
setvar("*", prefix);
if (p2->alias) setvar("<", copys(p2->alias));
else setvar("<", copys(p2->namep));
+ #endif !RCS
for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
if(implcom = lp2->shp) break;
goto endloop;
***************
*** 164,173 ****
--- 231,264 ----
endloop:
+ #ifdef RCS
+ if (dbgflag) {
+ printf("CO(%s): %s\n", p->namep, mkqlist(cochain));
+ fflush(stdout);
+ }
+ if (p->RCSnamep && (explcom || implcom)) {
+ if (keepgoing) {
+ errstat++;
+ printf("%s has both an RCS file and rules\n", p->namep);
+ } else
+ fatal1("%s has both an RCS file and rules", p->namep);
+ }
+ #endif RCS
if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) )
{
ptime = (tdep>0 ? tdep : prestime() );
+ #ifdef RCS
+ if (cochain)
+ co(cochain);
+ if (setimpl) {
+ setvar("*", prefix);
+ if (p2->alias)
+ setvar("<", copys(p2->alias));
+ else
+ setvar("<", copys(p2->namep));
+ }
+ #endif RCS
setvar("@", p->namep);
setvar("?", mkqlist(qchain) );
if(explcom)
***************
*** 195,201 ****
--- 286,296 ----
fatal1(" Don't know how to make %s", p->namep);
setvar("@", (char *) NULL);
+ #ifndef RCS
if(noexflag || (ptime = exists(p)) == 0)
+ #else
+ if(noexflag || (ptime = exists(p, (struct chain **)NULL)) == 0)
+ #endif !RCS
ptime = prestime();
}
***************
*** 206,217 ****
--- 301,322 ----
printf("`%s' is up to date.\n", p->namep);
if(questflag && reclevel==0)
+ #ifndef RCS
exit(ndocoms>0 ? -1 : 0);
+ #else
+ quit(ndocoms>0 ? -1 : 0);
+ #endif !RCS
p->done = (errstat ? 3 : 2);
if(ptime1 > ptime) ptime = ptime1;
p->modtime = ptime;
*tval = ptime;
+ #ifdef RCS
+ if (dbgflag) {
+ printf("%s: errstat = %d\n", p->namep, errstat);
+ fflush(stdout);
+ }
+ #endif RCS
return(errstat);
}
***************
*** 320,326 ****
--- 425,435 ----
case '*':
case '?':
case '[':
+ #ifndef RCS
if( p = srchdir(s1 , YES, q->nxtdepblock) )
+ #else
+ if( p = srchdir(s1 , YES, q->nxtdepblock, YES) )
+ #endif !RCS
{
q->nxtdepblock = p;
q->depname = 0;
Index: files.c
*** /tmp/,RCSt1005820 Fri Aug 14 13:42:21 1987
--- files.c Fri Aug 14 13:39:20 1987
***************
*** 1,5 ****
--- 1,8 ----
/*
* $Log: files.c,v $
+ * Revision 1.4 87/08/14 13:39:14 gww
+ * Add RCS and RCSROOT support.
+ *
* Revision 1.3 86/12/12 17:27:34 gww
* Don't dereference null pointer when VPATH is not defined.
*
***************
*** 11,17 ****
* Initial revision
*
*/
! static char *ERcsId = "$Header: files.c,v 1.3 86/12/12 17:27:34 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)files.c 4.12 (Berkeley) 86/01/09";
#include <fcntl.h>
--- 14,20 ----
* Initial revision
*
*/
! static char *ERcsId = "$Header: files.c,v 1.4 87/08/14 13:39:14 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)files.c 4.12 (Berkeley) 86/01/09";
#include <fcntl.h>
***************
*** 27,32 ****
--- 30,41 ----
#else
".SUFFIXES : .out .o .c .F .f .e .r .y .yr .ye .l .s .cl .p",
#endif
+ #ifdef RCS
+ "CO=co",
+ "COFLAGS=-q",
+ "RM=rm",
+ "RMFLAGS=-f",
+ #endif RCS
"YACC=yacc",
"YACCR=yacc -r",
"YACCE=yacc -e",
***************
*** 34,40 ****
"LEX=lex",
"LFLAGS=",
"CC=cc",
! #if defined(vax) || defined(sun)
"AS=as",
#else
"AS=as -",
--- 43,49 ----
"LEX=lex",
"LFLAGS=",
"CC=cc",
! #if defined(vax) || defined(sun) || defined(elxsi)
"AS=as",
#else
"AS=as -",
***************
*** 55,60 ****
--- 64,77 ----
"CMFLAGS=",
#endif
+ #ifdef RCS
+ ".CO :",
+ "\t$(CO) $(COFLAGS) $@",
+
+ ".CLEANUP :",
+ "\t$(RM) $(RMFLAGS) $?",
+ #endif RCS
+
".c.o :",
"\t$(CC) $(CFLAGS) -c $<",
***************
*** 152,159 ****
--- 169,183 ----
TIMETYPE
+ #ifndef RCS
exists(pname)
+ #else
+ exists(pname, ch)
+ #endif !RCS
struct nameblock *pname;
+ #ifdef RCS
+ struct chain **ch;
+ #endif RCS
{
struct stat buf;
register char *s, *filename;
***************
*** 176,182 ****
--- 200,216 ----
pname->alias = copys(s);
if(stat(pname->alias, &buf) == 0)
return(buf.st_mtime);
+ #ifdef RCS
+ if (coflag && ch)
+ return(getrcs(pname, pname->alias, ch));
+ else
+ return(0);
+ #endif RCS
}
+ #ifdef RCS
+ if (coflag && ch)
+ return(getrcs(pname, filename, ch));
+ #endif RCS
return(0);
}
else return(buf.st_mtime);
***************
*** 197,206 ****
--- 231,247 ----
+ #ifndef RCS
struct depblock *srchdir(pat, mkchain, nextdbl)
+ #else
+ struct depblock *srchdir(pat, mkchain, nextdbl, die)
+ #endif !RCS
register char *pat; /* pattern to be matched in directory */
int mkchain; /* nonzero if results to be remembered */
struct depblock *nextdbl; /* final value for chain */
+ #ifdef RCS
+ int die; /* fatal error if we can't open dir */
+ #endif RCS
{
DIR *dirf;
register int i;
***************
*** 214,219 ****
--- 255,263 ----
struct varblock *cp, *varptr();
char *path, pth[BUFSIZ], *strcpy();
struct direct *dptr;
+ #ifdef RCS
+ char temp2[BUFSIZ], *RCSpref;
+ #endif RCS
thisdbl = 0;
***************
*** 259,264 ****
--- 303,317 ----
*path++ = '\0';
break;
}
+ #ifdef RCS
+ RCSpref = NULL;
+ if (coflag && !mkchain) {
+ if (suffix(dirname, RCSdir, temp2))
+ RCSpref = temp2;
+ else
+ RCSpref = dirpref;
+ }
+ #endif RCS
dirf = NULL;
cldir = NO;
***************
*** 277,283 ****
dirf = opendir(dirname);
if(nopdir >= MAXDIR)
cldir = YES;
! else {
++nopdir;
od = ALLOC(dirhdr);
od->nxtopendir = firstod;
--- 330,336 ----
dirf = opendir(dirname);
if(nopdir >= MAXDIR)
cldir = YES;
! else if(dirf != NULL) {
++nopdir;
od = ALLOC(dirhdr);
od->nxtopendir = firstod;
***************
*** 290,298 ****
--- 343,360 ----
if(dirf == NULL)
{
+ #ifdef RCS
+ if (die) {
+ #endif RCS
fprintf(stderr, "Directory %s: ", dirname);
fatal("Cannot open");
}
+ #ifdef RCS
+ if (endir)
+ *endir = '/';
+ return(NULL);
+ }
+ #endif RCS
else for (dptr = readdir(dirf); dptr != NULL; dptr = readdir(dirf))
{
***************
*** 312,317 ****
--- 374,396 ----
thisdbl->depname = q;
nextdbl = thisdbl;
}
+ #ifdef RCS
+ /*
+ * if RCSpref is non-null, it is the dirpref
+ * without the "RCS/". This, along with RCS_SUF
+ * is stripped so implicit rules can find the
+ * corresponding files
+ */
+ if (!suffix(nbuf, RCSsuf, nbuf))
+ continue;
+ if (RCSpref)
+ p1=ncat(fullname, RCSpref, -1);
+ else
+ p1 = fullname;
+ ncat(p1, nbuf, -1);
+ if (srchname(fullname) == NULL)
+ makename(copys(fullname));
+ #endif RCS
}
}
***************
*** 666,668 ****
--- 745,905 ----
}
*d = '\0';
}
+ #ifdef RCS
+
+ extern char *rindex();
+ extern struct chain *appendq();
+
+ /*
+ * Try to find an RCS file corresponding to 'filename', and return
+ * the modified time of the RCS file.
+ * If ch is non-null, then append it on the chain for later check-out
+ */
+ TIMETYPE
+ getrcs(p, filename, ch)
+ struct nameblock *p;
+ register char *filename;
+ struct chain **ch;
+ {
+ struct stat sbuf;
+ char temp[BUFSIZ];
+ register char *tail;
+ register char *s;
+ int headlen;
+
+ if ((tail = rindex(filename, '/')) == NULL) {
+ headlen = 0;
+ tail = filename;
+ } else
+ headlen = ++tail - filename;
+ s = ncat(temp, filename, headlen);
+ s = ncat(s, RCSdir, -1);
+ *s++ = '/';
+ s = ncat(s, tail, -1);
+ ncat(s, RCSsuf, -1);
+ if (stat(temp, &sbuf) < 0) {
+ concat(filename, RCSsuf, temp);
+ if (stat(temp, &sbuf) < 0)
+ return(0);
+ }
+ p->RCSnamep = copys(temp);
+ if (ch)
+ *ch = appendq(*ch, filename);
+ return(sbuf.st_mtime);
+ }
+
+ /*
+ * Try to check-out the files specified in ch, if they do not
+ * already exist. If rmflag is true, mark successful attempts
+ * for automatic deletion.
+ * Try to make the modified time of the file the same as that of the
+ * RCS file.
+ */
+ co(ch)
+ register struct chain *ch;
+ {
+ register struct nameblock *p;
+ register char *file;
+ char *RCSfile;
+ struct stat sbuf;
+ int i;
+ time_t tm[2];
+
+ for ( ; ch; ch = ch->nextp) {
+ if ((file=ch->datap) == NULL || (p=srchname(file)) == NULL)
+ continue;
+ if (stat(file, &sbuf) == 0)
+ continue; /* don't do it again */
+ RCSfile = p->RCSnamep;
+ p->RCSnamep = NULL;
+ setvar("@", file);
+ setvar("<", RCSfile);
+ i = docom(co_cmd);
+ setvar("@", (char *) NULL); /* so it doesn't get deleted */
+ if (i)
+ continue; /* docom() failed */
+ /*
+ * since we succeeded, mark it for later deletion
+ */
+ if (rmflag && !isprecious(file))
+ rmchain = appendq(rmchain, file);
+ /*
+ * try to set modified time on file
+ */
+ if (stat(RCSfile, &sbuf) == 0) {
+ tm[0] = time((time_t *) NULL);
+ tm[1] = sbuf.st_mtime;
+ utime(file, tm);
+ }
+ }
+ }
+
+ /*
+ * delete the files listed in rmchain
+ */
+
+ rm ()
+ {
+ register struct chain *q;
+ struct nameblock *p;
+ register struct lineblock *lp;
+ register struct shblock *sp;
+ static int once = 0;
+
+ if (once || (q = rmchain) == NULL) /* only if we should */
+ return;
+ once = 1;
+ if ((p = srchname(".CLEANUP")) == NULL)
+ return;
+ sp = NULL;
+ for (lp = p->linep; lp; lp = lp->nxtlineblock)
+ if (sp = lp->shp)
+ break;
+ if (sp == NULL) /* no or NULL .CLEANUP ? */
+ return;
+ setvar("?", mkqlist(q));
+ docom(sp);
+ }
+
+ /*
+ * Do the srchdir for RCS files. For a pattern a/b, it searches
+ * a/RCS/b, without generating an error if it doesn't exist
+ */
+ srchRCS(pat)
+ register char *pat;
+ {
+ char temp[BUFSIZ];
+ int headlen;
+ register char *tail, *s;
+
+ if ((tail = rindex(pat, '/')) == NULL) {
+ /* quick search for '.' */
+ if (dotRCS) {
+ s = ncat(temp, RCSdir, -1);
+ *s++ = '/';
+ ncat(s, pat, -1);
+ srchdir(temp, NO, (struct depblock *) NULL, NO);
+ #ifdef RCSROOT
+ } else if (rootRCS) {
+ s = ncat(temp, RCSdir, -1);
+ ncat(s, pat, -1);
+ srchdir(temp, NO, (struct depblock *) NULL, NO);
+ #endif RCSROOT
+ }
+ return;
+ #ifdef RCSROOT
+ } else if (rootRCS) {
+ s = ncat(temp, RCSdir, -1);
+ ncat(s, pat, -1);
+ #endif RCSROOT
+ } else {
+ tail++;
+ headlen = tail - pat;
+ s = ncat(temp, pat, headlen);
+ s = ncat(s, RCSdir, -1);
+ *s++ = '/';
+ ncat(s, tail, -1);
+ }
+ srchdir(temp, NO, (struct depblock *) NULL, NO);
+ }
+ #endif RCS
Index: main.c
*** /tmp/,RCSt1005825 Fri Aug 14 13:42:36 1987
--- main.c Fri Aug 14 13:39:25 1987
***************
*** 1,5 ****
--- 1,8 ----
/*
* $Log: main.c,v $
+ * Revision 1.3 87/08/14 13:39:21 gww
+ * Add RCS and RCSROOT support.
+ *
* Revision 1.2 87/08/07 14:06:06 gww
* Add include Files feature.
*
***************
*** 7,30 ****
* Initial revision
*
*/
! static char *ERcsId = "$Header: main.c,v 1.2 87/08/07 14:06:06 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)main.c 4.8 (Berkeley) 86/01/09";
# include "defs"
/*
command make to update programs.
! Flags: 'd' print out debugging comments
'p' print out a version of the input graph
's' silent mode--don't print out commands
'f' the next argument is the name of the description file;
"makefile" is the default
'i' ignore error codes from the shell
'S' stop after any command fails (normally do parallel work)
'n' don't issue, just print, commands
't' touch (update time of) files but don't issue command
'q' don't do anything, but check if object is up to date;
returns exit code 0 if up to date, -1 if not
*/
struct nameblock *mainname = NULL;
struct nameblock *firstname = NULL;
struct lineblock *sufflist = NULL;
--- 10,45 ----
* Initial revision
*
*/
! static char *ERcsId = "$Header: main.c,v 1.3 87/08/14 13:39:21 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)main.c 4.8 (Berkeley) 86/01/09";
# include "defs"
/*
command make to update programs.
! Flags:
! 'c' don't check out RCS files
! 'C' check out RCS files (default)
! 'd' print out debugging comments
'p' print out a version of the input graph
's' silent mode--don't print out commands
'f' the next argument is the name of the description file;
"makefile" is the default
'i' ignore error codes from the shell
+ 'k' don't stop after any command fails (default)
'S' stop after any command fails (normally do parallel work)
'n' don't issue, just print, commands
+ 'r' don't use default rules
't' touch (update time of) files but don't issue command
+ 'u' don't unlink RCS working files
+ 'U' unlink RCS working files
'q' don't do anything, but check if object is up to date;
returns exit code 0 if up to date, -1 if not
*/
+ /*
+ * This version is based on the modifications made to the 4.1 make
+ * made by Charles LaBrec, Purdue University Physics Dept.
+ */
+
struct nameblock *mainname = NULL;
struct nameblock *firstname = NULL;
struct lineblock *sufflist = NULL;
***************
*** 32,37 ****
--- 47,71 ----
struct pattern *firstpat = NULL;
struct dirhdr *firstod = NULL;
+ #ifdef RCS
+ struct shblock *co_cmd = NULL;
+ struct chain *rmchain = NULL;
+
+ #include <sys/stat.h>
+
+ int rmflag = YES;
+ int coflag = YES;
+ char RCSdir[BUFSIZ] = "RCS";
+ char *RCSsuf = RCS_SUF;
+ int dotRCS = NO;
+ #ifdef RCSROOT
+ int rootRCS = NO;
+ #endif RCSROOT
+ int sighvalue = 0;
+ int sigtvalue = 0;
+ extern char *getenv(), *getwd();
+ #endif RCS
+
#include <signal.h>
int sigivalue = 0;
int sigqvalue = 0;
***************
*** 73,78 ****
--- 107,117 ----
int intrupt();
#endif
char *op = options + 1;
+ #ifdef RCS
+ struct lineblock *lp;
+ struct stat sbuf;
+ struct chain *ch;
+ #endif RCS
#ifdef METERFILE
***************
*** 102,107 ****
--- 141,156 ----
*op++ = c;
switch (c) {
+ #ifdef RCS
+ case 'c':
+ coflag = NO;
+ break;
+
+ case 'C':
+ coflag = YES;
+ break;
+ #endif RCS
+
case 'd':
dbgflag = YES;
break;
***************
*** 142,147 ****
--- 191,206 ----
questflag = YES;
break;
+ #ifdef RCS
+ case 'u':
+ rmflag = NO;
+ break;
+
+ case 'U':
+ rmflag = YES;
+ break;
+ #endif RCS
+
case 'f':
op--; /* don't pass this one */
if(i >= argc-1)
***************
*** 175,180 ****
--- 234,250 ----
if(prtrflag) printdesc(NO);
+ #ifdef RCS
+ if (p = srchname(".CO")) {
+ for (lp = p->linep; lp; lp = lp->nxtlineblock)
+ if ((co_cmd = lp->shp) != NULL)
+ break;
+ if (co_cmd == NULL)
+ coflag = NO;
+ } else
+ coflag = NO;
+ #endif RCS
+
if( srchname(".IGNORE") ) ++ignerr;
if( srchname(".SILENT") ) silflag = 1;
if(p=srchname(".SUFFIXES")) sufflist = p->linep;
***************
*** 183,191 ****
--- 253,298 ----
#ifdef unix
sigivalue = (int) signal(SIGINT, SIG_IGN) & 01;
sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01;
+ #ifdef RCS
+ sighvalue = (int) signal(SIGHUP, SIG_IGN) & 01;
+ sigtvalue = (int) signal(SIGTERM, SIG_IGN) & 01;
+ #endif RCS
enbint(intrupt);
#endif
+ #ifdef RCS
+ if (stat(RCSdir, &sbuf) == 0 && (sbuf.st_mode & S_IFMT) == S_IFDIR)
+ dotRCS = YES; /* fast check for ./RCS */
+ #ifdef RCSROOT
+ /* NOTE: dotRCS == YES implies rootRCS == NO */
+ else {
+ char pathname[BUFSIZ];
+ char *rcsroot;
+
+ if (rcsroot = getenv("RCSROOT")) {
+ strcpy(RCSdir, rcsroot);
+ strncat(RCSdir, getwd(pathname), BUFSIZ);
+ if ((stat(RCSdir, &sbuf) == 0) &&
+ ((sbuf.st_mode & S_IFMT) == S_IFDIR)) {
+ strncat(RCSdir, "/", BUFSIZ);
+ rootRCS = YES;
+ }
+ }
+ if (!rootRCS) {
+ strcpy(RCSdir, "/RCS");
+ strncat(RCSdir, getwd(pathname), BUFSIZ);
+ if ((stat(RCSdir, &sbuf) == 0) &&
+ ((sbuf.st_mode & S_IFMT) == S_IFDIR)) {
+ strncat(RCSdir, "/", BUFSIZ);
+ rootRCS = YES;
+ }
+ else
+ RCSdir[0] = '\0';
+ }
+ }
+ #endif RCSROOT
+ #endif RCS
+
nfargs = 0;
for(i=1; i<argc; ++i)
***************
*** 196,202 ****
--- 303,314 ----
p = makename(s);
}
++nfargs;
+ #ifndef RCS
doname(p, 0, &tjunk);
+ #else
+ ch = NULL;
+ doname(p, 0, &tjunk, &ch);
+ #endif !RCS
if(dbgflag) printdesc(YES);
}
***************
*** 209,222 ****
--- 321,345 ----
if(mainname == 0)
fatal("No arguments or description file");
else {
+ #ifndef RCS
doname(mainname, 0, &tjunk);
+ #else
+ ch = NULL;
+ doname(mainname, 0, &tjunk, &ch);
+ #endif !RCS
if(dbgflag) printdesc(YES);
}
+ #ifndef RCS
exit(0);
+ #else
+ quit(0);
+ #endif !RCS
}
+ #ifndef RCS
#include <sys/stat.h>
+ #endif !RCS
#ifdef unix
intrupt()
***************
*** 238,244 ****
--- 361,371 ----
if(junkname[0])
unlink(junkname);
fprintf(stderr, "\n");
+ #ifndef RCS
exit(2);
+ #else
+ quit(2);
+ #endif !RCS
}
***************
*** 268,273 ****
--- 395,406 ----
signal(SIGINT,k);
if(sigqvalue == 0)
signal(SIGQUIT,k);
+ #ifdef RCS
+ if(sighvalue == 0)
+ signal(SIGHUP,k);
+ if(sigtvalue == 0)
+ signal(SIGTERM,k);
+ #endif RCS
}
#endif
Index: misc.c
*** /tmp/,RCSt1005830 Fri Aug 14 13:42:51 1987
--- misc.c Fri Aug 14 13:39:54 1987
***************
*** 1,5 ****
--- 1,8 ----
/*
* $Log: misc.c,v $
+ * Revision 1.3 87/08/14 13:39:26 gww
+ * Add RCS and RCSROOT support.
+ *
* Revision 1.2 87/08/07 14:06:10 gww
* Add include Files feature.
*
***************
*** 7,13 ****
* Initial revision
*
*/
! static char *ERcsId = "$Header: misc.c,v 1.2 87/08/07 14:06:10 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)misc.c 4.3 (Berkeley) 85/08/30";
#include "defs"
--- 10,16 ----
* Initial revision
*
*/
! static char *ERcsId = "$Header: misc.c,v 1.3 87/08/14 13:39:26 gww Exp $ ENIX BSD";
static char *sccsid = "@(#)misc.c 4.3 (Berkeley) 85/08/30";
#include "defs"
***************
*** 274,283 ****
--- 277,294 ----
if(s) fprintf(stderr, "Make: %s. Stop.\n", s);
else fprintf(stderr, "\nStop.\n");
#ifdef unix
+ #ifndef RCS
exit(1);
+ #else
+ quit(1);
+ #endif !RCS
#endif
#ifdef gcos
+ #ifndef RCS
exit(0);
+ #else
+ quit(0);
+ #endif !RCS
#endif
}
***************
*** 389,391 ****
--- 400,439 ----
return( (top == -1) ? 1 : 0 );
}
#endif INCLUDES
+
+ #ifdef RCS
+ quit(val)
+ int val;
+ {
+ if (rmflag) { /* clean up co'ed files */
+ touchflag = 0; /* don't try to touch anything */
+ rm();
+ }
+ exit(val);
+ }
+
+ /*
+ * ncat copies n chars of string b at a, returning a pointer to the
+ * null terminating a. This way, it can be used to daisy-chain.
+ * If n < 0, all chars of b will be copied
+ */
+ char *
+ ncat(a, b, n)
+ register char *a, *b;
+ register int n;
+ {
+ if (n < 0) {
+ while(*a++ = *b++)
+ ;
+ return(--a);
+ } else {
+ if (n != 0)
+ do {
+ if ((*a++ = *b++) == '\0')
+ return(--a);
+ } while (--n);
+ *a = '\0';
+ return(a);
+ }
+ }
+ #endif RCS
Index: /usr/man/man1/make.1
*** /tmp/,RCSt1005207 Thu Mar 10 15:48:37 1988
--- make.1e Thu Mar 10 15:47:58 1988
***************
*** 1,6 ****
! .\" $Header: make.1e,v 1.2 87/08/07 15:01:04 gww Exp $ ENIX BSD
.\"
.\" $Log: make.1e,v $
.\" Revision 1.2 87/08/07 15:01:04 gww
.\" Add include support.
.\"
--- 1,9 ----
! .\" $Header: make.1e,v 1.3 88/03/10 15:47:50 gww Exp $ ENIX BSD
.\"
.\" $Log: make.1e,v $
+ .\" Revision 1.3 88/03/10 15:47:50 gww
+ .\" Add RCS support.
+ .\"
.\" Revision 1.2 87/08/07 15:01:04 gww
.\" Add include support.
.\"
***************
*** 149,155 ****
is inferred.
The default list is
.IP
! \&.SUFFIXES: .out .o .c .e .r .f .y .l .s .p
.PP
The rule to create a file with suffix
.I s2
--- 152,158 ----
is inferred.
The default list is
.IP
! \&.SUFFIXES: .out .o .c .F .f .e .r .y .yr .ye .l .s .cl .p
.PP
The rule to create a file with suffix
.I s2
***************
*** 216,221 ****
--- 219,226 ----
.PP
Command lines are executed one at a time, each by its
own shell.
+ The default shell is
+ .IR sh (1).
A line is printed when it is executed unless
the special target `.SILENT'
is in
***************
*** 249,256 ****
--- 254,384 ----
is interpreted.
Includes may be nested up to 20 deep.
.PP
+ .I Make
+ functions in conjunction with RCS (Revision Control System).
+ Unless the \-c option is specified,
+ if the search for a file (called the working file) fails,
+ .I make
+ looks for a corresponding RCS file.
+ For example, if a file xxx does not exist, ./RCS/xxx,v,
+ then enviroment variable RCSROOT/\fIcurrent-directory\fP/xxx,v,
+ then /RCS/\fIcurrent-directory\fP/xxx,v,
+ and finally ./xxx,v are searched for in that order.
+ (When subdirectories are specified, e.g., xxx/yyy, xxx/RCS/yyy,v,
+ RCSROOT/\fIcurrent-directory\fP/xxx/yyy,v,
+ /RCS/\fIcurrent-directory\fP/xxx/yyy,v,
+ and xxx/yyy,v are tried.)
+ If the search is successful, the `last modified' time of the RCS file
+ is considered to be the modified time of the working file, and
+ .I make
+ remembers that the working file must be checked out.
+ When the time comes to actually make a target, each of these dependents
+ is retrieved from RCS using the target `.CO'.
+ The default rule is:
+ .RS
+ .HP
+ .PD 0
+ .nf
+ \&.CO:
+ $(CO) $(COFLAGS) $@
+ .fi
+ .RE
+ .PD
+ .PP
+ where by default
+ .PP
+ .RS
+ .nf
+ CO = co
+ COFLAGS = -q
+ .fi
+ .RE
+ .PP
+ Also, the special macro `$@' is set to the name of the working
+ file and `$<' to the name of the RCS file (in the spirit that
+ this is an implicit command).
+ Note, however, that `$?' and `$*' have no meaning here.
+ Furthermore, after the check-out is complete,
+ .I make
+ will try to set the modified time of `$@' to that of the RCS file
+ in accordance with its earlier assumption.
+ Since this is the time that has been used throughout execution,
+ there is no way to avoid this action.
+ Also, unless \-u was specified or the working file is mentioned as
+ a dependent of `.PRECIOUS', it will be removed on exit.
+ If the `.CO' target is missing or has no commands associated with it,
+ then the effect is the same as if \-c had been specified.
+ .PP
+ When
+ .I make
+ terminates, if any files that were automatically checked out are marked
+ for deletion,
+ it will run the special target `.CLEANUP'.
+ The default rule is:
+ .nf
+ .RS
+ .HP
+ .PD 0
+ \&.CLEANUP:
+ $(RM) $(RMFLAGS) $?
+ .PD
+ .RE
+ .fi
+ .PP
+ where:
+ .PP
+ .RS
+ .nf
+ RM = rm
+ RMFLAGS = -f
+ .RE
+ .fi
+ .PP
+ and the macro `$?' is set to the names of the files that
+ were checked out previously and are not dependents of the
+ target `.PRECIOUS'.
+ If `.CLEANUP' is missing, has no commands associated with it, or `$?'
+ is blank, the effect is the same as if \-u had been specified.
+ .PP
+ The exact form of the `.CO' target is probably open to debate.
+ Since
+ .IR co (1)
+ strips subdirectories from working file names, but not RCS file names,
+ the `correct' form of the `.CO' should probably be:
+ .PP
+ .RS
+ $(CO) $(COFLAGS) -p $< > $@
+ .RE
+ .PP
+ However, in executing a command,
+ .I make
+ looks at it for the special shell characters:
+ .PP
+ .RS
+ =|^();&<>*?[]:$`'"\\\\n
+ .RE
+ .PP
+ If none are detected, the command is executed directly, without
+ a shell.
+ Thus, the latter form of the `.CO' target is less efficient, since
+ a shell must be used to do the redirection (`>').
+ Furthermore, the former description fails only when RCS files in
+ subdirectories other than `.' or `./RCS' must be checked out.
+ For this reason, the `less correct' rule has been chosen.
+ .PP
Other options:
.TP
+ .B \-c
+ If a file does not exist, do not try to find a corresponding
+ RCS file and check it out.
+ .TP
+ .B \-C
+ Try to get the file from RCS (this is the default).
+ .TP
+ .B \-d
+ Print debugging information (relatively useless except for
+ trying to find out what went wrong).
+ .TP
.B \-i
Equivalent to the special entry `.IGNORE:'.
.TP
***************
*** 263,284 ****
Trace and print, but do not execute the commands
needed to update the targets.
.TP
! .B \-t
! Touch, i.e. update the modified date of targets, without
! executing any commands.
.TP
.B \-r
! Equivalent to an initial special entry `.SUFFIXES:'
! with no list.
.TP
.B \-s
Equivalent to the special entry
`.SILENT:'.
.SH FILES
makefile, Makefile
.br
.SH "SEE ALSO"
! sh(1), touch(1), f77(1), pc(1)
.br
S. I. Feldman
.I
--- 391,429 ----
Trace and print, but do not execute the commands
needed to update the targets.
.TP
! .B \-p
! Print a version of the input graph.
.TP
+ .B \-q
+ Don't do anything, but check if object is up to date.
+ Return exit status 0 if it is, -1 if it is not.
+ .TP
.B \-r
! Do not use the default set of rules.
! .TP
! .B \-S
! The inverse of
! .BR \-k .
.TP
.B \-s
Equivalent to the special entry
`.SILENT:'.
+ .TP
+ .B \-t
+ Touch, i.e. update the modified date of targets, without
+ executing any commands.
+ .TP
+ .B \-u
+ Don't cleanup files that were automatically checked-out from RCS.
+ .TP
+ .B \-U
+ Cleanup files that were automatically checked-out from RCS,
+ unless they are listed in the `.PRECIOUS' target (default).
.SH FILES
makefile, Makefile
.br
.SH "SEE ALSO"
! co(1E), rcs(1E), sh(1), touch(1), utime(1)
.br
S. I. Feldman
.I
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list