fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 1990
0f2dc02ed2763dadc70bec1db8dd407e16db8e49ek * The Regents of the University of California. All rights reserved.
0f2dc02ed2763dadc70bec1db8dd407e16db8e49ek *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This code is derived from software contributed to Berkeley by
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Chris Torek.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * By using this file, you agree to the terms and conditions set
fa9e4066f08beec538e775443c5be79dd423fcabahrens * forth in the LICENSE file which can be found at the top level of
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the sendmail distribution.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#pragma ident "%Z%%M% %I% %E% SMI"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sm/gen.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrensSM_IDSTR(id, "@(#)$Id: vfprintf.c,v 1.54 2005/05/16 03:52:00 ca Exp $")
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Overall:
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum** Actual printing innards.
fa9e4066f08beec538e775443c5be79dd423fcabahrens** This code is large and complicated...
fa9e4066f08beec538e775443c5be79dd423fcabahrens*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/types.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <stdlib.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <string.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <errno.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sm/config.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sm/varargs.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sm/io.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sm/heap.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sm/conf.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "local.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "fvwrite.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sm_bprintf __P((SM_FILE_T *, const char *, va_list));
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sm_find_arguments __P((const char *, va_list , va_list **));
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sm_grow_type_table_x __P((unsigned char **, int *));
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sm_print __P((SM_FILE_T *, int, struct sm_uio *));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens** SM_PRINT -- print/flush to the file
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Flush out all the vectors defined by the given uio,
fa9e4066f08beec538e775443c5be79dd423fcabahrens** then reset it so that it can be reused.
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Parameters:
fa9e4066f08beec538e775443c5be79dd423fcabahrens** fp -- file pointer
fa9e4066f08beec538e775443c5be79dd423fcabahrens** timeout -- time to complete operation (milliseconds)
fa9e4066f08beec538e775443c5be79dd423fcabahrens** uio -- vector list of memory locations of data for printing
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
f18faf3f3e5def85fdfff681617d227703ace2adek** Results:
f18faf3f3e5def85fdfff681617d227703ace2adek** Success: 0 (zero)
f18faf3f3e5def85fdfff681617d227703ace2adek** Failure:
f18faf3f3e5def85fdfff681617d227703ace2adek*/
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adekstatic int
f18faf3f3e5def85fdfff681617d227703ace2adeksm_print(fp, timeout, uio)
f18faf3f3e5def85fdfff681617d227703ace2adek SM_FILE_T *fp;
f18faf3f3e5def85fdfff681617d227703ace2adek int timeout;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck register struct sm_uio *uio;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck{
fa9e4066f08beec538e775443c5be79dd423fcabahrens register int err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (uio->uio_resid == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio->uio_iovcnt = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return 0;
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb }
fa9e4066f08beec538e775443c5be79dd423fcabahrens err = sm_fvwrite(fp, timeout, uio);
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio->uio_resid = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio->uio_iovcnt = 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks** SM_BPRINTF -- allow formating to an unbuffered file.
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks**
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** Helper function for `fprintf to unbuffered unix file': creates a
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** temporary buffer (via a "fake" file pointer).
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** We only work on write-only files; this avoids
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** worries about ungetc buffers and so forth.
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck**
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** Parameters:
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** fp -- the file to send the o/p to
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** fmt -- format instructions for the o/p
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** ap -- vectors of data units used for formating
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck**
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** Results:
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck** Failure: SM_IO_EOF and errno set
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Success: number of data units used in the formating
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Side effects:
fa9e4066f08beec538e775443c5be79dd423fcabahrens** formatted o/p can be SM_IO_BUFSIZ length maximum
fa9e4066f08beec538e775443c5be79dd423fcabahrens*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssm_bprintf(fp, fmt, ap)
fa9e4066f08beec538e775443c5be79dd423fcabahrens SM_FILE_T *fp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *fmt;
fa9e4066f08beec538e775443c5be79dd423fcabahrens SM_VA_LOCAL_DECL
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens SM_FILE_T fake;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned char buf[SM_IO_BUFSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens extern const char SmFileMagic[];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* copy the important variables */
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.sm_magic = SmFileMagic;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_timeout = SM_TIME_FOREVER;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_timeoutstate = SM_TIME_BLOCK;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_flags = fp->f_flags & ~SMNBF;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_file = fp->f_file;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_cookie = fp->f_cookie;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright fake.f_write = fp->f_write;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright fake.f_close = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_open = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_read = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_seek = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_setinfo = fake.f_getinfo = NULL;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright fake.f_type = "sm_bprintf:fake";
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* set up the buffer */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright fake.f_bf.smb_base = fake.f_p = buf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fake.f_bf.smb_size = fake.f_w = sizeof(buf);
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck fake.f_lbfsize = 0; /* not actually used, but Just In Case */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* do the work, then copy any error status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ret >= 0 && sm_io_flush(&fake, SM_TIME_FOREVER))
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = SM_IO_EOF; /* errno set by sm_io_flush */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (fake.f_flags & SMERR)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright fp->f_flags |= SMERR;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright#define BUF 40
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright/* Macros for converting digits to letters and vice versa */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define to_digit(c) ((c) - '0')
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define is_digit(c) ((unsigned) to_digit(c) <= 9)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define to_char(n) ((char) (n) + '0')
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Flags used during conversion. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ALT 0x001 /* alternate form */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define LADJUST 0x004 /* left adjustment */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define LONGINT 0x010 /* long integer */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define QUADINT 0x020 /* quad integer */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define SHORTINT 0x040 /* short integer */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define FPT 0x100 /* Floating point number */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens** SM_IO_VPRINTF -- performs actual formating for o/p
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Parameters:
fa9e4066f08beec538e775443c5be79dd423fcabahrens** fp -- file pointer for o/p
fa9e4066f08beec538e775443c5be79dd423fcabahrens** timeout -- time to complete the print
fa9e4066f08beec538e775443c5be79dd423fcabahrens** fmt0 -- formating directives
fa9e4066f08beec538e775443c5be79dd423fcabahrens** ap -- vectors with data units for formating
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Results:
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Success: number of data units used for formatting
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Failure: SM_IO_EOF and sets errno
fa9e4066f08beec538e775443c5be79dd423fcabahrens*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenssm_io_vfprintf(fp, timeout, fmt0, ap)
fa9e4066f08beec538e775443c5be79dd423fcabahrens SM_FILE_T *fp;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright int timeout;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright const char *fmt0;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright SM_VA_LOCAL_DECL
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright{
fa9e4066f08beec538e775443c5be79dd423fcabahrens register char *fmt; /* format string */
fa9e4066f08beec538e775443c5be79dd423fcabahrens register int ch; /* character from fmt */
fa9e4066f08beec538e775443c5be79dd423fcabahrens register int n, m, n2; /* handy integers (short term usage) */
fa9e4066f08beec538e775443c5be79dd423fcabahrens register char *cp; /* handy char pointer (short term usage) */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright register struct sm_iov *iovp;/* for PRINT macro */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright register int flags; /* flags as above */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret; /* return value accumulator */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int width; /* width from format (%8d), or 0 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int prec; /* precision from format (%.3d), or -1 */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright char sign; /* sign prefix (' ', '+', '-', or \0) */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright wchar_t wc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ULONGLONG_T _uquad; /* integer arguments %[diouxX] */
fa9e4066f08beec538e775443c5be79dd423fcabahrens enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int dprec; /* a copy of prec if [diouxX], 0 otherwise */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int realsz; /* field size expanded by dprec */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int size; /* size of converted field or string */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright char *xdigs="0123456789abcdef"; /* digits for [xX] conversion */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright#define NIOV 8
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright struct sm_uio uio; /* output information: summary */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright struct sm_iov iov[NIOV];/* ... and individual io vectors */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright char ox[2]; /* space for 0x hex-prefix */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright va_list *argtable; /* args, built due to positional arg */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright va_list statargtable[STATIC_ARG_TBL_SIZE];
fa9e4066f08beec538e775443c5be79dd423fcabahrens int nextarg; /* 1-based argument index */
fa9e4066f08beec538e775443c5be79dd423fcabahrens va_list orgap; /* original argument pointer */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** Choose PADSIZE to trade efficiency vs. size. If larger printf
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** fields occur frequently, increase PADSIZE and make the initialisers
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** below longer.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define PADSIZE 16 /* pad chunk size */
fa9e4066f08beec538e775443c5be79dd423fcabahrens static char blanks[PADSIZE] =
fa9e4066f08beec538e775443c5be79dd423fcabahrens {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
a32fded1a905061abae92da5bcbab429cb6146f1ek static char zeroes[PADSIZE] =
fa9e4066f08beec538e775443c5be79dd423fcabahrens {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** BEWARE, these `goto error' on error, and PAD uses `n'.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define PRINT(ptr, len) do { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens iovp->iov_base = (ptr); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens iovp->iov_len = (len); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio.uio_resid += (len); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens iovp++; \
a32fded1a905061abae92da5bcbab429cb6146f1ek if (++uio.uio_iovcnt >= NIOV) \
a32fded1a905061abae92da5bcbab429cb6146f1ek { \
a32fded1a905061abae92da5bcbab429cb6146f1ek if (sm_print(fp, timeout, &uio)) \
a32fded1a905061abae92da5bcbab429cb6146f1ek goto error; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens iovp = iov; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
fa9e4066f08beec538e775443c5be79dd423fcabahrens} while (0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define PAD(howmany, with) do \
fa9e4066f08beec538e775443c5be79dd423fcabahrens{ \
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((n = (howmany)) > 0) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (n > PADSIZE) { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRINT(with, PADSIZE); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens n -= PADSIZE; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
8afd4dd66b1dd487290f73b2f35040343a3cb821perrin PRINT(with, n); \
8afd4dd66b1dd487290f73b2f35040343a3cb821perrin } \
8afd4dd66b1dd487290f73b2f35040343a3cb821perrin} while (0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define FLUSH() do \
fa9e4066f08beec538e775443c5be79dd423fcabahrens{ \
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (uio.uio_resid && sm_print(fp, timeout, &uio)) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto error; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio.uio_iovcnt = 0; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens iovp = iov; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens} while (0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** To extend shorts properly, we need both signed and unsigned
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** argument extraction methods.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define SARG() \
fa9e4066f08beec538e775443c5be79dd423fcabahrens (flags&QUADINT ? SM_VA_ARG(ap, LONGLONG_T) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags&LONGINT ? GETARG(long) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags&SHORTINT ? (long) (short) GETARG(int) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens (long) GETARG(int))
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define UARG() \
fa9e4066f08beec538e775443c5be79dd423fcabahrens (flags&QUADINT ? SM_VA_ARG(ap, ULONGLONG_T) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags&LONGINT ? GETARG(unsigned long) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags&SHORTINT ? (unsigned long) (unsigned short) GETARG(int) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens (unsigned long) GETARG(unsigned int))
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** Get * arguments, including the form *nn$. Preserve the nextarg
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ** that the argument can be gotten once the type is determined.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define GETASTER(val) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens n2 = 0; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp = fmt; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (is_digit(*cp)) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens n2 = 10 * n2 + to_digit(*cp); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp++; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*cp == '$') \
fa9e4066f08beec538e775443c5be79dd423fcabahrens { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens int hold = nextarg; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argtable == NULL) \
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtable = statargtable; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens sm_find_arguments(fmt0, orgap, &argtable); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg = n2; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens val = GETARG(int); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg = hold; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens fmt = ++cp; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
fa9e4066f08beec538e775443c5be79dd423fcabahrens else \
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw { \
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw val = GETARG(int); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum/*
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum** Get the argument indexed by nextarg. If the argument table is
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum** built, use it to get the argument. If its not, get the next
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum** argument (and arguments must be gotten sequentially).
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum*/
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum
fa9e4066f08beec538e775443c5be79dd423fcabahrens#if SM_VA_STD
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define GETARG(type) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens (((argtable != NULL) ? (void) (ap = argtable[nextarg]) : (void) 0), \
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg++, SM_VA_ARG(ap, type))
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else /* SM_VA_STD */
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define GETARG(type) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((argtable != NULL) ? (*((type*)(argtable[nextarg++]))) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens (nextarg++, SM_VA_ARG(ap, type)))
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif /* SM_VA_STD */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a32fded1a905061abae92da5bcbab429cb6146f1ek /* sorry, fprintf(read_only_file, "") returns SM_IO_EOF, not 0 */
a32fded1a905061abae92da5bcbab429cb6146f1ek if (cantwrite(fp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = EBADF;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return SM_IO_EOF;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* optimise fprintf(stderr) (and other unbuffered Unix files) */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((fp->f_flags & (SMNBF|SMWR|SMRW)) == (SMNBF|SMWR) &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens fp->f_file >= 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return sm_bprintf(fp, fmt0, ap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens fmt = (char *) fmt0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtable = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens SM_VA_COPY(orgap, ap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio.uio_iov = iovp = iov;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uio.uio_resid = 0;
a32fded1a905061abae92da5bcbab429cb6146f1ek uio.uio_iovcnt = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a32fded1a905061abae92da5bcbab429cb6146f1ek /* Scan the format for conversions (`%' character). */
a32fded1a905061abae92da5bcbab429cb6146f1ek for (;;)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp = fmt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw n = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens while ((wc = *fmt) != '\0')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (wc == '%')
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens n = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens fmt++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((m = fmt - cp) != 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRINT(cp, m);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret += m;
0f2dc02ed2763dadc70bec1db8dd407e16db8e49ek }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (n <= 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto done;
fa9e4066f08beec538e775443c5be79dd423fcabahrens fmt++; /* skip over '%' */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dprec = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens width = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens prec = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sign = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensrflag: ch = *fmt++;
fa9e4066f08beec538e775443c5be79dd423fcabahrensreswitch: switch (ch)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case ' ':
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** ``If the space and + flags both appear, the space
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** flag will be ignored.''
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ** -- ANSI X3J11
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (!sign)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright sign = ' ';
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto rflag;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case '#':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright flags |= ALT;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto rflag;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case '*':
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum /*
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum ** ``A negative field width argument is taken as a
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum ** - flag followed by a positive field width.''
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum ** -- ANSI X3J11
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum ** They don't exclude field widths read from args.
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright GETASTER(width);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (width >= 0)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto rflag;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright width = -width;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright /* FALLTHROUGH */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case '-':
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags |= LADJUST;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '+':
fa9e4066f08beec538e775443c5be79dd423fcabahrens sign = '+';
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '.':
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ch = *fmt++) == '*')
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens GETASTER(n);
fa9e4066f08beec538e775443c5be79dd423fcabahrens prec = n < 0 ? -1 : n;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens n = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (is_digit(ch))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens n = 10 * n + to_digit(ch);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ch = *fmt++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ch == '$')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nextarg = n;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argtable == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtable = statargtable;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sm_find_arguments(fmt0, orgap,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &argtable);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens prec = n < 0 ? -1 : n;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto reswitch;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '0':
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** ``Note that 0 is taken as a flag, not as the
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** beginning of a field width.''
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** -- ANSI X3J11
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags |= ZEROPAD;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto rflag;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case '1': case '2': case '3': case '4':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '5': case '6': case '7': case '8': case '9':
fa9e4066f08beec538e775443c5be79dd423fcabahrens n = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens do
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw n = 10 * n + to_digit(ch);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ch = *fmt++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (is_digit(ch));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ch == '$')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nextarg = n;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argtable == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtable = statargtable;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sm_find_arguments(fmt0, orgap,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &argtable);
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh }
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens width = n;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto reswitch;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'h':
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags |= SHORTINT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'l':
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum if (*fmt == 'l')
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum {
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum fmt++;
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum flags |= QUADINT;
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum }
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum else
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum {
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum flags |= LONGINT;
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum }
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum goto rflag;
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum case 'q':
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum flags |= QUADINT;
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum goto rflag;
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum case 'c':
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum *(cp = buf) = GETARG(int);
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum size = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sign = '\0';
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb break;
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb case 'D':
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb flags |= LONGINT;
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb /*FALLTHROUGH*/
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb case 'd':
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb case 'i':
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb _uquad = SARG();
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb if ((LONGLONG_T) _uquad < 0)
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb {
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum _uquad = -(LONGLONG_T) _uquad;
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb sign = '-';
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens base = DEC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto number;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'e':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'E':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'f':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'g':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'G':
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks {
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks double val;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *p;
5422900b426b0077b9c2720a47bf829be8225830maybee char fmt[16];
fa9e4066f08beec538e775443c5be79dd423fcabahrens char out[150];
5422900b426b0077b9c2720a47bf829be8225830maybee size_t len;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** This code implements floating point output
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** in the most portable manner possible,
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck ** relying only on 'sprintf' as defined by
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck ** the 1989 ANSI C standard.
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** We silently cap width and precision
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck ** at 120, to avoid buffer overflow.
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck val = GETARG(double);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens p = fmt;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = '%';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck if (sign)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *p++ = sign;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck if (flags & ALT)
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = '#';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck if (flags & LADJUST)
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = '-';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck if (flags & ZEROPAD)
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee *p++ = '0';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = '*';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck if (prec >= 0)
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck {
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = '.';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = '*';
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck }
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p++ = ch;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *p = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (width > 120)
fa9e4066f08beec538e775443c5be79dd423fcabahrens width = 120;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (prec > 120)
fa9e4066f08beec538e775443c5be79dd423fcabahrens prec = 120;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (prec >= 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#if HASSNPRINTF
5422900b426b0077b9c2720a47bf829be8225830maybee snprintf(out, sizeof(out), fmt, width,
fa9e4066f08beec538e775443c5be79dd423fcabahrens prec, val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else /* HASSNPRINTF */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sprintf(out, fmt, width, prec, val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif /* HASSNPRINTF */
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens#if HASSNPRINTF
fa9e4066f08beec538e775443c5be79dd423fcabahrens snprintf(out, sizeof(out), fmt, width,
fa9e4066f08beec538e775443c5be79dd423fcabahrens val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else /* HASSNPRINTF */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sprintf(out, fmt, width, val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif /* HASSNPRINTF */
fa9e4066f08beec538e775443c5be79dd423fcabahrens len = strlen(out);
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRINT(out, len);
fa9e4066f08beec538e775443c5be79dd423fcabahrens FLUSH();
5422900b426b0077b9c2720a47bf829be8225830maybee continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'n':
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flags & QUADINT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *GETARG(LONGLONG_T *) = ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else if (flags & LONGINT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *GETARG(long *) = ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else if (flags & SHORTINT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *GETARG(short *) = ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens *GETARG(int *) = ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue; /* no output */
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'O':
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags |= LONGINT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*FALLTHROUGH*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'o':
fa9e4066f08beec538e775443c5be79dd423fcabahrens _uquad = UARG();
fa9e4066f08beec538e775443c5be79dd423fcabahrens base = OCT;
0b69c2f001a429251e2d38f25aca860396551214ahrens goto nosign;
0b69c2f001a429251e2d38f25aca860396551214ahrens case 'p':
0b69c2f001a429251e2d38f25aca860396551214ahrens
0b69c2f001a429251e2d38f25aca860396551214ahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** ``The argument shall be a pointer to void. The
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** value of the pointer is converted to a sequence
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** of printable characters, in an implementation-
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** defined manner.''
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** -- ANSI X3J11
0b69c2f001a429251e2d38f25aca860396551214ahrens */
0b69c2f001a429251e2d38f25aca860396551214ahrens
0b69c2f001a429251e2d38f25aca860396551214ahrens /* NOSTRICT */
0b69c2f001a429251e2d38f25aca860396551214ahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens union
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens void *p;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ULONGLONG_T ll;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned long l;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } u;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw u.p = GETARG(void *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (sizeof(void *) == sizeof(ULONGLONG_T))
fa9e4066f08beec538e775443c5be79dd423fcabahrens _uquad = u.ll;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else if (sizeof(void *) == sizeof(long))
fa9e4066f08beec538e775443c5be79dd423fcabahrens _uquad = u.l;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens _uquad = u.i;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh }
fa9e4066f08beec538e775443c5be79dd423fcabahrens base = HEX;
fa9e4066f08beec538e775443c5be79dd423fcabahrens xdigs = "0123456789abcdef";
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh flags |= HEXPREFIX;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ch = 'x';
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto nosign;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh case 's':
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if ((cp = GETARG(char *)) == NULL)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh cp = "(null)";
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (prec >= 0)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh {
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh /*
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** can't use strlen; can only look for the
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** NUL in the first `prec' characters, and
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** strlen() will go further.
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh */
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh char *p = memchr(cp, 0, prec);
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (p != NULL)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks size = p - cp;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (size > prec)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh size = prec;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh }
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh else
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh size = prec;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens size = strlen(cp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens sign = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'U':
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags |= LONGINT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*FALLTHROUGH*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'u':
fa9e4066f08beec538e775443c5be79dd423fcabahrens _uquad = UARG();
fa9e4066f08beec538e775443c5be79dd423fcabahrens base = DEC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto nosign;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'X':
fa9e4066f08beec538e775443c5be79dd423fcabahrens xdigs = "0123456789ABCDEF";
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto hex;
5422900b426b0077b9c2720a47bf829be8225830maybee case 'x':
5422900b426b0077b9c2720a47bf829be8225830maybee xdigs = "0123456789abcdef";
5422900b426b0077b9c2720a47bf829be8225830maybeehex: _uquad = UARG();
fa9e4066f08beec538e775443c5be79dd423fcabahrens base = HEX;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* leading 0x/X only if non-zero */
cdf5b4ca0fa5ca7622b06bcb271be9e8a8245fecmmusante if (flags & ALT && _uquad != 0)
5422900b426b0077b9c2720a47bf829be8225830maybee flags |= HEXPREFIX;
5422900b426b0077b9c2720a47bf829be8225830maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* unsigned conversions */
fa9e4066f08beec538e775443c5be79dd423fcabahrensnosign: sign = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** ``... diouXx conversions ... if a precision is
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** specified, the 0 flag will be ignored.''
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** -- ANSI X3J11
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnumber: if ((dprec = prec) >= 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags &= ~ZEROPAD;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck /*
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck ** ``The result of converting a zero value with an
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** explicit precision of zero is no characters.''
fa9e4066f08beec538e775443c5be79dd423fcabahrens ** -- ANSI X3J11
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp = buf + BUF;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (_uquad != 0 || prec != 0)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh {
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh /*
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** Unsigned mod is hard, and unsigned mod
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** by a constant is easier than that by
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ** a variable; hence this switch.
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh */
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh switch (base)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh {
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh case OCT:
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh do
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh {
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh *--cp = to_char(_uquad & 7);
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh _uquad >>= 3;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh } while (_uquad);
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh /* handle octal leading 0 */
5422900b426b0077b9c2720a47bf829be8225830maybee if (flags & ALT && *cp != '0')
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh *--cp = '0';
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh break;
5422900b426b0077b9c2720a47bf829be8225830maybee
5422900b426b0077b9c2720a47bf829be8225830maybee case DEC:
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* many numbers are 1 digit */
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (_uquad >= 10)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *--cp = to_char(_uquad % 10);
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck _uquad /= 10;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck }
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *--cp = to_char(_uquad);
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck break;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck case HEX:
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck do
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck {
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck *--cp = xdigs[_uquad & 15];
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck _uquad >>= 4;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } while (_uquad);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp = "bug in sm_io_vfprintf: bad base";
fa9e4066f08beec538e775443c5be79dd423fcabahrens size = strlen(cp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto skipsize;
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek size = buf + BUF - cp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks skipsize:
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks break;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks default: /* "%?" prints ?, unless ? is NUL */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ch == '\0')
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto done;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* pretend it was %c with argument ch */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks cp = buf;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *cp = ch;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks size = 1;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks sign = '\0';
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks break;
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks }
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks /*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** All reasonable formats wind up here. At this point, `cp'
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** points to a string which (if not flags&LADJUST) should be
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** padded out to `width' places. If flags&ZEROPAD, it should
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** first be prefixed by any sign or other prefix; otherwise,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** it should be blank padded before the prefix is emitted.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** After any left-hand padding and prefixing, emit zeroes
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** required by a decimal [diouxX] precision, then print the
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** string proper, then emit zeroes required by any leftover
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** floating precision; finally, if LADJUST, pad with blanks.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks **
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** Compute actual size, so we know how much to pad.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ** size excludes decimal prec; realsz includes it.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks realsz = dprec > size ? dprec : size;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (sign)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks realsz++;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks else if (flags & HEXPREFIX)
fa9e4066f08beec538e775443c5be79dd423fcabahrens realsz+= 2;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* right-adjusting blank padding */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((flags & (LADJUST|ZEROPAD)) == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens PAD(width - realsz, blanks);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* prefix */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (sign)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRINT(&sign, 1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens else if (flags & HEXPREFIX)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ox[0] = '0';
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh ox[1] = ch;
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRINT(ox, 2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* right-adjusting zero padding */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
fa9e4066f08beec538e775443c5be79dd423fcabahrens PAD(width - realsz, zeroes);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* leading zeroes from decimal precision */
fa9e4066f08beec538e775443c5be79dd423fcabahrens PAD(dprec - size, zeroes);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* the string or number proper */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRINT(cp, size);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* left-adjusting padding (always blank) */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (flags & LADJUST)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PAD(width - realsz, blanks);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* finally, adjust ret */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret += width > realsz ? width : realsz;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens FLUSH(); /* copy out the I/O vectors */
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrensdone:
fa9e4066f08beec538e775443c5be79dd423fcabahrens FLUSH();
fa9e4066f08beec538e775443c5be79dd423fcabahrenserror:
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((argtable != NULL) && (argtable != statargtable))
fa9e4066f08beec538e775443c5be79dd423fcabahrens sm_free(argtable);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return sm_error(fp) ? SM_IO_EOF : ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Type ids for argument type table. */
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_UNUSED 0
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_SHORT 1
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_U_SHORT 2
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define TP_SHORT 3
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_INT 4
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_U_INT 5
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define TP_INT 6
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_LONG 7
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_U_LONG 8
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define TP_LONG 9
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_QUAD 10
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_U_QUAD 11
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define TP_QUAD 12
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define T_DOUBLE 13
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define TP_CHAR 15
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh#define TP_VOID 16
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens** SM_FIND_ARGUMENTS -- find all args when a positional parameter is found.
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
fa9e4066f08beec538e775443c5be79dd423fcabahrens** Find all arguments when a positional parameter is encountered. Returns a
fa9e4066f08beec538e775443c5be79dd423fcabahrens** table, indexed by argument number, of pointers to each arguments. The
fa9e4066f08beec538e775443c5be79dd423fcabahrens** initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** It will be replaced with a malloc-ed one if it overflows.
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee**
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** Parameters:
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** fmt0 -- formating directives
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** ap -- vector list of data unit for formating consumption
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** argtable -- an indexable table (returned) of 'ap'
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee**
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** Results:
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee** none.
fa9e4066f08beec538e775443c5be79dd423fcabahrens*/
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bckstatic void
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bcksm_find_arguments(fmt0, ap, argtable)
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck const char *fmt0;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck SM_VA_LOCAL_DECL
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck va_list **argtable;
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck{
bb963f1cfd0c29d3203584c421c00a566367047cmaybee register char *fmt; /* format string */
fa9e4066f08beec538e775443c5be79dd423fcabahrens register int ch; /* character from fmt */
fa9e4066f08beec538e775443c5be79dd423fcabahrens register int n, n2; /* handy integer (short term usage) */
bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77dbmaybee register char *cp; /* handy char pointer (short term usage) */
fa9e4066f08beec538e775443c5be79dd423fcabahrens register int flags; /* flags as above */
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned char *typetable; /* table of types */
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
fa9e4066f08beec538e775443c5be79dd423fcabahrens int tablesize; /* current size of type table */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int tablemax; /* largest used index in table */
5422900b426b0077b9c2720a47bf829be8225830maybee int nextarg; /* 1-based argument index */
5422900b426b0077b9c2720a47bf829be8225830maybee
5422900b426b0077b9c2720a47bf829be8225830maybee /* Add an argument type to the table, expanding if necessary. */
5422900b426b0077b9c2720a47bf829be8225830maybee#define ADDTYPE(type) \
2283022c7c1b8c8d3595e7fcb96a4e4bacc6141amarks ((nextarg >= tablesize) ? \
2283022c7c1b8c8d3595e7fcb96a4e4bacc6141amarks (sm_grow_type_table_x(&typetable, &tablesize), 0) : 0, \
2283022c7c1b8c8d3595e7fcb96a4e4bacc6141amarks typetable[nextarg++] = type, \
2283022c7c1b8c8d3595e7fcb96a4e4bacc6141amarks (nextarg > tablemax) ? tablemax = nextarg : 0)
2283022c7c1b8c8d3595e7fcb96a4e4bacc6141amarks
2283022c7c1b8c8d3595e7fcb96a4e4bacc6141amarks#define ADDSARG() \
5422900b426b0077b9c2720a47bf829be8225830maybee ((flags & LONGINT) ? ADDTYPE(T_LONG) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((flags & SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ADDUARG() \
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((flags & LONGINT) ? ADDTYPE(T_U_LONG) : \
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((flags & SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Add * arguments to the type array. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ADDASTER() \
fa9e4066f08beec538e775443c5be79dd423fcabahrens n2 = 0; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp = fmt; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (is_digit(*cp)) \
fa9e4066f08beec538e775443c5be79dd423fcabahrens { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens n2 = 10 * n2 + to_digit(*cp); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp++; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*cp == '$') \
fa9e4066f08beec538e775443c5be79dd423fcabahrens { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens int hold = nextarg; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg = n2; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE (T_INT); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg = hold; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens fmt = ++cp; \
fa9e4066f08beec538e775443c5be79dd423fcabahrens } \
fa9e4066f08beec538e775443c5be79dd423fcabahrens else \
fa9e4066f08beec538e775443c5be79dd423fcabahrens { \
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE (T_INT); \
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens fmt = (char *) fmt0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens typetable = stattypetable;
fa9e4066f08beec538e775443c5be79dd423fcabahrens tablesize = STATIC_ARG_TBL_SIZE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens tablemax = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens nextarg = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee /* Scan the format for conversions (`%' character). */
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee for (;;)
f18faf3f3e5def85fdfff681617d227703ace2adek {
f18faf3f3e5def85fdfff681617d227703ace2adek for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
f18faf3f3e5def85fdfff681617d227703ace2adek /* void */;
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee if (ch == '\0')
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee goto done;
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee fmt++; /* skip over '%' */
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags = 0;
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybeerflag: ch = *fmt++;
f18faf3f3e5def85fdfff681617d227703ace2adekreswitch: switch (ch)
ed097989586a51afeee476d7fbba56222d447ad8ek {
ed097989586a51afeee476d7fbba56222d447ad8ek case ' ':
f18faf3f3e5def85fdfff681617d227703ace2adek case '#':
f18faf3f3e5def85fdfff681617d227703ace2adek goto rflag;
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee case '*':
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee ADDASTER();
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee goto rflag;
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee case '-':
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee case '+':
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '.':
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ch = *fmt++) == '*')
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
bb963f1cfd0c29d3203584c421c00a566367047cmaybee ADDASTER();
bb963f1cfd0c29d3203584c421c00a566367047cmaybee goto rflag;
bb963f1cfd0c29d3203584c421c00a566367047cmaybee }
bb963f1cfd0c29d3203584c421c00a566367047cmaybee while (is_digit(ch))
bb963f1cfd0c29d3203584c421c00a566367047cmaybee {
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee ch = *fmt++;
bb963f1cfd0c29d3203584c421c00a566367047cmaybee }
bb963f1cfd0c29d3203584c421c00a566367047cmaybee goto reswitch;
95c9592adb96db1ca55dd488cb18abe5e5c261f4maybee case '0':
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto rflag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '1': case '2': case '3': case '4':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case '5': case '6': case '7': case '8': case '9':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright n = 0;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright do
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright {
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright n = 10 * n + to_digit(ch);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ch = *fmt++;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright } while (is_digit(ch));
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (ch == '$')
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright {
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright nextarg = n;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto rflag;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright }
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto reswitch;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'h':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright flags |= SHORTINT;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto rflag;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'l':
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum flags |= LONGINT;
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum goto rflag;
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum case 'q':
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum flags |= QUADINT;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright goto rflag;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'c':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ADDTYPE(T_INT);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'D':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright flags |= LONGINT;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright /*FALLTHROUGH*/
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'd':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'i':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (flags & QUADINT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE(T_QUAD);
b38f097029665f4ece801ca129913d36f757b49cck }
b38f097029665f4ece801ca129913d36f757b49cck else
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDSARG();
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
b38f097029665f4ece801ca129913d36f757b49cck case 'e':
b38f097029665f4ece801ca129913d36f757b49cck case 'E':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'f':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'g':
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'G':
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE(T_DOUBLE);
b38f097029665f4ece801ca129913d36f757b49cck break;
b38f097029665f4ece801ca129913d36f757b49cck case 'n':
b38f097029665f4ece801ca129913d36f757b49cck if (flags & QUADINT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE(TP_QUAD);
b38f097029665f4ece801ca129913d36f757b49cck else if (flags & LONGINT)
b38f097029665f4ece801ca129913d36f757b49cck ADDTYPE(TP_LONG);
b38f097029665f4ece801ca129913d36f757b49cck else if (flags & SHORTINT)
b38f097029665f4ece801ca129913d36f757b49cck ADDTYPE(TP_SHORT);
b38f097029665f4ece801ca129913d36f757b49cck else
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE(TP_INT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue; /* no output */
b38f097029665f4ece801ca129913d36f757b49cck case 'O':
b38f097029665f4ece801ca129913d36f757b49cck flags |= LONGINT;
b38f097029665f4ece801ca129913d36f757b49cck /*FALLTHROUGH*/
b38f097029665f4ece801ca129913d36f757b49cck case 'o':
b38f097029665f4ece801ca129913d36f757b49cck if (flags & QUADINT)
b38f097029665f4ece801ca129913d36f757b49cck ADDTYPE(T_U_QUAD);
b38f097029665f4ece801ca129913d36f757b49cck else
b38f097029665f4ece801ca129913d36f757b49cck ADDUARG();
b38f097029665f4ece801ca129913d36f757b49cck break;
b38f097029665f4ece801ca129913d36f757b49cck case 'p':
b38f097029665f4ece801ca129913d36f757b49cck ADDTYPE(TP_VOID);
b38f097029665f4ece801ca129913d36f757b49cck break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 's':
fa9e4066f08beec538e775443c5be79dd423fcabahrens ADDTYPE(TP_CHAR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'U':
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags |= LONGINT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*FALLTHROUGH*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'u':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (flags & QUADINT)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ADDTYPE(T_U_QUAD);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright else
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ADDUARG();
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'X':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case 'x':
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (flags & QUADINT)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ADDTYPE(T_U_QUAD);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright else
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright ADDUARG();
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum break;
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum default: /* "%?" prints ?, unless ? is NUL */
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum if (ch == '\0')
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum goto done;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright }
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright }
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wrightdone:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright /* Build the argument table. */
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if (tablemax >= STATIC_ARG_TBL_SIZE)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright {
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright *argtable = (va_list *)
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright sm_malloc(sizeof(va_list) * (tablemax + 1));
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright }
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright for (n = 1; n <= tablemax; n++)
f18faf3f3e5def85fdfff681617d227703ace2adek {
f18faf3f3e5def85fdfff681617d227703ace2adek SM_VA_COPY((*argtable)[n], ap);
f18faf3f3e5def85fdfff681617d227703ace2adek switch (typetable [n])
f18faf3f3e5def85fdfff681617d227703ace2adek {
f18faf3f3e5def85fdfff681617d227703ace2adek case T_UNUSED:
f18faf3f3e5def85fdfff681617d227703ace2adek (void) SM_VA_ARG(ap, int);
f18faf3f3e5def85fdfff681617d227703ace2adek break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case T_SHORT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) SM_VA_ARG(ap, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case T_U_SHORT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) SM_VA_ARG(ap, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case TP_SHORT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) SM_VA_ARG(ap, short *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case T_INT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) SM_VA_ARG(ap, int);
a32fded1a905061abae92da5bcbab429cb6146f1ek break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case T_U_INT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) SM_VA_ARG(ap, unsigned int);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case TP_INT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) SM_VA_ARG(ap, int *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case T_LONG:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, long);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case T_U_LONG:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, unsigned long);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case TP_LONG:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, long *);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case T_QUAD:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, LONGLONG_T);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case T_U_QUAD:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, ULONGLONG_T);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case TP_QUAD:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, LONGLONG_T *);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case T_DOUBLE:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, double);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case TP_CHAR:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright (void) SM_VA_ARG(ap, char *);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright break;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright case TP_VOID:
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum (void) SM_VA_ARG(ap, void *);
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum break;
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum }
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum }
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright if ((typetable != NULL) && (typetable != stattypetable))
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright sm_free(typetable);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright}
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright/*
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright** SM_GROW_TYPE_TABLE -- Increase the size of the type table.
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright**
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright** Parameters:
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright** tabletype -- type of table to grow
fa9e4066f08beec538e775443c5be79dd423fcabahrens** tablesize -- requested new table size
fa9e4066f08beec538e775443c5be79dd423fcabahrens**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw** Results:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw** Raises an exception if can't allocate memory.
fa9e4066f08beec538e775443c5be79dd423fcabahrens*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenssm_grow_type_table_x(typetable, tablesize)
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned char **typetable;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int *tablesize;
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned char *oldtable = *typetable;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int newsize = *tablesize * 2;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*tablesize == STATIC_ARG_TBL_SIZE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *typetable = (unsigned char *) sm_malloc_x(sizeof(unsigned char)
bb963f1cfd0c29d3203584c421c00a566367047cmaybee * newsize);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memmove(*typetable, oldtable, *tablesize);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
bb963f1cfd0c29d3203584c421c00a566367047cmaybee *typetable = (unsigned char *) sm_realloc_x(typetable,
bb963f1cfd0c29d3203584c421c00a566367047cmaybee sizeof(unsigned char) * newsize);
bb963f1cfd0c29d3203584c421c00a566367047cmaybee }
bb963f1cfd0c29d3203584c421c00a566367047cmaybee (void) memset(&typetable [*tablesize], T_UNUSED,
bb963f1cfd0c29d3203584c421c00a566367047cmaybee (newsize - *tablesize));
bb963f1cfd0c29d3203584c421c00a566367047cmaybee
bb963f1cfd0c29d3203584c421c00a566367047cmaybee *tablesize = newsize;
bb963f1cfd0c29d3203584c421c00a566367047cmaybee}
bb963f1cfd0c29d3203584c421c00a566367047cmaybee