version 1.2, 1995/12/14 03:23:36 |
version 1.3, 1995/12/17 13:42:02 |
|
|
/* $NetBSD: parse.c,v 1.17 1995/11/02 23:55:03 christos Exp $ */ |
/* $NetBSD: parse.c,v 1.18 1995/12/16 05:03:13 christos Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California. |
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California. |
|
|
#if 0 |
#if 0 |
static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91"; |
static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91"; |
#else |
#else |
static char rcsid[] = "$NetBSD: parse.c,v 1.17 1995/11/02 23:55:03 christos Exp $"; |
static char rcsid[] = "$NetBSD: parse.c,v 1.18 1995/12/16 05:03:13 christos Exp $"; |
#endif |
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
|
|
NotParallel, /* .NOTPARALELL */ |
NotParallel, /* .NOTPARALELL */ |
Null, /* .NULL */ |
Null, /* .NULL */ |
Order, /* .ORDER */ |
Order, /* .ORDER */ |
|
Parallel, /* .PARALLEL */ |
ExPath, /* .PATH */ |
ExPath, /* .PATH */ |
Precious, /* .PRECIOUS */ |
Precious, /* .PRECIOUS */ |
ExShell, /* .SHELL */ |
ExShell, /* .SHELL */ |
Silent, /* .SILENT */ |
Silent, /* .SILENT */ |
SingleShell, /* .SINGLESHELL */ |
SingleShell, /* .SINGLESHELL */ |
Suffixes, /* .SUFFIXES */ |
Suffixes, /* .SUFFIXES */ |
|
Wait, /* .WAIT */ |
Attribute /* Generic attribute */ |
Attribute /* Generic attribute */ |
} ParseSpecial; |
} ParseSpecial; |
|
|
static ParseSpecial specType; |
static ParseSpecial specType; |
|
static int waiting; |
|
|
/* |
/* |
* Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER |
* Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER |
|
|
{ ".MFLAGS", MFlags, 0 }, |
{ ".MFLAGS", MFlags, 0 }, |
{ ".NOTMAIN", Attribute, OP_NOTMAIN }, |
{ ".NOTMAIN", Attribute, OP_NOTMAIN }, |
{ ".NOTPARALLEL", NotParallel, 0 }, |
{ ".NOTPARALLEL", NotParallel, 0 }, |
|
{ ".NO_PARALLEL", NotParallel, 0 }, |
{ ".NULL", Null, 0 }, |
{ ".NULL", Null, 0 }, |
{ ".OPTIONAL", Attribute, OP_OPTIONAL }, |
{ ".OPTIONAL", Attribute, OP_OPTIONAL }, |
{ ".ORDER", Order, 0 }, |
{ ".ORDER", Order, 0 }, |
|
{ ".PARALLEL", Parallel, 0 }, |
{ ".PATH", ExPath, 0 }, |
{ ".PATH", ExPath, 0 }, |
{ ".PRECIOUS", Precious, OP_PRECIOUS }, |
{ ".PRECIOUS", Precious, OP_PRECIOUS }, |
{ ".RECURSIVE", Attribute, OP_MAKE }, |
{ ".RECURSIVE", Attribute, OP_MAKE }, |
|
|
{ ".SINGLESHELL", SingleShell, 0 }, |
{ ".SINGLESHELL", SingleShell, 0 }, |
{ ".SUFFIXES", Suffixes, 0 }, |
{ ".SUFFIXES", Suffixes, 0 }, |
{ ".USE", Attribute, OP_USE }, |
{ ".USE", Attribute, OP_USE }, |
|
{ ".WAIT", Wait, 0 }, |
}; |
}; |
|
|
static int ParseFindKeyword __P((char *)); |
static int ParseFindKeyword __P((char *)); |
static int ParseLinkSrc __P((ClientData, ClientData)); |
static int ParseLinkSrc __P((ClientData, ClientData)); |
static int ParseDoOp __P((ClientData, ClientData)); |
static int ParseDoOp __P((ClientData, ClientData)); |
static void ParseDoSrc __P((int, char *)); |
static int ParseAddDep __P((ClientData, ClientData)); |
|
static void ParseDoSrc __P((int, char *, Lst)); |
static int ParseFindMain __P((ClientData, ClientData)); |
static int ParseFindMain __P((ClientData, ClientData)); |
static int ParseAddDir __P((ClientData, ClientData)); |
static int ParseAddDir __P((ClientData, ClientData)); |
static int ParseClearPath __P((ClientData, ClientData)); |
static int ParseClearPath __P((ClientData, ClientData)); |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
/*- |
|
*--------------------------------------------------------------------- |
|
* ParseAddDep -- |
|
* Check if the pair of GNodes given needs to be synchronized. |
|
* This has to be when two nodes are on different sides of a |
|
* .WAIT directive. |
|
* |
|
* Results: |
|
* Returns 1 if the two targets need to be ordered, 0 otherwise. |
|
* If it returns 1, the search can stop |
|
* |
|
* Side Effects: |
|
* A dependency can be added between the two nodes. |
|
* |
|
*--------------------------------------------------------------------- |
|
*/ |
|
int |
|
ParseAddDep(pp, sp) |
|
ClientData pp; |
|
ClientData sp; |
|
{ |
|
GNode *p = (GNode *) pp; |
|
GNode *s = (GNode *) sp; |
|
|
|
if (p->order < s->order) { |
|
/* |
|
* XXX: This can cause loops, and loops can cause unmade targets, |
|
* but checking is tedious, and the debugging output can show the |
|
* problem |
|
*/ |
|
(void)Lst_AtEnd(p->successors, (ClientData)s); |
|
(void)Lst_AtEnd(s->preds, (ClientData)p); |
|
return 0; |
|
} |
|
else |
|
return 1; |
|
} |
|
|
|
|
/*- |
/*- |
*--------------------------------------------------------------------- |
*--------------------------------------------------------------------- |
* ParseDoSrc -- |
* ParseDoSrc -- |
|
|
*--------------------------------------------------------------------- |
*--------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
ParseDoSrc (tOp, src) |
ParseDoSrc (tOp, src, allsrc) |
int tOp; /* operator (if any) from special targets */ |
int tOp; /* operator (if any) from special targets */ |
char *src; /* name of the source to handle */ |
char *src; /* name of the source to handle */ |
|
Lst allsrc; /* List of all sources to wait for */ |
|
|
{ |
{ |
int op; /* operator (if any) from special source */ |
GNode *gn = NULL; |
GNode *gn; |
|
|
|
op = 0; |
|
if (*src == '.' && isupper (src[1])) { |
if (*src == '.' && isupper (src[1])) { |
int keywd = ParseFindKeyword(src); |
int keywd = ParseFindKeyword(src); |
if (keywd != -1) { |
if (keywd != -1) { |
op = parseKeywords[keywd].op; |
int op = parseKeywords[keywd].op; |
|
if (op != 0) { |
|
Lst_ForEach (targets, ParseDoOp, (ClientData)&op); |
|
return; |
|
} |
|
if (parseKeywords[keywd].spec == Wait) { |
|
waiting++; |
|
return; |
|
} |
} |
} |
} |
} |
if (op != 0) { |
|
Lst_ForEach (targets, ParseDoOp, (ClientData)&op); |
switch (specType) { |
} else if (specType == Main) { |
case Main: |
/* |
/* |
* If we have noted the existence of a .MAIN, it means we need |
* If we have noted the existence of a .MAIN, it means we need |
* to add the sources of said target to the list of things |
* to add the sources of said target to the list of things |
|
|
* employ that, if desired. |
* employ that, if desired. |
*/ |
*/ |
Var_Append(".TARGETS", src, VAR_GLOBAL); |
Var_Append(".TARGETS", src, VAR_GLOBAL); |
} else if (specType == Order) { |
return; |
|
|
|
case Order: |
/* |
/* |
* Create proper predecessor/successor links between the previous |
* Create proper predecessor/successor links between the previous |
* source and the current one. |
* source and the current one. |
|
|
* The current source now becomes the predecessor for the next one. |
* The current source now becomes the predecessor for the next one. |
*/ |
*/ |
predecessor = gn; |
predecessor = gn; |
} else { |
break; |
|
|
|
default: |
/* |
/* |
* If the source is not an attribute, we need to find/create |
* If the source is not an attribute, we need to find/create |
* a node for it. After that we can apply any operator to it |
* a node for it. After that we can apply any operator to it |
|
|
} |
} |
} |
} |
} |
} |
|
break; |
} |
} |
|
|
|
gn->order = waiting; |
|
(void)Lst_AtEnd(allsrc, (ClientData)gn); |
|
if (waiting) { |
|
Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn); |
|
} |
} |
} |
|
|
/*- |
/*- |
|
|
Lst paths; /* List of search paths to alter when parsing |
Lst paths; /* List of search paths to alter when parsing |
* a list of .PATH targets */ |
* a list of .PATH targets */ |
int tOp; /* operator from special target */ |
int tOp; /* operator from special target */ |
Lst sources; /* list of source names after expansion */ |
Lst sources; /* list of archive source names after |
|
* expansion */ |
Lst curTargs; /* list of target names to be found and added |
Lst curTargs; /* list of target names to be found and added |
* to the targets list */ |
* to the targets list */ |
|
Lst curSrcs; /* list of sources in order */ |
|
|
tOp = 0; |
tOp = 0; |
|
|
specType = Not; |
specType = Not; |
|
waiting = 0; |
paths = (Lst)NULL; |
paths = (Lst)NULL; |
|
|
curTargs = Lst_Init(FALSE); |
curTargs = Lst_Init(FALSE); |
|
curSrcs = Lst_Init(FALSE); |
|
|
do { |
do { |
for (cp = line; |
for (cp = line; |
|
|
|
|
while (!Lst_IsEmpty (sources)) { |
while (!Lst_IsEmpty (sources)) { |
gn = (GNode *) Lst_DeQueue (sources); |
gn = (GNode *) Lst_DeQueue (sources); |
ParseDoSrc (tOp, gn->name); |
ParseDoSrc (tOp, gn->name, curSrcs); |
} |
} |
Lst_Destroy (sources, NOFREE); |
Lst_Destroy (sources, NOFREE); |
cp = line; |
cp = line; |
|
|
cp += 1; |
cp += 1; |
} |
} |
|
|
ParseDoSrc (tOp, line); |
ParseDoSrc (tOp, line, curSrcs); |
} |
} |
while (*cp && isspace (*cp)) { |
while (*cp && isspace (*cp)) { |
cp++; |
cp++; |
|
|
Lst_ForEach (targets, ParseFindMain, (ClientData)0); |
Lst_ForEach (targets, ParseFindMain, (ClientData)0); |
} |
} |
|
|
|
/* |
|
* Finally, destroy the list of sources |
|
*/ |
|
Lst_Destroy(curSrcs, NOFREE); |
} |
} |
|
|
/*- |
/*- |