list.c (5983B)
1// list.c 2 3#include <stdio.h> 4#include <stdarg.h> 5#include <stdlib.h> 6#include <stdbool.h> 7#include <string.h> 8//#include <assert.h> 9//#include <ctype.h> 10//#include <signal.h> 11 12#include "list.h" 13 14// From lcc.c 15extern void *alloc(int); 16extern char *strsave(const char *str); 17extern char *stringf(const char *fmt, ...); 18extern char *path_stripext(char *name); 19extern int matches_ext(const char * filename, const char * ext); 20extern int verbose; 21 22 23 24/* append - append a node with string str onto list, return new list */ 25List append(char *str, List list) { 26 List p = alloc(sizeof *p); 27 28 p->str = str; 29 if (list) { 30 p->link = list->link; 31 list->link = p; 32 } 33 else 34 p->link = p; 35 return p; 36} 37 38 39/* find - find 1st occurrence of str in list, return list node or 0 */ 40List find(char *str, List list) { 41 List b; 42 43 b = list; 44 if (b) 45 do { 46 if (strcmp(str, b->str) == 0) 47 return b; 48 } while ((b = b->link) != list); 49 return 0; 50} 51 52 53/* path2list - convert a colon- or semicolon-separated list to a list */ 54List path2list(const char *path) { 55 List list = NULL; 56 char sep = ':'; 57 58 if (path == NULL) 59 return NULL; 60 if (strchr(path, ';')) 61 sep = ';'; 62 while (*path) { 63 char *p, buf[512]; 64 p = strchr(path, sep); 65 if (p) { 66 size_t len = p - path; 67 if(len >= sizeof(buf)) len = sizeof(buf)-1; 68 strncpy(buf, path, len); 69 buf[len] = '\0'; 70 } 71 else { 72 strncpy(buf, path, sizeof(buf)); 73 buf[sizeof(buf)-1] = '\0'; 74 } 75 if (!find(buf, list)) 76 list = append(strsave(buf), list); 77 if (p == 0) 78 break; 79 path = p + 1; 80 } 81 return list; 82} 83 84 85// Replace extensions for filenames in a list 86void list_rewrite_exts(List list_in, char * ext_match, char * ext_new) 87{ 88 char * filepath_old; 89 90 // Iterate through list and replace file extensions 91 if (list_in) { 92 List list_t = list_in; 93 do { 94 if (list_t->str) { 95 // Check to see if filname has desired extension 96 if (matches_ext(list_t->str, ext_match)) { 97 98 // Save a copy to free after re-assignment 99 filepath_old = list_t->str; 100 // Create a new string with the replaced suffix (stringf() allocs) 101 list_t->str = stringf("%s%s", path_stripext(list_t->str), ext_new); 102 if (verbose > 0) fprintf(stderr,"lcc: rename link obj (from -autobank): %s -> %s\n", filepath_old, list_t->str); 103 } 104 } 105 // Move to next list item, exit if start of list is reached 106 list_t = list_t->link; 107 } while (list_t != list_in); 108 } 109} 110 111 112// Duplicate items with [ext_match] into new list items with [ext_new] 113void list_duplicate_to_new_exts(List list_in, char * ext_match, char * ext_new) 114{ 115 // List may have entries appended, cache original start 116 List list_start = list_in; 117 118 // Iterate through list and replace file extensions 119 if (list_in) { 120 List list_t = list_in; 121 do { 122 if (list_t->str) { 123 // Check to see if filname has desired extension 124 if (matches_ext(list_t->str, ext_match)) { 125 // Make a copy with the replaced extension into the list 126 list_in = append(stringf("%s%s", path_stripext(list_t->str), ext_new), list_in); 127 if (verbose > 0) fprintf(stderr,"lcc: add to rmlist (from -autobank): %s -> %s\n", list_t->str, stringf("%s%s", path_stripext(list_t->str), ext_new)); 128 } 129 } 130 // Move to next list item, exit if start of list is reached 131 list_t = list_t->link; 132 } while (list_t != list_start); 133 } 134} 135 136 137// Remove all items from a list 138List list_remove_all(List list_in) { 139 140 // Well... the custom alloc() used for lists makes it hard to free their memory. 141 // Instead just set the list to NULL to erase it and let cleanup happen on program exit. 142 return NULL; 143 144 /* 145 List list_next; 146 // Iterate through list and free memory 147 if (list_in) { 148 List list_t = list_in->link; // Advance to next item 149 list_in->link = NULL; // Break list to create a stopping point 150 151 do { 152 // Copy next link before freeing the current item 153 list_next = list_t->link; 154 if (list_t) { 155 free(list_t); 156 list_t = NULL; 157 } 158 // Move to next list item, exit if start of list is reached 159 list_t = list_next; 160 } while (list_t && list_t->link); 161 } 162 return NULL; 163 */ 164} 165 166 167// Copies all items from [list_src] to [list_dest] 168// * optionally prefix items from [list_src] with [str_prefix] 169// * optionally append() a separate [str_add_before] for each item in [list_src] (use for space separated flags) 170List list_add_to_another(List list_dest, List list_src, char * str_prefix, char * str_add_before) { 171 172 if (list_src) { 173 List list_t = list_src->link; // Start at first list item (list usually points to END) 174 175 // Iterate through [list_src] and copy into to [list_dest], exit once start is reached again 176 do { 177 if (list_t->str) 178 // Add str_add_before string as a separate item if present 179 if (str_add_before) 180 list_dest = append( stringf("%s", str_add_before), list_dest); 181 182 // pre-pend string prefix if present 183 if (str_prefix) 184 list_dest = append( stringf("%s%s", str_prefix, list_t->str), list_dest); 185 else 186 list_dest = append( stringf("%s", list_t->str), list_dest); 187 // Move to next list item 188 list_t = list_t->link; 189 } while (list_t != list_src); 190 } 191 192 return list_dest; // Return updated list 193}