From ebd5ab5ca2cfcb3889d451530a1452ecd8415070 Mon Sep 17 00:00:00 2001
From: Bob Dubner <rdubner@symas.com>
Date: Tue, 2 Jan 2024 14:47:56 -0500
Subject: [PATCH] Recursive user-defined functions with local-storage

---
 gcc/cobol/UAT/testsuite.src/run_functions.at  |  53 +++++
 .../failures/multivariablepasser/Makefile     |   1 -
 .../failures/multivariablepasser/input.txt    |   0
 .../failures/multivariablepasser/playpen.cbl  | 188 ------------------
 .../failures/recursive_function/playpen.cbl   |   9 +-
 gcc/cobol/genapi.cc                           |  47 ++---
 libgcobol/libgcobol.cc                        |   5 -
 7 files changed, 83 insertions(+), 220 deletions(-)
 delete mode 100644 gcc/cobol/failures/multivariablepasser/Makefile
 delete mode 100644 gcc/cobol/failures/multivariablepasser/input.txt
 delete mode 100644 gcc/cobol/failures/multivariablepasser/playpen.cbl

diff --git a/gcc/cobol/UAT/testsuite.src/run_functions.at b/gcc/cobol/UAT/testsuite.src/run_functions.at
index 5cafe47b235b..1545173ebbfe 100644
--- a/gcc/cobol/UAT/testsuite.src/run_functions.at
+++ b/gcc/cobol/UAT/testsuite.src/run_functions.at
@@ -3762,3 +3762,56 @@ AT_CHECK([$COBCRUN_DIRECT ./a.out], [0], [1
 ], [])
 AT_CLEANUP
 
