Parse forward definiton of structs.
authorMichael Meskes <meskes@postgresql.org>
Thu, 29 May 2003 12:00:22 +0000 (12:00 +0000)
committerMichael Meskes <meskes@postgresql.org>
Thu, 29 May 2003 12:00:22 +0000 (12:00 +0000)
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/preproc/pgc.l
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/type.c
src/interfaces/ecpg/preproc/type.h
src/interfaces/ecpg/preproc/variable.c

index 02fe1e9d41ff78b630bcc0a8ba326c703b2085b7..ba19efc1d3635755f7dde1ea2f10e76ed90abe5d 100644 (file)
@@ -1449,6 +1449,10 @@ Tue May 27 13:29:28 CEST 2003
 Tue May 27 16:33:36 CEST 2003
 
    - Accept stdin/stdout as input/output file.
+   
+Thu May 29 13:58:25 CEST 2003
+
+   - ecpg should now be able to parse forward struct definition.
    - Set ecpg version to 2.12.0.
    - Set ecpg library to 3.4.2.
    - Set pgtypes library to 1.0.0
index c489f64dcb9529db6cbe52d4714aad091d76f274..880f6f050068c9f88d330e5a8e05965aa30d584f 100644 (file)
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.111 2003/05/27 14:36:00 meskes Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.112 2003/05/29 12:00:21 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -184,6 +184,7 @@ letter_or_digit [\200-\377_A-Za-z0-9]
 
 identifier     {letter}{letter_or_digit}*
 
