OSDN Git Service

Added typedef patches and a new option '-c' to automatically create C typedefs from...
authorMichael Meskes <meskes@postgresql.org>
Thu, 21 Mar 2002 09:42:52 +0000 (09:42 +0000)
committerMichael Meskes <meskes@postgresql.org>
Thu, 21 Mar 2002 09:42:52 +0000 (09:42 +0000)
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/preproc/c_keywords.c
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/test/test3.pgc

index 06e465f..939c3bd 100644 (file)
@@ -1225,6 +1225,12 @@ Wed Mar  6 10:40:28 CET 2002
 Sun Mar 10 13:08:22 CET 2002
 
        - Fixed two bugs in define command in lexer.
+
+Thu Mar 21 08:25:08 CET 2002
+
+       - Applied patch by Nicolas Bazin <nbazin@ingenico.com.au> for improved
+         typedef handling.
+       - Added option '-c' to automatically create C typedef from SQL one.
        - Set ecpg version to 2.10.0.
        - Set library version to 3.4.0.
 
index 2dd941f..7ce7e37 100644 (file)
@@ -36,6 +36,7 @@ static ScanKeyword ScanKeywords[] = {
        {"signed", SQL_SIGNED},
        {"static", S_STATIC},
        {"struct", SQL_STRUCT},
+       {"typedef", S_TYPEDEF},
        {"union", UNION},
        {"unsigned", SQL_UNSIGNED},
        {"varchar", VARCHAR},
index f097089..968218a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.53 2002/01/10 10:42:54 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.54 2002/03/21 09:42:50 meskes Exp $ */
 
 /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
 /* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
@@ -17,7 +17,8 @@ extern char *optarg;
 #include "extern.h"
 
 int                    ret_value = 0,
-                       autocommit = 0;
+                       autocommit = false;
+                       auto_create_c = false;
 struct _include_path *include_paths = NULL;
 struct cursor *cur = NULL;
 struct typedefs *types = NULL;
@@ -31,11 +32,11 @@ help(const char *progname)
        /* printf is a macro some places; don't #ifdef inside its arguments */
 #ifdef YYDEBUG
        printf("Usage:\n"
-          "  %s [-d] [-I DIRECTORY] [-o OUTFILE] [-t] file1 [file2...]\n\n",
+          "  %s [-d] [-I DIRECTORY] [-o OUTFILE] [-t] [-c] [-D symbol] file1 [file2...]\n\n",
                   progname);
 #else
        printf("Usage:\n"
-                  "  %s [-I DIRECTORY] [-o OUTFILE] [-t] file1 [file2...]\n\n",
+                  "  %s [-I DIRECTORY] [-o OUTFILE] [-t] [-c] [-D symbol] file1 [file2...]\n\n",
                   progname);
 #endif
        printf("Options:\n");
@@ -45,6 +46,8 @@ help(const char *progname)
        printf("  -I DIRECTORY         search DIRECTORY for include files\n");
        printf("  -o OUTFILE           write result to OUTFILE\n");
        printf("  -t                   turn on autocommit of transactions\n");
+       printf("  -c                   automatically generate C code from embedded SQL code\n                        currently this works for EXEC SQL TYPE\n");
+       printf("  -D symbol           define symbo\n");
        printf("\nIf no output file is specified, the name is formed by adding .c\n"
           "to the input file name, after stripping off .pgc if present.\n");
        printf("\nReport bugs to <pgsql-bugs@postgresql.org>.\n");
@@ -58,6 +61,7 @@ add_include_path(char *path)
        include_paths = mm_alloc(sizeof(struct _include_path));
        include_paths->path = path;
        include_paths->next = ip;
+               
 }
 
 static void
@@ -107,7 +111,7 @@ main(int argc, char *const argv[])
        add_include_path("/usr/local/include");
        add_include_path(".");
 
