From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) by sourceware.org (Postfix) with ESMTP id 7BB633858D1E for ; Sun, 25 Dec 2022 02:35:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7BB633858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gentoo.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gentoo.org Received: by smtp.gentoo.org (Postfix, from userid 559) id 19C8A33BF01; Sun, 25 Dec 2022 02:35:37 +0000 (UTC) From: Mike Frysinger To: gdb-patches@sourceware.org Subject: [PATCH] sim: igen: support in-place updates ourself Date: Sat, 24 Dec 2022 21:35:30 -0500 Message-Id: <20221225023530.31857-1-vapier@gentoo.org> X-Mailer: git-send-email 2.39.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00,GIT_PATCH_0,JMQ_SPF_NEUTRAL,KAM_DMARC_STATUS,KAM_SHORT,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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. --- sim/igen/lf.c | 79 ++++++++++++++++++++++++++++++++++++++++++----- sim/ppc/lf.c | 85 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 148 insertions(+), 16 deletions(-) diff --git a/sim/igen/lf.c b/sim/igen/lf.c index ca7a56ab0aa3..9316dd6d1588 100644 --- a/sim/igen/lf.c +++ b/sim/igen/lf.c @@ -20,7 +20,7 @@ along with this program. If not, see . */ - +#include #include #include #include @@ -37,7 +37,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; @@ -56,6 +58,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, "-")) @@ -65,7 +68,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); @@ -86,15 +93,73 @@ lf_get_file_type (const lf *file) void lf_close (lf *file) { - if (file->stream != stdout) + 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) { - if (fclose (file->stream)) + off_t len; + + fseek (fp, 0, SEEK_END); + len = ftell (fp); + + if (len == ftell (file->stream)) { - perror ("lf_close.fclose"); + 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); + } + + 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); } + + free (file->tmpname); + free (file); } diff --git a/sim/ppc/lf.c b/sim/ppc/lf.c index c40de5b5c5db..e170a47b0902 100644 --- a/sim/ppc/lf.c +++ b/sim/ppc/lf.c @@ -17,7 +17,7 @@ */ - +#include #include #include #include @@ -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); } -- 2.39.0