mirror of https://gerrit.osmocom.org/asn1c
231 lines
4.4 KiB
C
231 lines
4.4 KiB
C
#include "asn1c_internal.h"
|
|
#include "asn1c_fdeps.h"
|
|
|
|
static asn1c_fdeps_t *asn1c_new_dep(const char *filename);
|
|
static int asn1c_dep_add(asn1c_fdeps_t *deps, asn1c_fdeps_t *d);
|
|
|
|
int
|
|
asn1c_activate_dependency(asn1c_fdeps_t *deps, asn1c_fdeps_t *cur, const char *data) {
|
|
const char *fname;
|
|
int i;
|
|
|
|
if(!deps || !data || !*data)
|
|
return 0;
|
|
if(!cur) cur = deps;
|
|
|
|
if(cur->usage > FDEP_NOTUSED)
|
|
return 1; /* Already activated */
|
|
|
|
fname = data;
|
|
if(*data == '#') {
|
|
const char *start = data;
|
|
const char *end = 0;
|
|
|
|
start = strchr(data, '<');
|
|
if(start) {
|
|
start++;
|
|
end = strchr(start, '>');
|
|
} else if((start = strchr(data, '\"'))) {
|
|
start++;
|
|
end = strchr(start, '\"');
|
|
}
|
|
if(end) {
|
|
char *p = alloca((end - start) + 1);
|
|
memcpy(p, start, end - start);
|
|
p[end-start] = '\0';
|
|
fname = p;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if(cur->filename && strcmp(cur->filename, fname) == 0) {
|
|
cur->usage = FDEP_REFERRED;
|
|
|
|
/* Activate subdependencies */
|
|
for(i = 0; i < cur->el_count; i++) {
|
|
asn1c_activate_dependency(deps,
|
|
cur->elements[i],
|
|
cur->elements[i]->filename);
|
|
}
|
|
|
|
/*
|
|
* This might be a link to someplace else.
|
|
*/
|
|
return asn1c_activate_dependency(deps, NULL, fname);
|
|
} else {
|
|
for(i = 0; i < cur->el_count; i++) {
|
|
asn1c_activate_dependency(deps,
|
|
cur->elements[i], fname);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
asn1c_fdeps_t *
|
|
asn1c_read_file_dependencies(arg_t *arg, const char *datadir) {
|
|
char buf[4096];
|
|
asn1c_fdeps_t *deps;
|
|
asn1c_fdeps_t *cur;
|
|
FILE *f;
|
|
enum fdep_usage special_section = FDEP_NOTUSED;
|
|
|
|
(void)arg;
|
|
|
|
if(!datadir || strlen(datadir) > sizeof(buf) / 2) {
|
|
errno = EINVAL;
|
|
return NULL;
|
|
} else {
|
|
sprintf(buf, "%s/file-dependencies", datadir);
|
|
}
|
|
|
|
f = fopen(buf, "r");
|
|
if(!f) return NULL;
|
|
|
|
deps = asn1c_new_dep(0);
|
|
assert(deps);
|
|
|
|
while(fgets(buf, sizeof(buf), f)) {
|
|
char *p = strchr(buf, '#');
|
|
if(p) *p = '\0'; /* Remove comments */
|
|
|
|
cur = deps;
|
|
for(p = strtok(buf, " \t\r\n"); p;
|
|
p = strtok(NULL, " \t\r\n")) {
|
|
asn1c_fdeps_t *d;
|
|
|
|
/*
|
|
* Special "prefix" section.
|
|
*/
|
|
if(strchr(p, ':')) {
|
|
special_section = FDEP_IGNORE;
|
|
if(strcmp(p, "COMMON-FILES:") == 0) {
|
|
special_section = FDEP_COMMON_FILES;
|
|
} else if(strcmp(p, "CONVERTER:") == 0) {
|
|
special_section = FDEP_CONVERTER;
|
|
} else if((arg->flags & A1C_GEN_OER)
|
|
&& strcmp(p, "CODEC-OER:") == 0) {
|
|
special_section = FDEP_CODEC_OER;
|
|
} else if((arg->flags & A1C_GEN_PER)
|
|
&& strcmp(p, "CODEC-PER:") == 0) {
|
|
special_section = FDEP_CODEC_PER;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(special_section == FDEP_IGNORE)
|
|
continue;
|
|
|
|
d = asn1c_new_dep(p);
|
|
d->usage = special_section;
|
|
|
|
if(asn1c_dep_add(cur, d) == 1)
|
|
cur = d;
|
|
}
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return deps;
|
|
}
|
|
|
|
static asn1c_fdeps_t *
|
|
asn1c_new_dep(const char *filename) {
|
|
asn1c_fdeps_t *d;
|
|
|
|
d = calloc(1, sizeof(*d));
|
|
if(filename) {
|
|
d->filename = strdup(filename);
|
|
if(!d->filename) return NULL;
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
static void
|
|
asn1c_free_dep(asn1c_fdeps_t *d) {
|
|
|
|
if(d) {
|
|
if(d->filename) free(d->filename);
|
|
d->filename = 0;
|
|
free(d);
|
|
}
|
|
}
|
|
|
|
static int
|
|
asn1c_dep_add(asn1c_fdeps_t *deps, asn1c_fdeps_t *d) {
|
|
int n;
|
|
|
|
/* Check for duplicates */
|
|
for(n = 0; n < deps->el_count; n++) {
|
|
if(strcmp(deps->elements[n]->filename, d->filename) == 0)
|
|
return 0;
|
|
}
|
|
|
|
if(deps->el_count == deps->el_size) {
|
|
void *p;
|
|
n = deps->el_size?deps->el_size << 2:16;
|
|
p = realloc(deps->elements,
|
|
n * sizeof(deps->elements[0]));
|
|
assert(p);
|
|
deps->elements = p;
|
|
deps->el_size = n;
|
|
}
|
|
|
|
deps->elements[deps->el_count++] = d;
|
|
return 1;
|
|
}
|
|
|
|
asn1c_fdeps_t *
|
|
asn1c_deps_makelist(asn1c_fdeps_t *deps) {
|
|
asn1c_fdeps_t *dlist;
|
|
asn1c_fdeps_t *d;
|
|
int i;
|
|
|
|
if(!deps) {
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
dlist = asn1c_new_dep(0);
|
|
|
|
if(deps->filename && deps->usage != FDEP_NOTUSED) {
|
|
d = asn1c_new_dep(deps->filename);
|
|
d->usage = deps->usage;
|
|
if(!asn1c_dep_add(dlist, d)) {
|
|
asn1c_free_dep(d);
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < deps->el_count; i++) {
|
|
int j;
|
|
d = asn1c_deps_makelist(deps->elements[i]);
|
|
assert(!d->filename);
|
|
for(j = 0; j < d->el_count; j++) {
|
|
if(asn1c_dep_add(dlist, d->elements[j])) {
|
|
d->elements[j] = 0;
|
|
}
|
|
}
|
|
asn1c_deps_freelist(d);
|
|
}
|
|
|
|
return dlist;
|
|
}
|
|
|
|
void
|
|
asn1c_deps_freelist(asn1c_fdeps_t *deps) {
|
|
if(deps) {
|
|
int i;
|
|
if(deps->elements) {
|
|
for(i = 0; i < deps->el_count; i++) {
|
|
asn1c_deps_freelist(deps->elements[i]);
|
|
deps->elements[i] = 0;
|
|
}
|
|
free(deps->elements);
|
|
deps->elements = 0;
|
|
}
|
|
asn1c_free_dep(deps);
|
|
}
|
|
}
|