home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
misc_utils
/
dmake_440
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-19
|
33KB
|
1,283 lines
/*
* DMAKE.C
*
* (c)Copyright 1989 by Matthew Dillon, All Rights Reserved.
*
* ONLY AN APPROPRIATE AMIGA EXECUTABLE MAY BE DISTRIBUTED. DO
* NOT DISTRIBUTE SOURCE!
*
* This is a new try at makefiles ... read the documentation.
*/
#include "defs.h"
MLIST DepList; /* Dependancies */
short Verbose;
short Silent;
short LineNo;
short XDebug;
short ForceAll;
short ListOnly;
short Order;
long SaveLock;
char MakeFile[128];
main(ac, av)
char *av[];
{
short dofirst = 1;
short error = 0;
NewList(&DepList);
strcpy(MakeFile, "DMakefile");
SaveLock = CurrentDir(Lock("", SHARED_LOCK));
{
register short i;
short notenoughargs = 0;
for (i = 1; i < ac; ++i) {
register char *ptr = av[i];
if (*ptr != '-')
continue;
while (*++ptr) {
switch(*ptr) {
case 's':
++Silent;
break;
case 'v':
++Verbose;
break;
case 'd':
++XDebug;
break;
case 'n':
ListOnly = 1;
break;
case 'a':
ForceAll = 1;
break;
case 'f':
if (i + 1 < ac) {
strcpy(MakeFile, av[++i]);
av[i][0] = '-'; /* kill it */
} else {
notenoughargs = 1;
}
break;
}
}
}
if (notenoughargs) {
puts("Not enough args for option!");
xexit(20);
}
}
if (!Silent) {
puts("DMake Beta V0.6 26-Jan-89");
puts("(c)Copyright 1989 by Matthew Dillon, All Rights Reserved");
}
{
FILE *fi;
if (fi = fopen(MakeFile, "r")) {
ScanFile(fi);
fclose(fi);
} else {
printf("Unable to open %s\n", MakeFile);
xexit(25);
}
}
{
register short i;
for (i = 1; i < ac; ++i) {
register char *ptr = av[i];
register DEPEND *dep;
if (*ptr == '-')
continue;
dofirst = 0;
for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
if (strcmp(ptr, dep->Left) == 0) {
/* XXX ? */
Order = FindBeginPoint(dep, Order, 1);
break;
}
}
if (dep == NULL) {
printf("Could not find %s dependancy\n", ptr);
error = 10;
}
}
}
if (dofirst) {
register DEPEND *dep = GetHead(&DepList);
if (dep)
Order = FindBeginPoint(dep, Order, 1);
}
CombineRefCnts(NULL);
if (XDebug)
PrintDepList(&DepList);
ExecuteDepList();
xexit(error);
}
xexit(error)
{
UnLock(CurrentDir(SaveLock));
exit(error);
}
ScanFile(fi)
FILE *fi;
{
char *ptr;
LineNo = 0;
while (ptr = getline(fi, NULL)) {
MLIST *cmdlist = malloc(sizeof(MLIST));
NewList(cmdlist);
++LineNo;
if (*ptr == 0) {
free(cmdlist);
continue;
}
{
register char *str = ptr;
while ((*str >= 'a' && *str <= 'z') || (*str >= 'A' && *str <= 'Z') ||
(*str >= '0' && *str <= '9') ||
*str == '_' || *str == ' ' || *str == '\t')
++str;
if (*str == '=') { /* macro assignment */
MacroAssign(ptr, str);
continue;
}
}
{
short ac;
register char **av;
register short i;
av = parseline(ptr, &ac);
for (i = 0; i < ac; ++i) {
if (av[i][0] == ':' && av[i][1] == 0)
break;
}
if (i == ac) { /* could be blah: */
register char *str = av[0];
register short len = strlen(str);
if (len && str[len-1] == ':') { /* blah: */
str[len-1] = 0;
CreateDependancies(cmdlist, av, 0, 1, 1, ac);
} else {
short cmmnt;
printf("Badly formed command line %ld\n", LineNo);
while (ptr = getline(fi, &cmmnt)) {
if (ptr[0] == 0 && !cmmnt)
break;
}
}
} else {
CreateDependancies(cmdlist, av, 0, i, i + 1, ac);
}
}
{
register NODE *node;
short cmmnt;
while (ptr = getline(fi, &cmmnt)) {
if (ptr[0] == 0 && !cmmnt)
break;
if (ptr[0]) {
node = malloc(sizeof(NODE) + strlen(ptr) + 1);
node->ln_Name = (char *)(node + 1);
strcpy(node->ln_Name, ptr);
AddTail(cmdlist, node);
}
}
}
}
if (XDebug)
PrintDepList(&DepList);
}
/*
* COMBINEREFCNTS()
*
* All dependancies with the same left hand side are supposed to have
* the same (shared) common structure. This ensures they do and is
* called after operations which might invalidate the rule.
*/
CombineRefCnts(newlist)
MLIST *newlist;
{
register DEPEND *d1, *d2;
/*
* First combine references within a new list, then combine references
* from the new list to the master list, then combine references in
* the master list.
*/
if (newlist) {
for (d1 = GetHead(newlist); d1; d1 = GetSucc(d1)) {
for (d2 = GetSucc(d1); d2; d2 = GetSucc(d2)) {
if (strcmp(d1->Left, d2->Left) == 0 && d1->Common != d2->Common)
Combine(d1, d2);
}
}
for (d1 = GetHead(newlist); d1; d1 = GetSucc(d1)) {
for (d2 = GetHead(&DepList); d2; d2 = GetSucc(d2)) {
if (strcmp(d1->Left, d2->Left) == 0 && d1->Common != d2->Common)
Combine(d1, d2); /* deplist's gets it */
}
}
}
for (d1 = GetHead(&DepList); d1; d1 = GetSucc(d1)) {
for (d2 = GetSucc(d1); d2; d2 = GetSucc(d2)) {
if (strcmp(d1->Left, d2->Left) == 0 && d1->Common != d2->Common)
Combine(d1, d2);
}
}
}
Combine(d1, d2)
DEPEND *d1, *d2;
{
register COMMON *c1 = d1->Common;
register COMMON *c2 = d2->Common;
if (XDebug) {
printf("Combine (%s : %s -> %s : %s) com %08lx %08lx (%ld+%ld) %02lx|%02lx\n",
d1->Left, d1->Right, d2->Left, d2->Right, c1, c2,
c1->RefCnt, c2->RefCnt,
c1->Flags, c2->Flags
);
}
c2->RefCnt += c1->RefCnt;
c2->Flags |= c1->Flags;
c1->RefCnt = 0;
c1->Flags = 0;
d1->Common = c2;
}
/*
* FINDBEGINPOINT()
*
* The specified left side was requested to execute. Search the list for
* common points (left side the same)
*
* Find those entries whos left sides match this entry's right side
* (depth first, recursively) and assign an ordering number. The ordering
* number is essential to guarentee proper execution order of dependancies
* since their list positions are random.
*/
FindBeginPoint(db, order, add)
register DEPEND *db;
{
register DEPEND *dep;
db->Flags |= DF_ALLOWED;
db->Order = order;
order += add;
for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
if (dep->Flags & DF_ALLOWED)
continue;
if (strcmp(dep->Left, db->Right) == 0)
order = FindBeginPoint(dep, order, add); /* DEPTH FIRST */
}
for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
if (dep->Flags & DF_ALLOWED)
continue;
if (dep->Common == db->Common) /* BREADTH SECOND */
order = FindBeginPoint(dep, order, add);
}
return(order);
}
/*
* EXECUTEDEPLIST()
* MAIN EXECUTION LOOP
*
* This is the main execution loop for DMake. It scans the dependancy
* list calling appropriate functions, determining associations, and
* doing timestamp comparisons if necessary.
*
* (1) For all dependancies which have yet to be handled by this loop
* (DF_DIDTHIS is NOT set).
*
* (i) does the right side exist as the left side of some other
* dependancy? If not
*
* (ii) unless forced or a wildcard, check the file timestamps
* on the left vs right side and set appropriate flags.
*
* (2) Execution phase. Take the highest priority (lowest Ordered)
* dependancy and attempt to execute it. Collect all dependancies
* with a common left side. At this time any dependancies marked
* DF_EXPANDRIGHT must be expanded (this may result in the reference
* count becomming non-zero in which case we must abort the execution
* phase until the new dependancies have been resolved).
*
* If all non-special (the 'meat', not the exhausted wildcarded
* dependancies) timestamp flag checks out, execute the command
* list.
*
*
*/
ExecuteDepList()
{
register DEPEND *dep, *dp;
register short changed = 1;
DEPEND *lowdep;
if (Verbose == 1) {
puts("\nINITIAL DEPLIST");
PrintDepList(&DepList);
puts("");
}
if (XDebug)
puts("ExecuteDepList");
while (changed) {
char identchanged = 1;
/*
* (1) Determine highest priority ready dependancy to execute and
* handle datestamp checking.
*/
changed = 0;
if (XDebug)
puts("while-changed-loop");
while (identchanged) {
if (XDebug)
puts("while-ident-changed-loop");
identchanged = 0;
lowdep = NULL;
for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
if (dep->Common->RefCnt < 0 || !(dep->Flags & DF_ALLOWED))
continue;
if (!(dep->Flags & DF_DIDTHIS)) {
/*
* (i) does the right side exist as the left side of
* some other dependancy? If not, decrement the
* reference count and if a wildcard handle
* expansion.
*/
for (dp = GetHead(&DepList); dp; dp = GetSucc(dp)) {
if (strcmp(dep->Right, dp->Left) == 0)
break; /* valid references exist */
}
if (dp == NULL) { /* don't exist, dec. ref cnt*/
identchanged = 1;
--dep->Common->RefCnt;
dep->Flags |= DF_DIDTHIS;
if (XDebug)
printf("EDL1: DECREMENT REF: %s : %s (%08lx) -> %ld\n",
dep->Left, dep->Right, dep->Common, dep->Common->RefCnt
);
/*
* handling expansion. If the right side is a wild
* card defer expansion until the execution phase
* (2). This is in case files have yet to be
* created that will effect the expansion. If not
* a wildcard, and not APPLYALL, then we must
* expand the left side (a rare occurance but what
* if somebody does this?: *.c : charlie)
*/
if (IsWildCard(dep->Right)) /* defer expansion unless a-a */
dep->Flags |= DF_EXPANDRIGHT;
else if (dep->Common->RefCnt == 0) {
if (IsWildCard(dep->Left) && !(dep->Flags & DF_APPLYALL))
DirectoryWildScan(dep, NULL, 1);
else
;/*AddCollect(dep, dep);*/
}
}
/*
* (ii)
* Unless forced or a wildcard, we do a time-date comparison
* on the left and right side. If the right side does not
* exist as a file, nothing changes. If the right side
* DOES exist as a file, the time-date comparison overides
* anything propogated from below. This allows:
*
* $(OBJS) : $(SRCS)
* cc ..
*
* $(SRCS) : ram:symbols.m
*/
if (!(dep->Flags & DF_OUTDATED) && !ForceAll && IsWildCard(dep->Left) == 0) {
short validright;
short od = OutDated(dep->Left, dep->Right, &validright);
if (Verbose == 2)
printf("COMPARE %s : %s, od = %ld vr = %ld\n", dep->Left, dep->Right, od, validright);
if (validright && !(dep->Flags & DF_OUTDATED)) {
if (od)
dep->Flags |= DF_OUTDATED;
else
dep->Flags |= DF_DATEDOK;
}
}
}
if (dep->Common->RefCnt != 0)
continue;
if (lowdep == NULL || dep->Order < lowdep->Order)
lowdep = dep;
}
}
if (Verbose == 1) {
puts("\nSTABLE DEPLIST:");
PrintDepList(&DepList);
puts("");
}
/*
* (2) Execution phase. **************
*
*/
dep = lowdep;
if (dep == NULL || dep->Common->RefCnt != 0)
continue;
changed = 1;
if (Verbose)
printf("PICKED: %s : %s (seq# %d)\n", dep->Left, dep->Right, dep->Order);
/*
* References have fallen to zero. We must scan the dependancies
* for all common nodes (common to left hand side), combine
* various collected variables (i.e. *.c etc..) and do a single
* execution run.
*
* But, if a right hand side is a wildcard and therefore has
* not been determined yet, we must do a DirectoryWildScan()
* and if the refcnt is no longer 0 abort the execution.
*/
if (XDebug) {
printf("\nEDL: Refs have fallen to 0 %s : %s (%08lx)\n",
dep->Left, dep->Right, dep->Common
);
PrintDepList(&DepList);
}
{
MLIST exelist;
DEPEND *nextdp;
char numdatedok = 0;
char numdeps = 0;
NewList(&exelist);
for (dp = GetHead(&DepList); dp; dp = nextdp) {
nextdp = GetSucc(dp);
/*
* Gather the common entries together into a list.
* Look at the time stamp information and handle that.
* Collect all non-wildcarded entries into a separate list
* in preparation for execution.
*/
if (dep->Common == dp->Common && (dp->Flags & DF_DIDTHIS)) {
if (XDebug)
printf("ready exe date: %s : %s %02lx\n", dp->Left, dp->Right, dp->Flags & DF_DATEDOK);
if (dp->Flags & DF_EXPANDRIGHT) {
dp->Flags &= ~DF_EXPANDRIGHT;
DirectoryWildScan(dp, NULL, 0);
}
if (IsWildCard(dp->Right)) {
if (XDebug)
printf("Warn: IsWildCard! %s : %s\n", dp->Left, dp->Right);
} else { /* remove into separate list */
++numdeps;
if ((dp->Flags & DF_DATEDOK) && !(dp->Flags & DF_OUTDATED))
++numdatedok;
Remove(dp);
AddTail(&exelist, dp);
}
}
}
/*
* If there are any dependancies in the list, the reference
* count is still 0, the left side is not a wildcard, and the
* date doesn't checkout, execute the list. Set the common
* flags according to whether the list was executed or not
* (propogation upwards of the timestamp comparison results).
*/
if (dep->Common->RefCnt == 0 && GetHead(&exelist) && !IsWildCard(dep->Left)) {
if (numdeps != numdatedok || numdeps == 0) {
ExecuteCmdCollection(&exelist);
dep->Common->Flags |= DF_OUTDATED;
} else {
dep->Common->Flags |= DF_DATEDOK;
}
}
while (dp = RemHead(&exelist))
AddTail(&DepList, dp);
}
/*
* RefCnt != 0, abort cleanup
*/
if (dep->Common->RefCnt != 0)
continue;
dep->Common->RefCnt = -1; /* RAN! */
/*
* After execution has completed, decrement any occurances
* of our left side (now complete) on the right of other
* dependancies.
*/
for (dp = GetHead(&DepList); dp; dp = GetSucc(dp)) {
if (strcmp(dep->Left, dp->Right) == 0 && !(dp->Flags & DF_DIDTHIS)) {
--dp->Common->RefCnt;
dp->Flags |= DF_DIDTHIS;
if (XDebug)
printf("EDL2: DECREMENT REF (RHR): %s : %s (%08lx) -> %ld\n",
dp->Left, dp->Right, dp->Common, dp->Common->RefCnt
);
/*
* If all of the dependancies for dep->Left had a valid
* time (nothing needed to be executed), propogate the
* information upwards.
*/
dp->Flags |= dep->Common->Flags & (DF_DATEDOK | DF_OUTDATED);
if (Verbose == 2) {
if (dep->Common->Flags & DF_OUTDATED)
printf("Propogate outdated (%s:%s) -> (%s:%s)\n", dep->Left, dep->Right, dp->Left, dp->Right);
else if (dep->Common->Flags & DF_DATEDOK)
printf("Propogate date ok (%s:%s) -> (%s:%s)\n", dep->Left, dep->Right, dp->Left, dp->Right);
}
if (IsWildCard(dp->Right)) /* defer expansion ??APPLYALL */
dp->Flags |= DF_EXPANDRIGHT;
if (dp->Common->RefCnt == 0) {
if (IsWildCard(dp->Left) && !(dp->Flags & DF_APPLYALL))
DirectoryWildScan(dp, NULL, 1);
}
}
if (XDebug)
PrintDepList(&DepList);
}
}
if (XDebug) {
puts("ExecuteDepList End");
PrintDepList(&DepList);
}
}
/*
* ExecuteCmdCollect()
*
* Given a list of dependancies (all with the same left side), add
* their right sides into the %(variable) table under the name
* specified by their collection entry. This is how all those object
* modules in all : *.o get combined to so the programmer can
* specify %(*.o) in the command list.
*
*/
ExecuteCmdCollection(list)
MLIST *list;
{
register DEPEND *dep = GetHead(list);
if (XDebug) {
printf("EXECUTE %s :", dep->Left);
for (; dep; dep = GetSucc(dep))
printf("<%s> ", dep->Right);
puts("");
}
ResetVarCollector();
for (dep = GetHead(list); dep; dep = GetSucc(dep)) {
if (dep->ColDep)
AddVarCollector(dep->Right, dep->ColDep->Right, 1);
else
AddVarCollector(dep->Right, dep->Right, 1);
AddVarCollector(dep->Right, "right", 0);
}
dep = GetHead(list);
AddVarCollector(dep->Left, "left", 0);
ExecuteCmdList(dep->CmdList);
}
/*
* Test if a file contains a wildcard or not.
*/
IsWildCard(str)
register char *str;
{
while (*str) {
if (*str == '*' || *str == '?')
return(1);
++str;
}
return(0);
}
/*
* DirectoryWildScan(dep, autolist, scanleft)
*
* This is the major wildcard dependancy handling call.
*
* (1) If we have *.o : <any> which is flagged DF_APPLYALL (any must
* depend on each derived .o file), we cannot handle the dependancy
* at this point so we undo the DF_DIDTHIS flag and return.
*
* (2) Either the right side is expanded and the left side derived or
* the left side is expanded and the right side derived. When one
* side is expanded, if the other side is NOT a wildcard it is left
* alone ( all:*.c -> all:a.c, all:b.c, all:c.c etc.. ).
*
* (3)
*
*/
DirectoryWildScan(dep, autolist, scanleft)
DEPEND *dep;
MLIST *autolist;
{
MLIST DList;
register DEPEND *dp;
short iswcleft = IsWildCard(dep->Left);
if (XDebug)
printf("DirectoryWildScan: %s : %s (%ld)\n", dep->Left, dep->Right, scanleft);
NewList(&DList);
/*
* (1) Unless scanleft is set (set when we must expand ONE side because
* it *IS* DF_APPLYALL, i.e. *.c : *.h -> a.c : *.h, b.c : *.h),
* we defer DF_APPLYALL operation until all other associated
* dependancies have been resolved. Otherwise we would be forced
* to evaluate the left-side wildcard too early .. perhaps before
* the files have been created.
*/
if (!scanleft && iswcleft && (dep->Flags & DF_APPLYALL)) {
++dep->Common->RefCnt;
dep->Flags &= ~DF_DIDTHIS;
return(0);
}
/*
* (2) Expand either the left side or the right side. Do either
* a directory scan or use a predetermined list. Handle the
* three cases: <wild>:<wild>, <norm>:<wild>, <wild:norm>
*
* The only time <wild>:<wild> will occur is with the DF_APPLYALL
* case.
*/
{
char *left = (iswcleft) ? dep->Left : dep->Right;
char *right= (scanleft) ? dep->Left : dep->Right;
if (autolist)
AutoExpandRightSide(&DList, left, right, autolist);
else
ExpandRightSide(&DList, left, right);
/*
* if not wc must set left side all the same (cause we did a hack
* above so we could call the Virtuo routine). Also, assign the
*
* if scanleft (left side guarenteed to be a wildcard), we need
* to set the right side all the same (cause... )
*/
for (dp = GetHead(&DList); dp; dp = GetSucc(dp)) {
dp->Flags |= DF_ALLOWED;
dp->Order = dep->Order;
if (iswcleft == 0)
dp->Left = dep->Left;
else if (scanleft)
dp->Right= dep->Right;
AddCollect(dp, dep);
}
CombineRefCnts(&DList); /* combine reference counts for new left sides */
}
/*
* (3) If the left side is not a wildcard we are done for now.
*/
if (XDebug)
puts("Main Combinational complete");
if (iswcleft == 0) {
if (XDebug)
puts("Left side not wc, end");
while (dp = RemHead(&DList)) {
dp->CmdList = dep->CmdList;
Order = FindBeginPoint(dp, Order, 1);
AddTail(&DepList, dp);
}
return(1);
}
/*
* (3) If the left side IS a wildcard, then scan the list for two cases
* (a) if the left wildcard appears on the LEFT side of any other
* dependancy in which DF_APPLYALL is set, we must break up
* those dependancies.
*
* *.o : *.c *.h -> *.o : *.c and *.o : *.h (APPLYALL),
* when *.o : *.c is resolved in (1)&(2), we must break up
* the apply all case *.o : *.h -> a.o : *.h, b.o : *.h
* etc...
*
* (b) if the left wildcard appears on the RIGHT side of any
* other dependancy we must expand them as well:
*
* all : *.o
* *.o : *.c when *.o : *.c is resolved, we must also
* resolve all : *.o -> all : a.o, all : b.o
*
* NOTE: all : *.o is allowed to DF_DIDTHIS since several
* dependancies might reference it:
*
* *.o : *.c
* *.o : *.asm
*
* There are THREE cases in this expansion. (i) the left side
* of the found dep (i.e. all : *.o in the example above) is
* NOT a wildcard (simple). (ii) the left side IS a wildcard
* and DF_APPLYALL is set, (iii) the left side IS a wildcard
* and DF_APPLYALL is not set.
*
* (i) all : *.o -> all : a.o, all : b.o
* (ii) *.x : *.h -> *.x : mike.h, *.x : ben.h
* ^DF_APPLYALL (ii)
* (iii) *.x : *.o -> a.x : a.o, b.x : b.o
*/
for (dp = GetHead(&DepList); dp; dp = GetSucc(dp)) {
/*
* (3a)
*/
if (strcmp(dep->Left, dp->Left) == 0 && (dp->Flags & DF_APPLYALL)) {
DEPEND *dp2, *newdep;
if (!(dp->Flags & DF_DIDTHIS)) {
--dp->Common->RefCnt;
dp->Flags |= DF_DIDTHIS;
}
dp->Flags &= ~(DF_APPLYALL | DF_EXPANDRIGHT);
if (XDebug)
printf("DidThis FLAG SET (DWS1) for %s : %s (%ld)\n",
dp->Left, dp->Right, dp->Common->RefCnt
);
/*
* For each expanded left side, generate left : wildright
*/
for (dp2 = GetHead(&DList); dp2; dp2 = GetSucc(dp2)) {
newdep = MakeOneDepend(dp2->Common, &DepList, dp2->Left, dp->Right);
newdep->Order = dp2->Order;
newdep->Flags |= DF_ALLOWED;
newdep->CmdList = dp->CmdList;
AddCollect(newdep, dp);
if (XDebug)
printf("*** Created APPLYALL dep: %s : %s\n", newdep->Left, newdep->Right);
}
}
/*
* If our wild left side appears on the right side of anybody
* else, we must expand them. How we expand them depends whether
* they are wildcarded &| APPLYALL.
*
* (3b.i,ii,iii)
*/
if (strcmp(dep->Left, dp->Right) == 0 && (dp->Flags & DF_ALLOWED)) {
if (XDebug)
printf("DidThis FLAG SET (DWS2) for %s : %s (%ld)(%08lx)\n",
dp->Left, dp->Right, dp->Common->RefCnt, dp
);
if (!(dp->Flags & DF_DIDTHIS)) {
if (XDebug)
printf("SET %08lx ref %08lx\n", dp, dp->Common);
--dp->Common->RefCnt;
dp->Flags |= DF_DIDTHIS;
} else {
if (XDebug)
printf("NOTSET %08lx ref %08lx\n", dp, dp->Common);
}
if (dp->Common->RefCnt < 0) {
puts("INTERNAL ERROR #Directory-1");
xexit(30);
}
/*
* (3b. i, ii, iii). Here (i) is taken care of by checking
* if the left side is a wildcard... we skip the if. Inside
* the if (ii) and (iii) are handled.
*/
if (IsWildCard(dp->Left)) { /* create mult refs to mult objects */
/*
* (ii) APPLYALL flagged
*/
if (dp->Flags & DF_APPLYALL) {
DEPEND *dp2, *newdep;
if (!(dp->Flags & DF_DIDTHIS)) {
dp->Flags |= DF_DIDTHIS;
--dp->Common->RefCnt;
for (dp2 = GetHead(&DList); dp2; dp2 = GetSucc(dp2)) {
newdep = MakeOneDepend(dp->Common, &DepList, dp->Left, dp2->Left);
newdep->Order = dp->Order;
if (XDebug)
printf("Common: %s : %s now %d\n", dp->Left, dp->Right, dp->Common->RefCnt);
newdep->Flags |= DF_ALLOWED | DF_APPLYALL;
newdep->CmdList = dp->CmdList;
AddCollect(newdep, dp); /* RefCnt must be stable */
}
}
} else {
/*
* (iii) *.o : *.c -> a.o : a.c, b.o : b.c etc...
* Simple recurse.
*/
DirectoryWildScan(dp, &DList, 0);
}
} else { /* create multiple refs to one object */
/*
* (i) left side is not a wildcard, all : *.o
*/
DEPEND *dp2, *newdep;
for (dp2 = GetHead(&DList); dp2; dp2 = GetSucc(dp2)) {
newdep = MakeOneDepend(dp->Common, &DepList, dp->Left, dp2->Left);
newdep->Order = dp->Order;
if (XDebug)
printf("Common: %s : %s now %d\n", dp->Left, dp->Right, dp->Common->RefCnt);
newdep->Flags |= DF_ALLOWED;
newdep->CmdList = dp->CmdList;
AddCollect(newdep, dp); /* RefCnt must be stable */
}
}
}
}
/*
* For each of the new dependancies, FindBeginPoint() them (to handle
* special cases for wildcarded objects) and add them to the main list.
* Also note that we must CombineRefCnts() to combine the common
* structures (all dependancies with the same left side must point
* to the same shared common structure).
*
* (4) i.e. you have *.o : *.c and also have a special case like
* charlie.o : cook_takes_the_cake
*
*/
CombineRefCnts(&DList);
while (dp = RemHead(&DList)) {
dp->CmdList = dep->CmdList;
FindBeginPoint(dp, dep->Order, 0);
AddTail(&DepList, dp);
}
return(1);
}
/*
* AutoExpandRightSide()
*
* This routine works like ExpandRightSide(), but instead of scanning a
* directory it derives the results from a passed list of dependancies.
* The reasoning behind this follows: ram:*.o : *.c , DMake will
* scan the directory for *.c and derive ram:*.o without scaning ram:.
* After all, there might be additional .o files in ram: that we do NOT
* want to include.
*
* The previously found file's left side matches the new right side.
*/
AutoExpandRightSide(newlist, left, right, oldlist)
MLIST *newlist;
char *left;
char *right;
MLIST *oldlist;
{
register DEPEND *dp;
if (XDebug)
printf("AutoExpandRightSide %s : %s\n", left, right);
for (dp = GetHead(oldlist); dp; dp = GetSucc(dp)) {
MakeOneDepend(NULL, newlist, VirtuoExpand(left, right, dp->Left), dp->Left);
}
if (XDebug)
puts("AutoExpandRightSide done");
}
/*
* ExpandRightSide()
*
* This routine does a directory scan of the right side and creates
* a set of dependancies, placing them in the specified list.
*/
ExpandRightSide(newlist, left, right)
MLIST *newlist;
char *left;
char *right;
{
char *ptr;
int ac;
register char **av;
register short i;
char **expand();
if (XDebug)
printf("ExpandRightSide <%s> : <%s>\n", left, right);
av = expand(right, &ac);
if (XDebug) {
for (i = 0; i < ac; ++i)
printf("(%s)", av[i]);
puts("");
}
for (i = 0; i < ac; ++i)
MakeOneDepend(NULL, newlist, VirtuoExpand(left, right, av[i]), av[i]);
if (XDebug)
puts("ExpandRightSide done");
}
/*
* VirtuoExpand("x*.poof", "*.o", "charlie.o") -> xcharlie.poof
*
* This converts a filename from one name to another using the two
* provided wildcards (old and new).
*/
char *
VirtuoExpand(newwc, oldwc, filename)
register char *newwc, *oldwc, *filename;
{
char *newbase = newwc;
if (XDebug)
printf("VEIN: <%s> <%s> <%s>\n", newwc, oldwc, filename);
{ /* skip non-wildcards */
register char *old = oldwc;
register char *name = filename;
while (*old && *old != '*' && *old != '?') {
if (*name != *old) /* failure! */
return(NULL);
++name;
++old;
}
oldwc = old;
filename = name;
}
{ /* skip non wildcards in new */
register char *new = newwc;
while (*new && *new != '*' && *new != '?')
++new;
newwc = new;
}
if (*newwc != *oldwc) /* new pattern must match old */
return(NULL);
if (*oldwc == 0 && *filename == 0)
return(newbase); /* success! */
/*
* at this point, *oldwc == *newwc == '*' or '?'
*/
if (*oldwc == '?') { /* match a single char in *filename */
char *last = VirtuoExpand(newwc + 1, oldwc + 1, filename + 1);
char *str;
short i;
if (!last)
return(NULL);
/*
* combine (newbase..newwc) with *filename with last
*/
i = newwc - newbase;
str = malloc(i + strlen(last) + 2);
movmem(newbase, str, i);
str[i] = *filename;
strcpy(str+i+1, last);
return(str);
}
/*
* *oldwc == *newwc == '*', we must try to match all or part of
* the remaining filename.
*/
{
char *fi = filename + strlen(filename);
while (fi >= filename) {
char *last;
char *str;
short i, j;
if (last = VirtuoExpand(newwc + 1, oldwc + 1, fi)) {
/*
* combine (newbase..newwc with filename..fi with last
*/
i = newwc - newbase;
j = fi - filename;
str = malloc(i + j + strlen(last) + 1);
movmem(newbase, str, i);
movmem(filename, str + i, j);
strcpy(str + i + j, last);
return(str);
}
--fi;
}
}
return(NULL);
}
/*
* CreateDependancies()
*
* Given a just-parsed line from the initial file scan, this routine
* breaks it up into individual dependancies with a left and right side.
*
* It is pretty straight forward (see the dmake rules). Note that the
* APPLYALL flag must be set for dependancies like this:
* *.o : *.c *.h (set APPLYALL for *.o : *.h to prevent
* it from being misinterpreted later)
*
* each .c files depends on its .o file, but each .o files depends on
* ALL the .h files.
*/
CreateDependancies(cmdlist, av, ls, le, rs, re)
MLIST *cmdlist;
char **av;
short ls, le, rs, re;
{
register short i;
MLIST deplist;
NewList(&deplist);
if (Verbose == 4) {
printf("CreateDependancies %08lx %08lx %ld %ld %ld %ld\n",
cmdlist, av, ls, le, rs, re
);
for (i = 0; i + ls < le; ++i)
printf("left: %08lx <%s>\n", av[ls+i], av[ls+i]);
for (i = 0; i + rs < re; ++i)
printf("rght: %08lx <%s>\n", av[rs+i], av[rs+i]);
}
for (i = 0; ls + i < le && rs + i < re; ++i) {
MakeOneDepend(NULL, &deplist, av[ls+i], av[rs+i]);
}
while (ls + i < le) { /* only left guys remain */
if (rs == re) { /* special case, right side was empty */
MakeOneDepend(NULL, &deplist, av[ls + i], NULL);
} else if (rs + 1 == re) {
MakeOneDepend(NULL, &deplist, av[ls + i], av[rs]);
} else {
printf("Error line %ld. Under normal conditions one has the\n", LineNo);
puts("same number of dependancies on the left as on the right,");
puts("or more on the right. The only two cases allowed for more");
puts("on the left is when the right has 0 or 1 arguments");
xexit(25);
}
++i;
}
{ /* only right guys remain. Make all left's dep. on them. */
/* note: operation must be defered for wildcards on left */
register DEPEND *dbase = GetTail(&deplist);
if (dbase) {
while (rs + i < re) {
register DEPEND *dep, *new;
for (dep = dbase; dep; dep = GetPred(dep)) {
new = MakeOneDepend(dep->Common, &deplist, dep->Left, av[rs + i]);
if (IsWildCard(new->Left) /*&& !IsWildCard(new->Right)*/)
new->Flags |= DF_APPLYALL;
}
++i;
}
}
}
{
register DEPEND *dep;
while (dep = RemHead(&deplist)) {
dep->CmdList = cmdlist;
AddTail(&DepList, dep);
}
}
}
/*
* MakeOneDepend()
*
* Note: the fact that it adds to the tail of the list is counted on in
* an earlier routine. This creates a new dependancy. Note, however,
* that the common node might be allocated thus invalidating the rule
* that all dependancies with the same dep->Left have the same common
* structure. This is dealt with by calling CombineRefCnts().
*/
DEPEND *
MakeOneDepend(common, list, left, right)
register COMMON *common;
MLIST *list;
char *left;
char *right;
{
register DEPEND *dep = malloc(sizeof(DEPEND));
if (!common) {
common = malloc(sizeof(COMMON));
clrmem(common, sizeof(COMMON));
}
clrmem(dep, sizeof(DEPEND));
++common->RefCnt;
dep->Common = common;
dep->Left = left;
dep->Right= (right) ? right : "";
AddTail(list, dep);
if (XDebug)
printf("MakeOneDepend dep %08lx com %08lx %d %s : %s\n", dep, common, common->RefCnt, left, right);
return(dep);
}
/*
* ADDCOLLECT()
*
* Set dep's collection to dp (always dp->Right). I.E. when you have
* something like: *.o : *.c *.h, cc %(*.c) -o %(left). The individual
* C files get placed in the *.c collection one at a time so they can be
* referenced by a % variable
*/
AddCollect(dep, dp)
register DEPEND *dep;
DEPEND *dp;
{
dep->Flags |= DF_COLLECT;
dep->Common->Flags |= DF_COLLECT;
dep->ColDep = dp;
}
/*
* low level routines
*/
char LineBuf[4096];
char *
getline(fi, pcmmnt)
FILE *fi;
short *pcmmnt;
{
register short i = 0;
if (pcmmnt)
*pcmmnt = 0;
while (fgets(LineBuf + i, sizeof(LineBuf) - i, fi)) {
if (i == 0 && LineBuf[i] == '#') {
LineBuf[i] = 0;
if (pcmmnt)
*pcmmnt = 1;
}
i += MacroReplace(0, LineBuf + i, strlen(LineBuf + i));
while (i-- && (LineBuf[i] == '\n' || LineBuf[i] == '\t' || LineBuf[i] == ' '))
LineBuf[i] = 0;
if (LineBuf[i] == '\\') /* line continuance */
continue;
if (XDebug)
printf("LINE: %s\n", LineBuf);
return(LineBuf);
}
return(NULL);
}
char **
parseline(ptr, pac)
register char *ptr;
short *pac;
{
char *pbuf = malloc(strlen(ptr)+1);
static char *av[1024];
register short ac = 0;
strcpy(pbuf, ptr);
ptr = pbuf;
while (*ptr) {
while (*ptr == ' ' || *ptr == '\t')
++ptr;
av[ac++] = ptr;
while (*ptr && *ptr != ' ' && *ptr != '\t')
++ptr;
if (*ptr)
*ptr++ = 0;
}
*pac = ac;
return(av);
}
PrintDepList(list)
MLIST *list;
{
register DEPEND *dep;
puts("(DEP LIST)");
for (dep = GetHead(list); dep; dep = GetSucc(dep)) {
printf("dep: %02lx %2ld (#%2ld)(%08lx) %s : %s",
dep->Flags,
dep->Common->RefCnt,
dep->Order,
dep->Common,
dep->Left,
dep->Right
);
if (dep->Flags & DF_COLLECT) {
printf(" (collect to %s)", dep->ColDep->Right);
}
puts("");
}
puts("(END OF DEP LIST)");
}