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.
This commit is contained in:
parent
5d3539bd6b
commit
a5f08108c1
@ -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);
|
||||
}
|
||||
free (file);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (remove (file->tmpname) != 0)
|
||||
{
|
||||
perror ("lf_close.unlink");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
free (file->tmpname);
|
||||
free (file);
|
||||
}
|
||||
|
||||
|
||||
|
85
sim/ppc/lf.c
85
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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user