Starting FriCAS not in the $HOME directory

21 views
Skip to first unread message

Grégory Vanuxem

unread,
May 23, 2025, 3:57:07 PMMay 23
to fricas...@googlegroups.com, gcl-...@gnu.org
Hello,

I don't know if you can reproduce this: if I start FriCAS from $HOME it starts nicely but if I start in another directory see the snippet below.
I tried with gcl2.7.1-4 from a Debian based distribution and after with the official Debian sid and the same happens:

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  gcl27          2.7.1-6      amd64        GNU Common Lisp compiler



=======================================================
└─$ fricas
openServer result 0
                       FriCAS Computer Algebra System
               Version: FriCAS 2025-04-14 built with gcl 2.7.1
                 Timestamp: Fri May 23 08:52:14 PM CEST 2025
-----------------------------------------------------------------------------
   Issue )copyright to view copyright notices.
   Issue )summary for a summary of useful system commands.
   Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------


   >> System error:
   INTERNAL-SIMPLE-PARSE-ERROR: "/home/greg//.fricas.input" is not a valid pathname on host NIL


   >> System error:
   INTERNAL-SIMPLE-ERROR: The tag |top_level| is undefined.

Error:
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by "AN ANONYMOUS FUNCTION".

INTERNAL-SIMPLE-ERROR: The tag |top_level| is undefined.

Broken at NIL.  Type :H for Help.
    1  Return to top level.
BOOT>>
============================================================

I wonder if you can reproduce also this. I have CCed gcl-devel too in case this happens on other softwares.

==============================================================

└─$ fricas
openServer result 0
                       FriCAS Computer Algebra System
               Version: FriCAS 2025-04-14 built with gcl 2.7.1
                 Timestamp: Fri May 23 09:21:37 PM CEST 2025
-----------------------------------------------------------------------------
   Issue )copyright to view copyright notices.
   Issue )summary for a summary of useful system commands.
   Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------


(1) -> 1/7

        1
   (1)  -
        7
                                                      Type: Fraction(Integer)
(2) -> sqrt %

          1
   (2)  ----
         +-+
        \|7
                                                        Type: AlgebraicNumber
(3) ->

==============================================================
But in $HOME even if FriCAS starts normally $HOME/.fricas.input is not read, it should be:

(1) -> 1/7

        1
   (1)  -
        7
                                                                                       Type: Fraction(Integer)
                                                                                    Time: 0.02 (OT) = 0.03 sec

Regards,

- Greg

Waldek Hebisch

unread,
May 23, 2025, 8:40:53 PMMay 23
to fricas...@googlegroups.com
AFAICS this only happens if you actually have '.fricas.input' in
the home directory.

There are actually two troubles:
1) errors in .fricas.input are fatal, I have now a fix for this one
2) gcl does not tolerate double slashes in filenames, so we need
to modify our paths to avoid them (this potentially affects more
things).

--
Waldek Hebisch

Waldek Hebisch

unread,
May 24, 2025, 9:30:00 AMMay 24
to fricas...@googlegroups.com
On Fri, May 23, 2025 at 09:56:29PM +0200, Grégory Vanuxem wrote:
> Hello,
>
> I don't know if you can reproduce this: if I start FriCAS from $HOME it
> starts nicely but if I start in another directory see the snippet below.
> I tried with gcl2.7.1-4 from a Debian based distribution and after with the
> official Debian sid and the same happens:
>
<snip>
>
> >> System error:
> INTERNAL-SIMPLE-PARSE-ERROR: "/home/greg//.fricas.input" is not a valid
> pathname on host NIL
>
>
> >> System error:
> INTERNAL-SIMPLE-ERROR: The tag |top_level| is undefined.

Should be fixed now.

--
Waldek Hebisch

Grégory Vanuxem

unread,
May 24, 2025, 12:15:20 PMMay 24
to fricas...@googlegroups.com, gcl-...@gnu.org
Hi Waldek,

Many thanks for this quick response and fix. Just tested on official FriCAS and the 2 problems you mentioned previously gone away.

The .fricas.input file is still not "read" but for my mid-term work it is not a big problem, my startup file is just displaying computation times and augmenting line length of output to 110. Maybe this is related to my Kali distribution on WSL2, I don't know.

The )read command is to blame on my settings:

(1) -> )sys pws

   >> System error:
   INTERNAL-SIMPLE-ERROR: The assertion !posix_spawnp(&pid, *p1, &file_actions, &attr, (void *)p1, environ) on line 65 of o/unixsys.c in function vsystem failed: No such file or directory

(1) -> )sys pwd
/home/greg
(1) -> )sys ls -l .fricas.input
-rw-r--r-- 1 greg greg 35 Feb 11 09:42 .fricas.input
(1) -> )read .fricas.input

   The file .fricas.input is needed but does not exist.

