/* Copyright 1999, 1991, 1999 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */ /* This file contains general linked list routines. */ static const char rcsid[] = "$Id$"; #include #include #include #include "linked_list.h" /* * Requires: * List must point to a linked list structure. It is not acceptable * to pass a null pointer to this routine. * Modifies: * list * Effects: * Initializes the list to be one with no elements. If list is * NULL, prints an error message and causes the program to crash. */ void ll_init(linked_list *list) { if (list == NULL) { fprintf(stderr, "Error: calling ll_init with null pointer.\n"); abort(); } list->first = list->last = NULL; list->nelements = 0; } /* * Modifies: * list * Effects: * Adds a node to one end of the list (as specified by which_end) * and returns a pointer to the node added. which_end is of type * ll_end and should be either ll_head or ll_tail as specified in * list.h. If there is not enough memory to allocate a node, * the program returns NULL. */ ll_node *ll_add_node(linked_list *list, ll_end which_end) { ll_node *node = NULL; node = malloc(sizeof(ll_node)); if (node) { node->data = NULL; if (list->nelements == 0) { list->first = node; list->last = node; list->nelements = 1; node->prev = node->next = NULL; } else { switch (which_end) { case ll_head: list->first->prev = node; node->next = list->first; list->first = node; node->prev = NULL; break; case ll_tail: list->last->next = node; node->prev = list->last; list->last = node; node->next = NULL; break; default: fprintf(stderr, "ll_add_node got a which_end parameter that " "it can't handle.\n"); abort(); } list->nelements++; } } return node; } /* * Modifies: * list * Effects: * If node is in list, deletes node and returns LL_SUCCESS. * Otherwise, returns LL_FAILURE. If node contains other data, * it is the responsibility of the caller to free it. Also, since * this routine frees node, after the routine is called, "node" * won't point to valid data. */ int ll_delete_node(linked_list *list, ll_node *node) { ll_node *cur_node; for (cur_node = list->first; cur_node; cur_node = cur_node->next) { if (cur_node == node) { if (cur_node->prev) cur_node->prev->next = cur_node->next; else list->first = cur_node->next; if (cur_node->next) cur_node->next->prev = cur_node->prev; else list->last = cur_node->prev; free(cur_node); list->nelements--; return LL_SUCCESS; } } return LL_FAILURE; } int ll_string_check(linked_list *list, char *string) { ll_node *cur_node; /* Scan the list until we find the string in question */ for (cur_node = list->first; cur_node; cur_node = cur_node->next) { if (strcmp(string, cur_node->data) == 0) return 1; } return 0; } /* This routine maintains a list of strings preventing duplication. */ int ll_add_string(linked_list *list, char *string) { ll_node *node; char *new_string; if (!ll_string_check(list, string)) { node = ll_add_node(list, ll_tail); if (node) { new_string = strdup(string); if (new_string) ll_add_data(node, new_string); else return LL_FAILURE; } else return LL_FAILURE; } return LL_SUCCESS; }