aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meskes <meskes@postgresql.org>2002-03-21 09:42:52 +0000
committerMichael Meskes <meskes@postgresql.org>2002-03-21 09:42:52 +0000
commit73b92d10c66f12ed162857a966eed507bf8d2629 (patch)
tree5b390659e5319966514b931ddf17f740ac87044c
parenta13ddd36b03eb076d02bec6364ac07d010447fd2 (diff)
downloadpostgresql-73b92d10c66f12ed162857a966eed507bf8d2629.tar.gz
postgresql-73b92d10c66f12ed162857a966eed507bf8d2629.zip
Added typedef patches and a new option '-c' to automatically create C typedefs from SQL ones.
-rw-r--r--src/interfaces/ecpg/ChangeLog6
-rw-r--r--src/interfaces/ecpg/preproc/c_keywords.c1
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.c20
-rw-r--r--src/interfaces/ecpg/preproc/extern.h1
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y127
-rw-r--r--src/interfaces/ecpg/test/test3.pgc3
6 files changed, 123 insertions, 35 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index 06e465ff9cf..939c3bdec41 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -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.
diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c
index 2dd941f6182..7ce7e376c1b 100644
--- a/src/interfaces/ecpg/preproc/c_keywords.c
+++ b/src/interfaces/ecpg/preproc/c_keywords.c
@@ -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},
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index f097089f3b1..968218a3290 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -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':
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index 358a141025e..9759db21a2c 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -11,6 +11,7 @@
extern int braces_open,
autocommit,
+ auto_create_c,
ret_value,
struct_level;
extern char *descriptor_index;
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 7da47877cf8..f0140bc7a33 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -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"); }
diff --git a/src/interfaces/ecpg/test/test3.pgc b/src/interfaces/ecpg/test/test3.pgc
index 6f0afccc75b..2cdde342003 100644
--- a/src/interfaces/ecpg/test/test3.pgc
+++ b/src/interfaces/ecpg/test/test3.pgc
@@ -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;