https://gcc.gnu.org/g:895cab8f290dc120200f58ce6736f8e5f8234c30

commit r17-4442-g895cab8f290dc120200f58ce6736f8e5f8234c30
Author: Xavier Del Campo Romero <[email protected]>
Date:   Fri Sep 18 15:59:30 2026 +0200

    cobol: Partially implement CBL_GET_PROGRAM_INFO
    
    Only functions 0 and 2 are implemented, and only partially - only
    returning the program name is supported.
    
    libgcobol/ChangeLog:
    
            * Makefile.am: Add CBL_GET_PROGRAM_INFO.cbl and cbl_gpi.cc.
            * Makefile.in: Likewise.
            * compat/gnu/cpy/cblproto.cpy: Add CBL_GET_PROGRAM_INFO.
            * compat/gnu/cpy/cbltypes.cpy: Add cblt-prog-info-params.
            * compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl: New file.
            * compat/gnu/lib/cbl_get_program_info.3: New file.
            * compat/gnu/lib/cbl_gpi.cc: New file.

Diff:
---
 libgcobol/Makefile.am                             |   4 +-
 libgcobol/Makefile.in                             |  18 +-
 libgcobol/compat/gnu/cpy/cblproto.cpy             |  18 ++
 libgcobol/compat/gnu/cpy/cbltypes.cpy             |   7 +
 libgcobol/compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl |  57 ++++
 libgcobol/compat/gnu/lib/cbl_get_program_info.3   | 150 +++++++++
 libgcobol/compat/gnu/lib/cbl_gpi.cc               | 364 ++++++++++++++++++++++
 7 files changed, 613 insertions(+), 5 deletions(-)

diff --git a/libgcobol/Makefile.am b/libgcobol/Makefile.am
index 77ba271c3518..d557e1456806 100644
--- a/libgcobol/Makefile.am
+++ b/libgcobol/Makefile.am
@@ -80,9 +80,11 @@ libgcobol_compat_gnu_la_SOURCES =            \
        compat/gnu/lib/CBL_CREATE_FILE.cbl      \
        compat/gnu/lib/CBL_DELETE_FILE.cbl      \
        compat/gnu/lib/CBL_FREE_MEM.cbl         \
+       compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl \
        compat/gnu/lib/CBL_OPEN_FILE.cbl        \
        compat/gnu/lib/CBL_READ_FILE.cbl        \
-       compat/gnu/lib/CBL_WRITE_FILE.cbl
+       compat/gnu/lib/CBL_WRITE_FILE.cbl       \
+       compat/gnu/lib/cbl_gpi.cc
 
 libgcobol_posix_la_SOURCES =                   \
        posix/udf/posix-close.cbl               \
diff --git a/libgcobol/Makefile.in b/libgcobol/Makefile.in
index 949ee42d8a43..9d65a567ea98 100644
--- a/libgcobol/Makefile.in
+++ b/libgcobol/Makefile.in
@@ -201,9 +201,11 @@ libgcobol_compat_gnu_la_LIBADD =
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_CREATE_FILE.lo \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_DELETE_FILE.lo \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_FREE_MEM.lo \
+@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_GET_PROGRAM_INFO.lo \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_OPEN_FILE.lo \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_READ_FILE.lo \
-@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_WRITE_FILE.lo
+@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_WRITE_FILE.lo \
+@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/cbl_gpi.lo
 libgcobol_compat_gnu_la_OBJECTS =  \
        $(am_libgcobol_compat_gnu_la_OBJECTS)
 @BUILD_LIBGCOBOL_TRUE@am_libgcobol_compat_gnu_la_rpath = -rpath \
@@ -504,9 +506,11 @@ gcc_version := $(shell @get_gcc_base_ver@ 
$(top_srcdir)/../gcc/BASE-VER)
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_CREATE_FILE.cbl      \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_DELETE_FILE.cbl      \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_FREE_MEM.cbl         \
+@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_OPEN_FILE.cbl        \
 @BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_READ_FILE.cbl        \