+array          ({letter_or_digit}|[\+\-\*\%\/\(\)])*
 typecast       "::"
 
 /*
@@ -949,96 +950,7 @@ cppline            {space}*#(.*\\{space})+.*
 
 <incl>\<[^\>]+\>{space}*";"?       {   parse_include(); }
 <incl>{dquote}{xdinside}{dquote}{space}*";"?   {   parse_include(); }
-<incl>[^;\<\>\"]+";"       {
-               parse_include();
-#if 0
-                       /* got the include file name */
-                       struct _yy_buffer *yb;
-                       struct _include_path *ip;
-                       char inc_file[MAXPGPATH];
-                       unsigned int i;
-
-                       yb = mm_alloc(sizeof(struct _yy_buffer));
-
-                       yb->buffer =    YY_CURRENT_BUFFER;
-                       yb->lineno = yylineno;
-                       yb->filename = input_filename;
-                       yb->next = yy_buffer;
-
-                       yy_buffer = yb;
-
-                       /*
-                        * skip the ";" and trailing whitespace. Note that yytext contains
-                        * at least one non-space character plus the ";" 
-                        */
-                       for ( i = strlen(yytext)-2;
-                           i > 0 && isspace((unsigned char) yytext[i]);
-                           i-- )
-                           {}
-
-                       yytext[i+1] = '\0';
-                       yyin = NULL;
-
-                       /* If file name is enclosed in '"' remove these and look only in '.' */
-                       /* Informix does look into all include paths though, except filename starts with '/' */
-                       if ((yytext[0] == '"' && yytext[i] == '"') && (compat != ECPG_COMPAT_INFORMIX || yytext[0] == '/'))
-                       {
-                           yytext[i] = '\0';
-                           memmove(yytext, yytext+1, strlen(yytext));
-                       
-                           strncpy(inc_file, yytext, sizeof(inc_file));
-                           yyin = fopen(inc_file, "r");
-                           if (!yyin)
-                           {
-                               if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
-                               {
-                                   strcat(inc_file, ".h");
-                                   yyin = fopen(inc_file, "r");
-                               }
-                           }
-                           
-                       }
-                       else
-                       {
-                           if (yytext[0] == '"' && yytext[i] == '"')
-                           {
-                               yytext[i] = '\0';
-                               memmove(yytext, yytext+1, strlen(yytext));
-                           }
-                           
-                           for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next)
-                           {
-                               if (strlen(ip->path) + strlen(yytext) + 3 > MAXPGPATH)
-                               {
-                                   fprintf(stderr, "Error: Path %s/%s is too long in line %d, skipping.\n", ip->path, yytext, yylineno);
-                                   continue;
-                               }
-                               snprintf (inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext);
-                               yyin = fopen(inc_file, "r");
-                               if (!yyin)
-                               {
-                                   if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
-                                   {
-                                       strcat(inc_file, ".h");
-                                       yyin = fopen( inc_file, "r" );
-                                   }
-                               }
-                           }
-                       }
-                       if (!yyin)
-                       {
-                           snprintf(errortext, sizeof(errortext), "Cannot open include file %s in line %d\n", yytext, yylineno);
-                           mmerror(NO_INCLUDE_FILE, ET_FATAL, errortext);
-                       }
-
-                       input_filename = mm_strdup(inc_file);
-                       yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
-                       yylineno = 1;
-                       output_line_number();
-
-                       BEGIN C;
-#endif
-                   }
+<incl>[^;\<\>\"]+";"       { parse_include(); }
 
 <<EOF>>                {
                        if (yy_buffer == NULL) {
index 6f0aa04cc55db5a5eb2f323a909f6ce58c4d30a3..c1c279550cde734b584173c417d20922731290b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.223 2003/05/27 11:31:52 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.224 2003/05/29 12:00:21 meskes Exp $ */
 
 /* Copyright comment */
 %{
@@ -27,6 +27,9 @@ struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
 /* also store struct type so we can do a sizeof() later */
 static char *ECPGstruct_sizeof = NULL;
 
+/* for forward declarations we have to store some data as well */
+static char *forward_name = NULL;
+
 struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}};
 struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
 
@@ -196,6 +199,7 @@ create_questionmarks(char *name, bool array)
    enum    ECPGttype   type_enum;
    enum    ECPGdtype   dtype_enum;
    struct  fetch_desc  descriptor;
+   struct  su_symbol   struct_union;
 }
 
 /* special embedded SQL token */
@@ -440,7 +444,9 @@ create_questionmarks(char *name, bool array)
 %type  <str>   reserved_keyword unreserved_keyword ecpg_interval
 %type  <str>   col_name_keyword func_name_keyword precision opt_scale
 %type  <str>   ECPGTypeName variablelist ECPGColLabelCommon c_variable
-%type  <str>   s_struct_union_symbol inf_val_list inf_col_list
+%type  <str>   inf_val_list inf_col_list
+
+%type  <struct_union> s_struct_union_symbol
 
 %type  <descriptor> ECPGGetDescriptor
 
@@ -4039,7 +4045,6 @@ connection_target: database_name opt_server opt_port
        }
        | StringConst
        {
-           printf("MM: %s\n", $1);
            if ($1[0] == '\"')
                $$ = $1;
            else if (strcmp($1, " ?") == 0) /* variable */
@@ -4425,16 +4430,34 @@ single_vt_type: common_type
        | s_struct_union_symbol
        {
            /* this is for named structs/unions */
-           char *name = $1;
-           struct typedefs *this = get_typedef(name);
-
-           $$.type_str = mm_strdup(this->name);
-           $$.type_enum = this->type->type_enum;
-           $$.type_dimension = this->type->type_dimension;
-           $$.type_index = this->type->type_index;
-           $$.type_sizeof = this->type->type_sizeof;
-           struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
-           free(name);
+           char *name;
+           struct typedefs *this;
+           bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
+
+           name = cat2_str($1.su, $1.symbol);
+           /* Do we have a forward definition? */
+           if (!forward)
+           {
+               /* No */
+               
+               this = get_typedef(name);
+               $$.type_str = mm_strdup(this->name);
+               $$.type_enum = this->type->type_enum;
+               $$.type_dimension = this->type->type_dimension;
+               $$.type_index = this->type->type_index;
+               $$.type_sizeof = this->type->type_sizeof;
+               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+               free(name);
+           }
+           else
+           {
+               $$.type_str = name;
+                                $$.type_enum = ECPGt_long;
+                                $$.type_dimension = make_str("-1");
+                                $$.type_index = make_str("-1");
+                                $$.type_sizeof = make_str("");
+                                struct_member_list[struct_level] = NULL;
+           }
        }
        ;
 
@@ -4761,15 +4784,34 @@ var_type:   common_type
        | s_struct_union_symbol
        {
            /* this is for named structs/unions */
-           char *name = $1;
-           struct typedefs *this = get_typedef(name);
-           $$.type_str = mm_strdup(this->name);
-           $$.type_enum = this->type->type_enum;
-           $$.type_dimension = this->type->type_dimension;
-           $$.type_index = this->type->type_index;
-           $$.type_sizeof = this->type->type_sizeof;
-           struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
-           free(name);
+           char *name;
+           struct typedefs *this;
+           bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
+
+           name = cat2_str($1.su, $1.symbol);
+           /* Do we have a forward definition? */
+           if (!forward)
+           {
+               /* No */
+               
+               this = get_typedef(name);
+               $$.type_str = mm_strdup(this->name);
+               $$.type_enum = this->type->type_enum;
+               $$.type_dimension = this->type->type_dimension;
+               $$.type_index = this->type->type_index;
+               $$.type_sizeof = this->type->type_sizeof;
+               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+               free(name);
+           }
+           else
+           {
+               $$.type_str = name;
+                                $$.type_enum = ECPGt_long;
+                                $$.type_dimension = make_str("-1");
+                                $$.type_index = make_str("-1");
+                                $$.type_sizeof = make_str("");
+                                struct_member_list[struct_level] = NULL;
+           }
        }
        ;
 
@@ -4789,18 +4831,21 @@ struct_union_type_with_symbol: s_struct_union_symbol
            struct_member_list[struct_level++] = NULL;
            if (struct_level >= STRUCT_DEPTH)
                 mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
+           forward_name = mm_strdup($1.symbol);
        } 
        '{' variable_declarations '}'
        {
            ECPGfree_struct_member(struct_member_list[struct_level]);
            struct_member_list[struct_level] = NULL;
            free(actual_storage[struct_level--]);
-           if (strncmp($1, "struct", sizeof("struct")-1) == 0)
+           if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
                $$.type_enum = ECPGt_struct;
            else
                $$.type_enum = ECPGt_union;
-           $$.type_str = mm_strdup($1);
-           $$.type_sizeof = cat_str(4, $1, make_str("{"), $4, make_str("}"));
+           $$.type_str = cat2_str($1.su, $1.symbol);
+           $$.type_sizeof = cat_str(4, mm_strdup($$.type_str), make_str("{"), $4, make_str("}"));
+           free(forward_name);
+           forward_name = NULL;
        }
        ;
 