BTW great improvements have been done for gcl-2.7.1, thanks to you and Camm, it's a very good thing for me since I plan to code a wrapper in Common Lisp using my C wrapper to Julia compatible with GCL. I did one for Axiom in the past, a coding LISP game for me containing only "and", "or "and "not" keywords (no loops or conditionals). A direct wrapper to Fortran BLAS in fact. Now I have to look at documentation changes for the GCL-2.7 series FFI.

- Greg

PS / I Cc-ed to gcl-devel 

--
You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/fricas-devel/aDHJ1HqJwLlykCMl%40fricas.org.

Waldek Hebisch

unread,
May 24, 2025, 12:41:43 PMMay 24
to fricas...@googlegroups.com, gcl-...@gnu.org, ca...@maguirefamily.org
On Sat, May 24, 2025 at 06:14:40PM +0200, Grégory Vanuxem wrote:
> Hi Waldek,
>
> Many thanks for this quick response and fix. Just tested on official FriCAS
> and the 2 problems you mentioned previously gone away.
>
> The .fricas.input file is still not "read" but for my mid-term work it is
> not a big problem, my startup file is just displaying computation times and
> augmenting line length of output to 110. Maybe this is related to my Kali
> distribution on WSL2, I don't know.
>
> The )read command is to blame on my settings:
>
> (1) -> )sys pws
>
> >> System error:
> INTERNAL-SIMPLE-ERROR: The assertion !posix_spawnp(&pid, *p1,
> &file_actions, &attr, (void *)p1, environ) on line 65 of o/unixsys.c in
> function vsystem failed: No such file or directory
>
> (1) -> )sys pwd
> /home/greg
> (1) -> )sys ls -l .fricas.input
> -rw-r--r-- 1 greg greg 35 Feb 11 09:42 .fricas.input
> (1) -> )read .fricas.input
>
> The file .fricas.input is needed but does not exist.

AFAICS the problem is due to PATHNAME-TYPE in gcl:

)lisp (PATHNAME-TYPE "/home/hebisch/.fricas.input")

Value = "fricas.input"
(1) ->

All other Lisp implementations that we use return "input".

--
Waldek Hebisch

Grégory Vanuxem

unread,
May 25, 2025, 8:53:30 AMMay 25
to fricas...@googlegroups.com, gcl-...@gnu.org, Camm Maguire
Hello, 

Yes and this is required by CLHS from what I have read:


It's a good thing to know for Camm since apparently he is working on several things and will add some suggestions for macOS from Chun Tian from what I have understood so I think it will fix that. 

- Greg

Camm Maguire

unread,
May 29, 2025, 4:23:52 PMMay 29
to Grégory Vanuxem, ca...@maguirefamily.org, fricas...@googlegroups.com, gcl-...@gnu.org
Greetings!

Grégory Vanuxem <g.va...@gmail.com> writes:

> Hi Waldek,
>
> Many thanks for this quick response and fix. Just tested on official FriCAS and the 2 problems you mentioned previously gone away.
>
> The .fricas.input file is still not "read" but for my mid-term work it is not a big problem, my startup file is just displaying computation times and augmenting line
> length of output to 110. Maybe this is related to my Kali distribution on WSL2, I don't know.
>
> The )read command is to blame on my settings:
>
> (1) -> )sys pws
>
> >> System error:
> INTERNAL-SIMPLE-ERROR: The assertion !posix_spawnp(&pid, *p1, &file_actions, &attr, (void *)p1, environ) on line 65 of o/unixsys.c in function vsystem failed:
> No such file or directory
>
> (1) -> )sys pwd
> /home/greg
> (1) -> )sys ls -l .fricas.input
> -rw-r--r-- 1 greg greg 35 Feb 11 09:42 .fricas.input
> (1) -> )read .fricas.input
>
> The file .fricas.input is needed but does not exist.
>
> BTW great improvements have been done for gcl-2.7.1, thanks to you and
> Camm, it's a very good thing for me since I plan to code a wrapper in
> Common Lisp using my C wrapper to Julia compatible with GCL. I did one
> for Axiom in the past, a coding LISP game for me containing only
> "and", "or "and "not" keywords (no

Most happy to see a satisfied customer!

> loops or conditionals). A direct wrapper to Fortran BLAS in fact. Now
> I have to look at documentation changes for the GCL-2.7 series FFI.
>

I turn your attention to defdlfun. In 2.7.x we can establish persistent
(across image saves) bindings to new external shared libraries on the
fly, with the call overhead being a single pointer dereference:


