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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +int16_t +cbl_gpi_next_ep(gpi_param_t ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +int16_t +cbl_gpi_cancel_search_ep(gpi_param_t ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +int16_t +cbl_gpi_prg_name(gpi_param_t ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +int16_t +cbl_gpi_nargs(gpi_param_t ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +int16_t +cbl_gpi_reserved(gpi_param_t ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +int16_t +cbl_gpi_path_prg_name(gpi_param_t ¶ms, union retbuf buf, unsigned buflen) + { + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + } + +typedef int16_t (*gpi_func_t)(gpi_param_t ¶ms, 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 ¶ms, 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); + }
