git @ Cat's Eye Technologies Kangaroo-Iceberg / master src / graph.c
master

Tree @master (Download .tar.gz)

graph.c @masterraw · history · blame

/*
 * Copyright (c)2004 Cat's Eye Technologies.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 
 *   Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 * 
 *   Neither the name of Cat's Eye Technologies nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
/*
 * graph.h
 * Graph housekeeping and manipulation for kiceberg.
 * $Id$
 */

#include <stdio.h>
#include <stdlib.h>

#include "graph.h"
#include "symbol.h"
#include "mem.h"

struct node *
node_new(struct symbol *sym)
{
	struct node *n;

	MALLOC(n, node, "graph node");

	n->head = NULL;
	n->name = sym;

	if (sym != NULL)
		sym->dest = n;

	return(n);
}

void
node_free(struct node *n)
{
	struct arc *a, *a_last = NULL;

	a = n->head;
	while (a != NULL) {
		a_last = a;
		a = a->next;
		FREE(a_last, "arc");
	}
	FREE(n, "graph node");
}

void
graph_free(struct node *n)
{
	/* struct arc *a; */

	/* free all nodes connected to arcs */
	/* construct an itinerary and so forth */
	node_free(n);
}

struct arc *
node_arc_add(struct node *n, struct symbol *name, int weight)
{
	struct arc *a;

	MALLOC(a, arc, "graph arc");

	a->name = name;
	a->weight = weight;

	a->next = n->head;
	n->head = a;
	
	return(a);
}

struct itinerary *
itinerary_new(void)
{
	struct itinerary *i;

	MALLOC(i, itinerary, "itinerary");
	i->head = NULL;
	return(i);
}

void
itinerary_free(struct itinerary *i)
{
	struct visit *v, *v_last = NULL;

	v = i->head;
	while (v != NULL) {
		v_last = v;
		v = v->next;
		FREE(v_last, "visit");
	}
}

struct visit *
itinerary_add(struct itinerary *i, struct node *n)
{
	struct visit *v;

	MALLOC(v, visit, "visit");

	v->dest = n;

	v->next = i->head;
	i->head = v;

	return(v);
}

int
itinerary_find(struct itinerary *i, struct node *n)
{
	struct visit *v;

	for (v = i->head; v != NULL; v = v->next) {
		if (v->dest == n)
			return(1);
	}
	
	return(0);
}


void
node_dump(struct node *n)
{
	struct arc *a;

	if (n == NULL) {
		fprintf(stderr, " *NULLNODE { }\n");
		return;
	}
	symbol_print(n->name);
	fprintf(stderr, " { ");

	for (a = n->head; a != NULL; a = a->next)
		arc_dump(a);

	fprintf(stderr, "}\n");
}

void
arc_dump(struct arc *a)
{
	if (a == NULL) {
		fprintf(stderr, "*NULLARC*");
		return;
	}

	symbol_print(a->name);
	fprintf(stderr, ":%d ", a->weight);
}

void
graph_dump(struct node *start)
{
	struct itinerary *i;
		
	i = itinerary_new();
	graph_dump_r(start, i, 0);
	fprintf(stderr, "\n");
}

#define INDENT(x) { int j; for (j = 0; j < x; j++) fprintf(stderr, "  "); }

void
graph_dump_r(struct node *n, struct itinerary *i, int indent)
{
	struct arc *a;

	if (n == NULL)
		return;

	INDENT(indent);
	
	if (itinerary_find(i, n)) {
		symbol_print(n->name);
	} else {
		itinerary_add(i, n);
		symbol_print(n->name);
		fprintf(stderr, " {\n");
		for (a = n->head; a != NULL; a = a->next) {
			graph_dump_r(a->name->dest, i, indent + 1);
			fprintf(stderr, ":%d\n", a->weight);
		}
		INDENT(indent);
		fprintf(stderr, "}");
	}
}