Rewrote format_c_type() to deal with all aop_type objects.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Fri, 3 Sep 2010 22:24:21 +0000 (18:24 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Fri, 3 Sep 2010 22:24:21 +0000 (18:24 -0400)
src/aop-type.c

index acf30aa10cd80139d7f0ee283899ea57f19f7c6f..fb42c6cc09bd5fa544f3fed34be525dc97b1ed4c 100644 (file)
@@ -792,11 +792,24 @@ are_types_equal (const struct aop_type *a, const struct aop_type *b)
   return (a == b);
 }
 
+/* Quick-and-dirty printf variant that will output to a buffer without
+   overrunning it. */
+#define BUF_PRINTF(format, ...)                                \
+  do {                                                 \
+    int bytes;                                         \
+    bytes = snprintf (out, size, format, __VA_ARGS__); \
+    out += bytes;                                      \
+    total_bytes += bytes;                              \
+    size -= bytes;                                     \
+  } while (0)
+
 /* C names for special aop_type objects. */
 static const char *all_signed_name = "ALL_SIGNED_T";
 static const char *all_unsigned_name = "ALL_UNSIGNED_T";
 static const char *all_fp_name = "ALL_FP_T";
 static const char *all_pointer_name = "ALL_POINTER_T";
+static const char *signed_char_name = "signed char";
+static const char *unsigned_char_name = "unsigned char";
 
 /* Format an aop_type as a C/C++ typename.  The result is stored in
    the output buffer (n is the size of the buffer).  Returns the
@@ -805,37 +818,94 @@ static const char *all_pointer_name = "ALL_POINTER_T";
 int
 format_c_type (const struct aop_type *type, int n, char *output)
 {
-  int size;
+  /* Initialize these for the sake of BUF_PRINTF. */
+  int total_bytes = 0;
+  int size = n;
+  char *out = output;
 
-  if (type->kind == ATK_ALL_POINTER)
-    {
-      size = snprintf (output, n, "%s", all_pointer_name);
-    }
-  else if (is_all_integer_type (type))
+  switch (type->kind)
     {
-      if (type->kind == ATK_SIGNED_INT)
-       size = snprintf (output, n, "%s", all_signed_name);
-      else if (type->kind == ATK_UNSIGNED_INT)
-       size = snprintf (output, n, "%s", all_unsigned_name);
+    case ATK_SIGNED_INT:
+    case ATK_UNSIGNED_INT:
+      if (type->size == 0)
+       {
+         BUF_PRINTF ("%s", (type->kind == ATK_SIGNED_INT) ? all_signed_name
+                     : all_unsigned_name);
+       }
+      else if (type->size == 1)
+       {
+         /* We special case one byte integers because it looks really
+            awkward to see (int8_t *) when you wanted a (char *). 
+
+            It's ok to do this because the standard guarantees that
+            char == 1 byte.  */
+         BUF_PRINTF ("%s", (type->kind == ATK_SIGNED_INT) ? signed_char_name
+                     : unsigned_char_name);
+       }
       else
-       aop_assert (0); /* Should never happen. */
-    }
-  else if (is_all_fp_type (type))
-    {
-      size = snprintf (output, n, "%s", all_fp_name);
+       {
+         aop_assert (type->size == 2 || type->size == 4 || type->size == 8
+                     || type->size == 16);
+
+         BUF_PRINTF ("%s%d_t", (type->kind == ATK_SIGNED_INT) ? "int" : "uint",
+                     8 * type->size);
+       }
+      break;
+    case ATK_FP:
+      switch (type->size)
+       {
+       case 4:
+         BUF_PRINTF ("%s", "float");
+         break;
+       case 8:
+         BUF_PRINTF ("%s", "double");
+         break;
+       case 16:
+         BUF_PRINTF ("%s", "long double");
+         break;
+       case 0:
+         BUF_PRINTF ("%s", all_fp_name);
+         break;
+       default:
+         /* Invalid size for floating point type. */
+         aop_assert (0);
+       }
+      break;
+    case ATK_ALL_POINTER:
+       BUF_PRINTF ("%s", all_pointer_name);
+      break;
+    case ATK_STRUCT:
+       BUF_PRINTF ("struct %s", type->tag);
+      break;
+    case ATK_UNION:
+       BUF_PRINTF ("union %s", type->tag);
+      break;
+    case ATK_ENUM:
+       BUF_PRINTF ("enum %s", type->tag);
+      break;
+    default:
+      /* Unknown type kind. */
+      aop_assert (0);
     }
-  else
+
+  if (type->pointer_levels > 0)
     {
-      aop_assert (0);  /* Not yet supported. */
+      int i;
+
+      /* What can I say?  It's the C convention. */
+      BUF_PRINTF("%s", " ");
+
+      for (i = 0; i < type->pointer_levels; i++)
+       BUF_PRINTF("%s", "*");
     }
 
   /* Before returning, make absolutely sure that the result is
      NULL-terminated.  Note that snprintf will not terminate a string
      that it has to truncate because of too small buffer. */
-  if (size < n)
-    output[size] = '\0';
+  if (total_bytes < n)
+    output[total_bytes] = '\0';
   else
     output[n - 1] = '\0';
 
-  return size;
+  return total_bytes;
 }