>(describe 'defdlfun)

DEFDLFUN - internal symbol in COMMON-LISP-USER package
From ((DEFDLFUN . External Shared Libraries) gcl-si.info):

-- Macro: DEFDLFUN
Package:SYSTEM

Syntax:
(compile (DEFDLFUN {RETURN NAME &optional LIBNAME) ARGS*))

GCL specific: Produces an entry function to function NAME in
external shared library LIBNAME with the specified args/return
signature. This function must be compiled to run. When inlined,
the function call collapses to a single reference to a pointer
which is automatically updated to the location of the external
function at image startup. The connection to the external library
is persistent across image saves and re-executions. The RETURN and
ARGS specifiers are keywords from the following list corresponding
to the accompanying C programming types:

:char :short :int :long :float :double

Unsigned versions available are:

:uchar :ushort :uint

Complex float and complex double types can be access via:

:fcomplex :dcomples

Pointers to types available are

:void* :char* :long* :float* :double*

Example usage:




GCL (GNU Common Lisp) 2.7.0 Thu Oct 26 12:00:01 PM EDT 2023 CLtL1 git: Version_2_7_0pre38
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License: GPL due to GPL'ed components: (XGCL READLINE UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

>(do-symbols (s :lib) (print s))

LIB:|libm|
LIB:|libc|
NIL

>(compile (si::defdlfun (:double "cblas_ddot" "libblas.so") :uint :double* :uint :double* :uint))

;; Compiling /tmp/gazonk_653784_0.lsp.
;; End of Pass 1.
;; End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
;; Finished compiling /tmp/gazonk_653784_0.o.
;; Loading #P"/tmp/gazonk_653784_0.o"
;; start address for /tmp/gazonk_653784_0.o 0x2700860
;; Finished loading #P"/tmp/gazonk_653784_0.o"
#<function 0000000001a4a860>
NIL
NIL

>(do-symbols (s :lib) (print s))

LIB:|libblas|
LIB:|libm|
LIB:|libc|
NIL

>(do-symbols (s 'lib::|libblas|) (unless (find-symbol (symbol-name s) :user) (print s)))

|libblas|:|cblas_ddot|
NIL
NIL

>(setq a (make-array 3 :element-type 'long-float) b (make-array 3 :element-type 'long-float))

#(0.0 0.0 0.0)

>(setf (aref a 1) 1.2 (aref b 1) 2.3)

2.3

>(|libblas|:|cblas_ddot| 3 a 1 b 1)

2.76

>(compile (defun foo (a b) (declare ((vector long-float) a b)) (|libblas|:|cblas_ddot| (length a) a 1 b 1)))

;; Compiling /tmp/gazonk_653784_0.lsp.
;; End of Pass 1.
;; End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
;; Finished compiling /tmp/gazonk_653784_0.o.
;; Loading #P"/tmp/gazonk_653784_0.o"
;; start address for /tmp/gazonk_653784_0.o 0x2715050
;; Finished loading #P"/tmp/gazonk_653784_0.o"
#<function 0000000001a62140>
NIL
NIL

>(compile (defun bar (a b) (declare (inline |libblas|:|cblas_ddot|) ((vector long-float) a b)) (|libblas|:|cblas_ddot| (length a) a 1 b 1)))

;; Compiling /tmp/gazonk_653784_0.lsp.
;; End of Pass 1.
;; End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
;; Finished compiling /tmp/gazonk_653784_0.o.
;; Loading #P"/tmp/gazonk_653784_0.o"
;; start address for /tmp/gazonk_653784_0.o 0x2729570
;; Finished loading #P"/tmp/gazonk_653784_0.o"
#<function 0000000001a62740>
NIL
NIL

>(foo a b)

2.76

>(bar a b)

2.76

>(setq compiler::*disassemble-objdump* nil)

NIL

>(disassemble '|libblas|:|cblas_ddot|)

;; Compiling /tmp/gazonk_653784_0.lsp.
;; End of Pass 1.
;; End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
;; Finished compiling /tmp/gazonk_653784_0.o.

#include "gazonk_653784_0.h"
void init_code(){do_init((void *)VV);}
/* local entry for function libblas::cblas_ddot */

static object LI1__cblas_ddot___gazonk_653784_0(fixnum V6,object V7,fixnum V8,object V9,fixnum V10)
{ VMB1 VMS1 VMV1
if(!(((char)tp0(make_fixnum(V6)))==(1))){
goto T8;
}
if(!((0)<=(V6))){
goto T13;
}
if(!((V6)<=((fixnum)4294967295))){
goto T11;
}
goto T12;

goto T13;
T13:;
goto T11;

goto T12;
T12:;
goto T7;

goto T11;
T11:;
goto T6;

goto T8;
T8:;
goto T6;

goto T7;
T7:;
goto T5;

goto T6;
T6:;
goto T3;

goto T5;
T5:;
goto T2;

goto T3;
T3:;
V11= CMPmake_fixnum(V6);
V6= fixint((fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object )(*LnkLI2)(((object)VV[1]),(V11),((object)VV[2]),Cnil)));
goto T2;
T2:;
switch(tp6(V7)){
case 428:
goto T27;
T27:;
case 492:
goto T28;
T28:;
goto T25;

default:
goto T29;
T29:;
goto T24;

goto T24;
}
goto T24;

goto T25;
T25:;
goto T23;

goto T24;
T24:;
goto T22;

goto T23;
T23:;
goto T21;

goto T22;
T22:;
goto T19;

goto T21;
T21:;
goto T18;

goto T19;
T19:;
V7= (fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object )(*LnkLI2)(((object)VV[3]),(V7),((object)VV[4]),Cnil));
goto T18;
T18:;
if(!(((char)tp0(make_fixnum(V8)))==(1))){
goto T39;
}
if(!((0)<=(V8))){
goto T44;
}
if(!((V8)<=((fixnum)4294967295))){
goto T42;
}
goto T43;

goto T44;
T44:;
goto T42;

goto T43;
T43:;
goto T38;

goto T42;
T42:;
goto T37;

goto T39;
T39:;
goto T37;

goto T38;
T38:;
goto T36;

goto T37;
T37:;
goto T34;

goto T36;
T36:;
goto T33;

goto T34;
T34:;
V12= CMPmake_fixnum(V8);
V8= fixint((fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object )(*LnkLI2)(((object)VV[5]),(V12),((object)VV[2]),Cnil)));
goto T33;
T33:;
switch(tp6(V9)){
case 428:
goto T58;
T58:;
case 492:
goto T59;
T59:;
goto T56;

default:
goto T60;
T60:;
goto T55;

goto T55;
}
goto T55;

goto T56;
T56:;
goto T54;

goto T55;
T55:;
goto T53;

goto T54;
T54:;
goto T52;

goto T53;
T53:;
goto T50;

goto T52;
T52:;
goto T49;

goto T50;
T50:;
V9= (fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object )(*LnkLI2)(((object)VV[6]),(V9),((object)VV[4]),Cnil));
goto T49;
T49:;
if(!(((char)tp0(make_fixnum(V10)))==(1))){
goto T70;
}
if(!((0)<=(V10))){
goto T75;
}
if(!((V10)<=((fixnum)4294967295))){
goto T73;
}
goto T74;

goto T75;
T75:;
goto T73;

goto T74;
T74:;
goto T69;

goto T73;
T73:;
goto T68;

goto T70;
T70:;
goto T68;

goto T69;
T69:;
goto T67;

goto T68;
T68:;
goto T65;

goto T67;
T67:;
goto T64;

goto T65;
T65:;
V13= CMPmake_fixnum(V10);
V10= fixint((fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object )(*LnkLI2)(((object)VV[7]),(V13),((object)VV[2]),Cnil)));
goto T64;
T64:;
{object V14 = make_longfloat(((double(*)(uint,double*,uint,double*,uint))(dlcblas_ddot))((uint)V6,(double*)V7->v.v_self,(uint)V8,(double*)V9->v.v_self,(uint)V10));
VMR1(V14);}
}
static object LnkTLI2(object first,...){object V1;va_list ap;va_start(ap,first);V1=(object )call_proc_new(((object)VV[0]),0,262147,(void **)(void *)&LnkLI2,0,first,ap);va_end(ap);return V1;} /* SYSTEM::CHECK-TYPE-SYMBOL */
(9 (MAPC 'EVAL *COMPILER-COMPILE-DATA*))
static object LI1__cblas_ddot___gazonk_653784_0(fixnum V6,object V7,fixnum V8,object V9,fixnum V10)
;
static void *dlcblas_ddot;
#define VMB1 object V13 ,V12 ,V11;
#define VMS1
#define VMV1
#define VMRV1(a_,b_) return((object )a_);
#define VMR1(a_) VMRV1(a_,0);
#define VM1 0
static void * VVi[9]={
#define Cdata VV[8]
(void *)(&dlcblas_ddot),
(void *)(LI1__cblas_ddot___gazonk_653784_0)
};
#define VV (VVi)
static object LnkTLI2(object,...);
static object (*LnkLI2)() = (object (*)()) LnkTLI2;
NIL

>(disassemble 'foo)

;; Compiling /tmp/gazonk_653784_0.lsp.
;; End of Pass 1.
;; End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
;; Finished compiling /tmp/gazonk_653784_0.o.

#include "gazonk_653784_0.h"
void init_code(){do_init((void *)VV);}
/* local entry for function COMMON-LISP-USER::FOO */

static object LI1__FOO___gazonk_653784_0(object V3,object V4)
{ VMB1 VMS1 VMV1
if(!(((char)((fixnum)((uchar*)((fixnum)V3))[(fixnum)2]&(fixnum)1))==(0))){
goto T5;
}
goto T2;

goto T5;
T5:;
V5= ((fixnum)((uint*)((fixnum)V3))[(fixnum)4]&268435455);
goto T1;

goto T2;
T2:;
V5= (((fixnum)((uint*)((fixnum)V3))[(fixnum)1]>>(fixnum)3)&268435455);
goto T1;
T1:;
{object V6 = (/* libblas::cblas_ddot */(object )(*LnkLI2)(V5,(V3),(fixnum)1,(V4),(fixnum)1));
VMR1(V6);}
}
static object LnkTLI2(object first,...){object V1;va_list ap;va_start(ap,first);V1=(object )call_proc_new(((object)VV[0]),0,5,(void **)(void *)&LnkLI2,1092,first,ap);va_end(ap);return V1;} /* libblas::cblas_ddot */
(2 (MAPC 'EVAL *COMPILER-COMPILE-DATA*))
static object LI1__FOO___gazonk_653784_0(object V3,object V4)
;
#define VMB1 fixnum V5;
#define VMS1
#define VMV1
#define VMRV1(a_,b_) return((object )a_);
#define VMR1(a_) VMRV1(a_,0);
#define VM1 0
static void * VVi[2]={
#define Cdata VV[1]
(void *)(LI1__FOO___gazonk_653784_0)
};
#define VV (VVi)
static object LnkTLI2(object,...);
static object (*LnkLI2)() = (object (*)()) LnkTLI2;
NIL

>(disassemble 'bar)

;; Compiling /tmp/gazonk_653784_0.lsp.
;; End of Pass 1.
;; End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
;; Finished compiling /tmp/gazonk_653784_0.o.

#include "gazonk_653784_0.h"
void init_code(){do_init((void *)VV);}
/* local entry for function COMMON-LISP-USER::BAR */

static object LI1__BAR___gazonk_653784_0(object V3,object V4)
{ VMB1 VMS1 VMV1
{fixnum V5;
if(!(((char)((fixnum)((uchar*)((fixnum)V3))[(fixnum)2]&(fixnum)1))==(0))){
goto T5;
}
goto T2;

goto T5;
T5:;
V5= ((fixnum)((uint*)((fixnum)V3))[(fixnum)4]&268435455);
goto T1;

goto T2;
T2:;
V5= (((fixnum)((uint*)((fixnum)V3))[(fixnum)1]>>(fixnum)3)&268435455);
goto T1;
T1:;
{object V6 = make_longfloat(((double(*)(uint,double*,uint,double*,uint))(dlcblas_ddot))((uint)V5,(double*)V3->v.v_self,(uint)1,(double*)V4->v.v_self,(uint)1));
VMR1(V6);}}
}
(2 (MAPC 'EVAL *COMPILER-COMPILE-DATA*))
static object LI1__BAR___gazonk_653784_0(object V3,object V4)
;
static void *dlcblas_ddot;
#define VMB1
#define VMS1
#define VMV1
#define VMRV1(a_,b_) return((object )a_);
#define VMR1(a_) VMRV1(a_,0);
#define VM1 0
static void * VVi[2]={
#define Cdata VV[1]
(void *)(&dlcblas_ddot),
(void *)(LI1__BAR___gazonk_653784_0)
};
#define VV (VVi)
NIL

>(si::save-system "ff")
$ ./ff
GCL (GNU Common Lisp) 2.7.0 Thu Oct 26 12:00:01 PM EDT 2023 CLtL1 git: Version_2_7_0pre38
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License: GPL due to GPL'ed components: (XGCL READLINE UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

>(foo a b)

2.76

>(bar a b)

2.76

>


Take care,


>

> - Greg
>
> PS / I Cc-ed to gcl-devel
>
> Le sam. 24 mai 2025 à 15:30, Waldek Hebisch <de...@fricas.org> a écrit :
>
> On Fri, May 23, 2025 at 09:56:29PM +0200, Grégory Vanuxem wrote:
> > Hello,
> >
> > I don't know if you can reproduce this: if I start FriCAS from $HOME it
> > starts nicely but if I start in another directory see the snippet below.
> > I tried with gcl2.7.1-4 from a Debian based distribution and after with the
> > official Debian sid and the same happens:
> >
> <snip>
> >
> > >> System error:
> > INTERNAL-SIMPLE-PARSE-ERROR: "/home/greg//.fricas.input" is not a valid
> > pathname on host NIL
> >
> >
> > >> System error:
> > INTERNAL-SIMPLE-ERROR: The tag |top_level| is undefined.
>
> Should be fixed now.
>
> --
> Waldek Hebisch
>
> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/fricas-devel/aDHJ1HqJwLlykCMl%40fricas.org.

--
Camm Maguire ca...@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens." -- Baha'u'llah

Grégory Vanuxem

unread,
May 30, 2025, 11:09:29 AMMay 30
to Camm Maguire, fricas...@googlegroups.com, gcl-...@gnu.org
Hello Camm, *,

That's excellent, that's exactly what I was looking for. Data types and the GCL FFI access to a shared library. I have to look deeper since I load libjulia.so and initialize Julia the first time I use it. And only one time the library loading:

(defun init-julia (wrapper-lib)
    (if (ignore-errors (|quiet_load_alien| wrapper-lib) t)
        (let ((system-julia-name  #+:WIN32 "libjulia.dll"
                    #+:DARWIN "libjulia.dylib"
                    #-(or :WIN32 :DARWIN) "libjulia.so")
                (bundled-julia-name #+:WIN32 "/lib/libjulia.dll"
                    #+:DARWIN "/lib/libjulia.dylib"
                    #-(or :WIN32 :DARWIN) "/lib/libjulia.so"))
            (if (ignore-errors (|quiet_load_alien| system-julia-name) t)
                t
                (and bundled-julia-name (ignore-errors (|quiet_load_alien|
                    (BOOT::make-absolute-filename bundled-julia-name)) t))))))
After loading the library, the C code call Julia for its initialization, the GC and several other stuff.

I think mimicking the libspad.so support will be a good start.

However, I noticed that about utf-8 support:

In SBCL or Clozure CL, the later needs a special routine to handle utf-8 string returned from the C wrapper:

(1) -> #"Hello world, Καλημέρα κόσμε, コンニチハ"

   (1)  34

Whereas in gcl27, 2.7.1-7 (the Debian sid package):

(2) -> #"Hello world, Καλημέρα κόσμε, コンニチハ"

   (2)  59

# is the operation that returns the number of elements in an Aggregate.

So I think handling strings returned by Julia, I use them sometimes for formatting purposes or regular expressions related operation principally, will probably become difficult with gcl27, they are in utf-8. For BLAS and LAPACK and purely numerical functions I don't think it will it be a problem but for returned strings (char *) I wonder if there is a special function to let GCL "knows" it is in utf-8 and handle them correctly.

BTW many many thanks, it's a good headway for me, it will prevent me a lot of digging in the GCL internals.

- Greg

PS: attached is a file I regularly use to check utf-8 support.

Le jeu. 29 mai 2025, 22:28, Camm Maguire <ca...@maguirefamily.org> a écrit :
Greetings, and thanks again!

From my reading of the spec GCL's parsing of the pathname-type is
compliant.  It also passes Paul Dietz' test suite.  If this is causing
difficulties it would be great if someone could post the failing lisp
code.

There are advantages to not allowing '.' in pathname-name.

Take care,
utf-8-demo.txt

Waldek Hebisch

unread,
May 30, 2025, 2:35:21 PMMay 30
to fricas...@googlegroups.com, Camm Maguire, gcl-...@gnu.org
On Fri, May 30, 2025 at 05:08:21PM +0200, Grégory Vanuxem wrote:
>
> However, I noticed that about utf-8 support:
>
> In SBCL or Clozure CL, the later needs a special routine to handle utf-8
> string returned from the C wrapper:
>
> (1) -> #"Hello world, Καλημέρα κόσμε, コンニチハ"
>
> (1) 34
>
> Whereas in gcl27, 2.7.1-7 (the Debian sid package):
>
> (2) -> #"Hello world, Καλημέρα κόσμε, コンニチハ"
>
> (2) 59
>
> # is the operation that returns the number of elements in an Aggregate.
>
> So I think handling strings returned by Julia, I use them sometimes for
> formatting purposes or regular expressions related operation principally,
> will probably become difficult with gcl27, they are in utf-8. For BLAS and
> LAPACK and purely numerical functions I don't think it will it be a problem
> but for returned strings (char *) I wonder if there is a special function
> to let GCL "knows" it is in utf-8 and handle them correctly.
>

Nice things about utf-8 is that in most cases code expecting
8-bit characters will handle them correctly, so the only
thing which needs to know about utf-8 is input and display
subsystem. In particular, for regexes, in most cases you
should be able to pass utf-8 strings to 8-bit regex engine
and obtain correct result.

AFAICS number 34 above is useless for formatting purposes.
59 looks like correct number of bytes, which is crucial for
manipulating on the string using low-level operations.
For screen positioning you need number of positions on the
screen, which seem to be 39. To know this you need to
know a lot of specific thing, like which characters are
double width, which are combining (so does not need their
own position).

BTW: Clef has handle display issues, so I wrote a few support
routines for handling utf-8 (see 'dist_left' and 'dist_right' in
'src/clef/e_buf.c'). They use Clef representation for buffer
but idea should be clear.

--
Waldek Hebisch

Camm Maguire

unread,
May 31, 2025, 5:56:59 AMMay 31
to Grégory Vanuxem, ca...@maguirefamily.org, fricas...@googlegroups.com, gcl-...@gnu.org
Greetings, and thanks again!

From my reading of the spec GCL's parsing of the pathname-type is
compliant. It also passes Paul Dietz' test suite. If this is causing
difficulties it would be great if someone could post the failing lisp
code.

There are advantages to not allowing '.' in pathname-name.

Take care,

Grégory Vanuxem <g.va...@gmail.com> writes:

Waldek Hebisch

unread,
May 31, 2025, 7:34:51 AMMay 31
to fricas...@googlegroups.com, ca...@maguirefamily.org
On Thu, May 29, 2025 at 04:28:45PM -0400, Camm Maguire wrote:
> Greetings, and thanks again!
>
> >From my reading of the spec GCL's parsing of the pathname-type is
> compliant. It also passes Paul Dietz' test suite.

Well, CL spec require almost nothing. Basicaly the only requirement
is that it returns "extention" of the name.

> If this is causing
> difficulties it would be great if someone could post the failing lisp
> code.

Below is the trouble:

> Grégory Vanuxem <g.va...@gmail.com> writes:
>
> > Le sam. 24 mai 2025, 18:41, Waldek Hebisch <de...@fricas.org> a écrit :
> >
> > On Sat, May 24, 2025 at 06:14:40PM +0200, Grégory Vanuxem wrote:

> > > (1) -> )read .fricas.input
> > >
> > > The file .fricas.input is needed but does not exist.
> >
> > AFAICS the problem is due to PATHNAME-TYPE in gcl:
> >
> > )lisp (PATHNAME-TYPE "/home/hebisch/.fricas.input")
> >
> > Value = "fricas.input"
> > (1) ->
> >
> > All other Lisp implementations that we use return "input".

FriCAS only reads files with known extention, in this case FriCAS
expect extention "input", but gcl PATHNAME-TYPE returns
"fricas.input" which does not match.

This is temporary trouble, in the future I plan to rework FriCAS
code to avoid CL pathname functions, in particular the above
will use string comparison with a substring.

--
Waldek Hebisch

Camm Maguire

unread,
May 31, 2025, 8:38:42 AMMay 31
to Waldek Hebisch, ca...@maguirefamily.org, fricas...@googlegroups.com, gcl-...@gnu.org
Greetings!

Waldek Hebisch <de...@fricas.org> writes:

> On Fri, May 30, 2025 at 05:08:21PM +0200, Grégory Vanuxem wrote:
>>
>> However, I noticed that about utf-8 support:
>>
>> In SBCL or Clozure CL, the later needs a special routine to handle utf-8
>> string returned from the C wrapper:
>>
>> (1) -> #"Hello world, Καλημέρα κόσμε, コンニチハ"
>>
>> (1) 34
>>
>> Whereas in gcl27, 2.7.1-7 (the Debian sid package):
>>
>> (2) -> #"Hello world, Καλημέρα κόσμε, コンニチハ"
>>
>> (2) 59
>>
>> # is the operation that returns the number of elements in an Aggregate.
>>
>> So I think handling strings returned by Julia, I use them sometimes for
>> formatting purposes or regular expressions related operation principally,
>> will probably become difficult with gcl27, they are in utf-8. For BLAS and
>> LAPACK and purely numerical functions I don't think it will it be a problem
>> but for returned strings (char *) I wonder if there is a special function
>> to let GCL "knows" it is in utf-8 and handle them correctly.
>>
>
> Nice things about utf-8 is that in most cases code expecting
> 8-bit characters will handle them correctly, so the only
> thing which needs to know about utf-8 is input and display
> subsystem. In particular, for regexes, in most cases you
> should be able to pass utf-8 strings to 8-bit regex engine
> and obtain correct result.
>

Yes this has essentially allowed GCL to stick with the traditional
character definition to this point. Its just character counting that's
missing.

> AFAICS number 34 above is useless for formatting purposes.
> 59 looks like correct number of bytes, which is crucial for
> manipulating on the string using low-level operations.
> For screen positioning you need number of positions on the
> screen, which seem to be 39. To know this you need to
> know a lot of specific thing, like which characters are
> double width, which are combining (so does not need their
> own position).
>

Interesting point. So its just the international user who wants (aref
utf-string 23).

Nonetheless GCL will eventually support this. Current thoughts are
along the lines of emacs' implementation. There was a discussion of
this on gcl-devel not too long ago.

> BTW: Clef has handle display issues, so I wrote a few support
> routines for handling utf-8 (see 'dist_left' and 'dist_right' in
> 'src/clef/e_buf.c'). They use Clef representation for buffer
> but idea should be clear.

Will check it out -- thanks!

Take care,

>
> --
> Waldek Hebisch

Grégory Vanuxem

unread,
Jun 5, 2025, 3:07:13 AMJun 5
to gcl-...@gnu.org, fricas...@googlegroups.com
Hello Camm, *,

I am testing your instructions to load and use an external library dynamically linked and I have a couple of issues.
First, I am unable to load libjula.so because of an undefined symbol:

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

>(si:mdlsym "jl_init" "libjulia.so")


Error:
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by SYSTEM:MDLSYM.

Condition in SYSTEM:MDLSYM [or a callee]: INTERNAL-SIMPLE-ERROR: dlopen failure on "libjulia.so": "/usr/local/lib/libjulia.so: undefined symbol: jl_pgcstack_static_semaphore"

Broken at SYSTEM:MDLSYM.  Type :H for Help.

    1  Return to top level.

This is the same with your macro below. This does not happen with SBCL, Clozure CL or pure C (just tested). I looked at the Julia code and it almost not used; the only pieces of code (MIT licence) are:

In a header file:
#if !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_)
#define JULIA_DEFINE_FAST_TLS                                                                   \
static __attribute__((tls_model("local-exec"))) __thread jl_gcframe_t **jl_pgcstack_localexec;  \
JL_DLLEXPORT _Atomic(char) jl_pgcstack_static_semaphore;                                        \
JL_DLLEXPORT jl_gcframe_t **jl_get_pgcstack_static(void)                                        \
{                                                                                               \
    return jl_pgcstack_localexec;                                                               \
}                                                                                               \
JL_DLLEXPORT jl_gcframe_t ***jl_pgcstack_addr_static(void)                                      \
{                                                                                               \
    return &jl_pgcstack_localexec;                                                              \
}
#else
#define JULIA_DEFINE_FAST_TLS
#endif

and in a C file:

#if !defined(_OS_WINDOWS_) && !defined(_OS_DARWIN_)
    void (*jl_pgcstack_setkey)(void*, void*(*)(void)) = lookup_symbol(libjulia_internal, "jl_pgcstack_setkey");
    if (jl_pgcstack_setkey == NULL) {
        jl_loader_print_stderr("ERROR: Cannot find jl_pgcstack_setkey() function within libjulia-internal!\n");
        exit(1);
    }
    void *fptr = lookup_symbol(RTLD_DEFAULT, "jl_get_pgcstack_static");
    void *(*key)(void) = lookup_symbol(RTLD_DEFAULT, "jl_pgcstack_addr_static");
    _Atomic(char) *semaphore = lookup_symbol(RTLD_DEFAULT, "jl_pgcstack_static_semaphore");
    if (fptr != NULL && key != NULL && semaphore != NULL) {
        char already_used = 0;
        atomic_compare_exchange_strong(semaphore, &already_used, 1);
        if (already_used == 0) // RMW succeeded - we have exclusive access
            jl_pgcstack_setkey(fptr, key);
    }
#endif

So, since it seems to me it is just an optimization, for experimental purpose, I removed those pieces of code and rebuilt Julia and was able to load libjulia. I still wonder why GCL, contrary to the mentioned CL implementations, encounters the error above: undefined symbol.

The second issue is related to the macro you mentioned below, I cannot give a path to the library at run time:

(si::defdlfun (:void "jl_init" (|make_absolute_filename| "/lib/julia_wrap.so")) :void)

julia_wrap.so is in a FriCAS lib directory and not in the ld library path so I need to give the full path. Here '(|make_absolute_filename| "/lib/julia_wrap.so")' is not executed so GCLcomplains about the fact it's not of type STRING. Accessory I do not know if ':void' instead of ':void*' can be used. I tested the two.

Do you think I need to use more low-level operations with lib-name, mdl etc. the one used above in GCL, etc. and in fact, I do not know how?

julia_wrap.so is a wrapper linked against libjulia, and dload-ed by FriCAS, it's necessary, see some examples here eventually:

Maybe later I will ask some other questions about the GCL garbage collector to know if there is a "terminate" hook in it, I need it, I have two interface types in my Julia interface one where Julia operates directly on CL arrays, and another one where datas are in the Julia process stored in a hashed dictionary, so when GCL is GC-ing CL variables (a very simple class object in my interface that contains the key) I need to inform the Julia GC it can also GC them, i.e. delete them from the dictionary.

Hoping I am relatively clear, regards,

- Greg




Reply all
Reply to author
Forward
0 new messages