+AT_SETUP([Recursive FUNCTION with local-storage])
+AT_KEYWORDS([functions parameter])
+AT_DATA([prog.cob], [        IDENTIFICATION   DIVISION.
+        FUNCTION-ID.      callee.
+        DATA             DIVISION.
+        LOCAL-STORAGE    SECTION.
+        01 LCL-X         PIC 999 .
+        LINKAGE          SECTION.
+        01 parm          PIC 999.
+        01 retval        PIC 999.
+        PROCEDURE        DIVISION USING parm RETURNING retval.
+            display "On entry, parm is: " parm
+            move parm to lcl-x
+            move parm to retval
+            subtract 1 from parm
+            if parm > 0
+                display "A The function returns " function callee(parm).
+            if lcl-x not equal to retval
+                display "On exit, lcl-s and retval are: " lcl-x " and " retval
+                display "But they should be equal to each other"
+                end-if
+            goback.
+            end function callee.
+        IDENTIFICATION   DIVISION.
+        PROGRAM-ID.      caller.
+        ENVIRONMENT      DIVISION.
+        CONFIGURATION    SECTION.
+        REPOSITORY.
+                         FUNCTION callee.
+        DATA             DIVISION.
+        WORKING-STORAGE  SECTION.
+        01 val           PIC 999 VALUE 5.
+        PROCEDURE        DIVISION.
+           DISPLAY "Starting value is: " val
+           display "B The function returns " function callee(val).
+           STOP RUN.
+           end program caller.
+])
+AT_CHECK([$COMPILE prog.cob], [0], [], [])
+AT_CHECK([$COBCRUN_DIRECT ./a.out], [0], [Starting value is: 005
+On entry, parm is: 005
+On entry, parm is: 004
+On entry, parm is: 003
+On entry, parm is: 002
+On entry, parm is: 001
+A The function returns 001
+A The function returns 002
+A The function returns 003
+A The function returns 004
+B The function returns 005
+], [])
+AT_CLEANUP
+
diff --git a/gcc/cobol/failures/multivariablepasser/Makefile b/gcc/cobol/failures/multivariablepasser/Makefile
deleted file mode 100644
index f77e46b3451a..000000000000
--- a/gcc/cobol/failures/multivariablepasser/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-include ../Makefile.inc
diff --git a/gcc/cobol/failures/multivariablepasser/input.txt b/gcc/cobol/failures/multivariablepasser/input.txt
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/gcc/cobol/failures/multivariablepasser/playpen.cbl b/gcc/cobol/failures/multivariablepasser/playpen.cbl
deleted file mode 100644
index 004025a92375..000000000000
--- a/gcc/cobol/failures/multivariablepasser/playpen.cbl
+++ /dev/null
@@ -1,188 +0,0 @@
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID. "A".
-
-        DATA DIVISION.
-        WORKING-STORAGE SECTION.
-        01  var1        pic 9               VALUE 1.
-        01  var2        BINARY-CHAR         VALUE 22.
-        01  var3        pic s999 COMP-3     VALUE -333.
-        01  var4        pic 9999 BINARY     VALUE 4444.
-        01  var5        pic 99.99           VALUE "12.34".
-        01  var6        pic s999V999 COMP-5 VALUE -123.456.
-        01  var7        float-short         VALUE  1.23E10.
-        01  var8        float-long          VALUE  1.23E20.
-        01  var9        float-extended      VALUE  1.23E40.
-        01  var64       pic  9(30) VALUE 987654321098765.
-        01  var128      pic s9(30) VALUE -987654321098765432109876543210.
-
-        01  var1r        pic 9               .
-        01  var2r        BINARY-CHAR         .
-        01  var3r        pic s999 COMP-3     .
-        01  var4r        pic 9999 BINARY     .
-        01  var5r        pic 99.99           .
-        01  var6r        pic s999V999 COMP-5 .
-        01  var7r        float-short         .
-        01  var8r        float-long          .
-        01  var9r        float-extended      .
-        01  var64r       pic  9(30)          .
-        01  var128r      pic s9(30)          .
-
-        PROCEDURE DIVISION.
-            display     var1
-            call     "rvar1" USING by value var1r RETURNING var1r
-            display     var1r
-
-            display     var2
-            call     "rvar2" USING by value var2r RETURNING var2r
-            display     var2r
-
-            display     var3
-            call     "rvar3" USING by value var3r RETURNING var3r
-            display     var3r
-
-            display     var4
-            call     "rvar4" USING by value var4r RETURNING var4r
-            display     var4r
-
-            display     var5
-            call     "rvar5" USING by value var5r RETURNING var5r
-            display     var5r
-
-            display     var6
-            call     "rvar6" USING by value var6r RETURNING var6r
-            display     var6r
-
-      *>      display     var7
-      *>      call     "rvar7" USING by value var7r RETURNING var7r
-      *>      display     var7r
-      *>
-      *>      display     var8
-      *>      call     "rvar8" USING by value var8r RETURNING var8r
-      *>      display     var8r
-      *>
-      *>      display     var9
-      *>      call     "rvar9" USING by value var9r RETURNING var9r
-      *>      display     var9r
-
-            display     var64
-            call     "rvar64" USING by value var64r RETURNING var64r
-            display     var64r
-
-            display     var128
-            call     "rvar128" USING by value var128r RETURNING var128r
-            display     var128r
-
-            MOVE ZERO TO RETURN-CODE
-            GOBACK.
-            END PROGRAM A.
-
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar1.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var         pic 9               .
-        01  varr        pic 9               .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar1.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar2.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var         BINARY-CHAR         .
-        01  varr        BINARY-CHAR         .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar2.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar3.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var         pic s999 COMP-3     .
-        01  varr        pic s999 COMP-3     .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar3.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar4.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var         pic 9999 BINARY     .
-        01  varr        pic 9999 BINARY     .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar4.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar5.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var         pic 99.99           .
-        01  varr        pic 99.99           .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar5.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar6.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var         pic s999V999 COMP-5 .
-        01  varr        pic s999V999 COMP-5 .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar6.
-
-      *>  IDENTIFICATION DIVISION.
-      *>  PROGRAM-ID.rvar7.
-      *>  DATA DIVISION.
-      *>  LINKAGE SECTION.
-      *>  01  var         float-short         .
-      *>  01  varr        float-short         .
-      *>  PROCEDURE DIVISION USING by value varr RETURNING varr.
-      *>      MOVE var TO varr.
-      *>      END PROGRAM rvar7.
-
-      *>  IDENTIFICATION DIVISION.
-      *>  PROGRAM-ID.rvar8.
-      *>  DATA DIVISION.
-      *>  LINKAGE SECTION.
-      *>  01  var         float-long          .
-      *>  01  varr        float-long          .
-      *>  PROCEDURE DIVISION USING by value varr RETURNING varr.
-      *>      MOVE var TO varr.
-      *>      END PROGRAM rvar8.
-
-      *>  IDENTIFICATION DIVISION.
-      *>  PROGRAM-ID.rvar9.
-      *>  DATA DIVISION.
-      *>  LINKAGE SECTION.
-      *>  01  var         float-extended      .
-      *>  01  varr        float-extended      .
-      *>  PROCEDURE DIVISION USING by value varr RETURNING varr.
-      *>      MOVE var TO varr.
-      *>      END PROGRAM rvar9.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar64.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var        pic  9(30)          .
-        01  varr       pic  9(30)          .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar64.
-
-        IDENTIFICATION DIVISION.
-        PROGRAM-ID.rvar128.
-        DATA DIVISION.
-        LINKAGE SECTION.
-        01  var  pic s9(30) .
-        01  varr pic s9(30) .
-        PROCEDURE DIVISION USING by value varr RETURNING varr.
-            MOVE var TO varr.
-            END PROGRAM rvar128.
diff --git a/gcc/cobol/failures/recursive_function/playpen.cbl b/gcc/cobol/failures/recursive_function/playpen.cbl
index ab50a31eec04..80755fc361bd 100644
--- a/gcc/cobol/failures/recursive_function/playpen.cbl
+++ b/gcc/cobol/failures/recursive_function/playpen.cbl
@@ -7,13 +7,16 @@
         01 parm          PIC 999.
         01 retval        PIC 999.
         PROCEDURE        DIVISION USING parm RETURNING retval.
