diff --git a/common/utils/T/tracer/database.c b/common/utils/T/tracer/database.c
index 59d8cbdc852cca264fe2222bb8792954cd920c0d..e2362f8f081ce700b17fbcffb08db95f035955e1 100644
--- a/common/utils/T/tracer/database.c
+++ b/common/utils/T/tracer/database.c
@@ -8,8 +8,11 @@ typedef struct {
   char *name;
   char *desc;
   char **groups;
-  int size;
-  int id;
+  int  gsize;
+  char **arg_type;
+  char **arg_name;
+  int  asize;
+  int  id;
 } id;
 
 typedef struct {
@@ -129,7 +132,10 @@ id *add_id(database *r, char *idname, int i)
   if (r->i[r->isize].name == NULL) { printf("out of memory\n"); exit(1); }
   r->i[r->isize].desc = NULL;
   r->i[r->isize].groups = NULL;
-  r->i[r->isize].size = 0;
+  r->i[r->isize].gsize = 0;
+  r->i[r->isize].arg_type = NULL;
+  r->i[r->isize].arg_name = NULL;
+  r->i[r->isize].asize = 0;
   r->i[r->isize].id = i;
   r->isize++;
   qsort(r->i, r->isize, sizeof(id), id_cmp);
@@ -172,16 +178,16 @@ void group_add_id(group *g, char *id)
 
 void id_add_group(id *i, char *group)
 {
-  char *g = bsearch(&group, i->groups, i->size, sizeof(char *), string_cmp);
+  char *g = bsearch(&group, i->groups, i->gsize, sizeof(char *), string_cmp);
   if (g != NULL) return;
 
-  if ((i->size & 1023) == 0) {
-    i->groups = realloc(i->groups, (i->size+1024) * sizeof(char *));
+  if ((i->gsize & 1023) == 0) {
+    i->groups = realloc(i->groups, (i->gsize+1024) * sizeof(char *));
     if (i->groups == NULL) abort();
   }
-  i->groups[i->size] = group;
-  i->size++;
-  qsort(i->groups, i->size, sizeof(char *), string_cmp);
+  i->groups[i->gsize] = group;
+  i->gsize++;
+  qsort(i->groups, i->gsize, sizeof(char *), string_cmp);
 }
 
 void add_groups(database *r, id *i, char *groups)
@@ -216,6 +222,76 @@ void add_desc(id *i, char *desc)
   i->desc = strdup(desc); if (i->desc == NULL) abort();
 }
 
+char *format_get_next_token(char **cur)
+{
+  char *start;
+  char *end;
+  char *ret;
+
+  start = *cur;
+
+  /* remove spaces */
+  while (*start && isspace(*start)) start ++;
+  if (*start == 0) return NULL;
+
+  /* special cases: ',' and ':' */
+  if (*start == ',' || *start == ':') { end = start + 1; goto special; }
+
+  end = start;
+
+  /* go to end of token */
+  while (*end && !isspace(*end) && *end != ',' && *end != ':') end++;
+
+special:
+  ret = malloc(end-start+1); if (ret == NULL) abort();
+  memcpy(ret, start, end-start);
+  ret[end-start] = 0;
+
+  *cur = end;
+  return ret;
+}
+
+void add_format(id *id, char *format)
+{
+  char *cur = format;
+  char *type;
+  char *name;
+  char *sep;
+  while (1) {
+    /* parse next type/name: expected " <type> , <name> :" */
+    /* get type */
+    type = format_get_next_token(&cur);
+    if (type == NULL) break;
+    /* get comma */
+    sep = format_get_next_token(&cur);
+    if (sep == NULL || strcmp(sep, ",") != 0) goto error;
+    free(sep);
+    /* get name */
+    name = format_get_next_token(&cur);
+    if (name == NULL) goto error;
+    /* if there is a next token it has to be : */
+    sep = format_get_next_token(&cur);
+    if (sep != NULL && strcmp(sep, ":") != 0) goto error;
+    free(sep);
+
+    /* add type/name */
+    if (id->asize % 64 == 0) {
+      id->arg_type = realloc(id->arg_type, (id->asize + 64) * sizeof(char *));
+      if (id->arg_type == NULL) abort();
+      id->arg_name = realloc(id->arg_name, (id->asize + 64) * sizeof(char *));
+      if (id->arg_name == NULL) abort();
+    }
+    id->arg_type[id->asize] = type;
+    id->arg_name[id->asize] = name;
+    id->asize++;
+  }
+  return;
+
+error:
+  printf("bad format '%s'\n", format);
+  abort();
+}
+
 void *parse_database(char *filename)
 {
   FILE *in;
@@ -241,6 +317,7 @@ void *parse_database(char *filename)
     if (!strcmp(name, "ID")) { last_id = add_id(r, value, i); i++; }
     if (!strcmp(name, "GROUP")) add_groups(r, last_id, value);
     if (!strcmp(name, "DESC")) add_desc(last_id, value);
+    if (!strcmp(name, "FORMAT")) add_format(last_id, value);
   }
 
   fclose(in);
@@ -260,9 +337,18 @@ void dump_database(void *_d)
     int j;
     printf("ID %s [%s] [in %d group%s]\n",
            d->i[i].name, d->i[i].desc ? d->i[i].desc : "",
-           d->i[i].size, d->i[i].size > 1 ? "s" : "");
-    for (j = 0; j < d->i[i].size; j++)
+           d->i[i].gsize, d->i[i].gsize > 1 ? "s" : "");
+    for (j = 0; j < d->i[i].gsize; j++)
       printf("    in GROUP: %s\n", d->i[i].groups[j]);
+    if (d->i[i].asize == 0) printf("    no FORMAT\n");
+    else {
+      int j;
+      printf("    FORMAT: ");
+      for (j = 0; j < d->i[i].asize; j++)
+        printf("'%s' , '%s' %s", d->i[i].arg_type[j], d->i[i].arg_name[j],
+               j == d->i[i].asize-1 ? "" : " : ");
+      printf("\n");
+    }
   }
   for (i = 0; i < d->gsize; i++) {
     int j;