Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add_free_f use now a pointer to a free function
[simgrid.git] / src / gras / DataDesc / ddt_parse.c
index 3a3073e..bad0cb7 100644 (file)
@@ -1,53 +1,54 @@
 /* $Id$ */
 
-/* DataDesc/ddt_parse.c -- automatic parsing of data structures */
+/* DataDesc/ddt_parse.c -- automatic parsing of data structures             */
 
-/* Authors: Arnaud Legrand, Martin Quinson            */
-/* Copyright (C) 2003, 2004 Martin Quinson.                                 */
+/* Copyright (c) 2003 Arnaud Legrand.                                       */
+/* Copyright (c) 2003, 2004 Martin Quinson.                                 */
+/* All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
  under the terms of the license (GNU LGPL) which comes with this package. */
* under the terms of the license (GNU LGPL) which comes with this package. */
 
-#include "DataDesc/datadesc_private.h"
-#include "DataDesc/ddt_parse.yy.h"
+#include <ctype.h> /* isdigit */
 
-GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(parse,datadesc);
+#include "xbt/ex.h"
+#include "gras/DataDesc/datadesc_private.h"
+#include "gras/DataDesc/ddt_parse.yy.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_ddt_parse,gras_ddt,
+  "Parsing C data structures to build GRAS data description");
 
 typedef struct s_type_modifier{
-  short is_unsigned;
-  short is_short;
   short is_long;
+  int is_unsigned:1;
+  int is_short:1;
 
-  short is_struct;
-  short is_union;
-  short is_enum;
+  int is_struct:1;
+  int is_union:1;
+  int is_enum:1;
 
-  short is_ref;
-} type_modifier_t;
+  int is_ref:1;
+   
+  int is_dynar:2;
+  int is_matrix:2;
+} s_type_modifier_t,*type_modifier_t;
 
 typedef struct s_field {
-  gras_datadesc_type_t *type;
+  gras_datadesc_type_t type;
   char *type_name;
   char *name;
-} identifier_t;
+  s_type_modifier_t tm;
+} s_identifier_t;
  
 extern char *gras_ddt_parse_text; /* text being considered in the parser */
 
-/* prototypes */
-static void parse_type_modifier(type_modifier_t        *type_modifier);
-static void print_type_modifier(type_modifier_t                 type_modifier);
-
-static gras_error_t parse_statement(char               *definition,
-                                   gras_dynar_t        **dynar);
-static gras_datadesc_type_t * parse_struct(char        *definition);
-static gras_datadesc_type_t * parse_typedef(char       *definition);
-
 /* local functions */
