]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - sim/ppc/lf.c
sim: ppc: drop build-config.h usage
[thirdparty/binutils-gdb.git] / sim / ppc / lf.c
index ba0cc1d8fbc578c12e16ce7957515c06f68186f0..9a9d6151c6e8c6f4001f93f2851aa91ba58b755d 100644 (file)
@@ -4,21 +4,20 @@
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
+    the Free Software Foundation; either version 3 of the License, or
     (at your option) any later version.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
+
     You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-    */
+    along with this program; if not, see <http://www.gnu.org/licenses/>.
 
+    */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <ctype.h>
 #include "misc.h"
 #include "lf.h"
 
-#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
-#endif
+#include <string.h>
 
 struct _lf {
   FILE *stream;
   int line_nr; /* nr complete lines written, curr line is line_nr+1 */
   int indent;
   int line_blank;
-  char *file_name;
-  int number_lines;
+  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;
 };
 
 
 lf *
-lf_open(char *name,
-       char *real_name,
-       int number_lines)
+lf_open(const char *name,
+       const char *real_name,
+       lf_file_references references,
+       lf_file_type type,
+       const char *program)
 {
   /* create a file object */
   lf *new_lf = ZALLOC(lf);
   ASSERT(new_lf != NULL);
-  new_lf->number_lines = number_lines;
-  new_lf->file_name = (real_name == NULL
-                      ? name
-                      : real_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, "-")) {
     new_lf->stream = stdout;
   }
   else {
     /* create a new file */
-    new_lf->stream = fopen(name, "w");
-    ASSERT(new_lf->stream != NULL);
+    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);
+    }
   }
   return new_lf;
 }
@@ -69,20 +80,81 @@ lf_open(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);
 }
 
 
-void
+int
 lf_putchr(lf *file,
          const char chr)
 {
+  int nr = 0;
   if (chr == '\n') {
     file->line_nr += 1;
     file->line_blank = 1;
@@ -91,9 +163,12 @@ lf_putchr(lf *file,
     int pad;
     for (pad = file->indent; pad > 0; pad--)
       putc(' ', file->stream);
+    nr += file->indent;
     file->line_blank = 0;
   }
   putc(chr, file->stream);
+  nr += 1;
+  return nr;
 }
 
 void
@@ -103,52 +178,59 @@ lf_indent_suppress(lf *file)
 }
 
 
-void
+int
 lf_putstr(lf *file,
          const char *string)
 {
+  int nr = 0;
   const char *chp;
   if (string != NULL) {
     for (chp = string; *chp != '\0'; chp++) {
-      lf_putchr(file, *chp);
+      nr += lf_putchr(file, *chp);
     }
   }
+  return nr;
 }
 
-static void
+static int
 do_lf_putunsigned(lf *file,
              unsigned u)
 {
+  int nr = 0;
   if (u > 0) {
-    do_lf_putunsigned(file, u / 10);
-    lf_putchr(file, (u % 10) + '0');
+    nr += do_lf_putunsigned(file, u / 10);
+    nr += lf_putchr(file, (u % 10) + '0');
   }
+  return nr;
 }
 
 
-void
+int
 lf_putint(lf *file,
          int decimal)
 {
+  int nr = 0;
   if (decimal == 0)
-    lf_putchr(file, '0');
+    nr += lf_putchr(file, '0');
   else if (decimal < 0) {
-    lf_putchr(file, '-');
-    do_lf_putunsigned(file, -decimal);
+    nr += lf_putchr(file, '-');
+    nr += do_lf_putunsigned(file, -decimal);
   }
   else if (decimal > 0) {
-    do_lf_putunsigned(file, decimal);
+    nr += do_lf_putunsigned(file, decimal);
   }
   else
     ASSERT(0);
+  return nr;
 }
 
 
