The next one:

diff -rcN ecpg/ChangeLog ecpg.mm/ChangeLog
*** ecpg/ChangeLog	Tue Apr 21 15:22:19 1998
--- ecpg.mm/ChangeLog	Thu Apr 23 13:55:53 1998
***************
*** 126,128 ****
--- 126,137 ----
  
  	- Set indicator to amount of data really written (truncation).
  
+ Thu Apr 23 09:27:16 CEST 1998
+ 
+ 	- Also allow call in whenever statement with the same functionality
+ 	  as do.
+ 
+ Thu Apr 23 12:29:28 CEST 1998
+ 
+ 	- Also rewrote variable declaration part. It is now possible to
+ 	  declare more than one variable per line.
diff -rcN ecpg/preproc/Makefile ecpg.mm/preproc/Makefile
*** ecpg/preproc/Makefile	Tue Apr 21 15:22:21 1998
--- ecpg.mm/preproc/Makefile	Thu Apr 23 14:25:39 1998
***************
*** 2,8 ****
  include $(SRCDIR)/Makefile.global
  
  MAJOR_VERSION=2
! MINOR_VERSION=0
  PATCHLEVEL=0
  
  CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
--- 2,8 ----
  include $(SRCDIR)/Makefile.global
  
  MAJOR_VERSION=2
! MINOR_VERSION=1
  PATCHLEVEL=0
  
  CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
