Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 2ed6ddea7d
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 89 lines (71 sloc) 2.351 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
/*
* Copyright 2004 Jim Radford <radford@blackbean.org>
* Copyright 2007 David Caldwell <david@porkrind.org>
*/

#include "autolist.h"

struct autolist {
    struct autolist *next;
};

struct autolist *__autolist_chain(void *_head, void *_next, size_t offset_of_first)
{
    struct autolist *head = _head + offset_of_first, *next = _next, **start = &head->next;
    //while (*start) start = &(*start)->next; // call in order of construction
    struct autolist *orig = *start;
    *start = next;
    next->next = orig;
    return orig;
}

autolist_declare(void *, generic); // Not a real autolist, just used to get structures defined.

typedef struct __autolist_struct(generic) autolist; // Trust me, it's impossible to read without this.

static autolist *unhook(autolist *item, autolist **rest)
{
    // Remove item from rest.
    for (autolist *i = *rest, *last = NULL; i; last=i, i=i->next)
        if (i == item) {
            if (last)
                last->next = i->next;
            else
                *rest = (*rest)->next;
            break;
        }
    item->next = NULL;
    return item;
}

static void append(autolist ***next, autolist *list)
{
    **next = list;
    for (autolist *i=list; i; i=i->next)
        if (!i->next) // only advance next when we hit the end of list
            *next = &i->next;
}

#include <stdio.h>
static autolist *autolist_deps(autolist *item, autolist **rest)
{
    unhook(item, rest);
    item->state = as_sorting;

    autolist *deps, **next=&deps;
    for (struct __autolist_order(generic) *after = item->after; after; after=after->next) {
        if (after->dependency->state == as_sorting)
            fprintf(stderr, "Circular dependency! Dropping \"%s\"\n", after->description);
        if (after->dependency->state == as_unsorted)
            append(&next, autolist_deps(after->dependency, rest));
    }

    item->state = as_sorted;
    append(&next, item);

    return deps;
}

static autolist *autolist_sort(autolist *rest)
{
    autolist *list, **next=&list;

    while (rest)
        append(&next, autolist_deps(rest, &rest));

    return list;
}

void *__autolist__first(void *_list)
{
    struct __autolist_kind(generic) *list = _list;
    if (!list->unsorted) return list->first;

    list->first = autolist_sort(list->first);

    list->unsorted = false;
    return list->first;
}
Something went wrong with that request. Please try again.