Task: Topological sort_Extracted top item

C: char input[] =	"top1    des1 ip1 ip2\n"
		"top2    des1 ip2 ip3\n"
		"ip1     extra1 ip1a ipcommon\n"
		"ip2     ip2a ip2b ip2c ipcommon\n"
		"des1    des1a des1b des1c\n"
		"des1a   des1a1 des1a2\n"
		"des1c   des1c1 extra1\n";

...
int find_name(item base, int len, const char *name)
{
	int i;
	for (i = 0; i < len; i++)
		if (!strcmp(base[i].name, name)) return i;
	return -1;
}

int depends_on(item base, int n1, int n2)
{
	int i;
	if (n1 == n2) return 1;
	for (i = 0; i < base[n1].n_deps; i++)
		if (depends_on(base, base[n1].deps[i], n2)) return 1;
	return 0;
}

void compile_order(item base, int n_items, int *top, int n_top)
{
	int i, j, lvl;
	int d = 0;
	printf("Compile order for:");
	for (i = 0; i < n_top; i++) {
		printf(" %s", base[top[i]].name);
		if (base[top[i]].depth > d)
			d = base[top[i]].depth;
	}
	printf("\n");

	for (lvl = 1; lvl <= d; lvl ++) {
		printf("level %d:", lvl);
		for (i = 0; i < n_items; i++) {
			if (base[i].depth != lvl) continue;
			for (j = 0; j < n_top; j++) {
				if (depends_on(base, top[j], i)) {
					printf(" %s", base[i].name);
					break;
				}
			}
		}
		printf("\n");
	}
	printf("\n");
}

int main()
{
	int i, n, bad = -1;
	item items;
	n = parse_input(&items);
 
	for (i = 0; i < n; i++)
		if (!items[i].depth && get_depth(items, i, bad) < 0) bad--;
 
	int top[3];
	top[0] = find_name(items, n, "top1");
	top[1] = find_name(items, n, "top2");
	top[2] = find_name(items, n, "ip1");

	compile_order(items, n, top, 1);
	compile_order(items, n, top + 1, 1);
	compile_order(items, n, top, 2);
	compile_order(items, n, top + 2, 1);

	return 0;
}




Go: package main

import (
    "fmt"
    "strings"
)

var data = `
FILE    FILE DEPENDENCIES
====    =================
top1    des1 ip1 ip2
top2    des1 ip2 ip3
ip1     extra1 ip1a ipcommon
ip2     ip2a ip2b ip2c ipcommon
des1    des1a des1b des1c
des1a   des1a1 des1a2
des1c   des1c1 extra1`

func main() {
    g, dep, err := parseLibDep(data)
    if err != nil {
        fmt.Println(err)
        return
    }
    
    
    
    var tops []string
    for n := range g {
        if !dep[n] {
            tops = append(tops, n)
        }
    }
    fmt.Println("Top levels:", tops)
    
    showOrder(g, "top1")         
    showOrder(g, "top2")         
    showOrder(g, "top1", "top2") 

    fmt.Println("Cycle examples:")
    
    g, _, err = parseLibDep(data + `
des1a1  des1`)
    if err != nil {
        fmt.Println(err)
        return
    }
    showOrder(g, "top1")       
    showOrder(g, "ip1", "ip2") 
}

func showOrder(g graph, target ...string) {
    order, cyclic := g.orderFrom(target...)
    if cyclic == nil {
        reverse(order) 
        fmt.Println("Target", target, "order:", order)
    } else {
        fmt.Println("Target", target, "cyclic dependencies:", cyclic)
    }
}

func reverse(s []string) {
    last := len(s) - 1
    for i, e := range s[:len(s)/2] {
        s[i], s[last-i] = s[last-i], e
    }
}

type graph map[string][]string 
type depList map[string]bool



func parseLibDep(data string) (g graph, d depList, err error) {
    lines := strings.Split(data, "\n")
    if len(lines) < 3 || !strings.HasPrefix(lines[2], "=") {
        return nil, nil, fmt.Errorf("data format")
    }
    lines = lines[3:]
    g = graph{}
    d = depList{}
    for _, line := range lines {
        libs := strings.Fields(line)
        if len(libs) == 0 {
            continue
        }
        lib := libs[0]
        var deps []string
        for _, dep := range libs[1:] {
            g[dep] = g[dep]
            if dep == lib {
                continue
            }
            for i := 0; ; i++ {
                if i == len(deps) {
                    deps = append(deps, dep)
                    d[dep] = true
                    break
                }
                if dep == deps[i] {
                    break
                }
            }
        }
        g[lib] = deps
    }
    return g, d, nil
}






func (g graph) orderFrom(start ...string) (order, cyclic []string) {
    L := make([]string, len(g))
    i := len(L)
    temp := map[string]bool{}
    perm := map[string]bool{}
    var cycleFound bool
    var cycleStart string
    var visit func(string)
    visit = func(n string) {
        switch {
        case temp[n]:
            cycleFound = true
            cycleStart = n
            return
        case perm[n]:
            return
        }
        temp[n] = true
        for _, m := range g[n] {
            visit(m)
            if cycleFound {
                if cycleStart > "" {
                    cyclic = append(cyclic, n)
                    if n == cycleStart {
                        cycleStart = ""
                    }
                }
                return
            }
        }
        delete(temp, n)
        perm[n] = true
        i--
        L[i] = n
    }
    for _, n := range start {
        if perm[n] {
            continue
        }
        visit(n)
        if cycleFound {
            return nil, cyclic
        }
    }
    return L[i:], nil
}