diff -rcN ecpg/preproc/ecpg_keywords.c ecpg.mm/preproc/ecpg_keywords.c
*** ecpg/preproc/ecpg_keywords.c	Tue Apr 21 15:23:03 1998
--- ecpg.mm/preproc/ecpg_keywords.c	Thu Apr 23 09:26:52 1998
***************
*** 21,26 ****
--- 21,27 ----
   */
  static ScanKeyword ScanKeywords[] = {
  	/* name					value			*/
+ 	{"call", SQL_CALL},
  	{"connect", SQL_CONNECT},
  	{"continue", SQL_CONTINUE},
  	{"found", SQL_FOUND},
diff -rcN ecpg/preproc/extern.h ecpg.mm/preproc/extern.h
*** ecpg/preproc/extern.h	Tue Apr 21 15:22:21 1998
--- ecpg.mm/preproc/extern.h	Thu Apr 23 14:09:38 1998
***************
*** 23,28 ****
--- 23,40 ----
  
  extern struct cursor *cur;
  
+ /* This is a linked list of the variable names and types. */
+ struct variable
+ {
+     char * name;
+     struct ECPGtype * type;
+     int brace_level;
+     struct variable * next;
+ };
+                 
+ extern struct ECPGtype ecpg_no_indicator;
+ extern struct variable no_indicator;
+ 
  /* functions */
  
  extern void lex_init(void);
diff -rcN ecpg/preproc/pgc.l ecpg.mm/preproc/pgc.l
*** ecpg/preproc/pgc.l	Tue Apr 21 15:22:23 1998
--- ecpg.mm/preproc/pgc.l	Thu Apr 23 13:09:59 1998
***************
*** 70,75 ****
--- 70,76 ----
  %x xb
  %x xc
  %x xd
+ %x xdc
  %x xh
  %x xm
  %x xq
***************
*** 261,267 ****
  <xd>{xdstop}	{
  					BEGIN(SQL);
  					yylval.str = strdup(literal);
! 					return (IDENT);
  				}
  <xd>{xdinside}	{
  					if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
--- 262,268 ----
  <xd>{xdstop}	{
  					BEGIN(SQL);
  					yylval.str = strdup(literal);
! 					return (CSTRING);
  				}
  <xd>{xdinside}	{
  					if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
***************
*** 269,275 ****
  					memcpy(literal+llen, yytext, yyleng+1);
  					llen += yyleng;
  				}
! 
  
  <xm>{space}*	{ /* ignore */ }
  <xm>{xmstop}	{
--- 270,291 ----
  					memcpy(literal+llen, yytext, yyleng+1);
  					llen += yyleng;
  				}
! <C>{xdstart}		{
! 					BEGIN(xdc);
! 					llen = 0;
! 					*literal = '\0';
! 				}
! <xdc>{xdstop}	{
! 					BEGIN(C);
! 					yylval.str = strdup(literal);
! 					return (CSTRING);
! 				}
! <xdc>{xdinside}	{
! 					if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
! 						yyerror("ERROR: quoted string parse buffer exceeded");
! 					memcpy(literal+llen, yytext, yyleng+1);
! 					llen += yyleng;
! 				}
  
  <xm>{space}*	{ /* ignore */ }
  <xm>{xmstop}	{
***************
*** 283,289 ****
  <SQL>{self}/-[\.0-9]		{
  					return (yytext[0]);
  				}
! <SQL>{self}			{ 	return (yytext[0]); }
  <SQL>{operator}/-[\.0-9]	{
  					yylval.str = strdup((char*)yytext);
  					return (Op);
--- 299,305 ----
  <SQL>{self}/-[\.0-9]		{
  					return (yytext[0]);
  				}
! <SQL>{self}				{ 	return (yytext[0]); }
  <SQL>{operator}/-[\.0-9]	{
  					yylval.str = strdup((char*)yytext);
  					return (Op);
***************
*** 423,434 ****
  					}
  				}
  <C>";"	      	        { return(';'); }
  <C>{space}		{ ECHO; }
! \{			{ return('{'); }
! \}			{ return('}'); }
! \[			{ return('['); }
! \]			{ return(']'); }
! \=			{ return('='); }
  <C>{other}			{ return (S_ANYTHING); }
  <C>{exec}{space}{sql}{space}{include}	{ BEGIN(incl); }
  <incl>{space}		/* eat the whitespace */
--- 439,452 ----
  					}
  				}
  <C>";"	      	        { return(';'); }
+ <C>","	      	        { return(','); }
+ <C>"*"	      	        { return('*'); }
  <C>{space}		{ ECHO; }
! <C>\{			{ return('{'); }
! <C>\}			{ return('}'); }
! <C>\[			{ return('['); }
! <C>\]			{ return(']'); }
! <C>\=			{ return('='); }
  <C>{other}			{ return (S_ANYTHING); }
  <C>{exec}{space}{sql}{space}{include}	{ BEGIN(incl); }
  <incl>{space}		/* eat the whitespace */
diff -rcN ecpg/preproc/preproc.y ecpg.mm/preproc/preproc.y
*** ecpg/preproc/preproc.y	Tue Apr 21 15:23:26 1998
--- ecpg.mm/preproc/preproc.y	Thu Apr 23 14:06:24 1998
***************
*** 12,20 ****
   * Variables containing simple states.
   */
  static int	struct_level = 0;
! static char	*do_str = NULL, errortext[128];
! static int	do_length = 0;
  static int      QueryIsRule = 0;
  
  /* temporarily store record members while creating the data structure */
  struct ECPGrecord_member *record_member_list[128] = { NULL };
--- 12,21 ----
   * Variables containing simple states.
   */
  static int	struct_level = 0;
! static char	errortext[128];
  static int      QueryIsRule = 0;
+ static enum ECPGttype actual_type[128];
+ static char     *actual_storage[128];
  
  /* temporarily store record members while creating the data structure */
  struct ECPGrecord_member *record_member_list[128] = { NULL };
***************
*** 22,27 ****
--- 23,31 ----
  /* keep a list of cursors */
  struct cursor *cur = NULL;
  
+ struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
+ struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
+ 
  /*
   * Handle the filename and line numbering.
   */
***************
*** 82,96 ****
   */
  int braces_open;
  
- /* This is a linked list of the variable names and types. */
- struct variable
- {
-     char * name;
-     struct ECPGtype * type;
-     int brace_level;
-     struct variable * next;
- };
- 
  static struct variable * allvariables = NULL;
  
  static struct variable *
--- 86,91 ----
***************
*** 167,175 ****
  static struct arguments * argsinsert = NULL;
  static struct arguments * argsresult = NULL;
  
- static struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
- static struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
- 
  static void
  reset_variables(void)
  {
--- 162,167 ----
***************
*** 209,215 ****
      dump_variables(list->next);
  
      /* Then the current element and its indicator */
!     ECPGdump_a_type(yyout, list->variable->name, list->variable->type, list->indicator->name, list->indicator->type, NULL, NULL);
  
      /* Then release the list element. */
      free(list);
--- 201,209 ----
      dump_variables(list->next);
  
      /* Then the current element and its indicator */
!     ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
! 	(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL,
! 	(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
  
      /* Then release the list element. */
      free(list);
***************
*** 375,388 ****
  	double                  dval;
          int                     ival;
  	char *                  str;
- 	struct ECPGtemp_type    type;
  	struct when             action;
  	int			tagname;
  	enum ECPGttype		type_enum;
  }
  
  /* special embedded SQL token */
! %token		SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO
  %token		SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN
  %token		SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
  %token		SQL_STOP SQL_WHENEVER
--- 369,382 ----
  	double                  dval;
          int                     ival;
  	char *                  str;
  	struct when             action;
+ 	struct index		index;
  	int			tagname;
  	enum ECPGttype		type_enum;
  }
  
  /* special embedded SQL token */
! %token		SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO
  %token		SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN
  %token		SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
  %token		SQL_STOP SQL_WHENEVER
***************
*** 449,455 ****
  %token  USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
  
  /* Special keywords, not in the query language - see the "lex" file */
! %token <str>    IDENT SCONST Op
  %token <ival>   ICONST PARAM
  %token <dval>   FCONST
  
--- 443,449 ----
  %token  USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
  
  /* Special keywords, not in the query language - see the "lex" file */
! %token <str>    IDENT SCONST Op CSTRING
  %token <ival>   ICONST PARAM
  %token <dval>   FCONST
  
***************
*** 538,548 ****
  %type  <str>	GrantStmt privileges operation_commalist operation
  
  %type  <str>	ECPGWhenever ECPGConnect db_name ECPGOpen open_opts
! %type  <str>	indicator ECPGExecute c_expr
  %type  <str>	stmt symbol
  
  %type  <action> action
  
  %%
  prog: statements;
  
--- 532,549 ----
  %type  <str>	GrantStmt privileges operation_commalist operation
  
  %type  <str>	ECPGWhenever ECPGConnect db_name ECPGOpen open_opts
! %type  <str>	indicator ECPGExecute c_expr variable_list dotext
! %type  <str>    storage_clause opt_initializer vartext c_anything blockstart
! %type  <str>    blockend variable_list variable var_anything sql_anything
! %type  <str>	opt_pointer ecpg_ident
! 
  %type  <str>	stmt symbol
  
+ %type  <type_enum> simple_type type struct_type
+ 
  %type  <action> action
  
+ %type  <index>	opt_index
  %%
  prog: statements;
  
***************
*** 551,559 ****
  
  statement: ecpgstart stmt SQL_SEMI
  	| ECPGDeclaration
! 	| c_anything
! 	| blockstart
! 	| blockend
  
  stmt:  AddAttrStmt			{ output_statement($1); }
  		| AlterUserStmt		{ output_statement($1); }
--- 552,560 ----
  
  statement: ecpgstart stmt SQL_SEMI
  	| ECPGDeclaration
! 	| c_anything			{ fputs($1, yyout); }
! 	| blockstart			{ fputs($1, yyout); }
! 	| blockend			{ fputs($1, yyout); }
  
  stmt:  AddAttrStmt			{ output_statement($1); }
  		| AlterUserStmt		{ output_statement($1); }
***************
*** 1332,1338 ****
  					$$ = make_name();
  				}
  			| Sconst	{  $$ = $1; }
! 			| IDENT		{  $$ = $1; }
  		;
  
  DropTrigStmt:  DROP TRIGGER name ON relation_name
--- 1333,1339 ----
  					$$ = make_name();
  				}
  			| Sconst	{  $$ = $1; }
