Skip to content

Commit a5f0810

Browse files
committed
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.
1 parent 5d3539b commit a5f0810

File tree

2 files changed

+148
-16
lines changed

2 files changed

+148
-16
lines changed

sim/igen/lf.c

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
along with this program. If not, see <http://www.gnu.org/licenses/>. */
2121

2222

23-
23+
#include <stdbool.h>
2424
#include <stdio.h>
2525
#include <stdarg.h>
2626
#include <ctype.h>
@@ -37,7 +37,9 @@ struct _lf
3737
int line_nr; /* nr complete lines written, curr line is line_nr+1 */
3838
int indent;
3939
int line_blank;
40-
const char *name;
40+
const char *name; /* Output name with diagnostics. */
41+
const char *filename; /* Output filename. */
42+
char *tmpname; /* Temporary output filename. */
4143
const char *program;
4244
lf_file_references references;
4345
lf_file_type type;
@@ -56,6 +58,7 @@ lf_open (const char *name,
5658
new_lf->references = references;
5759
new_lf->type = type;
5860
new_lf->name = (real_name == NULL ? name : real_name);
61+
new_lf->filename = name;
5962
new_lf->program = program;
6063
/* attach to stdout if pipe */
6164
if (!strcmp (name, "-"))
@@ -65,7 +68,11 @@ lf_open (const char *name,
6568
else
6669
{
6770
/* create a new file */
68-
new_lf->stream = fopen (name, "w");
71+
char *tmpname = zalloc (strlen (name) + 5);
72+
sprintf (tmpname, "%s.tmp", name);
73+
new_lf->filename = name;
74+
new_lf->tmpname = tmpname;
75+
new_lf->stream = fopen (tmpname, "w+");
6976
if (new_lf->stream == NULL)
7077
{
7178
perror (name);
@@ -86,15 +93,73 @@ lf_get_file_type (const lf *file)
8693
void
8794
lf_close (lf *file)
8895
{
89-
if (file->stream != stdout)
96+
FILE *fp;
97+
bool update = true;
98+
99+
/* If we wrote to stdout, no house keeping needed. */
100+
if (file->stream == stdout)
101+
return;
102+
103+
/* Rename the temp file to the real file if it's changed. */
104+
fp = fopen (file->filename, "r");
105+
if (fp != NULL)
90106
{
91-
if (fclose (file->stream))
107+
off_t len;
108+
109+
fseek (fp, 0, SEEK_END);
110+
len = ftell (fp);
111+
112+
if (len == ftell (file->stream))
92113
{
93-
perror ("lf_close.fclose");
114+
off_t off;
115+
size_t cnt;
116+
char *oldbuf = zalloc (len);
117+
char *newbuf = zalloc (len);
118+
119+
rewind (fp);
120+
off = 0;
121+
while ((cnt = fread (oldbuf + off, 1, len - off, fp)) > 0)
122+
off += cnt;
123+
ASSERT (off == len);
124+
125+
rewind (file->stream);
126+
off = 0;
127+
while ((cnt = fread (newbuf + off, 1, len - off, file->stream)) > 0)
128+
off += cnt;
129+
ASSERT (off == len);
130+
131+
if (memcmp (oldbuf, newbuf, len) == 0)
132+
update = false;
133+
}
134+
135+
fclose (fp);
136+
}
137+
138+
if (fclose (file->stream))
139+
{
140+
perror ("lf_close.fclose");
141+
exit (1);
142+
}
143+
144+
if (update)
145+
{
146+
if (rename (file->tmpname, file->filename) != 0)
147+
{
148+
perror ("lf_close.rename");
149+
exit (1);
150+
}
151+
}
152+
else
153+
{
154+
if (remove (file->tmpname) != 0)
155+
{
156+
perror ("lf_close.unlink");
94157
exit (1);
95158
}
96-
free (file);
97159
}
160+
161+
free (file->tmpname);
162+
free (file);
98163
}
99164

100165

sim/ppc/lf.c

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
1818
*/
1919

20-
20+
#include <stdbool.h>
2121
#include <stdio.h>
2222
#include <stdarg.h>
2323
#include <ctype.h>
@@ -34,7 +34,9 @@ struct _lf {
3434
int line_nr; /* nr complete lines written, curr line is line_nr+1 */
3535
int indent;
3636
int line_blank;
37-
const char *name;
37+
const char *name; /* Output name with diagnostics. */
38+
const char *filename; /* Output filename. */
39+
char *tmpname; /* Temporary output filename. */
3840
const char *program;
3941
lf_file_references references;
4042
lf_file_type type;
@@ -54,14 +56,19 @@ lf_open(const char *name,
5456
new_lf->references = references;
5557
new_lf->type = type;
5658
new_lf->name = (real_name == NULL ? name : real_name);
59+
new_lf->filename = name;
5760
new_lf->program = program;
5861
/* attach to stdout if pipe */
5962
if (!strcmp(name, "-")) {
6063
new_lf->stream = stdout;
6164
}
6265
else {
6366
/* create a new file */
64-
new_lf->stream = fopen(name, "w");
67+
char *tmpname = zalloc (strlen (name) + 5);
68+
sprintf (tmpname, "%s.tmp", name);
69+
new_lf->filename = name;
70+
new_lf->tmpname = tmpname;
71+
new_lf->stream = fopen(tmpname, "w+");
6572
if (new_lf->stream == NULL) {
6673
perror(name);
6774
exit(1);
@@ -74,13 +81,73 @@ lf_open(const char *name,
7481
void
7582
lf_close(lf *file)
7683
{
77-
if (file->stream != stdout) {
78-
if (fclose(file->stream)) {
79-
perror("lf_close.fclose");
80-
exit(1);
84+
FILE *fp;
85+
bool update = true;
86+
87+
/* If we wrote to stdout, no house keeping needed. */
88+
if (file->stream == stdout)
89+
return;
90+
91+
/* Rename the temp file to the real file if it's changed. */
92+
fp = fopen (file->filename, "r");
93+
if (fp != NULL)
94+
{
95+
off_t len;
96+
97+
fseek (fp, 0, SEEK_END);
98+
len = ftell (fp);
99+
100+
if (len == ftell (file->stream))
101+
{
102+
off_t off;
103+
size_t cnt;
104+
char *oldbuf = zalloc (len);
105+
char *newbuf = zalloc (len);
106+
107+
rewind (fp);
108+
off = 0;
109+
while ((cnt = fread (oldbuf + off, 1, len - off, fp)) > 0)
110+
off += cnt;
111+
ASSERT (off == len);
112+
113+
rewind (file->stream);
114+
off = 0;
115+
while ((cnt = fread (newbuf + off, 1, len - off, file->stream)) > 0)
116+
off += cnt;
117+
ASSERT (off == len);
118+
119+
if (memcmp (oldbuf, newbuf, len) == 0)
120+
update = false;
121+
}
122+
123+
fclose (fp);
81124
}
82-
free(file);
83-
}
125+
126+
if (fclose (file->stream))
127+
{
128+
perror ("lf_close.fclose");
129+
exit (1);
130+
}
131+
132+
if (update)
133+
{
134+
if (rename (file->tmpname, file->filename) != 0)
135+
{
136+
perror ("lf_close.rename");
137+
exit (1);
138+
}
139+
}
140+
else
141+
{
142+
if (remove (file->tmpname) != 0)
143+
{
144+
perror ("lf_close.unlink");
145+
exit (1);
146+
}
147+
}
148+
149+
free (file->tmpname);
150+
free (file);
84151
}
85152

86153

0 commit comments

Comments
 (0)