/*+++++++++++++++++ linklist.c - implements some functions for linked lists markus@mhoenicka.de 7-11-00 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include /* for a definition of NULL */ #include /* for malloc */ #include #include "linklist.h" /********************************************************************* linked list for file descriptors This is an ordered linked list. The highest fd will always be the first member of the list. ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insert_olili(): inserts a new item into an ordered linked list. The list will be in descending order, so the first item after the sentinel is the item with the highest value int insert_olili returns 0 if ok, 1 if error struct olili *ptr_first pointer to sentinel int value the value to be inserted into the list (value >= 0) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int insert_olili(Olili *ptr_first, int value) { Olili *ptr_before; /* item before insertion point */ Olili *ptr_after; /* item after insertion point */ Olili *ptr_new_olili; /* new item */ ptr_before = ptr_first; /* start search at the beginning */ ptr_after = ptr_before->ptr_next; while (ptr_after != NULL) { if (ptr_after->fd <= value) { /* sort in descending order */ break; } ptr_after = ptr_after->ptr_next; ptr_before = ptr_before->ptr_next; } ptr_new_olili = malloc(sizeof(Olili)); if (ptr_new_olili == NULL) { return 1; } ptr_new_olili->fd = value; ptr_before->ptr_next = ptr_new_olili; ptr_new_olili->ptr_next = ptr_after; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_olili(): deletes an item from an ordered linked list. int delete_olili returns 0 if ok, 1 if error Olili *ptr_first pointer to sentinel int value the value to be inserted into the list ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_olili(Olili *ptr_first, int value) { Olili *ptr_before; /* item before deletion point */ Olili *ptr_curr; /* item at deletion point */ ptr_before = ptr_first; /* start search at the beginning */ ptr_curr = ptr_before->ptr_next; while (ptr_curr != NULL) { if (ptr_curr->fd == value) { /* got it */ break; } ptr_curr = ptr_curr->ptr_next; ptr_before = ptr_before->ptr_next; } if (ptr_curr == NULL) { return 1; } ptr_before->ptr_next = ptr_curr->ptr_next; free(ptr_curr); return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ max_olili(): returns the item with the highest value from an ordered linked list. int max_olili returns the maximum value, or -1 if an error occurred Olili *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int max_olili(Olili *ptr_first) { if (ptr_first != NULL && ptr_first->ptr_next != NULL) { return ptr_first->ptr_next->fd; } else if (ptr_first != NULL) { return ptr_first->fd; } else { return -1; } } /********************************************************************* linked list for allocated memory This is an unsorted linked list. The first list member is a sentinel which is not automatically deallocated by the lilimem functions. The calling fn has to explicitly declare, initialize, and destruct a lilimem struct for this purpose. ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insert_lilimem(): inserts a new member into the list int insert_lilimem returns 0 if ok, or 1 if an error occurred if an error occurs, the memory pointed to by ptr_mem will be freed Lilimem *ptr_first pointer to sentinel void** ptr_mem ptr to ptr to allocated memory char* varname ptr to string with the name of the variable used for that memory location. This name is used to find the correct list member if you want to delete a specific entry with the delete_lilimem() function. This can in fact be any unique string other than the variable name. You may pass NULL here if you don't use delete_lilimem(), but only delete_all_lilimem() ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int insert_lilimem(Lilimem *ptr_first, void** ptr_mem, char* varname) { Lilimem* ptr_new_item; if (varname && strlen(varname) > 32) { /* string too long to fit into struct */ return 1; } ptr_new_item = malloc(sizeof(Lilimem)); if (ptr_new_item == NULL) { /* malloc failed */ free(*ptr_mem); return 1; } if (varname) { strcpy(ptr_new_item->varname, varname); } else { (ptr_new_item->varname)[0] = '\0'; } ptr_new_item->ptr_mem = ptr_mem; ptr_new_item->ptr_next = ptr_first->ptr_next; ptr_first->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_lilimem(): deletes a member from the list by the varname int delete_lilimem returns 0 if ok, or 1 if an error occurred Lilimem *ptr_first pointer to sentinel char* varname ptr to string with the name of the variable used for that memory location ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_lilimem(Lilimem *ptr_first, char* varname) { Lilimem* ptr_curr_item; Lilimem* ptr_prev_item; int gotit = 0; ptr_prev_item = ptr_first; ptr_curr_item = ptr_first->ptr_next; while (ptr_curr_item) { if (ptr_curr_item->varname && strcmp(ptr_curr_item->varname, varname) == 0) { gotit = 1; break; } /* else: silently ignore if item has no varname */ ptr_prev_item = ptr_curr_item; ptr_curr_item = ptr_curr_item->ptr_next; } if (gotit) { free(*(ptr_curr_item->ptr_mem)); /* free the memory referenced by the list member */ /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */ *(ptr_curr_item->ptr_mem) = NULL; /* set the memory ptr to NULL to avoid problems with erroneous subsequent free() calls */ ptr_prev_item->ptr_next = ptr_curr_item->ptr_next; free(ptr_curr_item); /* free the memory allocated for the list member */ return 0; } else { return 1; } } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_all_lilimem(): deletes all members from the list int delete_all_lilimem returns 0 if ok, or 1 if an error occurred Lilimem *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_all_lilimem(Lilimem *ptr_first) { Lilimem* ptr_curr_item; Lilimem* ptr_next_item; ptr_curr_item = ptr_first->ptr_next; ptr_first->ptr_next = NULL; while (ptr_curr_item) { ptr_next_item = ptr_curr_item->ptr_next; /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */ free(*(ptr_curr_item->ptr_mem)); /* free the memory referenced by the list member */ *(ptr_curr_item->ptr_mem) = NULL; /* set the memory ptr to NULL to avoid problems with erroneous subsequent free() calls */ free(ptr_curr_item); /* free the memory allocated for the list member */ ptr_curr_item = ptr_next_item; } return 0; } /********************************************************************* linked list for decoding cgi data This is an unsorted linked list. The first list member is a sentinel which is not automatically deallocated by the lilimem functions. The calling fn has to explicitly declare, initialize, and destruct a lilimem struct for this purpose. ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insert_liliform(): inserts a new member into the list int insert_liliform returns 0 if ok, or 1 if an error occurred if an error occurs, the memory pointed to by ptr_mem will be freed Liliform *ptr_first pointer to sentinel char* name ptr to string with the name of the variable used for that memory location. char* value ptr to allocated memory ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int insert_liliform(Liliform *ptr_first, char* name, char* value) { Liliform* ptr_new_item; char* my_value; if (name == NULL) { return 0; /* do nothing, no error */ } if (strlen(name) > 32) { /* string too long to fit into struct */ return 1; } ptr_new_item = malloc(sizeof(Liliform)); if (!ptr_new_item) { /* malloc failed */ return 1; } strcpy(ptr_new_item->name, name); if (value && strlen(value)) { my_value = malloc(strlen(value)+1); if (!my_value) { free(ptr_new_item); return 1; } strcpy(my_value, value); ptr_new_item->value = my_value; } else { ptr_new_item->value = NULL; } ptr_new_item->ptr_next = ptr_first->ptr_next; ptr_first->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ append_liliform(): appends a new member into the list. The implementation is not very efficient but is ok for a low number of entries int append_liliform returns 0 if ok, or 1 if an error occurred if an error occurs Liliform *ptr_first pointer to sentinel char* name ptr to string with the name of the variable used for that memory location. char* value ptr to allocated memory ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int append_liliform(Liliform *ptr_first, char* name, char* value) { char* my_value; Liliform* ptr_new_item; Liliform* ptr_last_item; ptr_new_item = malloc(sizeof(Liliform)); if (!ptr_new_item) { /* malloc failed */ return 1; } strcpy(ptr_new_item->name, name); if (value && *value) { my_value = malloc(strlen(value)+1); if (!my_value) { free(ptr_new_item); return 1; } strcpy(my_value, value); ptr_new_item->value = my_value; } else { ptr_new_item->value = NULL; } ptr_new_item->ptr_next = NULL; ptr_last_item = ptr_first; /* this is going to be inefficient for a large number of entries */ while (ptr_last_item->ptr_next) { ptr_last_item = ptr_last_item->ptr_next; } ptr_last_item->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_liliform(): retrieves a member of the list by name Liliform* get_liliform returns a ptr to the first member whose name matches as specified and whose value is not NULL, otherwise it returns NULL Liliform *ptr_first pointer to sentinel char* name ptr to string with the name of the variable ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Liliform* get_liliform(Liliform* ptr_first, char* name) { Liliform* ptr_curr_item; Liliform* ptr_result = NULL; ptr_curr_item = ptr_first->ptr_next; while (ptr_curr_item) { if (!strcmp(ptr_curr_item->name, name)) { if (ptr_curr_item->value) { ptr_result = ptr_curr_item; } break; } ptr_curr_item = ptr_curr_item->ptr_next; } return ptr_result; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_nliliform(): retrieves a member of the list by partial name match Liliform* get_nliliform returns a ptr to the first member whose name matches as specified and whose value is not NULL, otherwise it returns NULL Liliform *ptr_first pointer to sentinel char* name ptr to string with the name of the variable size_t n the number of characters to compare, starting at name[0] ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Liliform* get_nliliform(Liliform* ptr_first, char* name, size_t n) { Liliform* ptr_curr_item; Liliform* ptr_result = NULL; ptr_curr_item = ptr_first->ptr_next; while (ptr_curr_item) { if (!strncmp(ptr_curr_item->name, name, n)) { if (ptr_curr_item->value) { ptr_result = ptr_curr_item; } break; } ptr_curr_item = ptr_curr_item->ptr_next; } return ptr_result; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_next_liliform(): retrieves next member of the list Liliform* get_next_liliform returns a ptr to the next member or NULL if we're at the end of the list. Use this fn to loop over all list entries. In the first iteration, pass a ptr to the sentinel. In subsequent iterations, pass the ptr that the previous iteration returns. Liliform *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Liliform* get_next_liliform(Liliform* ptr_first) { return ptr_first->ptr_next; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_all_liliform(): deletes all members from the list int delete_all_liliform returns 0 if ok, or 1 if an error occurred Liliform *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_all_liliform(Liliform *ptr_first) { Liliform* ptr_curr_item; Liliform* ptr_next_item; ptr_curr_item = ptr_first->ptr_next; ptr_first->ptr_next = NULL; while (ptr_curr_item) { ptr_next_item = ptr_curr_item->ptr_next; /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */ free(ptr_curr_item->value); /* free the memory allocated for the value */ free(ptr_curr_item); /* free the memory allocated for the list member */ ptr_curr_item = ptr_next_item; } return 0; } /********************************************************************* linked list for reading non-standard field mapping for BibTeX data This is an unsorted linked list. The first list member is a sentinel which is not automatically deallocated by the lilimem functions. The calling fn has to explicitly declare, initialize, and destruct a lilimem struct for this purpose. ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insert_lilibib(): inserts a new member into the list int insert_lilibib returns 0 if ok, or 1 if an error occurred if an error occurs, the memory pointed to by ptr_mem will be freed Lilibib *ptr_first pointer to sentinel char* name ptr to string with the name of the variable used for that memory location. May be NULL if retrieval by name is not necessary char* value ptr to allocated memory ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int insert_lilibib(Lilibib *ptr_first, char* name, char* value) { Lilibib* ptr_new_item; char* my_value; char* my_name; ptr_new_item = malloc(sizeof(Lilibib)); if (!ptr_new_item) { /* malloc failed */ return 1; } if (name && *name) { my_name = malloc(strlen(name)+1); if (!my_name) { free(ptr_new_item); return 1; } strcpy(my_name, name); ptr_new_item->name = my_name; } else { ptr_new_item->name = NULL; } if (value && *value) { my_value = malloc(strlen(value)+1); if (!my_value) { free(ptr_new_item); return 1; } strcpy(my_value, value); ptr_new_item->value = my_value; } else { ptr_new_item->value = NULL; } ptr_new_item->ptr_next = ptr_first->ptr_next; ptr_first->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_next_lilibib(): retrieves next member of the list Lilibib* get_next_lilibib returns a ptr to the next member or NULL if we're at the end of the list. Use this fn to loop over all list entries. In the first iteration, pass a ptr to the sentinel. In subsequent iterations, pass the ptr that the previous iteration returns. Lilibib *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Lilibib* get_next_lilibib(Lilibib* ptr_first) { return ptr_first->ptr_next; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_lilibib(): retrieves a member of the list by name Lilibib* get_next_lilibib returns a ptr to the list member with the given name or NULL if none such exists. Lilibib *ptr_first pointer to sentinel char* name name of the list member to return ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Lilibib* get_lilibib(Lilibib* ptr_first, char* name) { Lilibib* ptr_curr_item; Lilibib* ptr_result = NULL; ptr_curr_item = ptr_first->ptr_next; while (ptr_curr_item) { if (!strcmp(ptr_curr_item->name, name)) { if (ptr_curr_item->value) { ptr_result = ptr_curr_item; } break; } ptr_curr_item = ptr_curr_item->ptr_next; } return ptr_result; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_all_lilibib(): deletes all members from the list int delete_all_lilibib returns 0 if ok, or 1 if an error occurred Lilibib *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_all_lilibib(Lilibib *ptr_first) { Lilibib* ptr_curr_item; Lilibib* ptr_next_item; ptr_curr_item = ptr_first->ptr_next; ptr_first->ptr_next = NULL; while (ptr_curr_item) { ptr_next_item = ptr_curr_item->ptr_next; /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */ if (ptr_curr_item->name) { free(ptr_curr_item->name); /* free the memory allocated for the name */ } if (ptr_curr_item->value) { free(ptr_curr_item->value); /* free the memory allocated for the value */ } free(ptr_curr_item); /* free the memory allocated for the list member */ ptr_curr_item = ptr_next_item; } return 0; } /********************************************************************* linked list for reading id lists This is a sorted linked list. The first list member is a sentinel which is not automatically deallocated by the lilimem functions. The calling fn has to explicitly declare, initialize, and destruct a lilid struct for this purpose. The payload of a member is an id value and two ints used as booleans ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insert_lilid(): inserts a new member into the list int insert_lilid returns 0 if ok, or 1 if an error occurred Lilid *ptr_first pointer to sentinel unsigned long long value the value to store ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int insert_lilid(Lilid *ptr_first, unsigned long long value) { Lilid* ptr_new_item; /* ptr to new list member */ Lilid* ptr_before; /* ptr to member before insertion point */ Lilid* ptr_after; /* ptr to member after insertion point */ ptr_new_item = malloc(sizeof(Lilid)); if (!ptr_new_item) { /* malloc failed */ return 1; } /* set requested value */ ptr_new_item->value = value; /* set default values */ ptr_new_item->is_duplicate = 0; ptr_new_item->is_existent = 0; /* find insertion point */ ptr_before = ptr_first; /* start search at the beginning */ ptr_after = ptr_before->ptr_next; while (ptr_after != NULL) { if (ptr_after->value >= value) { /* sort in ascending order */ break; } ptr_after = ptr_after->ptr_next; ptr_before = ptr_before->ptr_next; } /* insert new item into list */ ptr_before->ptr_next = ptr_new_item; ptr_new_item->ptr_next = ptr_after; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_next_lilid(): retrieves next member of the list in ascending order Lilid* get_next_lilid returns a ptr to the next member or NULL if we're at the end of the list. Use this fn to loop over all list entries. In the first iteration, pass a ptr to the sentinel. In subsequent iterations, pass the ptr that the previous iteration returns. struct lilid *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Lilid* get_next_lilid(Lilid* ptr_first) { return ptr_first->ptr_next; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ count_lilid(): counts all members in the list unsigned long long count_lilid returns the number of list members Lilid *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ unsigned long long count_lilid(Lilid* ptr_first) { unsigned long long ull_counter = 0; Lilid *ptr_curr; /* start at the beginning */ ptr_curr = ptr_first; /* loop over all list elements */ while ((ptr_curr = get_next_lilid(ptr_curr)) != NULL) { ull_counter++; } return ull_counter; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_all_lilid(): deletes all members from the list int delete_all_lilid returns 0 if ok, or 1 if an error occurred Lilid *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_all_lilid(Lilid *ptr_first) { Lilid* ptr_curr_item; Lilid* ptr_next_item; /* skip the sentinel when freeing memory */ ptr_curr_item = ptr_first->ptr_next; ptr_first->ptr_next = NULL; /* loop over all list members after the sentinel */ while (ptr_curr_item) { /* save a pointer to the next member, if any */ ptr_next_item = ptr_curr_item->ptr_next; /* free the memory allocated for the list member */ free(ptr_curr_item); ptr_curr_item = ptr_next_item; } return 0; } /********************************************************************* linked list for tokenizing strings. The list stores pointers to the individual tokens. The calling function should terminate the tokens by inserting \0 between the tokens. This is an unsorted linked list. The first list member is a sentinel which is not automatically deallocated by the lilimem functions. The calling fn has to explicitly declare, initialize, and destruct a lilimem struct for this purpose. ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insert_lilistring(): inserts a new member into the list int insert_lilistring returns 0 if ok, or 1 if an error occurred if an error occurs Lilistring *ptr_first pointer to sentinel char* token ptr to token ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int insert_lilistring(Lilistring *ptr_first, char* token) { Lilistring* ptr_new_item; ptr_new_item = malloc(sizeof(Lilistring)); if (!ptr_new_item) { /* malloc failed */ return 1; } if (token) { ptr_new_item->token = token; } else { ptr_new_item->token = NULL; } ptr_new_item->ptr_next = ptr_first->ptr_next; ptr_first->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ append_lilistring(): appends a new member into the list. The implementation is not very efficient but is ok for a low number of entries int append_lilistring returns 0 if ok, or 1 if an error occurred if an error occurs Lilistring *ptr_first pointer to sentinel char* token ptr to token ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int append_lilistring(Lilistring *ptr_first, char* token) { Lilistring* ptr_new_item; Lilistring* ptr_last_item; ptr_new_item = malloc(sizeof(Lilistring)); if (!ptr_new_item) { /* malloc failed */ return 1; } if (token) { ptr_new_item->token = token; } else { ptr_new_item->token = NULL; } ptr_new_item->ptr_next = NULL; ptr_last_item = ptr_first; /* this is going to be inefficient for a large number of entries */ while (ptr_last_item->ptr_next) { ptr_last_item = ptr_last_item->ptr_next; } ptr_last_item->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_next_lilistring(): retrieves next member of the list Lilistring* get_next_lilistring returns a ptr to the next member or NULL if we're at the end of the list. Use this fn to loop over all list entries. In the first iteration, pass a ptr to the sentinel. In subsequent iterations, pass the ptr that the previous iteration returns. Lilistring *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Lilistring* get_next_lilistring(Lilistring* ptr_first) { return ptr_first->ptr_next; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_all_lilistring(): deletes all members from the list int delete_all_lilistring returns 0 if ok, or 1 if an error occurred Lilistring *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_all_lilistring(Lilistring *ptr_first) { Lilistring* ptr_curr_item; Lilistring* ptr_next_item; ptr_curr_item = ptr_first->ptr_next; ptr_first->ptr_next = NULL; while (ptr_curr_item) { ptr_next_item = ptr_curr_item->ptr_next; /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */ free(ptr_curr_item); /* free the memory allocated for the list member */ ptr_curr_item = ptr_next_item; } return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ count_lilistring(): counts all members in the list int count_lilistring returns the number of list members Lilistring *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int count_lilistring(Lilistring* ptr_first) { int counter = 0; Lilistring *ptr_curr; /* start at the beginning */ ptr_curr = ptr_first; /* loop over all list elements */ while ((ptr_curr = get_next_lilistring(ptr_curr)) != NULL) { counter++; } return counter; } /********************************************************************* linked list for fixed-size strings. The list keeps the original order of items ********************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ append_lilifstring(): appends a new member into the list. The implementation is not very efficient but is ok for a low number of entries int append_lilifstring returns 0 if ok, or 1 if an error occurred if an error occurs Lilifstring *ptr_first pointer to sentinel char* token ptr to token ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int append_lilifstring(Lilifstring *ptr_first, char* token) { Lilifstring* ptr_new_item; Lilifstring* ptr_last_item; ptr_new_item = malloc(sizeof(Lilifstring)); if (!ptr_new_item) { /* malloc failed */ return 1; } if (token) { strncpy(ptr_new_item->token, token, LILIFSTRING_SIZE); (ptr_new_item->token)[LILIFSTRING_SIZE-1] = '\0'; } else { (ptr_new_item->token)[0] = '\0'; } ptr_new_item->ptr_next = NULL; ptr_last_item = ptr_first; /* this is going to be inefficient for a large number of entries */ while (ptr_last_item->ptr_next) { ptr_last_item = ptr_last_item->ptr_next; } ptr_last_item->ptr_next = ptr_new_item; return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_next_lilifstring(): retrieves next member of the list Lilifstring* get_next_lilifstring returns a ptr to the next member or NULL if we're at the end of the list. Use this fn to loop over all list entries. In the first iteration, pass a ptr to the sentinel. In subsequent iterations, pass the ptr that the previous iteration returns. Lilifstring *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ Lilifstring* get_next_lilifstring(Lilifstring* ptr_first) { return ptr_first->ptr_next; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ delete_all_lilifstring(): deletes all members from the list int delete_all_lilifstring returns 0 if ok, or 1 if an error occurred Lilifstring *ptr_first pointer to sentinel ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int delete_all_lilifstring(Lilifstring *ptr_first) { Lilifstring* ptr_curr_item; Lilifstring* ptr_next_item; ptr_curr_item = ptr_first->ptr_next; ptr_first->ptr_next = NULL; while (ptr_curr_item) { ptr_next_item = ptr_curr_item->ptr_next; /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */ free(ptr_curr_item); /* free the memory allocated for the list member */ ptr_curr_item = ptr_next_item; } return 0; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ find_lilifstring(): checks whether token is already stored in the list int find_lilifstring returns 1 if token is part of the list. or 0 if not Lilifstring *ptr_first pointer to sentinel char* token ptr to token ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ char* find_lilifstring(Lilifstring* ptr_first, char* token) { Lilifstring* ptr_curr_item; ptr_curr_item = ptr_first; while ((ptr_curr_item = get_next_lilifstring(ptr_curr_item)) != NULL) { if (!strcmp(ptr_curr_item->token, token)) { return token; } } return NULL; }