! 			| ecpg_ident		{  $$ = $1; }
  		;
  
  DropTrigStmt:  DROP TRIGGER name ON relation_name
***************
*** 1829,1835 ****
  
  event_object:  relation_name '.' attr_name
  				{
! 					$$ = make3_str($1, ",", $3);
  				}
  		| relation_name
  				{
--- 1830,1836 ----
  
  event_object:  relation_name '.' attr_name
  				{
! 					$$ = cat3_str($1, ".", $3);
  				}
  		| relation_name
  				{
***************
*** 2243,2249 ****
  				}
  		| ColId '.' ColId OptUseOp
  				{
! 					$$ = make4_str($1, ".", $3, $4);
  				}
  		| Iconst OptUseOp
  				{
--- 2244,2250 ----
  				}
  		| ColId '.' ColId OptUseOp
  				{
! 					$$ = make2_str(cat3_str($1, ".", $3), $4);
  				}
  		| Iconst OptUseOp
  				{
***************
*** 2292,2298 ****
  				}
  		| ColId '.' ColId
  				{
! 					$$ = make3_str($1, ",", $3);
  				}
  		| Iconst
  				{
--- 2293,2299 ----
  				}
  		| ColId '.' ColId
  				{
! 					$$ = cat3_str($1, ",", $3);
  				}
  		| Iconst
  				{
***************
*** 2383,2389 ****
  				}
  		| ColId '.' ColId
  				{
! 					$$ = make3_str($1, ".", $3);
  				}
  		| Iconst
  				{
--- 2384,2390 ----
  				}
  		| ColId '.' ColId
  				{
! 					$$ = cat3_str($1, ".", $3);
  				}
  		| Iconst
  				{
***************
*** 2455,2461 ****
  				}
  		;
  
! generic:  IDENT					{ $$ = $1; }
  		| TYPE_P			{ $$ = "type"; }
  		;
  
--- 2456,2462 ----
  				}
  		;
  
! generic:  ecpg_ident					{ $$ = $1; }
  		| TYPE_P			{ $$ = "type"; }
  		;
  
