* New version 2.21
[alpine.git] / pith / list.c
blobd58e6d7c64432dbff88c71b9b3f1dd13bcb56a84
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: list.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2017 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
20 list.c
21 ====*/
24 #include "../pith/headers.h"
25 #include "../pith/list.h"
26 #include "../pith/string.h"
30 * Internal prototypes
35 * parse_list - takes a comma delimited list of "count" elements and
36 * returns an array of pointers to each element neatly
37 * malloc'd in its own array. Any errors are returned
38 * in the string pointed to by "error"
40 * If remove_surrounding_double_quotes is set, then double quotes around
41 * each element of the list are removed. We can't do this for all list
42 * variables. For example, incoming folders look like
43 * nickname foldername
44 * in the config file. Each of those may be quoted separately.
46 * NOTE: only recognizes escaped quotes
48 char **
49 parse_list(char *list, int count, int flags, char **error)
51 char **lvalue, *p2, *p3, *p4;
52 int was_quoted = 0;
53 int remove_surrounding_double_quotes;
54 int commas_may_be_escaped;
56 remove_surrounding_double_quotes = (flags & PL_REMSURRQUOT);
57 commas_may_be_escaped = (flags & PL_COMMAQUOTE);
59 lvalue = (char **) fs_get((count+1) * sizeof(char *));
60 count = 0;
61 while(*list){ /* pick elements from list */
62 p2 = list; /* find end of element */
63 while(1){
64 if(*p2 == '"') /* ignore ',' if quoted */
65 was_quoted = (was_quoted) ? 0 : 1 ;
67 if(*p2 == '\\' && *(p2+1) == '"')
68 p2++; /* preserve escaped quotes, too */
70 if((*p2 == ',' && !was_quoted) || *p2 == '\0')
71 break;
73 if(commas_may_be_escaped && *p2 == '\\' && *(p2+1) == ',')
74 p2++;
76 p2++;
79 if(was_quoted){ /* unbalanced quotes! */
80 if(error)
81 *error = "Unbalanced quotes";
83 break;
87 * if element found, eliminate trailing
88 * white space and tie into variable list
90 if(p2 != list){
91 for(p3 = p2 - 1; isspace((unsigned char) *p3) && list < p3; p3--)
94 p4 = fs_get(((p3 - list) + 2) * sizeof(char));
95 lvalue[count] = p4;
96 while(list <= p3)
97 *p4++ = *list++;
99 *p4 = '\0';
101 if(remove_surrounding_double_quotes)
102 removing_double_quotes(lvalue[count]);
104 count++;
107 if(*(list = p2) != '\0'){ /* move to beginning of next val */
108 while(*list == ',' || isspace((unsigned char)*list))
109 list++;
113 lvalue[count] = NULL; /* tie off pointer list */
114 return(lvalue);
119 * Free array of string pointers and associated strings
121 * Args: list -- array of char *'s
123 void
124 free_list_array(char ***list)
126 char **p;
128 if(list && *list){
129 for(p = *list; *p; p++)
130 fs_give((void **) p);
132 fs_give((void **) list);
138 * Copy array of string pointers and associated strings
140 * Args: list -- array of char *'s
142 * Returns: Allocated array of string pointers and allocated copies of strings.
143 * Caller should free the list array when done.
145 char **
146 copy_list_array(char **list)
148 int i, cnt = 0;
149 char **p, **ret_list = NULL;
151 if(list){
152 while(list[cnt++])
155 p = ret_list = (char **)fs_get((cnt+1) * sizeof(char *));
156 memset((void *) ret_list, 0, (cnt+1) * sizeof(char *));
158 for(i=0; list[i]; i++, p++)
159 *p = cpystr(list[i]);
161 *p = NULL;
165 return(ret_list);
170 equal_list_arrays(char **list1, char **list2)
172 int ret = 0;
174 if(list1 && list2){
175 while(*list1){
176 if(!*list2 || strcmp(*list1, *list2) != 0)
177 break;
179 list1++;
180 list2++;
183 if(*list1 == NULL && *list2 == NULL)
184 ret++;
187 return(ret);