sprintf
An implementation of sprintf, printf and fprintf
- raw LICENSE
- raw README.md
- raw history.txt
- raw package.4th
- raw printf-spec.md
- raw sprintf.fth
- raw sprintftest.fth
- raw tester.fr
Forth-sprintf
Many languages provide a family of PRINTF function either in a library or as part of the language. This package is an implementation of SPRINTF, PRINTF and FPRINTF
in standard Forth 2012. The functionality is a substantial subset of C PRINTF as described at https://linux.die.net/man/3/printf with a few additions and differences. The detailed specification is in file printf-spec.md
in this repository. A summary of the functionality provided follows.
It is assumed that the reader is familiar with PRINTF
, if not there are tutorials and descriptions readily available on the internet.
See file history.txt
for changes in the latest version.
User words
PRINTF ( arguments* format-string -- )
outputs the result to the user terminal
SPRINTF ( arguments* format-string -- caddr u )
outputs the result into a buffer, returns the result as a string
FPRINTF ( arguments* format-string fileid -- )
outputs the result into an opened file with identifier fileid.
SET-SPRINTF-BUFFER ( caddr size -- )
Sets the output buffer for SPRINTF
only. It is not needed for PRINTF
or FPRINTF
. SET-SPRINTF-BUFFER
must be used before SPRINTF
is called for the first time following loading - a default buffer is not provided by the system. Several buffers may be used - it is the user's responsibility to manage multiple buffers
Installation and testing
Download the files and unzip the files into a directory of your choice.
Following installation it is best to check that it runs successfully on your system by including the test program sprintftests.fth
which will include the tester and SPRINTF
source files. Note that if using SwiftForth please type this definition before running the test program (see the Portability section below):
create swiftforth
Assuming the Forth system implements floating point, the test output should be:
Start of tests
**********************
Six error reports should be displayed:
------
Format string: "This specification %&d is bad"
^
SPRINTF error: Invalid character
------
Format string: "Not enough %d %d arguments"
^
SPRINTF error: Too few arguments on the stack
------
Format string: "%*.0u"
^
SPRINTF error: Output buffer overflow
------
Format string: "Buffer not set"
^
SPRINTF error: No sprintf buffer set, use SET-SPRINTF-BUFFER
------
Format string: "Not enough %e FP arguments"
^
SPRINTF error: Too few arguments on the FP stack
------
Format string: "Too many fp formats %f %e %g"
^
SPRINTF error: FP-ARGS array too small
------
End of tests
-----[ Report ]-------
Stack empty
FP stack depth: 0
Number of tests: 475
Number of errors: 0
----------------------
Usage
To use sprintf.fth
simply include the file. Note that if your Forth system does not have the standard floating point word REPRESENT
then it is assumed that floating point has not been implemented and floating point functionality is not compiled.
Example
s" Mary" 23 s" My sister %s is %d years old." printf
displays
My sister Mary is 23 years old.
The arguments must be in the same order as the conversion specifications in the format string. The test program contains many other examples of usage.
Configuration
There are some user configurable values that can be changed:
MAX-PRECISION
the number of digits to be generated by REPRESENT
, initially set to 15 for 64 bit floating point.
FP-SEP
holds the character separating the integer and fractional parts of a floating point number. Initially set to '.'.
MAX-FP-ARGS
The maximum number of floating point arguments used in a single PRINTF
call, initially set to 10.
MAX-CONV-WIDTH
an upper limit to PRINTF
field width.
MAX-CONV-PREC
an upper limit to a conversion's precision.
Exception codes may be changed if they clash with user error codes.
These are Forth VALUEs
and may be set to other values in a user program instead of changing the sprintf.fth
source file e.g.
10 to MAX-PRECISION
Portability
The SPRINTF
test program has run successfully under Windows 10 on 32 and 64 bit GForth and Win32 Forth with no errors. It runs on VFX Forth and SwiftForth with 1 insignificant error as those systems seem to be unable to handle floating point -0
. In addition some tests are disabled for SwiftForth as it crashes if attempts are made to test floating point NAN
or INF
(hence the advice to create a swiftforth definition above).
Conversion specifications
The following is just a summary of features, see file printf-spec.md
for more details
A conversion specification starts with the character %
and takes this form:
%<flags><width>.<precision><length><conversion type>
Except for the %
character and <conversion type>
the fields are optional.
The <flags>
available are (these may be used in any order):.
#
an alternative form0
for left justified conversions the output is padded with 0 characters instead of spaces-
the conversion is left justified+
if a signed conversion positive numbers are preceded with a + character- ' ' (space character) if a signed conversion positive numbers are preceded with a space character
<width>
, <precision>
and <length>
are:
<width>
specifies the field width into which the conversion fits.<precision>
specifies the minimum number of significant digits to be generated. If the precision is present it must be preceded by a.
character.<length>
specified by an l (lower case L) character means the argument is a double length integer. Ignored for floating point conversions
The <conversion types>
available in this implementation are:
d
for a signed decimal integer conversionu
for an unsigned decimal integer conversionx
for an unsigned hexadecimal integer conversion using the a to f charactersX
as for x except that characters A to F are used in the resulto
for an unsigned octal integer conversionb
for an unsigned binary integer conversionr
for an integer conversion where a radix (base) value in the range 2 to 36 is used to convert the integer to a string.R
as for r except that characters A to Z are used for digits >9c
for a single characters
for a string%
for a % character i.e. the full conversion specification is %%e
for a floating point number in exponential form [-]d.dddde+/-dd where the d's are decimal digitsE
as for e except that the form is [-]d.ddddE+/-ddf
for a floating point number in fractional format in the style [-]dddd.dddg
for a floating point format where either the e or f type conversion is carried out.G
As for g except that style E or f is used.