Re: Embedding wishlist

Bernd Paysan <[email protected]> Tue, 07 Feb 2023 22:25:41 +0100
Newsgroups gmane.comp.lang.forth.gforth
Message-ID <8177827.T7Z3S40VBb@liubei>
Am Dienstag, 7. Februar 2023, 14:17:55 CET schrieb Anton Ertl:
> On Mon, Feb 06, 2023 at 07:09:49PM -0600, Ulf Herrman wrote:
> > I'm considering embedding gforth in a C program that uses an event
> > loop. I need to be able to suspend the current forth task and return to
> > C. I *think* the right primitive for this is (bye), unless I'm
> > mistaken. But once it's been suspended, I'd like to be able to resume
> > it. This could be done by having a forth wrapper word around (bye) which
> > will push the succeeding ip onto the return stack, and then executing
> > EXIT when it's time to resume. But I'd like it if I could resume
> > directly from what invoked (bye). I see that there's a saved_ip, but is
> > it current after returning from gforth_engine? I don't see a place where
> > it would be kept up to date... would (bye) have to be modified to store
> > it?
> 
> saved_ip is kept current in the engine gforth (through the macro NAME
> called at the start of every primitive), but not in gforth-fast.  It's
> there in order to report the primitive that caused an exception when
> producing a backtrace.  If you want to go through (bye), the idea of
> wrapping it in a colon definition, and then continuing at a ;S (the
> primitive for EXIT) sounds good.
> 
> For resuming you also need to save the stack pointers and restore them
> on returning.

That's not a problem, (BYE) does that — in the stackpointers format that is 
passed to engine().  That is done so that you can call different entry points 
into Forth with the same stackpointers argument, and pass data from one call 
to the next within Forth, or to use the stack pointer access macros to get the 
data into C.  The IP is not saved, because in the usual Gforth environment, 
there is no need for that.

To save the IP, the Forth side definition would be a simple high level 
definition:

: pause ( -- ) 0 (bye) ;

(or use a different return value to indicate continue, as 0 (bye) would be the 
normal exit), and in the C code that calls gforth_engine(), you use 
*gforth_RP++ to get the return address (the next word after calling PAUSE).  
This should be good enough.

> You can call a C function from within Gforth using the C interface.
> If you can arrange your C program such that you can call the C parts
> as a function rather than as a coroutine, that would be the way to go.
> 
> Otherwise you can
> 
> a) look for a C library for coroutining or somesuch, and call that, or

The way Gforth as library is used on Android is to create a new thread for 
Gforth, and run it there.

> b) pursue the approach of calling (BYE), saving and then restoring the
>    stack pointers and IP there.
> 
> c) you could also try the approach of calling (BYE), but somehow
>    arrange to get the stack pointers saved in a C structure
>    "stackpointers" (possibly by calling a dummy C functionthat you then pass
> to gforth_engine for resuming.
> > Also, it would be nice if gforth could be initialized without having to
> > install signal handlers.

A number of functions simply depend on those signal handlers.  But you can 
take a copy gforth_init() and delete install_signal_handlers() and see how far 
you get.

> > It would also be nice if gforth_stacks could be instructed to leave out
> > the guard pages and page-alignment requirements. This would allow for
> > tasks that are known to only require small stacks to be very compact. At
> > present this isn't even configurable at compile-time: totalsize is
> > always at least 10 pages large.
> 
> It seems that you want to replace some parts of the Gforth
> initialization with your own.  With the development Gforth this is
> entirely possible and I think you do not even need a change to Gforth
> source code.  You just need to do your own main (which you will do
> anyway), link with engine/libgforth.la (or engine/libgforth-fast.la
> etc.), perform your initialization and eventually call
> gforth-engine().

Indeed.  Add an argument for how large the user area should be, because that 
is another page now, and 256/512 bytes (32/64 bits) are sufficient for the 
standard Gforth image.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
net2o id: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ*
https://net2o.de/
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEERJ1NDqPQRwYnwBjr9y2Uk5MtoGcFAmPiwdUACgkQ9y2Uk5Mt
oGf1CQ/9GpPLT14e5/tSe8HKxSFyJ5w15pNqsNvVeuLprIrY5oGtK9QsW3BvALdL
zzhb881VmvuFvXILNX1Rp8YoxoC8oXcvV+8Iwhcc/tYcCOYU5plO5jl1mURGEnuC
vnIUEkFLqVuzVqhaiJ6MSU0hF0PHOY2Ng8/Jh0z41DRRE4Xv8T+tmEK6BS1RYrgF
xN+L7WTqkyIRgEzUR1euYyo09syBo+P/RCEezLzXS9tY/RcEXHZKfd5onPAT7Xwd
GGTnButnz0jE72oAkAfBxPm82lN2g/oCzSAX80LoQnXJfD8Fo7kTpMU6XkJaBBw8
xCnvTSLVxuTWtuhoT9a/H0Qp77hsgkSEO9lbONZaxDhxsoQAQ0MN7tpx6MlTiDpe
6u5HtwbGI86tDkrHdYQYk4rg3SHxXpQvONfs3RAWxGWxqCoC8BQ7ECiBKsJsqWcj
lOpMwDqanzbSopeA1tyvkmPJLIkrBvccychc8ff1CXH+oo/Bjn9t84S0LNLEdVSI
libbcKKc5IrSX5CAqZvZw5hLQtaPi14hP6Wm2wHIYkaio68GzrNgZKGn9vjDJFXd
4Hmp7Fd1qIFudx6EpMIFX0Uz8P21w4p/8IsYDalQjf1cDXfB0eZLdwxeAubXZtJ2
qwDDAQeh2pvG6F0cc3MzzJT3Juk7eiF0mU40e1I7qK49huywpL0=
=lzXX
-----END PGP SIGNATURE-----