1 const char list_rcs[] = "$Id: list.c,v 1.19 2007/04/17 18:14:06 fabiankeil Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/list.c,v $
6 * Purpose : Declares functions to handle lists.
7 * Functions declared include:
8 * `destroy_list', `enlist' and `list_to_text'
10 * Copyright : Written by and Copyright (C) 2001-2007 the SourceForge
11 * Privoxy team. http://www.privoxy.org/
13 * Based on the Internet Junkbuster originally written
14 * by and Copyright (C) 1997 Anonymous Coders and
15 * Junkbusters Corporation. http://www.junkbusters.com
17 * This program is free software; you can redistribute it
18 * and/or modify it under the terms of the GNU General
19 * Public License as published by the Free Software
20 * Foundation; either version 2 of the License, or (at
21 * your option) any later version.
23 * This program is distributed in the hope that it will
24 * be useful, but WITHOUT ANY WARRANTY; without even the
25 * implied warranty of MERCHANTABILITY or FITNESS FOR A
26 * PARTICULAR PURPOSE. See the GNU General Public
27 * License for more details.
29 * The GNU General Public License should be included with
30 * this file. If not, you can view it at
31 * http://www.gnu.org/copyleft/gpl.html
32 * or write to the Free Software Foundation, Inc., 59
33 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 * Revision 1.19 2007/04/17 18:14:06 fabiankeil
38 * Add list_contains_item().
40 * Revision 1.18 2006/12/28 19:21:23 fabiankeil
41 * Fixed gcc43 warning and enabled list_is_valid()'s loop
42 * detection again. It was ineffective since the removal of
43 * the arbitrary list length limit two years ago.
45 * Revision 1.17 2006/07/18 14:48:46 david__schmidt
46 * Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
47 * with what was really the latest development (the v_3_0_branch branch)
49 * Revision 1.15.2.2 2004/05/25 02:04:23 david__schmidt
50 * Removed the "arbitrary" 1000 filter limit in file.c. See tracker #911950.
52 * Revision 1.15.2.1 2002/11/28 18:14:54 oes
53 * Added unmap function that removes all items with a given
56 * Revision 1.15 2002/03/26 22:29:55 swa
57 * we have a new homepage!
59 * Revision 1.14 2002/03/24 13:25:43 swa
60 * name change related issues
62 * Revision 1.13 2002/03/07 03:46:17 oes
63 * Fixed compiler warnings
65 * Revision 1.12 2001/10/25 03:40:48 david__schmidt
66 * Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
67 * threads to call select() simultaneously. So, it's time to do a real, live,
68 * native OS/2 port. See defines for __EMX__ (the porting layer) vs. __OS2__
69 * (native). Both versions will work, but using __OS2__ offers multi-threading.
71 * Revision 1.11 2001/10/23 21:21:03 jongfoster
72 * New error handling - error codes are now jb_errs, not ints.
73 * Changed the way map() handles out-of-memory, to dramatically
74 * reduce the amount of error-checking clutter needed.
76 * Revision 1.10 2001/09/16 17:30:24 jongfoster
77 * Fixing a compiler warning.
79 * Revision 1.9 2001/09/16 13:20:29 jongfoster
80 * Rewrite of list library. Now has seperate header and list_entry
81 * structures. Also added a large sprinking of assert()s to the list
84 * Revision 1.8 2001/08/07 14:00:20 oes
87 * Revision 1.7 2001/08/05 16:06:20 jongfoster
88 * Modifiying "struct map" so that there are now separate header and
89 * "map_entry" structures. This means that functions which modify a
90 * map no longer need to return a pointer to the modified map.
91 * Also, it no longer reverses the order of the entries (which may be
92 * important with some advanced template substitutions).
94 * Revision 1.6 2001/07/31 14:44:51 oes
95 * list_to_text() now appends empty line at end
97 * Revision 1.5 2001/06/29 21:45:41 oes
98 * Indentation, CRLF->LF, Tab-> Space
100 * Revision 1.4 2001/06/29 13:30:22 oes
101 * - Added Convenience function enlist_unique_header(),
102 * which takes the Header name and value as separate
103 * arguments and thus saves the pain of sprintf()ing
104 * and determining the Header name length to enlist_unique
105 * - Improved comments
106 * - Removed logentry from cancelled commit
108 * Revision 1.3 2001/06/03 19:12:24 oes
109 * functions for new struct map, extended enlist_unique
111 * Revision 1.2 2001/06/01 18:49:17 jongfoster
112 * Replaced "list_share" with "list" - the tiny memory gain was not
113 * worth the extra complexity.
115 * Revision 1.1 2001/05/31 21:11:53 jongfoster
116 * - Moved linked list support to new "list.c" file.
117 * Structure definitions are still in project.h,
118 * function prototypes are now in "list.h".
119 * - Added support for "struct list_share", which is identical
120 * to "struct list" except it saves memory by not duplicating
121 * the strings. Obviously, this only works if there is some
122 * other way of managing the memory used by the strings.
123 * (These list_share lists are used for lists which last
124 * for only 1 request, and where all the list entries are
125 * just coming directly from entries in the actionsfile.)
126 * Note that you still need to destroy list_share lists
127 * properly to free the nodes - it's only the strings
131 *********************************************************************/
137 /* FIXME: The following headers are not needed for Win32. Are they
138 * needed on other platforms?
141 #include <sys/types.h>
147 #if !defined(_WIN32) && !defined(__OS2__)
155 #include "miscutil.h"
157 const char list_h_rcs[] = LIST_H_VERSION;
160 static int list_is_valid (const struct list *the_list);
163 /*********************************************************************
165 * Function : init_list
167 * Description : Create a new, empty list in user-allocated memory.
168 * Caller should allocate a "struct list" variable,
169 * then pass it to this function.
170 * (Implementation note: Rather than calling this
171 * function, you can also just memset the memory to
172 * zero, e.g. if you have a larger structure you
173 * want to initialize quickly. However, that isn't
174 * really good design.)
177 * 1 : the_list = pointer to list
181 *********************************************************************/
182 void init_list(struct list *the_list)
184 memset(the_list, '\0', sizeof(*the_list));
188 /*********************************************************************
190 * Function : destroy_list
192 * Description : Destroy a string list (opposite of list_init).
193 * On return, the memory used by the list entries has
194 * been freed, but not the memory used by the_list
195 * itself. You should not re-use the_list without
196 * calling list_init().
198 * (Implementation note: You *can* reuse the_list
199 * without calling list_init(), but please don't.
200 * If you want to remove all entries from a list
201 * and still have a usable list, then use
202 * list_remove_all().)
205 * 1 : the_list = pointer to list
209 *********************************************************************/
210 void destroy_list (struct list *the_list)
212 struct list_entry *cur_entry, *next_entry;
216 for (cur_entry = the_list->first; cur_entry ; cur_entry = next_entry)
218 next_entry = cur_entry->next;
219 freez(cur_entry->str);
223 the_list->first = NULL;
224 the_list->last = NULL;
228 /*********************************************************************
230 * Function : list_is_valid
232 * Description : Check that a string list is valid. The intended
233 * usage is "assert(list_is_valid(the_list))".
234 * Currently this checks that "the_list->last"
235 * is correct, and that the list dosn't contain
236 * circular references. It is likely to crash if
237 * it's passed complete garbage.
240 * 1 : the_list = pointer to list. Must be non-null.
242 * Returns : 1 if list is valid, 0 otherwise.
244 *********************************************************************/
245 static int list_is_valid (const struct list *the_list)
248 * If you don't want this check, just change the line below
249 * from "#if 1" to "#if 0".
252 const struct list_entry *cur_entry;
253 const struct list_entry *last_entry = NULL;
258 for (cur_entry = the_list->first; cur_entry ; cur_entry = cur_entry->next)
260 last_entry = cur_entry;
265 * Just check that this string can be accessed - i.e. it's a valid
268 (void)strlen(cur_entry->str);
272 * Check for looping back to first
274 if ((entry++ != 0) && (cur_entry == the_list->first))
280 * Arbitrarily limit list length to prevent infinite loops.
281 * Note that the 1000 limit was hit by a real user in tracker 911950;
282 * removing it for now. Real circular references should eventually
283 * be caught by the check above, anyway.
293 * Check this isn't marked as the last entry, unless of course it's
294 * *really* the last entry.
296 if ((the_list->last == cur_entry) && (cur_entry->next != NULL))
298 /* This is the last entry, but there's data after it !!?? */
303 return (the_list->last == last_entry);
309 /*********************************************************************
313 * Description : Append a string into a specified string list.
316 * 1 : the_list = pointer to list
317 * 2 : str = string to add to the list (maybe NULL)
319 * Returns : JB_ERR_OK on success
320 * JB_ERR_MEMORY on out-of-memory error.
321 * On error, the_list will be unchanged.
323 *********************************************************************/
324 jb_err enlist(struct list *the_list, const char *str)
326 struct list_entry *cur;
329 assert(list_is_valid(the_list));
331 if (NULL == (cur = (struct list_entry *)zalloc(sizeof(*cur))))
333 return JB_ERR_MEMORY;
338 if (NULL == (cur->str = strdup(str)))
341 return JB_ERR_MEMORY;
344 /* else { cur->str = NULL; } - implied by zalloc */
346 /* cur->next = NULL; - implied by zalloc */
350 the_list->last->next = cur;
351 the_list->last = cur;
355 the_list->first = cur;
356 the_list->last = cur;
359 assert(list_is_valid(the_list));
364 /*********************************************************************
366 * Function : enlist_first
368 * Description : Append a string as first element into a specified
372 * 1 : the_list = pointer to list
373 * 2 : str = string to add to the list (maybe NULL)
375 * Returns : JB_ERR_OK on success
376 * JB_ERR_MEMORY on out-of-memory error.
377 * On error, the_list will be unchanged.
379 *********************************************************************/
380 jb_err enlist_first(struct list *the_list, const char *str)
382 struct list_entry *cur;
385 assert(list_is_valid(the_list));
387 if (NULL == (cur = (struct list_entry *)zalloc(sizeof(*cur))))
389 return JB_ERR_MEMORY;
394 if (NULL == (cur->str = strdup(str)))
397 return JB_ERR_MEMORY;
400 /* else { cur->str = NULL; } - implied by zalloc */
402 cur->next = the_list->first;
404 the_list->first = cur;
405 if (the_list->last == NULL)
407 the_list->last = cur;
410 assert(list_is_valid(the_list));
415 /*********************************************************************
417 * Function : enlist_unique
419 * Description : Append a string into a specified string list,
420 * if & only if it's not there already.
421 * If the num_significant_chars argument is nonzero,
422 * only compare up to the nth character.
425 * 1 : the_list = pointer to list
426 * 2 : str = string to add to the list
427 * 3 : num_significant_chars = number of chars to use
428 * for uniqueness test, or 0 to require an exact match.
430 * Returns : JB_ERR_OK on success
431 * JB_ERR_MEMORY on out-of-memory error.
432 * On error, the_list will be unchanged.
433 * "Success" does not indicate whether or not the
434 * item was already in the list.
436 *********************************************************************/
437 jb_err enlist_unique(struct list *the_list, const char *str,
438 size_t num_significant_chars)
440 struct list_entry *cur_entry;
443 assert(list_is_valid(the_list));
445 assert(num_significant_chars >= 0);
446 assert(num_significant_chars <= strlen(str));
448 if (num_significant_chars > 0)
450 for (cur_entry = the_list->first; cur_entry != NULL; cur_entry = cur_entry->next)
452 if ( (cur_entry->str != NULL)
453 && (0 == strncmp(str, cur_entry->str, num_significant_chars)))
462 /* Test whole string */
463 for (cur_entry = the_list->first; cur_entry != NULL; cur_entry = cur_entry->next)
465 if ( (cur_entry->str != NULL) && (0 == strcmp(str, cur_entry->str)))
473 return enlist(the_list, str);
477 /*********************************************************************
479 * Function : enlist_unique_header
481 * Description : Make a HTTP header from the two strings name and value,
482 * and append the result into a specified string list,
483 * if & only if there isn't already a header with that name.
486 * 1 : the_list = pointer to list
487 * 2 : name = HTTP header name (e.g. "Content-type")
488 * 3 : value = HTTP header value (e.g. "text/html")
490 * Returns : JB_ERR_OK on success
491 * JB_ERR_MEMORY on out-of-memory error.
492 * On error, the_list will be unchanged.
493 * "Success" does not indicate whether or not the
494 * header was already in the list.
496 *********************************************************************/
497 jb_err enlist_unique_header(struct list *the_list, const char *name,
500 jb_err result = JB_ERR_MEMORY;
505 assert(list_is_valid(the_list));
509 /* + 2 for the ': ', + 1 for the \0 */
510 header_size = strlen(name) + 2 + strlen(value) + 1;
511 header = (char *)malloc(header_size);
515 const size_t bytes_to_compare = strlen(name) + 2;
517 snprintf(header, header_size, "%s: %s", name, value);
518 result = enlist_unique(the_list, header, bytes_to_compare);
520 assert(list_is_valid(the_list));
528 /*********************************************************************
530 * Function : list_remove_all
532 * Description : Remove all entries from a list. On return, the_list
533 * is a valid, empty list. Note that this is similar
534 * to destroy_list(), but the difference is that this
535 * function guarantees that the list structure is still
536 * valid after the call.
539 * 1 : the_list = pointer to list
543 *********************************************************************/
544 void list_remove_all(struct list *the_list)
546 struct list_entry *cur_entry;
547 struct list_entry *next_entry;
550 assert(list_is_valid(the_list));
552 for (cur_entry = the_list->first; cur_entry ; cur_entry = next_entry)
554 next_entry = cur_entry->next;
555 freez(cur_entry->str);
559 the_list->first = the_list->last = NULL;
561 assert(list_is_valid(the_list));
565 /*********************************************************************
567 * Function : list_to_text
569 * Description : "Flatten" a string list into 1 long \r\n delimited string,
570 * adding an empty line at the end. NULL entries are ignored.
571 * This function does not change the_list.
573 * XXX: Should probably be renamed as it's only
574 * useful (and used) to flatten header lists.
577 * 1 : the_list = pointer to list
579 * Returns : NULL on malloc error, else new long string.
580 * Caller must free() it.
582 *********************************************************************/
583 char *list_to_text(const struct list *the_list)
585 struct list_entry *cur_entry;
592 assert(list_is_valid(the_list));
595 * Calculate the lenght of the final text.
596 * '2' because of the '\r\n' at the end of
597 * each string and at the end of the text.
600 for (cur_entry = the_list->first; cur_entry; cur_entry = cur_entry->next)
604 text_length += strlen(cur_entry->str) + 2;
608 bytes_left = text_length + 1;
610 text = (char *)malloc(bytes_left);
618 for (cur_entry = the_list->first; cur_entry; cur_entry = cur_entry->next)
622 const int written = snprintf(cursor, bytes_left, "%s\r\n", cur_entry->str);
625 assert(written < bytes_left);
627 bytes_left -= (size_t)written;
628 cursor += (size_t)written;
632 assert(bytes_left == 3);
638 assert(text_length == cursor - text);
639 assert(text[text_length] == '\0');
645 /*********************************************************************
647 * Function : list_remove_item
649 * Description : Remove a string from a specified string list.
652 * 1 : the_list = pointer to list
653 * 2 : str = string to remove from the list - non-NULL
655 * Returns : Number of times it was removed.
657 *********************************************************************/
658 int list_remove_item(struct list *the_list, const char *str)
660 struct list_entry *prev = NULL;
661 struct list_entry *cur;
662 struct list_entry *next;
666 assert(list_is_valid(the_list));
669 cur = the_list->first;
675 if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
685 the_list->first = next;
687 free((char *)cur->str);
697 the_list->last = prev;
699 assert(list_is_valid(the_list));
705 /*********************************************************************
707 * Function : list_remove_list
709 * Description : Remove all strings in one list from another list.
710 * This is currently a brute-force algorithm
711 * (it compares every pair of strings).
714 * 1 : dest = list to change
715 * 2 : src = list of strings to remove
717 * Returns : Total number of strings removed.
719 *********************************************************************/
720 int list_remove_list(struct list *dest, const struct list *src)
722 struct list_entry *cur;
727 assert(list_is_valid(src));
728 assert(list_is_valid(dest));
730 for (cur = src->first; cur != NULL; cur = cur->next)
732 if (cur->str != NULL)
734 count += list_remove_item(dest, cur->str);
738 assert(list_is_valid(src));
739 assert(list_is_valid(dest));
745 /*********************************************************************
747 * Function : list_duplicate
749 * Description : Copy a string list
752 * 1 : dest = Destination list. Must be a valid list.
753 * All existing entries will be removed.
754 * 1 : src = pointer to source list for copy.
756 * Returns : JB_ERR_OK on success
757 * JB_ERR_MEMORY on out-of-memory error.
758 * On error, dest will be empty.
760 *********************************************************************/
761 jb_err list_duplicate(struct list *dest, const struct list *src)
763 struct list_entry * cur_src;
764 struct list_entry * cur_dest;
768 assert(list_is_valid(src));
769 assert(list_is_valid(dest));
771 list_remove_all(dest);
773 /* Need to process first entry specially so we can set dest->first */
774 cur_src = src->first;
777 cur_dest = dest->first = (struct list_entry *)zalloc(sizeof(*cur_dest));
778 if (cur_dest == NULL)
782 assert(list_is_valid(src));
783 assert(list_is_valid(dest));
785 return JB_ERR_MEMORY;
790 cur_dest->str = strdup(cur_src->str);
791 if (cur_dest->str == NULL)
795 assert(list_is_valid(src));
796 assert(list_is_valid(dest));
798 return JB_ERR_MEMORY;
801 /* else { cur_dest->str = NULL; } - implied by zalloc */
803 /* Now process the rest */
804 for (cur_src = cur_src->next; cur_src; cur_src = cur_src->next)
806 cur_dest = cur_dest->next = (struct list_entry *)zalloc(sizeof(*cur_dest));
807 if (cur_dest == NULL)
811 assert(list_is_valid(src));
812 assert(list_is_valid(dest));
814 return JB_ERR_MEMORY;
818 cur_dest->str = strdup(cur_src->str);
819 if (cur_dest->str == NULL)
823 assert(list_is_valid(src));
824 assert(list_is_valid(dest));
826 return JB_ERR_MEMORY;
829 /* else { cur_dest->str = NULL; } - implied by zalloc */
832 dest->last = cur_dest;
835 assert(list_is_valid(src));
836 assert(list_is_valid(dest));
842 /*********************************************************************
844 * Function : list_append_list_unique
846 * Description : Append a string list to another list.
847 * Duplicate items are not added.
850 * 1 : dest = pointer to destination list for merge.
851 * 2 : src = pointer to source for merge.
853 * Returns : JB_ERR_OK on success
854 * JB_ERR_MEMORY on out-of-memory error.
855 * On error, some (but not all) of src might have
856 * been copied into dest.
858 *********************************************************************/
859 jb_err list_append_list_unique(struct list *dest, const struct list *src)
861 struct list_entry * cur;
865 assert(list_is_valid(src));
866 assert(list_is_valid(dest));
868 for (cur = src->first; cur; cur = cur->next)
872 if (enlist_unique(dest, cur->str, 0))
874 assert(list_is_valid(src));
875 assert(list_is_valid(dest));
877 return JB_ERR_MEMORY;
882 assert(list_is_valid(src));
883 assert(list_is_valid(dest));
889 /*********************************************************************
891 * Function : list_is_empty
893 * Description : Test whether a list is empty. Does not change the list.
896 * 1 : the_list = pointer to list to test.
898 * Returns : Nonzero if the list contains no entries.
900 *********************************************************************/
901 int list_is_empty(const struct list *the_list)
904 assert(list_is_valid(the_list));
906 return (the_list->first == NULL);
910 /*********************************************************************
912 * Function : list_contains_item
914 * Description : Tests whether a list item is already set.
915 * Does not change the list.
918 * 1 : the_list = list to search in
919 * 2 : str = string to search for
921 * Returns : TRUE if the item was found,
924 *********************************************************************/
925 int list_contains_item(const struct list *the_list, const char *str)
927 struct list_entry *entry;
930 assert(list_is_valid(the_list));
933 for (entry = the_list->first; entry != NULL; entry = entry->next)
935 if (entry->str == NULL)
938 * NULL pointers are allowed in some lists.
939 * For example for csp->headers in case a
940 * header was removed.
945 if (0 == strcmp(str, entry->str))
956 /*********************************************************************
960 * Description : Create a new, empty map.
964 * Returns : A new, empty map, or NULL if out of memory.
966 *********************************************************************/
967 struct map *new_map(void)
969 return (struct map *) zalloc(sizeof(struct map));
973 /*********************************************************************
975 * Function : free_map
977 * Description : Free the memory occupied by a map and its
981 * 1 : the_map = map to be freed. May be NULL.
985 *********************************************************************/
986 void free_map(struct map *the_map)
988 struct map_entry *cur_entry;
989 struct map_entry *next_entry;
996 for (cur_entry = the_map->first; cur_entry != NULL; cur_entry = next_entry)
998 freez(cur_entry->name);
999 freez(cur_entry->value);
1001 next_entry = cur_entry->next;
1005 the_map->first = the_map->last = NULL;
1011 /*********************************************************************
1015 * Description : Add a mapping from given name to given value to a
1018 * Note: Since all strings will be free()d in free_map()
1019 * later, set the copy flags for constants or
1020 * strings that will be independantly free()d.
1022 * Note2: This function allows NULL parameters - it
1023 * returns JB_ERR_MEMORY in that case.
1025 * Note3: If this function returns JB_ERR_MEMORY,
1026 * it will free(name) unless you specify
1027 * name_needs_copying, and similarly it will
1028 * free(value) unless you specify
1029 * value_needs_copying.
1031 * Due to Note2 and Note3 above, the following code
1032 * is legal, and will never crash or leak memory even
1033 * if the system runs out of memory:
1035 * err = map(mymap, "xyz", 1, html_encode(somestring), 0);
1037 * err will be set to JB_ERR_MEMORY if either call runs
1038 * out-of-memory. Without these features, you would
1039 * need to check the return value of html_encode in the
1040 * above example for NULL, which (at least) doubles the
1041 * amount of error-checking code needed.
1044 * 1 : the_map = map to add to
1045 * 2 : name = name to add
1046 * 3 : name_needs_copying = flag set if a copy of name should be used
1047 * 4 : value = value to add
1048 * 5 : value_needs_copying = flag set if a copy of value should be used
1050 * Returns : JB_ERR_OK on success
1051 * JB_ERR_MEMORY on out-of-memory error.
1053 *********************************************************************/
1054 jb_err map(struct map *the_map,
1055 const char *name, int name_needs_copying,
1056 const char *value, int value_needs_copying)
1058 struct map_entry *new_entry;
1062 if ( (NULL == value)
1064 || (NULL == (new_entry = zalloc(sizeof(*new_entry)))) )
1066 if ((name != NULL) && (!name_needs_copying))
1070 if ((value != NULL) && (!value_needs_copying))
1072 free((char *)value);
1074 return JB_ERR_MEMORY;
1077 if (name_needs_copying)
1079 if (NULL == (name = strdup(name)))
1082 if (!value_needs_copying)
1084 free((char *)value);
1086 return JB_ERR_MEMORY;
1090 if (value_needs_copying)
1092 if (NULL == (value = strdup(value)))
1096 return JB_ERR_MEMORY;
1100 new_entry->name = name;
1101 new_entry->value = value;
1102 /* new_entry->next = NULL; - implied by zalloc */
1106 the_map->last->next = new_entry;
1107 the_map->last = new_entry;
1111 the_map->first = new_entry;
1112 the_map->last = new_entry;
1119 /*********************************************************************
1123 * Description : Remove all map_entry structs with a given name from
1127 * 1 : the_map = map to look in
1128 * 2 : name = name to unmap
1130 * Returns : JB_ERR_OK
1132 *********************************************************************/
1133 jb_err unmap(struct map *the_map, const char *name)
1135 struct map_entry *cur_entry, *last_entry;
1140 last_entry = the_map->first;
1142 for (cur_entry = the_map->first; cur_entry != NULL; cur_entry = cur_entry->next)
1144 if (!strcmp(name, cur_entry->name))
1147 * Update the incoming pointer
1149 if (cur_entry == the_map->first)
1151 the_map->first = cur_entry->next;
1155 last_entry->next = cur_entry->next;
1159 * Update the map's last pointer
1161 if (cur_entry == the_map->last)
1163 the_map->last = last_entry;
1167 * Free the map_entry
1169 freez(cur_entry->name);
1170 freez(cur_entry->value);
1173 cur_entry = last_entry;
1177 last_entry = cur_entry;
1184 /*********************************************************************
1188 * Description : Look up an item with a given name in a map, and
1192 * 1 : the_map = map to look in
1193 * 2 : name = name parameter to look for
1195 * Returns : the value if found, else the empty string.
1196 * Return value is alloced as part of the map, so
1197 * it is freed when the map is destroyed. Caller
1198 * must not free or modify it.
1200 *********************************************************************/
1201 const char *lookup(const struct map *the_map, const char *name)
1203 const struct map_entry *cur_entry;
1208 for (cur_entry = the_map->first; cur_entry != NULL; cur_entry = cur_entry->next)
1210 if (!strcmp(name, cur_entry->name))
1212 return cur_entry->value;