mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-21 19:35:28 -05:00
This big commit: * Adds support to the FFI mechanism to map Algol 68 procedures returning strings to an equivalent C interface. * Adds a new command-line option -fbuilding-libga68. * Adds support for having modules in libga68 implicitly invoked in user-written programs and modules. * Using the infrastructure agove, removes the compiler-generated glue to call the standard POSIX prelude shipped in libga68 to, instead, use the formal holes mechanism for FFI. * Adds posix.a68 to libga68. * Adds standard.a68 to libga68. Signed-off-by: Jose E. Marchesi <jemarch@gnu.org> gcc/algol68/ChangeLog * a68-moids-misc.cc (a68_is_c_mode): Allow C formal holes for routines yielding strings. * a68-low-holes.cc (a68_wrap_formal_proc_hole): Support wrappers that yield strings. * a68.h: Remove a68_posix_* and a68_lower_posix* prototypes. * a68-low-posix.cc: Remove. * a68-imports.cc (a68_open_packet): Get argument filename. * Make-lang.in (ALGOL68_OBJS): Remove algol68/a68-low-posix.o. * a68-low-runtime.def: Remove POSIX_*. * lang.opt (-fcheck): Add new undocumented option -fbuilding-libga68. * a68-parser-prelude.cc (stand_transput): New function. (posix_prelude): Remove hardcoded additions to the top-level environment and use a68_extract_revelations instead. * a68-parser-extract.cc (a68_extract_revelation): Renamed from extract_revelation and made accessible externally. * a68-low.cc (a68_make_formal_hole_decl): Remove unneeded check. (lower_lude_decl): New function. (lower_module_text): Add calls to preludes and postludes of standard modules if not building libga68. (a68_lower_particular_program): Likewise. * a68-low-prelude.cc (a68_lower_posixargc): Remove. (a68_lower_posixargv): Likewise. (a68_lower_posixgetenv): Likewise. (a68_lower_posixputchar): Likewise. (a68_lower_posixputs): Likewise. (a68_lower_posixfconnect): Likewise. (a68_lower_posixfopen): Likewise. (a68_lower_posixfcreate): Likewise. (a68_lower_posixfclose): Likewise. (a68_lower_posixfsize): Likewise. (a68_lower_posixlseek): Likewise. (a68_lower_posixseekcur): Likewise. (a68_lower_posixseekend): Likewise. (a68_lower_posixseekset): Likewise. (a68_lower_posixstdinfiledes): Likewise. (a68_lower_posixstdoutfiledes): Likewise. (a68_lower_posixstderrfiledes): Likewise. (a68_lower_posixfileodefault): Likewise. (a68_lower_posixfileordwr): Likewise. (a68_lower_posixfileordonly): Likewise. (a68_lower_posixfileowronly): Likewise. (a68_lower_posixfileotrunc): Likewise. (a68_lower_posixerrno): Likewise. (a68_lower_posixexit): Likewise. (a68_lower_posixperror): Likewise. (a68_lower_posixstrerror): Likewise. (a68_lower_posixfputc): Likewise. (a68_lower_posixfputs): Likewise. (a68_lower_posixgetchar): Likewise. (a68_lower_posixfgetc): Likewise. (a68_lower_posixgets): Likewise. (a68_lower_posixfgets): Likewise. gcc/testsuite/ChangeLog * lib/algol68.exp (algol68_init): Add -I options to ALGOL68_UNDER_TEST so exports in libga68.{a,so} are found. * algol68/compile/warning-hidding-6.a68: Likewise. * algol68/compile/warning-hidding-5.a68: Use maxint instead of getchar to trigger the warning. * algol68/compile/error-nest-4.a68: Procedures yielding strings are now on in C formal holes. libga68/ChangeLog * posix.a68: New file. * standard.a68.in: Likewise. * ga68-posix.c (_libga68_stdin): Define. (_libga68_stdout): Likewise. (_libga68_stderr): Likewise. (_libga68_file_o_default): Likewise. (_libga68_file_o_rdonly): Likewise. (_libga68_file_o_rdwr): Likewise. (_libga68_file_o_trunc): Likewise. (_libga68_seek_cur): Likewise. (_libga68_seek_end): Likewise. (_libga68_seek_set): Likewise. (_libga68_posixstrerror): Update interface to new way of returning Algol 68 strings. (_libga68_posixargv): Likewise. (_libga68_posixfgets): Likewise. (_libga68_posixgets): Likewise. (_libga68_posixfopen): Use _libga68_file_o_default rather than FILE_O_DEFAULT. (_libga68_posixfopen): Ditto for other FILE_O_* values. * ga68.h: Update prototypes. * Makefile.am (libga68_la_LIBADD): Add standard.lo. (libga68_la_DEPENDENCIES): Likeise. (.a68.o): Pass -fbuilding-libga68. (.a68.lo): Likewise. (standard.a68): New rule. * Makefile.in: Regenerate. * transput.a68.in: Add Emacs -*- mode: a68 -*- comment.
280 lines
11 KiB
Plaintext
280 lines
11 KiB
Plaintext
{ Process this file with sppp.awk -*- mode: a68 -*- }
|
|
|
|
{ transput.a68.in - Standard transput.
|
|
|
|
Copyright (C) 2025 Jose E. Marchesi
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
License for more details.
|
|
|
|
Under Section 7 of GPL version 3, you are granted additional
|
|
permissions described in the GCC Runtime Library Exception, version
|
|
3.1, as published by the Free Software Foundation.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
and a copy of the GCC Runtime Library Exception along with this
|
|
program; see the files COPYING3 and COPYING.RUNTIME respectively.
|
|
If not, see <http://www.gnu.org/licenses/>. }
|
|
|
|
module Transput =
|
|
def
|
|
{ 10.3.2.1. Conversion routines. }
|
|
|
|
mode Number = union (
|
|
{iter L {short short} {short} {} {long} {long long}}
|
|
{L} int
|
|
{reti {,}}
|
|
,
|
|
{iter L {} {long} {long long}}
|
|
{L} real
|
|
{reti {,}}
|
|
);
|
|
|
|
pub proc whole = (Number v, int width) string:
|
|
case v in
|
|
{iter L {short short} {short} {} {long} {long long}}
|
|
{iter L_ {short_short_} {short_} {} {long_} {long_long_}}
|
|
({L} int x):
|
|
(int length := ABS width - (x < {L} 0 OR width > 0 | 1 | 0),
|
|
{L} int n := ABS x;
|
|
if width = 0
|
|
then {L} int m := n; length := 0;
|
|
while m %:= {L} 10; length +:= 1; m /= {L} 0
|
|
do ~ od
|
|
fi;
|
|
string s := subwhole (n, length);
|
|
if length = 0 OR char_in_string (errorchar, loc int, s)
|
|
then ABS width * errorchar
|
|
else (x < {L} 0 | "-" |: width > 0 | "+" | "") +=: s;
|
|
(width /= 0 | (ABS width - UPB s) * " " +=: s);
|
|
s
|
|
fi),
|
|
({L} real x): fixed (x, width, 0)
|
|
{reti {,}}
|
|
esac;
|
|
|
|
pub proc fixed = (Number v, int width, after) string:
|
|
case v in
|
|
{iter L {} {long} {long long}}
|
|
({L} real x):
|
|
if int length := ABS width - (x < {L} 0 OR width > 0 | 1 | 0);
|
|
after >= 0 AND (length > after OR width = 0)
|
|
then {L} real y = ABS x;
|
|
if width = 0
|
|
then length := (after = 0 | 1 | 0);
|
|
while y + {L} .5 * {L} .1 ** after >= {L} 10 ** length
|
|
do length +:= 1 od;
|
|
length +:= (after = 0 | 0 | after + 1)
|
|
fi;
|
|
string s := subfixed (y, length, after);
|
|
if ~char_in_string (errorchar, loc int, s)
|
|
then (length > UPB s AND y < {L} 1.0 | "0" +=: s);
|
|
(x < {L} 0 | "-" |: width > 0 | "+" | "") +=: s;
|
|
(width /= 0 | (ABS width - UPB s) * " " +=: s);
|
|
s
|
|
elif after > 0
|
|
then fixed (v, width, after - 1)
|
|
else ABS width * errorchar
|
|
fi
|
|
else { XXX undefined } skip; ABS width * errorchar
|
|
fi,
|
|
({L} int x): fixed ({L} real (x), width, after)
|
|
{reti {,}}
|
|
esac;
|
|
|
|
pub proc float = (Number v, int width, after, exp) string:
|
|
case v in
|
|
{iter L {} {long} {long long}}
|
|
{iter L_ {} {long_} {long_long_}}
|
|
({L} real x):
|
|
if int before = ABS width - ABS exp - (after /= 0 | after+1 | 0) - 2;
|
|
SIGN before + SIGN after > 0
|
|
then string s, {L} real y := ABS x, int p := 0;
|
|
{L_}standardize (y, before, after, p);
|
|
s := fixed (SIGN (x * y), SIGN width * (ABS width - ABS exp - 1),
|
|
after) + "*^" + whole (p, exp);
|
|
if exp = 0 OR char_in_string (errorchar, loc int, s)
|
|
then float (x, width, (after /= 0 | after-1 | 0),
|
|
(exp > 0 | exp+1 | exp-1))
|
|
else s
|
|
fi
|
|
else { XXX undefined } skip; ABS width * errorchar
|
|
fi,
|
|
({L} int x): float ({L} real (x), width, after, exp)
|
|
{reti {,}}
|
|
esac;
|
|
|
|
{ Returns a string of maximum length `width' containing a decimal
|
|
representation of the positive integer `v'. }
|
|
|
|
proc subwhole = (Number v, int width) string:
|
|
case v in
|
|
{iter L {short short} {short} {} {long} {long long}}
|
|
{iter S {LENG LENG} {LENG} {} {SHORTEN} {SHORTEN SHORTEN}}
|
|
({L} int x):
|
|
begin string s, {L} int n := x;
|
|
while dig_char ({S} (n MOD {L} 10)) +=: s;
|
|
n %:= {L} 10; n /= {L} 0
|
|
do ~ od;
|
|
(UPB s > width | width * errorchar | s)
|
|
end
|
|
{reti {,}}
|
|
esac;
|
|
|
|
{ Returns a string of maximum length `width' containing a rounded
|
|
decimal representation of the positive real number `v'; if
|
|
`after' is greater than zero, this string contains a decimal
|
|
point followed by `after' digits. }
|
|
|
|
proc subfixed = (Number v, int width, after) string:
|
|
case v in
|
|
{iter L {} {long} {long long}}
|
|
{iter K {} {LENG} {LENG LENG}}
|
|
{iter S {} {SHORTEN} {SHORTEN SHORTEN}}
|
|
({L} real x):
|
|
begin string s, int before := 0;
|
|
{L} real y := x + {L} .5 * {L} .1 ** after;
|
|
proc choosedig = (ref {L} real y) char:
|
|
dig_char ((int c := {S} ENTIER (y *:= {L} 10.0); (c > 9 | c := 9);
|
|
y -:= {K} c; c));
|
|
while y >= {L} 10.0 ** before do before +:= 1 od;
|
|
y /:= {L} 10.0 ** before;
|
|
to before do s +:= choosedig (y) od;
|
|
(after > 0 | s +:= ".");
|
|
to after do s +:= choosedig (y) od;
|
|
(UPB s > width | width * errorchar | s)
|
|
end
|
|
{reti {,}}
|
|
esac;
|
|
|
|
{ Adjusts the value of `y' so that it may be transput according to
|
|
the format $ n(before)d, n(after)d $; `p' is set so that y * 10
|
|
** p is equal to the original value of `y'. }
|
|
|
|
{iter L {} {long} {long long}}
|
|
{iter L_ {} {long_} {long_long_}}
|
|
proc {L_}standardize = (ref {L} real y, int before, after, ref int p) void:
|
|
begin
|
|
{L} real g = {L} 10.0 ** before; {L} real h = g * {L} .1;
|
|
while y >= g do y *:= {L} .1; p +:= 1 od;
|
|
(y /= {L} 0.0 | while y < h do y *:= {L} 10.0; p -:= 1 od);
|
|
(y + {L} .5 * {L} .1 ** after >= g | y := h; p +:= 1)
|
|
end;
|
|
{reti}
|
|
|
|
proc dig_char = (int x) char: "0123456789abcdef"[x+1];
|
|
|
|
{ Returns true if the absolute value of the result is
|
|
<= L max int }
|
|
|
|
{iter L {short short} {short} {} {long} {long long}}
|
|
{iter K {SHORTEN SHORTEN} {SHORTEN} {} {LENG} {LENG LENG}}
|
|
{iter L_ {short_short_} {short_} {} {long_} {long_long_}}
|
|
proc string_to_{L_}int = (string s, int radix, ref {L} int i) bool:
|
|
begin
|
|
{L} int lr = {K} radix; bool safe := true;
|
|
{L} int n := {L} 0, {L} int m = {L_}max_int % lr;
|
|
{L} int m1 = {L_}max_int - m * lr;
|
|
for i from 2 to UPB s
|
|
while {L} int dig = {K} char_dig (s[i]);
|
|
safe := n < m OR n = m AND dig <= m1
|
|
do n := n * lr + dig od;
|
|
if safe then i := (s[1] = "+" | n | -n); true else false fi
|
|
end;
|
|
{reti}
|
|
|
|
{ Returns true if the absolute value of the result is <= L max
|
|
real. }
|
|
|
|
{iter L {} {long} {long long}}
|
|
{iter K {} {LENG} {LENG LENG}}
|
|
{iter S {} {SHORTEN} {SHORTEN SHORTEN}}
|
|
{iter L_ {} {long_} {long_long_}}
|
|
pub proc string_to_{L_}real = (string s, ref {L} real r) bool:
|
|
begin
|
|
int e := UPB s + 1;
|
|
char_in_string ("^" { XXX unicode 10^ }, e, s);
|
|
int p := e; char_in_string (".", p, s);
|
|
int j := 1, length := 0, {L} real x := {L} 0.0;
|
|
{ Skip leading zeroes: }
|
|
for i from 2 to e - 1
|
|
while s[i] = "0" OR s[i] = "." OR s[i] = "_."
|
|
do j := i od;
|
|
for i from j + 1 to e - 1 while length < {L_}real_width
|
|
do
|
|
if s[i] /= "."
|
|
then x := x * {L} 10.0 + {K} char_dig (s[j:=i]); length +:= 1
|
|
fi { all significant digits converted. }
|
|
od;
|
|
{ Set preliminary exponent: }
|
|
int exp := (p > j | p - j - 1 | p - j), expart := 0;
|
|
{ Convert exponent part: }
|
|
bool safe := if e < UPB s
|
|
then {L} int tmp := {K} expart;
|
|
bool b = string_to_{L_}int (s[e+1:], 10, tmp);
|
|
expart = {S} tmp;
|
|
b
|
|
else true
|
|
fi;
|
|
{ Prepare a representation of L max real to compare with the L
|
|
real value to be delivered: }
|
|
{L} real max_stag := {L_}max_real, int max_exp := 0;
|
|
{L_}standardize (max_stag, length, 0, max_exp); exp +:= expart;
|
|
if ~safe OR (exp > max_exp OR exp = max_exp AND x > max_stag)
|
|
then false
|
|
else r := (s[1] = "+" | x | -x) * {L} 10.0 ** exp; true
|
|
fi
|
|
end;
|
|
{reti}
|
|
|
|
proc char_dig = (char x) int:
|
|
(x = "." | 0 | int i; char_in_string (x,i,"0123456789abcdef"); i-1);
|
|
|
|
pub proc char_in_string = (char c, ref int i, string s) bool:
|
|
begin bool found := false;
|
|
for k from LWB s to UPB s while ~found
|
|
do (c = s[k] | i := k; found := true) od;
|
|
found
|
|
end;
|
|
|
|
{ The smallest integral value such that `L max int' may be
|
|
converted without error using the pattern n(L int width)d }
|
|
|
|
{iter L {} {long} {long long}}
|
|
{iter L_ {} {long_} {long_long_}}
|
|
pub int {L_}int_width =
|
|
(int c := 1; while {L} 10 ** (c - 1) < {L} .1 * {L_}max_int do c +:= 1 od;
|
|
c);
|
|
{reti}
|
|
|
|
{ The smallest integral value such that different string are
|
|
produced by conversion of `1.0' and of `1.0 + L small real'
|
|
using the pattern d .n(L real width - 1)d }
|
|
|
|
{iter L {} {long} {long long}}
|
|
{iter L_ {} {long_} {long_long_}}
|
|
{iter S {} {SHORTEN} {SHORTEN SHORTEN}}
|
|
pub int {L_}real_width = 1 - {S} ENTIER ({L_}ln ({L_}small_real) / {L_}ln ({L} 10));
|
|
{reti}
|
|
|
|
{ The smallest integral value such that `L max real' may be
|
|
converted without error using the pattern
|
|
d .n(L real width - 1)d e n(L exp with)d }
|
|
|
|
{iter L {} {long} {long long}}
|
|
{iter L_ {} {long_} {long_long_}}
|
|
{iter S {} {SHORTEN} {SHORTEN SHORTEN}}
|
|
pub int {L_}exp_width =
|
|
1 + {S} ENTIER ({L_}ln ({L_}ln ({L_}max_real) / {L_}ln ({L} 10)) / {L_}ln ({L} 10));
|
|
{reti}
|
|
|
|
skip
|
|
fed
|