-void
+int
 lf_printf(lf *file,
          const char *fmt,
          ...)
 {
+  int nr = 0;
   char buf[1024];
   va_list ap;
 
@@ -156,15 +238,18 @@ lf_printf(lf *file,
   vsprintf(buf, fmt, ap);
   /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
   ASSERT(strlen(buf) > 0 && strlen(buf) < sizeof(buf));
-  lf_putstr(file, buf);
+  nr += lf_putstr(file, buf);
   va_end(ap);
+  return nr;
 }
 
 
-void
-lf_print_c_code(lf *file, char *code)
+int
+lf_print__c_code(lf *file,
+                const char *code)
 {
-  char *chp = code;
+  int nr = 0;
+  const char *chp = code;
   int in_bit_field = 0;
   while (*chp != '\0') {
     if (*chp == '\t')
@@ -174,51 +259,60 @@ lf_print_c_code(lf *file, char *code)
     while (*chp != '\0' && *chp != '\n') {
       if (chp[0] == '{' && !isspace(chp[1])) {
        in_bit_field = 1;
-       lf_putchr(file, '_');
+       nr += lf_putchr(file, '_');
       }
       else if (in_bit_field && chp[0] == ':') {
-       lf_putchr(file, '_');
+       nr += lf_putchr(file, '_');
       }
       else if (in_bit_field && *chp == '}') {
-       lf_putchr(file, '_');
+       nr += lf_putchr(file, '_');
        in_bit_field = 0;
       }
       else {
-       lf_putchr(file, *chp);
+       nr += lf_putchr(file, *chp);
       }
       chp++;
     }
     if (in_bit_field)
       error("bit field paren miss match some where\n");
     if (*chp == '\n') {
-      lf_putchr(file, '\n');
+      nr += lf_putchr(file, '\n');
       chp++;
     }
   }
-  lf_putchr(file, '\n');
+  nr += lf_putchr(file, '\n');
+  return nr;
 }
 
 
-void
-lf_print_c_line_nr(lf *file,
-                  int line_nr,
-                  char *file_name)
+int
+lf_print__external_reference(lf *file,
+                            int line_nr,
+                            const char *file_name)
 {
-  if (file->number_lines) {
+  int nr = 0;
+  switch (file->references) {
+  case lf_include_references:
     lf_indent_suppress(file);
-    lf_putstr(file, "#line ");
-    lf_putint(file, line_nr);
-    lf_putstr(file, " \"");
-    lf_putstr(file, file_name);
-    lf_putstr(file, "\"\n");
+    nr += lf_putstr(file, "#line ");
+    nr += lf_putint(file, line_nr);
+    nr += lf_putstr(file, " \"");
+    nr += lf_putstr(file, file_name);
+    nr += lf_putstr(file, "\"\n");
+    break;
+  case lf_omit_references:
+    break;
   }
+  return nr;
 }
 
-void
-lf_print_lf_c_line_nr(lf *file)
+int
+lf_print__internal_reference(lf *file)
 {
-  lf_print_c_line_nr(file, file->line_nr+2, file->file_name);
+  int nr = 0;
+  nr += lf_print__external_reference(file, file->line_nr+2, file->name);
   /* line_nr == last_line, want to number from next */
+  return nr;
 }
 
 void
@@ -228,46 +322,174 @@ lf_indent(lf *file, int delta)
 }
 
 
-void
-lf_print_copyleft(lf *file)
+int
+lf_print__gnu_copyleft(lf *file)
 {
-  lf_putstr(file, "\
-/*  This file is part of the program psim.
-
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-    --
-
-    This file was generated by the program gen */
-");
+  int nr = 0;
+  switch (file->type) {
+  case lf_is_c:
+  case lf_is_h:
+    nr += lf_printf(file, "\n\
+/*  This file is part of the program psim.\n\
+\n\
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>\n\
+\n\
+    This program is free software; you can redistribute it and/or modify\n\
+    it under the terms of the GNU General Public License as published by\n\
+    the Free Software Foundation; either version 3 of the License, or\n\
+    (at your option) any later version.\n\
+\n\
+    This program is distributed in the hope that it will be useful,\n\
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
+    GNU General Public License for more details.\n\
+\n\
+    You should have received a copy of the GNU General Public License\n\
+    along with this program; if not, see <http://www.gnu.org/licenses/>.\n\
+\n\
+    --\n\
+\n\
+    This file was generated by the program %s */\n\
+", filter_filename(file->program));
+    break;
+  default:
+    ASSERT(0);
+    break;
+  }
+  return nr;
 }
 
 
-void
-lf_print_binary(lf *file, int decimal, int width)
+int
+lf_putbin(lf *file, int decimal, int width)
 {
+  int nr = 0;
   int bit;
   ASSERT(width > 0);
-
   for (bit = 1 << (width-1); bit != 0; bit >>= 1) {
     if (decimal & bit)
-      lf_putchr(file, '1');
+      nr += lf_putchr(file, '1');
+    else
+      nr += lf_putchr(file, '0');
+  }
+  return nr;
+}
+
+int
+lf_print__this_file_is_empty(lf *file)
+{
+  int nr = 0;
+  switch (file->type) {
+  case lf_is_c:
+  case lf_is_h:
+    nr += lf_printf(file,
+                   "/* This generated file (%s) is intentionally left blank */\n",
+                   file->name);
+    break;
+  default:
+    ASSERT(0);
+  }
+  return nr;
+}
+
+int
+lf_print__ucase_filename(lf *file)
+{
+  int nr = 0;
+  const char *chp = file->name;
+  while (*chp != '\0') {
+    char ch = *chp;
+    if (islower(ch)) {
+      nr += lf_putchr(file, toupper(ch));
+    }
+    else if (ch == '.')
+      nr += lf_putchr(file, '_');
     else
-      lf_putchr(file, '0');
+      nr += lf_putchr(file, ch);
+    chp++;
+  }
+  return nr;
+}
+
+int
+lf_print__file_start(lf *file)
+{
+  int nr = 0;
+  switch (file->type) {
+  case lf_is_h:
+  case lf_is_c:
+    nr += lf_print__gnu_copyleft(file);
+    nr += lf_printf(file, "\n");
+    nr += lf_printf(file, "#ifndef _");
+    nr += lf_print__ucase_filename(file);
+    nr += lf_printf(file, "_\n");
+    nr += lf_printf(file, "#define _");
+    nr += lf_print__ucase_filename(file);
+    nr += lf_printf(file, "_\n");
+    nr += lf_printf(file, "\n");
+    break;
+  default:
+    ASSERT(0);
+  }
+  return nr;
+}
+
+
+int
+lf_print__file_finish(lf *file)
+{
+  int nr = 0;
+  switch (file->type) {
+  case lf_is_h:
+  case lf_is_c:
+    nr += lf_printf(file, "\n");
+    nr += lf_printf(file, "#endif /* _");
+    nr += lf_print__ucase_filename(file);
+    nr += lf_printf(file, "_*/\n");
+    break;
+  default:
+    ASSERT(0);
   }
+  return nr;
+}
+
 
+int
+lf_print_function_type(lf *file,
+                      const char *type,
+                      const char *prefix,
+                      const char *trailing_space)
+{
+  int nr = 0;
+  nr += lf_printf(file, "%s\\\n(%s)", prefix, type);
+  if (trailing_space != NULL)
+    nr += lf_printf(file, "%s", trailing_space);
+#if 0
+  const char *type_pointer = strrchr(type, '*');
+  int type_pointer_offset = (type_pointer != NULL
+                            ? type_pointer - type
+                            : 0);
+  if (type_pointer == NULL) {
+    lf_printf(file, "%s %s", type, prefix);
+  }
+  else {
+    char *munged_type = (char*)zalloc(strlen(type)
+                                     + strlen(prefix)
+                                     + strlen(" * ")
+                                     + 1);
+    strcpy(munged_type, type);
+    munged_type[type_pointer_offset] = '\0';
+    if (type_pointer_offset > 0 && type[type_pointer_offset-1] != ' ')
+      strcat(munged_type, " ");
+    strcat(munged_type, prefix);
+    strcat(munged_type, " ");
+    strcat(munged_type, type + type_pointer_offset);
+    lf_printf(file, "%s", munged_type);
+    free(munged_type);
+  }
+  if (trailing_space != NULL && type_pointer_offset < strlen(type) - 1)
+    lf_printf(file, trailing_space);
+#endif
+  return nr;
 }
+