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 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 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 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 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 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