+# ifdef PTO_COLOR
+/* set a nice color to an object descriptor */
+static void pto_name_set_obj_color (obj_desc_t *obj_desc, int col_idx)
+{
+ int i;
+
+ for (i = 0; i < obj_desc->n_fields; i ++) {
+ qset_t *ptos = obj_desc->values [i];
+
+ desc_t *tgt = (desc_t*) qset_start (ptos);
+
+ while (NULL != tgt) {
+ pto_name_set_color (tgt, col_idx);
+
+ tgt = (desc_t*) qset_next (ptos);
+ }
+ }
+}
+
+/* set a nice color to an array descriptor */
+static void pto_name_set_arr_color (arr_desc_t *arr_desc, int col_idx)
+{
+ qset_t *ptos = arr_desc->value;
+
+ desc_t *tgt = (desc_t*) qset_start (ptos);
+
+ while (NULL != tgt) {
+ pto_name_set_color (tgt, col_idx);
+
+ tgt = (desc_t*) qset_next (ptos);
+ }
+}
+
+/* set a nice color to a descriptor */
+static void pto_name_set_color (desc_t *desc, int col_idx)
+{
+ /* assert (0 == desc->col_idx); */
+
+ desc->col_idx = col_idx;
+
+ if (FALSE == desc->visit) {
+ desc->visit = TRUE;
+ if (object == desc->kind) {
+ pto_name_set_obj_color ((obj_desc_t*) desc, col_idx);
+ } else if (array == desc->kind) {
+ pto_name_set_arr_color ((arr_desc_t*) desc, col_idx);
+ }
+
+ desc->visit = FALSE;
+ }
+}
+
+
+/* allocate nice colors for an object descriptor */
+static int pto_name_alloc_obj_color (obj_desc_t *obj_desc)
+{
+ int i;
+ int col_idx = 0;
+
+ for (i = 0; (0 == col_idx) && (i < obj_desc->n_fields); i ++) {
+ qset_t *ptos = obj_desc->values [i];
+ desc_t *tgt = (desc_t*) qset_start (ptos);
+
+ while ((0 == col_idx) && (NULL != tgt)) {
+ col_idx = pto_name_alloc_color (tgt);
+
+ tgt = (desc_t*) qset_next (ptos);
+ }
+ }
+
+ return (col_idx);
+}
+
+/* allocate nice colors for an array descriptor */
+static int pto_name_alloc_arr_color (arr_desc_t *arr_desc)
+{
+ int col_idx = 0;
+
+ qset_t *ptos = arr_desc->value;
+
+ desc_t *tgt = (desc_t*) qset_start (ptos);
+
+ while ((NULL != tgt) && (0 == col_idx)) {
+ col_idx = pto_name_alloc_color (tgt);
+ tgt = (desc_t*) qset_next (ptos);
+ }
+
+ return (col_idx);
+}
+
+/* allocate nice colors for the given descriptor */
+static int pto_name_alloc_color (desc_t *desc)
+{
+ int col_idx = 0;
+
+ if (0 != desc->col_idx) {
+ return (desc->col_idx);
+ }
+
+ if (FALSE == desc->visit) {
+ desc->visit = TRUE;
+ if (object == desc->kind) {
+ col_idx = pto_name_alloc_obj_color ((obj_desc_t*) desc);
+ } else if (array == desc->kind) {
+ col_idx = pto_name_alloc_arr_color ((arr_desc_t*) desc);
+ }
+ desc->visit = FALSE;
+ }
+
+ if (0 == col_idx) {
+ col_idx = ++ last_col_idx;
+ }
+
+ pto_name_set_color (desc, col_idx);
+
+ return (col_idx);
+}
+
+/* allocate nice colors */
+static void pto_name_alloc_colors (void)
+{
+ desc_t *desc = all_descs;
+
+ while (NULL != desc) {
+ pto_name_alloc_color (desc);
+
+ desc = desc->prev;
+ }
+}
+# endif /* defined PTO_COLOR */
+
+/* See whether the given entity is a field. */
+static int is_field (entity *ent)
+{
+ ir_type *tp = get_entity_type (ent);
+
+ if (is_Primitive_type (tp) || is_Pointer_type (tp)) {
+ /* actually, we don't get by by restricting ourselves to pointer types */
+ return (TRUE);
+ } else {
+ return (FALSE);
+ }
+}
+
+/* Helper to collect_fields(ir_type*): collect all fields of the given
+ clazz and its super classes into the given obstack. */
+static void _collect_fields (ir_type *clazz, struct obstack *obst)
+{
+ int n_members = get_class_n_members (clazz);
+ int n_supers = get_class_n_supertypes (clazz);
+ int i;
+
+ for (i = 0; i < n_members; i ++) {
+ entity *ent = get_class_member (clazz, i);
+
+ if (is_field (ent)) {
+ if (allocation_static != get_entity_allocation (ent)) {
+ obstack_ptr_grow (obst, ent);
+ }
+ }
+ }
+
+ for (i = 0; i < n_supers; i ++) {
+ ir_type *s_clazz = get_class_supertype (clazz, i);
+
+ _collect_fields (s_clazz, obst);
+ }
+}
+
+/* Collect the fields of the given class and its super classes into an array.
+ The last entry of the array is written NULL. */
+static entity **collect_fields (ir_type *clazz)
+{
+ struct obstack obst;
+ int n_fields;
+ entity ** fields;
+ void *tmp;
+
+ if (NULL != get_type_link (clazz)) {
+ DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
+ __FUNCTION__,
+ get_type_name (clazz)));
+
+ return ((entity **) get_type_link (clazz));
+ } else {
+ DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
+ __FUNCTION__,
+ get_type_name (clazz)));
+ }
+
+ obstack_init (&obst);
+
+ _collect_fields (clazz, &obst);
+
+ /* append terminating NULL */
+ obstack_ptr_grow (&obst, NULL);
+
+ n_fields = obstack_object_size (&obst) / sizeof (void*);
+
+ fields = NALLOC (n_fields * sizeof (entity*));
+ tmp = obstack_finish(&obst);
+
+ memcpy (fields, tmp, n_fields * sizeof (entity*));
+
+ obstack_free (&obst, NULL);
+
+ set_type_link (clazz, fields);
+
+ return (fields);
+}
+
+/* Write the intro text for a name dump into the given stream */
+static void pto_name_dump_start (FILE *stream)
+{
+# ifdef PTO_COLOR
+ pto_name_alloc_colors ();
+# endif /* defined PTO_COLOR */
+
+ fprintf (stream, "digraph \"Names\" {\n");
+ fprintf (stream, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11,7\", rotate=\"90\"];\n");
+ fprintf (stream, "\tnode [shape=\"record\", style=\"filled\"];\n");
+ fprintf (stream, "\tedge [color=\"black\"];\n");
+ fprintf (stream, "\n");
+}
+
+/* Write the extro text for a name dump into the given stream */
+static void pto_name_dump_finish (FILE *stream)
+{
+ fprintf (stream, "}\n");
+}
+
+/* Write a node for the given descriptor into the given stream */
+static void pto_name_dump_desc (desc_t *desc, FILE *stream)
+{
+ ir_type *tp = desc->tp;
+ const char *tp_name = get_type_name (tp);
+ ir_node *nd;
+
+ fprintf (stream, "\t/* %s \"%s\" */\n",
+ object == desc->kind ? "Object" : "Array",
+ tp_name);
+
+ fprintf (stream, "\tdesc_%i [label=\"<HEAD>type \\[%i\\]",
+ desc->id, desc->id);
+
+ if (-1 != desc->ctx) {
+ fprintf (stream, ", ctx = %i", desc->ctx);
+ } else {
+ fprintf (stream, " (global)");
+ }
+
+ fprintf (stream, "\\lname=\\\"%s\\\"",
+ tp_name);
+
+ nd = desc->node;
+
+ if (NULL != nd) {
+ ir_graph *graph = get_irn_irg (nd);
+ entity *method = get_irg_entity (graph);
+ const char *ent_name = get_entity_name (method);
+ const char *own_name = get_type_name (get_entity_owner (method));
+
+ fprintf (stream, "\\lnode=%s\\[%li\\]",
+ get_op_name (get_irn_op (nd)),
+ get_irn_node_nr (nd));
+ fprintf (stream, "\\lgraph=\\\"%s.%s\\\"",
+ own_name,
+ ent_name);
+ }
+
+ if (desc->kind == object) {
+ obj_desc_t *obj_desc = (obj_desc_t*) desc;
+
+ int i;
+ for (i = 0; i < obj_desc->n_fields; i ++) {
+ entity *field = obj_desc->fields [i];
+
+ if (is_Pointer_type (get_entity_type (field))) {
+ const char *ent_name = get_entity_name (field);
+
+ fprintf (stream, "|<%i>%s", i, ent_name);
+ }
+ }
+ } else if (array == desc->kind) {
+ fprintf (stream, "|<arr>[]");
+ } else {
+ assert (0 && "invalid descriptor");
+ }
+
+ /* end label string */
+ fprintf (stream, "\"");
+
+# ifdef PTO_COLOR
+ {
+ const char *fontcolor;
+ int col_idx = desc->col_idx;
+ float hue = (float) col_idx / (float) last_col_idx;
+ float sat = 1.000f; /* 0.300 .. 1.000 */
+ float val = 0.800f; /* 0.300 .. 1.000 */
+
+ # define MAX_COLORS 12
+ if (last_col_idx > MAX_COLORS) {
+ /* too many colors ... vary value too */
+ float div = (float) MAX_COLORS / (float) last_col_idx;
+
+ sat = (div * ((col_idx / MAX_COLORS)));
+ val = (div * ((col_idx / MAX_COLORS)));
+
+ col_idx = col_idx % MAX_COLORS;
+ hue = (float) col_idx / (float) MAX_COLORS;
+
+ // re-adjust sat and val
+ {
+ const float sat_min = 0.200f; /* 0.200 .. 0.400 */
+ const float val_min = 0.300f; /* 0.300 .. 0.400 */
+
+ sat = sat_min + ((1.0f - sat_min) * sat);
+ val = val_min + ((1.0f - val_min) * val);
+ }
+ }
+ # undef MAX_COLORS
+
+ fprintf (stream, ", color=\"%01.3f, %01.3f, %01.3f\"", hue, sat, val);
+
+ if ((hue > 0.3) && (sat < 0.5)) {
+ fontcolor = "white";
+ } else if (sat < 0.4) {
+ fontcolor = "white";
+ } else {
+ fontcolor = "black";
+ }
+
+ fprintf (stream, ", fontcolor=\"%s\"", fontcolor);
+ }
+# else /* if defined PTO_COLOR */
+ fprintf (stream, ", color=\"lightgrey\"");
+# endif /* defined PTO_COLOR */
+
+ /* end attributes */
+ fprintf (stream, "];\n");
+ fprintf (stream, "\n");
+
+ /* now the edges */
+ if (desc->kind == object) {
+ obj_desc_t *obj_desc = (obj_desc_t*) desc;
+
+ int i;
+ for (i = 0; i < obj_desc->n_fields; i ++) {
+ desc_t *tgt = (desc_t*) qset_start (obj_desc->values [i]);
+
+ while (NULL != tgt) {
+ fprintf (stream, "\tdesc_%i:%i -> desc_%i:HEAD;\n",
+ desc->id, i, tgt->id);
+
+ tgt = (desc_t*) qset_next (obj_desc->values [i]);
+ }
+ }
+ } else if (array == desc->kind) {
+ arr_desc_t *arr_desc = (arr_desc_t*) desc;
+
+ desc_t *tgt = (desc_t*) qset_start (arr_desc->value);
+
+ while (NULL != tgt) {
+ fprintf (stream, "\tdesc_%i:arr -> desc_%i:HEAD;\n",
+ desc->id, tgt->id);
+
+ tgt = (desc_t*) qset_next (arr_desc->value);
+ }
+ }
+
+ fprintf (stream, "\n");
+}