The code described here is specific to VFX Forth for Linux. Do not rely on any of the words documented here being present in any other VFX Forth implementation.
The VFX Forth console supports a number of command shell operations.
The words in this section are used to build the tools.
: csplit \ caddr len char -- raddr rlen laddr llen
Extract a substring at the start of caddr/len, returning
the string raddr/rlen which includes char (if found) and
the string laddr/llen which contains the text to left of char.
If the string does not contain the character, raddr is
caddr+len and rlen=0.
: xtype \ caddr len --
As TYPE, but LF characters cause a CR. This factor
copes with some user-written generic I/O devices that do not
implement TYPE correctly.
: >pShell \ z$ -- ior
Execute the given zero-terminated string as a shell command,
write any output to the current output device,
and return the result code from the popen() call.
This word provides consistent action regardless of whether
operation is running in a console or is detached.
This is the default action of (>xShell) below.
defer >xShell \ z$ -- ior
Execute the given zero-terminated string as a shell command,
and return the result code from the relevant system call
such that zero=success. Most words that cause shell actions
use >xShell as a primitive.
To use a raw system call instead as the action use:
assign ssystem to-do >xShell
: (>Shell) \ z$ -- ior
Execute the given zero-terminated string as a shell command,
and return the result code from >xShell above.
: >system \ z$ -- ior
Execute the given zero-terminated string as a shell command
using the system() API call, and return the result code.
: >Shell \ z$ --
Execute the given zero-terminated string as a shell command using
(>Shell) above.
Output from the command is written to the current output device.
: ShellCmd \ caddr len --
Execute the given caddr/len string as a shell command.
: ShellLine \ caddr len --
Execute the given counted string as a shell command. Before
execution, the remainder of the input line is added to the
given string.
: $shell \ cmd$ tail$ --
Take the command and tail counted strings and execute them as
a shell command using system().
: $linux \ cmd$ tail$ --
A synonym for $shell.
: sh \ -- ; "command"
Ask the host operating system to execute the supplied command line.
: ls \ -- ; "[spec]"
Display file information based on the supplied specification.
: dir \ -- ; "[spec]"
Display file information based on the supplied specification.
As LS but with colouring.
: makedir \ -- ; "name"
Create a new subdirectory from the current working one.
This word has been renamed to avoid a name conflict with
the system mkdir() API.
: deldir \ -- ; "name"
Remove a specified subdirectory. You can only remove an empty
directory. This word has been renamed to avoid a name conflict
with the system rmdir() API.
: rm \ -- ; "spec"
Delete a single file or group of files as described by the
given file specification. The wildcard '*' may also be used.
: cat \ -- ; "spec"
Perform an ASCII display of a file or group of files. No filtering
of the data is performed. This command should not be used to list
binary files.
: pwd \ --
Display the currently active working directory using the shell
pwd command.
: cd \ -- ; ["name"]
Attempt to change current working directory either as an
offset from the current directory or as a complete path.
The wildcard '*' can be used to match the first directory.
If there is no tail, CD displays the current directory.
No shell functions are used.
Signal numbers See /usr/src/linux-2.6.8-24/include/asm-i386/sigcontext.h
#define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 #define SIGILL 4 #define SIGTRAP 5 #define SIGABRT 6 #define SIGIOT 6 #define SIGBUS 7 #define SIGFPE 8 #define SIGKILL 9 #define SIGUSR1 10 #define SIGSEGV 11 #define SIGUSR2 12 #define SIGPIPE 13 #define SIGALRM 14 #define SIGTERM 15 #define SIGSTKFLT 16 #define SIGCHLD 17 #define SIGCONT 18 #define SIGSTOP 19 #define SIGTSTP 20 #define SIGTTIN 21 #define SIGTTOU 22 #define SIGURG 23 #define SIGXCPU 24 #define SIGXFSZ 25 #define SIGVTALRM 26 #define SIGPROF 27 #define SIGWINCH 28 #define SIGIO 29 #define SIGPOLL SIGIO #define SIGPWR 30 #define SIGSYS 31 #define SIGUNUSED 31
struct /fpstate \ -- len
Regular FPU environment.
See /usr/src/linux-2.6.8-24/include/asm-i386/sigcontext.h.
struct /_libc_fpstate \ -- len
The libc FPU environment.
See /usr/src/linux-2.6.8-24/include/asm-i386/ucontext.h.
struct /sigcontext \ -- len
CPU sigcontext structure.
See /usr/src/linux-2.6.8-24/include/asm-i386/sigcontext.h.
Note that this is not the same as a ucontext structure.
struct /gregset_t \ -- len
CPU gregset_t structure.
See /usr/src/linux-2.6.8-24/include/asm-i386/ucontext.h.
struct /mcontext \ -- len
System uncontext structure returned by signal handlers.
for Linux i32 this is the same as the /sigcontext structure.
struct /ucontext \ -- len
System uncontext structure returned by signal handlers.
struct /sigaction \ -- len
System sigaction structure.
The following is the stack structure seen by the siginfo signal handler.
|
create sigNames \ -- addr
Holds the signal numbers and names as counted strings.
: .sigName \ n --
Given a signal number, display its name.
: .RSitem \ x --
Display an item retrieved from the faulting return stack.
: .SigContext \ sc --
Display data from the sigcontext structure.
: SigThrow \ --
Runs the O/S THROW action.
3 0 callback: SigGenTrap \ signum *siginfo *ucontext --
Generic trap handler that causes a -57005 THROW on return.
Callbacks are documented in a separate section of the manual.
1 value -NestedSigs? \ -- x
Set non-zero to cause an exit if a nested signal exception
occurs in (SigGenTrap) below.
1 value SigPause? \ -- x
Set non-zero to cause a pause when a signal is processed
in (SigGenTrap) below.
: (SigGenTrap) \ signum *siginfo *ucontext --
Action of SigGenTrap. Displays an error message. On
return to Linux, a Forth THROW will occur.
: setSignal \ callback signum --
Set a signal handler to execute the given callback. The
callback must have the stack effect ( signum *siginfo *ucontext -- )
: setSigTraps \ --
Install the SigGenTrap signal handler for signals SIGILL,
SIGFPE and SIGSEGV. Performed at startup.
VFX Forth for Linux uses many functions from the libc shared library. The thread local error variables are exposed.
AliasedExtern: errno int * __errno_location( void );
errno is the well known errno C thread local variable
used by libraries and system calls.
Can be read by @ and written by !
AliasedExtern: h_errno int * __h_errno_location( void );
h_errno is the h_errno C thread local variable.
Can be read by @ and written by !
: ReadEnv \ naddr1 nlen -- vaddr vlen
Read the environment variable whose name is given by
naddr/nlen and return the string. If there is no
such variable vaddr is zNull and vlen is
zero.
: WriteEnv \ vaddr vlen naddr nlen --
Write the string value vaddr/vlen to the environment
variable named by vaddr/vlen.
: DelEnv \ naddr nlen --
Delete the environment variable naddr/nlen.
: EnvMacro: \ naddr nlen "<var>" -- ; -- caddr
Create a text macro called <var> that queries the
environment variable named by naddr/nlen the returned
string is a counted string. Use in the form:
s" HOME" EnvMacro: $home
By convention, environment macro names start with a '$'.
s" HOME" EnvMacro: $home
Text macro for the home directory.
Critical sections are implemented using the standard Linux semaphore structures and calls.
16 constant /sem_t \ -- len
Size of a Linux i32/ARM sem_t structure. You can treat this
as an opaque type that you do not have to deal with directly.
All you have to do is to reserve memory for it, e.g.
/sem_t buffer: MyCritSec
: InitCritSec \ sem --
Initialise the critical section. This must be done
before using it.
: TermCritSec \ sem --
Delete the critical section associated with the smaphore.
This releases internal Linux data, the /sem_t structure
is still available but needs to be initialised again before
reuse. Nothing should be waiting on the seamphore before
calling TermCritSec.
: [CritSec \ sem --
Wait until the section is available and lock it.
Does not call PAUSE.
: CritSec] \ sem --
Unlock the section.
: CritSec? \ sem -- u
Returns the section's counter, where non-zero indicates
that it is available, or zero when it is locked. Returns
zero on error.
The critical section words use Linux semaphores, which are counted semaphores. Thus when using critical sections you must be careful to match the use of [CritSec and
The Linux ticker frequency varies between implementations. The code in this section provides simple tools to return and handle a millisecond ticker.
: (ticks) \ -- ms ; return ticks in ms
Return the system ticker in milliseconds. Treat this as a 32 bit
unsigned value that wraps around on overflow.
: SetTicks \ --
Calibrate the Linux ticker and install it as the action of
TICKS. Performed at start up.
5 value tickStepMs \ -- ms
Minimum interval and granularity used by tick-ms
below.
: tick-ms \ ms --
Waits for at least ms milliseconds. Uses PAUSE
every tickStepMs. This is the default action of MS,
which is DEFERred.
4 field tv_sec 4 field tv_nsec end-struct
: td>epoch \ seconds mins hours day month year -- epoch
Returns the seconds since the start of the epoch. The input
time is treated as GMT/UTC.
: epoch>td \ epoch -- seconds mins hours day month year
Converts an epochal second into a GMT/UTC time and date.
These functions rely on the ANS Forth word TIME&DATE ( -- s m h dd mm yyyy ) and the non-standard DOW ( -- dow, 0=Sun) to get the day of the week.
create days$ \ -- addr
String containing 3 character text for the days of the week.
create months \ -- addr
String containing 3 character text for the months.
: .dow \ dow --
Display day of week.
: .2r \ n --
Display n as a two digit number with leading zeros.
: .4r \ n --
Display n as a four digit number with leading zeros.
: .Time&Date \ s m h dd mm yy --
Display the system time
The format is:
hh:mm:ss dd Mmm yyyy
: .AnsiDate \ zone --
Display the day of week, date and time. If zone is 0
GMT (system time) is displayed, otherwise local time
is displayed. The format is:
dow, hh:mm:ss dd Mmm yyyy [GMT]
The following notes are for developers working under x86-32 versions of Linux. Under normal use, direct access to I/O ports is forbidden. However, if you are running with root privilege, you can use the glibc functions ioperm() and iopl() to enable and disable port access.
code pc@ \ port -- b ; read port
Read a byte from the hardware control port supplied.
code pc! \ b port -- ; write port
Write the supplied byte to the selected hardware control port.
code pw@ \ port -- w ; read port
Read a 16 bit word from the hardware control port supplied.
code pw! \ w port -- ; write port
Write the supplied 16 bit word to the selected hardware control port.
code pl@ \ port -- x ; read port
Read 32 bits from the hardware control port supplied.
code pl! \ x port -- ; write port
Write the supplied 32 bits to the selected hardware control port.
: +Ports \ port #ports -- ior
Enable access to a range of ports starting at port.
Return 0 on success. Port numbers must be in the range
0..$3FF. You must have root permissions.
: -Ports \ port #ports -- ior
Disable access to a range of ports starting at port.
Return 0 on success. Port numbers must be in the range
0..$3FF. You must have root permissions.
: PlayNote \ hertz ms --
Play a note on the internal PC speaker.
Ports $42, $43 and $61 must be enabled first.
: pio-test \ --
A test routine for hardware access. Enables ports $40..$6F
and confirms access. If you hear a familiar tune, all is well!
Programs can be launched in several ways.
This code allows you to determine how the program was launched.
0 value AppPPID \ -- x
This application's parent's process ID.
0 value AppPGRP \ -- x
This application's process group.
0 value ctPGRP \ -- x
The controlling terminal's process group.
0 value AppLaunch \ -- x
How the application was launched:
: TestLaunch \ --
Set the data above to determine how the application was
launched. Run at program launch.
: dirExists? \ caddr len -- flag
Return true if a directory exists. Macros are expanded.
: create-dir \ caddr len -- ior
Create a directory, returning zero on success. Macros are expanded.
Default permissions are used.
: forceDir \ caddr len -- ior
Create the directory if it does not exist. Macros are expanded.
: copy-file \ src srclen dest destlen nooverwrite -- ior
Copy the file. If nooverwrite is non-zero and the destination
exists, an error is returned.