aklog-tidyup-20080401
[openafs.git] / src / aklog / linked_list.c
1 /* 
2  * $Id$
3  * 
4  * This file contains general linked list routines.
5  * 
6  * Copyright 1990,1991 by the Massachusetts Institute of Technology
7  * For distribution and copying rights, see the file "mit-copyright.h"
8  */
9
10 #include <afsconfig.h>
11 RCSID
12     ("$Header$");
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "linked_list.h"
18
19 #ifndef NULL
20 #define NULL 0
21 #endif
22
23 #ifndef TRUE
24 #define TRUE 1
25 #endif
26
27 #ifndef FALSE
28 #define FALSE 0
29 #endif
30
31 void ll_init(linked_list *list)
32   /* 
33    * Requires:
34    *   List must point to a linked list structure.  It is not acceptable
35    *   to pass a null pointer to this routine.
36    * Modifies:
37    *   list
38    * Effects:
39    *   Initializes the list to be one with no elements.  If list is
40    *   NULL, prints an error message and causes the program to crash.
41    */
42 {
43     if (list == NULL) {
44         fprintf(stderr, "Error: calling ll_init with null pointer.\n");
45         abort();
46     }
47
48     /* This sets everything to zero, which is what we want. */
49     bzero((char *)list, sizeof(linked_list));
50 }
51
52 ll_node *ll_add_node(linked_list *list, ll_end which_end)
53   /*
54    * Modifies:
55    *   list
56    * Effects: 
57    *   Adds a node to one end of the list (as specified by which_end)
58    *   and returns a pointer to the node added.  which_end is of type
59    *   ll_end and should be either ll_head or ll_tail as specified in 
60    *   list.h.  If there is not enough memory to allocate a node, 
61    *   the program returns NULL.
62    */
63 {
64     ll_node *node = NULL;
65     
66     if ((node = (ll_node *)calloc(1, sizeof(ll_node))) != NULL) {
67         if (list->nelements == 0) {
68             list->first = node;
69             list->last = node;
70             list->nelements = 1;
71         }
72         else {
73             switch (which_end) {
74               case ll_head:
75                 list->first->prev = node;
76                 node->next = list->first;
77                 list->first = node;
78                 break;
79               case ll_tail:
80                 list->last->next = node;
81                 node->prev = list->last;
82                 list->last = node;
83                 break;
84               default:
85                 fprintf(stderr, "%s%s",
86                         "ll_add_node got a which_end parameter that ",
87                         "it can't handle.\n");
88                 abort();
89             }
90             list->nelements++;
91         }
92     }
93         
94     return(node);
95 }
96
97
98 int ll_delete_node(linked_list *list, ll_node *node)
99   /* 
100    * Modifies: 
101    *   list
102    * Effects:
103    *   If node is in list, deletes node and returns LL_SUCCESS.  
104    *   Otherwise, returns LL_FAILURE.  If node contains other data,
105    *   it is the responsibility of the caller to free it.  Also, since
106    *   this routine frees node, after the routine is called, "node"
107    *   won't point to valid data.
108    */
109 {
110     int status = LL_SUCCESS;
111     ll_node *cur_node = NULL;
112     int found = FALSE;
113
114     if (list->nelements == 0)
115         status = LL_FAILURE;
116     else {
117         for (cur_node = list->first; (cur_node != NULL) && !found;
118              cur_node = cur_node->next) {
119             if (cur_node == node) {
120
121                 if (cur_node->prev)
122                     cur_node->prev->next = cur_node->next;
123                 else
124                     list->first = cur_node->next;
125
126                 if (cur_node->next)
127                     cur_node->next->prev = cur_node->prev;
128                 else
129                     list->last = cur_node->prev;
130
131                 free(cur_node);
132                 list->nelements--;
133                 found = TRUE;
134             }
135         }
136     }
137
138     if (!found)
139         status = LL_FAILURE;
140
141     return(status);
142 }
143
144
145 /* ll_add_data is a macro defined in linked_list.h */
146
147 /* This routine maintains a list of strings preventing duplication. */
148 int ll_string(linked_list *list, ll_s_action action, char *string)
149 {
150     int status = LL_SUCCESS;
151     ll_node *cur_node;
152
153     switch(action) {
154       case ll_s_check:
155         /* Scan the list until we find the string in question */
156         for (cur_node = list->first; cur_node && (status == FALSE); 
157              cur_node = cur_node->next)
158             status = (strcmp(string, cur_node->data) == 0);
159         break;
160       case ll_s_add:
161         /* Add a string to the list. */
162         if (!ll_string(list, ll_s_check, string)) {
163             if ((cur_node = ll_add_node(list, ll_tail))) {
164                 char *new_string;
165                 if ((new_string = (char *)calloc(strlen(string) + 1, 
166                                                 sizeof(char)))) {
167                     strcpy(new_string, string);
168                     ll_add_data(cur_node, new_string);
169                 }
170                 else 
171                     status = LL_FAILURE;
172             }
173             else
174                 status = LL_FAILURE;
175         }
176         break;
177       default:
178         /* This should never happen */
179         status = LL_FAILURE;
180         break;
181     }
182
183     return(status);
184 }