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 14, 2024 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 14, 2024 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 14, 2024 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 14, 2024 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 14, 2024 PRINT(3) PRINT(3) ITS FITNESS FOR ANY PARTICULAR PURPOSE. - 6 - Formatted: November 14, 2024