***************
*** 3409,3428 ****
  
  attr:  relation_name '.' attrs
  				{
! 					$$ = make3_str($1, ".", $3);
  				}
  		| ParamNo '.' attrs
  				{
! 					$$ = make3_str($1, ".", $3);
  				}
  		;
  
  attrs:	  attr_name
  				{ $$ = $1; }
  		| attrs '.' attr_name
! 				{ $$ = make3_str($1, ".", $3); }
  		| attrs '.' '*'
! 				{ $$ = make2_str($1, ".*"); }
  		;
  
  
--- 3410,3429 ----
  
  attr:  relation_name '.' attrs
  				{
! 					$$ = cat3_str($1, ".", $3);
  				}
  		| ParamNo '.' attrs
  				{
! 					$$ = cat3_str($1, ".", $3);
  				}
  		;
  
  attrs:	  attr_name
  				{ $$ = $1; }
  		| attrs '.' attr_name
! 				{ $$ = cat3_str($1, ".", $3); }
  		| attrs '.' '*'
! 				{ $$ = cat2_str($1, ".*"); }
  		;
  
  
***************
*** 3449,3455 ****
  				}
  		| relation_name '.' '*'
  				{
! 					$$ = make2_str($1, ".*");
  				}
  		;
  
--- 3450,3456 ----
  				}
  		| relation_name '.' '*'
  				{
! 					$$ = cat2_str($1, ".*");
  				}
  		;
  
***************
*** 3475,3481 ****
  				}
  		| relation_name '.' '*'
  				{
! 					$$ = make2_str($1, ".*");
  				}
  		| '*'
  				{
--- 3476,3482 ----
  				}
  		| relation_name '.' '*'
  				{
! 					$$ = cat2_str($1, ".*");
  				}
  		| '*'
  				{
***************
*** 3505,3513 ****
  		;
  
  database_name:			ColId			{ $$ = $1; };
! access_method:			IDENT			{ $$ = $1; };
  attr_name:				ColId			{ $$ = $1; };
! class:					IDENT			{ $$ = $1; };
  index_name:				ColId			{ $$ = $1; };
  
  /* Functions
--- 3506,3514 ----
  		;
  
  database_name:			ColId			{ $$ = $1; };
! access_method:			ecpg_ident			{ $$ = $1; };
  attr_name:				ColId			{ $$ = $1; };
! class:					ecpg_ident			{ $$ = $1; };
  index_name:				ColId			{ $$ = $1; };
  
  /* Functions
***************
*** 3518,3524 ****
  func_name:				ColId			{ $$ = $1; };
  
  file_name:				Sconst			{ $$ = $1; };
! recipe_name:			IDENT			{ $$ = $1; };
  
  /* Constants
   * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
--- 3519,3525 ----
  func_name:				ColId			{ $$ = $1; };
  
  file_name:				Sconst			{ $$ = $1; };
! recipe_name:			ecpg_ident			{ $$ = $1; };
  
  /* Constants
   * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
***************
*** 3569,3575 ****
  							$$[strlen($1)+2]='\0';
  							$$[strlen($1)+1]='\'';
  						}
! UserId:  IDENT                                  { $$ = $1;};
  
  /* Column and type identifier
   * Does not include explicit datetime types
--- 3570,3576 ----
  							$$[strlen($1)+2]='\0';
  							$$[strlen($1)+1]='\'';
  						}
! UserId:  ecpg_ident                                  { $$ = $1;};
  
  /* Column and type identifier
   * Does not include explicit datetime types
***************
*** 3591,3597 ****
   *  list due to shift/reduce conflicts in yacc. If so, move
   *  down to the ColLabel entity. - thomas 1997-11-06
   */
! ColId:  IDENT							{ $$ = $1; }
  		| datetime						{ $$ = $1; }
  		| ACTION						{ $$ = "action"; }
  		| CACHE							{ $$ = "cache"; }
--- 3592,3598 ----
   *  list due to shift/reduce conflicts in yacc. If so, move
   *  down to the ColLabel entity. - thomas 1997-11-06
   */
! ColId:  ecpg_ident							{ $$ = $1; }
  		| datetime						{ $$ = $1; }
  		| ACTION						{ $$ = "action"; }
  		| CACHE							{ $$ = "cache"; }
***************
*** 3688,3854 ****
      output_line_number();
  }
  
! variable_declarations : /* empty */
!                       | variable_declarations variable_declaration;
  
! /* Here is where we can enter support for typedef. */
! variable_declaration: type initializer ';'     { 
!     /* don't worry about our list when we're working on a struct */
!     if (struct_level == 0)
!     {
!         new_variable($<type>1.name, $<type>1.typ);
!         free((void *)$<type>1.name);
!     }
!     fputs(";", yyout); 
! }
  
! initializer : /*empty */
!             | '=' {fwrite(yytext, yyleng, 1, yyout);} vartext;
  
