blob: 18dd63775105d83d0c3d2ffe852f06616d3558ba [file] [log] [blame]
Lev Walkinacd9f8b2004-08-19 13:29:03 +00001#include "asn1c_internal.h"
2#include "asn1c_fdeps.h"
3
Lev Walkina4f8e942017-10-08 19:28:20 -07004#ifndef PATH_MAX
5#define PATH_MAX 1024
6#endif
7
Lev Walkinacd9f8b2004-08-19 13:29:03 +00008static asn1c_fdeps_t *asn1c_new_dep(const char *filename);
9static int asn1c_dep_add(asn1c_fdeps_t *deps, asn1c_fdeps_t *d);
10
11int
12asn1c_activate_dependency(asn1c_fdeps_t *deps, asn1c_fdeps_t *cur, const char *data) {
Lev Walkina4f8e942017-10-08 19:28:20 -070013 char fname_scratch[PATH_MAX];
Lev Walkinafa35b42005-06-15 18:12:48 +000014 const char *fname;
Lev Walkinacd9f8b2004-08-19 13:29:03 +000015 int i;
16
17 if(!deps || !data || !*data)
18 return 0;
19 if(!cur) cur = deps;
20
Lev Walkin0e89d102006-09-12 06:37:17 +000021 if(cur->usage > FDEP_NOTUSED)
Lev Walkinacd9f8b2004-08-19 13:29:03 +000022 return 1; /* Already activated */
23
Lev Walkinafa35b42005-06-15 18:12:48 +000024 fname = data;
Lev Walkinacd9f8b2004-08-19 13:29:03 +000025 if(*data == '#') {
26 const char *start = data;
27 const char *end = 0;
28
29 start = strchr(data, '<');
30 if(start) {
31 start++;
32 end = strchr(start, '>');
Lev Walkin34944f22010-10-07 08:25:37 +000033 } else if((start = strchr(data, '\"'))) {
34 start++;
35 end = strchr(start, '\"');
Lev Walkinacd9f8b2004-08-19 13:29:03 +000036 }
37 if(end) {
Lev Walkina4f8e942017-10-08 19:28:20 -070038 assert((end-start) + 1 < (ssize_t)sizeof(fname_scratch));
39 memcpy(fname_scratch, start, end - start);
40 fname_scratch[end-start] = '\0';
41 fname = fname_scratch;
Lev Walkinacd9f8b2004-08-19 13:29:03 +000042 } else {
43 return 0;
44 }
45 }
46
47 if(cur->filename && strcmp(cur->filename, fname) == 0) {
Lev Walkinf218e782006-09-12 06:21:18 +000048 cur->usage = FDEP_REFERRED;
Lev Walkinacd9f8b2004-08-19 13:29:03 +000049
50 /* Activate subdependencies */
51 for(i = 0; i < cur->el_count; i++) {
52 asn1c_activate_dependency(deps,
53 cur->elements[i],
54 cur->elements[i]->filename);
55 }
56
57 /*
58 * This might be a link to someplace else.
59 */
60 return asn1c_activate_dependency(deps, NULL, fname);
61 } else {
62 for(i = 0; i < cur->el_count; i++) {
63 asn1c_activate_dependency(deps,
64 cur->elements[i], fname);
65 }
66 }
67
68 return 0;
69}
70
71asn1c_fdeps_t *
72asn1c_read_file_dependencies(arg_t *arg, const char *datadir) {
Lev Walkinf218e782006-09-12 06:21:18 +000073 char buf[4096];
Lev Walkinacd9f8b2004-08-19 13:29:03 +000074 asn1c_fdeps_t *deps;
75 asn1c_fdeps_t *cur;
Lev Walkinacd9f8b2004-08-19 13:29:03 +000076 FILE *f;
Lev Walkin0e89d102006-09-12 06:37:17 +000077 enum fdep_usage special_section = FDEP_NOTUSED;
Lev Walkinacd9f8b2004-08-19 13:29:03 +000078
79 (void)arg;
80
81 if(!datadir || strlen(datadir) > sizeof(buf) / 2) {
82 errno = EINVAL;
83 return NULL;
84 } else {
85 sprintf(buf, "%s/file-dependencies", datadir);
86 }
87
88 f = fopen(buf, "r");
89 if(!f) return NULL;
90
91 deps = asn1c_new_dep(0);
92 assert(deps);
93
94 while(fgets(buf, sizeof(buf), f)) {
95 char *p = strchr(buf, '#');
96 if(p) *p = '\0'; /* Remove comments */
97
98 cur = deps;
99 for(p = strtok(buf, " \t\r\n"); p;
100 p = strtok(NULL, " \t\r\n")) {
101 asn1c_fdeps_t *d;
Lev Walkin59b176e2005-11-26 11:25:14 +0000102
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000103 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000104 * Special "prefix" section.
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000105 */
Lev Walkin59b176e2005-11-26 11:25:14 +0000106 if(strchr(p, ':')) {
Lev Walkinf218e782006-09-12 06:21:18 +0000107 special_section = FDEP_IGNORE;
Lev Walkin59b176e2005-11-26 11:25:14 +0000108 if(strcmp(p, "COMMON-FILES:") == 0) {
Lev Walkinf218e782006-09-12 06:21:18 +0000109 special_section = FDEP_COMMON_FILES;
110 } else if(strcmp(p, "CONVERTER:") == 0) {
111 special_section = FDEP_CONVERTER;
Lev Walkinf573ebb2017-07-24 00:25:51 +0400112 } else if((arg->flags & A1C_GEN_OER)
113 && strcmp(p, "CODEC-OER:") == 0) {
114 special_section = FDEP_CODEC_OER;
Lev Walkin59b176e2005-11-26 11:25:14 +0000115 } else if((arg->flags & A1C_GEN_PER)
116 && strcmp(p, "CODEC-PER:") == 0) {
Lev Walkinf218e782006-09-12 06:21:18 +0000117 special_section = FDEP_CODEC_PER;
Lev Walkin59b176e2005-11-26 11:25:14 +0000118 }
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000119 break;
120 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000121
Lev Walkinf218e782006-09-12 06:21:18 +0000122 if(special_section == FDEP_IGNORE)
Lev Walkin59b176e2005-11-26 11:25:14 +0000123 continue;
124
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000125 d = asn1c_new_dep(p);
Lev Walkinf218e782006-09-12 06:21:18 +0000126 d->usage = special_section;
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000127
128 if(asn1c_dep_add(cur, d) == 1)
129 cur = d;
130 }
131 }
132
133 fclose(f);
134
135 return deps;
136}
137
138static asn1c_fdeps_t *
139asn1c_new_dep(const char *filename) {
140 asn1c_fdeps_t *d;
141
142 d = calloc(1, sizeof(*d));
143 if(filename) {
144 d->filename = strdup(filename);
145 if(!d->filename) return NULL;
146 }
147
148 return d;
149}
150
Bi-Ruei, Chiu6f348942016-11-08 15:41:23 +0800151static void
152asn1c_free_dep(asn1c_fdeps_t *d) {
153
154 if(d) {
155 if(d->filename) free(d->filename);
156 d->filename = 0;
157 free(d);
158 }
159}
160
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000161static int
162asn1c_dep_add(asn1c_fdeps_t *deps, asn1c_fdeps_t *d) {
163 int n;
164
165 /* Check for duplicates */
166 for(n = 0; n < deps->el_count; n++) {
167 if(strcmp(deps->elements[n]->filename, d->filename) == 0)
168 return 0;
169 }
170
171 if(deps->el_count == deps->el_size) {
Lev Walkin3441a8b2004-08-19 13:45:27 +0000172 void *p;
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000173 n = deps->el_size?deps->el_size << 2:16;
Lev Walkin3441a8b2004-08-19 13:45:27 +0000174 p = realloc(deps->elements,
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000175 n * sizeof(deps->elements[0]));
176 assert(p);
177 deps->elements = p;
178 deps->el_size = n;
179 }
180
181 deps->elements[deps->el_count++] = d;
182 return 1;
183}
184
185asn1c_fdeps_t *
Lev Walkin8a85b362017-09-26 22:54:44 -0700186asn1c_deps_flatten(const asn1c_fdeps_t *deps) {
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000187 asn1c_fdeps_t *dlist;
188 asn1c_fdeps_t *d;
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000189
190 if(!deps) {
191 errno = EINVAL;
192 return 0;
193 }
194
195 dlist = asn1c_new_dep(0);
196
Lev Walkinf218e782006-09-12 06:21:18 +0000197 if(deps->filename && deps->usage != FDEP_NOTUSED) {
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000198 d = asn1c_new_dep(deps->filename);
Lev Walkinf218e782006-09-12 06:21:18 +0000199 d->usage = deps->usage;
Bi-Ruei, Chiu6f348942016-11-08 15:41:23 +0800200 if(!asn1c_dep_add(dlist, d)) {
201 asn1c_free_dep(d);
202 }
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000203 }
204
Lev Walkin8a85b362017-09-26 22:54:44 -0700205 for(int i = 0; i < deps->el_count; i++) {
206 d = asn1c_deps_flatten(deps->elements[i]);
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000207 assert(!d->filename);
Lev Walkin8a85b362017-09-26 22:54:44 -0700208 for(int j = 0; j < d->el_count; j++) {
Bi-Ruei, Chiu6f348942016-11-08 15:41:23 +0800209 if(asn1c_dep_add(dlist, d->elements[j])) {
210 d->elements[j] = 0;
211 }
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000212 }
Bi-Ruei, Chiu6f348942016-11-08 15:41:23 +0800213 asn1c_deps_freelist(d);
Lev Walkinacd9f8b2004-08-19 13:29:03 +0000214 }
215
216 return dlist;
217}
218
Bi-Ruei, Chiu6f348942016-11-08 15:41:23 +0800219void
220asn1c_deps_freelist(asn1c_fdeps_t *deps) {
221 if(deps) {
222 int i;
223 if(deps->elements) {
224 for(i = 0; i < deps->el_count; i++) {
225 asn1c_deps_freelist(deps->elements[i]);
226 deps->elements[i] = 0;
227 }
228 free(deps->elements);
229 deps->elements = 0;
230 }
231 asn1c_free_dep(deps);
232 }
233}