#
# recursestatic.awk
#
# input:
#   name0 name1 name2 component ...
#
# recursively traverses the component dependency files, putting out all
# the dependencies of the comp<n>
#
# intended for a fully static build
#
# if there're any repetitions, all but the last are suppressed
#
# the component dependency files are found at the concatenation of
#   name0
#   <component without diversity>
#   name1
#   <component without diversity>
#   name2

#-------------------------------------------------------------------------------
BEGIN {
    # phase
    #      0:  looking for name0
    #      1:  looking for name1
    #      2:  looking for name2
    #   else:  looking at component names
    phase = 0;
    recursionDetected = 0;
    numLibs = 0;
    dbg = 0;
    if (dbg>3) {printf("WB version of recursestatic.awk\n") >"/dev/fd/2";}
}

#-------------------------------------------------------------------------------
function readLFile(file,
                  res, res1, line)
{
    res = "";
    do {
        res1 = -1;
        res1 = (getline line < file);
        if (res1 == -1) {
            if (dbg>2) {printf("readLFile %s => ERR %s %d\n", file, res1, res1) >"/dev/fd/2";}
            close(file);
            return -1;
        }
        if (res1 == 0) {
            if (dbg>2) {printf("readLFile %s => EOF %s %d\n", file, res1, res1) >"/dev/fd/2";}
            close(file);
            return res;
        }
        if (dbg>2) {printf("readLFile %s => %s '%s'\n", file, res1, line) >"/dev/fd/2";}
        if (res == "") {
            res = line;
        } else {
            res = res " " line;
        }
    } while (1);
}

#-------------------------------------------------------------------------------
function readLibInfo(lib,
                     file, res, depends)
{
    numLibs++;
    sub(/_.*/, "", lib)
    file1 = name0 "comps/" lib name1 lib name2;
    if (dbg>2) {printf("WB recursestatic.awk: readLibInfo %s %s\n", lib, file1) >"/dev/fd/2";}
    res = readLFile(file1);
    if (res == -1) {
        file2 = name0 "intfs/" lib name1 lib name2;
        res = readLFile(file2);
        if (res == -1) {
            #printf("SDE2 recursestatic.awk: WARNING: no .l file for library %s\n", lib) >"/dev/fd/2";
            #printf("SDE2 recursestatic.awk: either %s\n", file1) >"/dev/fd/2";
            #printf("SDE2 recursestatic.awk: or     %s\n", file2) >"/dev/fd/2";
            #printf("Building library %s is a prerequisite.\n", lib) >"/dev/fd/2";
	    printf("ERR_L_%s\n",lib);
            return;
        }
    }
    if (dbg>1) {printf("%s depends on '%s'\n", lib, res) >"/dev/fd/2";}
    libDepends[lib] = res;
    split(res, depends);
    for (n in depends) {
        dependencyLib = depends[n];
        if (!libRead[dependencyLib]) {
            newReadList[dependencyLib] = 1;
        }
    }
}

#-------------------------------------------------------------------------------
function processReadlist()
{
    if (dbg>3) {printf("WB recursestatic.awk: processReadlist...\n") >"/dev/fd/2";}
    do {
        split("", newReadList);
        for (lib in readList) {
            if (!libRead[lib]) {
                libRead[lib] = 1;
                libsRead = libsRead " " lib;
                readLibInfo(lib);
            }
        }
        split("", readList);
        newLibsSeen = 0;
        for (lib in newReadList) {
            newLibsSeen = 1;
            readList[lib] = 1;
            delete newReadList[lib];
        }
    } while (newLibsSeen);
    if (dbg>3) {printf("WB recursestatic.awk: processReadlist DONE\n") >"/dev/fd/2";}
}

#-------------------------------------------------------------------------------
function sortLibs(lib)
{
    if (dbg>3) {printf("WB recursestatic.awk: sortLibs... libsRead = %s\n", libsRead) >"/dev/fd/2";}
    split(libsRead, libsToSort);
    maxLevel = 0;

    # Cycle over all libsToSort while we resolve at least one lib per iteration
    # otherwise we are stuck.
    do {
        someLibsResolved = 0;
        for (n in libsToSort) {
            lib = libsToSort[n];
            level = 0;
            allDependenciesResolved = 1;
            # cycle over dependencies of lib, and if each dependency has been given a level
            # then we can lib itself a level 1 greater.
            split(libDepends[lib], depends);
            for (d in depends) {
                dependencyLib = depends[d];
                if (dependencyLib in libLevel) {
                    if (libLevel[dependencyLib] >= level) {
                        level = libLevel[dependencyLib] + 1;
                    }
                } else {
                    allDependenciesResolved = 0;
                }
            }
            # all dependencies were resolved already, so now lib itself if resolved:
            if (allDependenciesResolved) {
                if (dbg>1) {printf("WB recursestatic.awk: %s has no unresolved dependencies, level %d\n", lib, level) >"/dev/fd/2";}
                libLevel[lib] = level;
                if (level > maxLevel) { maxLevel = level; }
                delete libsToSort[n];
                someLibsResolved++;
            }
        }
    } while (someLibsResolved > 0);

    # Check of recursive libs:
    for (n in libsToSort) {
        lib = libsToSort[n];
        printf("ERR_CIRC_COMPS_%s\n", lib) #>"/dev/fd/2";
        libLevel[lib] = maxLevel;
    }

    # reverse lookup:
    for (lib in libRead) {
        libsOrder[libLevel[lib]] = libsOrder[libLevel[lib]] " " lib;
    }
    if (dbg>3) {printf("WB recursestatic.awk: sortLibs DONE\n") >"/dev/fd/2";}
}
#-------------------------------------------------------------------------------
function printLibs(lib)
{
    #for (level = 0; level <= maxLevel; level++)
    for (level = maxLevel; level >= 0; level--) {
        if (dbg>1) {printf("%s\n", libsOrder[level]) >"/dev/fd/2";}
        printf("%s\n", libsOrder[level]);
    }
}
#-------------------------------------------------------------------------------
{
    if (dbg>0) {printf("WB recursestatic.awk: input line: %s\n", $0) >"/dev/fd/2";}
    n = split($0, words);
    for (i = 1; i <= n; i++)
    {
        if (phase == 0)
        {
            name0 = words[i]
            phase = 1
        }
        else if (phase == 1)
        {
            name1 = words[i]
            phase = 2
        }
        else if (phase == 2)
        {
            name2 = words[i]
            phase = 3
        }
        else
        {
            readList[words[i]] = 1;
        }
    }
}

#-------------------------------------------------------------------------------
END {
    processReadlist();
    sortLibs();
    printLibs();
}