@@ -4822,12 +4867,14 @@ struct_union_type: struct_union_type_with_symbol    { $$ = $1.type_sizeof; }
 
 s_struct_union_symbol: SQL_STRUCT symbol
        {
-           $$ = cat2_str(make_str("struct"), $2);
-           ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), strdup($$), make_str(")")); 
+           $$.su = make_str("struct");
+           $$.symbol = $2;
+           ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")")); 
        }
        | UNION symbol
        {
-           $$ = cat2_str(make_str("union"), $2);
+           $$.su = make_str("union");
+           $$.symbol = $2;
        }
        ;
 
index 8bef0b36e2019f66c8a9e6594a351a40c9db00a3..f9045cfb42527b2cd4a25f02ccc5b7a935d67074 100644 (file)
@@ -225,7 +225,6 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
        case ECPGt_array:
            if (indicator_set && ind_type->type != ECPGt_array)
                mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "Indicator for array/pointer has to be array/pointer.\n");
-
            switch (type->u.element->type)
            {
                case ECPGt_array:
@@ -233,8 +232,14 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
                    break;
                case ECPGt_struct:
                case ECPGt_union:
-                   /* If var_array_element is not equal                                                                                                                                   * NULL, we have to use the                                                                                                                                            * <var_array_element>th entry and not                                                                                                                                 * the whole array */                                                                                                                                                 if (var_array_element == NULL)
-                       ECPGdump_a_struct(o, name, ind_name, type->size,
+                   /* If var_array_element is not equal
+                    * NULL, we have to use the
+                    * <var_array_element>th entry and
+                    * not the whole array */
+                   if (var_array_element == NULL)
+                       ECPGdump_a_struct(o, name,
+                               ind_name,
+                               type->size,
                                type->u.element,
                                (ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
                                NULL, prefix, ind_prefix);
index 28615af8c9c471574028ed4096d91ebe5d2ea6d8..233bde035735d60eee9bd770a61fa9151a3c2fd8 100644 (file)
@@ -88,6 +88,12 @@ struct index
    char    *str;
 };
 
+struct su_symbol
+{
+   char    *su;
+   char    *symbol;
+};
+
 struct this_type
 {
    enum ECPGttype type_enum;
index b62ba4d2c4de7e5351c5313b30cf1db337ea23e8..82b749981cf3abb2d031f6fe67d1230cfb25edb7 100644 (file)
@@ -67,7 +67,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in
 }
 
 static struct variable *
-find_struct(char *name, char *next)
+find_struct(char *name, char *next, char *end)
 {
    struct variable *p;
    char        c = *next;
@@ -90,24 +90,45 @@ find_struct(char *name, char *next)
            mmerror(PARSE_ERROR, ET_FATAL, errortext);
        }
 
-       /* restore the name, we will need it later on */
+       /* restore the name, we will need it later */
        *next = c;
-       next++;
 
-       return find_struct_member(name, next, p->type->u.element->u.members, p->brace_level);
+       return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
    }
    else
    {
-       if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
+       if (next == end)
        {
-           snprintf(errortext, sizeof(errortext), "variable %s is neither a structure nor a union", name);
-           mmerror(PARSE_ERROR, ET_FATAL, errortext);
+           if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
+           {
+               snprintf(errortext, sizeof(errortext), "variable %s is neither a structure nor a union", name);
+               mmerror(PARSE_ERROR, ET_FATAL, errortext);
+           }
+
+           /* restore the name, we will need it later */
+           *next = c;
+
+           return find_struct_member(name, end, p->type->u.members, p->brace_level);
        }
+       else
+       {
+           if (p->type->type != ECPGt_array)
+           {
+               snprintf(errortext, sizeof(errortext), "variable %s is not an array", name);
+               mmerror(PARSE_ERROR, ET_FATAL, errortext);
+           }
 
-       /* restore the name, we will need it later on */
-       *next = c;
+           if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
+           {
+               snprintf(errortext, sizeof(errortext), "variable %s is not a pointer to a structure or a union", name);
+               mmerror(PARSE_ERROR, ET_FATAL, errortext);
+           }
+
+           /* restore the name, we will need it later */
+           *next = c;
 
-       return find_struct_member(name, next, p->type->u.members, p->brace_level);
+           return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
+       }
    }
 }
 