-@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_WRITE_FILE.cbl
+@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/CBL_WRITE_FILE.cbl       \
+@BUILD_LIBGCOBOL_TRUE@ compat/gnu/lib/cbl_gpi.cc
 
 @BUILD_LIBGCOBOL_TRUE@libgcobol_posix_la_SOURCES = \
 @BUILD_LIBGCOBOL_TRUE@ posix/udf/posix-close.cbl               \
@@ -764,12 +768,17 @@ compat/gnu/lib/CBL_DELETE_FILE.lo: 
compat/gnu/lib/$(am__dirstamp) \
        compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
 compat/gnu/lib/CBL_FREE_MEM.lo: compat/gnu/lib/$(am__dirstamp) \
        compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
+compat/gnu/lib/CBL_GET_PROGRAM_INFO.lo:  \
+       compat/gnu/lib/$(am__dirstamp) \
+       compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
 compat/gnu/lib/CBL_OPEN_FILE.lo: compat/gnu/lib/$(am__dirstamp) \
        compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
 compat/gnu/lib/CBL_READ_FILE.lo: compat/gnu/lib/$(am__dirstamp) \
        compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
 compat/gnu/lib/CBL_WRITE_FILE.lo: compat/gnu/lib/$(am__dirstamp) \
        compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
+compat/gnu/lib/cbl_gpi.lo: compat/gnu/lib/$(am__dirstamp) \
+       compat/gnu/lib/$(DEPDIR)/$(am__dirstamp)
 
 libgcobol_compat_gnu.la: $(libgcobol_compat_gnu_la_OBJECTS) 
$(libgcobol_compat_gnu_la_DEPENDENCIES) 
$(EXTRA_libgcobol_compat_gnu_la_DEPENDENCIES) 
        $(AM_V_GEN)$(libgcobol_compat_gnu_la_LINK) 
$(am_libgcobol_compat_gnu_la_rpath) $(libgcobol_compat_gnu_la_OBJECTS) 
$(libgcobol_compat_gnu_la_LIBADD) $(LIBS)
@@ -835,6 +844,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unstring.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/valconv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlparse.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@compat/gnu/lib/$(DEPDIR)/cbl_gpi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@posix/shim/$(DEPDIR)/errno.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@posix/shim/$(DEPDIR)/fstat.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@posix/shim/$(DEPDIR)/localtime.Plo@am__quote@
@@ -1034,7 +1044,7 @@ clean-am: clean-generic clean-libtool 
clean-toolexeclibLTLIBRARIES \
 
 distclean: distclean-am
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -rf ./$(DEPDIR) posix/shim/$(DEPDIR)
+       -rm -rf ./$(DEPDIR) compat/gnu/lib/$(DEPDIR) posix/shim/$(DEPDIR)
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
        distclean-hdr distclean-libtool distclean-tags
@@ -1083,7 +1093,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-am
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
        -rm -rf $(top_srcdir)/autom4te.cache
-       -rm -rf ./$(DEPDIR) posix/shim/$(DEPDIR)
+       -rm -rf ./$(DEPDIR) compat/gnu/lib/$(DEPDIR) posix/shim/$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
diff --git a/libgcobol/compat/gnu/cpy/cblproto.cpy 
b/libgcobol/compat/gnu/cpy/cblproto.cpy
index 42435ab00d13..b63a44c7bac1 100644
--- a/libgcobol/compat/gnu/cpy/cblproto.cpy
+++ b/libgcobol/compat/gnu/cpy/cblproto.cpy
@@ -118,6 +118,24 @@
                                 file-details
                                 returning status-code.
        end program CBL_CHECK_FILE_EXIST.
