diff options
author | Mike Frysinger <vapier@gentoo.org> | 2022-12-24 15:02:00 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2022-12-24 21:33:24 -0500 |
commit | a5f08108c14ed37cd9f71e0828876d96e9de46da (patch) | |
tree | e9e7f127f5c80defb349db29e9f1fb078298ca22 /sim/ppc | |
parent | 5d3539bd6bbd9cbd0fa1e09d93632ff08822f1c2 (diff) | |
download | fsf-binutils-gdb-a5f08108c14ed37cd9f71e0828876d96e9de46da.zip fsf-binutils-gdb-a5f08108c14ed37cd9f71e0828876d96e9de46da.tar.gz fsf-binutils-gdb-a5f08108c14ed37cd9f71e0828876d96e9de46da.tar.bz2 |
sim: igen: support in-place updates ourself
Every file that igen outputs is then processed with the move-if-changed
shell script. This creates a lot of boilerplate in the build and not an
insignificant amount of build-time overhead. Move the simple "is the file
changed" logic into igen itself.
Diffstat (limited to 'sim/ppc')
-rw-r--r-- | sim/ppc/lf.c | 85 |
1 files changed, 76 insertions, 9 deletions
diff --git a/sim/ppc/lf.c b/sim/ppc/lf.c index c40de5b..e170a47 100644 --- a/sim/ppc/lf.c +++ b/sim/ppc/lf.c @@ -17,7 +17,7 @@ */ - +#include <stdbool.h> #include <stdio.h> #include <stdarg.h> #include <ctype.h> @@ -34,7 +34,9 @@ struct _lf { int line_nr; /* nr complete lines written, curr line is line_nr+1 */ int indent; int line_blank; - const char *name; + const char *name; /* Output name with diagnostics. */ + const char *filename; /* Output filename. */ + char *tmpname; /* Temporary output filename. */ const char *program; lf_file_references references; lf_file_type type; @@ -54,6 +56,7 @@ lf_open(const char *name, new_lf->references = references; new_lf->type = type; new_lf->name = (real_name == NULL ? name : real_name); + new_lf->filename = name; new_lf->program = program; /* attach to stdout if pipe */ if (!strcmp(name, "-")) { @@ -61,7 +64,11 @@ lf_open(const char *name, } else { /* create a new file */ - new_lf->stream = fopen(name, "w"); + char *tmpname = zalloc (strlen (name) + 5); + sprintf (tmpname, "%s.tmp", name); + new_lf->filename = name; + new_lf->tmpname = tmpname; + new_lf->stream = fopen(tmpname, "w+"); if (new_lf->stream == NULL) { perror(name); exit(1); @@ -74,13 +81,73 @@ lf_open(const char *name, void lf_close(lf *file) { - if (file->stream != stdout) { - if (fclose(file->stream)) { - perror("lf_close.fclose"); - exit(1); + FILE *fp; + bool update = true; + + /* If we wrote to stdout, no house keeping needed. */ + if (file->stream == stdout) + return; + + /* Rename the temp file to the real file if it's changed. */ + fp = fopen (file->filename, "r"); + if (fp != NULL) + { + off_t len; + + fseek (fp, 0, SEEK_END); + len = ftell (fp); + + if (len == ftell (file->stream)) + { + off_t off; + size_t cnt; + char *oldbuf = zalloc (len); + char *newbuf = zalloc (len); + + rewind (fp); + off = 0; + while ((cnt = fread (oldbuf + off, 1, len - off, fp)) > 0) + off += cnt; + ASSERT (off == len); + + rewind (file->stream); + off = 0; + while ((cnt = fread (newbuf + off, 1, len - off, file->stream)) > 0) + off += cnt; + ASSERT (off == len); + + if (memcmp (oldbuf, newbuf, len) == 0) + update = false; + } + + fclose (fp); } - free(file); - } + + if (fclose (file->stream)) + { + perror ("lf_close.fclose"); + exit (1); + } + + if (update) + { + if (rename (file->tmpname, file->filename) != 0) + { + perror ("lf_close.rename"); + exit (1); + } + } + else + { + if (remove (file->tmpname) != 0) + { + perror ("lf_close.unlink"); + exit (1); + } + } + + free (file->tmpname); + free (file); } |