diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index bb8517a4b0f7191d0cb31b95b455cfcdbc19e876..aaa63f616a211df44e86d28fbec84b419164e8ae 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -775,5 +775,21 @@ Mon Jan 17 21:55:40 CET 2000
 	- Synced preproc.y with gram.y.
 	- Changed FETCH syntax using Rene's final patch. Made it more
 	  standard compliant.
+
+Thu Jan 20 10:00:50 CET 2000
+
+	- Synced preproc.y with gram.y.
+
+Fri Jan 21 14:52:27 CET 2000
+
+	- Added more log output to ecpglib.
+
+Thu Jan 27 08:12:05 CET 2000
+
+	- Added another patch by Rene Hogendoorn.
+	- Fixed error messages in pgc.l.
+	- Improved variable parsing.
+	- Synced preproc.y with gram.y.
 	- Set library version to 3.0.10.
 	- Set ecpg version to 2.7.0.
+
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
index 5190dd0635c6409a1904189235873ff38ff17b39..7e755782715b8d99b22fbc35acec7212c0e1696b 100644
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ b/src/interfaces/ecpg/lib/ecpglib.c
@@ -9,7 +9,7 @@
    slightly modified)
  */
 
-/* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
+/* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
    on Feb. 5th, 1998 */
 
 #include <stdio.h>
@@ -724,6 +724,9 @@ ECPGexecute(struct statement * stmt)
 						*((void **) var->pointer) = var->value;
 						add_mem(var->value, stmt->lineno);
 					}
+					
+					
+					ECPGlog("ECPGexecute line %d: TYPE db: %d c: %d\n", stmt->lineno, PQftype(results, act_field), var->type);
 
 					for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
 					{
@@ -764,7 +767,7 @@ ECPGexecute(struct statement * stmt)
 								status = false;
 								break;
 						}
-
+						
 						switch (var->type)
 						{
 								long		res;
diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c
index 4d04c00dd9cae5b5c996ac00bf9cb50fb223236d..15e1494eea5fe1c414e5248ded28dbc4b193fe9e 100644
--- a/src/interfaces/ecpg/preproc/c_keywords.c
+++ b/src/interfaces/ecpg/preproc/c_keywords.c
@@ -19,25 +19,26 @@
  */
 static ScanKeyword ScanKeywords[] = {
 	/* name					value			*/
-	{"VARCHAR", S_VARCHAR},
+	{"VARCHAR", VARCHAR},
 	{"auto", S_AUTO},
-	{"bool", S_BOOL},
-	{"char", S_CHAR},
+	{"bool", SQL_BOOL},
+	{"char", CHAR},
 	{"const", S_CONST},
-	{"double", S_DOUBLE},
-	{"enum", S_ENUM},
+	{"double", DOUBLE},
+	{"enum", SQL_ENUM},
 	{"extern", S_EXTERN},
-	{"float", S_FLOAT},
-	{"int", S_INT},
-	{"long", S_LONG},
+	{"float", FLOAT},
+	{"int", SQL_INT},
+	{"long", SQL_LONG},
 	{"register", S_REGISTER},
-	{"short", S_SHORT},
-	{"signed", S_SIGNED},
+	{"short", SQL_SHORT},
+	{"signed", SQL_SIGNED},
 	{"static", S_STATIC},
-	{"struct", S_STRUCT},
-	{"union", S_UNION},
-	{"unsigned", S_UNSIGNED},
-	{"varchar", S_VARCHAR},
+	{"struct", SQL_STRUCT},
+	{"union", UNION},
+	{"unsigned", SQL_UNSIGNED},
+	{"varchar", VARCHAR},
+	{"volatile", S_VOLATILE},
 };
 
 ScanKeyword *
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index 46c29ba2a2d0fe8d6d800e2826957555613c9788..2da1761c6d21fb7592ea3a926eb59f70710722e3 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -1,5 +1,5 @@
 /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
-/* (C) Michael Meskes <meskes@debian.org> Feb 5th, 1998 */
+/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
 /* Placed under the same copyright as PostgresSQL */
 
 #include <unistd.h>
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index e921cf664fb5274654e41a32d3b96adeb203b5d1..682ead43ec81b9154c66c2632833f16da61b7f80 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -40,6 +40,7 @@ extern int	yylex(void);
 extern void yyerror(char *);
 extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
 extern char *mm_strdup(const char *);
+extern void mmerror(enum errortype, char * );
 ScanKeyword *ScanECPGKeywordLookup(char *);
 ScanKeyword *ScanCKeywordLookup(char *);
 
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 7477676d2ffd42aa60397c18038022b3d640bd67..f69f21b94d0dc138790545874f1849e3e147fcb4 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.49 2000/01/26 05:58:41 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.50 2000/01/27 19:00:39 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -246,7 +246,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 					errno = 0;
 					yylval.ival = strtol(literalbuf, &endptr, 2);
 					if (*endptr != '\0' || errno == ERANGE)
-						yyerror("ERROR: Bad binary integer input!");
+						mmerror(ET_ERROR, "Bad binary integer input!");
 					return ICONST;
 				}
 <xh>{xhinside}	|
@@ -268,7 +268,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 					errno = 0;
 					yylval.ival = strtol(literalbuf, &endptr, 16);
 					if (*endptr != '\0' || errno == ERANGE)