! type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; };
! type_detailed : varchar_type { $<type>$ = $<type>1; }
! 	      | simple_type { $<type>$ = $<type>1; }
! 	      | string_type { $<type>$ = $<type>1; }
! /*	      | array_type {$<type>$ = $<type>1; }
! 	      | pointer_type {$<type>$ = $<type>1; }*/
! 	      | struct_type {$<type>$ = $<type>1; };
! 
! varchar_type : varchar_tag symbol index {
!     if ($<ival>3 > 0L)
! 	fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $2, $<ival>3, $2);
!     else
! 	fprintf(yyout, "struct varchar_%s { int len; char arr[]; } %s", $2, $2);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $2;
! 	$<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<ival>3);
!     }
!     else
! 	ECPGmake_record_member($2, ECPGmake_varchar_type(ECPGt_varchar, $<ival>3), &(record_member_list[struct_level-1]));
! }
  
! varchar_tag: S_VARCHAR /*| S_VARCHAR2 */;
  
! simple_type : simple_tag symbol {
!     fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $2);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $2;
! 	$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
!     }
!     else
!         ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
! }
  
! string_type : char_tag symbol index {
!     if ($<ival>3 > 0L)
! 	    fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $2, $<ival>3);
!     else
! 	    fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $2);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $2;
! 	$<type>$.typ = ECPGmake_simple_type($<type_enum>1, $<ival>3);
!     }
!     else
! 	ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, $<ival>3), &(record_member_list[struct_level-1]));
! }
! 	|	char_tag '*' symbol {
!     fprintf(yyout, "%s *%s", ECPGtype_name($<type_enum>1), $3);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $3;
! 	$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 0);
!     }
!     else
! 	ECPGmake_record_member($3, ECPGmake_simple_type($<type_enum>1, 0), &(record_member_list[struct_level-1]));
! }
! 	|	char_tag symbol {
!     fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $2);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $2;
! 	$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
!     }
!     else
!         ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
! }
  
! char_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
!            | S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; }
  
! /*
! array_type : simple_tag symbol index {
!     if ($<ival>3 > 0)
! 	    fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $2, $<ival>3);
!     else
! 	    fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $2);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $2;
! 	$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<ival>3);
!     }
!     else
! 	ECPGmake_record_member($2, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<ival>3), &(record_member_list[struct_level-1]));
! }
  
! pointer_type : simple_tag '*' symbol {
!     fprintf(yyout, "%s * %s", ECPGtype_name($<type_enum>1), $3);
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $3;
! 	$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0);
!     }
!     else
! 	ECPGmake_record_member($3, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0), &(record_member_list[struct_level-1]));
! }
! */
  
! s_struct : S_STRUCT symbol {
!     struct_level++;
!     fprintf(yyout, "struct %s {", $2);
! }
  
! struct_type : s_struct '{' variable_declarations '}' symbol {
!     struct_level--;
!     if (struct_level == 0)
!     {
! 	$<type>$.name = $5;
! 	$<type>$.typ = ECPGmake_record_type(record_member_list[struct_level]);
!     }
!     else
! 	ECPGmake_record_member($5, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1])); 
!     fprintf(yyout, "} %s", $5);
!     record_member_list[struct_level] = NULL;
! }
  
! simple_tag : S_SHORT { $<type_enum>$ = ECPGt_short; }
!            | S_UNSIGNED S_SHORT { $<type_enum>$ = ECPGt_unsigned_short; }
! 	   | S_INT { $<type_enum>$ = ECPGt_int; }
!            | S_UNSIGNED S_INT { $<type_enum>$ = ECPGt_unsigned_int; }
! 	   | S_LONG { $<type_enum>$ = ECPGt_long; }
!            | S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; }
!            | S_FLOAT { $<type_enum>$ = ECPGt_float; }
!            | S_DOUBLE { $<type_enum>$ = ECPGt_double; }
! 	   | S_BOOL { $<type_enum>$ = ECPGt_bool; };
! 
! maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); }
! 		       | S_STATIC { fwrite(yytext, yyleng, 1, yyout); }
! 		       | S_SIGNED { fwrite(yytext, yyleng, 1, yyout); }
! 		       | S_CONST { fwrite(yytext, yyleng, 1, yyout); }
! 		       | S_REGISTER { fwrite(yytext, yyleng, 1, yyout); }
! 		       | S_AUTO { fwrite(yytext, yyleng, 1, yyout); }
!                        | /* empty */ { };
!   	 
! index : '[' Iconst ']' { $<ival>$ = atol($2); }
! 	| '[' ']' { $<ival>$ = 0L; }
  
  /*
   * the exec sql connect statement: connect to the given database 
   */
! ECPGConnect : SQL_CONNECT db_name { $$ = $2; }
  
