* valops.c (value_one): Reimplement broken decimal-float case.
[deliverable/binutils-gdb.git] / gas / listing.c
index 61ef6f55e40f94acc29a8d38abcf6aa6cba8ade0..e307be21c9a3b77c9533d1af95eedbb91156fa68 100644 (file)
@@ -1,13 +1,13 @@
 /* listing.c - maintain assembly listings
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2005
+   2001, 2002, 2003, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS 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, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -94,6 +94,8 @@
 #include "safe-ctype.h"
 #include "input-file.h"
 #include "subsegs.h"
+#include "bfdver.h"
+#include <time.h>
 
 #ifndef NO_LISTING
 
 #ifndef LISTING_LHS_CONT_LINES
 #define LISTING_LHS_CONT_LINES 4
 #endif
+#define MAX_DATELEN 30
 
 /* This structure remembers which .s were used.  */
 typedef struct file_info_struct
@@ -335,13 +338,18 @@ listing_newline (char *ps)
          char *copy;
          int len;
          int seen_quote = 0;
+         int seen_slash = 0;
 
          for (copy = input_line_pointer - 1;
               *copy && (seen_quote
-                        || (! is_end_of_line [(unsigned char) *copy]));
+                        || is_end_of_line [(unsigned char) *copy] != 1);
               copy++)
-           if (*copy == '"' && copy[-1] != '\\')
-             seen_quote = ! seen_quote;
+           {
+             if (*copy == '\\')
+               seen_slash = ! seen_slash;
+             else if (*copy == '"' && seen_slash)
+               seen_quote = ! seen_quote;
+           }
 
          len = (copy - input_line_pointer) + 2;
 
@@ -468,8 +476,10 @@ buffer_line (file_info_type *file, char *line, unsigned int size)
          fclose (last_open_file);
        }
 
+      /* Open the file in the binary mode so that ftell above can
+        return a reliable value that we can feed to fseek below.  */
       last_open_file_info = file;
-      last_open_file = fopen (file->filename, FOPEN_RT);
+      last_open_file = fopen (file->filename, FOPEN_RB);
       if (last_open_file == NULL)
        {
          file->at_end = 1;
@@ -486,7 +496,7 @@ buffer_line (file_info_type *file, char *line, unsigned int size)
   /* Leave room for null.  */
   size -= 1;
 
-  while (c != EOF && c != '\n')
+  while (c != EOF && c != '\n' && c != '\r')
     {
       if (count < size)
        *p++ = c;
@@ -495,6 +505,17 @@ buffer_line (file_info_type *file, char *line, unsigned int size)
       c = fgetc (last_open_file);
 
     }
+
+  /* If '\r' is followed by '\n', swallow that.  Likewise, if '\n'
+     is followed by '\r', swallow that as well.  */
+  if (c == '\r' || c == '\n')
+    {
+      int next = fgetc (last_open_file);
+      if ((c == '\r' && next != '\n')
+         || (c == '\n' && next != '\r'))
+       ungetc (next, last_open_file);
+    }
+
   if (c == EOF)
     {
       file->at_end = 1;
@@ -946,15 +967,6 @@ listing_listing (char *name ATTRIBUTE_UNUSED)
   buffer = xmalloc (listing_rhs_width);
   data_buffer = xmalloc (MAX_BYTES);
   eject = 1;
-  list = head;
-
-  while (list != (list_info_type *) NULL && 0)
-    {
-      if (list->next)
-       list->frag = list->next->frag;
-      list = list->next;
-    }
-
   list = head->next;
 
   while (list)
@@ -1065,8 +1077,93 @@ listing_listing (char *name ATTRIBUTE_UNUSED)
   data_buffer = NULL;
 }
 
+/* Print time stamp in ISO format:  yyyy-mm-ddThh:mm:ss.ss+/-zzzz.  */
+
+static void
+print_timestamp (void)
+{
+  const time_t now = time (NULL);
+  struct tm * timestamp;
+  char stampstr[MAX_DATELEN];
+
+  /* Any portable way to obtain subsecond values???  */
+  timestamp = localtime (&now);
+  strftime (stampstr, MAX_DATELEN, "%Y-%m-%dT%H:%M:%S.000%z", timestamp);
+  fprintf (list_file, _("\n time stamp    \t: %s\n\n"), stampstr);
+}
+
+static void
+print_single_option (char * opt, int *pos)
+{
+  int opt_len = strlen (opt);
+
+   if ((*pos + opt_len) < paper_width)
+     {
+        fprintf (list_file, _("%s "), opt);
+        *pos = *pos + opt_len;
+     }
+   else
+     {
+        fprintf (list_file, _("\n\t%s "), opt);
+        *pos = opt_len;
+     }
+}
+
+/* Print options passed to as.  */
+
+static void
+print_options (char ** argv)
+{
+  const char *field_name = _("\n options passed\t: ");
+  int pos = strlen (field_name);
+  char **p;
+
+  fputs (field_name, list_file);
+  for (p = &argv[1]; *p != NULL; p++)
+    if (**p == '-')
+      {
+        /* Ignore these.  */
+        if (strcmp (*p, "-o") == 0)
+          {
+            if (p[1] != NULL)
+              p++;
+            continue;
+          }
+        if (strcmp (*p, "-v") == 0)
+          continue;
+
+        print_single_option (*p, &pos);
+      }
+}
+
+/* Print a first section with basic info like file names, as version,
+   options passed, target, and timestamp.
+   The format of this section is as follows:
+
+   AS VERSION
+
+   fieldname TAB ':' fieldcontents
+  { TAB fieldcontents-cont }  */
+
+static void
+listing_general_info (char ** argv)
+{
+  /* Print the stuff on the first line.  */
+  eject = 1;
+  listing_page (0);
+
+  fprintf (list_file,
+           _(" GNU assembler version %s (%s)\n\t using BFD version %s."),
+           VERSION, TARGET_ALIAS, BFD_VERSION_STRING);
+  print_options (argv);
+  fprintf (list_file, _("\n input file    \t: %s"), fn);
+  fprintf (list_file, _("\n output file   \t: %s"), out_file_name);
+  fprintf (list_file, _("\n target        \t: %s"), TARGET_CANONICAL);
+  print_timestamp ();
+}
+
 void
-listing_print (char *name)
+listing_print (char *name, char **argv)
 {
   int using_stdout;
 
@@ -1085,8 +1182,7 @@ listing_print (char *name)
        using_stdout = 0;
       else
        {
-         bfd_set_error (bfd_error_system_call);
-         as_perror (_("can't open list file: %s"), name);
+         as_warn (_("can't open %s: %s"), name, xstrerror (errno));
          list_file = stdout;
          using_stdout = 1;
        }
@@ -1095,6 +1191,9 @@ listing_print (char *name)
   if (listing & LISTING_NOFORM)
     paper_height = 0;
 
+  if (listing & LISTING_GENERAL)
+    listing_general_info (argv);
+
   if (listing & LISTING_LISTING)
     listing_listing (name);
 
@@ -1104,10 +1203,7 @@ listing_print (char *name)
   if (! using_stdout)
     {
       if (fclose (list_file) == EOF)
-       {
-         bfd_set_error (bfd_error_system_call);
-         as_perror (_("error closing list file: %s"), name);
-       }
+       as_warn (_("can't close %s: %s"), name, xstrerror (errno));
     }
 
   if (last_open_file)
This page took 0.029711 seconds and 4 git commands to generate.