#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; int hit_COMMON_FILES = 0; (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; /* * If hit "COMMON-FILES:", treat everything else * as a huge dependency. */ if(strcmp(p, "COMMON-FILES:") == 0) { hit_COMMON_FILES = 1; break; } d = asn1c_new_dep(p); assert(d); d->used_somewhere = hit_COMMON_FILES; 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; }