aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2005-03-04 08:52:50 +0000
committerLev Walkin <vlm@lionet.info>2005-03-04 08:52:50 +0000
commit4604d03d985731fb0a42e62c0e5b0b626f4d6c64 (patch)
treeccce01adbeabeedf2ed3e7cc235c9c5ff9590e90
parent21d00009376ee1e675301eeecea88b1ba2c91f18 (diff)
retaining old file if contents are the same
-rw-r--r--libasn1compiler/asn1c_C.c5
-rw-r--r--libasn1compiler/asn1c_compat.c42
-rw-r--r--libasn1compiler/asn1c_compat.h6
-rw-r--r--libasn1compiler/asn1c_save.c85
-rw-r--r--libasn1compiler/asn1compiler.h2
5 files changed, 116 insertions, 24 deletions
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index 5cd9e055..e35f534f 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -7,6 +7,7 @@
#include "asn1c_constraint.h"
#include "asn1c_out.h"
#include "asn1c_misc.h"
+#include "asn1c_compat.h"
#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
typedef struct tag2el_s {
@@ -1703,9 +1704,9 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_
int using_type_name = 0;
char *p;
- OUT("/* %s defined in %s at line %d */\n",
+ OUT("/* %s defined in %s near line %d */\n",
MKID_nc(expr->Identifier),
- arg->mod->source_file_name, expr->_lineno);
+ a1c_basename(arg->mod->source_file_name), expr->_lineno);
if(HIDE_INNER_DEFS)
OUT("static /* Use -fall-defs-global to expose */\n");
OUT("asn_TYPE_descriptor_t asn_DEF_%s", MKID_nc(expr->Identifier));
diff --git a/libasn1compiler/asn1c_compat.c b/libasn1compiler/asn1c_compat.c
index ebc6d3f0..2a80251a 100644
--- a/libasn1compiler/asn1c_compat.c
+++ b/libasn1compiler/asn1c_compat.c
@@ -14,7 +14,7 @@
#endif
FILE *
-asn1c_open_file(const char *name, const char *ext) {
+asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
int created = 1;
#ifndef WIN32
struct stat sb;
@@ -22,22 +22,35 @@ asn1c_open_file(const char *name, const char *ext) {
char *fname;
size_t len;
FILE *fp;
+ int ret;
int fd;
/*
* Compute filenames.
*/
- len = strlen(name) + strlen(ext) + 1;
+ len = strlen(name) + strlen(ext) + sizeof(".XXXXXX");
fname = alloca(len);
- snprintf(fname, len, "%s%s", name, ext);
-
- /*
- * Create files.
- */
- fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
- if(fd == -1 && errno == EEXIST) {
- fd = open(fname, O_WRONLY, DEFFILEMODE);
- created = 0;
+ ret = snprintf(fname, len, "%s%s%s", name, ext,
+ opt_tmpname ? ".XXXXXX" : "");
+ assert(ret > 0 && ret < len);
+
+ if(opt_tmpname) {
+ /*
+ * Create temporary file.
+ */
+ fd = mkstemp(fname);
+#ifndef WIN32
+ (void)fchmod(fd, DEFFILEMODE);
+#endif
+ } else {
+ /*
+ * Create specified file, or open the old one.
+ */
+ fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
+ if(fd == -1 && errno == EEXIST) {
+ fd = open(fname, O_WRONLY, DEFFILEMODE);
+ created = 0;
+ }
}
if(fd == -1) {
perror(fname);
@@ -68,6 +81,13 @@ asn1c_open_file(const char *name, const char *ext) {
if(created) unlink(fname);
close(fd);
}
+
+ /* Return the temporary file name */
+ if(opt_tmpname) {
+ *opt_tmpname = strdup(fname);
+ assert(*opt_tmpname);
+ }
+
return fp;
}
diff --git a/libasn1compiler/asn1c_compat.h b/libasn1compiler/asn1c_compat.h
index 44ac438c..8aa38654 100644
--- a/libasn1compiler/asn1c_compat.h
+++ b/libasn1compiler/asn1c_compat.h
@@ -3,8 +3,12 @@
/*
* Open the arbitrary file by its base name and extension.
+ * If opt_tmpname is given, a temporary file will be created and
+ * its name returned in (*opt_tmpname).
+ * The (*opt_tmpname) should then be subsequently freed by free(3).
*/
-FILE *asn1c_open_file(const char *base_part, const char *extension);
+FILE *asn1c_open_file(const char *base_part, const char *extension,
+ char **opt_tmpname);
/*
* Obtain base name and directory name of a path.
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index 1abf2427..2d0410f5 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -10,6 +10,7 @@ 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, asn1c_fdeps_t *);
static int asn1c_copy_over(arg_t *arg, char *path);
+static int identical_files(const char *fname1, const char *fname2);
int
asn1c_save_compiled_output(arg_t *arg, const char *datadir) {
@@ -41,7 +42,7 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir) {
return 0; /* Finished */
}
- mkf = asn1c_open_file("Makefile.am", ".sample");
+ mkf = asn1c_open_file("Makefile.am", ".sample", 0);
if(mkf == NULL) {
perror("Makefile.am.sample");
return -1;
@@ -174,7 +175,11 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
compiler_streams_t *cs = expr->data;
out_chunk_t *ot;
FILE *fp_c, *fp_h;
+ char *tmpname_c, *tmpname_h;
+ char *name_buf;
char *header_id;
+ const char *c_retained = "";
+ const char *h_retained = "";
if(cs == NULL) {
fprintf(stderr, "Cannot compile %s at line %d\n",
@@ -182,11 +187,11 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
return -1;
}
- fp_c = asn1c_open_file(expr->Identifier, ".c");
- fp_h = asn1c_open_file(expr->Identifier, ".h");
+ fp_c = asn1c_open_file(expr->Identifier, ".c", &tmpname_c);
+ fp_h = asn1c_open_file(expr->Identifier, ".h", &tmpname_h);
if(fp_c == NULL || fp_h == NULL) {
- if(fp_c) fclose(fp_c); /* lacks unlink() */
- if(fp_h) fclose(fp_h); /* lacks unlink() */
+ if(fp_c) { unlink(tmpname_c); free(tmpname_c); fclose(fp_c); }
+ if(fp_h) { unlink(tmpname_h); free(tmpname_h); fclose(fp_h); }
return -1;
}
@@ -250,11 +255,70 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
fclose(fp_c);
fclose(fp_h);
- fprintf(stderr, "Compiled %s.c\n", expr->Identifier);
- fprintf(stderr, "Compiled %s.h\n", expr->Identifier);
+
+ name_buf = alloca(strlen(expr->Identifier) + 3);
+
+ sprintf(name_buf, "%s.c", expr->Identifier);
+ if(identical_files(name_buf, tmpname_c)) {
+ c_retained = " (contents unchanged)";
+ unlink(tmpname_c);
+ } else {
+ if(rename(tmpname_c, name_buf)) {
+ unlink(tmpname_c);
+ perror(tmpname_c);
+ return -1;
+ }
+ }
+
+ sprintf(name_buf, "%s.h", expr->Identifier);
+ if(identical_files(name_buf, tmpname_h)) {
+ h_retained = " (contents unchanged)";
+ unlink(tmpname_h);
+ } else {
+ if(rename(tmpname_h, name_buf)) {
+ unlink(tmpname_h);
+ perror(tmpname_h);
+ return -1;
+ }
+ }
+
+ free(tmpname_c);
+ free(tmpname_h);
+
+ fprintf(stderr, "Compiled %s.c%s\n",
+ expr->Identifier, c_retained);
+ fprintf(stderr, "Compiled %s.h%s\n",
+ expr->Identifier, h_retained);
return 0;
}
+static int
+identical_files(const char *fname1, const char *fname2) {
+ char buf[2][8192];
+ FILE *fp1, *fp2;
+ size_t olen, nlen;
+ int retval = 1; /* Files are identical */
+
+ fp1 = fopen(fname1, "r");
+ if(!fp1) { return 0; }
+ fp2 = fopen(fname2, "r");
+ if(!fp2) { fclose(fp1); return 0; }
+
+ while((olen = fread(buf[0], 1, sizeof(buf[0]), fp1))) {
+ nlen = fread(buf[1], 1, olen, fp2);
+ if(nlen != olen || memcmp(buf[0], buf[1], nlen)) {
+ retval = 0;
+ break;
+ }
+ }
+ nlen = fread(buf[1], 1, 1, fp2);
+ if(nlen) retval = 0;
+
+ fclose(fp1);
+ fclose(fp2);
+ return retval;
+}
+
/*
* Copy file for real.
*/
@@ -265,9 +329,12 @@ real_copy(const char *src, const char *dst) {
size_t len;
int retval = 0;
- fpsrc = fopen(src, "rb");
+ if(identical_files(src, dst))
+ return retval; /* Success, no need to copy for real. */
+
+ fpsrc = fopen(src, "r");
if(!fpsrc) { errno = EIO; return -1; }
- fpdst = fopen(src, "wb");
+ fpdst = asn1c_open_file(dst, "", 0);
if(!fpdst) { fclose(fpsrc); errno = EIO; return -1; }
while(!feof(fpsrc)) {
diff --git a/libasn1compiler/asn1compiler.h b/libasn1compiler/asn1compiler.h
index 817e06c9..d073517e 100644
--- a/libasn1compiler/asn1compiler.h
+++ b/libasn1compiler/asn1compiler.h
@@ -42,7 +42,7 @@ enum asn1c_flags {
/*
* Generate type_id_PR_member things identifiers of id_PR_member.
*/
- A1C_DOUBLE_IDENTIFIERS = 0x0100,
+ A1C_COMPOUND_NAMES = 0x0100,
};
/*