@@ -130,15 +151,43 @@ find_simple(char *name)
 struct variable *
 find_variable(char *name)
 {
-   char       *next;
+   char       *next, *end;
    struct variable *p;
+   int count;
 
-   if ((next = strchr(name, '.')) != NULL)
-       p = find_struct(name, next);
-   else if ((next = strstr(name, "->")) != NULL)
-       p = find_struct(name, next);
-   else
-       p = find_simple(name);
+   printf("MM: find %s\n", name);
+
+   next = strpbrk(name, ".[-");
+   if (next)
+   {
+       if (*next == '[')
+       {
+           /* We don't care about what's inside the array braces
+            * so just eat up the character */
+           for (count=1, end=next+1; count; end++)
+           {
+                 switch (*end)
+                 {
+                     case '[': count++;
+                           break;
+                     case ']': count--;
+                           break;
+                     default : break;
+                 }
+           }
+           if (*end == '.') p = find_struct(name, next, end);
+           else
+           {
+                char c = *next;
+                
+                *next = '\0';
+                p = find_simple(name);
+                *next = c;
+           }
+       }
+       else p = find_struct(name, next, next);
+   }
+   else p = find_simple(name);
 
    if (p == NULL)
    {
@@ -330,6 +379,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
        mmerror(PARSE_ERROR, ET_FATAL, errortext);
 /*     mmerror(PARSE_ERROR, ET_FATAL, "No multilevel (more than 2) pointer supported %d",pointer_len);*/
    }
+
    if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char)
        mmerror(PARSE_ERROR, ET_FATAL, "No pointer to pointer supported for this type");