-						yyerror("ERROR: Bad hexadecimal integer input");
+						mmerror(ET_ERROR, "Bad hexadecimal integer input");
 					return ICONST;
 				}
 
@@ -355,7 +355,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 						errno = 0;
 						yylval.dval = strtod((char *)yytext,&endptr);
 						if (*endptr != '\0' || errno == ERANGE)
-							yyerror("ERROR: Bad float8 input");
+							mmerror(ET_ERROR, "Bad float8 input");
 						return FCONST;
 					}
 					yylval.str = mm_strdup((char*)yytext);
@@ -367,7 +367,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 					errno = 0;
 					yylval.dval = strtod((char *)yytext,&endptr);
 					if (*endptr != '\0' || errno == ERANGE)
-						yyerror("ERROR: Bad float input");
+						mmerror(ET_ERROR, "Bad float input");
 					return FCONST;
 				}
 <SQL>:{identifier}(("->"|\.){identifier})*	{
@@ -385,6 +385,13 @@ cppline			{space}*#(.*\\{line_end})*.*
 						if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
 							lower_text[i] = tolower(lower_text[i]);
 
+					if (i >= NAMEDATALEN)
+					{
+						sprintf(errortext, "Identifier \"%s\" will be truncated to \"%.*s\"", yytext, NAMEDATALEN-1, yytext);
+						mmerror (ET_WARN, errortext);
+                                                yytext[NAMEDATALEN-1] = '\0';
+					}
+
 					keyword = ScanKeywordLookup((char*)lower_text);
 					if (keyword != NULL) {
 						return keyword->value;
@@ -509,10 +516,10 @@ cppline			{space}*#(.*\\{line_end})*.*
 
 <C,xskip>{exec_sql}{elif}{space_or_nl}*	{	/* pop stack */
 						if ( preproc_tos == 0 ) {
-						    yyerror("ERROR: missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'");
+						    mmerror(ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'");
 						}
 						else if ( stacked_if_value[preproc_tos].else_branch ) {
-						    yyerror("ERROR: missing 'EXEC SQL ENDIF;'");
+						    mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
 						}
 						else {
 						    preproc_tos--;
@@ -523,7 +530,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 
 <C,xskip>{exec_sql}{else}{space_or_nl}*";" {	/* only exec sql endif pops the stack, so take care of duplicated 'else' */
 						if ( stacked_if_value[preproc_tos].else_branch ) {
-						    yyerror("ERROR: duplicated 'EXEC SQL ELSE;'");
+						    mmerror(ET_FATAL, "Duplicated 'EXEC SQL ELSE;'");
 						}
 						else {
 						    stacked_if_value[preproc_tos].else_branch = TRUE;
@@ -541,7 +548,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 					}
 <C,xskip>{exec_sql}{endif}{space_or_nl}*";" { 
 						if ( preproc_tos == 0 ) {
-						    yyerror("ERROR: unmatched 'EXEC SQL ENDIF;'");
+						    mmerror(ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'");
 						}
 						else {
 						    preproc_tos--;
@@ -559,7 +566,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 
 <xcond>{identifier}{space_or_nl}*";" {
 					if ( preproc_tos >= MAX_NESTED_IF-1 ) {
-					    yyerror("ERROR: too many nested 'EXEC SQL IFDEF' conditions");
+					    mmerror(ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions");
 					}
 					else {
 					    struct _defines *defptr;
@@ -680,7 +687,7 @@ cppline			{space}*#(.*\\{line_end})*.*
 			  if ( preproc_tos > 0 ) {
 			      preproc_tos = 0;
 
-			      yyerror("ERROR: missing 'EXEC SQL ENDIF;'");
+			      mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
 			  }
 
 			  if (yy_buffer == NULL)
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index c43ffcfa577fbd9407b033a2c5f85879cd780777..7b8d16f31a474738e1abc94fd153ed4ac0ce2421 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -24,6 +24,7 @@ int	struct_level = 0;
 char	errortext[128];
 static char	*connection = NULL;
 static int      QueryIsRule = 0, ForUpdateNotAllowed = 0, FoundInto = 0;
+static int	initializer = 0;
 static struct this_type actual_type[STRUCT_DEPTH];
 static char     *actual_storage[STRUCT_DEPTH];
 static char     *actual_startline[STRUCT_DEPTH];
@@ -36,12 +37,10 @@ struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
 
 struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, {NULL}};
 
-enum errortype {ET_WARN, ET_ERROR, ET_FATAL};
-
 /*
  * Handle parsing errors and warnings
  */
-static void
+void
 mmerror(enum errortype type, char * error)
 {
 
@@ -643,10 +642,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
 %token		SQL_VAR SQL_WHENEVER
 
 /* C token */
-%token		S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN
-%token		S_FLOAT S_INT S
-%token		S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
-%token		S_UNION S_UNSIGNED S_VARCHAR
+%token		S_ANYTHING S_AUTO S_CONST S_EXTERN
+%token		S_REGISTER S_STATIC S_VOLATILE
 
 /* I need this and don't know where it is defined inside the backend */
 %token		TYPECAST
@@ -814,21 +811,20 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
 %type  <str>	indicator ECPGExecute ECPGPrepare ecpg_using
 %type  <str>    storage_clause opt_initializer c_anything blockstart
 %type  <str>    blockend variable_list variable c_thing c_term
-%type  <str>	opt_pointer cvariable ECPGDisconnect dis_name
+%type  <str>	opt_pointer cvariable ECPGDisconnect dis_name storage_modifier
 %type  <str>	stmt symbol opt_symbol ECPGRelease execstring server_name
 %type  <str>	connection_object opt_server opt_port c_stuff opt_reference
 %type  <str>    user_name opt_user char_variable ora_user ident
 %type  <str>    db_prefix server opt_options opt_connection_name c_list
-%type  <str>	ECPGSetConnection cpp_line s_enum ECPGTypedef c_args
+%type  <str>	ECPGSetConnection cpp_line ECPGTypedef c_args
 %type  <str>	enum_type civariableonly ECPGCursorStmt ECPGDeallocate
-%type  <str>	ECPGFree ECPGDeclare ECPGVar sql_variable_declarations
-%type  <str>	sql_declaration sql_variable_list sql_variable opt_at
+%type  <str>	ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
 %type  <str>    struct_type s_struct declaration declarations variable_declarations
 %type  <str>    s_struct s_union union_type ECPGSetAutocommit on_off
 
-%type  <type_enum> simple_type varchar_type
+%type  <type_enum> simple_type signed_type unsigned_type varchar_type
 
-%type  <type>	type ctype
+%type  <type>	type
 
 %type  <action> action
 
@@ -943,7 +939,8 @@ stmt:  AlterTableStmt			{ output_statement($1, 0); }
 						output_statement($1, 0);
 					}
 		| ECPGFree		{
-						fprintf(yyout, "{ ECPGdeallocate(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); 
+						fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
+
 						whenever_action(2);
 						free($1);
 					}
@@ -1320,9 +1317,9 @@ DEFAULT} */
 		}
 /* ALTER TABLE <name> DROP [COLUMN] <name> {RESTRICT|CASCADE} */
 	| ALTER TABLE relation_name opt_inh_star DROP opt_column ColId
-		drop_behavior
+		/* drop_behavior */
 		{
-			$$ = cat_str(6, make_str("alter table"), $3, $4, make_str("drop"), $6, $7, $8);
+			$$ = cat_str(5, make_str("alter table"), $3, $4, make_str("drop"), $6, $7);
 		}
 /* ALTER TABLE <name> ADD CONSTRAINT ... */
 	| ALTER TABLE relation_name opt_inh_star ADD TableConstraint
@@ -2584,21 +2581,21 @@ createdb_opt_location:  LOCATION '=' Sconst	{ $$ = cat2_str(make_str("location =
 createdb_opt_encoding:  ENCODING '=' Sconst  
 			{
 #ifndef MULTIBYTE
-				mmerror(ET_ERROR, "WITH ENCODING is not supported.");
+				mmerror(ET_ERROR, "Multi-byte support is not enabled.");
 #endif
 				$$ = cat2_str(make_str("encoding ="), $3);
 			}
 		| ENCODING '=' Iconst  
 			{
 #ifndef MULTIBYTE
-				mmerror(ET_ERROR, "WITH ENCODING is not supported.");
+				mmerror(ET_ERROR, "Multi-byte support is not enabled.");
 #endif
 				$$ = cat2_str(make_str("encoding ="), $3);
 			}
 		| ENCODING '=' DEFAULT
 			{
 #ifndef MULTIBYTE
-				mmerror(ET_ERROR, "WITH ENCODING is not supported.");
+				mmerror(ET_ERROR, "Multi-byte support is not enabled.");
 #endif
 				$$ = make_str("encoding = default");
 			}
@@ -3405,17 +3402,16 @@ opt_decimal:  '(' Iconst ',' Iconst ')'
 				}
 		;
 
-/* SQL92 character data types
+/* 
+ * SQL92 character data types
  * The following implements CHAR() and VARCHAR().
  *								- ay 6/95
  */
 Character:  character '(' Iconst ')'
 				{
-					if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar")))
-						mmerror(ET_ERROR, "internal parsing error; unrecognized character type");
 					if (atol($3) < 1)
 					{
-						sprintf(errortext, "length for '%s' type must be at least 1",$1);
+						sprintf(errortext, "length for type '%s' type must be at least 1",$1);
 						mmerror(ET_ERROR, errortext);
 					}
 					else if (atol($3) > MaxAttrSize)
@@ -4332,7 +4328,9 @@ ColLabel:  ColId			{ $$ = $1; }
 		| EXPLAIN		{ $$ = make_str("explain"); }
 		| EXTEND		{ $$ = make_str("extend"); }
 		| FALSE_P		{ $$ = make_str("false"); }
+		| FLOAT			{ $$ = make_str("float"); }
 		| FOREIGN		{ $$ = make_str("foreign"); }
+		| GLOBAL		{ $$ = make_str("global"); }
 		| GROUP			{ $$ = make_str("group"); }
 		| LISTEN		{ $$ = make_str("listen"); }
 		| LOAD			{ $$ = make_str("load"); }
@@ -4620,30 +4618,40 @@ variable_declarations:  /* empty */ { $$ = EMPTY; }
 declarations:  declaration { $$ = $1; }
 			| declarations declaration { $$ = cat2_str($1, $2); }
 
-declaration: storage_clause
+declaration: storage_clause storage_modifier
 	{
-		actual_storage[struct_level] = mm_strdup($1);
+		actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
 		actual_startline[struct_level] = hashline_number();
 	}
 	type
 	{
-		actual_type[struct_level].type_enum = $3.type_enum;
-		actual_type[struct_level].type_dimension = $3.type_dimension;
-		actual_type[struct_level].type_index = $3.type_index;
+		actual_type[struct_level].type_enum = $4.type_enum;
+		actual_type[struct_level].type_dimension = $4.type_dimension;
+		actual_type[struct_level].type_index = $4.type_index;
+
+		/* we do not need the string "varchar" for output */
+		/* so replace it with an empty string */
+		if ($4.type_enum == ECPGt_varchar)
+		{
+			free($4.type_str);
+			$4.type_str=EMPTY;
+		}
 	}
 	variable_list ';'
 	{
- 		$$ = cat_str(5, actual_startline[struct_level], $1, $3.type_str, $5, make_str(";\n"));
+ 		$$ = cat_str(6, actual_startline[struct_level], $1, $2, $4.type_str, $6, make_str(";\n"));
 	}
 
 storage_clause : S_EXTERN	{ $$ = make_str("extern"); }
        | S_STATIC		{ $$ = make_str("static"); }
-       | S_SIGNED		{ $$ = make_str("signed"); }
-       | S_CONST		{ $$ = make_str("const"); }
        | S_REGISTER		{ $$ = make_str("register"); }
        | S_AUTO			{ $$ = make_str("auto"); }
        | /* empty */		{ $$ = EMPTY; }
 
+storage_modifier : S_CONST      { $$ = make_str("const"); }
+       | S_VOLATILE             { $$ = make_str("volatile"); }
+       | /* empty */            { $$ = EMPTY; }
+
 type: simple_type
 		{
 			$$.type_enum = $1;
@@ -4654,7 +4662,7 @@ type: simple_type
 	| varchar_type
 		{
 			$$.type_enum = ECPGt_varchar;
-			$$.type_str = EMPTY;
+			$$.type_str = make_str("varchar");;
 			$$.type_dimension = -1;
   			$$.type_index = -1;
 		}
@@ -4691,12 +4699,16 @@ type: simple_type
 			struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
 		}
 
-enum_type: s_enum '{' c_list '}'
+enum_type: SQL_ENUM opt_symbol enum_definition
 	{
-		$$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
+		$$ = cat_str(3, make_str("enum"), $2, $3);
+	}
+	|  SQL_ENUM symbol
+	{
+		$$ = cat2_str(make_str("enum"), $2);
 	}
-	
-s_enum: S_ENUM opt_symbol	{ $$ = cat2_str(make_str("enum"), $2); }
+
+enum_definition: '{' c_list '}'	{ $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
 
 struct_type: s_struct '{' variable_declarations '}'
 	{
@@ -4712,38 +4724,64 @@ union_type: s_union '{' variable_declarations '}'
 	    $$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
 	}
 
-s_struct : S_STRUCT opt_symbol
+s_struct: SQL_STRUCT opt_symbol
         {
             struct_member_list[struct_level++] = NULL;
             if (struct_level >= STRUCT_DEPTH)
                  mmerror(ET_ERROR, "Too many levels in nested structure definition");
+
+	    /* reset this variable so we see if there was */
+	    /* an initializer specified */
+	    initializer = 0;
+
 	    $$ = cat2_str(make_str("struct"), $2);
 	}
 
-s_union : S_UNION opt_symbol
+s_union: UNION opt_symbol
         {
             struct_member_list[struct_level++] = NULL;
             if (struct_level >= STRUCT_DEPTH)
                  mmerror(ET_ERROR, "Too many levels in nested structure definition");
+
+	    /* reset this variable so we see if there was */
+	    /* an initializer specified */
+	    initializer = 0;
+
 	    $$ = cat2_str(make_str("union"), $2);
 	}
 
 opt_symbol: /* empty */ 	{ $$ = EMPTY; }
 	| symbol		{ $$ = $1; }
 
-simple_type: S_SHORT		{ $$ = ECPGt_short; }
-           | S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; }
-	   | S_INT 		{ $$ = ECPGt_int; }
-           | S_UNSIGNED S_INT	{ $$ = ECPGt_unsigned_int; }
-	   | S_LONG		{ $$ = ECPGt_long; }
-           | S_UNSIGNED S_LONG	{ $$ = ECPGt_unsigned_long; }
-           | S_FLOAT		{ $$ = ECPGt_float; }
-           | S_DOUBLE		{ $$ = ECPGt_double; }
-	   | S_BOOL		{ $$ = ECPGt_bool; };
-	   | S_CHAR		{ $$ = ECPGt_char; }
-           | S_UNSIGNED S_CHAR	{ $$ = ECPGt_unsigned_char; }
+simple_type: unsigned_type		{ $$=$1; }
+	|	opt_signed signed_type	{ $$=$2; }
+	;
 
-varchar_type:  S_VARCHAR		{ $$ = ECPGt_varchar; }
+unsigned_type: SQL_UNSIGNED SQL_SHORT 			{ $$ = ECPGt_unsigned_short; }
+		| SQL_UNSIGNED SQL_SHORT SQL_INT	{ $$ = ECPGt_unsigned_short; }
+		| SQL_UNSIGNED 				{ $$ = ECPGt_unsigned_int; }
+		| SQL_UNSIGNED SQL_INT			{ $$ = ECPGt_unsigned_int; }
+		| SQL_UNSIGNED SQL_LONG			{ $$ = ECPGt_unsigned_long; }
+		| SQL_UNSIGNED SQL_LONG SQL_INT		{ $$ = ECPGt_unsigned_long; }
+	        | SQL_UNSIGNED CHAR			{ $$ = ECPGt_unsigned_char; }
+		;
+
+signed_type: SQL_SHORT          { $$ = ECPGt_short; }
+           | SQL_SHORT SQL_INT  { $$ = ECPGt_short; }
+           | SQL_INT            { $$ = ECPGt_int; }
+           | SQL_LONG           { $$ = ECPGt_long; }
+           | SQL_LONG SQL_INT   { $$ = ECPGt_long; }
+           | SQL_BOOL   	{ $$ = ECPGt_bool; };
+           | FLOAT         	{ $$ = ECPGt_float; }
+           | DOUBLE 	        { $$ = ECPGt_double; }
+           | CHAR            	{ $$ = ECPGt_char; }
+	   ;
+
+opt_signed:	SQL_SIGNED
+	|	/* EMPTY */
+	;
+
+varchar_type:  VARCHAR		{ $$ = ECPGt_varchar; }
 
 variable_list: variable 
 	{
@@ -4830,7 +4868,10 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer
 		}
 
 opt_initializer: /* empty */		{ $$ = EMPTY; }
-	| '=' c_term			{ $$ = cat2_str(make_str("="), $2); }
+	| '=' c_term			{ 
+						initializer = 1;
+						$$ = cat2_str(make_str("="), $2);
+					}
 
 opt_pointer: /* empty */	{ $$ = EMPTY; }
 	| '*'			{ $$ = make_str("*"); }
@@ -4966,19 +5007,24 @@ ECPGSetConnection:  SET SQL_CONNECTION to_equal connection_object
 /*
  * define a new type for embedded SQL
  */
-ECPGTypedef: TYPE_P symbol IS ctype opt_type_array_bounds opt_reference
+ECPGTypedef: TYPE_P symbol IS type opt_type_array_bounds opt_reference
 	{
 		/* add entry to list */
 		struct typedefs *ptr, *this;
 		int dimension = $5.index1;
 		int length = $5.index2;
 
+		if (($4.type_enum == ECPGt_struct ||
+		     $4.type_enum == ECPGt_union) &&
+		    initializer == 1)
+			mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+
 		for (ptr = types; ptr != NULL; ptr = ptr->next)
 		{
 			if (strcmp($2, ptr->name) == 0)
 			{
 			        /* re-definition is a bug */
-				sprintf(errortext, "type %s already defined", $2);
+				sprintf(errortext, "Type %s already defined", $2);
 				mmerror(ET_ERROR, errortext);
 	                }
 		}
@@ -5050,237 +5096,21 @@ opt_type_array_bounds:  '[' ']' opt_type_array_bounds
 opt_reference: SQL_REFERENCE { $$ = make_str("reference"); }
 	| /* empty */ 	     { $$ = EMPTY; }
 
-ctype: CHAR
-	{
-		$$.type_str = make_str("char");
-                $$.type_enum = ECPGt_char;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| VARCHAR
-	{
-		$$.type_str = make_str("varchar");
-                $$.type_enum = ECPGt_varchar;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| FLOAT
-	{
-		$$.type_str = make_str("float");
-                $$.type_enum = ECPGt_float;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| DOUBLE
-	{
-		$$.type_str = make_str("double");
-                $$.type_enum = ECPGt_double;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| opt_signed SQL_INT
-	{
-		$$.type_str = make_str("int");
-       	        $$.type_enum = ECPGt_int;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| SQL_ENUM
-	{
-		$$.type_str = make_str("int");
-       	        $$.type_enum = ECPGt_int;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| opt_signed SQL_SHORT
-	{
-		$$.type_str = make_str("short");
-       	        $$.type_enum = ECPGt_short;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| opt_signed SQL_LONG
-	{
-		$$.type_str = make_str("long");
-       	        $$.type_enum = ECPGt_long;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| SQL_BOOL
-	{
-		$$.type_str = make_str("bool");
-       	        $$.type_enum = ECPGt_bool;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| SQL_UNSIGNED SQL_INT
-	{
-		$$.type_str = make_str("unsigned int");
-       	        $$.type_enum = ECPGt_unsigned_int;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| SQL_UNSIGNED SQL_SHORT
-	{
-		$$.type_str = make_str("unsigned short");
-       	        $$.type_enum = ECPGt_unsigned_short;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| SQL_UNSIGNED SQL_LONG
-	{
-		$$.type_str = make_str("unsigned long");
-       	        $$.type_enum = ECPGt_unsigned_long;
-		$$.type_index = -1;
-		$$.type_dimension = -1;
-	}
-	| SQL_STRUCT
-	{
-		struct_member_list[struct_level++] = NULL;
-		if (struct_level >= STRUCT_DEPTH)
-        		mmerror(ET_ERROR, "Too many levels in nested structure definition");
-	} '{' sql_variable_declarations '}'
-	{
-		ECPGfree_struct_member(struct_member_list[struct_level--]);
-		$$.type_str = cat_str(3, make_str("struct {"), $4, make_str("}"));
-		$$.type_enum = ECPGt_struct;
-                $$.type_index = -1;
-                $$.type_dimension = -1;
-	}
-	| UNION
-	{
-		struct_member_list[struct_level++] = NULL;
-		if (struct_level >= STRUCT_DEPTH)
-        		mmerror(ET_ERROR, "Too many levels in nested structure definition");
-	} '{' sql_variable_declarations '}'
-	{
-		ECPGfree_struct_member(struct_member_list[struct_level--]);
-		$$.type_str = cat_str(3, make_str("union {"), $4, make_str("}"));
-		$$.type_enum = ECPGt_union;
-                $$.type_index = -1;
-                $$.type_dimension = -1;
-	}
-	| symbol
-	{
-		struct typedefs *this = get_typedef($1);
-
-		$$.type_str = mm_strdup($1);
-		$$.type_enum = this->type->type_enum;
-		$$.type_dimension = this->type->type_dimension;
-		$$.type_index = this->type->type_index;
-		struct_member_list[struct_level] = this->struct_member_list;
-	}
-
-opt_signed: SQL_SIGNED | /* empty */
-
-sql_variable_declarations: /* empty */
-	{
-		$$ = EMPTY;
-	}
-	| sql_declaration sql_variable_declarations
-	{
-		$$ = cat2_str($1, $2);
-	}
-	;
-
-sql_declaration: ctype
-	{
-		actual_type[struct_level].type_enum = $1.type_enum;
-		actual_type[struct_level].type_dimension = $1.type_dimension;
-		actual_type[struct_level].type_index = $1.type_index;
-	}
-	sql_variable_list ';'
-	{
-		$$ = cat_str(3, $1.type_str, $3, make_str(";"));
-	}
-
-sql_variable_list: sql_variable 
-	{
-		$$ = $1;
-	}
-	| sql_variable_list ',' sql_variable
-	{
-		$$ = cat_str(3, $1, make_str(","), $3);
-	}
-
-sql_variable: opt_pointer symbol opt_array_bounds
-		{
-			int dimension = $3.index1;
-			int length = $3.index2;
-			struct ECPGtype * type;
-                        char dim[14L];
-
-			adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1));
-
-			switch (actual_type[struct_level].type_enum)
-			{
-			   case ECPGt_struct:
-			   case ECPGt_union:
-                               if (dimension < 0)
-                                   type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum);
-                               else
-                                   type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum), dimension); 
-
-                               break;
-                           case ECPGt_varchar:
-                               if (dimension == -1)
-                                   type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
-                               else
-                                   type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
-
-                               switch(dimension)
-                               {
-                                  case 0:
-                                      strcpy(dim, "[]");
-                                      break;
-				  case -1:
-                                  case 1:
-                                      *dim = '\0';
-                                      break;
-                                  default:
-                                      sprintf(dim, "[%d]", dimension);
-                                      break;
-                                }
-
-                               break;
-                           case ECPGt_char:
-                           case ECPGt_unsigned_char:
-                               if (dimension == -1)
-                                   type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
-                               else
-                                   type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
-
-                               break;
-                           default:
-			       if (length >= 0)
-                	            mmerror(ET_ERROR, "No multi-dimensional array support for simple data types");
-
-                               if (dimension < 0)
-                                   type = ECPGmake_simple_type(actual_type[struct_level].type_enum, 1);
-                               else
-                                   type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, 1), dimension);
-
-                               break;
-			}
-
-			if (struct_level == 0)
-				new_variable($2, type);
-			else
-				ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
-
-			$$ = cat_str(3, $1, $2, $3.str);
-		}
-
 /*
  * define the type of one variable for embedded SQL
  */
-ECPGVar: SQL_VAR symbol IS ctype opt_type_array_bounds opt_reference
+ECPGVar: SQL_VAR symbol IS type opt_type_array_bounds opt_reference
 	{
 		struct variable *p = find_variable($2);
 		int dimension = $5.index1;
 		int length = $5.index2;
 		struct ECPGtype * type;
 
+		if (($4.type_enum == ECPGt_struct ||
+		     $4.type_enum == ECPGt_union) &&
+		    initializer == 1)
+			mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+
 		adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6));
 
 		switch ($4.type_enum)
@@ -5561,25 +5391,25 @@ c_anything:  IDENT 	{ $$ = $1; }
 	| '-'		{ $$ = make_str("-"); }
 	| '/'		{ $$ = make_str("/"); }
 	| '%'		{ $$ = make_str("%"); }
+	| S_ANYTHING	{ $$ = make_name(); }
 	| S_AUTO	{ $$ = make_str("auto"); }
-	| S_BOOL	{ $$ = make_str("bool"); }
-	| S_CHAR	{ $$ = make_str("char"); }
 	| S_CONST	{ $$ = make_str("const"); }
-	| S_DOUBLE	{ $$ = make_str("double"); }
-	| S_ENUM	{ $$ = make_str("enum"); }
 	| S_EXTERN	{ $$ = make_str("extern"); }
-	| S_FLOAT	{ $$ = make_str("float"); }
-        | S_INT		{ $$ = make_str("int"); }
-	| S_LONG	{ $$ = make_str("long"); }
 	| S_REGISTER	{ $$ = make_str("register"); }
-	| S_SHORT	{ $$ = make_str("short"); }
-	| S_SIGNED	{ $$ = make_str("signed"); }
 	| S_STATIC	{ $$ = make_str("static"); }
-        | S_STRUCT	{ $$ = make_str("struct"); }
-        | S_UNION	{ $$ = make_str("union"); }
-	| S_UNSIGNED	{ $$ = make_str("unsigned"); }
-	| S_VARCHAR	{ $$ = make_str("varchar"); }
-	| S_ANYTHING	{ $$ = make_name(); }
+	| SQL_BOOL	{ $$ = make_str("bool"); }
+	| SQL_ENUM	{ $$ = make_str("enum"); }
+        | SQL_INT	{ $$ = make_str("int"); }
+	| SQL_LONG	{ $$ = make_str("long"); }
+	| SQL_SHORT	{ $$ = make_str("short"); }
+	| SQL_SIGNED	{ $$ = make_str("signed"); }
+        | SQL_STRUCT	{ $$ = make_str("struct"); }
+	| SQL_UNSIGNED	{ $$ = make_str("unsigned"); }
+	| CHAR		{ $$ = make_str("char"); }
+	| DOUBLE	{ $$ = make_str("double"); }
+	| FLOAT		{ $$ = make_str("float"); }
+        | UNION		{ $$ = make_str("union"); }
+	| VARCHAR	{ $$ = make_str("varchar"); }
         | '['		{ $$ = make_str("["); }
 	| ']'		{ $$ = make_str("]"); }
 /*        | '('		{ $$ = make_str("("); }
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 1af1e63344fb3f711b37f3a557456c6cf1c848ed..efc8c6692382905f61b6a3ec827f3146567274d0 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -138,3 +138,5 @@ struct arguments
 	struct variable *indicator;
 	struct arguments *next;
 };
+
+enum errortype {ET_WARN, ET_ERROR, ET_FATAL};
diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
index e183ebc4b9f60b6a07b0cf5721fef72d9334dbdd..0af784f8eab6faff4f1157417f274c82209c650b 100644
--- a/src/interfaces/ecpg/test/Makefile
+++ b/src/interfaces/ecpg/test/Makefile
@@ -1,10 +1,12 @@
-all: test1 test2 test3 test4 perftest
+all: stp.so test1 test2 test3 test4 test5 perftest
 
 #LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt
 LDFLAGS=-g -I../include -I/usr/include/postgresql  -L/usr/lib/postgresql -L../lib -lecpg -lpq -lcrypt
+#LDFLAGS=-g -I/usr/include/postgresql -lecpg -lpq -lcrypt
 
 #ECPG=/usr/local/pgsql/bin/ecpg
 ECPG=../preproc/ecpg -I../include
+#ECPG=/usr/bin/ecpg -I/usr/include/postgresql
 
 .SUFFIXES: .pgc .c
 
@@ -12,10 +14,16 @@ test1: test1.c
 test2: test2.c
 test3: test3.c
 test4: test4.c
+test5: test5.c
 perftest: perftest.c
 
 .pgc.c:
 	$(ECPG) $? 
 
+stp.so: stp.c
+	cc -fPIC -I../include -I/usr/include/postgresql -c -o stp.o stp.c
+	cc -shared -Wl,-soname,stp.so -o stp.so stp.o -lpq -lecpg
+
+
 clean:
-	-/bin/rm test1 test2 test3 test4 perftest *.c log
+	-/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so
diff --git a/src/interfaces/ecpg/test/stp.pgc b/src/interfaces/ecpg/test/stp.pgc
new file mode 100644
index 0000000000000000000000000000000000000000..6021ae0db40ff14673e936a2771a8fa855ad66ea
--- /dev/null
+++ b/src/interfaces/ecpg/test/stp.pgc
@@ -0,0 +1,16 @@
+EXEC SQL INCLUDE sqlca;
+
+int my_fun (void)
+	{
+	EXEC SQL BEGIN DECLARE SECTION;
+	int			sql_index = 0;
+	EXEC SQL END DECLARE SECTION;	
+
+	EXEC SQL WHENEVER SQLERROR GOTO Error;
+	EXEC SQL SELECT MIN(index) INTO :sql_index FROM tab;
+
+	return (sql_index);
+
+Error:
+	return (sqlca.sqlcode);	
+	}
diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc
index d8980ade54ba2742350c5a571d70668739d3b280..02a631a12f51ba7abe51da0c60db8d16a0fd8bae 100644
--- a/src/interfaces/ecpg/test/test1.pgc
+++ b/src/interfaces/ecpg/test/test1.pgc
@@ -94,11 +94,20 @@ exec sql end declare section;
         strcpy(msg, "select");
         exec sql select name, amount, letter into :name, :amount, :letter from "Test";
 
+	printf("Database: mm\n");
         for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
+	{
             printf("name[%d]=%8.8s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
+	    amount[i]+=1000;
+	}
 
+	strcpy(msg, "insert");
+	exec sql at pm insert into "Test" (name, amount, letter) values (:name, :amount, :letter);
+
+        strcpy(msg, "select");
         exec sql at pm select * into :name, :amount, :letter from "Test";
 
+	printf("Database: pm\n");
         for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
             printf("name[%d]=%8.8s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
         
diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc
index 3288b7df6a58bbd5b4b2675fdcd85e48629c8963..2c5d16c4448773216fd5e7a5879a5b77998b1dda 100644
--- a/src/interfaces/ecpg/test/test2.pgc
+++ b/src/interfaces/ecpg/test/test2.pgc
@@ -62,7 +62,7 @@ exec sql end declare section;
 
 	while (1) {
 		strcpy(msg, "fetch");
-		exec sql fetch from cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint;
+		exec sql fetch cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint;
 		printf("%8.8s", personal.name.arr);
 		if (ind_personal.ind_birth.born >= 0)
 			printf(", born %d", personal.birth.born);
diff --git a/src/interfaces/ecpg/test/test3.pgc b/src/interfaces/ecpg/test/test3.pgc
index 8e0f6c30c6ef55259b3c531609e324f6b883af14..8ba8995e3347968720abb97291357e520e9fd2fa 100644
--- a/src/interfaces/ecpg/test/test3.pgc
+++ b/src/interfaces/ecpg/test/test3.pgc
@@ -19,7 +19,7 @@ exec sql begin declare section;
 	int ind_children;
 	str *married = NULL;
 	char *wifesname="Petra";
-	char *query="select * from meskes where name = :var1";
+	char *query="select * from meskes where name = ?";
 exec sql end declare section;
 
 	exec sql declare cur cursor for
@@ -54,7 +54,7 @@ exec sql end declare section;
 
 	while (1) {
 		strcpy(msg, "fetch");
-		exec sql fetch cur into :personal:ind_personal, :married:ind_married, :children:ind_children;
+		exec sql fetch from cur into :personal:ind_personal, :married:ind_married, :children:ind_children;
 		printf("%8.8s", personal.name.arr);
 		if (ind_personal.ind_birth.born >= 0)
 			printf(", born %d", personal.birth.born);
@@ -74,7 +74,7 @@ exec sql end declare section;
 	exec sql close cur;
 
 	/* and now a query with prepare */
-	exec sql prepare MM from "select name, born, age, married, children from meskes where name = ?";
+	exec sql prepare MM from :query;
 	exec sql declare prep cursor for MM;
 
 	strcpy(msg, "open");
diff --git a/src/interfaces/ecpg/test/test5.pgc b/src/interfaces/ecpg/test/test5.pgc
new file mode 100644
index 0000000000000000000000000000000000000000..1e0c60c4ddbff5b14afd44bd5b27a8699ebc0742
--- /dev/null
+++ b/src/interfaces/ecpg/test/test5.pgc
@@ -0,0 +1,61 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+EXEC SQL INCLUDE sqlca;
+
+static void ErrorExit (void);
+
+int main (void)
+	{
+	EXEC SQL BEGIN DECLARE SECTION;
+	int			result;
+	int			values[2], i;
+	EXEC SQL END DECLARE SECTION;
+	FILE *dbgs;
+	
+	
+        if ((dbgs = fopen("log", "w")) != NULL)
+                ECPGdebug(1, dbgs);
+
+	EXEC SQL WHENEVER SQLERROR DO ErrorExit();
+	EXEC SQL CONNECT TO 'mm';
+	EXEC SQL CREATE TABLE tab (index int);
+	EXEC SQL INSERT INTO tab(index) values(14);
+	EXEC SQL INSERT INTO tab(index) values(7);
+	EXEC SQL COMMIT;
+
+	EXEC SQL CREATE FUNCTION my_fun () RETURNS int AS
+		'/home/postgres/pgsql/src/interfaces/ecpg.mm/test/stp.so' LANGUAGE 'C';
+	EXEC SQL COMMIT;
+
+	EXEC SQL SELECT index INTO :values FROM tab;
+	for (i = 0; i < 2; i++)
+		printf("tab[%d] = %d\n", i, values[i]);
+
+	EXEC SQL SELECT my_fun () INTO :result;
+	printf ("result = %d\n", result);
+	
+	EXEC SQL DROP TABLE tab;
+	EXEC SQL DROP FUNCTION my_fun ();
+	EXEC SQL COMMIT;
+	EXEC SQL DISCONNECT;
+
+	if (dbgs != NULL)
+                fclose(dbgs);
+	exit (0);
+	}
+
+	
+static void ErrorExit (void)
+	{
+	EXEC SQL WHENEVER SQLERROR CONTINUE;
+	
+	sqlprint();
+
+	EXEC SQL DROP TABLE tab;
+	EXEC SQL DROP FUNCTION my_fun ();
+	EXEC SQL COMMIT;
+
+	EXEC SQL DISCONNECT;
+	exit (-1);
+	}