Modula-2 || Compiler & Tools || Library || Search Engine


Ulm's Modula-2 Library:
Printf


NAME

Printf - common base of formatted output toolkit

SYNOPSIS

CONST
   Pabort = 201;   Labort     = 205;
   Fabort = 202;   WabortP    = 206;
   Sabort = 203;   WabortA    = 207;
   Eabort = 204;   PanicAbort = 255;


CONST TellSyntax = 1; TellOutput = 2; AbortSyntax = 3; AbortOutput = 4; Default = {TellSyntax .. TellOutput};

TYPE FmtExitCode = (Success, Undefined, FmtPanic, IllegalWidth, TooFewFormElems, TooManyFormElems, IllegalConvChar, MinHat0Comb, BslashAnd0, BadOctalChar, AllocFailed, StringTooSmall, CannotWriteFile, CannotWriteStderr, CannotWriteStdout, IllegalWindowOffset, WindowTooSmall, CannotFlushWindow, CannotAccessWindow, CannotWriteWindow); FmtExitSet = SET OF FmtExitCode;

CONST SynError = FmtExitSet {IllegalWidth .. BadOctalChar}; OutError = FmtExitSet {AllocFailed .. CannotWriteWindow};

PROCEDURE Printf (output : Long; no : CARDINAL; VAR fmt : ARRAY OF CHAR; VAR i1 ,i2, i3, i4, i5, i6, i7,i8 : ARRAY OF BYTE) : FmtExitCode;

DESCRIPTION

This module is the common base of P, F, S, E, L and W which realize formatted output to various devices. It is not intended to be used directly but the declarations exported from here are common to all of the mentioned modules. Furthermore the description of Printf's formatting capabilities applies to all output routines of this toolkit.

Printf reads the format string fmt Any character not belonging to a escape sequence introduced by \ or a format element introduced by % is simply appended to output (type Long imported from LongStrings). Escape sequences are substituted by a single character while format elements are instantiated by the first no parameter of i1 .. i8 (no may be zero).

Printf returns Success on successful completion, a value out of SynError in case of illegal format specifications and AllocFailed if output cannot be appended to output.

The parameters of Printf are declared as VAR parameters for reasons of efficiency only. Printf will never updated them. Please note that this does not affect in any way the possibility to output expressions using the superior modules P, F etc.

FORMAT ELEMENTS

Format elements do not contain any space character and fulfill the following syntax (number is an unsigned sequence of digits, any stands for any single character):
formatelement
: % [align] [width] [ . scale] convchar

align
: [+] [ 0 | [--|^] [\ any] ]
width
: number | *
scale
: number | *

convchar
: b | c | d | e | f | j | l | o | s | u | x | y
| B | C | D | E | F | J | L | O | S | U | X | Y

Each format element defines a field in the output stream that is by default as wide as necessary to insert the result of a parameter conversion. The field width can be expanded by specifying width. If not given as an explicit number but as * Printf uses the value of the next yet unused parameter (interpreted as a CARDINAL) as width indication. Larger values than 2048 will cause Printf to return with IllegalWidth, values less or equal than the defaults have no effect. In all other cases the output field is filled up by leading blanks. Fillup character and alignment strategy may be altered by means of align:

+
Any numeric output will be signed (by default positive values do not get a +sign).
--
The output will be left aligned within its field. This option has no effect if width is omitted.
0
The output of numeric values is filled up with leading zeroes (0). This option implies --.
^
The fill up characters are inserted before the leading sign and the first digit of a number.
\ any
defines any to become the fill up character

Printf will return with MinHat0Comb or BslashAnd0 on illegal combinations of these options (refer to syntax description above). 0 and ^ have no effect, if the output value is not a number.

On output of real values, scale fixes the number of digits following the decimal point. Other numeric output is not affected while strings are cut to the length given by scale before there are aligned within their output fields. Printf will use the next yet unused parameter as scale indication, if * is specified.

Since Printf has no idea about the actual types of the arguments corresponding to its formal parameters, convchar is used to determine the conversions to be executed for the next yet unused parameter of i1 .. i8. Printf will not accept any other conversion character than those listed and described below (error return value: IllegalConvChar). In detail the specifications of convchar have the following effect:

u
decimal output of a CARDINAL
x
hexadecimal output of a CARDINAL
o
octal output of a CARDINAL
d
decimal output of an INTEGER
f
output of a REAL in floating point notation
e
output of a REAL in its normalized exponential form
c
output of a single CHAR
s
output of an ARRAY until the first null byte (0C) or the high bound of the array is reached
b
output of a BOOLEAN as text TRUE or FALSE
y
output of a BOOLEAN as text yes or no
j
output of a BOOLEAN as text ja or nein
l
output of a CHAR width times (i.e. use the character given as parameter to draw a line of length width). Without explicit width indication same as c.

If convchar is an upper case letter, Printf treats the parameter associated to the currently processed format element as the address (SYSTEM.ADDRESS) of an variable to be output (respectively as a POINTER TO the type expected for the corresponding lower case letters). If using S, ensure that that null byte is found at the end of the string or limit output size by specifying scale.