! db_name : database_name { $$ = $1; }
  	| ':' name { /* check if we have a char variable */
  			struct variable *p = find_variable($2);
  			enum ECPGttype typ = p->type->typ;
--- 3689,3825 ----
      output_line_number();
  }
  
! variable_declarations: /* empty */
! 	| declaration variable_declarations;
  
! declaration: storage_clause type
! 	{
! 		actual_storage[struct_level] = $1;
! 		actual_type[struct_level] = $2;
! 		if ($2 != ECPGt_varchar && $2 != ECPGt_record)
! 			fprintf(yyout, "%s %s", $1, ECPGtype_name($2));
! 	}
! 	variable_list ';' { fputc(';', yyout); }
  
! storage_clause : S_EXTERN	{ $$ = "extern"; }
!        | S_STATIC		{ $$ = "static"; }
!        | S_SIGNED		{ $$ = "signed"; }
!        | S_CONST		{ $$ = "const"; }
!        | S_REGISTER		{ $$ = "register"; }
!        | S_AUTO			{ $$ = "auto"; }
!        | /* empty */		{ $$ = "" ; }
  
! type: simple_type
! 	| struct_type
  
! struct_type: s_struct '{' variable_declarations '}'
! 	{
! 	    struct_level--;
! 	    $$ = actual_type[struct_level] = ECPGt_record;
! 	}
  
! s_struct : S_STRUCT symbol
! 	{
! 		struct_level++;
! 		fprintf(yyout, "struct %s {", $2);
! 	}
  
! 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; }
! 	   | S_VARCHAR		{ $$ = ECPGt_varchar; }
  
! variable_list: variable 
! 	| variable_list ','
! 	{
! 		if (actual_type[struct_level] != ECPGt_varchar)
! 			fputs(", ", yyout);
! 		else
! 			fputs(";\n ", yyout);
! 	} variable
  
! variable: opt_pointer symbol opt_index opt_initializer
! 		{
! 			int length = $3.ival;
  
! 			/* pointer has to get length 0 */
! 			if (strlen($1) > 0)
! 				length = 0;
  
! 			switch (actual_type[struct_level])
! 			{
! 			   case ECPGt_record:
! 				if (struct_level == 0)
! 					new_variable($2, ECPGmake_record_type(record_member_list[struct_level]));
! 				else
! 				        ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
  
! 				record_member_list[struct_level] = NULL;
! 		 		fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4);
  
! 				break;
! 			   case ECPGt_varchar:
! 				if (strlen($4) != 0)
! 					yyerror("varchar initilization impossible");
! 
! 				if (struct_level == 0) 
! 					new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
! 				else
! 				        ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
! 				
! 				if (length > 0)
! 					fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2);
! 				else
! 					fprintf(yyout, "%s struct varchar_%s { int len; char arr[]; } %s", actual_storage[struct_level], $2, $2);
! 
! 				break;
! 
! 			   default:
! 				if (struct_level == 0)
! 					new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length));
! 				else
! 				        ECPGmake_record_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
! 
! 				fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
! 
! 				break;
! 			}
! 		}
! 
! opt_initializer: /* empty */		{ $$ = ""; }
! 	| '=' vartext			{ $$ = cat2_str("=", $2); }
! 
! opt_pointer: /* empty */	{ $$ = ""; }
! 	| '*'			{ $$ = "*"; }
! 
! opt_index: '[' Iconst ']'	{
! 					$$.ival = atol($2);
! 					$$.str = cat3_str("[", $2, "]");
! 				}
!         | '[' ']'
! 				{
! 					$$.ival = 0;
! 					$$.str = "[]";
! 				}
! 	| /* empty */		{
! 					$$.ival = 1;
! 					$$.str = "";
! 				}
  
  /*
   * the exec sql connect statement: connect to the given database 
   */
! ECPGConnect: SQL_CONNECT db_name { $$ = $2; }
  
! db_name: database_name { $$ = $1; }
  	| ':' name { /* check if we have a char variable */
  			struct variable *p = find_variable($2);
  			enum ECPGttype typ = p->type->typ;
***************
*** 3895,3901 ****
  				}
  
  /*
!  * whenever statement: decide what to do in case of error/no dat
   */
  ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action {
  	when_error.code = $<action>3.code;
--- 3866,3875 ----
  				}
  
  /*
!  * whenever statement: decide what to do in case of error/no data found
!  * according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION
!  * and SQLWARNING
! 
   */
  ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action {
  	when_error.code = $<action>3.code;
***************
*** 3933,3949 ****
          $<action>$.command = $3;
  	$<action>$.str = make2_str("goto ", $3);
  }