-static void parse_type_modifier(type_modifier_t        *type_modifier)  {
-  DEBUG0("Parse the modifiers");
+static void parse_type_modifier(type_modifier_t type_modifier)  {
+  XBT_IN;
   do {
     if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
-      DEBUG0("This is a reference");
+      /* This only used when parsing 'short *' since this function returns when int, float, double,... is encountered */
+      DEBUG0("This is a reference"); 
       type_modifier->is_ref++;
       
     } else if (!strcmp(gras_ddt_parse_text,"unsigned")) {
@@ -74,6 +75,9 @@ static void parse_type_modifier(type_modifier_t       *type_modifier)  {
       DEBUG0("This is an enum");
       type_modifier->is_enum = 1;
       
+    } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_EMPTY) {
+      DEBUG0("Pass space");
+
     } else {
       DEBUG1("Done with modifiers (got %s)",gras_ddt_parse_text);
       break;
@@ -82,15 +86,17 @@ static void parse_type_modifier(type_modifier_t     *type_modifier)  {
     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
     if((gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) && 
        (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_STAR)) {
-      DEBUG1("Done with modifiers (got %s)",gras_ddt_parse_text);      
+      DEBUG2("Done with modifiers (got %s,%d)",gras_ddt_parse_text,gras_ddt_parse_tok_num);      
       break;
     }
   } while(1);
+  XBT_OUT;
 }
 
-static void print_type_modifier(type_modifier_t tm) {
+static void print_type_modifier(s_type_modifier_t tm) {
   int i;
 
+  XBT_IN;
   if (tm.is_unsigned)             printf("(unsigned) ");
   if (tm.is_short)                printf("(short) ");
   for (i=0 ; i<tm.is_long ; i++)  printf("(long) ");
@@ -100,62 +106,168 @@ static void print_type_modifier(type_modifier_t tm) {
   if(tm.is_union)                 printf("(union) ");
 
   for (i=0 ; i<tm.is_ref ; i++)   printf("(ref) ");
+  XBT_OUT;
+}
+
+static void change_to_fixed_array(xbt_dynar_t dynar, long int size) {
+  s_identifier_t former,array;
+  memset(&array,0,sizeof(array));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  array.type_name=(char*)xbt_malloc(strlen(former.type->name)+48);
+  DEBUG2("Array specification (size=%ld, elm='%s'), change pushed type",
+        size,former.type_name);
+  sprintf(array.type_name,"%s%s%s%s[%ld]",
+         (former.tm.is_unsigned?"u ":""),
+         (former.tm.is_short?"s ":""),
+         (former.tm.is_long?"l ":""),
+         former.type_name,
+         size);
+  free(former.type_name);
+
+  array.type = gras_datadesc_array_fixed(array.type_name, former.type, size); /* redeclaration are ignored */
+  array.name = former.name;
+
+  xbt_dynar_push(dynar,&array);
+  XBT_OUT;
+}
+static void change_to_ref(xbt_dynar_t dynar) {
+  s_identifier_t former,ref;
+  memset(&ref,0,sizeof(ref));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  ref.type_name=(char*)xbt_malloc(strlen(former.type->name)+2);
+  DEBUG1("Ref specification (elm='%s'), change pushed type", former.type_name);
+  sprintf(ref.type_name,"%s*",former.type_name);
+  free(former.type_name);
+
+  ref.type = gras_datadesc_ref(ref.type_name, former.type); /* redeclaration are ignored */
+  ref.name = former.name;
+
+  xbt_dynar_push(dynar,&ref);
+  XBT_OUT;
+}
+
+static void change_to_ref_pop_array(xbt_dynar_t dynar) {
+  s_identifier_t former,ref;
+  memset(&ref,0,sizeof(ref));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  ref.type = gras_datadesc_ref_pop_arr(former.type); /* redeclaration are ignored */
+  ref.type_name = (char*)strdup(ref.type->name);
+  ref.name = former.name;
+
+  free(former.type_name);
+
+  xbt_dynar_push(dynar,&ref);
+  XBT_OUT;
+}
+
+static void change_to_dynar_of(xbt_dynar_t dynar,gras_datadesc_type_t subtype) {
+  s_identifier_t former,ref;
+  memset(&ref,0,sizeof(ref));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  ref.type = gras_datadesc_dynar(subtype,NULL); /* redeclaration are ignored */
+  ref.type_name = (char*)strdup(ref.type->name);
+  ref.name = former.name;
+
+  free(former.type_name);
+
+  xbt_dynar_push(dynar,&ref);
+  XBT_OUT;
+}
+
+static void change_to_matrix_of(xbt_dynar_t dynar,gras_datadesc_type_t subtype) {
+  s_identifier_t former,ref;
+  memset(&ref,0,sizeof(ref));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  ref.type = gras_datadesc_matrix(subtype,NULL); /* redeclaration are ignored */
+  ref.type_name = (char*)strdup(ref.type->name);
+  ref.name = former.name;
+
+  free(former.type_name);
+
+  xbt_dynar_push(dynar,&ref);
+  XBT_OUT;
+}
+
+/*static void add_free_f(xbt_dynar_t dynar,void_f_pvoid_t free_f) {
+  s_identifier_t former,ref;
+  memset(&ref,0,sizeof(ref));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  memcpy(former.type->extra,&free_f, sizeof(free_f));
+  xbt_dynar_push(dynar,&former);
+  XBT_OUT;
+}*/
+
+static void add_free_f(xbt_dynar_t dynar,void_f_pvoid_t* free_f) {
+  s_identifier_t former,ref;
+  memset(&ref,0,sizeof(ref));
+
+  XBT_IN;
+  xbt_dynar_pop(dynar,&former);
+  memcpy(former.type->extra,free_f, sizeof(free_f));
+  xbt_dynar_push(dynar,&former);
+  XBT_OUT;
 }
 
-static gras_error_t parse_statement(char               *definition,
-                                   gras_dynar_t        **dynar) {
-  gras_error_t errcode;
+static void parse_statement(char        *definition,
+                           xbt_dynar_t  identifiers,
+                           xbt_dynar_t  fields_to_push) {
   char buffname[512];
 
-  identifier_t identifier;
-  type_modifier_t tm;
+  s_identifier_t identifier;
 
-  int starred = 0;
   int expect_id_separator = 0;
 
-  gras_dynar_reset(*dynar);
+  XBT_IN;
   memset(&identifier,0,sizeof(identifier));
-  memset(&tm,0,sizeof(tm));
-    
+
   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
-  if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RP) {
-    return mismatch_error; /* end of the englobing structure or union */
+  if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RA) {
+    XBT_OUT;
+    THROW0(mismatch_error,0,"End of the englobing structure or union");
   }
   
-  if (GRAS_LOG_ISENABLED(parse,gras_log_priority_debug)) {
+  if (XBT_LOG_ISENABLED(gras_ddt_parse,xbt_log_priority_debug)) {
     int colon_pos;
     for (colon_pos = gras_ddt_parse_col_pos;
         definition[colon_pos] != ';';
         colon_pos++);
     definition[colon_pos] = '\0';
-    DEBUG2("Parse the statement \"%s%s;\"",
+    DEBUG3("Parse the statement \"%s%s;\" (col_pos=%d)",
           gras_ddt_parse_text,
-          definition+gras_ddt_parse_col_pos);
+          definition+gras_ddt_parse_col_pos,
+          gras_ddt_parse_col_pos);
     definition[colon_pos] = ';';
   }
 
-  if(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) {
-    ERROR2("Unparsable symbol: found a typeless statement (got '%s' instead). Definition was:\n%s",
-          gras_ddt_parse_text, definition);
-    gras_abort();
-  }
+  if(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
+    PARSE_ERROR1("Unparsable symbol: found a typeless statement (got '%s' instead)",
+                gras_ddt_parse_text);
 
   /**** get the type modifier of this statement ****/
-  parse_type_modifier(&tm);
+  parse_type_modifier(&identifier.tm);
 
   /*  FIXME: This does not detect recursive definitions at all? */
-  if (tm.is_union || tm.is_enum || tm.is_struct) {
-    ERROR1("Cannot handle recursive type definition yet. Definition was:\n%s",
-          definition);
-    gras_abort();
-  }
+  if (identifier.tm.is_union || identifier.tm.is_enum || identifier.tm.is_struct)
+    PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle recursive type definition yet");
 
   /**** get the base type, giving "short a" the needed love ****/
-  if (!tm.is_union &&
-      !tm.is_enum  && 
-      !tm.is_struct &&
+  if (!identifier.tm.is_union &&
+      !identifier.tm.is_enum  && 
+      !identifier.tm.is_struct &&
 
-      (tm.is_short || tm.is_long || tm.is_unsigned) &&
+      (identifier.tm.is_short || identifier.tm.is_long || identifier.tm.is_unsigned) &&
 
       strcmp(gras_ddt_parse_text,"char") && 
       strcmp(gras_ddt_parse_text,"float") && 
@@ -163,39 +275,32 @@ static gras_error_t parse_statement(char          *definition,
       strcmp(gras_ddt_parse_text,"int") ) {
 
     /* bastard user, they omited "int" ! */
-    identifier.type_name=strdup("int");
-    DEBUG0("the base type is 'int', which were omited");
+    identifier.type_name=(char*)strdup("int");
+    DEBUG0("the base type is 'int', which were omited (you vicious user)");
   } else {
-    identifier.type_name=strdup(gras_ddt_parse_text);
+    identifier.type_name=(char*)strdup(gras_ddt_parse_text);
     DEBUG1("the base type is '%s'",identifier.type_name);
     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); 
   }
 
   /**** build the base type for latter use ****/
-  if (tm.is_union) {
-    ERROR1("Cannot handle union yet (need annotation to get the callback). Definition was:\n%s",
-           definition);
-    gras_abort();
+  if (identifier.tm.is_union) {
+    PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle union yet (get callback from annotation?)");
 
-  } else if (tm.is_enum) {
-    ERROR1("Cannot handle enum yet. Definition was:\n%s",
-          definition);
-    gras_abort();
+  } else if (identifier.tm.is_enum) {
+    PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle enum yet");
 
-  } else if (tm.is_struct) {
+  } else if (identifier.tm.is_struct) {
     sprintf(buffname,"struct %s",identifier.type_name);
-    identifier.type = gras_datadesc_by_name(buffname);
-    if (!identifier.type) {
-      TRY(gras_datadesc_declare_struct(buffname,&identifier.type));
-    }
+    identifier.type = gras_datadesc_struct(buffname); /* Get created when does not exist */
 
-  } else if (tm.is_unsigned) {
+  } else if (identifier.tm.is_unsigned) {
     if (!strcmp(identifier.type_name,"int")) {
-      if (tm.is_long == 2) {
+      if (identifier.tm.is_long == 2) {
        identifier.type = gras_datadesc_by_name("unsigned long long int");
-      } else if (tm.is_long) {
+      } else if (identifier.tm.is_long) {
        identifier.type = gras_datadesc_by_name("unsigned long int");
-      } else if (tm.is_short) {
+      } else if (identifier.tm.is_short) {
        identifier.type = gras_datadesc_by_name("unsigned short int");
       } else {
        identifier.type = gras_datadesc_by_name("unsigned int");
@@ -205,7 +310,7 @@ static gras_error_t parse_statement(char            *definition,
       identifier.type = gras_datadesc_by_name("unsigned char");
 
     } else { /* impossible, gcc parses this shit before us */
-      RAISE_IMPOSSIBLE;
+      THROW_IMPOSSIBLE;
     }
     
   } else if (!strcmp(identifier.type_name, "float")) {
@@ -213,19 +318,18 @@ static gras_error_t parse_statement(char          *definition,
     identifier.type = gras_datadesc_by_name("float");
 
   } else if (!strcmp(identifier.type_name, "double")) {
-    if (tm.is_long) {
-      ERROR0("long double not portable and thus not handled");
-      gras_abort();
-    }
+    if (identifier.tm.is_long)
+      PARSE_ERROR0("long double not portable and thus not handled");
+
     identifier.type = gras_datadesc_by_name("double");
 
   } else { /* signed integer elemental */
     if (!strcmp(identifier.type_name,"int")) {
-      if (tm.is_long == 2) {
+      if (identifier.tm.is_long == 2) {
        identifier.type = gras_datadesc_by_name("signed long long int");
-      } else if (tm.is_long) {
+      } else if (identifier.tm.is_long) {
        identifier.type = gras_datadesc_by_name("signed long int");
-      } else if (tm.is_short) {
+      } else if (identifier.tm.is_short) {
        identifier.type = gras_datadesc_by_name("signed short int");
       } else {
        identifier.type = gras_datadesc_by_name("int");
@@ -234,25 +338,30 @@ static gras_error_t parse_statement(char          *definition,
     } else if (!strcmp(identifier.type_name, "char")) {
       identifier.type = gras_datadesc_by_name("char");
 
-    } else { /* impossible */
-      ERROR3("The Impossible did happen at %d:%d of :\n%s",
-            gras_ddt_parse_line_pos,gras_ddt_parse_char_pos,definition);
-      gras_abort();
+    } else { 
+      DEBUG1("Base type is a constructed one (%s)",identifier.type_name);
+      if (!strcmp(identifier.type_name,"xbt_matrix_t")) {
+        identifier.tm.is_matrix = 1;
+      } else if (!strcmp(identifier.type_name,"xbt_dynar_t")) {
+        identifier.tm.is_dynar = 1;
+      } else {       
+        identifier.type = gras_datadesc_by_name(identifier.type_name);
+        if (!identifier.type)
+          PARSE_ERROR1("Unknown base type '%s'",identifier.type_name);
+      }
     }
-    
   } 
+  /* Now identifier.type and identifier.name speak about the base type.
+     Stars are not eaten unless 'int' was omitted.
+     We will have to enhance it if we are in fact asked for array or reference.
+   
+     Dynars and matrices also need some extra love (prodiged as annotations)
+   */
 
-  if (tm.is_ref) {
-    ERROR1("Cannot handle references yet (need annotations), sorry. Definition was:\n%s",
-          definition);
-    gras_abort();
-    /* Should build ref on the current identifier.type (beware of int****) */
-  }
-  
   /**** look for the symbols of this type ****/
   for(expect_id_separator = 0;
 
-      ((gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_EMPTY) &&
+      (/*(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_EMPTY) && FIXME*/
        (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_SEMI_COLON)) ; 
 
       gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()          ) {   
@@ -266,168 +375,295 @@ static gras_error_t parse_statement(char                *definition,
        /* Handle fixed size arrays */
        gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
        if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RB) {
-         ERROR3("Cannot dynamically sized array at %d:%d of %s",
-                gras_ddt_parse_line_pos,gras_ddt_parse_char_pos,
-                definition);
-         gras_abort();
+         PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot deal with [] constructs (yet)");
+
        } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
          char *end;
          long int size=strtol(gras_ddt_parse_text, &end, 10);
-         identifier_t array;
-
-         if (end == gras_ddt_parse_text ||
-             *end != '\0') {
-           ERROR4("Unparsable size of array at %d:%d of %s. Found '%c', expected '\\0'",
-                  gras_ddt_parse_line_pos,gras_ddt_parse_char_pos,
-                  definition,*end);
-           gras_abort();
+
+         if (end == gras_ddt_parse_text || *end != '\0') {
+           /* Not a number. Get the constant value, if any */
+           int *storage=xbt_dict_get_or_null(gras_dd_constants,gras_ddt_parse_text);
+           if (storage) {
+             size = *storage;
+           } else {
+             PARSE_ERROR1("Unparsable size of array. Found '%s', expected number or known constant. Need to use gras_datadesc_set_const(), huh?",
+                          gras_ddt_parse_text);
+           }
          }
+
          /* replace the previously pushed type to an array of it */
-         gras_dynar_pop(*dynar,&identifier.type);
-         array.type_name=malloc(strlen(identifier.type->name)+20);
-         DEBUG2("Array specification (size=%ld, elm='%s'), change pushed type",
-                size,identifier.type_name);
-         sprintf(array.type_name,"%s[%ld]",identifier.type_name,size);
-         free(identifier.type_name);
-         array.type = gras_datadesc_by_name(array.type_name);
-         if (array.type==NULL) {
-           TRY(gras_datadesc_declare_array_fixed(array.type_name,
-                                                 identifier.type,
-                                                 size, &array.type));
-         }
-         array.name = identifier.name;
-         TRY(gras_dynar_push(*dynar,&array));
+         change_to_fixed_array(identifiers,size);
 
          /* eat the closing bracket */
          gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
-         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RB) {
-           ERROR3("Unparsable size of array at %d:%d of %s",
-                  gras_ddt_parse_line_pos,gras_ddt_parse_char_pos,
-                  definition);
-           gras_abort();
-         }
+         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RB)
+           PARSE_ERROR0("Unparsable size of array");
        DEBUG1("Fixed size array, size=%ld",size);
        continue;
        } else {
-         ERROR3("Unparsable size of array at %d:%d of %s",
-                gras_ddt_parse_line_pos,gras_ddt_parse_char_pos,
-                definition);
-         gras_abort();
+         PARSE_ERROR0("Unparsable size of array");
        }
+       /* End of fixed size arrays handling */
+
+      } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
+       /* Handle annotation */
+       s_identifier_t array;
+       char *keyname = NULL;
+       char *keyval  = NULL;
+       memset(&array,0,sizeof(array));
+       if (strcmp(gras_ddt_parse_text,"GRAS_ANNOTE"))
+         PARSE_ERROR1("Unparsable symbol: Expected 'GRAS_ANNOTE', got '%s'",gras_ddt_parse_text);
+       
+       gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
+       if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LP) 
+         PARSE_ERROR1("Unparsable annotation: Expected parenthesis, got '%s'",gras_ddt_parse_text);
+
+       while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
+
+       if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
+         PARSE_ERROR1("Unparsable annotation: Expected key name, got '%s'",gras_ddt_parse_text);
+       keyname = (char*)strdup(gras_ddt_parse_text);
+
+       while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
+
+       if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_COLON) 
+         PARSE_ERROR1("Unparsable annotation: expected ',' after the key name, got '%s'",gras_ddt_parse_text);
+
+       while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
+
+       /* get the value */
+
+       if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
+         PARSE_ERROR1("Unparsable annotation: Expected key value, got '%s'",gras_ddt_parse_text);
+       keyval = (char*)strdup(gras_ddt_parse_text);
+
+       while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
+
+       /* Done with parsing the annotation. Now deal with it by replacing previously pushed type with the right one */
+
+       DEBUG2("Anotation: %s=%s",keyname,keyval);
+       if (!strcmp(keyname,"size")) {
+         free(keyname);
+         if (!identifier.tm.is_ref)
+           PARSE_ERROR0("Size annotation for a field not being a reference");
+         identifier.tm.is_ref--;
+
+         if (!strcmp(keyval,"1")) {
+           change_to_ref(identifiers);
+           free(keyval);
+         } else {
+           char *p;
+           int fixed = 1;
+           for (p = keyval; *p != '\0'; p++) 
+             if (! isdigit(*p) )
+               fixed = 0;
+           if (fixed) {
+             change_to_fixed_array(identifiers,atoi(keyval));
+             change_to_ref(identifiers);
+             free(keyval);
+
+           } else {
+             change_to_ref_pop_array(identifiers);
+             xbt_dynar_push(fields_to_push,&keyval);
+           }
+         }
+       } else if (!strcmp(keyname,"subtype")) {
+          gras_datadesc_type_t subtype = gras_datadesc_by_name(keyval);
+          if (identifier.tm.is_matrix) {
+             change_to_matrix_of(identifiers,subtype);
+             identifier.tm.is_matrix = -1;
+          } else if (identifier.tm.is_dynar) {
+             change_to_dynar_of(identifiers,subtype);
+             identifier.tm.is_dynar = -1;
+          } else {       
+            PARSE_ERROR1("subtype annotation only accepted for dynars and matrices, but passed to '%s'",identifier.type_name);
+          }
+          free(keyval);
+       } else if (!strcmp(keyname,"free_f")) {
+          int *storage=xbt_dict_get_or_null(gras_dd_constants,keyval);
+          if (!storage)
+            PARSE_ERROR1("value for free_f annotation of field %s is not a known constant",identifier.name);
+          if (identifier.tm.is_matrix == -1) {
+             add_free_f(identifiers,*(void_f_pvoid_t**)storage);
+             identifier.tm.is_matrix = 0;
+          } else if (identifier.tm.is_dynar == -1) {
+             add_free_f(identifiers,*(void_f_pvoid_t**)storage);
+             identifier.tm.is_dynar = 0;
+          } else {       
+             PARSE_ERROR1("free_f annotation only accepted for dynars and matrices which subtype is already declared (field %s)",
+                         identifier.name);
+          }
+          free(keyval);
+       } else {
+         free(keyval);
+         PARSE_ERROR1("Unknown annotation type: '%s'",keyname);
+       }
+
+       /* Get all the multipliers */
+       while (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
+
+         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
+
+         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
+           PARSE_ERROR1("Unparsable annotation: Expected field name after '*', got '%s'",gras_ddt_parse_text);
+         
+         keyval = xbt_malloc(strlen(gras_ddt_parse_text)+2);
+         sprintf(keyval,"*%s",gras_ddt_parse_text);
+
+         /* ask caller to push field as a multiplier */
+         xbt_dynar_push(fields_to_push,&keyval);
+
+         /* skip blanks after this block*/
+         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) 
+                 == GRAS_DDT_PARSE_TOKEN_EMPTY );
+       }
+
+       if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RP) 
+         PARSE_ERROR1("Unparsable annotation: Expected parenthesis, got '%s'",
+                      gras_ddt_parse_text);
+
+       continue;
+
+       /* End of annotation handling */
       } else {
-       ERROR2("Unparsable symbol: Expected a comma (','), got '%s' instead. Definition was:\n%s",
-               gras_ddt_parse_text, definition);
-       gras_abort();
+       PARSE_ERROR1("Unparsable symbol: Got '%s' instead of expected comma (',')",gras_ddt_parse_text);
       }
     } else if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
-      ERROR1("Unparsable symbol: Unexpected comma (','). Definition was:\n%s",
-            definition);
-      gras_abort();
+      PARSE_ERROR0("Unparsable symbol: Unexpected comma (',')");
     }
 
-    if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
-      starred = 1;
+    if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
+      identifier.tm.is_ref++; /* We indeed deal with multiple references with multiple annotations */
+      continue;
     }
 
     /* found a symbol name. Build the type and push it to dynar */
     if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
-      if (starred) {
-       /* FIXME: Build a ref or array on the base type */
-       ERROR1("Cannot handle references yet (need annotations), sorry. Definition was:\n%s",
-              definition);
-       gras_abort();
-      }
-      identifier.name=strdup(gras_ddt_parse_text);
+
+      identifier.name=(char*)strdup(gras_ddt_parse_text);
       DEBUG1("Found the identifier \"%s\"",identifier.name);
       
-      TRY(gras_dynar_push(*dynar, &identifier));
-      starred = 0;
+      xbt_dynar_push(identifiers, &identifier);
+      DEBUG1("Dynar_len=%lu",xbt_dynar_length(identifiers));
       expect_id_separator = 1;
       continue;
-    } 
+    }
 
-    ERROR3("Unparasable symbol (maybe a def struct in a def struct or so) at %d:%d of\n%s",
-          gras_ddt_parse_line_pos,gras_ddt_parse_char_pos,
-          definition);
-    gras_abort();
+    PARSE_ERROR0("Unparasable symbol (maybe a def struct in a def struct or a parser bug ;)");
   }
 
-  DEBUG0("End of this statement");
-  return no_error;
+  if (identifier.tm.is_matrix>0) 
+     PARSE_ERROR0("xbt_matrix_t field without 'subtype' annotation");
+  if (identifier.tm.is_dynar>0)
+     PARSE_ERROR0("xbt_dynar_t field without 'subtype' annotation");
+   
+  XBT_OUT;
 }
 
-static gras_datadesc_type_t *parse_struct(char *definition) {
+static gras_datadesc_type_t parse_struct(char *definition) {
+
+  xbt_ex_t e;
 
-  gras_error_t errcode;
   char buffname[32];
   static int anonymous_struct=0;
 
-  gras_dynar_t *fields;
-
-  identifier_t field;
+  xbt_dynar_t identifiers;
+  s_identifier_t field;
   int i;
+  int done;
 
-  gras_datadesc_type_t *struct_type;
+  xbt_dynar_t fields_to_push;
+  char *name;
+
+  gras_datadesc_type_t struct_type;
 
-  errcode=gras_dynar_new(&fields,sizeof(identifier_t),NULL);
-  if (errcode != no_error) 
-    return NULL;
+  XBT_IN;
+  identifiers = xbt_dynar_new(sizeof(s_identifier_t),NULL);
+  fields_to_push = xbt_dynar_new(sizeof(char*),NULL);
 
   /* Create the struct descriptor */
   if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
-    TRYFAIL(gras_datadesc_declare_struct(gras_ddt_parse_text,&struct_type));
-    DEBUG1("Parse the struct '%s'", gras_ddt_parse_text);
+    struct_type = gras_datadesc_struct(gras_ddt_parse_text);
+    VERB1("Parse the struct '%s'", gras_ddt_parse_text);
     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
   } else {
     sprintf(buffname,"anonymous struct %d",anonymous_struct++); 
-    DEBUG1("Parse the anonymous struct nb %d", anonymous_struct);
-    TRYFAIL(gras_datadesc_declare_struct(buffname,&struct_type));
+    VERB1("Parse the anonymous struct nb %d", anonymous_struct);
+    struct_type = gras_datadesc_struct(buffname);
   }
 
-  if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LP) {
-    ERROR2("Unparasable symbol: Expecting struct definition, but got %s instead of '{'. The definition was:\n%s",
-           gras_ddt_parse_text,definition);
-    gras_abort();
-  }
+  if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LA)
+    PARSE_ERROR1("Unparasable symbol: Expecting struct definition, but got %s instead of '{'",
+                gras_ddt_parse_text);
 
-  /* Parse the fields */
-  for (errcode=parse_statement(definition,&fields);
-       errcode == no_error                            ;
-       errcode=parse_statement(definition,&fields)) {
+  /* Parse the identifiers */
+  done = 0;
+  do {
+    TRY {
+      parse_statement(definition,identifiers,fields_to_push);
+    } CATCH(e) {
+      if (e.category != mismatch_error)
+       RETHROW;
+      xbt_ex_free(e);
+      done = 1;
+    }
     
-    DEBUG1("This statement contained %d fields",gras_dynar_length(fields));
-    gras_dynar_foreach(fields,i, field) {
-      DEBUG1("Append field %s",field.name);      
-      TRYFAIL(gras_datadesc_declare_struct_append(struct_type,field.name,
-                                                 field.type));
+    DEBUG1("This statement contained %lu identifiers",xbt_dynar_length(identifiers));
+    /* append the identifiers we've found */
+    xbt_dynar_foreach(identifiers,i, field) {
+      if (field.tm.is_ref)
+       PARSE_ERROR2("Not enough GRAS_ANNOTATE to deal with all dereferencing levels of %s (%d '*' left)",
+                    field.name,field.tm.is_ref);
+
+      VERB2("Append field '%s' to %p",field.name, (void*)struct_type);      
+      gras_datadesc_struct_append(struct_type, field.name, field.type);
       free(field.name);
       free(field.type_name);
+
     }
-  }
-  gras_datadesc_declare_struct_close(struct_type);
-  if (errcode != mismatch_error)
-    return NULL; /* FIXME: LEAK! */
+    xbt_dynar_reset(identifiers);
+    DEBUG1("struct_type=%p",(void*)struct_type);
+    
+    /* Make sure that all fields declaring a size push it into the cbps */
+    xbt_dynar_foreach(fields_to_push,i, name) {
+      DEBUG1("struct_type=%p",(void*)struct_type);
+      if (name[0] == '*') {
+       VERB2("Push field '%s' as a multiplier into size stack of %p",
+             name+1, (void*)struct_type);
+       gras_datadesc_cb_field_push_multiplier(struct_type, name+1);
+      } else {
+       VERB2("Push field '%s' into size stack of %p",
+             name, (void*)struct_type);
+       gras_datadesc_cb_field_push(struct_type, name);
+      }
+      free(name);
+    }
+    xbt_dynar_reset(fields_to_push);
+  } while (!done);
+  gras_datadesc_struct_close(struct_type);
 
   /* terminates */
-  if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RP) {
-    ERROR2("Unparasable symbol: Expected '}' at the end of struct definition, got '%s'. The definition was:\n%s",
-          gras_ddt_parse_text,definition);
-    gras_abort();
-  } 
+  if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RA)
+    PARSE_ERROR1("Unparasable symbol: Expected '}' at the end of struct definition, got '%s'",
+                gras_ddt_parse_text);
 
   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
 