+
+       IDENTIFICATION DIVISION.
+       PROGRAM-ID. CBL_GET_PROGRAM_INFO PROTOTYPE.
+       DATA DIVISION.
+       LINKAGE SECTION.
+       COPY "cbltypes.cpy".
+       01 fn pic x(4) comp-5.
+       01 param-block type cblt-prog-info-params.
+       01 return-buf pic x any length.
+       01 return-buf-len pic x(4) comp-5.
+       77 status-code pic x(2) comp-5.
+       procedure division using by value fn
+                                by reference param-block
+                                by reference return-buf
+                                by reference return-buf-len
+                                returning status-code.
+
+       END PROGRAM CBL_GET_PROGRAM_INFO.
        >>POP SOURCE FORMAT
 
        >>PUSH SOURCE FORMAT
diff --git a/libgcobol/compat/gnu/cpy/cbltypes.cpy 
b/libgcobol/compat/gnu/cpy/cbltypes.cpy
index 384bc0bdb172..bd9b1221fdda 100644
--- a/libgcobol/compat/gnu/cpy/cbltypes.cpy
+++ b/libgcobol/compat/gnu/cpy/cbltypes.cpy
@@ -16,4 +16,11 @@
             05 cblte-fe-seconds   PIC X COMP-X.
             05 cblte-fe-hundreths PIC X COMP-X.
 
+         01 cblt-prog-info-params typedef.
+          03 cblte-gpi-size       pic x(4) comp-5.
+          03 cblte-gpi-flags      pic x(4) comp-5.
+          03 cblte-gpi-handle     usage pointer.
+          03 cblte-gpi-prog-id    usage pointer.
+          03 cblte-gpi-attrs      pic x(4) comp-5.
+
         >> POP source format
