From 33c2da97257fe744fe0d3fd0e695543e93d59801 Mon Sep 17 00:00:00 2001
From: "Marc G. Fournier" <scrappy@hub.org>
Date: Thu, 12 Feb 1998 14:02:10 +0000
Subject: [PATCH] From: Michael Meskes <meskes@topsystem.de>

Here's the ecpg patch for the local variables bug I reported earlier:
---
 src/interfaces/ecpg/TODO              |  3 --
 src/interfaces/ecpg/doc/ecpg.texinfo  |  2 +-
 src/interfaces/ecpg/preproc/pgc.l     |  7 +++-
 src/interfaces/ecpg/preproc/preproc.y | 58 +++++++++++++++++++++------
 4 files changed, 51 insertions(+), 19 deletions(-)

diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO
index 6d18d049a98..24c1f15df6f 100644
--- a/src/interfaces/ecpg/TODO
+++ b/src/interfaces/ecpg/TODO
@@ -44,8 +44,5 @@ could be realised in a script.
 
 Now comes my list (MM):
 
-Ecpg should remove variables from its list as soon as they are undefined and
-not rely on cc to report an error.
-
 Variable definitions containing static/volatile have to be possible.
 
diff --git a/src/interfaces/ecpg/doc/ecpg.texinfo b/src/interfaces/ecpg/doc/ecpg.texinfo
index b6458104a7a..ad9361e0213 100644
--- a/src/interfaces/ecpg/doc/ecpg.texinfo
+++ b/src/interfaces/ecpg/doc/ecpg.texinfo
@@ -356,7 +356,7 @@ you are not interested in how it really works, skip this chapter.
 @comment  node-name,  next,  previous,  up
 @section To do list
 
-In the alpha version the preprocessor has a lot of flaws:
+This version the preprocessor has some flaws:
 @table @asis
 
 @item Preprocessor output
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 7ab3c5764f2..4e81182b804 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -3,7 +3,7 @@
 #include "type.h"
 #include "y.tab.h"
 
-extern int debugging;
+#include "extern.h"
 
 #define dbg(arg)       if (debugging) fprintf(stderr, "DEBUG, %d: %s\n", yylineno, #arg);
 %}
@@ -56,7 +56,7 @@ int			{ dbg(S_INT); return S_INT; }
 char			{ dbg(S_CHAR); return S_CHAR; }
 float			{ dbg(S_FLOAT); return S_FLOAT; }
 double			{ dbg(S_DOUBLE); return S_DOUBLE; }
-bool                   { dbg(S_BOOL); return S_BOOL; }
+bool                    { dbg(S_BOOL); return S_BOOL; }
 
 {string}		{ dbg(SQL_STRING); return SQL_STRING; }
 <SQL>{ws}		; 
@@ -97,6 +97,8 @@ bool                   { dbg(S_BOOL); return S_BOOL; }
 "]"			{ dbg(]); return ']'; }
 ";"			{ dbg(;); return ';'; }
 ","			{ dbg(komma); return ','; }
+\{			{ dbg(blockstart); return '{'; }
+\}			{ dbg(blockend); return'}'; }
 
 <SQL>":"		{ dbg(:); return ':'; }
 
@@ -106,6 +108,7 @@ bool                   { dbg(S_BOOL); return S_BOOL; }
 void
 lex_init(void)
 {
+    braces_open = 0;
     BEGIN C;
 }
 
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 4d4ba6279f9..827c5c40cf5 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -29,27 +29,24 @@ output_line_number()
 /*
  * Handling of the variables.
  */
-/* Since we don't want to keep track of where the functions end we just
- * have a list of functions that we search in, most reasently defined
- * function. This won't work if we use block scope for variables with the
- * same name but different types but in all other cases the c-compiler will
- * signal an error (hopefully).
- *
- * This list is leaked on program exit. This is because I don't think it is
- * important enough to spend the extra ten minutes to write the function that
- * deletes it. It would be another thing if I would have written in C++.
+
+/*
+ * brace level counter
  */
+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;
 
-struct variable *
+static struct variable *
 find_variable(char * name)
 {
     struct variable * p;
@@ -71,18 +68,42 @@ find_variable(char * name)
 }
 
 
-void
+static void
 new_variable(const char * name, struct ECPGtype * type)
 {
     struct variable * p = (struct variable*) malloc(sizeof(struct variable));
 
     p->name = strdup(name);
     p->type = type;
+    p->brace_level = braces_open;
 
     p->next = allvariables;
     allvariables = p;
 }
 
+static void
+remove_variables(int brace_level)
+{
+    struct variable * p, *prev;
+
+    for (p = prev = allvariables; p; p = p->next)
+    {
+	if (p->brace_level >= brace_level)
+	{
+	    /* remove it */
+	    if (p == allvariables)
+		prev = allvariables = p->next;
+	    else
+		prev->next = p->next;
+
+	    free(p);
+	    p = prev;
+	}
+	else
+	    prev = p;
+    }
+}
+
 
 /*
  * Here are the variables that need to be handled on every request.
@@ -161,7 +182,7 @@ dump_variables(struct arguments * list)
 %token <tagname> S_EXTERN S_STATIC
 %token <tagname> S_UNSIGNED S_SIGNED
 %token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
-%token <tagname> '[' ']' ';' ','
+%token <tagname> '[' ']' ';' ',' '{' '}'
 
 %type <type> type type_detailed varchar_type simple_type array_type
 %type <symbolname> symbol
@@ -184,7 +205,9 @@ statement : sqldeclaration
 	  | sqlcommit
 	  | sqlrollback
 	  | sqlstatement
-	  | cthing;
+	  | cthing
+	  | blockstart
+	  | blockend;
 
 sqldeclaration : sql_startdeclare
 		 variable_declarations
@@ -356,6 +379,15 @@ both_anything : S_LENGTH | S_VARCHAR | S_VARCHAR2
 	  | '[' | ']' | ','
 	  | S_ANYTHING;
 
+blockstart : '{' {
+    braces_open++;
+    fwrite(yytext, yyleng, 1, yyout);
+}
+
+blockend : '}' {
+    remove_variables(braces_open--);
+    fwrite(yytext, yyleng, 1, yyout);
+}
 %%
 static void yyerror(char * error)
 {
-- 
GitLab