#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ohash.h>
#include "defines.h"
#include "dir.h"
#include "engine.h"
#include "suff.h"
#include "var.h"
#include "targ.h"
#include "error.h"
#include "str.h"
#include "lst.h"
#include "memory.h"
#include "gnode.h"
#include "stats.h"
#include "dump.h"
#include "expandchildren.h"
static struct ohash suffixes;
size_t maxLen = 0U;
static LIST srclist;
static struct ohash transforms;
static int order = 0;
struct Suff_ {
size_t nameLen;
short flags;
#define SUFF_ACTIVE 0x08
#define SUFF_PATH 0x10
LIST searchPath;
int order;
LIST parents;
LIST children;
char name[1];
};
static struct ohash_info suff_info = {
offsetof(struct Suff_, name), NULL,
hash_calloc, hash_free, element_alloc
};
typedef struct Src_ {
char *file;
char *prefix;
Suff *suff;
struct Src_ *parent;
GNode *node;
int children;
#ifdef DEBUG_SRC
LIST cp;
#endif
} Src;
typedef struct {
Lst l;
Src *s;
} LstSrc;
static Suff *emptySuff;
#define parse_transform(s, p, q) parse_transformi(s, s + strlen(s), p, q)
static bool parse_transformi(const char *, const char *, Suff **, Suff **);
#define new_suffix(s) new_suffixi(s, NULL)
static Suff *new_suffixi(const char *, const char *);
static void reverse_hash_add_char(uint32_t *, const char *);
static uint32_t reverse_hashi(const char *, const char **);
static unsigned int reverse_slot(struct ohash *, const char *, const char **);
static void record_possible_suffix(Suff *, GNode *, char *, Lst, Lst);
static void record_possible_suffixes(GNode *, Lst, Lst);
static Suff *find_suffix_as_suffix(Lst, const char *, const char *);
static Suff *add_suffixi(const char *, const char *);
static void SuffInsert(Lst, Suff *);
static void SuffAddSrc(void *, void *);
static bool SuffRemoveSrc(Lst);
static void SuffAddLevel(Lst, Src *);
static Src *SuffFindThem(Lst, Lst);
static Src *SuffFindCmds(Src *, Lst);
static bool SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
static void SuffFindDeps(GNode *, Lst);
static void SuffFindArchiveDeps(GNode *, Lst);
static void SuffFindNormalDeps(GNode *, Lst);
static void SuffPrintName(void *);
static void SuffPrintSuff(void *);
static void SuffPrintTrans(GNode *);
#define find_suff(name) find_suffi(name, NULL)
static Suff *find_suffi(const char *, const char *);
static Suff *find_best_suffix(const char *, const char *);
static GNode *find_transform(const char *);
static GNode *find_or_create_transformi(const char *, const char *);
static void setup_paths(void);
static void build_suffixes_graph(void);
static void special_path_hack(void);
#ifdef DEBUG_SRC
static void PrintAddr(void *);
#endif
static void
reverse_hash_add_char(uint32_t *pk, const char *s)
{
*pk = ((*pk << 2) | (*pk >> 30)) ^ *s;
}
static uint32_t
reverse_hashi(const char *s, const char **e)
{
const char *p;
uint32_t k;
if (*e == NULL)
*e = s + strlen(s);
p = *e;
if (p == s)
k = 0;
else
k = *--p;
while (p != s) {
reverse_hash_add_char(&k, --p);
}
return k;
}
static unsigned int
reverse_slot(struct ohash *h, const char *s, const char **e)
{
uint32_t hv;
hv = reverse_hashi(s, e);
return ohash_lookup_interval(h, s, *e, hv);
}
static char *
suffix_is_suffix(Suff *s, const char *str, const char *estr)
{
const char *p1;
const char *p2;
if (estr - str < (ptrdiff_t) s->nameLen)
return NULL;
p1 = s->name + s->nameLen;
p2 = estr;
while (p1 != s->name) {
p1--;
p2--;
if (*p1 != *p2)
return NULL;
}
return (char *)p2;
}
static Suff *
find_suffi(const char *name, const char *ename)
{
unsigned int slot;
#ifdef STATS_SUFF
STAT_SUFF_LOOKUP_NAME++;
#endif
slot = reverse_slot(&suffixes, name, &ename);
return ohash_find(&suffixes, slot);
}
static GNode *
find_transform(const char *name)
{
unsigned int slot;
#ifdef STATS_SUFF
STAT_TRANSFORM_LOOKUP_NAME++;
#endif
slot = ohash_qlookup(&transforms, name);
return ohash_find(&transforms, slot);
}
static GNode *
find_or_create_transformi(const char *name, const char *end)
{
GNode *r;
unsigned int slot;
#ifdef STATS_SUFF
STAT_TRANSFORM_LOOKUP_NAME++;
#endif
slot = ohash_qlookupi(&transforms, name, &end);
r = ohash_find(&transforms, slot);
if (r == NULL) {
r = Targ_NewGNi(name, end);
ohash_insert(&transforms, slot, r);
}
return r;
}
static void
SuffInsert(Lst l, Suff *s)
{
LstNode ln;
Suff *s2 = NULL;
for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
s2 = Lst_Datum(ln);
if (s2->order >= s->order)
break;
}
if (DEBUG(SUFF))
printf("inserting %s(%d)...", s->name, s->order);
if (ln == NULL) {
if (DEBUG(SUFF))
printf("at end of list\n");
Lst_AtEnd(l, s);
} else if (s2->order != s->order) {
if (DEBUG(SUFF))
printf("before %s(%d)\n", s2->name, s2->order);
Lst_Insert(l, ln, s);
} else if (DEBUG(SUFF)) {
printf("already there\n");
}
}
void
Suff_DisableAllSuffixes(void)
{
unsigned int i;
Suff *s;
for (s = ohash_first(&suffixes, &i); s != NULL;
s = ohash_next(&suffixes, &i))
s->flags &= ~SUFF_ACTIVE;
order = 0;
maxLen = 0;
}
static bool
parse_transformi(const char *str, const char *e, Suff **srcPtr, Suff **targPtr)
{
Suff *src, *target, *best_src, *best_target;
const char *p;
size_t len;
uint32_t hv;
unsigned int slot;
if (e == str)
return false;
len = e - str;
if (len > 2 * maxLen)
return false;
p = e;
best_src = best_target = NULL;
hv = *--p;
while (p != str) {
slot = ohash_lookup_interval(&suffixes, p, e, hv);
if (p - str <= (ptrdiff_t)maxLen) {
target = ohash_find(&suffixes, slot);
if (target != NULL && (target->flags & SUFF_ACTIVE)) {
src = find_suffi(str, p);
if (src != NULL &&
(src->flags & (SUFF_ACTIVE | SUFF_PATH))) {
if (best_src == NULL ||
src->order < best_src->order) {
best_src = src;
best_target = target;
}
}
}
}
if (e - p >= (ptrdiff_t)maxLen)
break;
reverse_hash_add_char(&hv, --p);
}
if (p == str && best_src == NULL) {
slot = ohash_lookup_interval(&suffixes, p, e, hv);
src = ohash_find(&suffixes, slot);
if (src != NULL && (src->flags & (SUFF_ACTIVE | SUFF_PATH))) {
best_src = src;
best_target = emptySuff;
}
}
if (best_src != NULL) {
*srcPtr = best_src;
*targPtr = best_target;
return true;
} else {
return false;
}
}
static void
special_path_hack(void)
{
Suff *path = add_suffixi(".PATH", NULL);
path->flags |= SUFF_PATH;
}
static Suff *
find_best_suffix(const char *s, const char *e)
{
const char *p;
uint32_t hv;
unsigned int slot;
Suff *best = NULL;
Suff *suff;
if (e == s)
return NULL;
p = e;
hv = *--p;
while (p != s) {
slot = ohash_lookup_interval(&suffixes, p, e, hv);
suff = ohash_find(&suffixes, slot);
if (suff != NULL)
if (best == NULL || suff->order < best->order)
best = suff;
if (e - p >= (ptrdiff_t)maxLen)
break;
reverse_hash_add_char(&hv, --p);
}
return best;
}
Lst
find_best_path(const char *name)
{
Suff *s = find_best_suffix(name, name + strlen(name));
if (s != NULL) {
if (DEBUG(SUFF))
printf("suffix is \"%s\"...", s->name);
return &s->searchPath;
} else
return defaultPath;
}
GNode *
Suff_ParseAsTransform(const char *line, const char *end)
{
GNode *gn;
Suff *s;
Suff *t;
if (!parse_transformi(line, end, &s, &t))
return NULL;
gn = find_or_create_transformi(line, end);
if (!Lst_IsEmpty(&gn->commands)) {
Lst_Destroy(&gn->commands, NOFREE);
Lst_Init(&gn->commands);
}
if (!Lst_IsEmpty(&gn->children)) {
Lst_Destroy(&gn->children, NOFREE);
Lst_Init(&gn->children);
}
gn->type = OP_TRANSFORM;
if (s->flags & SUFF_PATH) {
gn->special = SPECIAL_PATH;
gn->suffix = t;
}
if (DEBUG(SUFF))
printf("defining transformation from `%s' to `%s'\n",
s->name, t->name);
return gn;
}
static void
make_suffix_known(Suff *s)
{
if ((s->flags & SUFF_ACTIVE) == 0) {
s->order = order++;
s->flags |= SUFF_ACTIVE;
if (s->nameLen > maxLen)
maxLen = s->nameLen;
}
}
static Suff *
new_suffixi(const char *str, const char *eptr)
{
Suff *s;
s = ohash_create_entry(&suff_info, str, &eptr);
s->nameLen = eptr - str;
Lst_Init(&s->searchPath);
Lst_Init(&s->children);
Lst_Init(&s->parents);
s->flags = 0;
return s;
}
void
Suff_AddSuffixi(const char *str, const char *end)
{
(void)add_suffixi(str, end);
}
static Suff *
add_suffixi(const char *str, const char *end)
{
Suff *s;
unsigned int slot;
slot = reverse_slot(&suffixes, str, &end);
s = ohash_find(&suffixes, slot);
if (s == NULL) {
s = new_suffixi(str, end);
ohash_insert(&suffixes, slot, s);
}
make_suffix_known(s);
return s;
}
Lst
find_suffix_path(GNode *gn)
{
if (gn->suffix != NULL && gn->suffix != emptySuff)
return &(gn->suffix->searchPath);
else
return defaultPath;
}
static void
build_suffixes_graph(void)
{
Suff *s, *s2;
GNode *gn;
unsigned int i;
for (gn = ohash_first(&transforms, &i); gn != NULL;
gn = ohash_next(&transforms, &i)) {
if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
continue;
if (gn->special == SPECIAL_PATH)
continue;
if (parse_transform(gn->name, &s, &s2)) {
SuffInsert(&s2->children, s);
SuffInsert(&s->parents, s2);
}
}
}
static void
setup_paths(void)
{
unsigned int i;
Suff *s;
for (s = ohash_first(&suffixes, &i); s != NULL;
s = ohash_next(&suffixes, &i)) {
if (!Lst_IsEmpty(&s->searchPath))
Dir_Concat(&s->searchPath, defaultPath);
else
Lst_Clone(&s->searchPath, defaultPath, Dir_CopyDir);
}
}
void
process_suffixes_after_makefile_is_read(void)
{
setup_paths();
build_suffixes_graph();
}
static void
SuffAddSrc(
void *sp,
void *lsp)
{
Suff *s = sp;
LstSrc *ls = lsp;
Src *s2;
Src *targ;
targ = ls->s;
s2 = emalloc(sizeof(Src));
s2->file = Str_concat(targ->prefix, s->name, 0);
s2->prefix = targ->prefix;
s2->parent = targ;
s2->node = NULL;
s2->suff = s;
s2->children = 0;
targ->children++;
Lst_AtEnd(ls->l, s2);
#ifdef DEBUG_SRC
Lst_Init(&s2->cp);
Lst_AtEnd(&targ->cp, s2);
printf("2 add %x %x to %x:", targ, s2, ls->l);
Lst_Every(ls->l, PrintAddr);
printf("\n");
#endif
}
static void
SuffAddLevel(
Lst l,
Src *targ)
{
LstSrc ls;
ls.s = targ;
ls.l = l;
Lst_ForEach(&targ->suff->children, SuffAddSrc, &ls);
}
static bool
SuffRemoveSrc(Lst l)
{
LstNode ln;
Src *s;
#ifdef DEBUG_SRC
printf("cleaning %lx: ", (unsigned long)l);
Lst_Every(l, PrintAddr);
printf("\n");
#endif
for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
s = Lst_Datum(ln);
if (s->children == 0) {
free(s->file);
if (!s->parent)
free(s->prefix);
else {
#ifdef DEBUG_SRC
LstNode ln2 = Lst_Member(&s->parent->cp, s);
if (ln2 != NULL)
Lst_Remove(&s->parent->cp, ln2);
#endif
--s->parent->children;
}
#ifdef DEBUG_SRC
printf("free: [l=%x] p=%x %d\n", l, s, s->children);
Lst_Destroy(&s->cp, NOFREE);
#endif
Lst_Remove(l, ln);
free(s);
return true;
}
#ifdef DEBUG_SRC
else {
printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
Lst_Every(&s->cp, PrintAddr);
printf("\n");
}
#endif
}
return false;
}
static Src *
SuffFindThem(
Lst srcs,
Lst slst)
{
Src *s;
Src *rs;
char *ptr;
rs = NULL;
while ((s = Lst_DeQueue(srcs)) != NULL) {
if (DEBUG(SUFF))
printf("\ttrying %s...", s->file);
if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
#ifdef DEBUG_SRC
printf("remove %x from %x\n", s, srcs);
#endif
rs = s;
break;
}
if ((ptr = Dir_FindFile(s->file, &s->suff->searchPath))
!= NULL) {
rs = s;
#ifdef DEBUG_SRC
printf("remove %x from %x\n", s, srcs);
#endif
free(ptr);
break;
}
if (DEBUG(SUFF))
printf("not there\n");
SuffAddLevel(srcs, s);
Lst_AtEnd(slst, s);
}
if (DEBUG(SUFF) && rs)
printf("got it\n");
return rs;
}
static Src *
SuffFindCmds(Src *targ, Lst slst)
{
LstNode ln;
GNode *t;
GNode *s;
int prefixLen;
Suff *suff;
Src *ret;
const char *cp;
t = targ->node;
prefixLen = strlen(targ->prefix);
for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Adv(ln)) {
s = Lst_Datum(ln);
cp = strrchr(s->name, '/');
if (cp == NULL)
cp = s->name;
else
cp++;
if (strncmp(cp, targ->prefix, prefixLen) != 0)
continue;
suff = find_suff(&cp[prefixLen]);
if (suff == NULL)
continue;
if (Lst_Member(&suff->parents, targ->suff) == NULL)
continue;
ret = emalloc(sizeof(Src));
ret->file = estrdup(s->name);
ret->prefix = targ->prefix;
ret->suff = suff;
ret->parent = targ;
ret->node = s;
ret->children = 0;
targ->children++;
#ifdef DEBUG_SRC
Lst_Init(&ret->cp);
printf("3 add %x %x\n", targ, ret);
Lst_AtEnd(&targ->cp, ret);
#endif
Lst_AtEnd(slst, ret);
if (DEBUG(SUFF))
printf("\tusing existing source %s\n", s->name);
return ret;
}
return NULL;
}
static bool
SuffApplyTransform(
GNode *tGn,
GNode *sGn,
Suff *t,
Suff *s)
{
LstNode ln;
char *tname;
GNode *gn;
if (Lst_AddNew(&tGn->children, sGn)) {
LinkParent(sGn, tGn);
}
if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) {
gn = Lst_Datum(ln);
if (Lst_AddNew(&tGn->children, gn)) {
LinkParent(gn, tGn);
}
}
}
tname = Str_concat(s->name, t->name, 0);
gn = find_transform(tname);
free(tname);
if (gn == NULL)
return false;
if (DEBUG(SUFF))
printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name,
tGn->name);
ln = Lst_Last(&tGn->children);
Make_HandleUse(gn, tGn);
expand_children_from(tGn, Lst_Succ(ln));
tGn->impliedsrc = sGn;
return true;
}
static Suff *
find_suffix_as_suffix(Lst l, const char *b, const char *e)
{
LstNode ln;
Suff *s;
for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
s = Lst_Datum(ln);
if (suffix_is_suffix(s, b, e))
return s;
}
return NULL;
}
static void
SuffFindArchiveDeps(
GNode *gn,
Lst slst)
{
char *eoarch;
char *eoname;
GNode *mem;
Suff *ms;
char *name;
eoarch = strchr(gn->name, '(');
if (eoarch == NULL)
return;
name = eoarch + 1;
eoname = strchr(name, ')');
if (eoname == NULL)
return;
mem = Targ_FindNodei(name, eoname, TARG_CREATE);
SuffFindDeps(mem, slst);
if (Lst_AddNew(&gn->children, mem))
LinkParent(mem, gn);
Var(TARGET_INDEX, gn) = Var(TARGET_INDEX, mem);
Var(PREFIX_INDEX, gn) = Var(PREFIX_INDEX, mem);
ms = mem->suffix;
if (ms == NULL) {
if (DEBUG(SUFF))
printf("using empty suffix\n");
ms = emptySuff;
}
Var(MEMBER_INDEX, gn) = mem->name;
Var(ARCHIVE_INDEX, gn) = gn->name;
if (ms != NULL) {
Suff *suff;
suff = find_suffix_as_suffix(&ms->parents, gn->name, eoarch);
if (suff != NULL) {
if (!SuffApplyTransform(gn, mem, suff, ms) &&
DEBUG(SUFF))
printf("\tNo transformation from %s -> %s\n",
ms->name, suff->name);
}
}
if (OP_NOP(gn->type))
gn->type |= OP_DEPENDS;
mem->type |= OP_MEMBER;
}
static void
record_possible_suffix(Suff *s, GNode *gn, char *eoname, Lst srcs, Lst targs)
{
int prefixLen;
Src *targ;
targ = emalloc(sizeof(Src));
targ->file = estrdup(gn->name);
targ->suff = s;
targ->node = gn;
targ->parent = NULL;
targ->children = 0;
#ifdef DEBUG_SRC
Lst_Init(&targ->cp);
#endif
prefixLen = (eoname - targ->suff->nameLen) - gn->name;
targ->prefix = emalloc(prefixLen + 1);
memcpy(targ->prefix, gn->name, prefixLen);
targ->prefix[prefixLen] = '\0';
SuffAddLevel(srcs, targ);
Lst_AtEnd(targs, targ);
}
static void
record_possible_suffixes(GNode *gn, Lst srcs, Lst targs)
{
char *s = gn->name;
char *e = s + strlen(s);
const char *p;
uint32_t hv;
unsigned int slot;
Suff *suff;
if (e == s)
return;
p = e;
hv = *--p;
while (p != s) {
slot = ohash_lookup_interval(&suffixes, p, e, hv);
suff = ohash_find(&suffixes, slot);
if (suff != NULL && (suff->flags & SUFF_ACTIVE))
record_possible_suffix(suff, gn, e, srcs, targs);
if (e - p >= (ptrdiff_t)maxLen)
break;
reverse_hash_add_char(&hv, --p);
}
}
static void
SuffFindNormalDeps(
GNode *gn,
Lst slst)
{
LIST srcs;
LIST targs;
Src *bottom;
Src *src;
char *prefix;
Src *targ;
Lst_Init(&srcs);
Lst_Init(&targs);
record_possible_suffixes(gn, &srcs, &targs);
if (Lst_IsEmpty(&srcs)) {
if (DEBUG(SUFF))
printf("\tNo known suffix on %s. Using empty suffix\n",
gn->name);
targ = emalloc(sizeof(Src));
targ->file = estrdup(gn->name);
targ->suff = emptySuff;
targ->node = gn;
targ->parent = NULL;
targ->children = 0;
targ->prefix = estrdup(gn->name);
#ifdef DEBUG_SRC
Lst_Init(&targ->cp);
#endif
if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
SuffAddLevel(&srcs, targ);
else {
if (DEBUG(SUFF))
printf("not ");
}
if (DEBUG(SUFF))
printf("adding suffix rules\n");
Lst_AtEnd(&targs, targ);
}
bottom = SuffFindThem(&srcs, slst);
if (bottom == NULL) {
if (!Lst_IsEmpty(&targs))
targ = Lst_Datum(Lst_First(&targs));
else
targ = NULL;
} else {
for (targ = bottom; targ->parent != NULL; targ = targ->parent)
continue;
}
Var(TARGET_INDEX, gn) = gn->name;
prefix = targ != NULL ? estrdup(targ->prefix) : gn->name;
Var(PREFIX_INDEX, gn) = prefix;
expand_all_children(gn);
if (targ == NULL) {
if (DEBUG(SUFF))
printf("\tNo valid suffix on %s\n", gn->name);
sfnd_abort:
if (OP_NOP(gn->type) ||
(Lst_IsEmpty(&gn->children) &&
Lst_IsEmpty(&gn->commands))) {
gn->path = Dir_FindFile(gn->name,
(targ == NULL ? defaultPath :
&targ->suff->searchPath));
if (gn->path != NULL) {
char *ptr;
Var(TARGET_INDEX, gn) = estrdup(gn->path);
if (targ != NULL) {
int savep = strlen(gn->path) -
targ->suff->nameLen;
char savec;
gn->suffix = targ->suff;
savec = gn->path[savep];
gn->path[savep] = '\0';
if ((ptr = strrchr(gn->path, '/')) !=
NULL)
ptr++;
else
ptr = gn->path;
Var(PREFIX_INDEX, gn) = estrdup(ptr);
gn->path[savep] = savec;
} else {
gn->suffix = NULL;
if ((ptr = strrchr(gn->path, '/')) !=
NULL)
ptr++;
else
ptr = gn->path;
Var(PREFIX_INDEX, gn) = estrdup(ptr);
}
}
} else {
gn->suffix = targ == NULL ? NULL : targ->suff;
free(gn->path);
gn->path = estrdup(gn->name);
}
goto sfnd_return;
}
if (!Lst_IsEmpty(&gn->children)) {
src = SuffFindCmds(targ, slst);
if (src != NULL) {
while (bottom && bottom->parent != NULL) {
(void)Lst_AddNew(slst, bottom);
bottom = bottom->parent;
}
bottom = src;
}
}
if (bottom == NULL) {
goto sfnd_abort;
}
if (bottom->node == NULL) {
bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
}
for (src = bottom; src->parent != NULL; src = src->parent) {
targ = src->parent;
src->node->suffix = src->suff;
if (targ->node == NULL) {
targ->node = Targ_FindNode(targ->file, TARG_CREATE);
}
SuffApplyTransform(targ->node, src->node,
targ->suff, src->suff);
if (targ->node != gn) {
targ->node->type |= OP_DEPS_FOUND;
Var(PREFIX_INDEX, targ->node) = estrdup(targ->prefix);
Var(TARGET_INDEX, targ->node) = targ->node->name;
}
}
gn->suffix = src->suff;
free(gn->path);
gn->path = estrdup(gn->name);
sfnd_return:
if (bottom)
(void)Lst_AddNew(slst, bottom);
while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs))
continue;
Lst_ConcatDestroy(slst, &srcs);
Lst_ConcatDestroy(slst, &targs);
}
void
Suff_FindDeps(GNode *gn)
{
SuffFindDeps(gn, &srclist);
while (SuffRemoveSrc(&srclist))
continue;
}
static void
SuffFindDeps(GNode *gn, Lst slst)
{
if (gn->type & OP_DEPS_FOUND) {
return;
} else {
gn->type |= OP_DEPS_FOUND;
}
if (DEBUG(SUFF))
printf("SuffFindDeps (%s)\n", gn->name);
current_node = gn;
if (gn->type & OP_ARCHV)
SuffFindArchiveDeps(gn, slst);
else
SuffFindNormalDeps(gn, slst);
current_node = NULL;
}
void
Suff_Init(void)
{
Static_Lst_Init(&srclist);
ohash_init(&transforms, 4, &gnode_info);
emptySuff = new_suffix("");
emptySuff->flags = SUFF_ACTIVE;
emptySuff->order = 0;
Dir_Concat(&emptySuff->searchPath, defaultPath);
ohash_init(&suffixes, 4, &suff_info);
special_path_hack();
}
static void
SuffPrintName(void *p)
{
const Suff *s = p;
printf("%s ", s == emptySuff ? "<empty>" : s->name);
}
static void
SuffPrintSuff(void *sp)
{
Suff *s = sp;
printf("# %-5s ", s->name);
if (!Lst_IsEmpty(&s->parents)) {
printf(" ->");
Lst_Every(&s->parents, SuffPrintName);
}
if (!Lst_IsEmpty(&s->children)) {
printf(" <-");
Lst_Every(&s->children, SuffPrintName);
}
fputc('\n', stdout);
}
static void
SuffPrintTrans(GNode *t)
{
printf("%-16s: ", t->name);
Targ_PrintType(t->type);
fputc('\n', stdout);
Lst_Every(&t->commands, Targ_PrintCmd);
fputc('\n', stdout);
}
static int
compare_order(const void *a, const void *b)
{
const Suff **pa = (const Suff **)a;
const Suff **pb = (const Suff **)b;
return (*pb)->order - (*pa)->order;
}
static void
print_path(Suff *s)
{
LstNode ln1, ln2;
bool first = true;
for (ln1 = Lst_First(&s->searchPath), ln2 = Lst_First(defaultPath);
ln1 != NULL && ln2 != NULL;
ln1 = Lst_Adv(ln1)) {
if (Lst_Datum(ln1) == Lst_Datum(ln2)) {
ln2 = Lst_Adv(ln2);
continue;
}
if (first) {
printf(".PATH%s:", s->name);
first = false;
}
printf(" %s", PathEntry_name(Lst_Datum(ln1)));
}
if (!first)
printf("\n\n");
}
void
Suff_PrintAll(void)
{
Suff **t;
GNode **u;
unsigned int i;
bool reprint;
printf("# Suffixes graph\n");
t = sort_ohash_by_name(&suffixes);
for (i = 0; t[i] != NULL; i++)
if (!(t[i]->flags & SUFF_PATH))
SuffPrintSuff(t[i]);
printf("\n.PATH: ");
Dir_PrintPath(defaultPath);
printf("\n\n");
for (i = 0; t[i] != NULL; i++)
if (!(t[i]->flags & SUFF_PATH))
print_path(t[i]);
free(t);
reprint = false;
t = sort_ohash(&suffixes, compare_order);
printf(".SUFFIXES:");
for (i = 0; t[i] != NULL; i++) {
if (t[i]->flags & SUFF_PATH)
continue;
printf(" %s", t[i]->name);
if (!(t[i]->flags & SUFF_ACTIVE))
reprint = true;
}
printf("\n\n");
u = sort_ohash_by_name(&transforms);
for (i = 0; u[i] != NULL; i++)
SuffPrintTrans(u[i]);
free(u);
if (reprint) {
printf(".SUFFIXES:");
for (i = 0; t[i] != NULL; i++)
if (t[i]->flags & SUFF_ACTIVE)
printf(" %s", t[i]->name);
printf("\n");
}
free(t);
}
#ifdef DEBUG_SRC
static void
PrintAddr(void *a)
{
printf("%lx ", (unsigned long)a);
}
#endif