X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=libasn1compiler%2Fasn1c_fdeps.c;fp=libasn1compiler%2Fasn1c_fdeps.c;h=60a52cbb9ab808c2f18185c9d6e93944b19cd447;hb=70ee6fc793ec8e828067a3569849b6c216054497;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=com%2Fasn1c.git diff --git a/libasn1compiler/asn1c_fdeps.c b/libasn1compiler/asn1c_fdeps.c new file mode 100644 index 0000000..60a52cb --- /dev/null +++ b/libasn1compiler/asn1c_fdeps.c @@ -0,0 +1,251 @@ +#include "asn1c_internal.h" +#include "asn1c_fdeps.h" + +static asn1c_dep_filename *asn1c_dep_filename_new(const char *filename); +static void asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, + int lineno, int column); +static asn1c_dep_chain *asn1c_dep_chain_new(void); + +static asn1c_dep_chain * +asn1c_dep_chains_add_new(asn1c_dep_chainset *deps, + enum asn1c_dep_section section, int active) { + asn1c_dep_chain *dc = asn1c_dep_chain_new(); + asn1c_tagged_dep_chain *tc = calloc(1, sizeof(*tc)); + tc->chain = dc; + tc->section = section; + tc->activated.active = active; + + deps->chains = realloc(deps->chains, + sizeof(deps->chains[0]) * (deps->chains_count + 1)); + assert(deps->chains); + deps->chains[deps->chains_count] = tc; + deps->chains_count++; + + return dc; +} + +void +asn1c_activate_dependency(asn1c_dep_chainset *deps, const char *data, + const char *by) { + char fname_scratch[PATH_MAX]; + + if(!deps || !data || !*data) { + return; + } + + assert(deps->chains_count); + + const char *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) { + assert((end-start) + 1 < (ssize_t)sizeof(fname_scratch)); + memcpy(fname_scratch, start, end - start); + fname_scratch[end-start] = '\0'; + fname = fname_scratch; + } else { + return; + } + } + + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_tagged_dep_chain *ch = deps->chains[i]; + if(!ch->activated.active && ch->chain->deps_count > 0 + && strcmp(ch->chain->deps[0]->filename, fname) == 0) { + ch->activated.by = strdup(by); + ch->activated.active = 1; + + for(size_t j = 0; j < ch->chain->deps_count; j++) { + asn1c_activate_dependency(deps, ch->chain->deps[j]->filename, + by); + } + } + } +} + +asn1c_dep_chainset * +asn1c_read_file_dependencies(arg_t *arg, const char *datadir) { + char buf[4096]; + asn1c_dep_chainset *deps; + FILE *f; + int lineno = 0; + + 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 = calloc(1, sizeof(*deps)); + assert(deps); + enum asn1c_dep_section section = FDEP_COMMON_FILES; + int activate = 0; + + while(fgets(buf, sizeof(buf), f)) { + char *p = strchr(buf, '#'); + if(p) *p = '\0'; /* Remove comments */ + + lineno++; + + asn1c_dep_chain *dc = asn1c_dep_chains_add_new(deps, section, activate); + + for(p = strtok(buf, " \t\r\n"); p; + p = strtok(NULL, " \t\r\n")) { + + /* + * Special "prefix" section. + */ + if(strchr(p, ':')) { + if(strcmp(p, "COMMON-FILES:") == 0) { + section = FDEP_COMMON_FILES; + activate = 1; + } else if(strcmp(p, "CONVERTER:") == 0) { + activate = 1; + section = FDEP_CONVERTER; + } else if((arg->flags & A1C_GEN_OER) + && strcmp(p, "CODEC-OER:") == 0) { + activate = 0; + section = FDEP_CODEC_OER; + } else if((arg->flags & A1C_GEN_PER) + && strcmp(p, "CODEC-PER:") == 0) { + activate = 0; + section = FDEP_CODEC_PER; + } else { + section = FDEP_IGNORE; + activate = 0; + } + break; + } + + asn1c_dep_add(dc, p, lineno, p - buf); + } + } + + fclose(f); + + /* A single filename by itself means that we should include that */ + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_tagged_dep_chain *ch = deps->chains[i]; + if(!ch->activated.active && ch->chain->deps_count == 1) { + asn1c_activate_dependency(deps, ch->chain->deps[0]->filename, + "implicit"); + } + } + + return deps; +} + +static asn1c_dep_filename * +asn1c_dep_filename_new(const char *filename) { + asn1c_dep_filename *d; + + assert(filename); + + d = calloc(1, sizeof(*d)); + assert(d); + d->filename = strdup(filename); + assert(d->filename); + + return d; +} + +static asn1c_dep_chain * +asn1c_dep_chain_new() { + return calloc(1, sizeof(asn1c_dep_chain)); +} + +static void +asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, int lineno, int column) { + asn1c_dep_filename *df = asn1c_dep_filename_new(filename); + df->lineno = lineno; + df->column = column; + + dlist->deps = + realloc(dlist->deps, (dlist->deps_count + 1) * sizeof(dlist->deps[0])); + assert(dlist->deps); + dlist->deps[dlist->deps_count] = df; + dlist->deps_count += 1; +} + +static int +asn1c_dep_has_filename(const asn1c_dep_chain *dlist, const char *filename) { + for(size_t i = 0; i < dlist->deps_count; i++) { + if(strcmp(dlist->deps[i]->filename, filename) == 0) { + return 1; + } + } + return 0; +} + +asn1c_dep_chain * +asn1c_deps_flatten(const asn1c_dep_chainset *deps, + enum asn1c_dep_section include_section) { + asn1c_dep_chain *dlist; + + if(!deps) { + errno = EINVAL; + return 0; + } + + dlist = asn1c_dep_chain_new(); + + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_tagged_dep_chain *tc = deps->chains[i]; + asn1c_dep_chain *dc = tc->chain; + + if(!tc->activated.active) { + continue; + } + if((tc->section & include_section) == 0) { + continue; + } + + for(size_t j = 0; j < dc->deps_count; j++) { + if(!asn1c_dep_has_filename(dlist, dc->deps[j]->filename)) { + asn1c_dep_add(dlist, dc->deps[j]->filename, dc->deps[j]->lineno, + dc->deps[j]->column); + } + } + } + + return dlist; +} + +void +asn1c_dep_chain_free(asn1c_dep_chain *dc) { + if(dc) { + for(size_t i = 0; i < dc->deps_count; i++) { + asn1c_dep_filename *df = dc->deps[i]; + free(df->filename); + free(df); + } + free(dc->deps); + } +} + +void +asn1c_dep_chainset_free(asn1c_dep_chainset *deps) { + if(deps) { + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_dep_chain_free(deps->chains[i]->chain); + free(deps->chains[i]->activated.by); + free(deps->chains[i]); + } + free(deps->chains); + free(deps); + } +}