17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate * All rights reserved.
47c478bd9Sstevel@tonic-gate * Copyright (c) 1990
57c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate * Chris Torek.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate * the sendmail distribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*49218d4fSjbeck SM_IDSTR(id, "@(#)$Id: vfprintf.c,v 1.54 2005/05/16 03:52:00 ca Exp $")
197c478bd9Sstevel@tonic-gate
207c478bd9Sstevel@tonic-gate /*
217c478bd9Sstevel@tonic-gate ** Overall:
227c478bd9Sstevel@tonic-gate ** Actual printing innards.
237c478bd9Sstevel@tonic-gate ** This code is large and complicated...
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <errno.h>
307c478bd9Sstevel@tonic-gate #include <sm/config.h>
317c478bd9Sstevel@tonic-gate #include <sm/varargs.h>
327c478bd9Sstevel@tonic-gate #include <sm/io.h>
337c478bd9Sstevel@tonic-gate #include <sm/heap.h>
347c478bd9Sstevel@tonic-gate #include <sm/conf.h>
357c478bd9Sstevel@tonic-gate #include "local.h"
367c478bd9Sstevel@tonic-gate #include "fvwrite.h"
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate static int sm_bprintf __P((SM_FILE_T *, const char *, va_list));
397c478bd9Sstevel@tonic-gate static void sm_find_arguments __P((const char *, va_list , va_list **));
407c478bd9Sstevel@tonic-gate static void sm_grow_type_table_x __P((unsigned char **, int *));
417c478bd9Sstevel@tonic-gate static int sm_print __P((SM_FILE_T *, int, struct sm_uio *));
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate ** SM_PRINT -- print/flush to the file
457c478bd9Sstevel@tonic-gate **
467c478bd9Sstevel@tonic-gate ** Flush out all the vectors defined by the given uio,
477c478bd9Sstevel@tonic-gate ** then reset it so that it can be reused.
487c478bd9Sstevel@tonic-gate **
497c478bd9Sstevel@tonic-gate ** Parameters:
507c478bd9Sstevel@tonic-gate ** fp -- file pointer
517c478bd9Sstevel@tonic-gate ** timeout -- time to complete operation (milliseconds)
527c478bd9Sstevel@tonic-gate ** uio -- vector list of memory locations of data for printing
537c478bd9Sstevel@tonic-gate **
547c478bd9Sstevel@tonic-gate ** Results:
557c478bd9Sstevel@tonic-gate ** Success: 0 (zero)
567c478bd9Sstevel@tonic-gate ** Failure:
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate static int
sm_print(fp,timeout,uio)607c478bd9Sstevel@tonic-gate sm_print(fp, timeout, uio)
617c478bd9Sstevel@tonic-gate SM_FILE_T *fp;
627c478bd9Sstevel@tonic-gate int timeout;
637c478bd9Sstevel@tonic-gate register struct sm_uio *uio;
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate register int err;
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate if (uio->uio_resid == 0)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 0;
707c478bd9Sstevel@tonic-gate return 0;
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate err = sm_fvwrite(fp, timeout, uio);
737c478bd9Sstevel@tonic-gate uio->uio_resid = 0;
747c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 0;
757c478bd9Sstevel@tonic-gate return err;
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate ** SM_BPRINTF -- allow formating to an unbuffered file.
807c478bd9Sstevel@tonic-gate **
817c478bd9Sstevel@tonic-gate ** Helper function for `fprintf to unbuffered unix file': creates a
827c478bd9Sstevel@tonic-gate ** temporary buffer (via a "fake" file pointer).
837c478bd9Sstevel@tonic-gate ** We only work on write-only files; this avoids
847c478bd9Sstevel@tonic-gate ** worries about ungetc buffers and so forth.
857c478bd9Sstevel@tonic-gate **
867c478bd9Sstevel@tonic-gate ** Parameters:
877c478bd9Sstevel@tonic-gate ** fp -- the file to send the o/p to
887c478bd9Sstevel@tonic-gate ** fmt -- format instructions for the o/p
897c478bd9Sstevel@tonic-gate ** ap -- vectors of data units used for formating
907c478bd9Sstevel@tonic-gate **
917c478bd9Sstevel@tonic-gate ** Results:
927c478bd9Sstevel@tonic-gate ** Failure: SM_IO_EOF and errno set
937c478bd9Sstevel@tonic-gate ** Success: number of data units used in the formating
947c478bd9Sstevel@tonic-gate **
957c478bd9Sstevel@tonic-gate ** Side effects:
967c478bd9Sstevel@tonic-gate ** formatted o/p can be SM_IO_BUFSIZ length maximum
977c478bd9Sstevel@tonic-gate */
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate static int
sm_bprintf(fp,fmt,ap)1007c478bd9Sstevel@tonic-gate sm_bprintf(fp, fmt, ap)
1017c478bd9Sstevel@tonic-gate SM_FILE_T *fp;
1027c478bd9Sstevel@tonic-gate const char *fmt;
1037c478bd9Sstevel@tonic-gate SM_VA_LOCAL_DECL
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate int ret;
1067c478bd9Sstevel@tonic-gate SM_FILE_T fake;
1077c478bd9Sstevel@tonic-gate unsigned char buf[SM_IO_BUFSIZ];
1087c478bd9Sstevel@tonic-gate extern const char SmFileMagic[];
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate /* copy the important variables */
1117c478bd9Sstevel@tonic-gate fake.sm_magic = SmFileMagic;
1127c478bd9Sstevel@tonic-gate fake.f_timeout = SM_TIME_FOREVER;
1137c478bd9Sstevel@tonic-gate fake.f_timeoutstate = SM_TIME_BLOCK;
1147c478bd9Sstevel@tonic-gate fake.f_flags = fp->f_flags & ~SMNBF;
1157c478bd9Sstevel@tonic-gate fake.f_file = fp->f_file;
1167c478bd9Sstevel@tonic-gate fake.f_cookie = fp->f_cookie;
1177c478bd9Sstevel@tonic-gate fake.f_write = fp->f_write;
1187c478bd9Sstevel@tonic-gate fake.f_close = NULL;
1197c478bd9Sstevel@tonic-gate fake.f_open = NULL;
1207c478bd9Sstevel@tonic-gate fake.f_read = NULL;
1217c478bd9Sstevel@tonic-gate fake.f_seek = NULL;
1227c478bd9Sstevel@tonic-gate fake.f_setinfo = fake.f_getinfo = NULL;
1237c478bd9Sstevel@tonic-gate fake.f_type = "sm_bprintf:fake";
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /* set up the buffer */
1267c478bd9Sstevel@tonic-gate fake.f_bf.smb_base = fake.f_p = buf;
1277c478bd9Sstevel@tonic-gate fake.f_bf.smb_size = fake.f_w = sizeof(buf);
1287c478bd9Sstevel@tonic-gate fake.f_lbfsize = 0; /* not actually used, but Just In Case */
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /* do the work, then copy any error status */
1317c478bd9Sstevel@tonic-gate ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap);
1327c478bd9Sstevel@tonic-gate if (ret >= 0 && sm_io_flush(&fake, SM_TIME_FOREVER))
1337c478bd9Sstevel@tonic-gate ret = SM_IO_EOF; /* errno set by sm_io_flush */
1347c478bd9Sstevel@tonic-gate if (fake.f_flags & SMERR)
1357c478bd9Sstevel@tonic-gate fp->f_flags |= SMERR;
1367c478bd9Sstevel@tonic-gate return ret;
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate #define BUF 40
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate /* Macros for converting digits to letters and vice versa */
1467c478bd9Sstevel@tonic-gate #define to_digit(c) ((c) - '0')
1477c478bd9Sstevel@tonic-gate #define is_digit(c) ((unsigned) to_digit(c) <= 9)
1487c478bd9Sstevel@tonic-gate #define to_char(n) ((char) (n) + '0')
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate /* Flags used during conversion. */
1517c478bd9Sstevel@tonic-gate #define ALT 0x001 /* alternate form */
1527c478bd9Sstevel@tonic-gate #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
1537c478bd9Sstevel@tonic-gate #define LADJUST 0x004 /* left adjustment */
1547c478bd9Sstevel@tonic-gate #define LONGINT 0x010 /* long integer */
1557c478bd9Sstevel@tonic-gate #define QUADINT 0x020 /* quad integer */
1567c478bd9Sstevel@tonic-gate #define SHORTINT 0x040 /* short integer */
1577c478bd9Sstevel@tonic-gate #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
1587c478bd9Sstevel@tonic-gate #define FPT 0x100 /* Floating point number */
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate ** SM_IO_VPRINTF -- performs actual formating for o/p
1627c478bd9Sstevel@tonic-gate **
1637c478bd9Sstevel@tonic-gate ** Parameters:
1647c478bd9Sstevel@tonic-gate ** fp -- file pointer for o/p
1657c478bd9Sstevel@tonic-gate ** timeout -- time to complete the print
1667c478bd9Sstevel@tonic-gate ** fmt0 -- formating directives
1677c478bd9Sstevel@tonic-gate ** ap -- vectors with data units for formating
1687c478bd9Sstevel@tonic-gate **
1697c478bd9Sstevel@tonic-gate ** Results:
1707c478bd9Sstevel@tonic-gate ** Success: number of data units used for formatting
1717c478bd9Sstevel@tonic-gate ** Failure: SM_IO_EOF and sets errno
1727c478bd9Sstevel@tonic-gate */
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate int
sm_io_vfprintf(fp,timeout,fmt0,ap)1757c478bd9Sstevel@tonic-gate sm_io_vfprintf(fp, timeout, fmt0, ap)
1767c478bd9Sstevel@tonic-gate SM_FILE_T *fp;
1777c478bd9Sstevel@tonic-gate int timeout;
1787c478bd9Sstevel@tonic-gate const char *fmt0;
1797c478bd9Sstevel@tonic-gate SM_VA_LOCAL_DECL
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate register char *fmt; /* format string */
1827c478bd9Sstevel@tonic-gate register int ch; /* character from fmt */
1837c478bd9Sstevel@tonic-gate register int n, m, n2; /* handy integers (short term usage) */
1847c478bd9Sstevel@tonic-gate register char *cp; /* handy char pointer (short term usage) */
1857c478bd9Sstevel@tonic-gate register struct sm_iov *iovp;/* for PRINT macro */
1867c478bd9Sstevel@tonic-gate register int flags; /* flags as above */
1877c478bd9Sstevel@tonic-gate int ret; /* return value accumulator */
1887c478bd9Sstevel@tonic-gate int width; /* width from format (%8d), or 0 */
1897c478bd9Sstevel@tonic-gate int prec; /* precision from format (%.3d), or -1 */
1907c478bd9Sstevel@tonic-gate char sign; /* sign prefix (' ', '+', '-', or \0) */
1917c478bd9Sstevel@tonic-gate wchar_t wc;
1927c478bd9Sstevel@tonic-gate ULONGLONG_T _uquad; /* integer arguments %[diouxX] */
1937c478bd9Sstevel@tonic-gate enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
1947c478bd9Sstevel@tonic-gate int dprec; /* a copy of prec if [diouxX], 0 otherwise */
1957c478bd9Sstevel@tonic-gate int realsz; /* field size expanded by dprec */
1967c478bd9Sstevel@tonic-gate int size; /* size of converted field or string */
1977c478bd9Sstevel@tonic-gate char *xdigs="0123456789abcdef"; /* digits for [xX] conversion */
1987c478bd9Sstevel@tonic-gate #define NIOV 8
1997c478bd9Sstevel@tonic-gate struct sm_uio uio; /* output information: summary */
2007c478bd9Sstevel@tonic-gate struct sm_iov iov[NIOV];/* ... and individual io vectors */
2017c478bd9Sstevel@tonic-gate char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
2027c478bd9Sstevel@tonic-gate char ox[2]; /* space for 0x hex-prefix */
2037c478bd9Sstevel@tonic-gate va_list *argtable; /* args, built due to positional arg */
2047c478bd9Sstevel@tonic-gate va_list statargtable[STATIC_ARG_TBL_SIZE];
2057c478bd9Sstevel@tonic-gate int nextarg; /* 1-based argument index */
2067c478bd9Sstevel@tonic-gate va_list orgap; /* original argument pointer */
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate ** Choose PADSIZE to trade efficiency vs. size. If larger printf
2107c478bd9Sstevel@tonic-gate ** fields occur frequently, increase PADSIZE and make the initialisers
2117c478bd9Sstevel@tonic-gate ** below longer.
2127c478bd9Sstevel@tonic-gate */
2137c478bd9Sstevel@tonic-gate #define PADSIZE 16 /* pad chunk size */
2147c478bd9Sstevel@tonic-gate static char blanks[PADSIZE] =
2157c478bd9Sstevel@tonic-gate {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
2167c478bd9Sstevel@tonic-gate static char zeroes[PADSIZE] =
2177c478bd9Sstevel@tonic-gate {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate ** BEWARE, these `goto error' on error, and PAD uses `n'.
2217c478bd9Sstevel@tonic-gate */
2227c478bd9Sstevel@tonic-gate #define PRINT(ptr, len) do { \
2237c478bd9Sstevel@tonic-gate iovp->iov_base = (ptr); \
2247c478bd9Sstevel@tonic-gate iovp->iov_len = (len); \
2257c478bd9Sstevel@tonic-gate uio.uio_resid += (len); \
2267c478bd9Sstevel@tonic-gate iovp++; \
2277c478bd9Sstevel@tonic-gate if (++uio.uio_iovcnt >= NIOV) \
2287c478bd9Sstevel@tonic-gate { \
2297c478bd9Sstevel@tonic-gate if (sm_print(fp, timeout, &uio)) \
2307c478bd9Sstevel@tonic-gate goto error; \
2317c478bd9Sstevel@tonic-gate iovp = iov; \
2327c478bd9Sstevel@tonic-gate } \
2337c478bd9Sstevel@tonic-gate } while (0)
2347c478bd9Sstevel@tonic-gate #define PAD(howmany, with) do \
2357c478bd9Sstevel@tonic-gate { \
2367c478bd9Sstevel@tonic-gate if ((n = (howmany)) > 0) \
2377c478bd9Sstevel@tonic-gate { \
2387c478bd9Sstevel@tonic-gate while (n > PADSIZE) { \
2397c478bd9Sstevel@tonic-gate PRINT(with, PADSIZE); \
2407c478bd9Sstevel@tonic-gate n -= PADSIZE; \
2417c478bd9Sstevel@tonic-gate } \
2427c478bd9Sstevel@tonic-gate PRINT(with, n); \
2437c478bd9Sstevel@tonic-gate } \
2447c478bd9Sstevel@tonic-gate } while (0)
2457c478bd9Sstevel@tonic-gate #define FLUSH() do \
2467c478bd9Sstevel@tonic-gate { \
2477c478bd9Sstevel@tonic-gate if (uio.uio_resid && sm_print(fp, timeout, &uio)) \
2487c478bd9Sstevel@tonic-gate goto error; \
2497c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 0; \
2507c478bd9Sstevel@tonic-gate iovp = iov; \
2517c478bd9Sstevel@tonic-gate } while (0)
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate ** To extend shorts properly, we need both signed and unsigned
2557c478bd9Sstevel@tonic-gate ** argument extraction methods.
2567c478bd9Sstevel@tonic-gate */
2577c478bd9Sstevel@tonic-gate #define SARG() \
2587c478bd9Sstevel@tonic-gate (flags&QUADINT ? SM_VA_ARG(ap, LONGLONG_T) : \
2597c478bd9Sstevel@tonic-gate flags&LONGINT ? GETARG(long) : \
2607c478bd9Sstevel@tonic-gate flags&SHORTINT ? (long) (short) GETARG(int) : \
2617c478bd9Sstevel@tonic-gate (long) GETARG(int))
2627c478bd9Sstevel@tonic-gate #define UARG() \
2637c478bd9Sstevel@tonic-gate (flags&QUADINT ? SM_VA_ARG(ap, ULONGLONG_T) : \
2647c478bd9Sstevel@tonic-gate flags&LONGINT ? GETARG(unsigned long) : \
2657c478bd9Sstevel@tonic-gate flags&SHORTINT ? (unsigned long) (unsigned short) GETARG(int) : \
2667c478bd9Sstevel@tonic-gate (unsigned long) GETARG(unsigned int))
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate /*
2697c478bd9Sstevel@tonic-gate ** Get * arguments, including the form *nn$. Preserve the nextarg
2707c478bd9Sstevel@tonic-gate ** that the argument can be gotten once the type is determined.
2717c478bd9Sstevel@tonic-gate */
2727c478bd9Sstevel@tonic-gate #define GETASTER(val) \
2737c478bd9Sstevel@tonic-gate n2 = 0; \
2747c478bd9Sstevel@tonic-gate cp = fmt; \
2757c478bd9Sstevel@tonic-gate while (is_digit(*cp)) \
2767c478bd9Sstevel@tonic-gate { \
2777c478bd9Sstevel@tonic-gate n2 = 10 * n2 + to_digit(*cp); \
2787c478bd9Sstevel@tonic-gate cp++; \
2797c478bd9Sstevel@tonic-gate } \
2807c478bd9Sstevel@tonic-gate if (*cp == '$') \
2817c478bd9Sstevel@tonic-gate { \
2827c478bd9Sstevel@tonic-gate int hold = nextarg; \
2837c478bd9Sstevel@tonic-gate if (argtable == NULL) \
2847c478bd9Sstevel@tonic-gate { \
2857c478bd9Sstevel@tonic-gate argtable = statargtable; \
2867c478bd9Sstevel@tonic-gate sm_find_arguments(fmt0, orgap, &argtable); \
2877c478bd9Sstevel@tonic-gate } \
2887c478bd9Sstevel@tonic-gate nextarg = n2; \
2897c478bd9Sstevel@tonic-gate val = GETARG(int); \
2907c478bd9Sstevel@tonic-gate nextarg = hold; \
2917c478bd9Sstevel@tonic-gate fmt = ++cp; \
2927c478bd9Sstevel@tonic-gate } \
2937c478bd9Sstevel@tonic-gate else \
2947c478bd9Sstevel@tonic-gate { \
2957c478bd9Sstevel@tonic-gate val = GETARG(int); \
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate ** Get the argument indexed by nextarg. If the argument table is
3007c478bd9Sstevel@tonic-gate ** built, use it to get the argument. If its not, get the next
3017c478bd9Sstevel@tonic-gate ** argument (and arguments must be gotten sequentially).
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate #if SM_VA_STD
3057c478bd9Sstevel@tonic-gate # define GETARG(type) \
3067c478bd9Sstevel@tonic-gate (((argtable != NULL) ? (void) (ap = argtable[nextarg]) : (void) 0), \
3077c478bd9Sstevel@tonic-gate nextarg++, SM_VA_ARG(ap, type))
3087c478bd9Sstevel@tonic-gate #else /* SM_VA_STD */
3097c478bd9Sstevel@tonic-gate # define GETARG(type) \
3107c478bd9Sstevel@tonic-gate ((argtable != NULL) ? (*((type*)(argtable[nextarg++]))) : \
3117c478bd9Sstevel@tonic-gate (nextarg++, SM_VA_ARG(ap, type)))
3127c478bd9Sstevel@tonic-gate #endif /* SM_VA_STD */
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /* sorry, fprintf(read_only_file, "") returns SM_IO_EOF, not 0 */
3157c478bd9Sstevel@tonic-gate if (cantwrite(fp))
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate errno = EBADF;
3187c478bd9Sstevel@tonic-gate return SM_IO_EOF;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /* optimise fprintf(stderr) (and other unbuffered Unix files) */
3227c478bd9Sstevel@tonic-gate if ((fp->f_flags & (SMNBF|SMWR|SMRW)) == (SMNBF|SMWR) &&
3237c478bd9Sstevel@tonic-gate fp->f_file >= 0)
3247c478bd9Sstevel@tonic-gate return sm_bprintf(fp, fmt0, ap);
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate fmt = (char *) fmt0;
3277c478bd9Sstevel@tonic-gate argtable = NULL;
3287c478bd9Sstevel@tonic-gate nextarg = 1;
3297c478bd9Sstevel@tonic-gate SM_VA_COPY(orgap, ap);
3307c478bd9Sstevel@tonic-gate uio.uio_iov = iovp = iov;
3317c478bd9Sstevel@tonic-gate uio.uio_resid = 0;
3327c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 0;
3337c478bd9Sstevel@tonic-gate ret = 0;
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /* Scan the format for conversions (`%' character). */
3367c478bd9Sstevel@tonic-gate for (;;)
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate cp = fmt;
3397c478bd9Sstevel@tonic-gate n = 0;
3407c478bd9Sstevel@tonic-gate while ((wc = *fmt) != '\0')
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate if (wc == '%')
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate n = 1;
3457c478bd9Sstevel@tonic-gate break;
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate fmt++;
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate if ((m = fmt - cp) != 0)
3507c478bd9Sstevel@tonic-gate {
3517c478bd9Sstevel@tonic-gate PRINT(cp, m);
3527c478bd9Sstevel@tonic-gate ret += m;
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate if (n <= 0)
3557c478bd9Sstevel@tonic-gate goto done;
3567c478bd9Sstevel@tonic-gate fmt++; /* skip over '%' */
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate flags = 0;
3597c478bd9Sstevel@tonic-gate dprec = 0;
3607c478bd9Sstevel@tonic-gate width = 0;
3617c478bd9Sstevel@tonic-gate prec = -1;
3627c478bd9Sstevel@tonic-gate sign = '\0';
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate rflag: ch = *fmt++;
3657c478bd9Sstevel@tonic-gate reswitch: switch (ch)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate case ' ':
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate ** ``If the space and + flags both appear, the space
3717c478bd9Sstevel@tonic-gate ** flag will be ignored.''
3727c478bd9Sstevel@tonic-gate ** -- ANSI X3J11
3737c478bd9Sstevel@tonic-gate */
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate if (!sign)
3767c478bd9Sstevel@tonic-gate sign = ' ';
3777c478bd9Sstevel@tonic-gate goto rflag;
3787c478bd9Sstevel@tonic-gate case '#':
3797c478bd9Sstevel@tonic-gate flags |= ALT;
3807c478bd9Sstevel@tonic-gate goto rflag;
3817c478bd9Sstevel@tonic-gate case '*':
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate ** ``A negative field width argument is taken as a
3857c478bd9Sstevel@tonic-gate ** - flag followed by a positive field width.''
3867c478bd9Sstevel@tonic-gate ** -- ANSI X3J11
3877c478bd9Sstevel@tonic-gate ** They don't exclude field widths read from args.
3887c478bd9Sstevel@tonic-gate */
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate GETASTER(width);
3917c478bd9Sstevel@tonic-gate if (width >= 0)
3927c478bd9Sstevel@tonic-gate goto rflag;
3937c478bd9Sstevel@tonic-gate width = -width;
3947c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
3957c478bd9Sstevel@tonic-gate case '-':
3967c478bd9Sstevel@tonic-gate flags |= LADJUST;
3977c478bd9Sstevel@tonic-gate goto rflag;
3987c478bd9Sstevel@tonic-gate case '+':
3997c478bd9Sstevel@tonic-gate sign = '+';
4007c478bd9Sstevel@tonic-gate goto rflag;
4017c478bd9Sstevel@tonic-gate case '.':
4027c478bd9Sstevel@tonic-gate if ((ch = *fmt++) == '*')
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate GETASTER(n);
4057c478bd9Sstevel@tonic-gate prec = n < 0 ? -1 : n;
4067c478bd9Sstevel@tonic-gate goto rflag;
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate n = 0;
4097c478bd9Sstevel@tonic-gate while (is_digit(ch))
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate n = 10 * n + to_digit(ch);
4127c478bd9Sstevel@tonic-gate ch = *fmt++;
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate if (ch == '$')
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate nextarg = n;
4177c478bd9Sstevel@tonic-gate if (argtable == NULL)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate argtable = statargtable;
4207c478bd9Sstevel@tonic-gate sm_find_arguments(fmt0, orgap,
4217c478bd9Sstevel@tonic-gate &argtable);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate goto rflag;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate prec = n < 0 ? -1 : n;
4267c478bd9Sstevel@tonic-gate goto reswitch;
4277c478bd9Sstevel@tonic-gate case '0':
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate ** ``Note that 0 is taken as a flag, not as the
4317c478bd9Sstevel@tonic-gate ** beginning of a field width.''
4327c478bd9Sstevel@tonic-gate ** -- ANSI X3J11
4337c478bd9Sstevel@tonic-gate */
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate flags |= ZEROPAD;
4367c478bd9Sstevel@tonic-gate goto rflag;
4377c478bd9Sstevel@tonic-gate case '1': case '2': case '3': case '4':
4387c478bd9Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9':
4397c478bd9Sstevel@tonic-gate n = 0;
4407c478bd9Sstevel@tonic-gate do
4417c478bd9Sstevel@tonic-gate {
4427c478bd9Sstevel@tonic-gate n = 10 * n + to_digit(ch);
4437c478bd9Sstevel@tonic-gate ch = *fmt++;
4447c478bd9Sstevel@tonic-gate } while (is_digit(ch));
4457c478bd9Sstevel@tonic-gate if (ch == '$')
4467c478bd9Sstevel@tonic-gate {
4477c478bd9Sstevel@tonic-gate nextarg = n;
4487c478bd9Sstevel@tonic-gate if (argtable == NULL)
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate argtable = statargtable;
4517c478bd9Sstevel@tonic-gate sm_find_arguments(fmt0, orgap,
4527c478bd9Sstevel@tonic-gate &argtable);
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate goto rflag;
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate width = n;
4577c478bd9Sstevel@tonic-gate goto reswitch;
4587c478bd9Sstevel@tonic-gate case 'h':
4597c478bd9Sstevel@tonic-gate flags |= SHORTINT;
4607c478bd9Sstevel@tonic-gate goto rflag;
4617c478bd9Sstevel@tonic-gate case 'l':
4627c478bd9Sstevel@tonic-gate if (*fmt == 'l')
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate fmt++;
4657c478bd9Sstevel@tonic-gate flags |= QUADINT;
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate else
4687c478bd9Sstevel@tonic-gate {
4697c478bd9Sstevel@tonic-gate flags |= LONGINT;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate goto rflag;
4727c478bd9Sstevel@tonic-gate case 'q':
4737c478bd9Sstevel@tonic-gate flags |= QUADINT;
4747c478bd9Sstevel@tonic-gate goto rflag;
4757c478bd9Sstevel@tonic-gate case 'c':
4767c478bd9Sstevel@tonic-gate *(cp = buf) = GETARG(int);
4777c478bd9Sstevel@tonic-gate size = 1;
4787c478bd9Sstevel@tonic-gate sign = '\0';
4797c478bd9Sstevel@tonic-gate break;
4807c478bd9Sstevel@tonic-gate case 'D':
4817c478bd9Sstevel@tonic-gate flags |= LONGINT;
4827c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
4837c478bd9Sstevel@tonic-gate case 'd':
4847c478bd9Sstevel@tonic-gate case 'i':
4857c478bd9Sstevel@tonic-gate _uquad = SARG();
4867c478bd9Sstevel@tonic-gate if ((LONGLONG_T) _uquad < 0)
4877c478bd9Sstevel@tonic-gate {
4887c478bd9Sstevel@tonic-gate _uquad = -(LONGLONG_T) _uquad;
4897c478bd9Sstevel@tonic-gate sign = '-';
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate base = DEC;
4927c478bd9Sstevel@tonic-gate goto number;
4937c478bd9Sstevel@tonic-gate case 'e':
4947c478bd9Sstevel@tonic-gate case 'E':
4957c478bd9Sstevel@tonic-gate case 'f':
4967c478bd9Sstevel@tonic-gate case 'g':
4977c478bd9Sstevel@tonic-gate case 'G':
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate double val;
5007c478bd9Sstevel@tonic-gate char *p;
5017c478bd9Sstevel@tonic-gate char fmt[16];
5027c478bd9Sstevel@tonic-gate char out[150];
5037c478bd9Sstevel@tonic-gate size_t len;
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate ** This code implements floating point output
5077c478bd9Sstevel@tonic-gate ** in the most portable manner possible,
5087c478bd9Sstevel@tonic-gate ** relying only on 'sprintf' as defined by
5097c478bd9Sstevel@tonic-gate ** the 1989 ANSI C standard.
5107c478bd9Sstevel@tonic-gate ** We silently cap width and precision
5117c478bd9Sstevel@tonic-gate ** at 120, to avoid buffer overflow.
5127c478bd9Sstevel@tonic-gate */
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate val = GETARG(double);
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate p = fmt;
5177c478bd9Sstevel@tonic-gate *p++ = '%';
5187c478bd9Sstevel@tonic-gate if (sign)
5197c478bd9Sstevel@tonic-gate *p++ = sign;
5207c478bd9Sstevel@tonic-gate if (flags & ALT)
5217c478bd9Sstevel@tonic-gate *p++ = '#';
5227c478bd9Sstevel@tonic-gate if (flags & LADJUST)
5237c478bd9Sstevel@tonic-gate *p++ = '-';
5247c478bd9Sstevel@tonic-gate if (flags & ZEROPAD)
5257c478bd9Sstevel@tonic-gate *p++ = '0';
5267c478bd9Sstevel@tonic-gate *p++ = '*';
5277c478bd9Sstevel@tonic-gate if (prec >= 0)
5287c478bd9Sstevel@tonic-gate {
5297c478bd9Sstevel@tonic-gate *p++ = '.';
5307c478bd9Sstevel@tonic-gate *p++ = '*';
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate *p++ = ch;
5337c478bd9Sstevel@tonic-gate *p = '\0';
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate if (width > 120)
5367c478bd9Sstevel@tonic-gate width = 120;
5377c478bd9Sstevel@tonic-gate if (prec > 120)
5387c478bd9Sstevel@tonic-gate prec = 120;
5397c478bd9Sstevel@tonic-gate if (prec >= 0)
540*49218d4fSjbeck #if HASSNPRINTF
541*49218d4fSjbeck snprintf(out, sizeof(out), fmt, width,
542*49218d4fSjbeck prec, val);
543*49218d4fSjbeck #else /* HASSNPRINTF */
5447c478bd9Sstevel@tonic-gate sprintf(out, fmt, width, prec, val);
545*49218d4fSjbeck #endif /* HASSNPRINTF */
5467c478bd9Sstevel@tonic-gate else
547*49218d4fSjbeck #if HASSNPRINTF
548*49218d4fSjbeck snprintf(out, sizeof(out), fmt, width,
549*49218d4fSjbeck val);
550*49218d4fSjbeck #else /* HASSNPRINTF */
5517c478bd9Sstevel@tonic-gate sprintf(out, fmt, width, val);
552*49218d4fSjbeck #endif /* HASSNPRINTF */
5537c478bd9Sstevel@tonic-gate len = strlen(out);
5547c478bd9Sstevel@tonic-gate PRINT(out, len);
5557c478bd9Sstevel@tonic-gate FLUSH();
5567c478bd9Sstevel@tonic-gate continue;
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate case 'n':
5597c478bd9Sstevel@tonic-gate if (flags & QUADINT)
5607c478bd9Sstevel@tonic-gate *GETARG(LONGLONG_T *) = ret;
5617c478bd9Sstevel@tonic-gate else if (flags & LONGINT)
5627c478bd9Sstevel@tonic-gate *GETARG(long *) = ret;
5637c478bd9Sstevel@tonic-gate else if (flags & SHORTINT)
5647c478bd9Sstevel@tonic-gate *GETARG(short *) = ret;
5657c478bd9Sstevel@tonic-gate else
5667c478bd9Sstevel@tonic-gate *GETARG(int *) = ret;
5677c478bd9Sstevel@tonic-gate continue; /* no output */
5687c478bd9Sstevel@tonic-gate case 'O':
5697c478bd9Sstevel@tonic-gate flags |= LONGINT;
5707c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
5717c478bd9Sstevel@tonic-gate case 'o':
5727c478bd9Sstevel@tonic-gate _uquad = UARG();
5737c478bd9Sstevel@tonic-gate base = OCT;
5747c478bd9Sstevel@tonic-gate goto nosign;
5757c478bd9Sstevel@tonic-gate case 'p':
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /*
5787c478bd9Sstevel@tonic-gate ** ``The argument shall be a pointer to void. The
5797c478bd9Sstevel@tonic-gate ** value of the pointer is converted to a sequence
5807c478bd9Sstevel@tonic-gate ** of printable characters, in an implementation-
5817c478bd9Sstevel@tonic-gate ** defined manner.''
5827c478bd9Sstevel@tonic-gate ** -- ANSI X3J11
5837c478bd9Sstevel@tonic-gate */
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate /* NOSTRICT */
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate union
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate void *p;
5907c478bd9Sstevel@tonic-gate ULONGLONG_T ll;
5917c478bd9Sstevel@tonic-gate unsigned long l;
5927c478bd9Sstevel@tonic-gate unsigned i;
5937c478bd9Sstevel@tonic-gate } u;
5947c478bd9Sstevel@tonic-gate u.p = GETARG(void *);
5957c478bd9Sstevel@tonic-gate if (sizeof(void *) == sizeof(ULONGLONG_T))
5967c478bd9Sstevel@tonic-gate _uquad = u.ll;
5977c478bd9Sstevel@tonic-gate else if (sizeof(void *) == sizeof(long))
5987c478bd9Sstevel@tonic-gate _uquad = u.l;
5997c478bd9Sstevel@tonic-gate else
6007c478bd9Sstevel@tonic-gate _uquad = u.i;
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate base = HEX;
6037c478bd9Sstevel@tonic-gate xdigs = "0123456789abcdef";
6047c478bd9Sstevel@tonic-gate flags |= HEXPREFIX;
6057c478bd9Sstevel@tonic-gate ch = 'x';
6067c478bd9Sstevel@tonic-gate goto nosign;
6077c478bd9Sstevel@tonic-gate case 's':
6087c478bd9Sstevel@tonic-gate if ((cp = GETARG(char *)) == NULL)
6097c478bd9Sstevel@tonic-gate cp = "(null)";
6107c478bd9Sstevel@tonic-gate if (prec >= 0)
6117c478bd9Sstevel@tonic-gate {
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate ** can't use strlen; can only look for the
6147c478bd9Sstevel@tonic-gate ** NUL in the first `prec' characters, and
6157c478bd9Sstevel@tonic-gate ** strlen() will go further.
6167c478bd9Sstevel@tonic-gate */
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate char *p = memchr(cp, 0, prec);
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate if (p != NULL)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate size = p - cp;
6237c478bd9Sstevel@tonic-gate if (size > prec)
6247c478bd9Sstevel@tonic-gate size = prec;
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate else
6277c478bd9Sstevel@tonic-gate size = prec;
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate else
6307c478bd9Sstevel@tonic-gate size = strlen(cp);
6317c478bd9Sstevel@tonic-gate sign = '\0';
6327c478bd9Sstevel@tonic-gate break;
6337c478bd9Sstevel@tonic-gate case 'U':
6347c478bd9Sstevel@tonic-gate flags |= LONGINT;
6357c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
6367c478bd9Sstevel@tonic-gate case 'u':
6377c478bd9Sstevel@tonic-gate _uquad = UARG();
6387c478bd9Sstevel@tonic-gate base = DEC;
6397c478bd9Sstevel@tonic-gate goto nosign;
6407c478bd9Sstevel@tonic-gate case 'X':
6417c478bd9Sstevel@tonic-gate xdigs = "0123456789ABCDEF";
6427c478bd9Sstevel@tonic-gate goto hex;
6437c478bd9Sstevel@tonic-gate case 'x':
6447c478bd9Sstevel@tonic-gate xdigs = "0123456789abcdef";
6457c478bd9Sstevel@tonic-gate hex: _uquad = UARG();
6467c478bd9Sstevel@tonic-gate base = HEX;
6477c478bd9Sstevel@tonic-gate /* leading 0x/X only if non-zero */
6487c478bd9Sstevel@tonic-gate if (flags & ALT && _uquad != 0)
6497c478bd9Sstevel@tonic-gate flags |= HEXPREFIX;
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate /* unsigned conversions */
6527c478bd9Sstevel@tonic-gate nosign: sign = '\0';
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate /*
6557c478bd9Sstevel@tonic-gate ** ``... diouXx conversions ... if a precision is
6567c478bd9Sstevel@tonic-gate ** specified, the 0 flag will be ignored.''
6577c478bd9Sstevel@tonic-gate ** -- ANSI X3J11
6587c478bd9Sstevel@tonic-gate */
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate number: if ((dprec = prec) >= 0)
6617c478bd9Sstevel@tonic-gate flags &= ~ZEROPAD;
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate /*
6647c478bd9Sstevel@tonic-gate ** ``The result of converting a zero value with an
6657c478bd9Sstevel@tonic-gate ** explicit precision of zero is no characters.''
6667c478bd9Sstevel@tonic-gate ** -- ANSI X3J11
6677c478bd9Sstevel@tonic-gate */
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate cp = buf + BUF;
6707c478bd9Sstevel@tonic-gate if (_uquad != 0 || prec != 0)
6717c478bd9Sstevel@tonic-gate {
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate ** Unsigned mod is hard, and unsigned mod
6747c478bd9Sstevel@tonic-gate ** by a constant is easier than that by
6757c478bd9Sstevel@tonic-gate ** a variable; hence this switch.
6767c478bd9Sstevel@tonic-gate */
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate switch (base)
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate case OCT:
6817c478bd9Sstevel@tonic-gate do
6827c478bd9Sstevel@tonic-gate {
6837c478bd9Sstevel@tonic-gate *--cp = to_char(_uquad & 7);
6847c478bd9Sstevel@tonic-gate _uquad >>= 3;
6857c478bd9Sstevel@tonic-gate } while (_uquad);
6867c478bd9Sstevel@tonic-gate /* handle octal leading 0 */
6877c478bd9Sstevel@tonic-gate if (flags & ALT && *cp != '0')
6887c478bd9Sstevel@tonic-gate *--cp = '0';
6897c478bd9Sstevel@tonic-gate break;
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate case DEC:
6927c478bd9Sstevel@tonic-gate /* many numbers are 1 digit */
6937c478bd9Sstevel@tonic-gate while (_uquad >= 10)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate *--cp = to_char(_uquad % 10);
6967c478bd9Sstevel@tonic-gate _uquad /= 10;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate *--cp = to_char(_uquad);
6997c478bd9Sstevel@tonic-gate break;
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate case HEX:
7027c478bd9Sstevel@tonic-gate do
7037c478bd9Sstevel@tonic-gate {
7047c478bd9Sstevel@tonic-gate *--cp = xdigs[_uquad & 15];
7057c478bd9Sstevel@tonic-gate _uquad >>= 4;
7067c478bd9Sstevel@tonic-gate } while (_uquad);
7077c478bd9Sstevel@tonic-gate break;
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate default:
7107c478bd9Sstevel@tonic-gate cp = "bug in sm_io_vfprintf: bad base";
7117c478bd9Sstevel@tonic-gate size = strlen(cp);
7127c478bd9Sstevel@tonic-gate goto skipsize;
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate size = buf + BUF - cp;
7167c478bd9Sstevel@tonic-gate skipsize:
7177c478bd9Sstevel@tonic-gate break;
7187c478bd9Sstevel@tonic-gate default: /* "%?" prints ?, unless ? is NUL */
7197c478bd9Sstevel@tonic-gate if (ch == '\0')
7207c478bd9Sstevel@tonic-gate goto done;
7217c478bd9Sstevel@tonic-gate /* pretend it was %c with argument ch */
7227c478bd9Sstevel@tonic-gate cp = buf;
7237c478bd9Sstevel@tonic-gate *cp = ch;
7247c478bd9Sstevel@tonic-gate size = 1;
7257c478bd9Sstevel@tonic-gate sign = '\0';
7267c478bd9Sstevel@tonic-gate break;
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate /*
7307c478bd9Sstevel@tonic-gate ** All reasonable formats wind up here. At this point, `cp'
7317c478bd9Sstevel@tonic-gate ** points to a string which (if not flags&LADJUST) should be
7327c478bd9Sstevel@tonic-gate ** padded out to `width' places. If flags&ZEROPAD, it should
7337c478bd9Sstevel@tonic-gate ** first be prefixed by any sign or other prefix; otherwise,
7347c478bd9Sstevel@tonic-gate ** it should be blank padded before the prefix is emitted.
7357c478bd9Sstevel@tonic-gate ** After any left-hand padding and prefixing, emit zeroes
7367c478bd9Sstevel@tonic-gate ** required by a decimal [diouxX] precision, then print the
7377c478bd9Sstevel@tonic-gate ** string proper, then emit zeroes required by any leftover
7387c478bd9Sstevel@tonic-gate ** floating precision; finally, if LADJUST, pad with blanks.
7397c478bd9Sstevel@tonic-gate **
7407c478bd9Sstevel@tonic-gate ** Compute actual size, so we know how much to pad.
7417c478bd9Sstevel@tonic-gate ** size excludes decimal prec; realsz includes it.
7427c478bd9Sstevel@tonic-gate */
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate realsz = dprec > size ? dprec : size;
7457c478bd9Sstevel@tonic-gate if (sign)
7467c478bd9Sstevel@tonic-gate realsz++;
7477c478bd9Sstevel@tonic-gate else if (flags & HEXPREFIX)
7487c478bd9Sstevel@tonic-gate realsz+= 2;
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate /* right-adjusting blank padding */
7517c478bd9Sstevel@tonic-gate if ((flags & (LADJUST|ZEROPAD)) == 0)
7527c478bd9Sstevel@tonic-gate PAD(width - realsz, blanks);
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /* prefix */
7557c478bd9Sstevel@tonic-gate if (sign)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate PRINT(&sign, 1);
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate else if (flags & HEXPREFIX)
7607c478bd9Sstevel@tonic-gate {
7617c478bd9Sstevel@tonic-gate ox[0] = '0';
7627c478bd9Sstevel@tonic-gate ox[1] = ch;
7637c478bd9Sstevel@tonic-gate PRINT(ox, 2);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate /* right-adjusting zero padding */
7677c478bd9Sstevel@tonic-gate if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
7687c478bd9Sstevel@tonic-gate PAD(width - realsz, zeroes);
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate /* leading zeroes from decimal precision */
7717c478bd9Sstevel@tonic-gate PAD(dprec - size, zeroes);
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate /* the string or number proper */
7747c478bd9Sstevel@tonic-gate PRINT(cp, size);
7757c478bd9Sstevel@tonic-gate /* left-adjusting padding (always blank) */
7767c478bd9Sstevel@tonic-gate if (flags & LADJUST)
7777c478bd9Sstevel@tonic-gate PAD(width - realsz, blanks);
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate /* finally, adjust ret */
7807c478bd9Sstevel@tonic-gate ret += width > realsz ? width : realsz;
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate FLUSH(); /* copy out the I/O vectors */
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate done:
7857c478bd9Sstevel@tonic-gate FLUSH();
7867c478bd9Sstevel@tonic-gate error:
7877c478bd9Sstevel@tonic-gate if ((argtable != NULL) && (argtable != statargtable))
7887c478bd9Sstevel@tonic-gate sm_free(argtable);
7897c478bd9Sstevel@tonic-gate return sm_error(fp) ? SM_IO_EOF : ret;
7907c478bd9Sstevel@tonic-gate /* NOTREACHED */
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate /* Type ids for argument type table. */
7947c478bd9Sstevel@tonic-gate #define T_UNUSED 0
7957c478bd9Sstevel@tonic-gate #define T_SHORT 1
7967c478bd9Sstevel@tonic-gate #define T_U_SHORT 2
7977c478bd9Sstevel@tonic-gate #define TP_SHORT 3
7987c478bd9Sstevel@tonic-gate #define T_INT 4
7997c478bd9Sstevel@tonic-gate #define T_U_INT 5
8007c478bd9Sstevel@tonic-gate #define TP_INT 6
8017c478bd9Sstevel@tonic-gate #define T_LONG 7
8027c478bd9Sstevel@tonic-gate #define T_U_LONG 8
8037c478bd9Sstevel@tonic-gate #define TP_LONG 9
8047c478bd9Sstevel@tonic-gate #define T_QUAD 10
8057c478bd9Sstevel@tonic-gate #define T_U_QUAD 11
8067c478bd9Sstevel@tonic-gate #define TP_QUAD 12
8077c478bd9Sstevel@tonic-gate #define T_DOUBLE 13
8087c478bd9Sstevel@tonic-gate #define TP_CHAR 15
8097c478bd9Sstevel@tonic-gate #define TP_VOID 16
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate ** SM_FIND_ARGUMENTS -- find all args when a positional parameter is found.
8137c478bd9Sstevel@tonic-gate **
8147c478bd9Sstevel@tonic-gate ** Find all arguments when a positional parameter is encountered. Returns a
8157c478bd9Sstevel@tonic-gate ** table, indexed by argument number, of pointers to each arguments. The
8167c478bd9Sstevel@tonic-gate ** initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
8177c478bd9Sstevel@tonic-gate ** It will be replaced with a malloc-ed one if it overflows.
8187c478bd9Sstevel@tonic-gate **
8197c478bd9Sstevel@tonic-gate ** Parameters:
8207c478bd9Sstevel@tonic-gate ** fmt0 -- formating directives
8217c478bd9Sstevel@tonic-gate ** ap -- vector list of data unit for formating consumption
8227c478bd9Sstevel@tonic-gate ** argtable -- an indexable table (returned) of 'ap'
8237c478bd9Sstevel@tonic-gate **
8247c478bd9Sstevel@tonic-gate ** Results:
8257c478bd9Sstevel@tonic-gate ** none.
8267c478bd9Sstevel@tonic-gate */
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate static void
sm_find_arguments(fmt0,ap,argtable)8297c478bd9Sstevel@tonic-gate sm_find_arguments(fmt0, ap, argtable)
8307c478bd9Sstevel@tonic-gate const char *fmt0;
8317c478bd9Sstevel@tonic-gate SM_VA_LOCAL_DECL
8327c478bd9Sstevel@tonic-gate va_list **argtable;
8337c478bd9Sstevel@tonic-gate {
8347c478bd9Sstevel@tonic-gate register char *fmt; /* format string */
8357c478bd9Sstevel@tonic-gate register int ch; /* character from fmt */
8367c478bd9Sstevel@tonic-gate register int n, n2; /* handy integer (short term usage) */
8377c478bd9Sstevel@tonic-gate register char *cp; /* handy char pointer (short term usage) */
8387c478bd9Sstevel@tonic-gate register int flags; /* flags as above */
8397c478bd9Sstevel@tonic-gate unsigned char *typetable; /* table of types */
8407c478bd9Sstevel@tonic-gate unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
8417c478bd9Sstevel@tonic-gate int tablesize; /* current size of type table */
8427c478bd9Sstevel@tonic-gate int tablemax; /* largest used index in table */
8437c478bd9Sstevel@tonic-gate int nextarg; /* 1-based argument index */
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate /* Add an argument type to the table, expanding if necessary. */
8467c478bd9Sstevel@tonic-gate #define ADDTYPE(type) \
8477c478bd9Sstevel@tonic-gate ((nextarg >= tablesize) ? \
8487c478bd9Sstevel@tonic-gate (sm_grow_type_table_x(&typetable, &tablesize), 0) : 0, \
8497c478bd9Sstevel@tonic-gate typetable[nextarg++] = type, \
8507c478bd9Sstevel@tonic-gate (nextarg > tablemax) ? tablemax = nextarg : 0)
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate #define ADDSARG() \
8537c478bd9Sstevel@tonic-gate ((flags & LONGINT) ? ADDTYPE(T_LONG) : \
8547c478bd9Sstevel@tonic-gate ((flags & SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate #define ADDUARG() \
8577c478bd9Sstevel@tonic-gate ((flags & LONGINT) ? ADDTYPE(T_U_LONG) : \
8587c478bd9Sstevel@tonic-gate ((flags & SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate /* Add * arguments to the type array. */
8617c478bd9Sstevel@tonic-gate #define ADDASTER() \
8627c478bd9Sstevel@tonic-gate n2 = 0; \
8637c478bd9Sstevel@tonic-gate cp = fmt; \
8647c478bd9Sstevel@tonic-gate while (is_digit(*cp)) \
8657c478bd9Sstevel@tonic-gate { \
8667c478bd9Sstevel@tonic-gate n2 = 10 * n2 + to_digit(*cp); \
8677c478bd9Sstevel@tonic-gate cp++; \
8687c478bd9Sstevel@tonic-gate } \
8697c478bd9Sstevel@tonic-gate if (*cp == '$') \
8707c478bd9Sstevel@tonic-gate { \
8717c478bd9Sstevel@tonic-gate int hold = nextarg; \
8727c478bd9Sstevel@tonic-gate nextarg = n2; \
8737c478bd9Sstevel@tonic-gate ADDTYPE (T_INT); \
8747c478bd9Sstevel@tonic-gate nextarg = hold; \
8757c478bd9Sstevel@tonic-gate fmt = ++cp; \
8767c478bd9Sstevel@tonic-gate } \
8777c478bd9Sstevel@tonic-gate else \
8787c478bd9Sstevel@tonic-gate { \
8797c478bd9Sstevel@tonic-gate ADDTYPE (T_INT); \
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate fmt = (char *) fmt0;
8827c478bd9Sstevel@tonic-gate typetable = stattypetable;
8837c478bd9Sstevel@tonic-gate tablesize = STATIC_ARG_TBL_SIZE;
8847c478bd9Sstevel@tonic-gate tablemax = 0;
8857c478bd9Sstevel@tonic-gate nextarg = 1;
8867c478bd9Sstevel@tonic-gate (void) memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate /* Scan the format for conversions (`%' character). */
8897c478bd9Sstevel@tonic-gate for (;;)
8907c478bd9Sstevel@tonic-gate {
8917c478bd9Sstevel@tonic-gate for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
8927c478bd9Sstevel@tonic-gate /* void */;
8937c478bd9Sstevel@tonic-gate if (ch == '\0')
8947c478bd9Sstevel@tonic-gate goto done;
8957c478bd9Sstevel@tonic-gate fmt++; /* skip over '%' */
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate flags = 0;
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate rflag: ch = *fmt++;
9007c478bd9Sstevel@tonic-gate reswitch: switch (ch)
9017c478bd9Sstevel@tonic-gate {
9027c478bd9Sstevel@tonic-gate case ' ':
9037c478bd9Sstevel@tonic-gate case '#':
9047c478bd9Sstevel@tonic-gate goto rflag;
9057c478bd9Sstevel@tonic-gate case '*':
9067c478bd9Sstevel@tonic-gate ADDASTER();
9077c478bd9Sstevel@tonic-gate goto rflag;
9087c478bd9Sstevel@tonic-gate case '-':
9097c478bd9Sstevel@tonic-gate case '+':
9107c478bd9Sstevel@tonic-gate goto rflag;
9117c478bd9Sstevel@tonic-gate case '.':
9127c478bd9Sstevel@tonic-gate if ((ch = *fmt++) == '*')
9137c478bd9Sstevel@tonic-gate {
9147c478bd9Sstevel@tonic-gate ADDASTER();
9157c478bd9Sstevel@tonic-gate goto rflag;
9167c478bd9Sstevel@tonic-gate }
9177c478bd9Sstevel@tonic-gate while (is_digit(ch))
9187c478bd9Sstevel@tonic-gate {
9197c478bd9Sstevel@tonic-gate ch = *fmt++;
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate goto reswitch;
9227c478bd9Sstevel@tonic-gate case '0':
9237c478bd9Sstevel@tonic-gate goto rflag;
9247c478bd9Sstevel@tonic-gate case '1': case '2': case '3': case '4':
9257c478bd9Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9':
9267c478bd9Sstevel@tonic-gate n = 0;
9277c478bd9Sstevel@tonic-gate do
9287c478bd9Sstevel@tonic-gate {
9297c478bd9Sstevel@tonic-gate n = 10 * n + to_digit(ch);
9307c478bd9Sstevel@tonic-gate ch = *fmt++;
9317c478bd9Sstevel@tonic-gate } while (is_digit(ch));
9327c478bd9Sstevel@tonic-gate if (ch == '$')
9337c478bd9Sstevel@tonic-gate {
9347c478bd9Sstevel@tonic-gate nextarg = n;
9357c478bd9Sstevel@tonic-gate goto rflag;
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate goto reswitch;
9387c478bd9Sstevel@tonic-gate case 'h':
9397c478bd9Sstevel@tonic-gate flags |= SHORTINT;
9407c478bd9Sstevel@tonic-gate goto rflag;
9417c478bd9Sstevel@tonic-gate case 'l':
9427c478bd9Sstevel@tonic-gate flags |= LONGINT;
9437c478bd9Sstevel@tonic-gate goto rflag;
9447c478bd9Sstevel@tonic-gate case 'q':
9457c478bd9Sstevel@tonic-gate flags |= QUADINT;
9467c478bd9Sstevel@tonic-gate goto rflag;
9477c478bd9Sstevel@tonic-gate case 'c':
9487c478bd9Sstevel@tonic-gate ADDTYPE(T_INT);
9497c478bd9Sstevel@tonic-gate break;
9507c478bd9Sstevel@tonic-gate case 'D':
9517c478bd9Sstevel@tonic-gate flags |= LONGINT;
9527c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
9537c478bd9Sstevel@tonic-gate case 'd':
9547c478bd9Sstevel@tonic-gate case 'i':
9557c478bd9Sstevel@tonic-gate if (flags & QUADINT)
9567c478bd9Sstevel@tonic-gate {
9577c478bd9Sstevel@tonic-gate ADDTYPE(T_QUAD);
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate else
9607c478bd9Sstevel@tonic-gate {
9617c478bd9Sstevel@tonic-gate ADDSARG();
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate break;
9647c478bd9Sstevel@tonic-gate case 'e':
9657c478bd9Sstevel@tonic-gate case 'E':
9667c478bd9Sstevel@tonic-gate case 'f':
9677c478bd9Sstevel@tonic-gate case 'g':
9687c478bd9Sstevel@tonic-gate case 'G':
9697c478bd9Sstevel@tonic-gate ADDTYPE(T_DOUBLE);
9707c478bd9Sstevel@tonic-gate break;
9717c478bd9Sstevel@tonic-gate case 'n':
9727c478bd9Sstevel@tonic-gate if (flags & QUADINT)
9737c478bd9Sstevel@tonic-gate ADDTYPE(TP_QUAD);
9747c478bd9Sstevel@tonic-gate else if (flags & LONGINT)
9757c478bd9Sstevel@tonic-gate ADDTYPE(TP_LONG);
9767c478bd9Sstevel@tonic-gate else if (flags & SHORTINT)
9777c478bd9Sstevel@tonic-gate ADDTYPE(TP_SHORT);
9787c478bd9Sstevel@tonic-gate else
9797c478bd9Sstevel@tonic-gate ADDTYPE(TP_INT);
9807c478bd9Sstevel@tonic-gate continue; /* no output */
9817c478bd9Sstevel@tonic-gate case 'O':
9827c478bd9Sstevel@tonic-gate flags |= LONGINT;
9837c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
9847c478bd9Sstevel@tonic-gate case 'o':
9857c478bd9Sstevel@tonic-gate if (flags & QUADINT)
9867c478bd9Sstevel@tonic-gate ADDTYPE(T_U_QUAD);
9877c478bd9Sstevel@tonic-gate else
9887c478bd9Sstevel@tonic-gate ADDUARG();
9897c478bd9Sstevel@tonic-gate break;
9907c478bd9Sstevel@tonic-gate case 'p':
9917c478bd9Sstevel@tonic-gate ADDTYPE(TP_VOID);
9927c478bd9Sstevel@tonic-gate break;
9937c478bd9Sstevel@tonic-gate case 's':
9947c478bd9Sstevel@tonic-gate ADDTYPE(TP_CHAR);
9957c478bd9Sstevel@tonic-gate break;
9967c478bd9Sstevel@tonic-gate case 'U':
9977c478bd9Sstevel@tonic-gate flags |= LONGINT;
9987c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
9997c478bd9Sstevel@tonic-gate case 'u':
10007c478bd9Sstevel@tonic-gate if (flags & QUADINT)
10017c478bd9Sstevel@tonic-gate ADDTYPE(T_U_QUAD);
10027c478bd9Sstevel@tonic-gate else
10037c478bd9Sstevel@tonic-gate ADDUARG();
10047c478bd9Sstevel@tonic-gate break;
10057c478bd9Sstevel@tonic-gate case 'X':
10067c478bd9Sstevel@tonic-gate case 'x':
10077c478bd9Sstevel@tonic-gate if (flags & QUADINT)
10087c478bd9Sstevel@tonic-gate ADDTYPE(T_U_QUAD);
10097c478bd9Sstevel@tonic-gate else
10107c478bd9Sstevel@tonic-gate ADDUARG();
10117c478bd9Sstevel@tonic-gate break;
10127c478bd9Sstevel@tonic-gate default: /* "%?" prints ?, unless ? is NUL */
10137c478bd9Sstevel@tonic-gate if (ch == '\0')
10147c478bd9Sstevel@tonic-gate goto done;
10157c478bd9Sstevel@tonic-gate break;
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate }
10187c478bd9Sstevel@tonic-gate done:
10197c478bd9Sstevel@tonic-gate /* Build the argument table. */
10207c478bd9Sstevel@tonic-gate if (tablemax >= STATIC_ARG_TBL_SIZE)
10217c478bd9Sstevel@tonic-gate {
10227c478bd9Sstevel@tonic-gate *argtable = (va_list *)
10237c478bd9Sstevel@tonic-gate sm_malloc(sizeof(va_list) * (tablemax + 1));
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate for (n = 1; n <= tablemax; n++)
10277c478bd9Sstevel@tonic-gate {
10287c478bd9Sstevel@tonic-gate SM_VA_COPY((*argtable)[n], ap);
10297c478bd9Sstevel@tonic-gate switch (typetable [n])
10307c478bd9Sstevel@tonic-gate {
10317c478bd9Sstevel@tonic-gate case T_UNUSED:
10327c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, int);
10337c478bd9Sstevel@tonic-gate break;
10347c478bd9Sstevel@tonic-gate case T_SHORT:
10357c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, int);
10367c478bd9Sstevel@tonic-gate break;
10377c478bd9Sstevel@tonic-gate case T_U_SHORT:
10387c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, int);
10397c478bd9Sstevel@tonic-gate break;
10407c478bd9Sstevel@tonic-gate case TP_SHORT:
10417c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, short *);
10427c478bd9Sstevel@tonic-gate break;
10437c478bd9Sstevel@tonic-gate case T_INT:
10447c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, int);
10457c478bd9Sstevel@tonic-gate break;
10467c478bd9Sstevel@tonic-gate case T_U_INT:
10477c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, unsigned int);
10487c478bd9Sstevel@tonic-gate break;
10497c478bd9Sstevel@tonic-gate case TP_INT:
10507c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, int *);
10517c478bd9Sstevel@tonic-gate break;
10527c478bd9Sstevel@tonic-gate case T_LONG:
10537c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, long);
10547c478bd9Sstevel@tonic-gate break;
10557c478bd9Sstevel@tonic-gate case T_U_LONG:
10567c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, unsigned long);
10577c478bd9Sstevel@tonic-gate break;
10587c478bd9Sstevel@tonic-gate case TP_LONG:
10597c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, long *);
10607c478bd9Sstevel@tonic-gate break;
10617c478bd9Sstevel@tonic-gate case T_QUAD:
10627c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, LONGLONG_T);
10637c478bd9Sstevel@tonic-gate break;
10647c478bd9Sstevel@tonic-gate case T_U_QUAD:
10657c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, ULONGLONG_T);
10667c478bd9Sstevel@tonic-gate break;
10677c478bd9Sstevel@tonic-gate case TP_QUAD:
10687c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, LONGLONG_T *);
10697c478bd9Sstevel@tonic-gate break;
10707c478bd9Sstevel@tonic-gate case T_DOUBLE:
10717c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, double);
10727c478bd9Sstevel@tonic-gate break;
10737c478bd9Sstevel@tonic-gate case TP_CHAR:
10747c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, char *);
10757c478bd9Sstevel@tonic-gate break;
10767c478bd9Sstevel@tonic-gate case TP_VOID:
10777c478bd9Sstevel@tonic-gate (void) SM_VA_ARG(ap, void *);
10787c478bd9Sstevel@tonic-gate break;
10797c478bd9Sstevel@tonic-gate }
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate if ((typetable != NULL) && (typetable != stattypetable))
10837c478bd9Sstevel@tonic-gate sm_free(typetable);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate ** SM_GROW_TYPE_TABLE -- Increase the size of the type table.
10887c478bd9Sstevel@tonic-gate **
10897c478bd9Sstevel@tonic-gate ** Parameters:
10907c478bd9Sstevel@tonic-gate ** tabletype -- type of table to grow
10917c478bd9Sstevel@tonic-gate ** tablesize -- requested new table size
10927c478bd9Sstevel@tonic-gate **
10937c478bd9Sstevel@tonic-gate ** Results:
10947c478bd9Sstevel@tonic-gate ** Raises an exception if can't allocate memory.
10957c478bd9Sstevel@tonic-gate */
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate static void
sm_grow_type_table_x(typetable,tablesize)10987c478bd9Sstevel@tonic-gate sm_grow_type_table_x(typetable, tablesize)
10997c478bd9Sstevel@tonic-gate unsigned char **typetable;
11007c478bd9Sstevel@tonic-gate int *tablesize;
11017c478bd9Sstevel@tonic-gate {
11027c478bd9Sstevel@tonic-gate unsigned char *oldtable = *typetable;
11037c478bd9Sstevel@tonic-gate int newsize = *tablesize * 2;
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate if (*tablesize == STATIC_ARG_TBL_SIZE)
11067c478bd9Sstevel@tonic-gate {
11077c478bd9Sstevel@tonic-gate *typetable = (unsigned char *) sm_malloc_x(sizeof(unsigned char)
11087c478bd9Sstevel@tonic-gate * newsize);
11097c478bd9Sstevel@tonic-gate (void) memmove(*typetable, oldtable, *tablesize);
11107c478bd9Sstevel@tonic-gate }
11117c478bd9Sstevel@tonic-gate else
11127c478bd9Sstevel@tonic-gate {
11137c478bd9Sstevel@tonic-gate *typetable = (unsigned char *) sm_realloc_x(typetable,
11147c478bd9Sstevel@tonic-gate sizeof(unsigned char) * newsize);
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate (void) memset(&typetable [*tablesize], T_UNUSED,
11177c478bd9Sstevel@tonic-gate (newsize - *tablesize));
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate *tablesize = newsize;
11207c478bd9Sstevel@tonic-gate }
1121