1 /*+++++++++++++++++
2 linklist.c - implements some functions for linked lists
3 markus@mhoenicka.de 7-11-00
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
20
21 #include <stdio.h> /* for a definition of NULL */
22 #include <stdlib.h> /* for malloc */
23 #include <string.h>
24
25 #include "linklist.h"
26
27 /*********************************************************************
28 linked list for file descriptors
29 This is an ordered linked list. The highest fd will always be the
30 first member of the list.
31 ********************************************************************/
32
33 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34 insert_olili(): inserts a new item into an ordered linked list. The
35 list will be in descending order, so the first item
36 after the sentinel is the item with the highest
37 value
38
39 int insert_olili returns 0 if ok, 1 if error
40
41 struct olili *ptr_first pointer to sentinel
42
43 int value the value to be inserted into the list (value >= 0)
44
45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
insert_olili(Olili * ptr_first,int value)46 int insert_olili(Olili *ptr_first, int value) {
47 Olili *ptr_before; /* item before insertion point */
48 Olili *ptr_after; /* item after insertion point */
49 Olili *ptr_new_olili; /* new item */
50
51 ptr_before = ptr_first; /* start search at the beginning */
52 ptr_after = ptr_before->ptr_next;
53
54 while (ptr_after != NULL) {
55 if (ptr_after->fd <= value) { /* sort in descending order */
56 break;
57 }
58 ptr_after = ptr_after->ptr_next;
59 ptr_before = ptr_before->ptr_next;
60 }
61
62 ptr_new_olili = malloc(sizeof(Olili));
63 if (ptr_new_olili == NULL) {
64 return 1;
65 }
66 ptr_new_olili->fd = value;
67 ptr_before->ptr_next = ptr_new_olili;
68 ptr_new_olili->ptr_next = ptr_after;
69
70 return 0;
71 }
72
73 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
74 delete_olili(): deletes an item from an ordered linked list.
75
76 int delete_olili returns 0 if ok, 1 if error
77
78 Olili *ptr_first pointer to sentinel
79
80 int value the value to be inserted into the list
81
82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_olili(Olili * ptr_first,int value)83 int delete_olili(Olili *ptr_first, int value) {
84 Olili *ptr_before; /* item before deletion point */
85 Olili *ptr_curr; /* item at deletion point */
86
87 ptr_before = ptr_first; /* start search at the beginning */
88 ptr_curr = ptr_before->ptr_next;
89
90 while (ptr_curr != NULL) {
91 if (ptr_curr->fd == value) { /* got it */
92 break;
93 }
94 ptr_curr = ptr_curr->ptr_next;
95 ptr_before = ptr_before->ptr_next;
96 }
97
98 if (ptr_curr == NULL) {
99 return 1;
100 }
101
102 ptr_before->ptr_next = ptr_curr->ptr_next;
103 free(ptr_curr);
104 return 0;
105 }
106
107 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
108 max_olili(): returns the item with the highest value from an ordered
109 linked list.
110
111 int max_olili returns the maximum value, or -1 if an error occurred
112
113 Olili *ptr_first pointer to sentinel
114
115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
max_olili(Olili * ptr_first)116 int max_olili(Olili *ptr_first) {
117 if (ptr_first != NULL && ptr_first->ptr_next != NULL) {
118 return ptr_first->ptr_next->fd;
119 }
120 else if (ptr_first != NULL) {
121 return ptr_first->fd;
122 }
123 else {
124 return -1;
125 }
126 }
127
128
129 /*********************************************************************
130 linked list for allocated memory
131 This is an unsorted linked list. The first list member is a sentinel
132 which is not automatically deallocated by the lilimem functions.
133 The calling fn has to explicitly declare, initialize, and destruct
134 a lilimem struct for this purpose.
135 ********************************************************************/
136
137 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
138 insert_lilimem(): inserts a new member into the list
139
140 int insert_lilimem returns 0 if ok, or 1 if an error occurred
141 if an error occurs, the memory pointed to by ptr_mem
142 will be freed
143
144 Lilimem *ptr_first pointer to sentinel
145
146 void** ptr_mem ptr to ptr to allocated memory
147
148 char* varname ptr to string with the name of the variable used for
149 that memory location. This name is used to find the
150 correct list member if you want to delete a specific
151 entry with the delete_lilimem() function. This can in
152 fact be any unique string other than the variable name.
153 You may pass NULL here if you don't use
154 delete_lilimem(), but only delete_all_lilimem()
155
156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
insert_lilimem(Lilimem * ptr_first,void ** ptr_mem,char * varname)157 int insert_lilimem(Lilimem *ptr_first, void** ptr_mem, char* varname) {
158 Lilimem* ptr_new_item;
159
160 if (varname && strlen(varname) > 32) { /* string too long to fit into struct */
161 return 1;
162 }
163
164 ptr_new_item = malloc(sizeof(Lilimem));
165
166 if (ptr_new_item == NULL) { /* malloc failed */
167 free(*ptr_mem);
168 return 1;
169 }
170
171 if (varname) {
172 strcpy(ptr_new_item->varname, varname);
173 }
174 else {
175 (ptr_new_item->varname)[0] = '\0';
176 }
177 ptr_new_item->ptr_mem = ptr_mem;
178 ptr_new_item->ptr_next = ptr_first->ptr_next;
179 ptr_first->ptr_next = ptr_new_item;
180
181 return 0;
182 }
183
184 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
185 delete_lilimem(): deletes a member from the list by the varname
186
187 int delete_lilimem returns 0 if ok, or 1 if an error occurred
188
189 Lilimem *ptr_first pointer to sentinel
190
191 char* varname ptr to string with the name of the variable used for
192 that memory location
193
194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_lilimem(Lilimem * ptr_first,char * varname)195 int delete_lilimem(Lilimem *ptr_first, char* varname) {
196 Lilimem* ptr_curr_item;
197 Lilimem* ptr_prev_item;
198 int gotit = 0;
199
200 ptr_prev_item = ptr_first;
201 ptr_curr_item = ptr_first->ptr_next;
202
203 while (ptr_curr_item) {
204 if (ptr_curr_item->varname && strcmp(ptr_curr_item->varname, varname) == 0) {
205 gotit = 1;
206 break;
207 }
208 /* else: silently ignore if item has no varname */
209 ptr_prev_item = ptr_curr_item;
210 ptr_curr_item = ptr_curr_item->ptr_next;
211 }
212
213 if (gotit) {
214 free(*(ptr_curr_item->ptr_mem)); /* free the memory referenced by the list
215 member */
216 /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */
217 *(ptr_curr_item->ptr_mem) = NULL; /* set the memory ptr to NULL to avoid
218 problems with erroneous subsequent
219 free() calls */
220 ptr_prev_item->ptr_next = ptr_curr_item->ptr_next;
221 free(ptr_curr_item); /* free the memory allocated for the list member */
222 return 0;
223 }
224 else {
225 return 1;
226 }
227 }
228
229 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
230 delete_all_lilimem(): deletes all members from the list
231
232 int delete_all_lilimem returns 0 if ok, or 1 if an error occurred
233
234 Lilimem *ptr_first pointer to sentinel
235
236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_all_lilimem(Lilimem * ptr_first)237 int delete_all_lilimem(Lilimem *ptr_first) {
238 Lilimem* ptr_curr_item;
239 Lilimem* ptr_next_item;
240
241 ptr_curr_item = ptr_first->ptr_next;
242 ptr_first->ptr_next = NULL;
243
244 while (ptr_curr_item) {
245 ptr_next_item = ptr_curr_item->ptr_next;
246 /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */
247 free(*(ptr_curr_item->ptr_mem)); /* free the memory referenced by the list
248 member */
249 *(ptr_curr_item->ptr_mem) = NULL; /* set the memory ptr to NULL to avoid
250 problems with erroneous subsequent
251 free() calls */
252 free(ptr_curr_item); /* free the memory allocated for the list member */
253
254 ptr_curr_item = ptr_next_item;
255 }
256 return 0;
257 }
258
259 /*********************************************************************
260 linked list for decoding cgi data
261 This is an unsorted linked list. The first list member is a sentinel
262 which is not automatically deallocated by the lilimem functions.
263 The calling fn has to explicitly declare, initialize, and destruct
264 a lilimem struct for this purpose.
265 ********************************************************************/
266
267 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
268 insert_liliform(): inserts a new member into the list
269
270 int insert_liliform returns 0 if ok, or 1 if an error occurred
271 if an error occurs, the memory pointed to by ptr_mem
272 will be freed
273
274 Liliform *ptr_first pointer to sentinel
275
276 char* name ptr to string with the name of the variable used for
277 that memory location.
278
279 char* value ptr to allocated memory
280
281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
insert_liliform(Liliform * ptr_first,char * name,char * value)282 int insert_liliform(Liliform *ptr_first, char* name, char* value) {
283 Liliform* ptr_new_item;
284 char* my_value;
285
286 if (name == NULL) {
287 return 0; /* do nothing, no error */
288 }
289
290 if (strlen(name) > 32) { /* string too long to fit into struct */
291 return 1;
292 }
293
294 ptr_new_item = malloc(sizeof(Liliform));
295
296 if (!ptr_new_item) { /* malloc failed */
297 return 1;
298 }
299
300 strcpy(ptr_new_item->name, name);
301
302 if (value && strlen(value)) {
303 my_value = malloc(strlen(value)+1);
304 if (!my_value) {
305 free(ptr_new_item);
306 return 1;
307 }
308 strcpy(my_value, value);
309 ptr_new_item->value = my_value;
310 }
311 else {
312 ptr_new_item->value = NULL;
313 }
314
315 ptr_new_item->ptr_next = ptr_first->ptr_next;
316 ptr_first->ptr_next = ptr_new_item;
317
318 return 0;
319 }
320
321 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
322 append_liliform(): appends a new member into the list. The
323 implementation is not very efficient but is ok
324 for a low number of entries
325
326 int append_liliform returns 0 if ok, or 1 if an error occurred
327 if an error occurs
328
329 Liliform *ptr_first pointer to sentinel
330
331 char* name ptr to string with the name of the variable used for
332 that memory location.
333
334 char* value ptr to allocated memory
335
336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
append_liliform(Liliform * ptr_first,char * name,char * value)337 int append_liliform(Liliform *ptr_first, char* name, char* value) {
338 char* my_value;
339 Liliform* ptr_new_item;
340 Liliform* ptr_last_item;
341
342 ptr_new_item = malloc(sizeof(Liliform));
343
344 if (!ptr_new_item) { /* malloc failed */
345 return 1;
346 }
347
348 strcpy(ptr_new_item->name, name);
349
350 if (value && *value) {
351 my_value = malloc(strlen(value)+1);
352 if (!my_value) {
353 free(ptr_new_item);
354 return 1;
355 }
356 strcpy(my_value, value);
357 ptr_new_item->value = my_value;
358 }
359 else {
360 ptr_new_item->value = NULL;
361 }
362
363 ptr_new_item->ptr_next = NULL;
364
365 ptr_last_item = ptr_first;
366
367 /* this is going to be inefficient for a large number of entries */
368 while (ptr_last_item->ptr_next) {
369 ptr_last_item = ptr_last_item->ptr_next;
370 }
371 ptr_last_item->ptr_next = ptr_new_item;
372
373 return 0;
374 }
375
376 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
377 get_liliform(): retrieves a member of the list by name
378
379 Liliform* get_liliform returns a ptr to the first member
380 whose name matches as specified and whose value is
381 not NULL, otherwise it returns NULL
382
383 Liliform *ptr_first pointer to sentinel
384
385 char* name ptr to string with the name of the variable
386
387 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_liliform(Liliform * ptr_first,char * name)388 Liliform* get_liliform(Liliform* ptr_first, char* name) {
389 Liliform* ptr_curr_item;
390 Liliform* ptr_result = NULL;
391
392 ptr_curr_item = ptr_first->ptr_next;
393
394 while (ptr_curr_item) {
395 if (!strcmp(ptr_curr_item->name, name)) {
396 if (ptr_curr_item->value) {
397 ptr_result = ptr_curr_item;
398 }
399 break;
400 }
401 ptr_curr_item = ptr_curr_item->ptr_next;
402 }
403 return ptr_result;
404 }
405
406 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
407 get_nliliform(): retrieves a member of the list by partial name match
408
409 Liliform* get_nliliform returns a ptr to the first member
410 whose name matches as specified and whose value is
411 not NULL, otherwise it returns NULL
412
413 Liliform *ptr_first pointer to sentinel
414
415 char* name ptr to string with the name of the variable
416
417 size_t n the number of characters to compare, starting at name[0]
418
419 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_nliliform(Liliform * ptr_first,char * name,size_t n)420 Liliform* get_nliliform(Liliform* ptr_first, char* name, size_t n) {
421 Liliform* ptr_curr_item;
422 Liliform* ptr_result = NULL;
423
424 ptr_curr_item = ptr_first->ptr_next;
425
426 while (ptr_curr_item) {
427 if (!strncmp(ptr_curr_item->name, name, n)) {
428 if (ptr_curr_item->value) {
429 ptr_result = ptr_curr_item;
430 }
431 break;
432 }
433 ptr_curr_item = ptr_curr_item->ptr_next;
434 }
435 return ptr_result;
436 }
437
438 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
439 get_next_liliform(): retrieves next member of the list
440
441 Liliform* get_next_liliform returns a ptr to the next member or NULL
442 if we're at the end of the list. Use this fn
443 to loop over all list entries. In the first
444 iteration, pass a ptr to the sentinel. In
445 subsequent iterations, pass the ptr that the
446 previous iteration returns.
447
448
449 Liliform *ptr_first pointer to sentinel
450
451 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_next_liliform(Liliform * ptr_first)452 Liliform* get_next_liliform(Liliform* ptr_first) {
453 return ptr_first->ptr_next;
454 }
455
456 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
457 delete_all_liliform(): deletes all members from the list
458
459 int delete_all_liliform returns 0 if ok, or 1 if an error occurred
460
461 Liliform *ptr_first pointer to sentinel
462
463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_all_liliform(Liliform * ptr_first)464 int delete_all_liliform(Liliform *ptr_first) {
465 Liliform* ptr_curr_item;
466 Liliform* ptr_next_item;
467
468 ptr_curr_item = ptr_first->ptr_next;
469 ptr_first->ptr_next = NULL;
470
471 while (ptr_curr_item) {
472 ptr_next_item = ptr_curr_item->ptr_next;
473 /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */
474 free(ptr_curr_item->value); /* free the memory allocated for the value */
475 free(ptr_curr_item); /* free the memory allocated for the list member */
476
477 ptr_curr_item = ptr_next_item;
478 }
479 return 0;
480 }
481
482 /*********************************************************************
483 linked list for reading non-standard field mapping for BibTeX data
484 This is an unsorted linked list. The first list member is a sentinel
485 which is not automatically deallocated by the lilimem functions.
486 The calling fn has to explicitly declare, initialize, and destruct
487 a lilimem struct for this purpose.
488 ********************************************************************/
489
490 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
491 insert_lilibib(): inserts a new member into the list
492
493 int insert_lilibib returns 0 if ok, or 1 if an error occurred
494 if an error occurs, the memory pointed to by ptr_mem
495 will be freed
496
497 Lilibib *ptr_first pointer to sentinel
498
499 char* name ptr to string with the name of the variable used for
500 that memory location. May be NULL if retrieval by name
501 is not necessary
502
503 char* value ptr to allocated memory
504
505 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
insert_lilibib(Lilibib * ptr_first,char * name,char * value)506 int insert_lilibib(Lilibib *ptr_first, char* name, char* value) {
507 Lilibib* ptr_new_item;
508 char* my_value;
509 char* my_name;
510
511 ptr_new_item = malloc(sizeof(Lilibib));
512
513 if (!ptr_new_item) { /* malloc failed */
514 return 1;
515 }
516
517 if (name && *name) {
518 my_name = malloc(strlen(name)+1);
519 if (!my_name) {
520 free(ptr_new_item);
521 return 1;
522 }
523 strcpy(my_name, name);
524 ptr_new_item->name = my_name;
525 }
526 else {
527 ptr_new_item->name = NULL;
528 }
529
530 if (value && *value) {
531 my_value = malloc(strlen(value)+1);
532 if (!my_value) {
533 free(ptr_new_item);
534 return 1;
535 }
536 strcpy(my_value, value);
537 ptr_new_item->value = my_value;
538 }
539 else {
540 ptr_new_item->value = NULL;
541 }
542
543 ptr_new_item->ptr_next = ptr_first->ptr_next;
544 ptr_first->ptr_next = ptr_new_item;
545
546 return 0;
547 }
548
549 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
550 get_next_lilibib(): retrieves next member of the list
551
552 Lilibib* get_next_lilibib returns a ptr to the next member or NULL
553 if we're at the end of the list. Use this fn
554 to loop over all list entries. In the first
555 iteration, pass a ptr to the sentinel. In
556 subsequent iterations, pass the ptr that the
557 previous iteration returns.
558
559
560 Lilibib *ptr_first pointer to sentinel
561
562 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_next_lilibib(Lilibib * ptr_first)563 Lilibib* get_next_lilibib(Lilibib* ptr_first) {
564 return ptr_first->ptr_next;
565 }
566
567 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
568 get_lilibib(): retrieves a member of the list by name
569
570 Lilibib* get_next_lilibib returns a ptr to the list member with
571 the given name or NULL if none such exists.
572
573
574 Lilibib *ptr_first pointer to sentinel
575
576 char* name name of the list member to return
577
578 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_lilibib(Lilibib * ptr_first,char * name)579 Lilibib* get_lilibib(Lilibib* ptr_first, char* name) {
580 Lilibib* ptr_curr_item;
581 Lilibib* ptr_result = NULL;
582
583 ptr_curr_item = ptr_first->ptr_next;
584
585 while (ptr_curr_item) {
586 if (!strcmp(ptr_curr_item->name, name)) {
587 if (ptr_curr_item->value) {
588 ptr_result = ptr_curr_item;
589 }
590 break;
591 }
592 ptr_curr_item = ptr_curr_item->ptr_next;
593 }
594 return ptr_result;
595 }
596
597 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
598 delete_all_lilibib(): deletes all members from the list
599
600 int delete_all_lilibib returns 0 if ok, or 1 if an error occurred
601
602 Lilibib *ptr_first pointer to sentinel
603
604 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_all_lilibib(Lilibib * ptr_first)605 int delete_all_lilibib(Lilibib *ptr_first) {
606 Lilibib* ptr_curr_item;
607 Lilibib* ptr_next_item;
608
609 ptr_curr_item = ptr_first->ptr_next;
610 ptr_first->ptr_next = NULL;
611
612 while (ptr_curr_item) {
613 ptr_next_item = ptr_curr_item->ptr_next;
614 /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */
615 if (ptr_curr_item->name) {
616 free(ptr_curr_item->name); /* free the memory allocated for the name */
617 }
618 if (ptr_curr_item->value) {
619 free(ptr_curr_item->value); /* free the memory allocated for the value */
620 }
621 free(ptr_curr_item); /* free the memory allocated for the list member */
622
623 ptr_curr_item = ptr_next_item;
624 }
625 return 0;
626 }
627
628 /*********************************************************************
629 linked list for reading id lists
630 This is a sorted linked list. The first list member is a sentinel
631 which is not automatically deallocated by the lilimem functions.
632 The calling fn has to explicitly declare, initialize, and destruct
633 a lilid struct for this purpose.
634 The payload of a member is an id value and two ints used as booleans
635 ********************************************************************/
636
637 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
638 insert_lilid(): inserts a new member into the list
639
640 int insert_lilid returns 0 if ok, or 1 if an error occurred
641
642 Lilid *ptr_first pointer to sentinel
643
644 unsigned long long value the value to store
645
646 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
insert_lilid(Lilid * ptr_first,unsigned long long value)647 int insert_lilid(Lilid *ptr_first, unsigned long long value) {
648 Lilid* ptr_new_item; /* ptr to new list member */
649 Lilid* ptr_before; /* ptr to member before insertion point */
650 Lilid* ptr_after; /* ptr to member after insertion point */
651
652 ptr_new_item = malloc(sizeof(Lilid));
653
654 if (!ptr_new_item) { /* malloc failed */
655 return 1;
656 }
657
658 /* set requested value */
659 ptr_new_item->value = value;
660
661 /* set default values */
662 ptr_new_item->is_duplicate = 0;
663 ptr_new_item->is_existent = 0;
664
665 /* find insertion point */
666 ptr_before = ptr_first; /* start search at the beginning */
667 ptr_after = ptr_before->ptr_next;
668
669 while (ptr_after != NULL) {
670 if (ptr_after->value >= value) { /* sort in ascending order */
671 break;
672 }
673 ptr_after = ptr_after->ptr_next;
674 ptr_before = ptr_before->ptr_next;
675 }
676
677 /* insert new item into list */
678 ptr_before->ptr_next = ptr_new_item;
679 ptr_new_item->ptr_next = ptr_after;
680
681 return 0;
682 }
683
684 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
685 get_next_lilid(): retrieves next member of the list in ascending order
686
687 Lilid* get_next_lilid returns a ptr to the next member or NULL
688 if we're at the end of the list. Use this fn
689 to loop over all list entries. In the first
690 iteration, pass a ptr to the sentinel. In
691 subsequent iterations, pass the ptr that the
692 previous iteration returns.
693
694
695 struct lilid *ptr_first pointer to sentinel
696
697 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_next_lilid(Lilid * ptr_first)698 Lilid* get_next_lilid(Lilid* ptr_first) {
699 return ptr_first->ptr_next;
700 }
701
702 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
703 count_lilid(): counts all members in the list
704
705 unsigned long long count_lilid returns the number of list members
706
707 Lilid *ptr_first pointer to sentinel
708
709 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
count_lilid(Lilid * ptr_first)710 unsigned long long count_lilid(Lilid* ptr_first) {
711 unsigned long long ull_counter = 0;
712 Lilid *ptr_curr;
713
714 /* start at the beginning */
715 ptr_curr = ptr_first;
716
717 /* loop over all list elements */
718 while ((ptr_curr = get_next_lilid(ptr_curr)) != NULL) {
719 ull_counter++;
720 }
721
722 return ull_counter;
723 }
724
725 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
726 delete_all_lilid(): deletes all members from the list
727
728 int delete_all_lilid returns 0 if ok, or 1 if an error occurred
729
730 Lilid *ptr_first pointer to sentinel
731
732 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_all_lilid(Lilid * ptr_first)733 int delete_all_lilid(Lilid *ptr_first) {
734 Lilid* ptr_curr_item;
735 Lilid* ptr_next_item;
736
737 /* skip the sentinel when freeing memory */
738 ptr_curr_item = ptr_first->ptr_next;
739 ptr_first->ptr_next = NULL;
740
741 /* loop over all list members after the sentinel */
742 while (ptr_curr_item) {
743 /* save a pointer to the next member, if any */
744 ptr_next_item = ptr_curr_item->ptr_next;
745
746 /* free the memory allocated for the list member */
747 free(ptr_curr_item);
748
749 ptr_curr_item = ptr_next_item;
750 }
751 return 0;
752 }
753
754 /*********************************************************************
755 linked list for tokenizing strings. The list stores pointers to
756 the individual tokens. The calling function should terminate the tokens
757 by inserting \0 between the tokens.
758 This is an unsorted linked list. The first list member is a sentinel
759 which is not automatically deallocated by the lilimem functions.
760 The calling fn has to explicitly declare, initialize, and destruct
761 a lilimem struct for this purpose.
762 ********************************************************************/
763
764 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
765 insert_lilistring(): inserts a new member into the list
766
767 int insert_lilistring returns 0 if ok, or 1 if an error occurred
768 if an error occurs
769
770 Lilistring *ptr_first pointer to sentinel
771
772 char* token ptr to token
773
774 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
insert_lilistring(Lilistring * ptr_first,char * token)775 int insert_lilistring(Lilistring *ptr_first, char* token) {
776 Lilistring* ptr_new_item;
777
778 ptr_new_item = malloc(sizeof(Lilistring));
779
780 if (!ptr_new_item) { /* malloc failed */
781 return 1;
782 }
783
784 if (token) {
785 ptr_new_item->token = token;
786 }
787 else {
788 ptr_new_item->token = NULL;
789 }
790
791 ptr_new_item->ptr_next = ptr_first->ptr_next;
792 ptr_first->ptr_next = ptr_new_item;
793
794 return 0;
795 }
796
797 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
798 append_lilistring(): appends a new member into the list. The
799 implementation is not very efficient but is ok
800 for a low number of entries
801
802 int append_lilistring returns 0 if ok, or 1 if an error occurred
803 if an error occurs
804
805 Lilistring *ptr_first pointer to sentinel
806
807 char* token ptr to token
808
809 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
append_lilistring(Lilistring * ptr_first,char * token)810 int append_lilistring(Lilistring *ptr_first, char* token) {
811 Lilistring* ptr_new_item;
812 Lilistring* ptr_last_item;
813
814 ptr_new_item = malloc(sizeof(Lilistring));
815
816 if (!ptr_new_item) { /* malloc failed */
817 return 1;
818 }
819
820 if (token) {
821 ptr_new_item->token = token;
822 }
823 else {
824 ptr_new_item->token = NULL;
825 }
826
827 ptr_new_item->ptr_next = NULL;
828
829 ptr_last_item = ptr_first;
830
831 /* this is going to be inefficient for a large number of entries */
832 while (ptr_last_item->ptr_next) {
833 ptr_last_item = ptr_last_item->ptr_next;
834 }
835 ptr_last_item->ptr_next = ptr_new_item;
836
837 return 0;
838 }
839
840 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
841 get_next_lilistring(): retrieves next member of the list
842
843 Lilistring* get_next_lilistring returns a ptr to the next member or NULL
844 if we're at the end of the list. Use this fn
845 to loop over all list entries. In the first
846 iteration, pass a ptr to the sentinel. In
847 subsequent iterations, pass the ptr that the
848 previous iteration returns.
849
850
851 Lilistring *ptr_first pointer to sentinel
852
853 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_next_lilistring(Lilistring * ptr_first)854 Lilistring* get_next_lilistring(Lilistring* ptr_first) {
855 return ptr_first->ptr_next;
856 }
857
858 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
859 delete_all_lilistring(): deletes all members from the list
860
861 int delete_all_lilistring returns 0 if ok, or 1 if an error occurred
862
863 Lilistring *ptr_first pointer to sentinel
864
865 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_all_lilistring(Lilistring * ptr_first)866 int delete_all_lilistring(Lilistring *ptr_first) {
867 Lilistring* ptr_curr_item;
868 Lilistring* ptr_next_item;
869
870 ptr_curr_item = ptr_first->ptr_next;
871 ptr_first->ptr_next = NULL;
872
873 while (ptr_curr_item) {
874 ptr_next_item = ptr_curr_item->ptr_next;
875 /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */
876 free(ptr_curr_item); /* free the memory allocated for the list member */
877
878 ptr_curr_item = ptr_next_item;
879 }
880 return 0;
881 }
882
883 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
884 count_lilistring(): counts all members in the list
885
886 int count_lilistring returns the number of list members
887
888 Lilistring *ptr_first pointer to sentinel
889
890 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
count_lilistring(Lilistring * ptr_first)891 int count_lilistring(Lilistring* ptr_first) {
892 int counter = 0;
893 Lilistring *ptr_curr;
894
895 /* start at the beginning */
896 ptr_curr = ptr_first;
897
898 /* loop over all list elements */
899 while ((ptr_curr = get_next_lilistring(ptr_curr)) != NULL) {
900 counter++;
901 }
902
903 return counter;
904 }
905
906 /*********************************************************************
907 linked list for fixed-size strings. The list keeps the original order
908 of items
909 ********************************************************************/
910
911 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
912 append_lilifstring(): appends a new member into the list. The
913 implementation is not very efficient but is ok
914 for a low number of entries
915
916 int append_lilifstring returns 0 if ok, or 1 if an error occurred
917 if an error occurs
918
919 Lilifstring *ptr_first pointer to sentinel
920
921 char* token ptr to token
922
923 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
append_lilifstring(Lilifstring * ptr_first,char * token)924 int append_lilifstring(Lilifstring *ptr_first, char* token) {
925 Lilifstring* ptr_new_item;
926 Lilifstring* ptr_last_item;
927
928 ptr_new_item = malloc(sizeof(Lilifstring));
929
930 if (!ptr_new_item) { /* malloc failed */
931 return 1;
932 }
933
934 if (token) {
935 strncpy(ptr_new_item->token, token, LILIFSTRING_SIZE);
936 (ptr_new_item->token)[LILIFSTRING_SIZE-1] = '\0';
937 }
938 else {
939 (ptr_new_item->token)[0] = '\0';
940 }
941
942 ptr_new_item->ptr_next = NULL;
943
944 ptr_last_item = ptr_first;
945
946 /* this is going to be inefficient for a large number of entries */
947 while (ptr_last_item->ptr_next) {
948 ptr_last_item = ptr_last_item->ptr_next;
949 }
950 ptr_last_item->ptr_next = ptr_new_item;
951
952 return 0;
953 }
954
955 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
956 get_next_lilifstring(): retrieves next member of the list
957
958 Lilifstring* get_next_lilifstring returns a ptr to the next member or NULL
959 if we're at the end of the list. Use this fn
960 to loop over all list entries. In the first
961 iteration, pass a ptr to the sentinel. In
962 subsequent iterations, pass the ptr that the
963 previous iteration returns.
964
965
966 Lilifstring *ptr_first pointer to sentinel
967
968 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_next_lilifstring(Lilifstring * ptr_first)969 Lilifstring* get_next_lilifstring(Lilifstring* ptr_first) {
970 return ptr_first->ptr_next;
971 }
972
973 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
974 delete_all_lilifstring(): deletes all members from the list
975
976 int delete_all_lilifstring returns 0 if ok, or 1 if an error occurred
977
978 Lilifstring *ptr_first pointer to sentinel
979
980 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
delete_all_lilifstring(Lilifstring * ptr_first)981 int delete_all_lilifstring(Lilifstring *ptr_first) {
982 Lilifstring* ptr_curr_item;
983 Lilifstring* ptr_next_item;
984
985 ptr_curr_item = ptr_first->ptr_next;
986 ptr_first->ptr_next = NULL;
987
988 while (ptr_curr_item) {
989 ptr_next_item = ptr_curr_item->ptr_next;
990 /* fprintf(stderr, "freeing %s\n", ptr_curr_item->varname); */
991 free(ptr_curr_item); /* free the memory allocated for the list member */
992
993 ptr_curr_item = ptr_next_item;
994 }
995 return 0;
996 }
997
998
999 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1000 find_lilifstring(): checks whether token is already stored in the list
1001
1002 int find_lilifstring returns 1 if token is part of the list. or
1003 0 if not
1004
1005 Lilifstring *ptr_first pointer to sentinel
1006
1007 char* token ptr to token
1008
1009 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
find_lilifstring(Lilifstring * ptr_first,char * token)1010 char* find_lilifstring(Lilifstring* ptr_first, char* token) {
1011 Lilifstring* ptr_curr_item;
1012
1013 ptr_curr_item = ptr_first;
1014
1015 while ((ptr_curr_item = get_next_lilifstring(ptr_curr_item)) != NULL) {
1016 if (!strcmp(ptr_curr_item->token, token)) {
1017 return token;
1018 }
1019 }
1020
1021 return NULL;
1022 }
1023