gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-support/lcc/list.c
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
15 extern void *alloc(int);
16 extern char *strsave(const char *str);
17 extern char *stringf(const char *fmt, ...);
18 extern char *path_stripext(char *name);
19 extern int matches_ext(const char * filename, const char * ext);
20 extern int verbose;
21
22
23
24 /* append - append a node with string str onto list, return new list */
25 List 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 */
40 List 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 */
54 List 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
86 void 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]
113 void 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
138 List 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)
170 List 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 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.