FMTINSTALL(2)                                       FMTINSTALL(2)

          fmtinstall, dofmt, dorfmt, fmtprint, fmtvprint, fmtrune,
          fmtstrcpy, fmtrunestrcpy, fmtfdinit, fmtfdflush, fmtstrinit,
          fmtstrflush, runefmtstrinit, runefmtstrflush, errfmt -
          support for user-defined print formats and output routines

          #include <u.h>
          #include <libc.h>

          typedef struct Fmt  Fmt;
          struct Fmt{
              uchar   runes;  /* output buffer is runes or chars? */
              void    *start; /* of buffer */
              void    *to;    /* current place in the buffer */
              void    *stop;  /* end of the buffer; overwritten if flush fails */
              int     (*flush)(Fmt*);/* called when to == stop */
              void    *farg;  /* to make flush a closure */
              int     nfmt;   /* num chars formatted so far */
              va_list args;   /* args passed to dofmt */
              int     r;      /* % format Rune */
              int     width;
              int     prec;
              ulong   flags;
9          enum{
              FmtWidth    = 1,
              FmtLeft     = FmtWidth << 1,
              FmtPrec     = FmtLeft << 1,
              FmtSharp    = FmtPrec << 1,
              FmtSpace    = FmtSharp << 1,
              FmtSign     = FmtSpace << 1,
              FmtZero     = FmtSign << 1,
              FmtUnsigned = FmtZero << 1,
              FmtShort    = FmtUnsigned << 1,
              FmtLong     = FmtShort << 1,
              FmtVLong    = FmtLong << 1,
              FmtComma    = FmtVLong << 1,
9              FmtFlag     = FmtComma << 1

          int   fmtfdinit(Fmt *f, int fd, char *buf, int nbuf);

          int   fmtfdflush(Fmt *f);

          int   fmtstrinit(Fmt *f);

          char* fmtstrflush(Fmt *f);

     Page 1                       Plan 9             (printed 7/23/24)

     FMTINSTALL(2)                                       FMTINSTALL(2)

          int   runefmtstrinit(Fmt *f);

          Rune* runefmtstrflush(Fmt *f);
          int   fmtinstall(int c, int (*fn)(Fmt*));

          int   dofmt(Fmt *f, char *fmt);

          int   dorfmt(Fmt*, Rune *fmt);

          int   fmtprint(Fmt *f, char *fmt, ...);

          int   fmtvprint(Fmt *f, char *fmt, va_list v);

          int   fmtrune(Fmt *f, int r);

          int   fmtstrcpy(Fmt *f, char *s);

          int   fmtrunestrcpy(Fmt *f, Rune *s);

          int   errfmt(Fmt *f);

          The interface described here allows the construction of cus-
          tom print(2) verbs and output routines.  In essence, they
          provide access to the workings of the formatted print code.

          The print(2) suite maintains its state with a data structure
          called Fmt.  A typical call to print(2) or its relatives
          initializes a Fmt structure, passes it to subsidiary rou-
          tines to process the output, and finishes by emitting any
          saved state recorded in the Fmt.  The details of the Fmt are
          unimportant to outside users, except insofar as the general
          design influences the interface.  The Fmt records whether
          the output is in runes or bytes, the verb being processed,
          its precision and width, and buffering parameters.  Most
          important, it also records a flush routine that the library
          will call if a buffer overflows.  When printing to a file
          descriptor, the flush routine will emit saved characters and
          reset the buffer; when printing to an allocated string, it
          will resize the string to receive more output.  The flush
          routine is nil when printing to fixed-size buffers.  User
          code need never provide a flush routine; this is done inter-
          nally by the library.

        Custom output routines
          To write a custom output routine, such as an error handler
          that formats and prints custom error messages, the output
          sequence can be run from outside the library using the rou-
          tines described here.  There are two main cases: output to
          an open file descriptor and output to a string.

     Page 2                       Plan 9             (printed 7/23/24)

     FMTINSTALL(2)                                       FMTINSTALL(2)

          To write to a file descriptor, call fmtfdinit to initialize
          the local Fmt structure f, giving the file descriptor fd,
          the buffer buf, and its size nbuf. Then call fmtprint or
          fmtvprint to generate the output.  These behave like fprint
          (see print(2)) or vfprint except that the characters are
          buffered until fmtfdflush is called and the return value is
          either 0 or -1.  A typical example of this sequence appears
          in the Examples section.

          The same basic sequence applies when outputting to an allo-
          cated string: call fmtstrinit to initialize the Fmt, then
          call fmtprint and fmtvprint to generate the output.
          Finally, fmtstrflush will return the allocated string, which
          should be freed after use.  To output to a rune string, use
          runefmtstrinit and runefmtstrflush. Regardless of the output
          style or type, fmtprint or fmtvprint generates the charac-

        Custom format verbs
          Fmtinstall is used to install custom verbs and flags labeled
          by character c, which may be any non-zero Unicode character.
          Fn should be declared as

               int   fn(Fmt*)

          Fp->r is the flag or verb character to cause fn to be
          called.  In fn, fp->width, fp->prec are the width and preci-
          sion, and fp->flags the decoded flags for the verb (see
          print(2) for a description of these items).  The standard
          flag values are: FmtSign (+), FmtLeft (-), FmtSpace (' '),
          FmtSharp (#), FmtComma (,), FmtLong (l), FmtShort (h),
          FmtUnsigned (u), and FmtVLong (ll).  The flag bits FmtWidth
          and FmtPrec identify whether a width and precision were

          Fn is passed a pointer to the Fmt structure recording the
          state of the output.  If fp->r is a verb (rather than a
          flag), fn should use Fmt->args to fetch its argument from
          the list, then format it, and return zero.  If fp->r is a
          flag, fn should return one.  All interpretation of
          fp->width, fp->prec, and fp->flags is left up to the conver-
          sion routine.  Fmtinstall returns 0 if the installation suc-
          ceeds, -1 if it fails.

          Fmtprint and fmtvprint may be called to help prepare output
          in custom conversion routines.  However, these functions
          clear the width, precision, and flags.  Both functions
          return 0 for success and -1 for failure.

          The functions dofmt and dorfmt are the underlying format-
          ters; they use the existing contents of Fmt and should be
          called only by sophisticated conversion routines.  These

     Page 3                       Plan 9             (printed 7/23/24)

     FMTINSTALL(2)                                       FMTINSTALL(2)

          routines return the number of characters (bytes of UTF or
          runes) produced.

          Some internal functions may be useful to format primitive
          types.  They honor the width, precision and flags as
          described in print(2). Fmtrune formats a single character r.
          Fmtstrcpy formats a string s; fmtrunestrcpy formats a rune
          string s.  Errfmt formats the system error string.  All
          these routines return zero for successful execution.  Con-
          version routines that call these functions will work prop-
          erly regardless of whether the output is bytes or runes.

          2c(1) describes the C directive #pragma varargck that can be
          used to provide type-checking for custom print verbs and
          output routines.

          This function prints an error message with a variable number
          of arguments and then quits.  Compared to the corresponding
          example in print(2), this version uses a smaller buffer,
          will never truncate the output message, but might generate
          multiple write system calls to produce its output.

               #pragma     varargck    argpos      fatal 1
9               void
               fatal(char *fmt, ...)
                     Fmt f;
                     char buf[64];
                     va_list arg;
9                     fmtfdinit(&f, 1, buf, sizeof buf);
                     fmtprint(&f, "fatal: ");
                     va_start(arg, fmt);
                     fmtvprint(&f, fmt, arg);
                     fmtprint(&f, "\n");
                     exits("fatal error");

          This example adds a verb to print complex numbers.

               typedef struct {
                     double      r, i;
               } Complex;
9               #pragma     varargck    type  "X"   Complex
9               int
               Xfmt(Fmt *f)
                     Complex c;

     Page 4                       Plan 9             (printed 7/23/24)

     FMTINSTALL(2)                                       FMTINSTALL(2)

                     c = va_arg(f->args, Complex);
                     return fmtprint(f, "(%g,%g)", c.r, c.i);
9               main(...)
                     Complex x = (Complex){ 1.5, -2.3 };
9                     fmtinstall('X', Xfmt);
                     print("x = %X\n", x);


          print(2), utf(6), errstr(2)

          These routines return negative numbers or nil for errors and
          set errstr.

     Page 5                       Plan 9             (printed 7/23/24)