-  gras_dynar_free(fields);
+  xbt_dynar_free(&identifiers);
+  xbt_dynar_free(&fields_to_push);
+  XBT_OUT;
   return struct_type;
 }
 
-static gras_datadesc_type_t parse_typedef(char *definition) {
+static gras_datadesc_type_t parse_typedef(char *definition) {
 
-  type_modifier_t tm;
+  s_type_modifier_t tm;
 
-  gras_datadesc_type_t *struct_desc=NULL;
-  gras_datadesc_type_t *typedef_desc=NULL;
+  gras_datadesc_type_t struct_desc=NULL;
+  gras_datadesc_type_t typedef_desc=NULL;
 
+  XBT_IN;
   memset(&tm,0,sizeof(tm));
 
   /* get the aliased type */
@@ -439,47 +675,42 @@ static gras_datadesc_type_t * parse_typedef(char *definition) {
 
   parse_type_modifier(&tm);
 
-  if (tm.is_ref) {
-    ERROR1("Cannot handle reference without annotation. Definition was:\n%s",
-          definition);
-    gras_abort();
-  }    
+  if (tm.is_ref) 
+    PARSE_ERROR0("GRAS_DEFINE_TYPE cannot handle reference without annotation");
 
   /* get the aliasing name */
-  if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) {
-    ERROR2("Unparsable typedef: Expected the alias name, and got '%s'.\n%s",
-          gras_ddt_parse_text,definition);
-    gras_abort();
-  }
+  if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
+    PARSE_ERROR1("Unparsable typedef: Expected the alias name, and got '%s'",
+                gras_ddt_parse_text);
   
   /* (FIXME: should) build the alias */
-  ERROR1("Cannot handle typedef yet. Definition was: \n%s",definition);
-  gras_abort();
+  PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle typedef yet");
 
-  //  identifier.type=gras_ddt_type_new_typedef(bag, NULL, strdup(gras_ddt_parse_text) );
-  
+  XBT_OUT;
   return typedef_desc;
 }
 
 
 /**
- * gras_datadesc_declare_parse:
+ * gras_datadesc_parse:
  *
  * Create a datadescription from the result of parsing the C type description
  */
-gras_datadesc_type_t *
+gras_datadesc_type_t 
 gras_datadesc_parse(const char            *name,
                    const char            *C_statement) {
 
-  gras_datadesc_type_t res=NULL;
+  gras_datadesc_type_t res=NULL;
   char *definition;
   int semicolon_count=0;
   int def_count,C_count;
+
+  XBT_IN;
   /* reput the \n in place for debug */
   for (C_count=0; C_statement[C_count] != '\0'; C_count++)
     if (C_statement[C_count] == ';' || C_statement[C_count] == '{')
       semicolon_count++;
-  definition = malloc(C_count + semicolon_count + 1);
+  definition = (char*)xbt_malloc(C_count + semicolon_count + 1);
   for (C_count=0,def_count=0; C_statement[C_count] != '\0'; C_count++) {
     definition[def_count++] = C_statement[C_count];
     if (C_statement[C_count] == ';' || C_statement[C_count] == '{') {
@@ -489,7 +720,7 @@ gras_datadesc_parse(const char            *name,
   definition[def_count] = '\0';
 
   /* init */ 
-  VERB1("_gras_ddt_type_parse(%s)",definition);
+  VERB2("_gras_ddt_type_parse(%s) -> %d chars",definition, def_count);
   gras_ddt_parse_pointer_string_init(definition);
 
   /* Do I have a typedef, or a raw struct ?*/
@@ -505,7 +736,7 @@ gras_datadesc_parse(const char            *name,
 
   } else {
     ERROR1("Failed to parse the following symbol (not a struct neither a typedef) :\n%s",definition);    
-    gras_abort();
+    xbt_abort();
   }
 
   gras_ddt_parse_pointer_string_close();
@@ -515,9 +746,18 @@ gras_datadesc_parse(const char            *name,
   if (strcmp(res->name,name)) {
     ERROR2("In GRAS_DEFINE_TYPE, the provided symbol (here %s) must be the C type name (here %s)",
           name,res->name);
-    gras_abort();
+    xbt_abort();
   }    
+  gras_ddt_parse_lex_destroy();
+  XBT_OUT;
   return res;
 }
 
+xbt_dict_t gras_dd_constants;
+/** \brief Declare a constant to the parsing mecanism. See the "\#define and fixed size array" section */
+void gras_datadesc_set_const(const char*name, int value) {
+  int *stored = xbt_new(int, 1);
+  *stored=value;
 
+  xbt_dict_set(gras_dd_constants,name, stored, xbt_free_f); 
+}