The code described here is specific to VFX Forth for Mac OS X. 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.
Text macros are expanded before the operation.
: 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(). Text macros are expanded.
: $osx \ 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.
: cwd \ -- ; ["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, CWD
displays the current directory.
No shell functions are used. Text macros are expanded.
: cd \ -- ; ["name"]
A synonym for *fo{CWD}. Use *fo{CWD} as *fo{CD}
will be removed in a future release to avoid conflicts
with hex numbers.
Signal numbers See /usr/include/sys/signal.h.
#define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 #define SIGILL 4 #define SIGTRAP 5 #define SIGABRT 6 #define SIGIOT 6 #define SIGEMT 7 #define SIGFPE 8 #define SIGKILL 9 #define SIGBUS 10 #define SIGSEGV 11 #define SIGSYS 12 #define SIGPIPE 13 #define SIGALRM 14 #define SIGTERM 15 #define SIGURG 16 #define SIGSTOP 17 #define SIGSTP 18 #define SIGCONT 19 #define SIGCHLD 20 #define SIGTTIN 21 #define SIGTTOU 22 #define SIGIO 23 #define SIGXCPU 24 #define SIGXFSZ 25 #define SIGVTALRM 26 #define SIGPROF 27 #define SIGWINCH 28 #define SIGINFO 29 #define SIGUSR1 30 #define SIGUSR2 31
struct /ts32 \ -- len
Regular thread state.
See /usr/include/mach/i386/_structs.h
_STRUCT_X86_THREAD_STATE32.
struct /fs32 \ -- len
Regular FPU environment.
See /usr/include/mach/i386/_structs.h
_STRUCT_X86_FLOAT_STATE32.
struct /excpt32 \ -- len
See /usr/include/mach/i386/_structs.h
_STRUCT_X86_EXCEPTION_STATE32.
8 cells constant /dbg32 \ -- len ; dr0..dr7
See /usr/include/mach/i386/_structs.h
_STRUCT_X86_DEBUG_STATE32.
4 constant /sigset_t \ -- len
size of sigset_t.
struct /sigaltstack \ -- len
See /usr/include/sys/_structs.h
struct /mcontext \ -- len
Machine dependent context structure.
See /usr/include/i386/_structs.h.
struct /ucontext \ -- len
See /usr/include/sys/_structs.h
struct /siginfo \ -- len
Siginfo structure in /usr/include/sys/signal.h.
struct /sigaction \ -- len
System sigaction structure.
The following is the stack structure seen by the siginfo signal handler.
| |
+-------------+
| Return code | 8 bytes of code to return to kernel context at
| | end of the handler run via a special system call
| | (now a dummy left as a signature for debuggers
| | as many systems don't allow execution from the
| | stack)
+-------------+
| Floating | FPU state if FPU has been used by this process
| point state |
+-------------+
| User | OSX extension user context for the signal
| Context | handler. Includes pointer to register contents
+->| | which are modifiable by the signal handler
| +-------------+
| | Siginfo | Traditional signal information structure.
| | structure |<-+ Duplicates/simplifies some of User Context
| +-------------+ |
+--| void * | | Pointer to OSX user context
+-------------+ |
| siginfo_t * |--+ Pointer to OSX Siginfo structure
+-------------+
| Signum | Actual signal number generated
+-------------+
| Return | Originally this pointed at the stack based
| address | return code above. Now points directly at the
| | sigreturn syscall gate in the vDSO
+-------------+
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.
: .mcontext \ *mc --
Display data from the mcontext 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 OS X, 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, SIGBUS and SIGSEGV. Performed at startup.
VFX Forth for Mac OS X uses many functions from the libSystem shared library. The thread local error variables are exposed.
AliasedExtern: errno int * __error( void );
errno
is the well known errno C thread local variable
used by libraries and system calls.
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 OS X semaphore structures and calls.
struct /semosx \ -- len
We use a structure consisting of a pointer to the sem_t
structure followed by a 32 byte zname.
: InitCritSec \ *smo --
Initialise a critical section base on a /semosx
structure. This must be done before using the critical
section.
: TermCritSec \ *smo --
Delete the critical section associated with the smaphore.
This releases internal OS X data and closes the semaphore.
Nothing should be waiting on the seamphore before
calling TermCritSec
.
: [CritSec \ *smo --
Wait until the section is available and lock it.
Does not call PAUSE
.
: CritSec] \ *smo --
Unlock the section.
The critical section words use OS X semaphores, which are
counted semaphores. Thus when using critical sections you
must be careful to match the use of [CritSec
and
The OS X 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 OS X 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 DEFER
red.
The following timer tools have better resolution but are very basic.
: ns@ \ -- nanoseconds
Return a system ticker in nanoseconds.
: ms@ \ -- milliseconds
Return a system ticker in milliseconds.
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]
Programs can be launched in several ways.
vfxosx &
:
it shares a terminal which is normally only useful for output.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.
: (changedir) \ caddr len -- ior ; 0=success
Expand text macros and change the current working directory.
Return 0 on success.
: changeDir \ caddr len --
Expand text macros and change the current working directory.
There is no return code.
: workingdir \ -- caddr len
Return the text for the current working directory.
: 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.
: +dirSep \ c$ --
Add a directory separator to the end of a counted string.
: prepFileName \ caddr len --
Convert '\' and '/' characters in-place as required by the
operating system.
: prepDirName \ caddr --
Force the counted string at caddr to end with a '\' character.
: makeDirLevels \ caddr1 len1 caddr2 len -- ior
The string caddr1/len1 represents a directory that
must already exist. Caddr2/len2 represents additional
directory levels that may or may not already exist. The
additional levels are created if they do not exist.
Successful operation returns 0. For example, to create the
directory /Users/stephen/jim/foo/bar
, you could use
s" /Users/stephen" s" jim/foo/bar" makedirlevels
: copy-file \ src slen dest dlen failexist -- ior
Copy a file. Macros are expanded. If failexist is
non-zero, existing files are not overwritten.