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 06e465ff9cf91d58ec90b4c5432cf45a0ebaf34d..939c3bdec41a56cc7090dbfb032790cc8e36242c 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 2dd941f61827143afa8cfaa5c40de6e10dd31469..7ce7e376c1bdc85f289ccddcfcba5256c05dd591 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 f097089f3b1aca16891b933fe1937f952ad5ade1..968218a3290159742cb7dd3023feccac20756051 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 358a141025e2b799caf363b2fa07107efd618b03..9759db21a2c04afea120c3102881e3728cd17742 100644 (file)
@@ -11,6 +11,7 @@
 
 extern int braces_open,
            autocommit,
+           auto_create_c,
            ret_value,
            struct_level;
 extern char *descriptor_index;
index 7da47877cf8c155ce24a5a4de059b8c6f3bf28f4..f0140bc7a33cd41c0cf8f7ae58b0a035cc46faac 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 6f0afccc75bbe8c8407c776f8d77bb9fd1309320..2cdde342003e1337042eea0676cc4d6d86efb27c 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;