diff --git a/libgcobol/compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl 
b/libgcobol/compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl
new file mode 100644
index 000000000000..393f6bc98e60
--- /dev/null
+++ b/libgcobol/compat/gnu/lib/CBL_GET_PROGRAM_INFO.cbl
@@ -0,0 +1,57 @@
+       >>PUSH source format
+       >>SOURCE format is fixed
+      * Copyright (c) 2021-2026 Symas Corporation
+      *
+      * Redistribution and use in source and binary forms, with or without
+      * modification, are permitted provided that the following conditions are
+      * met:
+      *
+      * * Redistributions of source code must retain the above copyright
+      *   notice, this list of conditions and the following disclaimer.
+      * * Redistributions in binary form must reproduce the above
+      *   copyright notice, this list of conditions and the following 
disclaimer
+      *   in the documentation and/or other materials provided with the
+      *   distribution.
+      * * Neither the name of the Symas Corporation nor the names of its
+      *   contributors may be used to endorse or promote products derived from
+      *   this software without specific prior written permission.
+      *
+      * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+      * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+      * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+      * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+      * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+      * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+      * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+      * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+      * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+      * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+      * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+        COPY "cblproto.cpy".
+
+        IDENTIFICATION DIVISION.
+        PROGRAM-ID. CBL_GET_PROGRAM_INFO.
+        DATA DIVISION.
+        LINKAGE SECTION.
+        COPY "cbltypes.cpy".
+        01 fn pic x(4) comp-5.
+        01 param-block type cblt-prog-info-params.
+        01 return-buf pic x any length.
+        01 return-buf-len pic x(4) comp-5.
+        77 retcode pic x(2) comp-5.
+        procedure division using by value fn
+                                 by reference param-block
+                                 by reference return-buf
+                                 by reference return-buf-len
+                                 returning retcode.
+
+        call "cbl_gpi" using by value fn
+                             by reference param-block
+                                          return-buf
+                                          return-buf-len
+                             returning retcode.
+
+        END PROGRAM CBL_GET_PROGRAM_INFO.
+
+        >>POP source format
\ No newline at end of file
diff --git a/libgcobol/compat/gnu/lib/cbl_get_program_info.3 
b/libgcobol/compat/gnu/lib/cbl_get_program_info.3
new file mode 100644
index 000000000000..d6b9a38b9bfb
--- /dev/null
+++ b/libgcobol/compat/gnu/lib/cbl_get_program_info.3
@@ -0,0 +1,150 @@
+.ds lang COBOL
+.ds gcobol GCC\ \*[lang]\ Front-end
+.Dd \& September 2026
+.Dt CBL_GET_PROGRAM_INFO 3\& "\&GNU Compatibility Library"
+.Os Linux
+.Sh NAME
+.Nm CBL_GET_PROGRAM_INFO
+.Nd Get metadata from a given program.
+.Sh LIBRARY
+libgcobol_compat_gnu
+.
+.Sh SYNOPSIS
+.Ic COPY CBL_GET_PROGRAM_INFO
+.Pp
+.Ic call Dq "CBL_GET_PROGRAM_INFO"
+using
+by value
+.Ar fn
+by reference
+.Ar param-block
+.Ar return-buf
+.Ar return-buf-len
+returning
+.Ar status-code
+.
+.Sh DESCRIPTION
+Parameters:
+.Pp
+.Bl -tag -compact -width fn
+.It Ar fn
+is the function number to execute, from 0 to 10.
+The list of supported functions is shown below:
+
+.Ar 0 :
+Return the program name for the innermost program in the call stack above
+.Nm
+and assign
+.Ar cblte-gpi-handle .
+
+.Ar 2 :
+Return the program name associated with a
+.Ar cblte-gpi-handle
+instance previously allocated by function 0.
+
+.Ar 3 :
+close a
+.Ar cblte-gpi-handle
+instance previously allocated by function 0.
+
+.It Ar param-block
+an instance of type
+.Ar cblt-prog-info-params ,
+defined in the
+.Ar cbltypes
+copybook as:
+.Bd -literal:
+         01 cblt-prog-info-params typedef.
+          03 cblte-gpi-size       pic x(4) comp-5.
+          03 cblte-gpi-flags      pic x(4) comp-5.
+          03 cblte-gpi-handle     usage pointer.
+          03 cblte-gpi-prog-id    usage pointer.
+          03 cblte-gpi-attrs      pic x(4) comp-5.
+
+.Ar cblte-gpi-flags
+can further modify the behaviour of the 11 functions inside
+.Nm .
+A list of the currently supported bits is shown below:
+
+.Ar 0 :
+assign
+.Ar cblte-gpi-handle .
+This bit is only relevant for function
+.Ar 0 ,
+and is ignored by all other functions.
+
+.Ar 1 :
+fill
+.Ar return-buf
+with the program name.
+.Ar return-buf-len
+therefore indicates the length of the
+.Ar return-buf
+buffer. If the program name is longer than
+.Ar return-buf-len ,
+the result is truncated.
+This bit is only relevant for functions
+.Ar 0
+and
+.Ar 2 .
+
+.Ar 2 :
+if set, the program name stored into
+.Ar return-buf
+shall be null-terminated,
+or space-terminated otherwise.
+
+.It Ar return-buf
+points to a buffer to be filled by
+.Nm .
+
+.It Ar return-buf-len
+determines the length for the
+.Ar return-buf
+buffer.
+
+.Sh RETURN STATUS
+.Nm
+returns
+.Sy "PIC X(2) COMP-5" .
+The return status is 0 on success, else nonzero.
+.
+.Sh SEE ALSO
+.Xr CBL_CLOSE_FILE
+.Xr CBL_CREATE_FILE
+.Xr CBL_DELETE_FILE
+.Xr CBL_OPEN_FILE
+.Xr CBL_READ_FILE
+.Xr CBL_WRITE_FILE
+.Xr CBL_CHECK_FILE_EXIST
+.
+.Sh COPYRIGHT
+.Bd -unfilled -indent
+Copyright (c) 2021-2026 Symas Corporation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+* Neither the name of the Symas Corporation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.Ed
diff --git a/libgcobol/compat/gnu/lib/cbl_gpi.cc 
b/libgcobol/compat/gnu/lib/cbl_gpi.cc
new file mode 100644
index 000000000000..5e02ac4bd584
--- /dev/null
+++ b/libgcobol/compat/gnu/lib/cbl_gpi.cc
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2021-2026 Symas Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following disclaimer
+ *   in the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of the Symas Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+#include <string>
+
+struct gpi_priv
+  {
+  gpi_priv(const std::string &name) : name(name){}
+  std::string name;
+  };
+
+/* From the COBOL side, we add no padding bytes at all for groups. */
+struct gpi_param_t
+  {
+  uint32_t size, flags;
+  struct gpi_priv *handle;
+  void *prog_id;
+  uint32_t attrs;
+  } __attribute__ ((packed));
+
+struct retbuf_gpiai
+  {
+  uint32_t size, argc;
+  void *reserved1, *reserved2;
+  } __attribute__ ((packed));
+
+enum
+  {
+  /* return cblte-gpi-handle. */
+  GPI_PARAM_RET_HANDLE = 1 << 0,
+  /* return program basename in name-buf. */
+  GPI_PARAM_RET_BASENAME = 1 << 1,
+  /* 0: space-terminated, 1: null-terminated. */
+  GPI_PARAM_NULL_TERM = 1 << 2,
+  /* return in cblte-gpi-attr */
+  GPI_PARAM_RET_PRGATTR = 1 << 3,
+  /* return for all programs */
+  GPI_PARAM_ALL_PROG = 1 << 4,
+  /* 0: return full path, 1: return program name. */
+  GPI_PARAM_RET_PRGNAME = 1 << 5
+  };
+
+union retbuf
+  {
+  char *basename;
+  struct retbuf_gpiai *gpiai ;
+  };
+
+enum cbl_backtrace_flags
+  {
+  CBL_BACKTRACE_AMODE24     = 1 << 0,
+  CBL_BACKTRACE_AMODE31     = 1 << 1,
+  CBL_BACKTRACE_EBCDIC      = 1 << 2,
+  CBL_BACKTRACE_ANS85       = 1 << 3,
+  CBL_BACKTRACE_VCS2        = 1 << 4,
+  CBL_BACKTRACE_OSVS        = 1 << 5,
+  CBL_BACKTRACE_DATA24      = 1 << 6,
+  CBL_BACKTRACE_DATACONTEXT = 1 << 7,
+  CBL_BACKTRACE_PLI         = 1 << 8,
+  /* bits 9-10 reserved */
+  CBL_BACKTRACE_BIGENDIAN   = 1 << 11,
+  /* bits 12-22 reserved */
+  CBL_BACKTRACE_AMODE64     = 1 << 23,
+  CBL_BACKTRACE_DATA31      = 1 << 24
+  };
+
+static std::string
+getlastprog()
+  {
+  const std::vector<std::string> &__gg__get_module_names(),
+    &names = __gg__get_module_names();
+  const char *s = NULL;
+  std::string ret;
+
+  for (const auto &name : names)
+    {
+    /* libgcobol.cc stores module names with a leading character
+     * e.g.: 'T', 'N' or 'M'. */
+    const char *cname = name.c_str() + 1;
+
+    if (strcasecmp(cname, "CBL_GET_PROGRAM_INFO"))
+      s = cname;
+    else
+      break;
+    }
+
+  if (s)
+    ret = s;
+
+  return ret;
+  }
+
+static void
+setbasename(const std::string &src, const gpi_param_t &p, char *dst, unsigned 
n)
+  {
+  strncpy(dst, src.c_str(), n);
+
+  if (n)
+    {
+    dst[n - 1] = '\0';
+
+    if (!(p.flags & GPI_PARAM_NULL_TERM))
+      dst[strlen(dst)] = ' ';
+    }
+  }
+
+int16_t
+cbl_gpi_cur_status(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  std::string prog = getlastprog();
+
+  if (prog.empty())
+    return -1;
+  else if (params.flags & GPI_PARAM_RET_BASENAME)
+    setbasename(prog, params, buf.basename, buflen);
+
+  if (params.flags & GPI_PARAM_RET_HANDLE)
+    params.handle = new gpi_priv(prog);
+
+  /* TODO: set status bits */
+  return 0;
+  }
+
+int16_t
+cbl_gpi_named_status(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  /* TODO: how are we supposed to return for a "named program"
+   * if no name is given?*/
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_handle_status(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  const gpi_priv *prv = static_cast<const struct gpi_priv *>(params.handle);
+
+  if (params.flags & GPI_PARAM_RET_BASENAME)
+    setbasename(prv->name.c_str(), params, buf.basename, buflen);
+
+  /* TODO: set status bits */
+  return 0;
+  }
+
+int16_t
+cbl_gpi_close_handle(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  delete static_cast<gpi_priv *>(params.handle);
+  /* TODO: set status bits */
+  return 0;
+  }
+
+int16_t
+cbl_gpi_first_ep(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_next_ep(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_cancel_search_ep(gpi_param_t &params, union retbuf buf, unsigned 
buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_prg_name(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_nargs(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_reserved(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+int16_t
+cbl_gpi_path_prg_name(gpi_param_t &params, union retbuf buf, unsigned buflen)
+  {
+  fprintf(stderr, "%s: TODO\n", __func__);
+  return -1;
+  }
+
+typedef int16_t (*gpi_func_t)(gpi_param_t &params, union retbuf buf,
+  unsigned buflen);
+
+static const struct func
+  {
+  gpi_func_t func;
+  int accept, ignore, unimplemented;
+  } funcs[11] =
+  {
+    {
+    cbl_gpi_cur_status,
+    GPI_PARAM_RET_HANDLE | GPI_PARAM_RET_BASENAME | GPI_PARAM_NULL_TERM
+      | GPI_PARAM_RET_PRGATTR
+    },
+
+    {
+    cbl_gpi_named_status,
+    GPI_PARAM_RET_HANDLE | GPI_PARAM_RET_PRGATTR
+    },
+
+    {
+    cbl_gpi_handle_status,
+    GPI_PARAM_RET_BASENAME | GPI_PARAM_RET_PRGATTR | GPI_PARAM_NULL_TERM
+      | GPI_PARAM_ALL_PROG,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_close_handle,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_first_ep,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_next_ep,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_cancel_search_ep,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_prg_name,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_nargs,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_reserved,
+    0,
+    GPI_PARAM_RET_HANDLE
+    },
+
+    {
+    cbl_gpi_path_prg_name,
+    GPI_PARAM_RET_PRGNAME,
+    GPI_PARAM_RET_HANDLE
+    }
+  };
+
+static int checkflags(uint32_t fn, uint32_t flags)
+  {
+  const struct func &f = funcs[fn];
+
+  for (uint32_t i = 0; i < 8 * sizeof flags; i++)
+    {
+    uint32_t mask = 1 << i;
+
+    if (flags & mask)
+      {
+      if (!(f.accept & mask) && !(f.ignore & mask))
+        {
+        fprintf(stderr, "bit %" PRIu32 " not allowed for function %" PRIu32
+          "\n", i, fn);
+        return -1;
+        }
+      else if (f.unimplemented & mask)
+        {
+        fprintf(stderr, "bit %" PRIu32 " unimplemented for function %" PRIu32
+          "\n", i, fn);
+        return -1;
+        }
+      }
+    }
+
+  return 0;
+  }
+
+extern "C"
+int16_t cbl_gpi(uint32_t fn, struct gpi_param_t &params, union retbuf buf,
+  uint32_t *buflen)
+  {
+  if (fn >= sizeof funcs / sizeof *funcs)
+    {
+    fprintf(stderr, "invalid function number %u\n", fn);
+    return -1;
+    }
+
+  if (params.size != sizeof params)
+    {
+    fprintf(stderr, "invalid cblte-gpi-size, expected %zu, got %u\n",
+      sizeof params, params.size);
+    assert(params.size == sizeof params);
+    }
+
+  if (checkflags(fn, params.flags))
+    {
+    fprintf(stderr, "invalid bits\n");
+    return -1;
+    }
+
+  return funcs[fn].func(params, buf, *buflen);
+  }

Reply via email to