1 /*************************************************************************
2  *
3  *N  Module LINKLIST.C
4  *
5  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
6  *
7  *   Purpose:
8  *P
9  *     This module contains functions that make up a singly linked list
10  *     data structure.  It is generic in the sense that it can hold any
11  *     type of data, including user-defined types and structures.  That
12  *     is why you must treat the data element as a void pointer and pass
13  *     in its size when inserting into the list.  These routines are
14  *     assured of working with "non-pointer" types of data elements.
15  *     If you try storing other lists, or structures with pointers hanging
16  *     off of them, the results will become unpredictable.
17  *E
18  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
19  *
20  *   Parameters:
21  *A
22  *    N/A
23  *E
24  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
25  *
26  *   History:
27  *H
28  *    Barry Michaels   Feb. 1990                      DOS Turbo C
29  *E
30  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
31  *
32  *   External Variables:
33  *X
34  *    None
35  *E
36  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
37  *
38  *   Functions Called:
39  *F
40  *    linked_list_type ll_init();
41  *    int ll_empty( linked_list_type list );
42  *    position_type ll_first( linked_list_type list );
43  *    position_type ll_last( linked_list_type list );
44  *    position_type ll_next( position_type position );
45  *    position_type ll_previous( position_type position, linked_list_type
46  *                  list );
47  *    int ll_end( position_type position );
48  *    void ll_element( position_type position, void *element );
49  *    void ll_insert( void *element, unsigned size, position_type position );
50  *    void ll_delete( position_type position );
51  *    void ll_reset( linked_list_type list );
52  *    position_type ll_locate( void *element, linked_list_type list );
53  *    void ll_replace( void *element, position_type position );
54  *E
55  *************************************************************************/
56 #ifdef __MSDOS__
57 #include <alloc.h>
58 #include <mem.h>
59 #else
60 #ifdef __APPLE__
61 #include <sys/types.h>
62 #include <sys/malloc.h>
63 #else
64 #if !defined(__OpenBSD__) && !defined( __FreeBSD__)
65 #include <malloc.h>
66 #include <string.h>
67 #endif
68 #endif
69 #endif
70 
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <ossim/vpfutil/linklist.h>
74 #include <string.h>
75 
76 #ifndef __MSDOS__
77 #define farmalloc malloc
78 #define farfree free
79 #define movmem(a,b,c) memmove(b,a,c)
80 #endif
81 
82 /*************************************************************************
83  *
84  *N  ll_init
85  *
86  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
87  *
88  *   Purpose:
89  *P
90  *     This function allocates and initializes a new linked list structure.
91  *E
92  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
93  *
94  *   Parameters:
95  *A
96  *    ll_init <output> == (linked_list_type) initialized head of the list.
97  *E
98  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
99  *
100  *   History:
101  *H
102  *    Barry Michaels   Feb. 1990                      DOS Turbo C
103  *E
104  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
105  *
106  *   External Variables:
107  *X
108  *    None
109  *E
110  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
111  *
112  *   Functions Called:
113  *F
114  *    None
115  *E
116  *************************************************************************/
117 linked_list_type ll_init()
118 {
119    linked_list_type list;
120 
121    if ((list = (linked_list_type) farmalloc( sizeof(cell_type) ))==NULL) {
122       printf("Out of memory in ll_init()\n");
123       exit(1);
124    }
125    list->element = NULL;
126    list->element_size = 0;
127    list->next = NULL;
128    return list;
129 }
130 
131 
132 /*************************************************************************
133  *
134  *N  ll_empty
135  *
136  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
137  *
138  *   Purpose:
139  *P
140  *     This function TRUE if the list is empty and FALSE if it is not.
141  *E
142  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
143  *
144  *   Parameters:
145  *A
146  *    list      <input> == (linked_list_type) linked list being checked.
147  *    ll_empty <output> == (int) boolean function result.
148  *E
149  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
150  *
151  *   History:
152  *H
153  *    Barry Michaels   Feb. 1990                      DOS Turbo C
154  *E
155  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
156  *
157  *   External Variables:
158  *X
159  *    None
160  *E
161  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
162  *
163  *   Functions Called:
164  *F
165  *    None
166  *E
167  *************************************************************************/
168 int ll_empty( linked_list_type list )
169 {
170    if (list == NULL) return TRUE;
171    if (list->next == NULL)
172       return TRUE;
173    else
174       return FALSE;
175 }
176 
177 
178 /*************************************************************************
179  *
180  *N  ll_first
181  *
182  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
183  *
184  *   Purpose:
185  *P
186  *     This function returns the head of the list.
187  *E
188  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
189  *
190  *   Parameters:
191  *A
192  *    list      <input> == (linked_list_type) linked list.
193  *    ll_first <output> == (position_type) head of the list.
194  *E
195  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
196  *
197  *   History:
198  *H
199  *    Barry Michaels   Feb. 1990                      DOS Turbo C
200  *E
201  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
202  *
203  *   External Variables:
204  *X
205  *    None
206  *E
207  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
208  *
209  *   Functions Called:
210  *F
211  *    None
212  *E
213  *************************************************************************/
214 position_type ll_first( linked_list_type list )
215 {
216    return ((position_type) list);
217 }
218 
219 
220 /*************************************************************************
221  *
222  *N  ll_last
223  *
224  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
225  *
226  *   Purpose:
227  *P
228  *     This function returns *THE* last position in the list, which is
229  *     not useable.  Use ll_previous to get to the las USEABLE link in
230  *     the list.
231  *E
232  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
233  *
234  *   Parameters:
235  *A
236  *    list     <input> == (linked_list_type) linked list.
237  *    ll_last <output> == (position_type) tail of the list.
238  *E
239  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
240  *
241  *   History:
242  *H
243  *    Barry Michaels   Feb. 1990                      DOS Turbo C
244  *E
245  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
246  *
247  *   External Variables:
248  *X
249  *    None
250  *E
251  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
252  *
253  *   Functions Called:
254  *F
255  *    None
256  *E
257  *************************************************************************/
258 position_type ll_last( linked_list_type list )
259 {
260    position_type p;
261 
262    p = (position_type) list;
263    while (p->next != NULL)
264       p = p->next;
265    return p;
266 }
267 
268 
269 /*************************************************************************
270  *
271  *N  ll_next
272  *
273  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
274  *
275  *   Purpose:
276  *P
277  *     This function returns the next position in the list.
278  *E
279  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
280  *
281  *   Parameters:
282  *A
283  *    position <input> == (position_type) current position in the list.
284  *    ll_next <output> == (position_type) next position in the list.
285  *E
286  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
287  *
288  *   History:
289  *H
290  *    Barry Michaels   Feb. 1990                      DOS Turbo C
291  *E
292  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
293  *
294  *   External Variables:
295  *X
296  *    None
297  *E
298  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
299  *
300  *   Functions Called:
301  *F
302  *    None
303  *E
304  *************************************************************************/
305 position_type ll_next( position_type position )
306 {
307    return(position->next);
308 }
309 
310 
311 /*************************************************************************
312  *
313  *N  ll_previous
314  *
315  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
316  *
317  *   Purpose:
318  *P
319  *     This function returns the previous position in the list.  Note:
320  *     This is a singly linked list -> no backward pointer -> this
321  *     operation is relatively inefficient.
322  *E
323  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
324  *
325  *   Parameters:
326  *A
327  *    position     <input> == (position_type) current position.
328  *    list         <input> == (linked_list_type) linked list.
329  *    ll_previous <output> == (position_type) previous position in the list.
330  *E
331  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
332  *
333  *   History:
334  *H
335  *    Barry Michaels   Feb. 1990                      DOS Turbo C
336  *E
337  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
338  *
339  *   External Variables:
340  *X
341  *    None
342  *E
343  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
344  *
345  *   Functions Called:
346  *F
347  *    None
348  *E
349  *************************************************************************/
350 position_type ll_previous( position_type    position,
351 			   linked_list_type list )
352 {
353    position_type p;
354 
355    if (position==list) return(position);
356    p = list;
357    while (p->next != position)
358       p = p->next;
359    return(p);
360 }
361 
362 
363 /*************************************************************************
364  *
365  *N  ll_end
366  *
367  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
368  *
369  *   Purpose:
370  *P
371  *     This function determines if the given position is at the end of the
372  *     list.
373  *E
374  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
375  *
376  *   Parameters:
377  *A
378  *    position <input> == (position_type) current position in the list.
379  *    ll_end  <output> == (int) TRUE  -- if position is the end of the list.
380  *                              FALSE -- if not.
381  *E
382  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
383  *
384  *   History:
385  *H
386  *    Barry Michaels   Feb. 1990                      DOS Turbo C
387  *E
388  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
389  *
390  *   External Variables:
391  *X
392  *    None
393  *E
394  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
395  *
396  *   Functions Called:
397  *F
398  *    None
399  *E
400  *************************************************************************/
401 int ll_end( position_type position )
402 {
403    if (position == NULL)
404       return(TRUE);
405    else {
406       if (position->next == NULL)
407 	 return(TRUE);
408       else
409 	 return(FALSE);
410    }
411 }
412 
413 
414 /*************************************************************************
415  *
416  *N  ll_element
417  *
418  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
419  *
420  *   Purpose:
421  *P
422  *     This function copies the element at position in the list into the
423  *     contents of element.
424  *E
425  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
426  *
427  *   Parameters:
428  *A
429  *    position <input> == (position_type) position in the list.
430  *    element <output> == (void *) pointer to the element data.
431  *E
432  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
433  *
434  *   History:
435  *H
436  *    Barry Michaels   Feb. 1990                      DOS Turbo C
437  *E
438  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
439  *
440  *   External Variables:
441  *X
442  *    None
443  *E
444  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
445  *
446  *   Functions Called:
447  *F
448  *    None
449  *E
450  *************************************************************************/
451 void ll_element( position_type position,
452 		 void         *element )
453 {
454    movmem(position->next->element,element,position->next->element_size);
455 }
456 
457 /*************************************************************************
458  *
459  *N  ll_insert
460  *
461  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
462  *
463  *   Purpose:
464  *P
465  *     This function inserts a new cell into the list at position that will
466  *     contain the data pointed to by element.
467  *E
468  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
469  *
470  *   Parameters:
471  *A
472  *    element  <input> == (void *) pointer to the data element to insert.
473  *    size     <input> == (unsigned) size of the data element.
474  *    position <input> == (position_type) position to insert the new cell.
475  *E
476  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
477  *
478  *   History:
479  *H
480  *    Barry Michaels   Feb. 1990                      DOS Turbo C
481  *E
482  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
483  *
484  *   External Variables:
485  *X
486  *    None
487  *E
488  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
489  *
490  *   Functions Called:
491  *F
492  *    None
493  *E
494  *************************************************************************/
495 void ll_insert( void          *element,
496 		unsigned      size,
497 		position_type position )
498 {
499    position_type temp;
500 
501    if ((temp = (position_type) farmalloc( sizeof(cell_type) )) == NULL) {
502       printf("out of memory\n");
503       abort();
504    }
505    temp->next = position->next;
506    position->next = temp;
507    temp->element_size = size;
508    if ((temp->element = farmalloc( size ))==NULL) {
509       printf("out of memory\n");
510       abort();
511    }
512    movmem(element,temp->element,size);
513 
514 }
515 
516 
517 /*************************************************************************
518  *
519  *N  ll_delete
520  *
521  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
522  *
523  *   Purpose:
524  *P
525  *     This function deletes and disposes of a cell from the linked list.
526  *E
527  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
528  *
529  *   Parameters:
530  *A
531  *    position <input> == (position_type) position in the list to delete.
532  *E
533  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
534  *
535  *   History:
536  *H
537  *    Barry Michaels   Feb. 1990                      DOS Turbo C
538  *E
539  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
540  *
541  *   External Variables:
542  *X
543  *    None
544  *E
545  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
546  *
547  *   Functions Called:
548  *F
549  *    None
550  *E
551  *************************************************************************/
552 void ll_delete( position_type position )
553 {
554    position_type    p;
555 
556    if (position != NULL) {  /* Cut the element out of the chain */
557       p = position->next;
558       position->next = p->next;
559       farfree( p->element );
560       farfree( p );
561    }
562 }
563 
564 
565 
566 
567 /*************************************************************************
568  *
569  *N  ll_reset
570  *
571  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
572  *
573  *   Purpose:
574  *P
575  *     This function empties out a linked list.
576  *E
577  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
578  *
579  *   Parameters:
580  *A
581  *    list <inout> == (linked_list_type) linked list to be emptied.
582  *E
583  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
584  *
585  *   History:
586  *H
587  *    Barry Michaels   Feb. 1990                      DOS Turbo C
588  *E
589  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
590  *
591  *   External Variables:
592  *X
593  *    None
594  *E
595  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
596  *
597  *   Functions Called:
598  *F
599  *    void ll_delete( position_type position );
600  *    int ll_empty( linked_list_type list );
601  *E
602  *************************************************************************/
603 void ll_reset( linked_list_type list )
604 {
605    while (! ll_empty(list))
606       ll_delete(ll_first(list));
607    farfree(list);
608    list = NULL;
609 }
610 
611 
612 
613 /*************************************************************************
614  *
615  *N  ll_locate
616  *
617  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
618  *
619  *   Purpose:
620  *P
621  *     This function locates a position in the list by comparing data.
622  *E
623  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
624  *
625  *   Parameters:
626  *A
627  *    element <input> == (void *) pointer to the data element to locate.
628  *    list    <input> == (linked_list_type) linked list.
629  *E
630  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
631  *
632  *   History:
633  *H
634  *    Barry Michaels   Feb. 1990                      DOS Turbo C
635  *E
636  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
637  *
638  *   External Variables:
639  *X
640  *    None
641  *E
642  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
643  *
644  *   Functions Called:
645  *F
646  *    None
647  *E
648  *************************************************************************/
649 position_type ll_locate( void             *element,
650 			 linked_list_type list )
651 {
652    position_type p;
653 
654    p = list;
655    while (p->next != NULL) {
656       if ( memcmp(p->next->element,element,p->next->element_size) == 0 )
657 	 return p;
658       else
659 	 p = p->next;
660    }
661    return NULL;
662 }
663 
664 
665 /*************************************************************************
666  *
667  *N  ll_replace
668  *
669  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
670  *
671  *   Purpose:
672  *P
673  *     This function replaces an element in the linked list at the given
674  *     position.  WARNING:  The new data element must be the same size as
675  *     the previous data element or you will get some rather INTERESTING
676  *     results.
677  *E
678  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
679  *
680  *   Parameters:
681  *A
682  *    element  <input> == (void *) data element to replace existing data.
683  *    position <input> == (position_type) position in the list to replace
684  *                        the data.
685  *E
686  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
687  *
688  *   History:
689  *H
690  *    Barry Michaels   Feb. 1990                      DOS Turbo C
691  *E
692  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
693  *
694  *   External Variables:
695  *X
696  *    None
697  *E
698  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
699  *
700  *   Functions Called:
701  *F
702  *    None
703  *E
704  *************************************************************************/
705 void ll_replace( void          *element,
706 		 position_type position )
707 {
708    movmem(element,position->next->element,position->next->element_size);
709 }
710 
711 
712 
713