Note that u, o, x, and d are legal conversion characters to output any type which has the same size (in bytes) as the expected one. This feature can be used to output an enumeration value (i.e its ordinal number) or an address (equal size presumed). Furthermore these conversion characters may be used to output the ascii-value of a CHAR. Vice versa c may be used to output a character that is specified by a small CARDINAL- or INTEGER-value. You should avoid other combinations than those mentioned, the results are undefined.

If the number of format elements within fmt plus the number of variable scale of width indications (*) is not equal to no, Printf will return with an error (TooManyFormElems, TooFewFormElems). Using the high level routines of P, F, S, E, W, and L the expected number of format elements (including additional parameter used for scale or width indication) derives from the procedure name respectively from the number of formal parameters declared as ARRAY BYTE.

%% will not be interpreted as a format element. A single percent character is output instead.

ESCAPE SEQUENCES

Any appearance of the following escape sequences in format string fmt is substituted as listed:
\n
newline (line feed) (12C)
\r
carriage return (15C)
\t
horizontal tab (11C)
\e
escape (33C)
\f
form feed (14C)
\b
backspace (10C)
\&
bell (7C)
\Q
double quote (")
\q
quote(')
\%
percent (%)
\\
backslash (\)
\[0-7]+C
character specified by [0-7]+C. Printf will return BadOctalChar on illegal character specifications.
\ other
other (where other is a character not listed above)

EXAMPLES

The formatting capabilities of Printf are illustrated by means of module P. All examples apply accordingly to the other modules of this toolkit. The 'input' is left aligned, output has been indented 8 spaces.
P.rintf1(stdout,"Hello.\n%6l\n",'-');

Hello.
------
pi := 4.0 * arctan(1.0);
scale := 3;
P.rintf2(,"100*pi = %f or %e \n",100.0*pi,100.0*pi);
P.rintf1(,"pi (scale=1): %.1e!\n",pi);
P.rintf1(,"pi (scale=1): %.1e!\n",pi);
P.rintf1(,"pi (scale=2): %10.2e!\n",pi);
P.rintf3(,"pi (scale=%u): %.*f!\n",scale,scale,pi);
P.rintf4(,"pi (scale=%u): %+-*.*f!\n",15,scale+1,scale+1,pi);

100*pi = 314.1592653589793 or 3.141592653589793e+02
pi (scale=1): 3.1e+00!
pi (scale=1): 3.1e+00!
pi (scale=2): 3.14e+00!
pi (scale=3): 3.142!
pi (scale=4): +3.1416 !

string := "Hello world.";
P.rintf1("|%s|\n",string);
P.rintf1("|%20s|\n",string);
P.rintf1("|%-20s|\n",string);
P.rintf1("|%20.8s|\n",string);
P.rintf1("|%-20.8s|\n",string);
P.rintf1("|%5.3S|\n",ADR(string[3]));

|Hello world.|
| Hello world.|
|Hello world. |
| Hello wo|
|Hello wo |
| lo |

P.rintf4("%10u\n%10u\n%10u\n%10u\n",1,12,223,43333);

1
12
223
43333

P.rintf3("1. %+05d\n2. %+05d\n3. %+04d\n",234,-233,1000);

1. +0234
2. -0233
3. +1000

val1 := 1; val2 := -20; val3 := 300;
P.rintf5 ("%+^\.7d\n%+^\.7d\n%+^\.7d\n%7l\n%+^\.7d\n",
val1,val2,val3,'=',val1+val2+val3);

+.....1
-....20
+...300
=======
+...281

ch := ' ';
P.rintf4(,"char: \Q%c\Q -- octal: %o -- hex: %x -- dec: %u\n",
ch,ch,ch,ch);

char: " " -- octal: 40 -- hex: 20 -- dec: 32

DIAGNOSTICS

As already mentioned any illegal specification of the format string will cause Printf to return immediately with an result # Success. The toolkit in general provides automatic error recognition and output success control due to the following conventions.

Errors on formatted output are divided into SynError which result from illegal format specifications and OutError which result from illegal parameters or problems on writing to the various devices. Any error will be treated accordingly to the bits set in the current error handling mode of the affected module:

TellSyntax
any SynError (in a format string) will be reported to StdIO.stderr.
AbortSyntax
any SynError will cause a program termination. The relevant exit code is given by the constants declared in module Printf (P will terminate with Pabort F with Fabort etc).
TellOutput
any OutError will be reported to StdIO.stderr.
AbortOutput
any OutError will terminate the program (exit codes as above).

By default, any error will be reported and cause a process termination. Thus, success of output routines has to be controlled only if an other error handling mode than Default has been explicitly assigned to the modules.

SEE ALSO

m2c, mrc(1), P, F, E, S, W, L, LongStrings, StdIO

BUGS

Due to implementation restriction of mrc(1) the output routines of P, F, S, E, W, and L are not available for other arguments than simple variables (expressions are rejected with error code 214).

A quoted character as an argument to an ARRAY OF BYTE will be interpreted as a string of length one. Therefore s (not c) is the suitable conversion character.

Strange effects will always occur if the parameter types are not suitable for the conversion characters. Using %f or %e improperly may even result in a floating point exception.

AUTHOR

Werner Stanglow
Edited by: borchert, last change: 1997/02/25, revision: 1.2, converted to HTML: 1997/04/28

Modula-2 || Compiler & Tools || Library || Search Engine