#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); } }