* dwarf2read.c (follow_die_ref): Add comment.
[deliverable/binutils-gdb.git] / gdb / utils.c
index 92248391eedf49b3eb7711552ac14d4b92451ad0..4396d145df7326b71cf3b49183ef8620eebfcc8b 100644 (file)
 #include <sys/time.h>
 #include <time.h>
 
+#include "gdb_usleep.h"
+
 #if !HAVE_DECL_MALLOC
-extern PTR malloc ();          /* OK: PTR */
+extern PTR malloc ();          /* ARI: PTR */
 #endif
 #if !HAVE_DECL_REALLOC
-extern PTR realloc ();         /* OK: PTR */
+extern PTR realloc ();         /* ARI: PTR */
 #endif
 #if !HAVE_DECL_FREE
 extern void free ();
@@ -271,6 +273,23 @@ make_cleanup_fclose (FILE *file)
   return make_cleanup (do_fclose_cleanup, file);
 }
 
+/* Helper function which does the work for make_cleanup_obstack_free.  */
+
+static void
+do_obstack_free (void *arg)
+{
+  struct obstack *ob = arg;
+  obstack_free (ob, NULL);
+}
+
+/* Return a new cleanup that frees OBSTACK.  */
+
+struct cleanup *
+make_cleanup_obstack_free (struct obstack *obstack)
+{
+  return make_cleanup (do_obstack_free, obstack);
+}
+
 static void
 do_ui_file_delete (void *arg)
 {
@@ -1184,7 +1203,7 @@ nomem (long size)
 /* NOTE: These are declared using PTR to ensure consistency with
    "libiberty.h".  xfree() is GDB local.  */
 
-PTR                            /* OK: PTR */
+PTR                            /* ARI: PTR */
 xmalloc (size_t size)
 {
   void *val;
@@ -1194,7 +1213,7 @@ xmalloc (size_t size)
   if (size == 0)
     size = 1;
 
-  val = malloc (size);         /* OK: malloc */
+  val = malloc (size);         /* ARI: malloc */
   if (val == NULL)
     nomem (size);
 
@@ -1207,8 +1226,8 @@ xzalloc (size_t size)
   return xcalloc (1, size);
 }
 
-PTR                            /* OK: PTR */
-xrealloc (PTR ptr, size_t size)        /* OK: PTR */
+PTR                            /* ARI: PTR */
+xrealloc (PTR ptr, size_t size)        /* ARI: PTR */
 {
   void *val;
 
@@ -1218,16 +1237,16 @@ xrealloc (PTR ptr, size_t size) /* OK: PTR */
     size = 1;
 
   if (ptr != NULL)
-    val = realloc (ptr, size); /* OK: realloc */
+    val = realloc (ptr, size); /* ARI: realloc */
   else
-    val = malloc (size);               /* OK: malloc */
+    val = malloc (size);               /* ARI: malloc */
   if (val == NULL)
     nomem (size);
 
   return (val);
 }
 
-PTR                            /* OK: PTR */
+PTR                            /* ARI: PTR */
 xcalloc (size_t number, size_t size)
 {
   void *mem;
@@ -1240,7 +1259,7 @@ xcalloc (size_t number, size_t size)
       size = 1;
     }
 
-  mem = calloc (number, size);         /* OK: xcalloc */
+  mem = calloc (number, size);         /* ARI: xcalloc */
   if (mem == NULL)
     nomem (number * size);
 
@@ -1251,7 +1270,7 @@ void
 xfree (void *ptr)
 {
   if (ptr != NULL)
-    free (ptr);                /* OK: free */
+    free (ptr);                /* ARI: free */
 }
 \f
 
@@ -1460,6 +1479,25 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
       gdb_flush (gdb_stdout);
 
       answer = fgetc (stdin);
+
+      /* We expect fgetc to block until a character is read.  But
+         this may not be the case if the terminal was opened with
+         the NONBLOCK flag.  In that case, if there is nothing to
+         read on stdin, fgetc returns EOF, but also sets the error
+         condition flag on stdin and errno to EAGAIN.  With a true
+         EOF, stdin's error condition flag is not set.
+
+         A situation where this behavior was observed is a pseudo
+         terminal on AIX.  */
+      while (answer == EOF && ferror (stdin) && errno == EAGAIN)
+        {
+          /* Not a real EOF.  Wait a little while and try again until
+             we read something.  */
+          clearerr (stdin);
+          gdb_usleep (10000);
+          answer = fgetc (stdin);
+        }
+
       clearerr (stdin);                /* in case of C-d */
       if (answer == EOF)       /* C-d */
        {
@@ -1554,21 +1592,33 @@ query (const char *ctlstr, ...)
   va_end (args);
 }
 
-/* Print an error message saying that we couldn't make sense of a
-   \^mumble sequence in a string or character constant.  START and END
-   indicate a substring of some larger string that contains the
-   erroneous backslash sequence, missing the initial backslash.  */
-static NORETURN int
-no_control_char_error (const char *start, const char *end)
+/* A helper for parse_escape that converts a host character to a
+   target character.  C is the host character.  If conversion is
+   possible, then the target character is stored in *TARGET_C and the
+   function returns 1.  Otherwise, the function returns 0.  */
+
+static int
+host_char_to_target (int c, int *target_c)
 {
-  int len = end - start;
-  char *copy = alloca (end - start + 1);
+  struct obstack host_data;
+  char the_char = c;
+  struct cleanup *cleanups;
+  int result = 0;
 
-  memcpy (copy, start, len);
-  copy[len] = '\0';
+  obstack_init (&host_data);
+  cleanups = make_cleanup_obstack_free (&host_data);
 
-  error (_("There is no control character `\\%s' in the `%s' character set."),
-        copy, target_charset ());
+  convert_between_encodings (target_charset (), host_charset (),
+                            &the_char, 1, 1, &host_data, translit_none);
+
+  if (obstack_object_size (&host_data) == 1)
+    {
+      result = 1;
+      *target_c = *(char *) obstack_base (&host_data);
+    }
+
+  do_cleanups (cleanups);
+  return result;
 }
 
 /* Parse a C escape sequence.  STRING_PTR points to a variable
@@ -1589,55 +1639,15 @@ no_control_char_error (const char *start, const char *end)
 int
 parse_escape (char **string_ptr)
 {
-  int target_char;
+  int target_char = -2;        /* initialize to avoid GCC warnings */
   int c = *(*string_ptr)++;
-  if (c_parse_backslash (c, &target_char))
-    return target_char;
-  else
-    switch (c)
-      {
+  switch (c)
+    {
       case '\n':
        return -2;
       case 0:
        (*string_ptr)--;
        return 0;
-      case '^':
-       {
-         /* Remember where this escape sequence started, for reporting
-            errors.  */
-         char *sequence_start_pos = *string_ptr - 1;
-
-         c = *(*string_ptr)++;
-
-         if (c == '?')
-           {
-             /* XXXCHARSET: What is `delete' in the host character set?  */
-             c = 0177;
-
-             if (!host_char_to_target (c, &target_char))
-               error (_("There is no character corresponding to `Delete' "
-                      "in the target character set `%s'."), host_charset ());
-
-             return target_char;
-           }
-         else if (c == '\\')
-           target_char = parse_escape (string_ptr);
-         else
-           {
-             if (!host_char_to_target (c, &target_char))
-               no_control_char_error (sequence_start_pos, *string_ptr);
-           }
-
-         /* Now target_char is something like `c', and we want to find
-            its control-character equivalent.  */
-         if (!target_char_to_control_char (target_char, &target_char))
-           no_control_char_error (sequence_start_pos, *string_ptr);
-
-         return target_char;
-       }
-
-       /* XXXCHARSET: we need to use isdigit and value-of-digit
-          methods of the host character set here.  */
 
       case '0':
       case '1':
@@ -1648,16 +1658,16 @@ parse_escape (char **string_ptr)
       case '6':
       case '7':
        {
-         int i = c - '0';
+         int i = host_hex_value (c);
          int count = 0;
          while (++count < 3)
            {
              c = (**string_ptr);
-             if (c >= '0' && c <= '7')
+             if (isdigit (c) && c != '8' && c != '9')
                {
                  (*string_ptr)++;
                  i *= 8;
-                 i += c - '0';
+                 i += host_hex_value (c);
                }
              else
                {
@@ -1666,14 +1676,39 @@ parse_escape (char **string_ptr)
            }
          return i;
        }
-      default:
-       if (!host_char_to_target (c, &target_char))
-         error
-           ("The escape sequence `\%c' is equivalent to plain `%c', which"
-            " has no equivalent\n" "in the `%s' character set.", c, c,
-            target_charset ());
-       return target_char;
-      }
+
+    case 'a':
+      c = '\a';
+      break;
+    case 'b':
+      c = '\b';
+      break;
+    case 'f':
+      c = '\f';
+      break;
+    case 'n':
+      c = '\n';
+      break;
+    case 'r':
+      c = '\r';
+      break;
+    case 't':
+      c = '\t';
+      break;
+    case 'v':
+      c = '\v';
+      break;
+
+    default:
+      break;
+    }
+
+  if (!host_char_to_target (c, &target_char))
+    error
+      ("The escape sequence `\%c' is equivalent to plain `%c', which"
+       " has no equivalent\n" "in the `%s' character set.", c, c,
+       target_charset ());
+  return target_char;
 }
 \f
 /* Print the character C on STREAM as part of the contents of a literal
This page took 0.027823 seconds and 4 git commands to generate.