diff --git a/libasn1compiler/asn1c_fdeps.c b/libasn1compiler/asn1c_fdeps.c new file mode 100644 index 0000000000000000000000000000000000000000..cb53b3cee87370aa51b5f639ecbe966d84edfa59 --- /dev/null +++ b/libasn1compiler/asn1c_fdeps.c @@ -0,0 +1,180 @@ +#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) { + char *fname; + int i; + + if(!deps || !data || !*data) + return 0; + if(!cur) cur = deps; + + if(cur->used_somewhere) + return 1; /* Already activated */ + + (const char *)fname = data; + if(*data == '#') { + const char *start = data; + const char *end = 0; + + start = strchr(data, '<'); + if(start) { + start++; + end = strchr(start, '>'); + } + if(end) { + fname = alloca((end - start) + 1); + memcpy(fname, start, end - start); + fname[end-start] = '\0'; + } 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) { + n = deps->el_size?deps->el_size << 2:16; + void *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; +} + diff --git a/libasn1compiler/asn1c_fdeps.h b/libasn1compiler/asn1c_fdeps.h new file mode 100644 index 0000000000000000000000000000000000000000..bb9496f9235a1bcd2c35905856305996631ed4e4 --- /dev/null +++ b/libasn1compiler/asn1c_fdeps.h @@ -0,0 +1,22 @@ +#ifndef _ASN1C_FDEPS_H_ +#define _ASN1C_FDEPS_H_ + +typedef struct asn1c_fdeps_s { + char *filename; /* Or 0, if root. */ + + int used_somewhere; /* Somefile refers to it */ + + struct asn1c_fdeps_s **elements; + int el_size; + int el_count; +} asn1c_fdeps_t; + +asn1c_fdeps_t *asn1c_read_file_dependencies(arg_t *arg, const char *datadir); + +/* Data may be a filename or an "#include <>" string. */ +int asn1c_activate_dependency(asn1c_fdeps_t *deps, asn1c_fdeps_t *cur, + const char *data); + +asn1c_fdeps_t *asn1c_deps_makelist(asn1c_fdeps_t *deps); + +#endif /* _ASN1C_FDEPS_H_ */ diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c index 15d1b676d5bffaed0928922954126899a071a907..3c630538de33666a508f525ad0bf753063ce1771 100644 --- a/libasn1compiler/asn1c_save.c +++ b/libasn1compiler/asn1c_save.c @@ -1,21 +1,29 @@ #include "asn1c_internal.h" #include "asn1c_compat.h" +#include "asn1c_fdeps.h" -static int asn1c_dump_streams(arg_t *arg); +static int asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *); static int asn1c_print_streams(arg_t *arg); -static int asn1c_save_streams(arg_t *arg); +static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *); static int asn1c_copy_over(arg_t *arg, char *path); int asn1c_save_compiled_output(arg_t *arg, const char *datadir) { - - (void)datadir; + asn1c_fdeps_t *deps = 0; + FILE *mkf; + asn1c_fdeps_t *dlist; + + deps = asn1c_read_file_dependencies(arg, datadir); + if(!deps && datadir) { + WARNING("Cannot read file-dependencies information " + "from %s\n", datadir); + } TQ_FOR(arg->mod, &(arg->asn->modules), mod_next) { TQ_FOR(arg->expr, &(arg->mod->members), next) { if(asn1_lang_map[arg->expr->meta_type] [arg->expr->expr_type].type_cb) { - if(asn1c_dump_streams(arg)) + if(asn1c_dump_streams(arg, deps)) return -1; } } @@ -24,68 +32,65 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir) { /* * Dump out the Makefile template and the rest of the support code. */ - if((arg->flags & A1C_PRINT_COMPILED) == 0 - && (arg->flags & A1C_OMIT_SUPPORT_CODE) == 0) { - glob_t pg; - FILE *mkf; - char *p; - int i; - - i = strlen(datadir) + sizeof("/*.[ch]"); - p = alloca(i); - snprintf(p, i, "%s/*.[ch]", datadir); - - memset(&pg, 0, sizeof(pg)); - if(glob(p, GLOB_ERR -#ifdef GLOB_TILDE - | GLOB_TILDE -#endif /* GLOB_TILDE */ - , NULL, &pg)) { - fprintf(stderr, - "Bad skeletons directory (-S) %s: %s\n", - datadir, strerror(errno)); - return -1; - } + if((arg->flags & A1C_PRINT_COMPILED) + || (arg->flags & A1C_OMIT_SUPPORT_CODE)) { + return 0; /* Finished */ + } - mkf = asn1c_open_file(arg, "Makefile.am", ".sample"); - if(mkf == NULL) { - globfree(&pg); - perror("Makefile.am.sample"); - return -1; - } + mkf = asn1c_open_file("Makefile.am", ".sample"); + if(mkf == NULL) { + perror("Makefile.am.sample"); + return -1; + } - fprintf(mkf, "ASN_SRCS="); - TQ_FOR(arg->mod, &(arg->asn->modules), mod_next) { - TQ_FOR(arg->expr, &(arg->mod->members), next) { - if(asn1_lang_map[arg->expr->meta_type] - [arg->expr->expr_type].type_cb) { - fprintf(mkf, "\t\\\n\t%s.c %s.h", - arg->expr->Identifier, - arg->expr->Identifier); - } + fprintf(mkf, "ASN_MODULE_SOURCES="); + TQ_FOR(arg->mod, &(arg->asn->modules), mod_next) { + TQ_FOR(arg->expr, &(arg->mod->members), next) { + if(asn1_lang_map[arg->expr->meta_type] + [arg->expr->expr_type].type_cb) { + fprintf(mkf, "\t\\\n\t%s.c %s.h", + arg->expr->Identifier, + arg->expr->Identifier); } } + } + + /* + * Move necessary skeleton files and add them to Makefile.am.sample. + */ + dlist = asn1c_deps_makelist(deps); + if(dlist) { + char buf[8129]; + char *dir_end; + int i = strlen(datadir); + + assert(i < (int)(sizeof(buf) / 2 - 2)); + memcpy(buf, datadir, i); + dir_end = buf + i; + *dir_end++ = '/'; + + for(i = 0; i < dlist->el_count; i++) { + char *fname = dlist->elements[i]->filename; + + assert(strlen(fname) < (sizeof(buf) / 2)); + strcpy(dir_end, fname); - for(i = 0; i < pg.gl_pathc; i++) { - if(asn1c_copy_over(arg, pg.gl_pathv[i])) { + if(asn1c_copy_over(arg, buf) == -1) { fprintf(mkf, ">>>ABORTED<<<"); fclose(mkf); - globfree(&pg); return -1; } else { - fprintf(mkf, "\t\\\n\t%s", - a1c_basename(pg.gl_pathv[i])); + fprintf(mkf, "\t\\\n\t%s", fname); } } - - fprintf(mkf, "\n\n"); - fprintf(mkf, "lib_LTLIBRARIES=libsomething.la\n"); - fprintf(mkf, "libsomething_la_SOURCES=${ASN_SRCS}\n"); - fclose(mkf); - fprintf(stderr, "Generated Makefile.am.sample\n"); - globfree(&pg); } + fprintf(mkf, "\n\n"); + fprintf(mkf, "lib_LTLIBRARIES=libsomething.la\n"); + fprintf(mkf, "libsomething_la_SOURCES=$(ASN_MODULE_SOURCES)\n"); + fclose(mkf); + fprintf(stderr, "Generated Makefile.am.sample\n"); + return 0; } @@ -93,11 +98,11 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir) { * Dump the streams. */ static int -asn1c_dump_streams(arg_t *arg) { +asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *deps) { if(arg->flags & A1C_PRINT_COMPILED) { return asn1c_print_streams(arg); } else { - return asn1c_save_streams(arg); + return asn1c_save_streams(arg, deps); } } @@ -125,7 +130,7 @@ asn1c_print_streams(arg_t *arg) { } static int -asn1c_save_streams(arg_t *arg) { +asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) { asn1p_expr_t *expr = arg->expr; compiler_streams_t *cs = expr->data; out_chunk_t *ot; @@ -138,8 +143,8 @@ asn1c_save_streams(arg_t *arg) { return -1; } - fp_c = asn1c_open_file(arg, expr->Identifier, ".c"); - fp_h = asn1c_open_file(arg, expr->Identifier, ".h"); + fp_c = asn1c_open_file(expr->Identifier, ".c"); + fp_h = asn1c_open_file(expr->Identifier, ".h"); if(fp_c == NULL || fp_h == NULL) { if(fp_c) fclose(fp_c); /* lacks unlink() */ if(fp_h) fclose(fp_h); /* lacks unlink() */ @@ -163,15 +168,7 @@ asn1c_save_streams(arg_t *arg) { arg->mod->source_file_name ); - header_id = alloca(strlen(expr->Identifier) + 1); - if(1) { - char *src, *dst; - for(src = expr->Identifier, dst = header_id; - (*dst=*src); src++, dst++) - if(!isalnum(*src)) *dst = '_'; - *dst = '\0'; - } - + header_id = asn1c_make_identifier(0, expr->Identifier, NULL); fprintf(fp_h, "#ifndef\t_%s_H_\n" "#define\t_%s_H_\n" @@ -181,8 +178,10 @@ asn1c_save_streams(arg_t *arg) { fprintf(fp_h, "#include <constr_TYPE.h>\n\n"); - TQ_FOR(ot, &(cs->targets[OT_INCLUDES]), next) + TQ_FOR(ot, &(cs->targets[OT_INCLUDES]), next) { + asn1c_activate_dependency(deps, 0, ot->buf); fwrite(ot->buf, ot->len, 1, fp_h); + } fprintf(fp_h, "\n"); TQ_FOR(ot, &(cs->targets[OT_DEPS]), next) fwrite(ot->buf, ot->len, 1, fp_h); @@ -232,13 +231,16 @@ asn1c_copy_over(arg_t *arg, char *path) { fprintf(stderr, "File %s is already here as %s\n", path, fname); - return 0; + return 1; } else { fprintf(stderr, "Retaining local %s (%s suggested)\n", fname, path); - return 0; + return 1; } + } else if(errno == ENOENT) { + /* Ignore this */ + return 0; } else { fprintf(stderr, "Symlink %s -> %s failed: %s\n", path, fname, strerror(errno)); @@ -248,6 +250,6 @@ asn1c_copy_over(arg_t *arg, char *path) { fprintf(stderr, "Symlinked %s\t-> %s\n", path, fname); - return 0; + return 1; } diff --git a/libasn1compiler/asn1c_save.h b/libasn1compiler/asn1c_save.h index 487e625b023f71a8dedcbb6b58b00cbc5540b6fc..8d4b1f5e137de982b29e5dc09ea3ab9316533028 100644 --- a/libasn1compiler/asn1c_save.h +++ b/libasn1compiler/asn1c_save.h @@ -1,6 +1,6 @@ -#ifndef _ASN1_SAVE_H_ -#define _ASN1_SAVE_H_ +#ifndef _ASN1C_SAVE_H_ +#define _ASN1C_SAVE_H_ int asn1c_save_compiled_output(arg_t *arg, const char *datadir); -#endif /* _ASN1_SAVE_H_ */ +#endif /* _ASN1C_SAVE_H_ */