mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-21 19:35:36 -05:00
Most of the standard prelude is implemented in a combination of code
lowered by the front-end (standard operators, contants, etc) and
functions provided by the libga68 run-time library, to which the
former libcalls. Until now, all the support routines in libga68 were
written in C. However, many of the transput facilities are better
implemented in Algol 68.
The Revised Report includes a reference implementation (code listing)
of many of the standard routines. This implementation, however, makes
use of an "extended" program notation in order to denote certain
notions to avoid repetitive code. Therefore this commit includes
sppp, a build-time pre-processor written in awk that is only intended
to be used internally by the libga68 run-time library. This
preprocessor allows us to write code like:
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;
Resulting in cases for short short int, short int, int, long int and
long long int being macro-expanded in the routine's conformance
clause.
This commit also adds the necessary infrastructure for writing Algol
68 code in the libga68 library, including the ability of having
modules exported by libga68. An implementation of some of the
transput routines is also provided in standard.a68: whole, fixed,
float, string_to_L_real, char_in_string, L_int_width, L_real_width and
L_exp_with.
The build system changes include the backport of the Automake Algol 68
support, which is in a released version of Automake but not in the
version used for GCC, to libga68/m4/autoconf.m4.
Signed-off-by: Jose E. Marchesi <jemarch@gnu.org>
ChangeLog
* Makefile.def (flags_to_pass): Rename GA68, GA68FLAGS,
GA68_FOR_TARGET, GA68FLAGS_FOR_TARGET to A68, A68FLAGS,
A68_FOR_TARGET and A68FLAGS_FOR_TARGET.
* Makefile.tpl: Use A68, A68FLAGS, A68_FOR_BUILD and
A68_FOR_TARGET rather than GA68, GA68FLAGS, GA68_FOR_BUILD and
GA68_FOR_TARGET.
* Makefile.in: Regenerate.
* configure.ac: Set A68_FOR_BUILD rather than GA68_FOR_BUILD, and
invoke ACX_PROG_A68 rather than ACX_PROG_GA68.
Subst A68_FOR_BUILD rather than GA68_FOR_BUILD.
Subst A68 and A68FLAGS rather than GA68 and GA68FLAGS.
Set A68_FOR_TARGET rather than GA68_FOR_TARGET.
* configure: Regenerate.
* config-ml.in: Handle A68FLAGS and define A68 in sub-configures.
config/ChangeLog
* acx.m4: Define ACX_PROG_A68 rather than ACX_PROG_GA68.
(ACX_PROG_A68): Set A68 rather than GA68.
gcc/algol68/ChangeLog
* a68-lang.cc (a68_init_options): Add an entry to A68_MODULE_FILES
to map module Transput to the basename ga68.
gcc/testsuite/ChangeLog
* algol68/execute/char-in-string-1.a68: New test.
libga68/ChangeLog
* m4/autoconf.m4: New file.
* configure.ac: Expand AC_PROG_A68.
* configure: Regenerate.
* Makefile.am: Add rules to build Algol 68 sources and to
build the transput module.
* Makefile.in: Regenerate.
* acinclude.m4: Include m4/autoconf.m4.
* sppp.awk: New file.
* transput.a68.in: Likewise.
280 lines
11 KiB
Plaintext
280 lines
11 KiB
Plaintext
{ Process this file with sppp.awk }
|
|
|
|
{ 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
|