Thread

  1. ecpg patches

    Michael Meskes <meskes@topsystem.de> — 1998-04-23T12:30:03Z

    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