PRINT(3) PRINT(3)
NAME
print - string formatting and printing library
SYNOPSYS
#include <print.h>
typedef struct Format Format;
typedef int (*Fmtconv)(Format *, int);
struct Format {
/* for the formatting routines */
va_list args;
long flags, f1, f2;
Fmtconv* fmttab;
/* for the buffer maintainence routines */
char *buf, *bufbegin, *bufend;
int flushed;
int (*grow)(Format *, SIZE_T);
int error;
union { int n; void *p; } u;
/* misc */
void* client_data;
};
int print (const char *fmt,...)
int eprint (const char *fmt,...)
int fprint (int fd, const char *fmt,...)
int vfprint (int fd, const char *fmt, va_list)
int sprint (char *buf, const char *fmt,...)
int snprint (char *buf, int buflen, const char *fmt,...)
int vsnprint (char *buf, int buflen, const char *fmt, va_list)
char *mprint (const char *fmt,...)
char *smprint (Alloc alloc, SIZE_T* len, const char* fmt, ...)
char *vsmprint (Alloc alloc, SIZE_T* len, const char* fmt, va_list)
char *palloc (char* p, SIZE_T size)
Fmtconv fmtinstall (int c, Fmtconv f)
int fmtputc (Format *f, const char c)
int fmtappend (Format *format, const char *s, SIZE_T len)
int fmtcat (Format *format, const char *s)
int fmtengine (Format *format, const char *fmt)
int fmtprint (Format *format, const char *fmt,...)
SUMMARY
These routines format strings similarly to the printf family of
functions. Unlike printf, they support user supplied format
specifiers, they can format into memory that is allocated as needed
(using a user supplied allocation function), they are reentrant
(except for errno, the global table of format specifiers, and possibly
malloc if you choose to use it), and they are 8 bit clean ('\0' bytes
can be printed). Print is also space efficient. The program text is
about 5K when compiled for a sparc.
fprint writes formatted text to a file descriptor and returns the
- 1 - Formatted: November 5, 2025
PRINT(3) PRINT(3)
number of bytes written, or -1 on error. print writes text to stdout
while eprint writes text to stderr. vfprint formats arguments
supplied in a va_list obtained from stdargs.
sprint writes text into a user supplied buffer. It writes at most
FMT_SPRINT_BUFSIZ bytes including the terminating '\0'. It returns
the number of bytes requested (not including the terminating '\0').
Note that one must check for truncation by comparing this value to the
size of the buffer. snprint writes at most n bytes into a user
supplied buffer. vsnprint does the same, but takes its arguments
from a va_list.
mprint formats into a dynamically allocated buffer, to which it
returns a pointer. The space is obtained from malloc and should be
freed when no longer needed. smprint takes a user supplied allocation
function as an argument. This function should behave as ANSI-realloc
does. Some pre-ANSI systems' realloc fails to treat realloc(0,n) as
equivalent to malloc(n), so we provide a routine palloc which does.
smprint also returns the number of bytes generated by writing into the
*len argument if it is a non-null pointer. vsmprint is like smprint,
but that it reads arguments from a va_list.
fmtinstall installs a user supplied conversion function for a given
character, and returns the old value. A conversion function takes a
pointer to a format structure and the character that induced the call.
It must return FMT_flag if the format character signals setting a flag
and FMT_verb if it signals performing a conversion.
A conversion function can use fmtappend to put new text into the
output buffer; fmtputc and fmtcat are supplied for convenience.
fmtengine is the entry point for the actual formatting engine. Given
a properly initialized format structure and a format string, it will
do the specified work.
fmtprint is a very general interface to fmtengine. Its arguments are a
properly initialized format structure, a format string, and a matching
number of parameters. fmtprint saves and restores the argument list
stored in the format structure, so it can be used inside a conversion
function to perform arbitrary formatting operations. This usage
avoids the temporary buffers that fmtappend would require. fmtengine
and fmtprint return the number of characters that they generated.
The format structure contains three kinds of information. First,
variables used by the formatting routines. These are: args, the
argument list containing the data to be formatted. flags, a bitmask
storing the flags set at the time each conversion function is called.
Possible values are given in print.h. f1, f2 are the field width and
precision of each conversion. The flags, f1, and f2 are zeroed before
each conversion begins. fmttab is a pointer to the per-format array
of conversion functions, indexed by conversion character. If it is
- 2 - Formatted: November 5, 2025
PRINT(3) PRINT(3)
zero, the global table will be used instead.
Second, variables used for buffer maintainance: These are: buf,
bufbegin, bufend, pointers to the insertion point in the output
buffer, the buffer itself, and the end of the buffer. flushed, the
number of characters that have been transmitted to their ultimate
destination thus far. grow, the buffer growing function, called when
the buffer is nearly full so that it can be flushed or reallocated.
error, nonzero if an error has occurred during formatting. Formatting
will stop after the first error is noticed. u.n, u.p, the name of the
file descriptor to write to, or the realloc function to call to resize
a buffer.
Finally, client_data provides access to other arguments in a reentrant
way.
A simple format function, the one for %c, looks like this:
static int cconv(Format *format, int c) {
fmtputc(format, va_arg(format->args, int));
return FMT_verb;
}
A more interesting example is a conversion function that formats a
string with all unprintable characters quoted as in C.
int print_cquote_conv (Format* format, int c)
{
unsigned char* s = va_arg (format->args, unsigned char*);
unsigned char ch;
while ((ch = *s++)) {
if (isascii (ch) && isalnum (ch)) {
if (ch == '\\')
fmtputc (format, ch);
fmtputc (format, ch);
} else {
fmtprint (format, "\\%03uo", ch);
}
}
return FMT_verb;
}
STANDARD CONVERSIONS
verbs
% A literal percent.
s A string. With the # flag, use f2 for size and don't assume
'\0' termination.
c A single character.
- 3 - Formatted: November 5, 2025
PRINT(3) PRINT(3)
d, i A decimal integer.
o An octal integer. With #, prefix 0.
x A hex integer. With #, prefix 0x.
e, f, g Floating point conversions (not implemented).
r, m sys_errlist[errno]. With # flag, errno.
n writes the number of characters emitted thus far into into
an int* argument. Note! Since transput stops if an error
occurs, this verb may not be executed.
flags
u Arg is unsigned.
h Arg is short.
l Arg is long.
q Arg is quad (not implemented).
# Select alternate output format.
- Left justify output.
0 Zero pad output.
1-9 Set the f1 (field width) specifier.
. The f2 (precision) specifier follows.
* Set f1 or f2 from int arg.
OPTIONAL CONVERSIONS
Calling fmt_install_runeconv() installs conversion functions which
support Unicode 16 bit "Runes" by transforming them to the UTF-8
multibyte encoding. The %C operator transforms a single Rune, while
%S transforms a 0 terminated array, analagously to %c and %s.
NOTES
Unlike printf, flags like 'u' need to be followed by a verb like 'd'.
This code is derived from the print routines that Paul Haahr wrote
for Byron Rakitzis' implementation of rc.
AUTHORS
libprint: Paul Haahr, Byron Rakitzis, Scott Schwartz. runes: Rob
Pike, Howard Trickey runeconv: Erik Quanstrom
BUGS
What to do when an invalid print char is detected? BSD printf emits
the character without comment. We print a warning to stderr and stop
formatting. What should snprint return? The namespace for
installable format specifiers is very small, so collisions and
mistakes will probably cause trouble. No floating point conversion
functions (%e, %f, %g) yet. Quadword conversions (%qd) would be nice
too. Does %d really work in boundary cases (signed/unsigned
long/int/short maxint, minint)? What should snprint return? Number
of bytes requested, or transferred? fmtputc still feels kludgy. It
- 4 - Formatted: November 5, 2025
PRINT(3) PRINT(3)
used to directly write bytes into the buffer, in an attempt at
efficiency, but that turned out to complicate snprint. Now it just
calls fmtappend.
COPYRIGHT
All files in this library except rune.c and rune.h are covered by the
following copyright notice:
Copyright 1994 Paul Haahr, Scott Schwartz, Byron Rakitzis. All
rights reserved.
This software is not subject to any license of the American
Telephone and Telegraph Company or of the Regents of the
University of California.
Permission is granted to anyone to use this software for any
purpose on any computer system, and to alter it and redistribute
it freely, subject to the following restrictions:
1. The author is not responsible for the consequences of use of
this software, no matter how awful, even if they arise from flaws
in it.
2. The origin of this software must not be misrepresented, either
by explicit claim or by omission. Since few users ever read
sources, credits must appear in the documentation.
3. Altered versions must be plainly marked as such, and must not
be misrepresented as being the original software. Since few
users ever read sources, credits must appear in the
documentation.
4. This notice may not be removed or altered.
[this copyright notice is adapted from Henry Spencer's "awf"
copyright notice.]
The files rune.c and rune.h, originally distributed as part of the sam
editor, are covered by the following copyright notice:
The authors of this software are Rob Pike and Howard Trickey.
Copyright (c) 1992 by AT&T. Permission to use, copy, modify, and
distribute this software for any purpose without fee is hereby
granted, provided that this entire notice is included in all
copies of any software which is or includes a copy or
modification of this software and in all copies of the supporting
documentation for such software. THIS SOFTWARE IS BEING PROVIDED
"AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN PARTICULAR,
NEITHER THE AUTHORS NOR AT&T MAKE ANY REPRESENTATION OR WARRANTY
OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR
- 5 - Formatted: November 5, 2025
PRINT(3) PRINT(3)
ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- 6 - Formatted: November 5, 2025