60a52cbb9ab808c2f18185c9d6e93944b19cd447
[com/asn1c.git] / libasn1compiler / asn1c_fdeps.c
1 #include "asn1c_internal.h"
2 #include "asn1c_fdeps.h"
3
4 static asn1c_dep_filename *asn1c_dep_filename_new(const char *filename);
5 static void asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename,
6                          int lineno, int column);
7 static asn1c_dep_chain *asn1c_dep_chain_new(void);
8
9 static asn1c_dep_chain *
10 asn1c_dep_chains_add_new(asn1c_dep_chainset *deps,
11                          enum asn1c_dep_section section, int active) {
12     asn1c_dep_chain *dc = asn1c_dep_chain_new();
13     asn1c_tagged_dep_chain *tc = calloc(1, sizeof(*tc));
14     tc->chain = dc;
15     tc->section = section;
16     tc->activated.active = active;
17
18     deps->chains = realloc(deps->chains,
19                            sizeof(deps->chains[0]) * (deps->chains_count + 1));
20     assert(deps->chains);
21     deps->chains[deps->chains_count] = tc;
22     deps->chains_count++;
23
24     return dc;
25 }
26
27 void
28 asn1c_activate_dependency(asn1c_dep_chainset *deps, const char *data,
29                           const char *by) {
30     char fname_scratch[PATH_MAX];
31
32     if(!deps || !data || !*data) {
33         return;
34     }
35
36     assert(deps->chains_count);
37
38     const char *fname = data;
39     if(*data == '#') {
40         const char *start = data;
41         const char *end = 0;
42
43         start = strchr(data, '<');
44         if(start) {
45             start++;
46             end = strchr(start, '>');
47         } else if((start = strchr(data, '\"'))) {
48             start++;
49             end = strchr(start, '\"');
50         }
51         if(end) {
52             assert((end-start) + 1 < (ssize_t)sizeof(fname_scratch));
53             memcpy(fname_scratch, start, end - start);
54             fname_scratch[end-start] = '\0';
55             fname = fname_scratch;
56         } else {
57             return;
58         }
59     }
60
61     for(size_t i = 0; i < deps->chains_count; i++) {
62         asn1c_tagged_dep_chain *ch = deps->chains[i];
63         if(!ch->activated.active && ch->chain->deps_count > 0
64            && strcmp(ch->chain->deps[0]->filename, fname) == 0) {
65             ch->activated.by = strdup(by);
66             ch->activated.active = 1;
67
68             for(size_t j = 0; j < ch->chain->deps_count; j++) {
69                 asn1c_activate_dependency(deps, ch->chain->deps[j]->filename,
70                                           by);
71             }
72         }
73     }
74 }
75
76 asn1c_dep_chainset *
77 asn1c_read_file_dependencies(arg_t *arg, const char *datadir) {
78         char buf[4096];
79         asn1c_dep_chainset *deps;
80         FILE *f;
81     int lineno = 0;
82
83         if(!datadir || strlen(datadir) > sizeof(buf) / 2) {
84                 errno = EINVAL;
85                 return NULL;
86         } else {
87                 sprintf(buf, "%s/file-dependencies", datadir);
88         }
89
90         f = fopen(buf, "r");
91         if(!f) return NULL;
92
93         deps = calloc(1, sizeof(*deps));
94         assert(deps);
95     enum asn1c_dep_section section = FDEP_COMMON_FILES;
96     int activate = 0;
97
98     while(fgets(buf, sizeof(buf), f)) {
99                 char *p = strchr(buf, '#');
100                 if(p) *p = '\0';        /* Remove comments */
101
102         lineno++;
103
104         asn1c_dep_chain *dc = asn1c_dep_chains_add_new(deps, section, activate);
105
106         for(p = strtok(buf, " \t\r\n"); p;
107                                 p = strtok(NULL, " \t\r\n")) {
108
109                         /*
110                          * Special "prefix" section.
111                          */
112                         if(strchr(p, ':')) {
113                                 if(strcmp(p, "COMMON-FILES:") == 0) {
114                                         section = FDEP_COMMON_FILES;
115                     activate = 1;
116                                 } else if(strcmp(p, "CONVERTER:") == 0) {
117                     activate = 1;
118                                         section = FDEP_CONVERTER;
119                                 } else if((arg->flags & A1C_GEN_OER)
120                                           && strcmp(p, "CODEC-OER:") == 0) {
121                     activate = 0;
122                                         section = FDEP_CODEC_OER;
123                                 } else if((arg->flags & A1C_GEN_PER)
124                                           && strcmp(p, "CODEC-PER:") == 0) {
125                     activate = 0;
126                                         section = FDEP_CODEC_PER;
127                                 } else {
128                                         section = FDEP_IGNORE;
129                     activate = 0;
130                 }
131                 break;
132                         }
133
134             asn1c_dep_add(dc, p, lineno, p - buf);
135         }
136         }
137
138         fclose(f);
139
140     /* A single filename by itself means that we should include that */
141     for(size_t i = 0; i < deps->chains_count; i++) {
142         asn1c_tagged_dep_chain *ch = deps->chains[i];
143         if(!ch->activated.active && ch->chain->deps_count == 1) {
144             asn1c_activate_dependency(deps, ch->chain->deps[0]->filename,
145                                       "implicit");
146         }
147     }
148
149         return deps;
150 }
151
152 static asn1c_dep_filename *
153 asn1c_dep_filename_new(const char *filename) {
154     asn1c_dep_filename *d;
155
156     assert(filename);
157
158     d = calloc(1, sizeof(*d));
159     assert(d);
160     d->filename = strdup(filename);
161     assert(d->filename);
162
163         return d;
164 }
165
166 static asn1c_dep_chain *
167 asn1c_dep_chain_new() {
168     return calloc(1, sizeof(asn1c_dep_chain));
169 }
170
171 static void
172 asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, int lineno, int column) {
173     asn1c_dep_filename *df = asn1c_dep_filename_new(filename);
174     df->lineno = lineno;
175     df->column = column;
176
177     dlist->deps =
178         realloc(dlist->deps, (dlist->deps_count + 1) * sizeof(dlist->deps[0]));
179     assert(dlist->deps);
180     dlist->deps[dlist->deps_count] = df;
181     dlist->deps_count += 1;
182 }
183
184 static int
185 asn1c_dep_has_filename(const asn1c_dep_chain *dlist, const char *filename) {
186     for(size_t i = 0; i < dlist->deps_count; i++) {
187         if(strcmp(dlist->deps[i]->filename, filename) == 0) {
188             return 1;
189         }
190     }
191     return 0;
192 }
193
194 asn1c_dep_chain *
195 asn1c_deps_flatten(const asn1c_dep_chainset *deps,
196                    enum asn1c_dep_section include_section) {
197     asn1c_dep_chain *dlist;
198
199         if(!deps) {
200                 errno = EINVAL;
201                 return 0;
202         }
203
204         dlist = asn1c_dep_chain_new();
205
206         for(size_t i = 0; i < deps->chains_count; i++) {
207         asn1c_tagged_dep_chain *tc = deps->chains[i];
208         asn1c_dep_chain *dc = tc->chain;
209
210         if(!tc->activated.active) {
211             continue;
212         }
213         if((tc->section & include_section) == 0) {
214             continue;
215         }
216
217         for(size_t j = 0; j < dc->deps_count; j++) {
218             if(!asn1c_dep_has_filename(dlist, dc->deps[j]->filename))  {
219                 asn1c_dep_add(dlist, dc->deps[j]->filename, dc->deps[j]->lineno,
220                               dc->deps[j]->column);
221             }
222         }
223     }
224
225         return dlist;
226 }
227
228 void
229 asn1c_dep_chain_free(asn1c_dep_chain *dc) {
230     if(dc) {
231         for(size_t i = 0; i < dc->deps_count; i++) {
232             asn1c_dep_filename *df = dc->deps[i];
233             free(df->filename);
234             free(df);
235         }
236         free(dc->deps);
237     }
238 }
239
240 void
241 asn1c_dep_chainset_free(asn1c_dep_chainset *deps) {
242         if(deps) {
243         for(size_t i = 0; i < deps->chains_count; i++) {
244             asn1c_dep_chain_free(deps->chains[i]->chain);
245             free(deps->chains[i]->activated.by);
246             free(deps->chains[i]);
247         }
248         free(deps->chains);
249         free(deps);
250     }
251 }