-            display "On entry: " parm
+            display "On entry, parm is: " parm
             move parm to lcl-x
             move parm to retval
             subtract 1 from parm
             if parm > 0
                 display "A The function returns " function callee(parm).
-            display "On exit: " lcl-x " and " retval
+            if lcl-x not equal to retval
+                display "On exit, lcl-s and retval are: " lcl-x " and " retval
+                display "But they should be equal to each other"
+                end-if
             goback.
             end function callee.
 
@@ -27,7 +30,7 @@
         WORKING-STORAGE  SECTION.
         01 val           PIC 999 VALUE 5.
         PROCEDURE        DIVISION.
-           DISPLAY val
+           DISPLAY "Starting value is: " val
            display "B The function returns " function callee(val).
            STOP RUN.
            end program caller.
diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc
index 17206fd18842..4b2e3ad75a2d 100644
--- a/gcc/cobol/genapi.cc
+++ b/gcc/cobol/genapi.cc
@@ -4918,10 +4918,12 @@ parser_exit(void)
                           rdigits,
                           NULL,
                           current_function->returning);
+//        gg_printf("KILROY returning %ld\n", gg_cast(LONG, value), NULL_TREE);
         gg_memcpy(gg_get_address_of(retval),
                   gg_get_address_of(value),
                   build_int_cst_type(SIZE_T, nbytes));
         }
+      restore_local_variables();
       gg_return(retval);
       }
     else
