>From 5d53920602e234e4d99ae2d502e662ee3699978e 4 Oct 2024 12:01:22 -0400
From: "James K. Lowden" <jklow...@symas.com>
Date: Sat 15 Feb 2025 12:50:54 PM EST
Subject: [PATCH] 12 new 'cobol' FE files

gcc/cobol/ChangeLog
        * posix/.gitignore: New file.
        * posix/Makefile: New file.
        * posix/README.md: New file.
        * posix/headers: New file.
        * posix/scrape.awk: New file.
        * posix/udf-gen: New file.
        * posix/c/posix_errno.c: New file.
        * posix/udf/Makefile: New file.
        * posix/udf/posix-errno.cbl: New file.
        * posix/udf/posix-exit.cbl: New file.
        * posix/udf/t/errno.cbl: New file.
        * posix/udf/t/exit.cbl: New file.

---
gcc/cobol/posix/.gitignore | +++-
gcc/cobol/posix/Makefile | +++++++++++++-
gcc/cobol/posix/README.md | 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
gcc/cobol/posix/c/posix_errno.c | +++++-
gcc/cobol/posix/headers | +++++++++++++++++++++++++++++++++++++-
gcc/cobol/posix/scrape.awk | +++++++++++++++++++-
gcc/cobol/posix/udf-gen | 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
gcc/cobol/posix/udf/Makefile | +++++++++++++++++++++++++++-
gcc/cobol/posix/udf/posix-errno.cbl | ++++++++++++++++++-
gcc/cobol/posix/udf/posix-exit.cbl | ++++++++++++-
gcc/cobol/posix/udf/t/errno.cbl | ++++++++++++++++++++++++++-
gcc/cobol/posix/udf/t/exit.cbl | +++++++++++++++
12 files changed, 590 insertions(+), 12 deletions(-)
diff --git a/gcc/cobol/posix/.gitignore b/gcc/cobol/posix/.gitignore
new file mode 100644
index 00000000000..a65b24a10dc
--- /dev/null
+++ b/gcc/cobol/posix/.gitignore
@@ -0,0 +1,3 @@
+posix.txt
+prototypes.c
+prototypes.cpp
diff --git a/gcc/cobol/posix/Makefile b/gcc/cobol/posix/Makefile
new file mode 100644
index 00000000000..471769482b2
--- /dev/null
+++ b/gcc/cobol/posix/Makefile
@@ -0,0 +1,13 @@
+prototypes.c:  headers prototypes.cpp
+       cat $^ > $@~
+       @mv $@~ $@
+
+prototypes.cpp: posix.txt
+       awk -F'[/.]' '{ print $$6 }' $^ | \
+       while read F; do echo "/* $$F */" && man 2 $$F | \
+                       ./scrape.awk -v funcname=$$6; done > $@~
+       @mv $@~ $@
+
+posix.txt:
+       zgrep -l 'POSIX[.]' /usr/share/man/man2/*z > $@~
+       @mv $@~ $@
diff --git a/gcc/cobol/posix/README.md b/gcc/cobol/posix/README.md
new file mode 100644
index 00000000000..f126a8be990
--- /dev/null
+++ b/gcc/cobol/posix/README.md
@@ -0,0 +1,65 @@
+# GCC COBOL Posix Functions and Adapter
+
+## Purpose
+
+ISO COBOL does not specify any relationship to any particular
+operating system, and does not reference Posix. The raw capability is
+there, of course, via the `CALL` statement.  But that's not very
+convenient, and offers no parameter validation.
+
+GCC COBOL as of this writing works *only* in a Posix environment. This
+directory exists to make using OS-provided functions a bit more convenient.
+
+## Contents
+
+The machine-shop tools are in this directory.  Things directly usable
+by a COBOL program are in the `udf/` and `c/` directories.
+
+- `scrape.awk` extracts function prototypes from the SYNOPSIS of a man page.
+- `udf-gen` reads function declarations and, for each one, produces a
+  COBOL User Defined Function (UDF) that calls the function.
+- `Makefile` produces a list of function prototypes from Section 2 of
+  the manual.
+- `c/` contains helper functions in C that cannot be expressed in
+  COBOL. For example, the C `errno` "variable" may be a macro, and may
+  not be declared except by `errno.h`, which is not accessible to
+  COBOL.
+- `udf/Makefile` builds some infrastructure and examples:
+  - `udf/libposix-errno.so`, to get at the C `errno` variable and its
+    string representation.
+  - `udf/posix-mkdir.cbl` automatically from the manual, using `udf-gen`.
+  - `udf/t/errno` and
+  - `udf/t/exit` as examples of COBOL programs using these Posix UDFs.
+
+## Prerequisites
+
+`udf-gen` is a Python program that imports
+the [PLY pycparser module](http://www.dabeaz.com/ply/) module, which must be 
installed.
+
+`udf-gen` is lightly documented, use `udf-gen --help`. It can be a
+little tedious to set up the first time, but if you want to use more a
+few functions, it will be faster than doing the work by hand.
+
+## Limitations
+
+`udf-gen` does not
+
+- generate a working UDF for function parameters of type `struct`,
+  such as is used by **stat**(2).  This is because the information is
+  not available in a standardized way in the SYNOPSIS of a man page.
+- define helpful Level 88 values for "magic" numbers, such as
+  permission bits in **chmod**(2).
+
+None of this is particularly difficult; it's just a matter of time and
+need. The `scrape.awk` script finds 560 functions in the Ubuntu LTS
+22.04 manual.  Which of those is important is for users to decide.
+
+## Other Options
+
+IBM and Microfocus both supply intrinsic functions to interface with
+the OS, each in their own way. GnuCOBOL implements some of those functions.
+
+## Portability
+
+The UDF produced by `udf-gen` is pure ISO COBOL.  The code should be
+compilable by any ISO COBOL compiler.
diff --git a/gcc/cobol/posix/c/posix_errno.c b/gcc/cobol/posix/c/posix_errno.c
new file mode 100644
index 00000000000..f87e271ced4
--- /dev/null
+++ b/gcc/cobol/posix/c/posix_errno.c
@@ -0,0 +1,5 @@
+#include <errno.h>
+
+int posix_errno() {
+  return errno;
+}
diff --git a/gcc/cobol/posix/headers b/gcc/cobol/posix/headers
new file mode 100644
index 00000000000..b17c0f30cb3
--- /dev/null
+++ b/gcc/cobol/posix/headers
@@ -0,0 +1,37 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+#define loff_t ssize_t
+#define socklen_t size_t
+#define fd_set struct fd_set
+#define id_t unsigned int
+// typedef int mqd_t;
+#define mqd_t int
+// typedef unsigned long int nfds_t;
+#define nfds_t unsigned long int
+
+#if 0
+typedef struct
+{
+  unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
+} __sigset_t;
+define struct py_sigset_t                                              \
+{                                                                      \
+  unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];  \
+};
+#else
+#define kernel_sigset_t     sigset_t
+#define old_kernel_sigset_t sigset_t
+#endif
+
+#if 0
+typedef enum
+{
+  P_ALL,
+  P_PID,
+  P_PGID
+} idtype_t;
+#else
+#define idtype_t int
+#endif
diff --git a/gcc/cobol/posix/scrape.awk b/gcc/cobol/posix/scrape.awk
new file mode 100755
index 00000000000..4d244d0ee3d
--- /dev/null
+++ b/gcc/cobol/posix/scrape.awk
@@ -0,0 +1,19 @@
+#! /usr/bin/awk -f
+
+/^UNIMPLEMENTED/ {
+  exit
+}
+
+/^DESCRIPTION/ {
+  exit
+}
+
+/struct sched_param {$/ {
+  exit
+}
+
+/SYNOPSIS/,/DESCRIPTION/ {
+  if( /([.][.]|[{},;]) *$/ ) {
+    print
+  }
+}
diff --git a/gcc/cobol/posix/udf-gen b/gcc/cobol/posix/udf-gen
new file mode 100755
index 00000000000..e6207085b1d
--- /dev/null
+++ b/gcc/cobol/posix/udf-gen
@@ -0,0 +1,350 @@
+#! /usr/bin/python3
+
+# Copyright (c) 2024 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.
+
+import sys, os, getopt, re, copy
+from pycparser import c_parser, c_generator, c_ast, parse_file
+
+def starify(param):
+    stars = ""
+    while( isinstance(param, c_ast.PtrDecl) ):
+        q = ' '.join(param.quals)
+        stars = '*' + ' '.join((stars, q))
+        param = param.type
+    if( isinstance(param.type, c_ast.PtrDecl) ):
+        (stars, param) = starify(param.type)
+    if( isinstance(param, c_ast.TypeDecl) ):
+        return (stars, param)
+    return (stars, param.type)
+
+def linkage_str( i, name, param ) -> str:
+    if name == 'execve':
+        param.show()
+    if( isinstance(param, c_ast.EllipsisParam) ):
+        return (None, None, '...') # COBOL syntax error: no variadic UDF
+
+    is_array = False;
+    node = param
+
+    if( isinstance(node, c_ast.Decl) ):
+        node = node.type
+
+    if( isinstance(node, c_ast.ArrayDecl) ):
+        is_array = True;
+        node = node.type
+
+    (stars, node) = starify(node)
+
+    if( isinstance(node, c_ast.TypeDecl) ):
+        level = 1
+        item_name = ''
+        picture = ''
+        usage = ''
+        if node.declname:
+            item_name = 'Lk-' + node.declname
+
+        if is_array: # ignore level
+            if stars:
+                usage = 'Usage POINTER'
+            output = '01 FILLER.\n              02 %s %s %s OCCURS 100' \
+                % (item_name, picture, usage)
+            return (None, None, output)
+
+        if( isinstance(node.type, c_ast.Struct) ):
+            stars = None
+
+        if isinstance(node.type, c_ast.IdentifierType):
+            ctype = node.type.names[-1]
+            if ctype == 'void':
+                if not stars and not item_name:
+                    return (None, None, None)
+            if ctype == 'char':
+                picture = 'X'
+                if stars[0] == '*':
+                    picture = 'X ANY LENGTH'
+            if ctype == 'int' or \
+               ctype == 'long' or \
+               ctype == 'mode_t' or \
+               ctype == 'off_t' or \
+               ctype == 'size_t':
+                picture = '9(8)'
+                usage = 'Usage COMP'
+                stars = None
+
+        output = "%02d %s" % (level, ' '.join((item_name, 'PIC ' + picture, 
usage)))
+        return (stars, item_name, output)
+
+    node.show()
+    return (None, None, '???')
+
+def using_str( i, name, param ) -> str:
+    item_name = ''
+    if( isinstance(param, c_ast.EllipsisParam) ):
+        return '...' # COBOL syntax error: no variadic UDF
+    node = param
+
+    if( isinstance(node, c_ast.Decl) ):
+        node = node.type
+
+    if( isinstance(node, c_ast.ArrayDecl) ):
+        node = node.type
+
+    (stars, node) = starify(node)
+
+    if( isinstance(node, c_ast.TypeDecl) ):
+        item_name = ''
+
+        if isinstance(node.type, c_ast.IdentifierType):
+            ctype = node.type.names[-1]
+            how = 'By Reference'
+            if ctype == 'int' or \
+               ctype == 'long' or \
+               ctype == 'mode_t' or \
+               ctype == 'off_t' or \
+               ctype == 'size_t':
+                how = 'By Value'
+        if node.declname:
+            item_name = '%s Lk-%s' % (how, node.declname)
+
+    return item_name
+
+def parameter_str( i, name, param ) -> str:
+    if( isinstance(param, c_ast.EllipsisParam) ):
+        return '...'
+
+    t = [0, 1, 2] # qual, type, name
+    is_array = False;
+    node = param
+
+    if( isinstance(node, c_ast.Decl) ):
+        node = node.type
+
+    if( isinstance(node, c_ast.ArrayDecl) ):
+        is_array = True;
+        node = node.type
+
+    (stars, node) = starify(node)
+
+    if( isinstance(node, c_ast.TypeDecl) ):
+        t[0] = ' '.join(node.quals)
+        item_name = ''
+        if node.declname:
+            item_name = 'Lk-' + node.declname
+        t[2] = ' '.join((stars, item_name))
+        if( node.declname == None ):
+            t[2] = ''
+        if( isinstance(node.type, c_ast.IdentifierType) ):
+            try:
+                t[1] = ' '.join(node.type.names)
+            except:
+                print("oops: node.type of %s is %s" % (name, str(node.type)))
+                return "could not parse %s arg[%d]" % (name, i)
+        if( isinstance(node.type, c_ast.Struct) ):
+            t[0] = ' '.join(node.quals)
+            t[1] = "struct " + node.type.name
+    if( isinstance(node, c_ast.ArrayDecl) ):
+        return parameter_str(i, name, node.type) + '[]'
+
+    try:
+        return ' '.join(t)
+    except:
+        print("oops: %s[%d]: {%s}" % (name, i, str(t)) )
+        param.show()
+
+class VisitPrototypes(c_ast.NodeVisitor):
+    def __init__(self):
+        self.done = set()
+
+    def type_of(self, node):
+        while( not isinstance(node.type, c_ast.TypeDecl) ):
+            node = node.type
+        return node.type.type.name
+
+    def visit_Decl(self, node):
+        name = node.name
+        if name in self.done:
+            return
+        self.done.add(name)
+
+        params = []
+        cbl_args = []
+        linkage_items = []
+        string_items = []
+        returns = '???'
+
+        if False and isinstance(node.type, c_ast.FuncDecl):
+            function_decl = node.type
+            print('Function: %s' % node.name)
+            if( node.type.args == None ):
+                print('  (no arguments)')
+            else:
+                for param_decl in node.type.args.params:
+                    if( isinstance(param_decl, c_ast.EllipsisParam) ):
+                        param_decl.show(offset=6)
+                        continue
+                    print('  Arg name: %s' % param_decl.name)
+                    print('  Type:')
+                    param_decl.type.show(offset=6)
+
+        if isinstance(node.type, c_ast.FuncDecl):
+            args = node.type.args
+            if isinstance(args, c_ast.ParamList):
+                #rint("params are %s (type %s)" % (str(args.params), 
type(args.params)))
+                if( args == None ):
+                    params.append('')
+                else:
+                    for (i, param) in enumerate(args.params):
+                        params.append(parameter_str(i, name, param))
+                        cbl_args.append(using_str(i, name, param))
+                        (stars, item, definition) = linkage_str(i, name, param)
+                        if definition:
+                            if stars:
+                                string_items.append(item)
+                            linkage_items.append(definition)
+
+            (stars, rets) = starify(node.type)
+
+            if isinstance(rets, c_ast.TypeDecl):
+                q =  ' '.join(rets.quals)
+                if( isinstance(rets.type, c_ast.Struct) ):
+                    t = "struct " + rets.type.name
+                else:
+                    t =  ' '.join(rets.type.names)
+                returns = ' '.join((q, t, stars))
+
+        if name == None:
+            return
+
+        # print the C version as a comment
+        cparams = [ x.replace('Lk-', '') for x in params ]
+        print( "      * %s %s(%s)"
+               % (returns, name, ', '.join(cparams)) )
+
+        # print the UDF
+        print( '        Identification Division.')
+        sname = name
+        if( sname[0] == '_' ):
+            sname = sname[1:]
+        print( '        Function-ID. posix-%s.' % sname)
+
+        print( '        Data Division.')
+        print( '        Linkage Section.')
+        print( '          77 Return-Value Binary-Long.')
+        for item  in linkage_items:
+            print( '          %s.' % item.strip())
+        args = ',\n             '.join(cbl_args)
+        args = 'using\n             %s\n            ' % args
+        print( '        Procedure Division %s Returning Return-Value.'
+               % args )
+        for item in string_items:
+            print( '          Inspect Backward %s ' % item +
+                   'Replacing Leading Space By Low-Value' )
+        using_args = ''
+        if args:
+            using_args = '%s' % args
+        print( '          Call "%s" %s Returning Return-Value.'
+               % (name, using_args) )
+        print( '          Goback.')
+        print( '        End Function posix-%s.' % sname)
+
+# Hard code a path to the fake includes
+# if not using cpp(1) environment variables.
+cpp_args = ['-I/home/jklowden/projects/3rd/pycparser/utils/fake_libc_include']
+
+for var in ('CPATH', 'C_INCLUDE_PATH'):
+    dir = os.getenv(var)
+    if dir:
+        cpp_args = ''
+
+def process(srcfile):
+    ast = parse_file(srcfile, use_cpp=True, cpp_args=cpp_args)
+    # print(c_generator.CGenerator().visit(ast))
+    v = VisitPrototypes()
+    v.visit(ast)
+
+__doc__ = """
+SYNOPSIS
+    udf-gen [-I include-path] [header-file ...]
+
+DESCRIPTION
+    For each C function declared in header-file,
+produce an ISO COBOL user-defined function definition to call it.
+If no filename is supplied, declarations are read from standard input.
+All output is written to standard output.
+
+    This Python script uses the PLY pycparser module,
+(http://www.dabeaz.com/ply/), which supplies a set of simplified "fake
+header files" to avoid parsing the (very complex) standard C header
+files.  These alost suffice for parsing the Posix function
+declarations in Section 2 of the manual.
+
+    Use the -I option or the cpp(1) environment variables to direct
+the preprocessor to use the fake header files instead of the system
+header files.
+
+LIMITATIONS
+    udf-gen does not recognize C struct parameters, such as used by stat(2).
+
+     No attempt has been made to define "magic" values, such as would
+be needed for example by chmod(2).
+"""
+
+def main( argv=None ):
+    global cpp_args
+    if argv is None:
+        argv = sys.argv
+    # parse command line options
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "D:hI:m:", ["help"])
+    except getopt.error as msg:
+        print(msg)
+        print("for help use --help")
+        sys.exit(2)
+
+    # process options
+    astfile = None
+
+    for opt, arg in opts:
+        if opt in ("-h", "--help"):
+            print(__doc__)
+            sys.exit(0)
+        if opt == '-D':
+            cpp_args.append('-D%s ' % arg)
+        if opt == '-I':
+            cpp_args[0] = '-I' + arg
+
+    # process arguments
+    if not args:
+        args = ('/dev/stdin',)
+
+    for arg in args:
+        process(arg)
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/gcc/cobol/posix/udf/Makefile b/gcc/cobol/posix/udf/Makefile
new file mode 100644
index 00000000000..8321f2dde90
--- /dev/null
+++ b/gcc/cobol/posix/udf/Makefile
@@ -0,0 +1,27 @@
+LDFLAGS = -L $$(pwd) -Wl,-rpath -Wl,$$(pwd)
+
+all: t/exit t/errno
+
+t/exit: posix-exit.cbl t/exit.cbl
+       ../../built-gcobol $(FLAGS) -o $@ -I$$(pwd) $(lastword $^)
+
+t/errno: t/errno.cbl posix-mkdir.cbl | libposix-errno.so
+       ../../built-gcobol $(FLAGS) -o $@ -I$$(pwd) \
+       $(firstword $^) $(LDFLAGS) -lposix-errno
+
+libposix-errno.so: ../c/posix_errno.c posix-errno.o
+       gcc $(CFLAGS) -shared -o $@ $^
+
+posix-errno.o: posix-errno.cbl
+       ../../built-gcobol $(FLAGS) -fPIC  -c -o $@ $^
+
+posix-mkdir.cbl:
+       man 2 mkdir | ../scrape.awk | \
+       ../udf-gen -D mode_t=unsigned\ long  > $@~
+       @mv $@~ $@
+
+test: $(basename $(wildcard t/*.cbl))
+       t/errno
+
+clean:
+       rm -f *.o *.so $(basename $(wildcard t/*.cbl))
diff --git a/gcc/cobol/posix/udf/posix-errno.cbl 
b/gcc/cobol/posix/udf/posix-errno.cbl
new file mode 100644
index 00000000000..9670637b3ba
--- /dev/null
+++ b/gcc/cobol/posix/udf/posix-errno.cbl
@@ -0,0 +1,18 @@
+       Identification Division.
+       Function-ID. posix-errno.
+
+       Data Division.
+       Linkage Section.
+       77 Return-Value Binary-Long.
+       01 Error-Msg PIC X ANY LENGTH.
+
+       Procedure Division
+           using Error-Msg
+           Returning Return-Value.
+       CALL "posix_errno"
+           returning Return-Value.
+       CALL "strerror"
+           using by value Return-Value
+           returning error-msg.
+       Goback.
+       END FUNCTION posix-errno.
diff --git a/gcc/cobol/posix/udf/posix-exit.cbl 
b/gcc/cobol/posix/udf/posix-exit.cbl
new file mode 100644
index 00000000000..cd2ac1857e9
--- /dev/null
+++ b/gcc/cobol/posix/udf/posix-exit.cbl
@@ -0,0 +1,12 @@
+       Identification Division.
+       Function-ID. posix-exit.
+
+       Data Division.
+       Linkage Section.
+       77 Return-Value Binary-Long.
+       77 Exit-Status Binary-Long.
+
+       Procedure Division using Exit-Status Returning Return-Value.
+       CALL "_exit" using by value Exit-Status.
+       Goback.
+       END FUNCTION posix-exit.
\ No newline at end of file
diff --git a/gcc/cobol/posix/udf/t/errno.cbl b/gcc/cobol/posix/udf/t/errno.cbl
new file mode 100644
index 00000000000..22078ae3c31
--- /dev/null
+++ b/gcc/cobol/posix/udf/t/errno.cbl
@@ -0,0 +1,26 @@
+        COPY posix-mkdir.
+        COPY posix-errno.
+
+        Identification Division.
+        Program-ID. test-errno.
+        Data Division.
+        Working-Storage Section.
+        77 Return-Value Binary-Long.
+        77 Exit-Status Binary-Long Value 1.
+        77 error-msg PIC X(100).
+        77 errnum Binary-Long.
+        77 Filename PIC X(100) Value '/'.
+
+        Procedure Division.
+        Display 'calling posix-mkdir with a foolish name ...'
+        Move Function posix-mkdir(Filename, 0) to Return-Value.
+        If Return-Value <> 0
+            Display 'calling posix-errno ...'
+            Move Function posix-errno(error-msg) to errnum
+            Display 'error: "' Filename '": ' error-msg ' (' errnum ')'
+            Goback with Error Status errnum
+        Else
+            Display 'Return-Value is ' Return-Value
+        End-If.
+
+        Goback.
diff --git a/gcc/cobol/posix/udf/t/exit.cbl b/gcc/cobol/posix/udf/t/exit.cbl
new file mode 100644
index 00000000000..4aed400b17a
--- /dev/null
+++ b/gcc/cobol/posix/udf/t/exit.cbl
@@ -0,0 +1,15 @@
+        COPY posix-exit.
+
+        Identification Division.
+        Program-ID. test-exit.
+        Data Division.
+        Working-Storage Section.
+        77 Return-Value Binary-Long.
+        77 Exit-Status Binary-Long Value 1.
+
+        Procedure Division.
+        Display 'calling posix-exit ...'
+        Move Function posix-exit(Exit-Status) to Return-Value.
+      * Does not return, Does not print
+        Display 'How did we get here?'
+        Goback.

Reply via email to