packages icon

 PRINT(3)                                                           PRINT(3)

      print - string formatting and printing library

      #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,...)

      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:  July 6, 2020

 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:  July 6, 2020

 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

      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;

      %         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:  July 6, 2020

 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.

      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.

      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.

      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.

      libprint: Paul Haahr, Byron Rakitzis, Scott Schwartz.  runes: Rob
      Pike, Howard Trickey runeconv: Erik Quanstrom

      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:  July 6, 2020

 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.

      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

           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

                                    - 5 -           Formatted:  July 6, 2020

 PRINT(3)                                                           PRINT(3)


                                    - 6 -           Formatted:  July 6, 2020