!        | DO name '(' {
! 	do_str = (char *) mm_alloc(do_length = strlen($2) + 4);
! 	sprintf(do_str, "%s (", $2);
! } dotext ')' {
! 	do_str[strlen(do_str)+1]='\0';
! 	do_str[strlen(do_str)]=')';
  	$<action>$.code = W_DO;
! 	$<action>$.command = do_str;
! 	$<action>$.str = make2_str("do ", do_str);
! 	do_str = NULL;
! 	do_length = 0;
  }
  
  /* some other stuff for ecpg */
--- 3907,3921 ----
          $<action>$.command = $3;
  	$<action>$.str = make2_str("goto ", $3);
  }
!        | DO name '(' dotext ')' {
! 	$<action>$.code = W_DO;
! 	$<action>$.command = cat4_str($2, "(", $4, ")");
! 	$<action>$.str = make2_str("do", $<action>$.command);
! }
!        | SQL_CALL name '(' dotext ')' {
  	$<action>$.code = W_DO;
! 	$<action>$.command = cat4_str($2, "(", $4, ")");
! 	$<action>$.str = make2_str("call", $<action>$.command);
  }
  
  /* some other stuff for ecpg */
***************
*** 4231,4246 ****
  
  ecpgstart: SQL_START { reset_variables();}
  
