dvitomp fix from Akira
[mplib] / src / texk / kpathsea / str-list.c
1 /* str-list.c: define routines for string lists.
2
3     Copyright 1993, 2008 Karl Berry.
4     Copyright 2001, 2005 Olaf Weber.
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public License
17    along with this library; if not, see <http://www.gnu.org/licenses/>.  */
18
19 #include <kpathsea/config.h>
20
21 #include <kpathsea/str-list.h>
22
23
24 /* See the .h file for comments.  */
25
26
27 str_list_type
28 str_list_init P1H(void)
29 {
30   str_list_type ret;
31   
32   STR_LIST_LENGTH (ret) = 0;
33   STR_LIST (ret) = NULL;
34   
35   return ret;
36 }
37
38
39 void
40 str_list_add P2C(str_list_type *, l,  string, s)
41 {
42   STR_LIST_LENGTH (*l)++;
43   XRETALLOC (STR_LIST (*l), STR_LIST_LENGTH (*l), string);
44   STR_LIST_LAST_ELT (*l) = s;
45 }
46
47
48 /* May as well save some reallocations and do everything in a chunk
49    instead of calling str_list_add on each element.  */
50    
51 void
52 str_list_concat P2C(str_list_type *, target,  str_list_type, more)
53 {
54   unsigned e;
55   unsigned prev_len = STR_LIST_LENGTH (*target);
56
57   STR_LIST_LENGTH (*target) += STR_LIST_LENGTH (more);
58   XRETALLOC (STR_LIST (*target), STR_LIST_LENGTH (*target), string);
59   
60   for (e = 0; e < STR_LIST_LENGTH (more); e++)
61     STR_LIST_ELT (*target, prev_len + e) = STR_LIST_ELT (more, e);
62 }
63
64
65 /* Concatenate the elements of more to each element of target.  This
66    _must_ be done with the first index varying fastest. */
67 /* Note that we free the old elements of target as well. */
68
69 void
70 str_list_concat_elements P2C(str_list_type *, target,  str_list_type, more)
71 {
72     if (STR_LIST_LENGTH(more) == 0) {
73         return;
74     } else if (STR_LIST_LENGTH(*target) == 0) {
75         unsigned int i;
76         STR_LIST_LENGTH(*target) = STR_LIST_LENGTH(more);
77         STR_LIST(*target) =
78                 (string*)xmalloc(STR_LIST_LENGTH(more)*sizeof(char*));
79         for (i=0;i!=STR_LIST_LENGTH(more);++i) {
80             STR_LIST_ELT(*target,i)=xstrdup(STR_LIST_ELT(more,i));
81         }
82         return;
83     } else {
84         unsigned new_len;
85         char ** new_list;
86         unsigned int i,j;
87         new_list = (string*)xmalloc(STR_LIST_LENGTH (*target)
88                                     * STR_LIST_LENGTH (more) * sizeof(char*));
89
90         new_len = 0;
91         for (j = 0; j != STR_LIST_LENGTH(more); ++j) {
92             for (i = 0; i != STR_LIST_LENGTH(*target); ++i) {
93                 new_list[new_len] = concat(STR_LIST_ELT(*target,i),
94                                            STR_LIST_ELT(more,j));
95                 ++new_len;
96             }
97         }
98         for (i = 0; i != STR_LIST_LENGTH(*target); ++i)
99             free(STR_LIST_ELT(*target, i));
100         free(STR_LIST(*target));
101         STR_LIST_LENGTH(*target) = new_len;
102         STR_LIST(*target) = new_list;
103     }
104 }
105
106
107 /* Free the list (but not the elements within it).  */
108
109 void
110 str_list_free P1C(str_list_type *, l)
111 {
112   if (STR_LIST (*l))
113     {
114       free (STR_LIST (*l));
115       STR_LIST (*l) = NULL;
116     }
117 }
118
119
120 \f
121 /* Remove duplicate elements from L, freeing their space.  Since our
122    lists are so short, we do a maximally inefficient bubble search.  */
123
124 void
125 str_list_uniqify P1C(str_list_type *, l)
126 {
127   unsigned e;
128   str_list_type ret = str_list_init ();
129   
130   for (e = 0; e < STR_LIST_LENGTH (*l); e++) {
131     string elt1 = STR_LIST_ELT (*l, e);
132     unsigned f;
133     for (f = e + 1; f < STR_LIST_LENGTH (*l); f++) {
134       string elt2 = STR_LIST_ELT (*l, f);
135       /* I don't think our list should ever contain NULL's, but if
136          it does, let it stay and don't bother collapsing multiple
137          NULL's into one.  */
138       if (FILESTRCASEEQ (elt1, elt2)) {
139         break;
140       }
141     }
142     
143     if (f == STR_LIST_LENGTH (*l)) {
144       str_list_add (&ret, elt1); /* not found */
145     } else {
146       free (elt1);  /* duplicate, forget this one */
147     }
148   }
149   
150   /* Replace the passed list with what we constructed.  */
151   *l = ret;
152 }