@@ -5379,23 +5381,18 @@ parser_division(cbl_division_t division,
     // RETURNING variables are supposed to be in the linkage section, which
     // means that we didn't assign any storage to them during
     // parser_symbol_add().  We do that here.
-
-    // We actually create two variables.  The first behaves like a LOCAL-STORAGE
-    // variable, because we need to handle the possibility of the return value
-    // having to survive recursive calls.  The second one is static storage; the
-    // LOCAL-STORAGE stack variable gets copied to the static one at return time
-    // so that the caller isn't trying to copy from a stack variable that has
-    // disappeared.
-
-    // returning is the stack-based operative variable; returning is the space
-    // in static mamory used to actually return the value
     
+    // returning also needs to behave like local storage, even though it is 
+    // in linkage.
+
+    // This counter is used to help keep track of local variables
+    gg_increment(var_decl_unique_prog_id);
     if( returning )
       {
       parser_local_add(returning);
       current_function->returning = returning;
       }
-
+   
     // Stash the returning variables for use during parser_return()
     current_function->returning = returning;
 
@@ -5578,9 +5575,6 @@ parser_division(cbl_division_t division,
       gg_assign(var_decl_call_parameter_count, build_int_cst_type(INT, A_ZILLION));
       }
 
-    // This counter is used to help keep track of local variables
-    gg_increment(var_decl_unique_prog_id);
-
     gg_call(VOID,
             "__gg__pseudo_return_bookmark",
             0);
@@ -13156,7 +13150,7 @@ move_helper(cbl_refer_t destref,
                               size_error);
     }
 
-  dont_be_clever:
+  //dont_be_clever:
 
   if( !moved )
     {
@@ -14063,7 +14057,7 @@ psa_new_var_decl(cbl_field_t *new_var, const char *external_record_base)
         static size_t literal_count = 1;
         sprintf(base_name, "%s_%zd", "literal", literal_count++);
         }
-      else if( new_var->attr & (temporary_e | intermediate_e) )// | linkage_e) )
+      else if( new_var->attr & (temporary_e | intermediate_e) )
         {
         static size_t temp_count = 1;
         sprintf(base_name, "%s_%zd", "_temporary", temp_count++);
@@ -14082,7 +14076,7 @@ psa_new_var_decl(cbl_field_t *new_var, const char *external_record_base)
                                           base_name,
                                           vs_external);
       }
-    else if( new_var->attr & (temporary_e | intermediate_e) )// | linkage_e) )
+    else if( new_var->attr & (temporary_e | intermediate_e) )
       {
       new_var_decl = gg_define_variable(  cblc_field_type_node,
                                           base_name,
@@ -14108,10 +14102,17 @@ parser_local_add(struct cbl_field_t *new_var )
     SHOW_PARSE_END
     }
 
-  gg_call(VOID,
-          "__gg__push_local_variable",
-          1,
-          gg_get_address_of(new_var->var_decl_node));
+  IF( member(new_var->var_decl_node, "data"),
+      ne_op,
+      gg_cast(UCHAR_P, null_pointer_node) )
+    {
+    gg_call(VOID,
+            "__gg__push_local_variable",
+            1,
+            gg_get_address_of(new_var->var_decl_node));
+    }
+  ELSE
+    ENDIF
 
   if( new_var->level == LEVEL01 || new_var->level == LEVEL77 )
     {
@@ -14141,7 +14142,7 @@ parser_symbol_add(struct cbl_field_t *new_var )
   // fprintf(stderr, " %s\n", dch);
 
   const char *new_initial = NULL;
-
+  
   if( !(new_var->attr & initialized_e) )
     {
     if( is_register_field(new_var) )
@@ -14743,7 +14744,7 @@ parser_symbol_add(struct cbl_field_t *new_var )
       free(level_88_string);
       }
 
-    if(   !(new_var->attr & (linkage_e | based_e)) )
+    if(  !(new_var->attr & ( linkage_e | based_e)) )
       {
       IF( gg_attribute_bit_get(new_var, initialized_e), eq_op, size_t_zero_node )
         {
diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc
index 9c335bbee32f..860e460c7215 100644
--- a/libgcobol/libgcobol.cc
+++ b/libgcobol/libgcobol.cc
@@ -6601,11 +6601,6 @@ __gg__display(  cblc_refer_t *var,
   static size_t display_string_size = MINIMUM_ALLOCATION_SIZE;
   static char *display_string = (char *)MALLOC(display_string_size);
 
-  if(strcmp(var->field->name, "arg") == 0 )
-    {
-    fprintf(stderr, "__gg__display of arg %p\n", var->qual_data);
-    }
-
   // if( var->qual_data )
     // {
     format_for_display_internal(&display_string,
-- 
GitLab