-       while ((c = getopt(argc, argv, "vo:I:tD:d")) != -1)
+       while ((c = getopt(argc, argv, "vco:I:tD:d")) != -1)
        {
                switch (c)
                {
@@ -122,13 +126,15 @@ main(int argc, char *const argv[])
                                add_include_path(optarg);
                                break;
                        case 't':
-                               autocommit = 1;
+                               autocommit = true;
                                break;
                        case 'v':
                                verbose = true;
                                break;
+                       case 'c':
+                               auto_create_c = true;
+                               break;
                        case 'D':
-                               /* XXX not documented */
                                add_preprocessor_define(optarg);
                                break;
                        case 'd':
index 358a141..9759db2 100644 (file)
@@ -11,6 +11,7 @@
 
 extern int     braces_open,
                        autocommit,
+                       auto_create_c,
                        ret_value,
                        struct_level;
 extern char *descriptor_index;
index 7da4787..f0140bc 100644 (file)
@@ -169,6 +169,7 @@ make_name(void)
                S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
                S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
                S_STATIC S_SUB S_VOLATILE
+               S_TYPEDEF
 
 /* I need this and don't know where it is defined inside the backend */
 %token TYPECAST
@@ -354,12 +355,13 @@ make_name(void)
 %type  <str>   stmt ECPGRelease execstring server_name
 %type  <str>   connection_object opt_server opt_port c_stuff c_stuff_item
 %type  <str>   user_name opt_user char_variable ora_user ident opt_reference
-%type  <str>   quoted_ident_stringvar
+%type  <str>   quoted_ident_stringvar var_type_declarations
 %type  <str>   db_prefix server opt_options opt_connection_name c_list
 %type  <str>   ECPGSetConnection cpp_line ECPGTypedef c_args ECPGKeywords
 %type  <str>   enum_type civar civarind ECPGCursorStmt ECPGDeallocate
 %type  <str>   ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
-%type  <str>   struct_type s_struct declaration declarations variable_declarations
+%type  <str>   struct_type s_struct vt_declarations variable_declarations
+%type  <str>   var_declaration type_declaration 
 %type  <str>   s_union union_type ECPGSetAutocommit on_off
 %type  <str>   ECPGAllocateDescr ECPGDeallocateDescr symbol opt_symbol
 %type  <str>   ECPGGetDescriptorHeader ECPGColLabel
@@ -418,7 +420,7 @@ stmt:  AlterDatabaseSetStmt { output_statement($1, 0, connection); }
                | AlterUserSetStmt      { output_statement($1, 0, connection); }
                | ClosePortalStmt       { output_statement($1, 0, connection); }
                | CommentStmt           { output_statement($1, 0, connection); }
-               | CopyStmt                      { output_statement($1, 0, connection); }
+               | CopyStmt              { output_statement($1, 0, connection); }
                | CreateStmt            { output_statement($1, 0, connection); }
                | CreateAsStmt          { output_statement($1, 0, connection); }
                | CreateSchemaStmt      { output_statement($1, 0, connection); }
@@ -429,7 +431,7 @@ stmt:  AlterDatabaseSetStmt { output_statement($1, 0, connection); }
                | CreateUserStmt        { output_statement($1, 0, connection); }
                | ClusterStmt           { output_statement($1, 0, connection); }
                | DefineStmt            { output_statement($1, 0, connection); }
-               | DropStmt                      { output_statement($1, 0, connection); }
+               | DropStmt              { output_statement($1, 0, connection); }
                | DropSchemaStmt        { output_statement($1, 0, connection); }
                | TruncateStmt          { output_statement($1, 0, connection); }
                | DropGroupStmt         { output_statement($1, 0, connection); }
@@ -437,12 +439,12 @@ stmt:  AlterDatabaseSetStmt { output_statement($1, 0, connection); }
                | DropTrigStmt          { output_statement($1, 0, connection); }
                | DropUserStmt          { output_statement($1, 0, connection); }
                | ExplainStmt           { output_statement($1, 0, connection); }
-               | FetchStmt                     { output_statement($1, 1, connection); }
-               | GrantStmt                     { output_statement($1, 0, connection); }
-               | IndexStmt                     { output_statement($1, 0, connection); }
+               | FetchStmt             { output_statement($1, 1, connection); }
+               | GrantStmt             { output_statement($1, 0, connection); }
+               | IndexStmt             { output_statement($1, 0, connection); }
                | ListenStmt            { output_statement($1, 0, connection); }
                | UnlistenStmt          { output_statement($1, 0, connection); }
-               | LockStmt                      { output_statement($1, 0, connection); }
+               | LockStmt              { output_statement($1, 0, connection); }
                | NotifyStmt            { output_statement($1, 0, connection); }
                | ProcedureStmt         { output_statement($1, 0, connection); }
                | ReindexStmt           { output_statement($1, 0, connection); }
@@ -458,23 +460,23 @@ stmt:  AlterDatabaseSetStmt { output_statement($1, 0, connection); }
                        else
                                output_statement($1, 1, connection);
                }
-               | RuleStmt                      { output_statement($1, 0, connection); }
+               | RuleStmt              { output_statement($1, 0, connection); }
                | TransactionStmt
                {
                        fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
                        whenever_action(2);
                        free($1);
                }
-               | ViewStmt                      { output_statement($1, 0, connection); }
-               | LoadStmt                      { output_statement($1, 0, connection); }
+               | ViewStmt              { output_statement($1, 0, connection); }
+               | LoadStmt              { output_statement($1, 0, connection); }
                | CreatedbStmt          { output_statement($1, 0, connection); }
                | DropdbStmt            { output_statement($1, 0, connection); }
                | VacuumStmt            { output_statement($1, 0, connection); }
                | AnalyzeStmt           { output_statement($1, 0, connection); }
                | VariableSetStmt       { output_statement($1, 0, connection); }
                | VariableShowStmt      { output_statement($1, 0, connection); }
-               | VariableResetStmt { output_statement($1, 0, connection); }
-               | ConstraintsSetStmt { output_statement($1, 0, connection); }
+               | VariableResetStmt     { output_statement($1, 0, connection); }
+               | ConstraintsSetStmt    { output_statement($1, 0, connection); }
                | CheckPointStmt        { output_statement($1, 0, connection); }
                | ECPGAllocateDescr
                {
@@ -605,7 +607,9 @@ stmt:  AlterDatabaseSetStmt { output_statement($1, 0, connection); }
                        if (connection)
                                mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement.\n");
 
-                       output_simple_statement($1);
+                       fprintf(yyout, "%s", $1);
+                       free($1);
+                       output_line_number();
                }
                | ECPGVar
                {
@@ -3666,7 +3670,7 @@ ECPGDeallocate: SQL_DEALLOCATE SQL_PREPARE ident
  */
 ECPGDeclaration: sql_startdeclare
                { fputs("/* exec sql begin declare section */", yyout); }
-               variable_declarations sql_enddeclare
+               var_type_declarations sql_enddeclare
                {
                        fprintf(yyout, "%s/* exec sql end declare section */", $3);
                        free($3);
@@ -3678,15 +3682,82 @@ sql_startdeclare: ecpgstart BEGIN_TRANS DECLARE SQL_SECTION ';' {};
 
 sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION ';' {};
 
-variable_declarations: /*EMPTY*/                       { $$ = EMPTY; }
-               | declarations                                          { $$ = $1; }
+var_type_declarations: /*EMPTY*/                       { $$ = EMPTY; }
+               | vt_declarations                       { $$ = $1; }
                ;
 
-declarations:  declaration                                     { $$ = $1; }
-               | declarations declaration                      { $$ = cat2_str($1, $2); }
+vt_declarations:  var_declaration                      { $$ = $1; }
+               | type_declaration                      { $$ = $1; }
+               | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
+               | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
                ;
 
-declaration: storage_clause storage_modifier
+variable_declarations: var_declaration                         { $$ = $1; }
+               | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
+               ;
+
+type_declaration: S_TYPEDEF
+       {
+               /* reset this variable so we see if there was */
+               /* an initializer specified */
+               initializer = 0;
+       }
+       type opt_pointer ECPGColLabel opt_type_array_bounds ';' 
+       {
+               /* add entry to list */
+               struct typedefs *ptr, *this;
+               int dimension = $6.index1;
+               int length = $6.index2;
+
+               if (($3.type_enum == ECPGt_struct ||
+                    $3.type_enum == ECPGt_union) &&
+                   initializer == 1)
+               {
+                       mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command");
+
+               }
+               else
+               {
+                       for (ptr = types; ptr != NULL; ptr = ptr->next)
+                       {
+                               if (strcmp($5, ptr->name) == 0)
+                               {
+                                       /* re-definition is a bug */
+                                       sprintf(errortext, "Type %s already defined", $5);
+                                       mmerror(PARSE_ERROR, ET_ERROR, errortext);
+                               }
+                       }
+
+                       adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0);
+
+                       this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
+
+                       /* initial definition */
+                       this->next = types;
+                       this->name = $5;
+                       this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+                       this->type->type_enum = $3.type_enum;
+                       this->type->type_str = mm_strdup($5);
+                       this->type->type_dimension = dimension; /* dimension of array */
+                       this->type->type_index = length;    /* lenght of string */
+                       this->struct_member_list = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ?
+                               struct_member_list[struct_level] : NULL;
+
+                       if ($3.type_enum != ECPGt_varchar &&
+                           $3.type_enum != ECPGt_char &&
+                           $3.type_enum != ECPGt_unsigned_char &&
+                           this->type->type_index >= 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
+
+                       types = this;
+               }
+
+               fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4?"*":"", $5, $6.str);
+               output_line_number();
+               $$ = make_str("");
+       };
+
+var_declaration: storage_clause storage_modifier
                {
                        actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
                        actual_startline[struct_level] = hashline_number();
@@ -4239,7 +4310,7 @@ ECPGTypedef: TYPE_P
                        if (($5.type_enum == ECPGt_struct ||
                                 $5.type_enum == ECPGt_union) &&
                                initializer == 1)
-                               mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+                               mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL TYPE command");
                        else
                        {
                                for (ptr = types; ptr != NULL; ptr = ptr->next)
@@ -4276,7 +4347,10 @@ ECPGTypedef: TYPE_P
                                types = this;
                        }
 
-                       $$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
+                       if (auto_create_c == false)
+                               $$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
+                       else
+                               $$ = cat_str(6, make_str("typedef "), mm_strdup($5.type_str), *$7?make_str("*"):make_str(""), mm_strdup($6.str), mm_strdup($3), make_str(";"));
                }
                ;
 
@@ -4504,10 +4578,10 @@ ECPGKeywords:  SQL_BREAK                { $$ = make_str("break"); }
                ;
 
 /* additional keywords that can be SQL type names (but not ECPGColLabels) */
-ECPGTypeName:  SQL_BOOL                        { $$ = make_str("bool"); }
-               | SQL_INT                               { $$ = make_str("int"); }
-               | SQL_LONG                              { $$ = make_str("long"); }
-               | SQL_SHORT                             { $$ = make_str("short"); }
+ECPGTypeName:  SQL_BOOL                                { $$ = make_str("bool"); }
+               | SQL_INT                       { $$ = make_str("int"); }
+               | SQL_LONG                      { $$ = make_str("long"); }
+               | SQL_SHORT                     { $$ = make_str("short"); }
                | SQL_STRUCT                    { $$ = make_str("struct"); }
                | SQL_SIGNED                    { $$ = make_str("signed"); }
                | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
@@ -5006,6 +5080,7 @@ c_anything:  IDENT                                        { $$ = $1; }
                | S_RSHIFT                                      { $$ = make_str(">>"); }
                | S_STATIC                                      { $$ = make_str("static"); }
                | S_SUB                                         { $$ = make_str("-="); }
+               | S_TYPEDEF                             { $$ = make_str("typedef"); }
                | SQL_BOOL                                      { $$ = make_str("bool"); }
                | SQL_ENUM                                      { $$ = make_str("enum"); }
                | SQL_INT                                       { $$ = make_str("int"); }
index 6f0afcc..2cdde34 100644 (file)
@@ -11,9 +11,8 @@ exec sql type str is varchar[10];
 int
 main ()
 {
-       typedef struct { long born; short age; } birthinfo;
-       exec sql type birthinfo is struct { long born; short age; };
 exec sql begin declare section;
+       typedef struct { long born; short age; } birthinfo;
        struct personal_struct  {       str name;
                                        birthinfo birth;
                                } personal;