From: mquinson Date: Sun, 11 Jul 2004 22:39:39 +0000 (+0000) Subject: First version of the structure parsing macro, and associated stuff X-Git-Tag: v3.3~5099 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/5b0c21a63f0957fb6c02b7c025a8f33dbd932842 First version of the structure parsing macro, and associated stuff git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@247 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- diff --git a/src/gras/DataDesc/ddt_parse.c b/src/gras/DataDesc/ddt_parse.c new file mode 100644 index 0000000000..6745833276 --- /dev/null +++ b/src/gras/DataDesc/ddt_parse.c @@ -0,0 +1,522 @@ +/* $Id$ */ + +/* DataDesc/ddt_parse.c -- automatic parsing of data structures */ + +/* Authors: Arnaud Legrand, Martin Quinson */ +/* Copyright (C) 2003, 2004 Martin Quinson. */ + +/* 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. */ + +#include "DataDesc/datadesc_private.h" +#include "DataDesc/ddt_parse.yy.h" + +GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(parse,datadesc); + +typedef struct s_type_modifier{ + short is_unsigned; + short is_short; + short is_long; + + short is_struct; + short is_union; + short is_enum; + + short is_ref; +} type_modifier_t; + +typedef struct s_field { + gras_datadesc_type_t *type; + char *type_name; + char *name; +} 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"); + do { + if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) { + DEBUG0("This is a reference"); + type_modifier->is_ref++; + + } else if (!strcmp(gras_ddt_parse_text,"unsigned")) { + DEBUG0("This is an unsigned"); + type_modifier->is_unsigned = 1; + + } else if (!strcmp(gras_ddt_parse_text,"short")) { + DEBUG0("This is short"); + type_modifier->is_short = 1; + + } else if (!strcmp(gras_ddt_parse_text,"long")) { + DEBUG0("This is long"); + type_modifier->is_long++; /* handle "long long" */ + + } else if (!strcmp(gras_ddt_parse_text,"struct")) { + DEBUG0("This is a struct"); + type_modifier->is_struct = 1; + + } else if (!strcmp(gras_ddt_parse_text,"union")) { + DEBUG0("This is an union"); + type_modifier->is_union = 1; + + } else if (!strcmp(gras_ddt_parse_text,"enum")) { + DEBUG0("This is an enum"); + type_modifier->is_enum = 1; + + } else { + DEBUG1("Done with modifiers (got %s)",gras_ddt_parse_text); + break; + } + + 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); + break; + } + } while(1); +} + +static void print_type_modifier(type_modifier_t tm) { + int i; + + if (tm.is_unsigned) printf("(unsigned) "); + if (tm.is_short) printf("(short) "); + for (i=0 ; iname)+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)); + + /* 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(); + } + DEBUG1("Fixed size array, size=%d",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(); + } + } else { + ERROR2("Unparsable symbol: Expected a comma (','), got '%s' instead. Definition was:\n%s", + gras_ddt_parse_text, definition); + gras_abort(); + } + } else if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) { + ERROR1("Unparsable symbol: Unexpected comma (','). Definition was:\n%s", + definition); + gras_abort(); + } + + if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) { + starred = 1; + } + + /* 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); + DEBUG1("Found the identifier \"%s\"",identifier.name); + + TRY(gras_dynar_push(*dynar, &identifier)); + starred = 0; + 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(); + } + + DEBUG0("End of this statement"); + return no_error; +} + +static gras_datadesc_type_t *parse_struct(char *definition) { + + gras_error_t errcode; + char buffname[32]; + static int anonymous_struct=0; + + gras_dynar_t *fields; + + identifier_t field; + int i; + + gras_datadesc_type_t *struct_type; + + errcode=gras_dynar_new(&fields,sizeof(identifier_t),NULL); + if (errcode != no_error) + return 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); + 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)); + } + + 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(); + } + + /* Parse the fields */ + for (errcode=parse_statement(definition,&fields); + errcode == no_error ; + errcode=parse_statement(definition,&fields)) { + + 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)); + free(field.name); + free(field.type_name); + } + } + if (errcode != mismatch_error) + return NULL; /* FIXME: LEAK! */ + + /* 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(); + } + + gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); + + gras_dynar_free(fields); + return struct_type; +} + +static gras_datadesc_type_t * parse_typedef(char *definition) { + + type_modifier_t tm; + + gras_datadesc_type_t *struct_desc=NULL; + gras_datadesc_type_t *typedef_desc=NULL; + + memset(&tm,0,sizeof(tm)); + + /* get the aliased type */ + parse_type_modifier(&tm); + + if (tm.is_struct) { + struct_desc = parse_struct(definition); + } + + parse_type_modifier(&tm); + + if (tm.is_ref) { + ERROR1("Cannot handle reference without annotation. Definition was:\n%s", + definition); + gras_abort(); + } + + /* 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(); + } + + /* (FIXME: should) build the alias */ + ERROR1("Cannot handle typedef yet. Definition was: \n%s",definition); + gras_abort(); + + // identifier.type=gras_ddt_type_new_typedef(bag, NULL, strdup(gras_ddt_parse_text) ); + + return typedef_desc; +} + + +/** + * gras_datadesc_declare_parse: + * + * Create a datadescription from the result of parsing the C type description + */ +gras_datadesc_type_t * +gras_datadesc_parse(const char *name, + const char *C_statement) { + + gras_datadesc_type_t * res=NULL; + char *definition; + int semicolon_count=0; + int def_count,C_count; + /* 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); + 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] == '{') { + definition[def_count++] = '\n'; + } + } + definition[def_count] = '\0'; + + /* init */ + VERB1("_gras_ddt_type_parse(%s)",definition); + gras_ddt_parse_pointer_string_init(definition); + + /* Do I have a typedef, or a raw struct ?*/ + gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); + + if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"struct"))) { + gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); + res = parse_struct(definition); + + } else if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"typedef"))) { + gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); + res = parse_typedef(definition); + + } else { + ERROR1("Failed to parse the following symbol (not a struct neither a typedef) :\n%s",definition); + gras_abort(); + } + + gras_ddt_parse_pointer_string_close(); + VERB0("end of _gras_ddt_type_parse()"); + free(definition); + /* register it under the name provided as symbol */ + 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(); + } + return res; +} + + diff --git a/src/gras/DataDesc/ddt_parse.yy.h b/src/gras/DataDesc/ddt_parse.yy.h new file mode 100644 index 0000000000..7a33ad0d94 --- /dev/null +++ b/src/gras/DataDesc/ddt_parse.yy.h @@ -0,0 +1,37 @@ +/* $Id$ */ + +/* gs/parse.h -- automatic parsing of data structures */ + +/* Authors: Arnaud Legrand, Martin Quinson */ + +typedef enum { + GRAS_DDT_PARSE_TOKEN_EMPTY = 0, + GRAS_DDT_PARSE_TOKEN_LP = 512, /* { */ + GRAS_DDT_PARSE_TOKEN_RP, /* } */ + GRAS_DDT_PARSE_TOKEN_LB, /* [ */ + GRAS_DDT_PARSE_TOKEN_RB, /* ] */ + GRAS_DDT_PARSE_TOKEN_WORD, + GRAS_DDT_PARSE_TOKEN_SPACE, + GRAS_DDT_PARSE_TOKEN_QUOTE, + GRAS_DDT_PARSE_TOKEN_COMMENT, + GRAS_DDT_PARSE_TOKEN_NEWLINE, + GRAS_DDT_PARSE_TOKEN_STAR, + GRAS_DDT_PARSE_TOKEN_SEMI_COLON, + GRAS_DDT_PARSE_TOKEN_COLON, + GRAS_DDT_PARSE_TOKEN_ERROR +} gras_ddt_parse_token_t; + +#define GRAS_DDT_PARSE_MAX_STR_CONST 4048 + +extern int gras_ddt_parse_line_pos; +extern int gras_ddt_parse_col_pos; +extern int gras_ddt_parse_char_pos; +extern int gras_ddt_parse_tok_num; + +void gras_ddt_parse_dump(void); +int gras_ddt_parse_lex(void); +int gras_ddt_parse_lex_n_dump(void); +void gras_ddt_parse_pointer_init(const char *file); +void gras_ddt_parse_pointer_close(void); +void gras_ddt_parse_pointer_string_init(const char *string_to_parse); +void gras_ddt_parse_pointer_string_close(void); diff --git a/src/gras/DataDesc/ddt_parse.yy.l b/src/gras/DataDesc/ddt_parse.yy.l new file mode 100644 index 0000000000..020d89cc1f --- /dev/null +++ b/src/gras/DataDesc/ddt_parse.yy.l @@ -0,0 +1,246 @@ +/**** MSG_LICENCE DO NOT REMOVE ****/ + +%option noyywrap +%{ +#include"DataDesc/datadesc_private.h" +#include"DataDesc/ddt_parse.yy.h" +#include + YY_BUFFER_STATE input_buffer; + FILE *file_to_parse; + + int gras_ddt_parse_line_pos = 1; + int gras_ddt_parse_col_pos = 0; + int gras_ddt_parse_char_pos = 0; + int gras_ddt_parse_tok_num = 0; +%} + +%x comment foo str +space [ \t] +letter [A-Za-z._-] +digit [0-9] + +%% + int comment_caller=0; + + char string_buf[GRAS_DDT_PARSE_MAX_STR_CONST]; + char *string_buf_ptr = NULL; + +"//"[^\n]* +"/*" { + comment_caller = INITIAL; + BEGIN(comment); + } + +"/*" { + comment_caller = foo; + BEGIN(comment); + } + +[^*\n]* /* eat anything that's not a '*' */ +"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ +\n { + ++gras_ddt_parse_line_pos; + gras_ddt_parse_col_pos=0; + gras_ddt_parse_char_pos++; +} +"*"+"/" BEGIN(comment_caller); + +\" string_buf_ptr = string_buf; gras_ddt_parse_char_pos++;gras_ddt_parse_col_pos++; BEGIN(str); + +\" { /* saw closing quote - all done */ + BEGIN(INITIAL); + *string_buf_ptr = '\0'; + yytext=string_buf; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return GRAS_DDT_PARSE_TOKEN_WORD; + /* return string constant token type and + * value to parser + */ + } + +\n { + /* error - unterminated string constant */ + /* generate error message */ + } + +\\[0-7]{1,3} { + /* octal escape sequence */ + int result; + + (void) sscanf( yytext + 1, "%o", &result ); + + if ( result > 0xff ) + /* error, constant is out-of-bounds */ + + *string_buf_ptr++ = result; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + } + +\\[0-9]+ { + /* generate error - bad escape sequence; something + * like '\48' or '\0777777' + */ + } + +\\n { + *string_buf_ptr++ = '\n'; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} +\\t { + *string_buf_ptr++ = '\t'; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} +\\r { + *string_buf_ptr++ = '\r'; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} +\\b { + *string_buf_ptr++ = '\b'; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} +\\f { + *string_buf_ptr++ = '\f'; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} + +\\(.|\n) { + *string_buf_ptr++ = yytext[1]; + if(yytext[1]=='\n') { + ++gras_ddt_parse_line_pos; + gras_ddt_parse_col_pos=0; + } else { + gras_ddt_parse_col_pos++; + } + gras_ddt_parse_char_pos++; +} + +[^\\\n\"]+ { + char *yptr = yytext; + + while ( *yptr ) + *string_buf_ptr++ = *yptr++; + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} + +({letter}|{digit})* { + gras_ddt_parse_char_pos+= strlen(yytext); + gras_ddt_parse_col_pos+= strlen(yytext); + return(GRAS_DDT_PARSE_TOKEN_WORD); +} +"{" { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_LP); +} +"}" { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_RP); +} +"[" { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_LB); +} +"]" { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_RB); +} +"*" { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_STAR); +} +";" { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_SEMI_COLON); +} +"," { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; + return(GRAS_DDT_PARSE_TOKEN_COLON); +} +"\n" { + gras_ddt_parse_line_pos++; + gras_ddt_parse_char_pos=0; + gras_ddt_parse_col_pos++; +} +. { + gras_ddt_parse_char_pos++; + gras_ddt_parse_col_pos++; +} +%% +/* {space}+ { return(TOKEN_SPACE);} */ + +void gras_ddt_parse_dump(void) { + switch(gras_ddt_parse_tok_num) { + case GRAS_DDT_PARSE_TOKEN_LP : {printf("TOKEN_LP ");break;} + case GRAS_DDT_PARSE_TOKEN_RP : {printf("TOKEN_RP ");break;} + case GRAS_DDT_PARSE_TOKEN_WORD : {printf("TOKEN_WORD ");break;} + // case GRAS_DDT_PARSE_TOKEN_SPACE : {printf("TOKEN_SPACE ");break;} + // case GRAS_DDT_PARSE_TOKEN_COMMENT : {printf("TOKEN_COMMENT ");break;} + case GRAS_DDT_PARSE_TOKEN_NEWLINE : {printf("TOKEN_NEWLINE\n");return;} + case GRAS_DDT_PARSE_TOKEN_EMPTY : {printf("TOKEN_EMPTY\n");return;} + default : {printf("Unknown token %d\n", gras_ddt_parse_tok_num);return;} + } + printf("-->%s<-- [line %d, pos %d]\n",yytext,gras_ddt_parse_line_pos,gras_ddt_parse_char_pos); + return; +} + +int gras_ddt_parse_lex_n_dump(void) { + gras_ddt_parse_tok_num = gras_ddt_parse_lex(); + // gras_ddt_parse_char_pos += strlen(yytext); + return(gras_ddt_parse_tok_num); +} + +void gras_ddt_parse_pointer_init(const char *file) { + file_to_parse = fopen(file,"r"); + input_buffer = yy_create_buffer( file_to_parse, 10 ); + yy_switch_to_buffer(input_buffer); + + gras_ddt_parse_line_pos = 1; + gras_ddt_parse_char_pos = 0; + gras_ddt_parse_col_pos = 0; + gras_ddt_parse_tok_num = 0; +} + +void gras_ddt_parse_pointer_close(void) { + yy_delete_buffer(input_buffer); + fclose(file_to_parse); + + gras_ddt_parse_line_pos = 1; + gras_ddt_parse_char_pos = 0; + gras_ddt_parse_tok_num = 0; +} + + +void gras_ddt_parse_pointer_string_init(const char *string_to_parse) { + input_buffer = yy_scan_string (string_to_parse); + yy_switch_to_buffer(input_buffer); + + gras_ddt_parse_line_pos = 1; + gras_ddt_parse_char_pos = 0; + gras_ddt_parse_tok_num = 0; +} + +void gras_ddt_parse_pointer_string_close(void) { + yy_delete_buffer(input_buffer); + + gras_ddt_parse_line_pos = 1; + gras_ddt_parse_char_pos = 0; + gras_ddt_parse_tok_num = 0; +} + +// Local variables: +// mode: c +// End: diff --git a/src/gras/Makefile.am b/src/gras/Makefile.am index d2cf2f72ad..c70917e60c 100644 --- a/src/gras/Makefile.am +++ b/src/gras/Makefile.am @@ -7,9 +7,8 @@ EXTRA_DIST= ./gras_private.h \ Transport/transport_interface.h \ Virtu/virtu_interface.h \ Virtu/virtu_rl.h \ - Virtu/virtu_sg.h -# DataDesc/parse.yy.l - + Virtu/virtu_sg.h \ + DataDesc/ddt_parse.yy.l DataDesc/ddt_parse.yy.c if HAVE_SG lib_LIBRARIES= libgrasrl.a libgrassg.a @@ -33,6 +32,7 @@ COMMON_S=\ DataDesc/ddt_convert.c DataDesc/ddt_exchange.c \ DataDesc/cbps.c DataDesc/datadesc.c \ DataDesc/datadesc_interface.h DataDesc/datadesc_private.h \ + DataDesc/ddt_parse.c DataDesc/ddt_parse.yy.c DataDesc/ddt_parse.yy.h \ \ Msg/msg.c Msg/msg_interface.h Msg/msg_private.h \ \ @@ -40,8 +40,8 @@ COMMON_S=\ # DataDesc/ddt_declare.c -DataDesc/parse.yy.c: DataDesc/parse.yy.l - flex -o$@ -Pgras_ddt_ $^ +DataDesc/ddt_parse.yy.c: DataDesc/ddt_parse.yy.l + @LEX@ -o$@ -Pgras_ddt_parse_ $^ libgrasrl_a_SOURCES= $(COMMON_S) \ Transport/rl_transport.c Transport/transport_plugin_tcp.c Transport/transport_plugin_file.c \