From: Mike Frysinger <vapier@gentoo.org>
To: gdb-patches@sourceware.org
Subject: [PATCH] sim: igen: support in-place updates ourself
Date: Sat, 24 Dec 2022 21:35:30 -0500 [thread overview]
Message-ID: <20221225023530.31857-1-vapier@gentoo.org> (raw)
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 <http://www.gnu.org/licenses/>. */
-
+#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
@@ -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 <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);
}
--
2.39.0
next reply other threads:[~2022-12-25 2:35 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-25 2:35 Mike Frysinger [this message]
2022-12-25 2:37 ` [PATCH] sim: igen: drop move-if-changed usage Mike Frysinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221225023530.31857-1-vapier@gentoo.org \
--to=vapier@gentoo.org \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).