]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
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");