asn1c/libasn1compiler/asn1c_fdeps.c

198 lines
3.8 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->used_somewhere)
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, '>');
}
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->used_somewhere = 1;
/* 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) {
asn1c_fdeps_t *deps;
asn1c_fdeps_t *cur;
char buf[4096];
FILE *f;
enum {
SS_DYNAMIC, /* Dynamic list of dependencies */
SS_CODEC_PER, /* Use contents only if -gen-PER */
SS_COMMON_FILES, /* Section for dependencies */
SS_IGNORE /* Ignore contents of this section */
} special_section = SS_DYNAMIC;
(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 = SS_IGNORE;
if(strcmp(p, "COMMON-FILES:") == 0) {
special_section = SS_COMMON_FILES;
} else if((arg->flags & A1C_GEN_PER)
&& strcmp(p, "CODEC-PER:") == 0) {
special_section = SS_CODEC_PER;
}
break;
}
if(special_section == SS_IGNORE)
continue;
d = asn1c_new_dep(p);
assert(d);
d->used_somewhere = 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 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->used_somewhere) {
d = asn1c_new_dep(deps->filename);
asn1c_dep_add(dlist, 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++) {
asn1c_dep_add(dlist, d->elements[j]);
}
}
return dlist;
}