[v2] a68: Add exit function to POSIX prelude

Message ID 20260109051624.241877-1-pietro@sociotechnical.xyz
State Superseded
Headers
Series [v2] a68: Add exit function to POSIX prelude |

Commit Message

Pietro Monteiro Jan. 9, 2026, 5:16 a.m. UTC
  I wans't able to figure out how to to add a test that exits with a
non-zero status and is marked as passing.  So I added a simple test
that exits with a zero status.
-- >8 --
Add the procedure `posixexit'.

gcc/algol68/ChangeLog:

	* a68-low-posix.cc (a68_posix_exit): New function.
	* a68-low-prelude.cc (a68_lower_posixexit): Likewise.
	* a68-low-runtime.def (POSIX_EXIT): Add definition for posixexit.
	* a68-parser-prelude.cc (posix_prelude): Add posixexit identifier to
	standenv.
	* a68.h (a68_posix_exit): New prototype.
	(a68_lower_posixexit): Likewise.
	* ga68.texi: Describe posix_exit.

gcc/testsuite/ChangeLog:

	* algol68/execute/posix-exit-1.a68: New test.

libga68/ChangeLog:

	* ga68-posix.c (_libga68_posixexit): New function.
	* ga68.h (_libga68_posixexit): New prototype.
	* ga68.map: Add _libga68_posixexit to global map.

Signed-off-by: Pietro Monteiro <pietro@sociotechnical.xyz>
---
 gcc/algol68/a68-low-posix.cc                   |  6 ++++++
 gcc/algol68/a68-low-prelude.cc                 | 10 ++++++++++
 gcc/algol68/a68-low-runtime.def                |  1 +
 gcc/algol68/a68-parser-prelude.cc              |  2 ++
 gcc/algol68/a68.h                              |  2 ++
 gcc/algol68/ga68.texi                          | 13 +++++++++----
 gcc/testsuite/algol68/execute/posix-exit-1.a68 |  3 +++
 libga68/ga68-posix.c                           |  9 +++++++++
 libga68/ga68.h                                 |  1 +
 libga68/ga68.map                               |  1 +
 10 files changed, 44 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/algol68/execute/posix-exit-1.a68


base-commit: 35476a0da65fb13651238e38ae98398c78f12b2e
  

Comments

Jose E. Marchesi Jan. 9, 2026, 10:25 a.m. UTC | #1
Hello Pietro.
Thanks for the patch.

> I wans't able to figure out how to to add a test that exits with a
> non-zero status and is marked as passing.  So I added a simple test
> that exits with a zero status.
> -- >8 --
> Add the procedure `posixexit'.
>
> gcc/algol68/ChangeLog:
>
> 	* a68-low-posix.cc (a68_posix_exit): New function.
> 	* a68-low-prelude.cc (a68_lower_posixexit): Likewise.
> 	* a68-low-runtime.def (POSIX_EXIT): Add definition for posixexit.
> 	* a68-parser-prelude.cc (posix_prelude): Add posixexit identifier to
> 	standenv.
> 	* a68.h (a68_posix_exit): New prototype.
> 	(a68_lower_posixexit): Likewise.
> 	* ga68.texi: Describe posix_exit.
>
> gcc/testsuite/ChangeLog:
>
> 	* algol68/execute/posix-exit-1.a68: New test.
>
> libga68/ChangeLog:
>
> 	* ga68-posix.c (_libga68_posixexit): New function.
> 	* ga68.h (_libga68_posixexit): New prototype.
> 	* ga68.map: Add _libga68_posixexit to global map.
>
> Signed-off-by: Pietro Monteiro <pietro@sociotechnical.xyz>
> ---
>  gcc/algol68/a68-low-posix.cc                   |  6 ++++++
>  gcc/algol68/a68-low-prelude.cc                 | 10 ++++++++++
>  gcc/algol68/a68-low-runtime.def                |  1 +
>  gcc/algol68/a68-parser-prelude.cc              |  2 ++
>  gcc/algol68/a68.h                              |  2 ++
>  gcc/algol68/ga68.texi                          | 13 +++++++++----
>  gcc/testsuite/algol68/execute/posix-exit-1.a68 |  3 +++
>  libga68/ga68-posix.c                           |  9 +++++++++
>  libga68/ga68.h                                 |  1 +
>  libga68/ga68.map                               |  1 +
>  10 files changed, 44 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/algol68/execute/posix-exit-1.a68
>
> diff --git a/gcc/algol68/a68-low-posix.cc b/gcc/algol68/a68-low-posix.cc
> index 6b6ae76cf37..bc5b811ae01 100644
> --- a/gcc/algol68/a68-low-posix.cc
> +++ b/gcc/algol68/a68-low-posix.cc
> @@ -341,6 +341,12 @@ a68_posix_errno (void)
>    return a68_get_libcall (A68_LIBCALL_POSIX_ERRNO);
>  }
>  
> +tree
> +a68_posix_exit (void)
> +{
> +  return a68_get_libcall (A68_LIBCALL_POSIX_EXIT);
> +}
> +
>  tree
>  a68_posix_perror (void)
>  {
> diff --git a/gcc/algol68/a68-low-prelude.cc b/gcc/algol68/a68-low-prelude.cc
> index bd54b207fbe..ded200c5d4a 100644
> --- a/gcc/algol68/a68-low-prelude.cc
> +++ b/gcc/algol68/a68-low-prelude.cc
> @@ -2112,6 +2112,16 @@ a68_lower_posixerrno (NODE_T *p ATTRIBUTE_UNUSED,
>    return t;
>  }
>  
> +tree
> +a68_lower_posixexit (NODE_T *p ATTRIBUTE_UNUSED,
> +		     LOW_CTX_T ctx ATTRIBUTE_UNUSED)
> +{
> +  tree t = a68_posix_exit ();
> +  if (CAN_HAVE_LOCATION_P (t))
> +    SET_EXPR_LOCATION (t, a68_get_node_location (p));
> +  return t;
> +}
> +
>  tree
>  a68_lower_posixperror (NODE_T *p ATTRIBUTE_UNUSED,
>  		       LOW_CTX_T ctx ATTRIBUTE_UNUSED)
> diff --git a/gcc/algol68/a68-low-runtime.def b/gcc/algol68/a68-low-runtime.def
> index 04cca03ca51..b3d90942710 100644
> --- a/gcc/algol68/a68-low-runtime.def
> +++ b/gcc/algol68/a68-low-runtime.def
> @@ -78,6 +78,7 @@ DEF_A68_RUNTIME (POSIX_GETS, "_libga68_posixgets", RT(UNISTRPTR), P2(INT,SIZEPTR
>  DEF_A68_RUNTIME (POSIX_FGETS, "_libga68_posixfgets", RT(UNISTRPTR), P3(INT,INT,SIZEPTR), 0)
>  DEF_A68_RUNTIME (POSIX_GETENV, "_libga68_posixgetenv", RT(VOID), P5(UNISTR,SIZE,SIZE,UNISTRPTR,SIZEPTR), 0)
>  DEF_A68_RUNTIME (POSIX_ERRNO, "_libga68_posixerrno", RT(INT), P0(), 0)
> +DEF_A68_RUNTIME (POSIX_EXIT, "_libga68_posixexit", RT(VOID), P1(INT), 0)
>  DEF_A68_RUNTIME (POSIX_PERROR, "_libga68_posixperror", RT(VOID), P3(UNISTR,SIZE,SIZE), 0)
>  DEF_A68_RUNTIME (POSIX_STRERROR, "_libga68_posixstrerror", RT(UNISTRPTR), P2(INT, SIZEPTR), 0)
>  DEF_A68_RUNTIME (POSIX_LSEEK, "_libga68_posixlseek", RT(LONGLONGINT), P3(INT,LONGLONGINT,INT), 0)
> diff --git a/gcc/algol68/a68-parser-prelude.cc b/gcc/algol68/a68-parser-prelude.cc
> index cb899873f35..5c54a513883 100644
> --- a/gcc/algol68/a68-parser-prelude.cc
> +++ b/gcc/algol68/a68-parser-prelude.cc
> @@ -1379,6 +1379,8 @@ posix_prelude (void)
>    /* Exit status handling.  */
>    m = a68_proc (M_VOID, M_INT, NO_MOID);
>    a68_idf (A68_EXT, "setexitstatus", m, a68_lower_setexitstatus);
> +  m = a68_proc (M_VOID, M_INT, NO_MOID);
> +  a68_idf (A68_EXT, "posixexit", m, a68_lower_posixexit);
>    /* Argument handling.  */
>    m = A68_MCACHE (proc_int);
>    a68_idf (A68_EXT, "argc", m, a68_lower_posixargc);
> diff --git a/gcc/algol68/a68.h b/gcc/algol68/a68.h
> index dc73277038c..3f288811f4b 100644
> --- a/gcc/algol68/a68.h
> +++ b/gcc/algol68/a68.h
> @@ -591,6 +591,7 @@ tree a68_posix_fclose (void);
>  tree a68_posix_fsize (void);
>  tree a68_posix_lseek (void);
>  tree a68_posix_errno (void);
> +tree a68_posix_exit (void);
>  tree a68_posix_perror (void);
>  tree a68_posix_strerror (void);
>  tree a68_posix_getchar (void);
> @@ -1093,6 +1094,7 @@ tree a68_lower_posixfileordonly (NODE_T *p, LOW_CTX_T ctx);
>  tree a68_lower_posixfileowronly (NODE_T *p, LOW_CTX_T ctx);
>  tree a68_lower_posixfileotrunc (NODE_T *p, LOW_CTX_T ctx);
>  tree a68_lower_posixerrno (NODE_T *p, LOW_CTX_T ctx);
> +tree a68_lower_posixexit (NODE_T *p, LOW_CTX_T ctx);
>  tree a68_lower_posixperror (NODE_T *p, LOW_CTX_T ctx);
>  tree a68_lower_posixstrerror (NODE_T *p, LOW_CTX_T ctx);
>  tree a68_lower_posixgetchar (NODE_T *p, LOW_CTX_T ctx);
> diff --git a/gcc/algol68/ga68.texi b/gcc/algol68/ga68.texi
> index d63b1f9de35..93ad1aa3343 100644
> --- a/gcc/algol68/ga68.texi
> +++ b/gcc/algol68/ga68.texi
> @@ -2894,19 +2894,24 @@ which is the default.
>  @node POSIX process
>  @section POSIX process
>  
> -The Algol 68 program can report an exit status to the operating system
> -once they stop running.  The exit status reported by default is zero,
> -which corresponds to success.
> +The Algol 68 program reports an exit status to the operating system once
> +it stops running.  The exit status reported by default is zero, which
> +corresponds to success.
>  
>  @deftypefn Procedure {} {set exit status} {= (@B{int} status)}
>  Procedure that sets the exit status to report to the operating system
> -once the program stop executing.  The default exit status is 0 which,
> +once the program stops executing.  The default exit status is 0 which,
>  by convention, is interpreted by POSIX systems as success.  A value
>  different to zero is interpreted as an error status.  This procedure
>  can be invoked more than one, the previous exit status being
>  overwritten.
>  @end deftypefn
>  
> +@deftypefn Procedure {} {posix exit} {= (@B{int} status)}
> +Procedure that sets the exit status to report to the operating system
> +and stops executing the program.
> +@end deftypefn
> +
>  @node POSIX command line
>  @section POSIX command line

Now we have two ways a process can exit with a status code:

* By reaching the end of the particular program.
* By calling posix_exit()

In the first case, the value set by set_exit_status is returned to the
operating system. In the second case, i tis the argument passed to
posix_exit.

The documentation should explicitly explain this, or it may not be clear
if/how these calls impact each other.

---

At this point I am wondering: is it worth to keep set_exit_status along
with posix_exit, given that they are both part of the POSIX prelude?

The process in which set_exit_status came to live was:

* Initially I thought I was very smart and made particular programs to
  yield a value of `int', which was the value returned to the operating
  system, i.e.

    begin initilize();
          int exit_code = if do_work() then 0 else get_error_code() fi;
          finalize();
          exit_code
    end

* But this was of course non-conformant, and someone rightly complained.
  The Revised Report mandates the existence of an implicit label `stop',
  which can be used by programs to exit at any time, and it also says
  that the mode yielded by a particular program is void.

* So I obliged, changed the mode of the particular program from `int' to
  `void', and added the extra set_exit_status procedure and
  corresponding global variable in the runtime. Now you do:

    begin initialize();
          if NOT do_work()then set_exit_status (get_error_code()) fi;
          finalize()
    end

  or using the conformant implicit `stop' label:

    begin initialize();
          if NOT do_work()
          then puts("Error, exitting'n");
               set_exit_status(get_error_code());
               stop
          fi;
          finalize()
    end

So the proposal would be to remove set_exit_status and make the
particular program to return "success" to the operating system if it has
reached the end of the program, directly or indirectly via `stop'.  But
since now we have posix_exit, we should be good:

  begin initialize();
        if NOT do_work()
        then puts("Error, exitting'n");
             posix_exit(1)
        fi;
        finalize()
  end

If we want to retire set_exit_status from the POSIX prelude, this is the
right time to do so.  Otherwise we will be stuck with it forever.

WDYT?

> diff --git a/gcc/testsuite/algol68/execute/posix-exit-1.a68 b/gcc/testsuite/algol68/execute/posix-exit-1.a68
> new file mode 100644
> index 00000000000..c2b9b99d2c4
> --- /dev/null
> +++ b/gcc/testsuite/algol68/execute/posix-exit-1.a68
> @@ -0,0 +1,3 @@
> +begin posix_exit (0);
> +      assert (1 = 2) { if this assert triggers then posix_exit is broken}

Why not simply `assert(false)'?

> +end
> diff --git a/libga68/ga68-posix.c b/libga68/ga68-posix.c
> index 47038d6e39f..40c703d09c6 100644
> --- a/libga68/ga68-posix.c
> +++ b/libga68/ga68-posix.c
> @@ -461,3 +461,12 @@ _libga68_posixlseek (int fd, long long int offset, int whence)
>    _libga68_errno = errno;
>    return ret;
>  }
> +
> +/* Implementation of the posix prelude `exit'.  */
> +
> +void
> +_libga68_posixexit (int status)
> +{
> +  _libga68_set_exit_status (status);
> +  exit (status);
> +}
> diff --git a/libga68/ga68.h b/libga68/ga68.h
> index 18f3a563112..7077f866109 100644
> --- a/libga68/ga68.h
> +++ b/libga68/ga68.h
> @@ -84,6 +84,7 @@ long double _libga68_longlongrandom (void);
>  /* ga68-posix.c  */
>  
>  int _libga68_posixerrno (void);
> +void _libga68_posixexit (int) __attribute__ ((__noreturn__));
>  void _libga68_posixperror (uint32_t *s, size_t len, size_t stride);
>  uint32_t *_libga68_posixstrerror (int errnum, size_t *len);
>  long long int _libga68_posixfsize (int fd);
> diff --git a/libga68/ga68.map b/libga68/ga68.map
> index f956655de03..48bcae4a3c2 100644
> --- a/libga68/ga68.map
> +++ b/libga68/ga68.map
> @@ -16,6 +16,7 @@ LIBGA68_2.0 {
>      _libga68_posixclose;
>      _libga68_posixcreat;
>      _libga68_posixerrno;
> +    _libga68_posixexit;
>      _libga68_posixfconnect;
>      _libga68_posixfgetc;
>      _libga68_posixfgets;
>
> base-commit: 35476a0da65fb13651238e38ae98398c78f12b2e
  

Patch

diff --git a/gcc/algol68/a68-low-posix.cc b/gcc/algol68/a68-low-posix.cc
index 6b6ae76cf37..bc5b811ae01 100644
--- a/gcc/algol68/a68-low-posix.cc
+++ b/gcc/algol68/a68-low-posix.cc
@@ -341,6 +341,12 @@  a68_posix_errno (void)
   return a68_get_libcall (A68_LIBCALL_POSIX_ERRNO);
 }
 
+tree
+a68_posix_exit (void)
+{
+  return a68_get_libcall (A68_LIBCALL_POSIX_EXIT);
+}
+
 tree
 a68_posix_perror (void)
 {
diff --git a/gcc/algol68/a68-low-prelude.cc b/gcc/algol68/a68-low-prelude.cc
index bd54b207fbe..ded200c5d4a 100644
--- a/gcc/algol68/a68-low-prelude.cc
+++ b/gcc/algol68/a68-low-prelude.cc
@@ -2112,6 +2112,16 @@  a68_lower_posixerrno (NODE_T *p ATTRIBUTE_UNUSED,
   return t;
 }
 
+tree
+a68_lower_posixexit (NODE_T *p ATTRIBUTE_UNUSED,
+		     LOW_CTX_T ctx ATTRIBUTE_UNUSED)
+{
+  tree t = a68_posix_exit ();
+  if (CAN_HAVE_LOCATION_P (t))
+    SET_EXPR_LOCATION (t, a68_get_node_location (p));
+  return t;
+}
+
 tree
 a68_lower_posixperror (NODE_T *p ATTRIBUTE_UNUSED,
 		       LOW_CTX_T ctx ATTRIBUTE_UNUSED)
diff --git a/gcc/algol68/a68-low-runtime.def b/gcc/algol68/a68-low-runtime.def
index 04cca03ca51..b3d90942710 100644
--- a/gcc/algol68/a68-low-runtime.def
+++ b/gcc/algol68/a68-low-runtime.def
@@ -78,6 +78,7 @@  DEF_A68_RUNTIME (POSIX_GETS, "_libga68_posixgets", RT(UNISTRPTR), P2(INT,SIZEPTR
 DEF_A68_RUNTIME (POSIX_FGETS, "_libga68_posixfgets", RT(UNISTRPTR), P3(INT,INT,SIZEPTR), 0)
 DEF_A68_RUNTIME (POSIX_GETENV, "_libga68_posixgetenv", RT(VOID), P5(UNISTR,SIZE,SIZE,UNISTRPTR,SIZEPTR), 0)
 DEF_A68_RUNTIME (POSIX_ERRNO, "_libga68_posixerrno", RT(INT), P0(), 0)
+DEF_A68_RUNTIME (POSIX_EXIT, "_libga68_posixexit", RT(VOID), P1(INT), 0)
 DEF_A68_RUNTIME (POSIX_PERROR, "_libga68_posixperror", RT(VOID), P3(UNISTR,SIZE,SIZE), 0)
 DEF_A68_RUNTIME (POSIX_STRERROR, "_libga68_posixstrerror", RT(UNISTRPTR), P2(INT, SIZEPTR), 0)
 DEF_A68_RUNTIME (POSIX_LSEEK, "_libga68_posixlseek", RT(LONGLONGINT), P3(INT,LONGLONGINT,INT), 0)
diff --git a/gcc/algol68/a68-parser-prelude.cc b/gcc/algol68/a68-parser-prelude.cc
index cb899873f35..5c54a513883 100644
--- a/gcc/algol68/a68-parser-prelude.cc
+++ b/gcc/algol68/a68-parser-prelude.cc
@@ -1379,6 +1379,8 @@  posix_prelude (void)
   /* Exit status handling.  */
   m = a68_proc (M_VOID, M_INT, NO_MOID);
   a68_idf (A68_EXT, "setexitstatus", m, a68_lower_setexitstatus);
+  m = a68_proc (M_VOID, M_INT, NO_MOID);
+  a68_idf (A68_EXT, "posixexit", m, a68_lower_posixexit);
   /* Argument handling.  */
   m = A68_MCACHE (proc_int);
   a68_idf (A68_EXT, "argc", m, a68_lower_posixargc);
diff --git a/gcc/algol68/a68.h b/gcc/algol68/a68.h
index dc73277038c..3f288811f4b 100644
--- a/gcc/algol68/a68.h
+++ b/gcc/algol68/a68.h
@@ -591,6 +591,7 @@  tree a68_posix_fclose (void);
 tree a68_posix_fsize (void);
 tree a68_posix_lseek (void);
 tree a68_posix_errno (void);
+tree a68_posix_exit (void);
 tree a68_posix_perror (void);
 tree a68_posix_strerror (void);
 tree a68_posix_getchar (void);
@@ -1093,6 +1094,7 @@  tree a68_lower_posixfileordonly (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_posixfileowronly (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_posixfileotrunc (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_posixerrno (NODE_T *p, LOW_CTX_T ctx);
+tree a68_lower_posixexit (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_posixperror (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_posixstrerror (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_posixgetchar (NODE_T *p, LOW_CTX_T ctx);
diff --git a/gcc/algol68/ga68.texi b/gcc/algol68/ga68.texi
index d63b1f9de35..93ad1aa3343 100644
--- a/gcc/algol68/ga68.texi
+++ b/gcc/algol68/ga68.texi
@@ -2894,19 +2894,24 @@  which is the default.
 @node POSIX process
 @section POSIX process
 
-The Algol 68 program can report an exit status to the operating system
-once they stop running.  The exit status reported by default is zero,
-which corresponds to success.
+The Algol 68 program reports an exit status to the operating system once
+it stops running.  The exit status reported by default is zero, which
+corresponds to success.
 
 @deftypefn Procedure {} {set exit status} {= (@B{int} status)}
 Procedure that sets the exit status to report to the operating system
-once the program stop executing.  The default exit status is 0 which,
+once the program stops executing.  The default exit status is 0 which,
 by convention, is interpreted by POSIX systems as success.  A value
 different to zero is interpreted as an error status.  This procedure
 can be invoked more than one, the previous exit status being
 overwritten.
 @end deftypefn
 
+@deftypefn Procedure {} {posix exit} {= (@B{int} status)}
+Procedure that sets the exit status to report to the operating system
+and stops executing the program.
+@end deftypefn
+
 @node POSIX command line
 @section POSIX command line
 
diff --git a/gcc/testsuite/algol68/execute/posix-exit-1.a68 b/gcc/testsuite/algol68/execute/posix-exit-1.a68
new file mode 100644
index 00000000000..c2b9b99d2c4
--- /dev/null
+++ b/gcc/testsuite/algol68/execute/posix-exit-1.a68
@@ -0,0 +1,3 @@ 
+begin posix_exit (0);
+      assert (1 = 2) { if this assert triggers then posix_exit is broken}
+end
diff --git a/libga68/ga68-posix.c b/libga68/ga68-posix.c
index 47038d6e39f..40c703d09c6 100644
--- a/libga68/ga68-posix.c
+++ b/libga68/ga68-posix.c
@@ -461,3 +461,12 @@  _libga68_posixlseek (int fd, long long int offset, int whence)
   _libga68_errno = errno;
   return ret;
 }
+
+/* Implementation of the posix prelude `exit'.  */
+
+void
+_libga68_posixexit (int status)
+{
+  _libga68_set_exit_status (status);
+  exit (status);
+}
diff --git a/libga68/ga68.h b/libga68/ga68.h
index 18f3a563112..7077f866109 100644
--- a/libga68/ga68.h
+++ b/libga68/ga68.h
@@ -84,6 +84,7 @@  long double _libga68_longlongrandom (void);
 /* ga68-posix.c  */
 
 int _libga68_posixerrno (void);
+void _libga68_posixexit (int) __attribute__ ((__noreturn__));
 void _libga68_posixperror (uint32_t *s, size_t len, size_t stride);
 uint32_t *_libga68_posixstrerror (int errnum, size_t *len);
 long long int _libga68_posixfsize (int fd);
diff --git a/libga68/ga68.map b/libga68/ga68.map
index f956655de03..48bcae4a3c2 100644
--- a/libga68/ga68.map
+++ b/libga68/ga68.map
@@ -16,6 +16,7 @@  LIBGA68_2.0 {
     _libga68_posixclose;
     _libga68_posixcreat;
     _libga68_posixerrno;
+    _libga68_posixexit;
     _libga68_posixfconnect;
     _libga68_posixfgetc;
     _libga68_posixfgets;