! dotext: /* empty */
! 	| dotext sql_anything {
!                 if (strlen(do_str) + yyleng + 1 >= do_length)
!                         do_str = mm_realloc(do_str, do_length += yyleng);
  
!                 strcat(do_str, yytext);
! }
! 
! vartext: both_anything { fwrite(yytext, yyleng, 1, yyout); }
!         | vartext both_anything { fwrite(yytext, yyleng, 1, yyout); }
  
  coutputvariable : ':' name indicator {
  		add_variable(&argsresult, find_variable($2), ($3 == NULL) ? &no_indicator : find_variable($3)); 
--- 4203,4213 ----
  
  ecpgstart: SQL_START { reset_variables();}
  
! dotext: /* empty */		{ $$ = ""; }
! 	| dotext sql_anything	{ $$ = cat2_str($1, $2); }
  
! vartext: var_anything		{ $$ = $1; }
!         | vartext var_anything { $$ = cat2_str($1, $2); }
  
  coutputvariable : ':' name indicator {
  		add_variable(&argsresult, find_variable($2), ($3 == NULL) ? &no_indicator : find_variable($3)); 
***************
*** 4259,4289 ****
  	| SQL_INDICATOR ':' name 	{ check_indicator((find_variable($3))->type); $$ = $3; }
  	| SQL_INDICATOR name		{ check_indicator((find_variable($2))->type); $$ = $2; }
  
  /*
   * C stuff
   */
  
! symbol: IDENT	{ $$ = $1; }
! 
! c_anything: both_anything	{ fwrite(yytext, yyleng, 1, yyout); }
! 	| ';'			{ fputc(';', yyout); }
! 
! sql_anything: IDENT {} | ICONST {} | FCONST {}
  
! both_anything: IDENT {} | ICONST {} | FCONST {}
! 	| S_AUTO | S_BOOL | S_CHAR | S_CONST | S_DOUBLE | S_EXTERN | S_FLOAT
! 	| S_INT	| S_LONG | S_REGISTER | S_SHORT	| S_SIGNED | S_STATIC
! 	| S_STRUCT | S_UNSIGNED	| S_VARCHAR | S_ANYTHING
! 	| '[' | ']' | '(' | ')' | '='
  
  blockstart : '{' {
      braces_open++;
!     fputc('{', yyout);
  }
  
  blockend : '}' {
      remove_variables(braces_open--);
!     fputc('}', yyout);
  }
  
  %%
--- 4226,4288 ----
  	| SQL_INDICATOR ':' name 	{ check_indicator((find_variable($3))->type); $$ = $3; }
  	| SQL_INDICATOR name		{ check_indicator((find_variable($2))->type); $$ = $2; }
  
+ ecpg_ident: IDENT	{ $$ = $1; }
+ 	| CSTRING	{ $$ = cat3_str("\"", $1, "\""); }
  /*
   * C stuff
   */
  
! symbol: ecpg_ident	{ $$ = $1; }
  
! c_anything:  ecpg_ident 	{ $$ = $1; }
! 	| Iconst	{ $$ = $1; }
! 	| FCONST	{ $$ = make_name(); }
! 	| '*'			{ $$ = "*"; }
! 	| ';'			{ $$ = ";"; }
! 	| S_AUTO	{ $$ = "auto"; }
! 	| S_BOOL	{ $$ = "bool"; }
! 	| S_CHAR	{ $$ = "char"; }
! 	| S_CONST	{ $$ = "const"; }
! 	| S_DOUBLE	{ $$ = "double"; }
! 	| S_EXTERN	{ $$ = "extern"; }
! 	| S_FLOAT	{ $$ = "float"; }
!         | S_INT		{ $$ = "int"; }
! 	| S_LONG	{ $$ = "long"; }
! 	| S_REGISTER	{ $$ = "register"; }
! 	| S_SHORT	{ $$ = "short"; }
! 	| S_SIGNED	{ $$ = "signed"; }
! 	| S_STATIC	{ $$ = "static"; }
!         | S_STRUCT	{ $$ = "struct"; }
! 	| S_UNSIGNED	{ $$ = "unsigned"; }
! 	| S_VARCHAR	{ $$ = "varchar"; }
! 	| S_ANYTHING	{ $$ = make_name(); }
!         | '['		{ $$ = "["; }
! 	| ']'		{ $$ = "]"; }
! 	| '('		{ $$ = "("; }
! 	| ')'		{ $$ = ")"; }
! 	| '='		{ $$ = "="; }
! 	| ','		{ $$ = ","; }
! 
! sql_anything: ecpg_ident	{ $$ = $1; }
! 	| Iconst	{ $$ = $1; }
! 	| FCONST	{ $$ = make_name(); }
! 	| ','		{ $$ = ","; }
! 
! var_anything: ecpg_ident 	{ $$ = $1; }
! 	| Iconst	{ $$ = $1; }
! 	| FCONST	{ $$ = make_name(); }
! /*FIXME:	| ','		{ $$ = ","; }*/
! 	| '{'		{ $$ = "{"; }
! 	| '}'		{ $$ = "}"; }
  
  blockstart : '{' {
      braces_open++;
!     $$ = "{";
  }
  
  blockend : '}' {
      remove_variables(braces_open--);
!     $$ = "}";
  }
  
  %%
diff -rcN ecpg/preproc/type.c ecpg.mm/preproc/type.c
*** ecpg/preproc/type.c	Tue Apr 21 15:23:26 1998
--- ecpg.mm/preproc/type.c	Thu Apr 23 14:11:56 1998
***************
*** 130,135 ****
--- 130,141 ----
  void
  ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix)
  {
+ 	if (ind_typ == NULL)
+ 	{
+ 		ind_typ = &ecpg_no_indicator;
+ 		ind_name = "no_indicator";
+ 	}
+ 	
  	if (IS_SIMPLE_TYPE(typ->typ))
  	{
  		ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix);
***************
*** 267,273 ****
  	 * then we are in a record in a record and the offset is used as
  	 * offset.
  	 */
! 	struct ECPGrecord_member *p, *ind_p;
  	char		obuf[BUFSIZ];
  	char		pbuf[BUFSIZ], ind_pbuf[BUFSIZ];
  	const char *offset;
--- 273,279 ----
  	 * then we are in a record in a record and the offset is used as
  	 * offset.
  	 */
! 	struct ECPGrecord_member *p, *ind_p = NULL;
  	char		obuf[BUFSIZ];
  	char		pbuf[BUFSIZ], ind_pbuf[BUFSIZ];
  	const char *offset;
***************
*** 288,296 ****
  	sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
  	ind_prefix = ind_pbuf;
  
! 	for (p = typ->u.members, ind_p = ind_typ->u.members; p; p = p->next, ind_p = ind_p->next)
  	{
! 		ECPGdump_a_type(o, p->name, p->typ, ind_p->name, ind_p->typ, prefix, ind_prefix);
  	}
  }
  
--- 294,304 ----
  	sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
  	ind_prefix = ind_pbuf;
  
! 	if (ind_typ != NULL) ind_p = ind_typ->u.members;
! 	for (p = typ->u.members; p; p = p->next)
  	{
! 		ECPGdump_a_type(o, p->name, p->typ, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->typ : NULL, prefix, ind_prefix);
! 		if (ind_p != NULL) ind_p = ind_p->next;
  	}
  }
  
diff -rcN ecpg/preproc/type.h ecpg.mm/preproc/type.h
*** ecpg/preproc/type.h	Tue Apr 21 15:23:26 1998
--- ecpg.mm/preproc/type.h	Thu Apr 23 10:50:36 1998
***************
*** 74,76 ****
--- 74,82 ----
  	char		*command;
  	char	   	*str;
  };
+ 
+ struct index
+ {
+ 	int ival;
+ 	char *str;
+ };

Michael
-- 
Dr. Michael Meskes, Project-Manager    | topsystem Systemhaus GmbH
meskes@topsystem.de                    | Europark A2, Adenauerstr. 20
meskes@debian.org                      | 52146 Wuerselen
Go SF49ers! Go Rhein Fire!             | Tel: (+49) 2405/4670-44
Use Debian GNU/Linux!                  | Fax: (+49) 2405/4670-10

Thu, 23 Apr 1998 14:30:03 +0200 ()
Michael Meskes <meskes@topsystem.de>
ecpg patches