summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-08-02 21:44:04 +0100
committerVincent Sanders <vince@kyllikki.org>2015-08-02 21:44:04 +0100
commit780d7c53a8479b62fe8d90e16a3045187e347cc7 (patch)
tree7d1766aea3d80fdfa21e0779acb520ff05a80dcb /src
parentcf89528fc6668e6d07b6e99db0069c9fe1f6e05d (diff)
downloadnsgenbind-780d7c53a8479b62fe8d90e16a3045187e347cc7.tar.gz
nsgenbind-780d7c53a8479b62fe8d90e16a3045187e347cc7.tar.bz2
generates files with temporary name and only overwites on change
Diffstat (limited to 'src')
-rw-r--r--src/duk-libdom.c35
-rw-r--r--src/utils.c149
-rw-r--r--src/utils.h14
3 files changed, 158 insertions, 40 deletions
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index bc27dfc..3e2fbe4 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -366,7 +366,7 @@ static FILE *open_header(struct interface_map *interface_map, const char *name)
snprintf(fname, fnamel, "%s.h", name);
/* open output file */
- hdrf = genb_fopen(fname, "w");
+ hdrf = genb_fopen_tmp(fname);
free(fname);
if (hdrf == NULL) {
return NULL;
@@ -387,8 +387,17 @@ static FILE *open_header(struct interface_map *interface_map, const char *name)
return hdrf;
}
-static int close_header(struct interface_map *interface_map, FILE *hdrf)
+static int close_header(struct interface_map *interface_map,
+ FILE *hdrf,
+ const char *name)
{
+ char *fname;
+ int fnamel;
+
+ fnamel = strlen(name) + 4;
+ fname = malloc(fnamel);
+ snprintf(fname, fnamel, "%s.h", name);
+
fprintf(hdrf, "\n#endif\n");
/* binding postface */
@@ -396,7 +405,8 @@ static int close_header(struct interface_map *interface_map, FILE *hdrf)
interface_map->binding_node,
GENBIND_NODE_TYPE_POSTFACE);
- fclose(hdrf);
+ genb_fclose_tmp(hdrf, fname);
+ free(fname);
return 0;
}
@@ -1056,7 +1066,7 @@ static int output_interface(struct interface_map *interface_map,
"%s.c", interfacee->class_name);
/* open output file */
- ifacef = genb_fopen(interfacee->filename, "w");
+ ifacef = genb_fopen_tmp(interfacee->filename);
if (ifacef == NULL) {
return -1;
}
@@ -1131,7 +1141,7 @@ static int output_interface(struct interface_map *interface_map,
GENBIND_NODE_TYPE_POSTFACE);
op_error:
- fclose(ifacef);
+ genb_fclose_tmp(ifacef, interfacee->filename);
return res;
}
@@ -1193,7 +1203,7 @@ output_private_header(struct interface_map *interface_map)
}
- close_header(interface_map, privf);
+ close_header(interface_map, privf, "private");
return 0;
}
@@ -1249,7 +1259,7 @@ output_prototype_header(struct interface_map *interface_map)
fprintf(protof, ";\n\n");
}
- close_header(interface_map, protof);
+ close_header(interface_map, protof, "prototype");
return 0;
}
@@ -1264,7 +1274,7 @@ output_makefile(struct interface_map *interface_map)
FILE *makef;
/* open output file */
- makef = genb_fopen("Makefile", "w");
+ makef = genb_fopen_tmp("Makefile");
if (makef == NULL) {
return -1;
}
@@ -1286,7 +1296,7 @@ output_makefile(struct interface_map *interface_map)
}
fprintf(makef, "\nNSGENBIND_PREFIX:=%s\n", options->outdirname);
- fclose(makef);
+ genb_fclose_tmp(makef, "Makefile");
return 0;
}
@@ -1331,7 +1341,7 @@ output_binding_header(struct interface_map *interface_map)
fprintf(bindf,
"duk_ret_t %s_create_prototypes(duk_context *ctx);\n", DLPFX);
- close_header(interface_map, bindf);
+ close_header(interface_map, bindf, "binding");
return 0;
}
@@ -1352,7 +1362,7 @@ output_binding_src(struct interface_map *interface_map)
char *proto_name;
/* open output file */
- bindf = genb_fopen("binding.c", "w");
+ bindf = genb_fopen_tmp("binding.c");
if (bindf == NULL) {
return -1;
}
@@ -1523,7 +1533,8 @@ output_binding_src(struct interface_map *interface_map)
interface_map->binding_node,
GENBIND_NODE_TYPE_POSTFACE);
- fclose(bindf);
+ genb_fclose_tmp(bindf, "binding.c");
+
return 0;
}
diff --git a/src/utils.c b/src/utils.c
index 9e50a93..1e8ec23 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,3 +1,11 @@
+/* utility functions
+ *
+ * This file is part of nsgenbind.
+ * Published under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ */
+
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
@@ -10,34 +18,120 @@
/* exported function documented in utils.h */
char *genb_fpath(const char *fname)
{
- char *fpath;
- int fpathl;
+ char *fpath;
+ int fpathl;
+
+ fpathl = strlen(options->outdirname) + strlen(fname) + 2;
+ fpath = malloc(fpathl);
+ snprintf(fpath, fpathl, "%s/%s", options->outdirname, fname);
+
+ return fpath;
+}
+
+static char *genb_fpath_tmp(const char *fname)
+{
+ char *fpath;
+ int fpathl;
- fpathl = strlen(options->outdirname) + strlen(fname) + 2;
- fpath = malloc(fpathl);
- snprintf(fpath, fpathl, "%s/%s", options->outdirname, fname);
+ fpathl = strlen(options->outdirname) + strlen(fname) + 3;
+ fpath = malloc(fpathl);
+ snprintf(fpath, fpathl, "%s/%s~", options->outdirname, fname);
- return fpath;
+ return fpath;
}
/* exported function documented in utils.h */
FILE *genb_fopen(const char *fname, const char *mode)
{
- char *fpath;
- FILE *filef;
+ char *fpath;
+ FILE *filef;
+
+ fpath = genb_fpath(fname);
+
+ filef = fopen(fpath, mode);
+ if (filef == NULL) {
+ fprintf(stderr, "Error: unable to open file %s (%s)\n",
+ fpath, strerror(errno));
+ free(fpath);
+ return NULL;
+ }
+ free(fpath);
+
+ return filef;
+}
+
+/* exported function documented in utils.h */
+FILE *genb_fopen_tmp(const char *fname)
+{
+ char *fpath;
+ FILE *filef;
+
+ fpath = genb_fpath_tmp(fname);
+
+ filef = fopen(fpath, "w+");
+ if (filef == NULL) {
+ fprintf(stderr, "Error: unable to open file %s (%s)\n",
+ fpath, strerror(errno));
+ free(fpath);
+ return NULL;
+ }
+ free(fpath);
- fpath = genb_fpath(fname);
+ return filef;
+}
- filef = fopen(fpath, mode);
- if (filef == NULL) {
- fprintf(stderr, "Error: unable to open file %s (%s)\n",
- fpath, strerror(errno));
+int genb_fclose_tmp(FILE *filef_tmp, const char *fname)
+{
+ char *fpath;
+ char *tpath;
+ FILE *filef;
+ char tbuf[1024];
+ char fbuf[1024];
+ size_t trd;
+ size_t frd;
+
+ fpath = genb_fpath(fname);
+ tpath = genb_fpath_tmp(fname);
+
+ filef = fopen(fpath, "r");
+ if (filef == NULL) {
+ /* unable to open target file for comparison */
+
+ fclose(filef_tmp); /* close tmpfile */
+
+ remove(fpath);
+ rename(tpath, fpath);
+ } else {
+ rewind(filef_tmp);
+
+ frd = fread(fbuf, 1, 1024, filef);
+ while (frd != 0) {
+ trd = fread(tbuf, 1, frd, filef_tmp);
+ if ((trd != frd) ||
+ (memcmp(tbuf, fbuf, trd) != 0)) {
+ /* file doesnt match */
+ fclose(filef_tmp);
+
+ remove(fpath);
+ rename(tpath, fpath);
+
+ goto close_done;
+ }
+
+ frd = fread(fbuf, 1, 1024, filef);
+ }
+
+ /* was the same kill temporary file */
+ fclose(filef_tmp);
+ fclose(filef);
+ remove(tpath);
+ }
+
+close_done:
free(fpath);
- return NULL;
- }
- free(fpath);
+ free(tpath);
- return filef;
+ return 0;
}
@@ -45,20 +139,19 @@ FILE *genb_fopen(const char *fname, const char *mode)
char *strndup(const char *s, size_t n)
{
- size_t len;
- char *s2;
+ size_t len;
+ char *s2;
- for (len = 0; len != n && s[len]; len++)
- continue;
+ for (len = 0; len != n && s[len]; len++)
+ continue;
- s2 = malloc(len + 1);
- if (!s2)
- return 0;
+ s2 = malloc(len + 1);
+ if (!s2)
+ return 0;
- memcpy(s2, s, len);
- s2[len] = 0;
- return s2;
+ memcpy(s2, s, len);
+ s2[len] = 0;
+ return s2;
}
#endif
-
diff --git a/src/utils.h b/src/utils.h
index b37d755..508d1c1 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -22,6 +22,20 @@ char *genb_fpath(const char *fname);
*/
FILE *genb_fopen(const char *fname, const char *mode);
+/**
+ * Open file allowing for output path prefix
+ *
+ * file is opened for reading/writing with a temporary suffix allowing for the
+ * matching close call to check the output is different before touching the
+ * target file.
+ */
+FILE *genb_fopen_tmp(const char *fname);
+
+/**
+ * Close file opened with genb_fopen
+ */
+int genb_fclose_tmp(FILE *filef, const char *fname);
+
#ifdef _WIN32
#define NEED_STRNDUP 1
char *strndup(const char *s, size_t n);