1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California.  All rights reserved.
4 Authors: 1987 Wayne A. Christopher
5          1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Wordlist manipulation stuff.
10  */
11 
12 #include "spice.h"
13 #include "cpstd.h"
14 #include "suffix.h"
15 
16 #ifdef __STDC__
17 static int wlcomp(char**,char**);
18 #else
19 static int wlcomp();
20 #endif
21 
22 /***************************************************************************/
23 /* Determine the length of a word list. */
24 
25 int
wl_length(wlist)26 wl_length(wlist)
27 
28 wordlist *wlist;
29 {
30     register int i = 0;
31     register wordlist *wl;
32 
33     for (wl = wlist; wl; wl = wl->wl_next)
34         i++;
35     return (i);
36 }
37 
38 
39 /***************************************************************************/
40 /* Free the storage used by a word list. */
41 
42 void
wl_free(wlist)43 wl_free(wlist)
44 
45 wordlist *wlist;
46 {
47     wordlist *wl, *nw;
48 
49     for (wl = wlist; wl; wl = nw) {
50         nw = wl->wl_next;
51         tfree(wl->wl_word);
52         tfree(wl);
53     }
54     return;
55 }
56 
57 
58 /***************************************************************************/
59 /* Copy a wordlist and the words. */
60 
61 wordlist *
wl_copy(wlist)62 wl_copy(wlist)
63 
64 wordlist *wlist;
65 {
66     register wordlist *wl, *nwl = NULL, *w;
67 
68     for (wl = wlist; wl; wl = wl->wl_next) {
69         if (nwl == NULL) {
70             nwl = w = alloc(struct wordlist);
71         }
72         else {
73             w->wl_next = alloc(struct wordlist);
74             w->wl_next->wl_prev = w;
75             w = w->wl_next;
76         }
77         w->wl_word = copy(wl->wl_word);
78     }
79     return (nwl);
80 }
81 
82 
83 /***************************************************************************/
84 /* Substitute a wordlist for one element of a wordlist, and return a pointer
85  * to the last element of the inserted list.
86  */
87 
88 wordlist *
wl_splice(elt,list)89 wl_splice(elt, list)
90 
91 wordlist *elt, *list;
92 {
93     if (list)
94         list->wl_prev = elt->wl_prev;
95     if (elt->wl_prev)
96         elt->wl_prev->wl_next = list;
97     if (list) {
98         while (list->wl_next)
99             list = list->wl_next;
100         list->wl_next = elt->wl_next;
101     }
102     if (elt->wl_next)
103         elt->wl_next->wl_prev = list;
104     tfree(elt->wl_word);
105     tfree(elt);
106     return (list);
107 }
108 
109 
110 /***************************************************************************/
111 /* Print a word list. (No \n at the end...) */
112 
113 void
wl_print(wlist,fp)114 wl_print(wlist, fp)
115 
116 wordlist *wlist;
117 FILE *fp;
118 {
119     wordlist *wl;
120 
121     for (wl = wlist; wl; wl = wl->wl_next) {
122         cp_printword(wl->wl_word, fp);
123         if (wl->wl_next)
124             (void) putc(' ', fp);
125     }
126     return;
127 }
128 
129 
130 /***************************************************************************/
131 /* Turn an array of char *'s into a wordlist. */
132 
133 wordlist *
wl_build(v)134 wl_build(v)
135 
136 char *v[];
137 {
138     wordlist *wlist, *wl = NULL, *cwl;
139 
140     while (*v) {
141         cwl = alloc(struct wordlist);
142         cwl->wl_prev = wl;
143         if (wl)
144             wl->wl_next = cwl;
145         else
146             wlist = cwl;
147         cwl->wl_word = copy(*v);
148         wl = cwl;
149         v++;
150     }
151     return (wlist);
152 }
153 
154 
155 /***************************************************************************/
156 /* Turn a wordlist into an array of char *'s */
157 
158 char **
wl_mkvec(wl)159 wl_mkvec(wl)
160 
161 wordlist *wl;
162 {
163     int len, i;
164     char **v;
165 
166     len = wl_length(wl);
167     v = (char **) tmalloc((len + 1) * sizeof (char **));
168     for (i = 0; i < len; i++) {
169         v[i] = copy(wl->wl_word);
170         wl = wl->wl_next;
171     }
172     v[i] = NULL;
173     return (v);
174 }
175 
176 
177 /***************************************************************************/
178 /* Link two wordlists together. */
179 
180 wordlist *
wl_append(wlist,nwl)181 wl_append(wlist, nwl)
182 
183 wordlist *wlist, *nwl;
184 {
185     wordlist *wl;
186     if (wlist == NULL)
187         return (nwl);
188     if (nwl == NULL)
189         return (wlist);
190     for (wl = wlist; wl->wl_next; wl = wl->wl_next);
191     wl->wl_next = nwl;
192     nwl->wl_prev = wl;
193     return (wlist);
194 }
195 
196 
197 /***************************************************************************/
198 /* Reverse a word list. */
199 
200 wordlist *
wl_reverse(wl)201 wl_reverse(wl)
202 
203 wordlist *wl;
204 {
205     wordlist *w, *t;
206 
207     for (w = wl; ; w = t) {
208          t = w->wl_next;
209          w->wl_next = w->wl_prev;
210          w->wl_prev = t;
211          if (t == NULL)
212             break;
213     }
214     return (w);
215 }
216 
217 
218 /***************************************************************************/
219 /* Convert a wordlist into a string. */
220 
221 char *
wl_flatten(wl)222 wl_flatten(wl)
223 wordlist *wl;
224 {
225     char *buf;
226     wordlist *tw;
227     int i = 0;
228 
229     for (tw = wl; tw; tw = tw->wl_next)
230         i += strlen(tw->wl_word) + 1;
231     buf = tmalloc(i + 1);
232 
233     while (wl != NULL) {
234         (void) strcat(buf, wl->wl_word);
235         if (wl->wl_next)
236             (void) strcat(buf, " ");
237         wl = wl->wl_next;
238     }
239     return (buf);
240 }
241 
242 
243 /***************************************************************************/
244 /* Return the nth element of a wordlist, or the last one if n is too big.
245  * Numbering starts at 0...
246  */
247 
248 wordlist *
wl_nthelem(i,wl)249 wl_nthelem(i, wl)
250 
251 wordlist *wl;
252 register int i;
253 {
254     register wordlist *ww = wl;
255 
256     while ((i-- > 0) && ww->wl_next)
257         ww = ww->wl_next;
258     return (ww);
259 }
260 
261 
262 /***************************************************************************/
263 /* Sort a wordlist */
264 
265 void
wl_sort(wl)266 wl_sort(wl)
267 
268 wordlist *wl;
269 {
270     register int i = 0;
271     register wordlist *ww = wl;
272     char **stuff;
273 
274     for (i = 0; ww; i++)
275         ww = ww->wl_next;
276     if (i < 2)
277         return;
278     stuff = (char **) tmalloc(i * sizeof (char *));
279     for (i = 0, ww = wl; ww; i++, ww = ww->wl_next)
280         stuff[i] = ww->wl_word;
281     qsort((char *) stuff, i, sizeof (char *),
282 #ifdef __STDC__
283         (int(*)(const void*,const void*))wlcomp);
284 #else
285         wlcomp);
286 #endif
287     for (i = 0, ww = wl; ww; i++, ww = ww->wl_next)
288         ww->wl_word = stuff[i];
289     tfree(stuff);
290     return;
291 }
292 
293 
294 static int
wlcomp(s,t)295 wlcomp(s, t)
296 
297 char **s, **t;
298 {
299     return (strcmp(*s, *t));
300 }
301 
302 
303 /***************************************************************************/
304 /* Return a range of wordlist elements... */
305 
306 wordlist *
wl_range(wl,low,up)307 wl_range(wl, low, up)
308 
309 wordlist *wl;
310 int low, up;
311 {
312     int i;
313     wordlist *tt;
314     bool rev = false;
315 
316     if (low > up) {
317         i = up;
318         up = low;
319         low = i;
320         rev = true;
321     }
322     up -= low;
323     while (wl && (low > 0)) {
324         tt = wl->wl_next;
325         tfree(wl->wl_word);
326         tfree(wl);
327         wl = tt;
328         if (wl)
329             wl->wl_prev = NULL;
330         low--;
331     }
332     tt = wl;
333     while (tt && (up > 0)) {
334         tt = tt->wl_next;
335         up--;
336     }
337     if (tt && tt->wl_next) {
338         wl_free(tt->wl_next);
339         tt->wl_next = NULL;
340     }
341     if (rev)
342         wl = wl_reverse(wl);
343     return (wl);
344 }
345 
346