#!/usr/bin/awk -f
#
# filter stdout/stderr of make to output from tree leves where
# the make failed
# 

# output looks like this if a command executed by a target fails:
#   make[3]: Entering directory `/scratch/markd/kent/src/hg/lib/tests'
#  ..
#   make[3]: *** [spDbTest] Error 255
#   make[3]: Leaving directory `/scratch/markd/kent/src/hg/lib/tests'
#
# If make generates an error, the results looks like this if it's in the
# top top level make:
#
#   make[1]: Entering directory `/cluster/store3/markd/kent/src/lib'
#   ../inc/common.mk:2: *** missing separator.  Stop.
#   make[1]: Leaving directory `/cluster/store3/markd/kent/src/lib'
#   make: *** [clean] Error 2
#
# and like this in lower-levels
#   make[2]: Entering directory `/cluster/store3/markd/kent/src/lib'
#   ../inc/common.mk:2: *** missing separator.  Stop.
#   make[2]: Leaving directory `/cluster/store3/markd/kent/src/lib'
#   make[1]: *** [clean] Error 2
#   make[1]: Leaving directory `/cluster/store3/markd/kent/src'
#
# this makes the state machine somewhat complex
#

# parse make[n] to get level
function getLevel(line) {
    if (match(line, "^make:") != 0) {
        return "0";  # top level
    }
    if (match(line, "^make\\[([0-9]+)\\]:", a) == 0) {
        print "Error: can't parse:",line >"/dev/stderr";
        exit(1);
    }
    return a[1];
}

# print buffered lines, if there is any output buffered.  Reset buffer
# state
function prLines(level) {
    if ((levelOutCnt[level] > 0) && (levelStarts[level] <= nLines)) {
        if (errCount == 0) {
            print sep >"/dev/stderr";
        }
        for (i = levelStarts[level]; i <= nLines; i++) {
            print lines[i] >"/dev/stderr";
        }
        print sep >"/dev/stderr";
        nLines = 0;
        levelOutCnt[level] = 0;
        levelStarts[level] = -1;
        errCount++;
    }
    
}

BEGIN {
    nLines = 0;  # count of lines buffered in lines array
    level = 0;   # current make level
    curLevel = 0;     # currrent level being parsed
    prevWasLeave = 0;  # previous line was leaving a directory
    errCount = 0;      # count of errors reported
    # arrays
    #  lines - array of all lines in file 
    #  levelStarts - contains line index where level started
    #  levelOutCnt - count of none make: lines at this level
    sep = "-----------------------------------------------------";
}

{
    lines[++nLines] = $0;
}

/^make\[[0-9]+\]: Entering directory/ {
    curLevel = getLevel($0);
    levelStarts[curLevel] = nLines;
    levelOutCnt[curLevel] = 0;
}

/^make.*: \*\*\*/ {
    prLines((prevWasLeave ? curLevel+1 : curLevel));
}

{
    prevWasLeave = 0;  # reset now that print check is done.
}

/^make\[[0-9]+\]: Leaving directory/ {
    curLevel = getLevel($0)-1;
    prevWasLeave = 1;
}

!/^make\[[0-9]+\]:/ {
    levelOutCnt[curLevel]++;
}
