17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*5d54f3d8Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*5d54f3d8Smuffin * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate * _doprnt: common code for printf, fprintf, sprintf
347c478bd9Sstevel@tonic-gate * Floating-point code is included or not, depending
357c478bd9Sstevel@tonic-gate * on whether the preprocessor variable FLOAT is 1 or 0.
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate #define MAXARGS 50
387c478bd9Sstevel@tonic-gate #ifndef FLOAT
397c478bd9Sstevel@tonic-gate #define FLOAT 1 /* YES! we want floating */
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <ctype.h>
44*5d54f3d8Smuffin #include <stdarg.h>
457c478bd9Sstevel@tonic-gate #include <values.h>
467c478bd9Sstevel@tonic-gate #include <locale.h>
477c478bd9Sstevel@tonic-gate #include "doprnt.h"
487c478bd9Sstevel@tonic-gate #include "stdiom.h"
497c478bd9Sstevel@tonic-gate #include <string.h> /* strchr, strlen, strspn */
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #define max(a,b) ((a) > (b) ? (a) : (b))
527c478bd9Sstevel@tonic-gate #define min(a,b) ((a) < (b) ? (a) : (b))
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate /* If this symbol is nonzero, allow '0' as a flag */
557c478bd9Sstevel@tonic-gate /* If this symbol is nonzero, allow '0' as a flag */
567c478bd9Sstevel@tonic-gate #define FZERO 1
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #if FLOAT
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate * libc/gen/common functions for floating-point conversion
617c478bd9Sstevel@tonic-gate */
627c478bd9Sstevel@tonic-gate #include <floatingpoint.h>
637c478bd9Sstevel@tonic-gate extern void _fourdigitsquick();
647c478bd9Sstevel@tonic-gate #endif
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate #define emitchar(c) { if (--filecnt < 0) { \
67*5d54f3d8Smuffin FILE *iop = file; \
687c478bd9Sstevel@tonic-gate if (((iop->_flag & (_IOLBF|_IONBF)) == 0 \
697c478bd9Sstevel@tonic-gate || -filecnt >= iop->_bufsiz)) { \
707c478bd9Sstevel@tonic-gate iop->_ptr = fileptr; \
717c478bd9Sstevel@tonic-gate if (iop->_flag & _IOSTRG) \
727c478bd9Sstevel@tonic-gate return iop->_ptr - iop->_base; \
737c478bd9Sstevel@tonic-gate else \
747c478bd9Sstevel@tonic-gate (void) _xflsbuf(iop); \
757c478bd9Sstevel@tonic-gate fileptr = iop->_ptr; \
767c478bd9Sstevel@tonic-gate filecnt = iop->_cnt; \
777c478bd9Sstevel@tonic-gate filecnt--; \
787c478bd9Sstevel@tonic-gate } \
797c478bd9Sstevel@tonic-gate } \
807c478bd9Sstevel@tonic-gate *fileptr++ = (unsigned)(c); \
817c478bd9Sstevel@tonic-gate count++; \
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate static char *nullstr = "(null)";
857c478bd9Sstevel@tonic-gate static char *lowerhex = "0123456789abcdef";
867c478bd9Sstevel@tonic-gate static char *upperhex = "0123456789ABCDEF";
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /* stva_list is used to subvert C's restriction that a variable with an
897c478bd9Sstevel@tonic-gate * array type can not appear on the left hand side of an assignment operator.
907c478bd9Sstevel@tonic-gate * By putting the array inside a structure, the functionality of assigning to
917c478bd9Sstevel@tonic-gate * the whole array through a simple assignment is achieved..
927c478bd9Sstevel@tonic-gate */
937c478bd9Sstevel@tonic-gate typedef struct stva_list {
947c478bd9Sstevel@tonic-gate va_list ap;
957c478bd9Sstevel@tonic-gate } stva_list;
967c478bd9Sstevel@tonic-gate
97*5d54f3d8Smuffin void _mkarglst(char *, stva_list, stva_list []);
98*5d54f3d8Smuffin void _getarg(char *, stva_list *, int);
99*5d54f3d8Smuffin static char *_check_dol(char *, int *);
100*5d54f3d8Smuffin
101*5d54f3d8Smuffin int
_doprnt(char * format,va_list in_args,FILE * file)102*5d54f3d8Smuffin _doprnt(char *format, va_list in_args, FILE *file)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate char convertbuffer[1024] ;
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate /* Current position in format */
107*5d54f3d8Smuffin char *cp;
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate /* Starting and ending points for value to be printed */
110*5d54f3d8Smuffin char *bp;
1117c478bd9Sstevel@tonic-gate char *p;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate /* Pointer and count for I/O buffer */
114*5d54f3d8Smuffin unsigned char *fileptr;
115*5d54f3d8Smuffin int filecnt;
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate /* Field width and precision */
1187c478bd9Sstevel@tonic-gate int width;
119*5d54f3d8Smuffin int prec;
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /* Format code */
1227c478bd9Sstevel@tonic-gate char fcode;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate /* Number of padding zeroes required on the left */
1257c478bd9Sstevel@tonic-gate int lzero;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate /* Flags - nonzero if corresponding character appears in format */
1287c478bd9Sstevel@tonic-gate bool fplus; /* + */
1297c478bd9Sstevel@tonic-gate bool fminus; /* - */
1307c478bd9Sstevel@tonic-gate bool fblank; /* blank */
1317c478bd9Sstevel@tonic-gate bool fsharp; /* # */
1327c478bd9Sstevel@tonic-gate #if FZERO
1337c478bd9Sstevel@tonic-gate bool ansi_fzero; /* 0 for ansi-dictated formats */
1347c478bd9Sstevel@tonic-gate bool compat_fzero; /* 0 for backward compatibility */
1357c478bd9Sstevel@tonic-gate #endif
1367c478bd9Sstevel@tonic-gate bool Lsize; /* Capital L for size = long double = quadruple */
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /* Pointer to sign, "0x", "0X", or empty */
1397c478bd9Sstevel@tonic-gate char *prefix;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate /* Scratch */
1427c478bd9Sstevel@tonic-gate int nblank;
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate #if FLOAT
1457c478bd9Sstevel@tonic-gate /* Exponent or empty */
1467c478bd9Sstevel@tonic-gate char *suffix;
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate /* Buffer to create exponent */
1497c478bd9Sstevel@tonic-gate char expbuf[7]; /* "e+xxxx\0" */
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /* Number of padding zeroes required on the right */
1527c478bd9Sstevel@tonic-gate int rzero;
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate /* Length of exponent suffix. */
1557c478bd9Sstevel@tonic-gate int suffixlength;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate /* The value being converted, if real or quadruple */
1587c478bd9Sstevel@tonic-gate double dval;
1597c478bd9Sstevel@tonic-gate quadruple qval;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /* Output values from fconvert and econvert */
1627c478bd9Sstevel@tonic-gate int decpt, sign;
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate /* Values are developed in this buffer */
1657c478bd9Sstevel@tonic-gate char buf[1034]; /* Size of convertbuffer, plus some for exponent and sign. */
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /* Current locale's decimal point */
1687c478bd9Sstevel@tonic-gate char decpt_char = *(localeconv()->decimal_point);
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate #else
1717c478bd9Sstevel@tonic-gate /* Values are developed in this buffer */
1727c478bd9Sstevel@tonic-gate char buf[MAXDIGS];
1737c478bd9Sstevel@tonic-gate #endif
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /* The value being converted, if integer */
177*5d54f3d8Smuffin unsigned long val;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /* Work variables */
180*5d54f3d8Smuffin int n;
181*5d54f3d8Smuffin char c;
1827c478bd9Sstevel@tonic-gate char radix;
1837c478bd9Sstevel@tonic-gate int svswitch = 0;
1847c478bd9Sstevel@tonic-gate /* count of output characters */
185*5d54f3d8Smuffin int count;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate /* variables for positional parameters */
1887c478bd9Sstevel@tonic-gate char *sformat = format; /* save the beginning of the format */
1897c478bd9Sstevel@tonic-gate int fpos = 1; /* 1 if first positional parameter */
1907c478bd9Sstevel@tonic-gate stva_list args, /* used to step through the argument list */
1917c478bd9Sstevel@tonic-gate args_width, /* for width */
1927c478bd9Sstevel@tonic-gate args_prec, /* for prec */
1937c478bd9Sstevel@tonic-gate sargs; /* used to save the start of the argument list */
1947c478bd9Sstevel@tonic-gate stva_list arglst[MAXARGS];/* array giving the approriate values
1957c478bd9Sstevel@tonic-gate * for va_arg() to retrieve the
1967c478bd9Sstevel@tonic-gate * corresponding argument:
1977c478bd9Sstevel@tonic-gate * arglst[0] is the first argument
1987c478bd9Sstevel@tonic-gate * arglst[1] is the second argument, etc.
1997c478bd9Sstevel@tonic-gate */
2007c478bd9Sstevel@tonic-gate int index = 0; /* argument placeolder */
2017c478bd9Sstevel@tonic-gate /* Initialize args and sargs to the start of the argument list.
2027c478bd9Sstevel@tonic-gate * Note that ANSI guarantees that the address of the first member of
2037c478bd9Sstevel@tonic-gate * a structure will be the same as the address of the structure. */
2047c478bd9Sstevel@tonic-gate args_width = args_prec = args = sargs = *(struct stva_list *)&in_args;
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate /* initialize p an bp (starting and ending points) bugid 1141781 */
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate p = bp = NULL;
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate cp = format;
2127c478bd9Sstevel@tonic-gate if ((c = *cp++) != '\0') {
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate * We know we're going to write something; make sure
2157c478bd9Sstevel@tonic-gate * we can write and set up buffers, etc..
2167c478bd9Sstevel@tonic-gate */
2177c478bd9Sstevel@tonic-gate if (_WRTCHK(file))
2187c478bd9Sstevel@tonic-gate return(EOF);
2197c478bd9Sstevel@tonic-gate } else
2207c478bd9Sstevel@tonic-gate return(0); /* no fault, no error */
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate count = 0;
2237c478bd9Sstevel@tonic-gate fileptr = file->_ptr;
2247c478bd9Sstevel@tonic-gate filecnt = file->_cnt;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /*
2277c478bd9Sstevel@tonic-gate * The main loop -- this loop goes through one iteration
2287c478bd9Sstevel@tonic-gate * for each ordinary character or format specification.
2297c478bd9Sstevel@tonic-gate */
2307c478bd9Sstevel@tonic-gate do {
2317c478bd9Sstevel@tonic-gate if (c != '%') {
2327c478bd9Sstevel@tonic-gate /* Ordinary (non-%) character */
2337c478bd9Sstevel@tonic-gate emitchar(c);
2347c478bd9Sstevel@tonic-gate } else {
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate * % has been spotted!
2377c478bd9Sstevel@tonic-gate *
2387c478bd9Sstevel@tonic-gate * First, try the 99% cases.
2397c478bd9Sstevel@tonic-gate * then parse the format specification.
2407c478bd9Sstevel@tonic-gate *
2417c478bd9Sstevel@tonic-gate * Note that this code assumes the Sun
2427c478bd9Sstevel@tonic-gate * Workstation environment (all params
2437c478bd9Sstevel@tonic-gate * passed as int == long, no interrupts
2447c478bd9Sstevel@tonic-gate * for fixed point overflow from negating
2457c478bd9Sstevel@tonic-gate * the most negative number).
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate skipit:
2487c478bd9Sstevel@tonic-gate switch(c = *cp++) {
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate case 'l':
2517c478bd9Sstevel@tonic-gate case 'h':
2527c478bd9Sstevel@tonic-gate /* Quickly ignore long & short specifiers */
2537c478bd9Sstevel@tonic-gate goto skipit;
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate case 's':
2567c478bd9Sstevel@tonic-gate bp = va_arg(args.ap, char *);
2577c478bd9Sstevel@tonic-gate if (bp == NULL)
2587c478bd9Sstevel@tonic-gate bp = nullstr;
2597c478bd9Sstevel@tonic-gate while (c = *bp++)
2607c478bd9Sstevel@tonic-gate emitchar(c);
2617c478bd9Sstevel@tonic-gate p = bp;
2627c478bd9Sstevel@tonic-gate continue;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate case 'c':
2657c478bd9Sstevel@tonic-gate c = va_arg(args.ap, int);
2667c478bd9Sstevel@tonic-gate emitc:
2677c478bd9Sstevel@tonic-gate emitchar(c);
2687c478bd9Sstevel@tonic-gate continue;
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate case 'i':
2717c478bd9Sstevel@tonic-gate case 'd':
2727c478bd9Sstevel@tonic-gate case 'D':
2737c478bd9Sstevel@tonic-gate val = va_arg(args.ap, int);
2747c478bd9Sstevel@tonic-gate if ((long) val < 0) {
2757c478bd9Sstevel@tonic-gate emitchar('-');
2767c478bd9Sstevel@tonic-gate val = -val;
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate goto udcommon;
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate case 'U':
2817c478bd9Sstevel@tonic-gate case 'u':
2827c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned);
2837c478bd9Sstevel@tonic-gate udcommon:
2847c478bd9Sstevel@tonic-gate {
285*5d54f3d8Smuffin char *stringp = lowerhex;
2867c478bd9Sstevel@tonic-gate bp = buf+MAXDIGS;
2877c478bd9Sstevel@tonic-gate stringp = lowerhex;
2887c478bd9Sstevel@tonic-gate do {
2897c478bd9Sstevel@tonic-gate *--bp = stringp[val%10];
2907c478bd9Sstevel@tonic-gate val /= 10;
2917c478bd9Sstevel@tonic-gate } while (val);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate goto intout;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate case 'X':
2967c478bd9Sstevel@tonic-gate {
297*5d54f3d8Smuffin char *stringp = upperhex;
2987c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned);
2997c478bd9Sstevel@tonic-gate bp = buf + MAXDIGS;
3007c478bd9Sstevel@tonic-gate if (val == 0)
3017c478bd9Sstevel@tonic-gate goto zero;
3027c478bd9Sstevel@tonic-gate while (val) {
3037c478bd9Sstevel@tonic-gate *--bp = stringp[val%16];
3047c478bd9Sstevel@tonic-gate val /= 16;
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate goto intout;
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate case 'x':
3107c478bd9Sstevel@tonic-gate case 'p':
3117c478bd9Sstevel@tonic-gate {
312*5d54f3d8Smuffin char *stringp = lowerhex;
3137c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned);
3147c478bd9Sstevel@tonic-gate bp = buf + MAXDIGS;
3157c478bd9Sstevel@tonic-gate if (val == 0)
3167c478bd9Sstevel@tonic-gate goto zero;
3177c478bd9Sstevel@tonic-gate while (val) {
3187c478bd9Sstevel@tonic-gate *--bp = stringp[val%16];
3197c478bd9Sstevel@tonic-gate val /= 16;
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate goto intout;
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate case 'O':
3257c478bd9Sstevel@tonic-gate case 'o':
3267c478bd9Sstevel@tonic-gate {
327*5d54f3d8Smuffin char *stringp = lowerhex;
3287c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned);
3297c478bd9Sstevel@tonic-gate bp = buf + MAXDIGS;
3307c478bd9Sstevel@tonic-gate if (val == 0)
3317c478bd9Sstevel@tonic-gate goto zero;
3327c478bd9Sstevel@tonic-gate while (val) {
3337c478bd9Sstevel@tonic-gate *--bp = stringp[val%8];
3347c478bd9Sstevel@tonic-gate val /= 8;
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate /* Common code to output integers */
3387c478bd9Sstevel@tonic-gate intout:
3397c478bd9Sstevel@tonic-gate p = buf + MAXDIGS;
3407c478bd9Sstevel@tonic-gate while (bp < p) {
3417c478bd9Sstevel@tonic-gate c = *bp++;
3427c478bd9Sstevel@tonic-gate emitchar(c);
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate continue;
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate zero:
3477c478bd9Sstevel@tonic-gate c = '0';
3487c478bd9Sstevel@tonic-gate goto emitc;
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate default:
3517c478bd9Sstevel@tonic-gate /*
3527c478bd9Sstevel@tonic-gate * let AT&T deal with it
3537c478bd9Sstevel@tonic-gate */
3547c478bd9Sstevel@tonic-gate cp-= 2;
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate Lsize = 0; /* Not long double unless we say so. */
3587c478bd9Sstevel@tonic-gate /* Scan the <flags> */
3597c478bd9Sstevel@tonic-gate fplus = 0;
3607c478bd9Sstevel@tonic-gate fminus = 0;
3617c478bd9Sstevel@tonic-gate fblank = 0;
3627c478bd9Sstevel@tonic-gate fsharp = 0;
3637c478bd9Sstevel@tonic-gate #if FZERO
3647c478bd9Sstevel@tonic-gate ansi_fzero = 0;
3657c478bd9Sstevel@tonic-gate compat_fzero = 0;
3667c478bd9Sstevel@tonic-gate #endif
3677c478bd9Sstevel@tonic-gate scan: switch (*++cp) {
3687c478bd9Sstevel@tonic-gate case '+':
3697c478bd9Sstevel@tonic-gate fplus = 1;
3707c478bd9Sstevel@tonic-gate goto scan;
3717c478bd9Sstevel@tonic-gate case '-':
3727c478bd9Sstevel@tonic-gate fminus = 1;
3737c478bd9Sstevel@tonic-gate goto scan;
3747c478bd9Sstevel@tonic-gate case ' ':
3757c478bd9Sstevel@tonic-gate fblank = 1;
3767c478bd9Sstevel@tonic-gate goto scan;
3777c478bd9Sstevel@tonic-gate case '#':
3787c478bd9Sstevel@tonic-gate fsharp = 1;
3797c478bd9Sstevel@tonic-gate goto scan;
3807c478bd9Sstevel@tonic-gate #if FZERO
3817c478bd9Sstevel@tonic-gate case '0':
3827c478bd9Sstevel@tonic-gate ansi_fzero = 1;
3837c478bd9Sstevel@tonic-gate compat_fzero = 1;
3847c478bd9Sstevel@tonic-gate goto scan;
3857c478bd9Sstevel@tonic-gate #endif
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /* Scan the field width */
3897c478bd9Sstevel@tonic-gate if (*cp == '*') {
3907c478bd9Sstevel@tonic-gate char *p;
3917c478bd9Sstevel@tonic-gate int val;
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate p = _check_dol(cp+1, &val);
3947c478bd9Sstevel@tonic-gate if (p != (char *)NULL) {
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate * argument re-order
3977c478bd9Sstevel@tonic-gate */
3987c478bd9Sstevel@tonic-gate if (fpos) {
3997c478bd9Sstevel@tonic-gate _mkarglst(sformat, sargs, arglst);
4007c478bd9Sstevel@tonic-gate fpos = 0;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate if (val <= MAXARGS) {
4037c478bd9Sstevel@tonic-gate args_width = arglst[val - 1];
4047c478bd9Sstevel@tonic-gate } else {
4057c478bd9Sstevel@tonic-gate args_width = arglst[MAXARGS - 1];
4067c478bd9Sstevel@tonic-gate _getarg(sformat, &args_width, val);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate width = va_arg(args_width.ap, int);
4097c478bd9Sstevel@tonic-gate if (width < 0) {
4107c478bd9Sstevel@tonic-gate width = -width;
4117c478bd9Sstevel@tonic-gate fminus = 1;
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate cp = p;
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate else {
4167c478bd9Sstevel@tonic-gate width = va_arg(args.ap, int);
4177c478bd9Sstevel@tonic-gate if (width < 0) {
4187c478bd9Sstevel@tonic-gate width = -width;
4197c478bd9Sstevel@tonic-gate fminus = 1;
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate cp++;
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate } else {
4247c478bd9Sstevel@tonic-gate index = width = 0;
4257c478bd9Sstevel@tonic-gate while (isdigit(*cp)) {
4267c478bd9Sstevel@tonic-gate n = tonumber(*cp++);
4277c478bd9Sstevel@tonic-gate index = width = width * 10 + n;
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate /* Scan the precision */
4327c478bd9Sstevel@tonic-gate if (*cp == '.') {
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate /* '*' instead of digits? */
4357c478bd9Sstevel@tonic-gate if (*++cp == '*') {
4367c478bd9Sstevel@tonic-gate char *p;
4377c478bd9Sstevel@tonic-gate int val;
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate p = _check_dol(cp+1, &val);
4407c478bd9Sstevel@tonic-gate if (p != (char *)NULL) {
4417c478bd9Sstevel@tonic-gate /*
4427c478bd9Sstevel@tonic-gate * argument re-order
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate if (fpos) {
4457c478bd9Sstevel@tonic-gate _mkarglst(sformat, sargs, arglst);
4467c478bd9Sstevel@tonic-gate fpos = 0;
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate if (val <= MAXARGS) {
4497c478bd9Sstevel@tonic-gate args_prec = arglst[val - 1];
4507c478bd9Sstevel@tonic-gate } else {
4517c478bd9Sstevel@tonic-gate args_prec = arglst[MAXARGS - 1];
4527c478bd9Sstevel@tonic-gate _getarg(sformat, &args_prec, val);
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate prec = va_arg(args_prec.ap, int);
4557c478bd9Sstevel@tonic-gate cp = p;
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate else {
4587c478bd9Sstevel@tonic-gate prec = va_arg(args.ap, int);
4597c478bd9Sstevel@tonic-gate cp++;
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate } else {
4627c478bd9Sstevel@tonic-gate prec = 0;
4637c478bd9Sstevel@tonic-gate while (isdigit(*cp)) {
4647c478bd9Sstevel@tonic-gate n = tonumber(*cp++);
4657c478bd9Sstevel@tonic-gate prec = prec * 10 + n;
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate } else
4697c478bd9Sstevel@tonic-gate prec = -1;
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate if (*cp == '$') {
4727c478bd9Sstevel@tonic-gate if (fpos) {
4737c478bd9Sstevel@tonic-gate _mkarglst(sformat, sargs, arglst);
4747c478bd9Sstevel@tonic-gate fpos = 0;
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate if (index <= MAXARGS) {
4777c478bd9Sstevel@tonic-gate args = arglst[index - 1];
4787c478bd9Sstevel@tonic-gate } else {
4797c478bd9Sstevel@tonic-gate args = arglst[MAXARGS - 1];
4807c478bd9Sstevel@tonic-gate _getarg(sformat, &args, index);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate goto scan;
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate /*
4857c478bd9Sstevel@tonic-gate * The character addressed by cp must be the
4867c478bd9Sstevel@tonic-gate * format letter -- there is nothing left for
4877c478bd9Sstevel@tonic-gate * it to be.
4887c478bd9Sstevel@tonic-gate *
4897c478bd9Sstevel@tonic-gate * The status of the +, -, #, blank, and 0
4907c478bd9Sstevel@tonic-gate * flags are reflected in the variables
4917c478bd9Sstevel@tonic-gate * "fplus", "fminus", "fsharp", "fblank",
4927c478bd9Sstevel@tonic-gate * and "ansi_fzero"/"compat_fzero", respectively.
4937c478bd9Sstevel@tonic-gate * "width" and "prec" contain numbers
4947c478bd9Sstevel@tonic-gate * corresponding to the digit strings
4957c478bd9Sstevel@tonic-gate * before and after the decimal point,
4967c478bd9Sstevel@tonic-gate * respectively. If there was no decimal
4977c478bd9Sstevel@tonic-gate * point, "prec" is -1.
4987c478bd9Sstevel@tonic-gate *
4997c478bd9Sstevel@tonic-gate * The following switch sets things up
5007c478bd9Sstevel@tonic-gate * for printing. What ultimately gets
5017c478bd9Sstevel@tonic-gate * printed will be padding blanks, a prefix,
5027c478bd9Sstevel@tonic-gate * left padding zeroes, a value, right padding
5037c478bd9Sstevel@tonic-gate * zeroes, a suffix, and more padding
5047c478bd9Sstevel@tonic-gate * blanks. Padding blanks will not appear
5057c478bd9Sstevel@tonic-gate * simultaneously on both the left and the
5067c478bd9Sstevel@tonic-gate * right. Each case in this switch will
5077c478bd9Sstevel@tonic-gate * compute the value, and leave in several
5087c478bd9Sstevel@tonic-gate * variables the information necessary to
5097c478bd9Sstevel@tonic-gate * construct what is to be printed.
5107c478bd9Sstevel@tonic-gate *
5117c478bd9Sstevel@tonic-gate * The prefix is a sign, a blank, "0x", "0X",
5127c478bd9Sstevel@tonic-gate * or null, and is addressed by "prefix".
5137c478bd9Sstevel@tonic-gate *
5147c478bd9Sstevel@tonic-gate * The suffix is either null or an exponent,
5157c478bd9Sstevel@tonic-gate * and is addressed by "suffix".
5167c478bd9Sstevel@tonic-gate *
5177c478bd9Sstevel@tonic-gate * The value to be printed starts at "bp"
5187c478bd9Sstevel@tonic-gate * and continues up to and not including "p".
5197c478bd9Sstevel@tonic-gate *
5207c478bd9Sstevel@tonic-gate * "lzero" and "rzero" will contain the number
5217c478bd9Sstevel@tonic-gate * of padding zeroes required on the left
5227c478bd9Sstevel@tonic-gate * and right, respectively. If either of
5237c478bd9Sstevel@tonic-gate * these variables is negative, it will be
5247c478bd9Sstevel@tonic-gate * treated as if it were zero.
5257c478bd9Sstevel@tonic-gate *
5267c478bd9Sstevel@tonic-gate * The number of padding blanks, and whether
5277c478bd9Sstevel@tonic-gate * they go on the left or the right, will be
5287c478bd9Sstevel@tonic-gate * computed on exit from the switch.
5297c478bd9Sstevel@tonic-gate */
5307c478bd9Sstevel@tonic-gate
5317c478bd9Sstevel@tonic-gate lzero = 0;
5327c478bd9Sstevel@tonic-gate prefix = "";
5337c478bd9Sstevel@tonic-gate #if FLOAT
5347c478bd9Sstevel@tonic-gate rzero = 0;
5357c478bd9Sstevel@tonic-gate suffix = prefix;
5367c478bd9Sstevel@tonic-gate #endif
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate #if FZERO
5397c478bd9Sstevel@tonic-gate /* if both zero-padding and left-justify flags
5407c478bd9Sstevel@tonic-gate * are used, ignore zero-padding, per ansi c
5417c478bd9Sstevel@tonic-gate */
5427c478bd9Sstevel@tonic-gate if (ansi_fzero & fminus) {
5437c478bd9Sstevel@tonic-gate ansi_fzero = 0;
5447c478bd9Sstevel@tonic-gate compat_fzero = 0;
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate /* if zero-padding and precision are specified,
5487c478bd9Sstevel@tonic-gate * ignore zero-padding for ansi-dictated formats,
5497c478bd9Sstevel@tonic-gate * per ansi c
5507c478bd9Sstevel@tonic-gate */
5517c478bd9Sstevel@tonic-gate if (ansi_fzero & (prec != -1)) ansi_fzero = 0;
5527c478bd9Sstevel@tonic-gate #endif
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate next:
5557c478bd9Sstevel@tonic-gate switch (fcode = *cp++) {
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate /* toss the length modifier, if any */
5587c478bd9Sstevel@tonic-gate case 'l':
5597c478bd9Sstevel@tonic-gate case 'h':
5607c478bd9Sstevel@tonic-gate goto next;
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate case 'L':
5637c478bd9Sstevel@tonic-gate Lsize = 1; /* Remember long double size. */
5647c478bd9Sstevel@tonic-gate goto next;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate * fixed point representations
5687c478bd9Sstevel@tonic-gate *
5697c478bd9Sstevel@tonic-gate * "radix" is the radix for the conversion.
5707c478bd9Sstevel@tonic-gate * Conversion is unsigned unless fcode is 'd'.
5717c478bd9Sstevel@tonic-gate * We assume a 2's complement machine and
5727c478bd9Sstevel@tonic-gate * that fixed point overflow (from negating
5737c478bd9Sstevel@tonic-gate * the largest negative int) is ignored.
5747c478bd9Sstevel@tonic-gate */
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate case 'i':
5777c478bd9Sstevel@tonic-gate case 'D':
5787c478bd9Sstevel@tonic-gate case 'U':
5797c478bd9Sstevel@tonic-gate case 'd':
5807c478bd9Sstevel@tonic-gate case 'u':
5817c478bd9Sstevel@tonic-gate radix = 10;
5827c478bd9Sstevel@tonic-gate goto fixed;
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate case 'O':
5857c478bd9Sstevel@tonic-gate case 'o':
5867c478bd9Sstevel@tonic-gate radix = 8;
5877c478bd9Sstevel@tonic-gate goto fixed;
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate case 'X':
5907c478bd9Sstevel@tonic-gate case 'x':
5917c478bd9Sstevel@tonic-gate radix = 16;
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate fixed:
5947c478bd9Sstevel@tonic-gate /* Establish default precision */
5957c478bd9Sstevel@tonic-gate if (prec < 0)
5967c478bd9Sstevel@tonic-gate prec = 1;
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate /* Fetch the argument to be printed */
5997c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned);
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate /* If signed conversion, establish sign */
6027c478bd9Sstevel@tonic-gate if (fcode == 'd' || fcode == 'D' || fcode == 'i') {
6037c478bd9Sstevel@tonic-gate if ((long) val < 0) {
6047c478bd9Sstevel@tonic-gate prefix = "-";
6057c478bd9Sstevel@tonic-gate val = -val;
6067c478bd9Sstevel@tonic-gate } else if (fplus)
6077c478bd9Sstevel@tonic-gate prefix = "+";
6087c478bd9Sstevel@tonic-gate else if (fblank)
6097c478bd9Sstevel@tonic-gate prefix = " ";
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate /* Set translate table for digits */
6127c478bd9Sstevel@tonic-gate {
613*5d54f3d8Smuffin char *stringp;
6147c478bd9Sstevel@tonic-gate if (fcode == 'X')
6157c478bd9Sstevel@tonic-gate stringp = upperhex;
6167c478bd9Sstevel@tonic-gate else
6177c478bd9Sstevel@tonic-gate stringp = lowerhex;
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate /* Develop the digits of the value */
6207c478bd9Sstevel@tonic-gate bp = buf + MAXDIGS;
6217c478bd9Sstevel@tonic-gate switch(radix) {
6227c478bd9Sstevel@tonic-gate case 8: /*octal*/
6237c478bd9Sstevel@tonic-gate while (val) {
6247c478bd9Sstevel@tonic-gate *--bp = stringp[val%8];
6257c478bd9Sstevel@tonic-gate val /= 8;
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate break;
6287c478bd9Sstevel@tonic-gate case 16:/*hex*/
6297c478bd9Sstevel@tonic-gate while (val) {
6307c478bd9Sstevel@tonic-gate *--bp = stringp[val%16];
6317c478bd9Sstevel@tonic-gate val /= 16;
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate break;
6347c478bd9Sstevel@tonic-gate default:
6357c478bd9Sstevel@tonic-gate while (val) {
6367c478bd9Sstevel@tonic-gate *--bp = stringp[val%10];
6377c478bd9Sstevel@tonic-gate val /= 10;
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate break;
6407c478bd9Sstevel@tonic-gate } /* switch */
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate /* Calculate padding zero requirement */
6447c478bd9Sstevel@tonic-gate p = buf + MAXDIGS;
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate /* Handle the # flag */
6477c478bd9Sstevel@tonic-gate if (fsharp && bp != p) {
6487c478bd9Sstevel@tonic-gate switch (fcode) {
6497c478bd9Sstevel@tonic-gate case 'x':
6507c478bd9Sstevel@tonic-gate prefix = "0x";
6517c478bd9Sstevel@tonic-gate break;
6527c478bd9Sstevel@tonic-gate case 'X':
6537c478bd9Sstevel@tonic-gate prefix = "0X";
6547c478bd9Sstevel@tonic-gate break;
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate #if FZERO
6587c478bd9Sstevel@tonic-gate if (ansi_fzero) {
6597c478bd9Sstevel@tonic-gate n = width - strlen(prefix);
6607c478bd9Sstevel@tonic-gate if (n > prec)
6617c478bd9Sstevel@tonic-gate prec = n;
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate #endif
6647c478bd9Sstevel@tonic-gate lzero = bp - p + prec;
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate /* Handle the # flag for 'o' */
6677c478bd9Sstevel@tonic-gate if (fsharp && bp != p && fcode == 'o' &&
6687c478bd9Sstevel@tonic-gate lzero < 1) {
6697c478bd9Sstevel@tonic-gate lzero = 1;
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate break;
6727c478bd9Sstevel@tonic-gate #if FLOAT
6737c478bd9Sstevel@tonic-gate
674*5d54f3d8Smuffin #if defined(__sparc)
6757c478bd9Sstevel@tonic-gate #define GETQVAL /* Sun-4 macro to get a quad q from the argument list, passed as a pointer. */ \
6767c478bd9Sstevel@tonic-gate { qval = *(va_arg(args.ap, quadruple*)) ; }
6777c478bd9Sstevel@tonic-gate #else
6787c478bd9Sstevel@tonic-gate #define GETQVAL /* Sun-3 macro to get a quad q from the argument list, passed as a value. */ \
6797c478bd9Sstevel@tonic-gate { int iq ; unsigned long * pl = (unsigned long *) (&qval) ; for(iq=0;iq<4;iq++) pl[iq] = (unsigned long) va_arg(args.ap, unsigned long) ; }
6807c478bd9Sstevel@tonic-gate #endif
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate case 'E':
6837c478bd9Sstevel@tonic-gate case 'e':
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate * E-format. The general strategy
6867c478bd9Sstevel@tonic-gate * here is fairly easy: we take
6877c478bd9Sstevel@tonic-gate * what econvert gives us and re-format it.
6887c478bd9Sstevel@tonic-gate */
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate /* Establish default precision */
6917c478bd9Sstevel@tonic-gate if (prec < 0)
6927c478bd9Sstevel@tonic-gate prec = 6;
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate /* Fetch the value */
6957c478bd9Sstevel@tonic-gate if (Lsize == 0) { /* Double */
6967c478bd9Sstevel@tonic-gate dval = va_arg(args.ap, double);
6977c478bd9Sstevel@tonic-gate bp = econvert(dval, prec + 1, &decpt, &sign, convertbuffer);
6987c478bd9Sstevel@tonic-gate } else { /* Long Double = quadruple */
6997c478bd9Sstevel@tonic-gate GETQVAL;
7007c478bd9Sstevel@tonic-gate bp = qeconvert(&qval, prec + 1, &decpt, &sign, convertbuffer);
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate /* Determine the prefix */
7047c478bd9Sstevel@tonic-gate if (sign)
7057c478bd9Sstevel@tonic-gate prefix = "-";
7067c478bd9Sstevel@tonic-gate else if (fplus)
7077c478bd9Sstevel@tonic-gate prefix = "+";
7087c478bd9Sstevel@tonic-gate else if (fblank)
7097c478bd9Sstevel@tonic-gate prefix = " ";
7107c478bd9Sstevel@tonic-gate if (convertbuffer[0] > '9')
7117c478bd9Sstevel@tonic-gate { /* handle infinity, nan */
7127c478bd9Sstevel@tonic-gate bp = &convertbuffer[0];
7137c478bd9Sstevel@tonic-gate for (p = bp+1 ; *p != 0 ; p++) ;
7147c478bd9Sstevel@tonic-gate goto ebreak ;
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate {
717*5d54f3d8Smuffin char *stringp;
7187c478bd9Sstevel@tonic-gate /* Place the first digit in the buffer */
7197c478bd9Sstevel@tonic-gate stringp = &buf[0];
7207c478bd9Sstevel@tonic-gate *stringp++ = *bp != '\0'? *bp++: '0';
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate /* Put in a decimal point if needed */
7237c478bd9Sstevel@tonic-gate if (prec != 0 || fsharp)
7247c478bd9Sstevel@tonic-gate *stringp++ = decpt_char;
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate /* Create the rest of the mantissa */
7277c478bd9Sstevel@tonic-gate rzero = prec;
7287c478bd9Sstevel@tonic-gate while (rzero > 0 && *bp!= '\0') {
7297c478bd9Sstevel@tonic-gate --rzero;
7307c478bd9Sstevel@tonic-gate *stringp++ = *bp++;
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate p = stringp;
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate bp = &buf[0];
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate /* Create the exponent */
7387c478bd9Sstevel@tonic-gate if (convertbuffer[0] != '0')
7397c478bd9Sstevel@tonic-gate n = decpt - 1;
7407c478bd9Sstevel@tonic-gate else
7417c478bd9Sstevel@tonic-gate n = 0 ;
7427c478bd9Sstevel@tonic-gate if (n < 0)
7437c478bd9Sstevel@tonic-gate n = -n;
7447c478bd9Sstevel@tonic-gate _fourdigitsquick( (short unsigned) n, &(expbuf[2]) ) ;
7457c478bd9Sstevel@tonic-gate expbuf[6] = 0 ;
7467c478bd9Sstevel@tonic-gate if (n < 100)
7477c478bd9Sstevel@tonic-gate /*
7487c478bd9Sstevel@tonic-gate * Normally two digit exponent field,
7497c478bd9Sstevel@tonic-gate * three or four if required.
7507c478bd9Sstevel@tonic-gate */
7517c478bd9Sstevel@tonic-gate { suffix = &(expbuf[4]) ; suffixlength = 4 ; }
7527c478bd9Sstevel@tonic-gate else if (n < 1000)
7537c478bd9Sstevel@tonic-gate { suffix = &(expbuf[3]) ; suffixlength = 5 ; }
7547c478bd9Sstevel@tonic-gate else
7557c478bd9Sstevel@tonic-gate { suffix = &(expbuf[2]) ; suffixlength = 6 ; }
7567c478bd9Sstevel@tonic-gate /* Put in the exponent sign */
7577c478bd9Sstevel@tonic-gate *--suffix = (decpt > 0 || convertbuffer[0] == '0' )? '+': '-';
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate /* Put in the e; note kludge in 'g' format */
7607c478bd9Sstevel@tonic-gate *--suffix = fcode;
7617c478bd9Sstevel@tonic-gate ebreak:
7627c478bd9Sstevel@tonic-gate #if FZERO
7637c478bd9Sstevel@tonic-gate if (compat_fzero &! fminus)
7647c478bd9Sstevel@tonic-gate /* Calculate padding zero requirement */
7657c478bd9Sstevel@tonic-gate lzero = width - (strlen(prefix)
7667c478bd9Sstevel@tonic-gate + (p - buf) + rzero + suffixlength);
7677c478bd9Sstevel@tonic-gate #endif
7687c478bd9Sstevel@tonic-gate break;
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate case 'f':
7717c478bd9Sstevel@tonic-gate /*
7727c478bd9Sstevel@tonic-gate * F-format floating point. This is
7737c478bd9Sstevel@tonic-gate * a good deal less simple than E-format.
7747c478bd9Sstevel@tonic-gate * The overall strategy will be to call
7757c478bd9Sstevel@tonic-gate * fconvert, reformat its result into buf,
7767c478bd9Sstevel@tonic-gate * and calculate how many trailing
7777c478bd9Sstevel@tonic-gate * zeroes will be required. There will
7787c478bd9Sstevel@tonic-gate * never be any leading zeroes needed.
7797c478bd9Sstevel@tonic-gate */
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate /* Establish default precision */
7827c478bd9Sstevel@tonic-gate if (prec < 0)
7837c478bd9Sstevel@tonic-gate prec = 6;
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate if (Lsize == 0) {
7867c478bd9Sstevel@tonic-gate dval = va_arg(args.ap, double);
7877c478bd9Sstevel@tonic-gate bp = fconvert(dval, prec, &decpt, &sign, convertbuffer);
7887c478bd9Sstevel@tonic-gate } else {
7897c478bd9Sstevel@tonic-gate GETQVAL ;
7907c478bd9Sstevel@tonic-gate bp = qfconvert(&qval, prec, &decpt, &sign, convertbuffer);
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate /* Determine the prefix */
7947c478bd9Sstevel@tonic-gate if (sign)
7957c478bd9Sstevel@tonic-gate prefix = "-";
7967c478bd9Sstevel@tonic-gate else if (fplus)
7977c478bd9Sstevel@tonic-gate prefix = "+";
7987c478bd9Sstevel@tonic-gate else if (fblank)
7997c478bd9Sstevel@tonic-gate prefix = " ";
8007c478bd9Sstevel@tonic-gate if (convertbuffer[0] > '9')
8017c478bd9Sstevel@tonic-gate { /* handle infinity, nan */
8027c478bd9Sstevel@tonic-gate bp = &convertbuffer[0];
8037c478bd9Sstevel@tonic-gate for (p = bp+1 ; *p != 0 ; p++) ;
8047c478bd9Sstevel@tonic-gate goto fbreak ;
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate {
807*5d54f3d8Smuffin char *stringp;
8087c478bd9Sstevel@tonic-gate /* Initialize buffer pointer */
8097c478bd9Sstevel@tonic-gate stringp = &buf[0];
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate /* Emit the digits before the decimal point */
8127c478bd9Sstevel@tonic-gate n = decpt;
8137c478bd9Sstevel@tonic-gate if (n <= 0)
8147c478bd9Sstevel@tonic-gate *stringp++ = '0';
8157c478bd9Sstevel@tonic-gate else
8167c478bd9Sstevel@tonic-gate do
8177c478bd9Sstevel@tonic-gate if (*bp == '\0' )
8187c478bd9Sstevel@tonic-gate *stringp++ = '0';
8197c478bd9Sstevel@tonic-gate else {
8207c478bd9Sstevel@tonic-gate *stringp++ = *bp++;
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate while (--n != 0);
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate /* Decide whether we need a decimal point */
8257c478bd9Sstevel@tonic-gate if (fsharp || prec > 0)
8267c478bd9Sstevel@tonic-gate *stringp++ = decpt_char;
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate /* Digits(if any) after the decimal point */
8297c478bd9Sstevel@tonic-gate n = prec;
8307c478bd9Sstevel@tonic-gate rzero = prec - n;
8317c478bd9Sstevel@tonic-gate while (--n >= 0) {
8327c478bd9Sstevel@tonic-gate if (++decpt <= 0 || *bp == '\0')
8337c478bd9Sstevel@tonic-gate *stringp++ = '0';
8347c478bd9Sstevel@tonic-gate else {
8357c478bd9Sstevel@tonic-gate *stringp++ = *bp++;
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate }
8387c478bd9Sstevel@tonic-gate #if FZERO
8397c478bd9Sstevel@tonic-gate if (compat_fzero &! fminus)
8407c478bd9Sstevel@tonic-gate /* Calculate padding zero requirement */
8417c478bd9Sstevel@tonic-gate lzero = width - (strlen(prefix)
8427c478bd9Sstevel@tonic-gate + (stringp - buf) + rzero);
8437c478bd9Sstevel@tonic-gate #endif
8447c478bd9Sstevel@tonic-gate p = stringp;
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate bp = &buf[0];
8487c478bd9Sstevel@tonic-gate fbreak:
8497c478bd9Sstevel@tonic-gate break;
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate case 'G':
8527c478bd9Sstevel@tonic-gate case 'g':
8537c478bd9Sstevel@tonic-gate /*
8547c478bd9Sstevel@tonic-gate * g-format. We play around a bit
8557c478bd9Sstevel@tonic-gate * and then jump into e or f, as needed.
8567c478bd9Sstevel@tonic-gate */
8577c478bd9Sstevel@tonic-gate
8587c478bd9Sstevel@tonic-gate /* Establish default precision */
8597c478bd9Sstevel@tonic-gate if (prec < 0)
8607c478bd9Sstevel@tonic-gate prec = 6;
8617c478bd9Sstevel@tonic-gate else if (prec == 0)
8627c478bd9Sstevel@tonic-gate prec = 1;
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate if (Lsize == 0) {
8657c478bd9Sstevel@tonic-gate dval = va_arg(args.ap, double);
8667c478bd9Sstevel@tonic-gate bp = gconvert(dval, prec, fsharp, convertbuffer);
8677c478bd9Sstevel@tonic-gate } else {
8687c478bd9Sstevel@tonic-gate GETQVAL;
8697c478bd9Sstevel@tonic-gate bp = qgconvert(&qval, prec, fsharp, convertbuffer);
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate bp = convertbuffer ;
8727c478bd9Sstevel@tonic-gate if (convertbuffer[0] == '-') {
8737c478bd9Sstevel@tonic-gate prefix = "-" ;
8747c478bd9Sstevel@tonic-gate bp++;
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate else if (fplus)
8777c478bd9Sstevel@tonic-gate prefix = "+";
8787c478bd9Sstevel@tonic-gate else if (fblank)
8797c478bd9Sstevel@tonic-gate prefix = " ";
8807c478bd9Sstevel@tonic-gate if (isupper(fcode))
8817c478bd9Sstevel@tonic-gate { /* Put in a big E for small minds. */
8827c478bd9Sstevel@tonic-gate for (p = bp ; (*p != NULL) && (*p != 'e') ; p++) ;
8837c478bd9Sstevel@tonic-gate if (*p == 'e') *p = 'E' ;
8847c478bd9Sstevel@tonic-gate for (; (*p != NULL) ; p++) ;
8857c478bd9Sstevel@tonic-gate /* Find end of string. */
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate else
8887c478bd9Sstevel@tonic-gate for (p = bp ; *p != NULL ; p++) ;
8897c478bd9Sstevel@tonic-gate /* Find end of string. */
8907c478bd9Sstevel@tonic-gate rzero = 0;
8917c478bd9Sstevel@tonic-gate #if FZERO
8927c478bd9Sstevel@tonic-gate if (compat_fzero & !fminus)
8937c478bd9Sstevel@tonic-gate /* Calculate padding zero requirement */
8947c478bd9Sstevel@tonic-gate lzero = width - (strlen(prefix)
8957c478bd9Sstevel@tonic-gate + (p - bp) + rzero);
8967c478bd9Sstevel@tonic-gate #endif
8977c478bd9Sstevel@tonic-gate break ;
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate #endif
9007c478bd9Sstevel@tonic-gate case 'c':
9017c478bd9Sstevel@tonic-gate buf[0] = va_arg(args.ap, int);
9027c478bd9Sstevel@tonic-gate bp = &buf[0];
9037c478bd9Sstevel@tonic-gate p = bp + 1;
9047c478bd9Sstevel@tonic-gate break;
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate case 's':
9077c478bd9Sstevel@tonic-gate bp = va_arg(args.ap, char *);
9087c478bd9Sstevel@tonic-gate if (prec < 0)
9097c478bd9Sstevel@tonic-gate prec = MAXINT;
9107c478bd9Sstevel@tonic-gate /* avoid *(0) */
9117c478bd9Sstevel@tonic-gate if (bp == NULL)
9127c478bd9Sstevel@tonic-gate bp = nullstr;
9137c478bd9Sstevel@tonic-gate for (n=0; *bp++ != '\0' && n < prec; n++)
9147c478bd9Sstevel@tonic-gate ;
9157c478bd9Sstevel@tonic-gate #if FZERO
9167c478bd9Sstevel@tonic-gate if (compat_fzero &! fminus)
9177c478bd9Sstevel@tonic-gate lzero = width - n;
9187c478bd9Sstevel@tonic-gate #endif
9197c478bd9Sstevel@tonic-gate p = --bp;
9207c478bd9Sstevel@tonic-gate bp -= n;
9217c478bd9Sstevel@tonic-gate break;
9227c478bd9Sstevel@tonic-gate
9237c478bd9Sstevel@tonic-gate case '\0':
9247c478bd9Sstevel@tonic-gate /* well, what's the punch line? */
9257c478bd9Sstevel@tonic-gate goto out;
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate case 'n':
9287c478bd9Sstevel@tonic-gate svswitch = 1;
9297c478bd9Sstevel@tonic-gate break;
9307c478bd9Sstevel@tonic-gate default:
9317c478bd9Sstevel@tonic-gate p = bp = &fcode;
9327c478bd9Sstevel@tonic-gate p++;
9337c478bd9Sstevel@tonic-gate break;
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate /* Calculate number of padding blanks */
9377c478bd9Sstevel@tonic-gate nblank = width
9387c478bd9Sstevel@tonic-gate #if FLOAT
9397c478bd9Sstevel@tonic-gate - (rzero < 0? 0: rzero)
9407c478bd9Sstevel@tonic-gate - strlen(suffix)
9417c478bd9Sstevel@tonic-gate #endif
9427c478bd9Sstevel@tonic-gate - (p - bp)
9437c478bd9Sstevel@tonic-gate - (lzero < 0? 0: lzero)
9447c478bd9Sstevel@tonic-gate - strlen(prefix);
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate /* Blanks on left if required */
9477c478bd9Sstevel@tonic-gate if (!fminus)
9487c478bd9Sstevel@tonic-gate while (--nblank >= 0)
9497c478bd9Sstevel@tonic-gate emitchar(' ');
9507c478bd9Sstevel@tonic-gate
9517c478bd9Sstevel@tonic-gate /* Prefix, if any */
9527c478bd9Sstevel@tonic-gate while (*prefix != '\0') {
9537c478bd9Sstevel@tonic-gate emitchar(*prefix);
9547c478bd9Sstevel@tonic-gate prefix++;
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate /* Zeroes on the left */
9587c478bd9Sstevel@tonic-gate while (--lzero >= 0)
9597c478bd9Sstevel@tonic-gate emitchar('0');
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate /* The value itself */
9627c478bd9Sstevel@tonic-gate while (bp < p) {
9637c478bd9Sstevel@tonic-gate emitchar(*bp);
9647c478bd9Sstevel@tonic-gate bp++;
9657c478bd9Sstevel@tonic-gate }
9667c478bd9Sstevel@tonic-gate #if FLOAT
9677c478bd9Sstevel@tonic-gate /* Zeroes on the right */
9687c478bd9Sstevel@tonic-gate while (--rzero >= 0)
9697c478bd9Sstevel@tonic-gate emitchar('0');
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate /* The suffix */
9727c478bd9Sstevel@tonic-gate while (*suffix != '\0') {
9737c478bd9Sstevel@tonic-gate emitchar(*suffix);
9747c478bd9Sstevel@tonic-gate suffix++;
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate #endif
9777c478bd9Sstevel@tonic-gate /* Blanks on the right if required */
9787c478bd9Sstevel@tonic-gate if (fminus)
9797c478bd9Sstevel@tonic-gate while (--nblank >= 0)
9807c478bd9Sstevel@tonic-gate emitchar(' ');
9817c478bd9Sstevel@tonic-gate /* If %n is seen, save count in argument */
9827c478bd9Sstevel@tonic-gate if (svswitch == 1) {
9837c478bd9Sstevel@tonic-gate long *svcount;
9847c478bd9Sstevel@tonic-gate svcount = va_arg (args.ap, long *);
9857c478bd9Sstevel@tonic-gate *svcount = count;
9867c478bd9Sstevel@tonic-gate svswitch = 0;
9877c478bd9Sstevel@tonic-gate }
9887c478bd9Sstevel@tonic-gate } /* else */
9897c478bd9Sstevel@tonic-gate } while ((c = *cp++) != '\0'); /* do */
9907c478bd9Sstevel@tonic-gate out:
9917c478bd9Sstevel@tonic-gate file->_ptr = fileptr;
9927c478bd9Sstevel@tonic-gate file->_cnt = filecnt;
9937c478bd9Sstevel@tonic-gate if (file->_flag & (_IONBF | _IOLBF) &&
9947c478bd9Sstevel@tonic-gate (file->_flag & _IONBF ||
9957c478bd9Sstevel@tonic-gate memchr((char *)file->_base, '\n', fileptr - file->_base) != NULL))
9967c478bd9Sstevel@tonic-gate (void) _xflsbuf(file);
9977c478bd9Sstevel@tonic-gate return (ferror(file)? EOF: count);
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate
1000*5d54f3d8Smuffin #if defined(__sparc)
10017c478bd9Sstevel@tonic-gate /*
10027c478bd9Sstevel@tonic-gate * We use "double *" instead of "quadruple *" to skip over the pointer to
10037c478bd9Sstevel@tonic-gate * long double on the argument list since a pointer is a pointer after all.
10047c478bd9Sstevel@tonic-gate */
10057c478bd9Sstevel@tonic-gate #define SKIPQVAL { \
10067c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, double *); \
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate #else /* Sun-3 */
10097c478bd9Sstevel@tonic-gate #define SKIPQVAL { \
10107c478bd9Sstevel@tonic-gate int iq; \
10117c478bd9Sstevel@tonic-gate for (iq = 0; iq < 4; iq++) \
10127c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, unsigned long); \
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate #endif
1015*5d54f3d8Smuffin /*
1016*5d54f3d8Smuffin * This function initializes arglst, to contain the appropriate va_list values
1017*5d54f3d8Smuffin * for the first MAXARGS arguments.
1018*5d54f3d8Smuffin */
10197c478bd9Sstevel@tonic-gate void
_mkarglst(char * fmt,stva_list args,stva_list arglst[])1020*5d54f3d8Smuffin _mkarglst(char *fmt, stva_list args, stva_list arglst[])
10217c478bd9Sstevel@tonic-gate {
10227c478bd9Sstevel@tonic-gate static char *digits = "01234567890", *skips = "# +-.0123456789h$";
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR,
10257c478bd9Sstevel@tonic-gate LONG_PTR, INT_PTR};
10267c478bd9Sstevel@tonic-gate enum types typelst[MAXARGS], curtype;
10277c478bd9Sstevel@tonic-gate int maxnum, n, curargno, flags;
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate /*
10307c478bd9Sstevel@tonic-gate * Algorithm 1. set all argument types to zero.
10317c478bd9Sstevel@tonic-gate * 2. walk through fmt putting arg types in typelst[].
10327c478bd9Sstevel@tonic-gate * 3. walk through args using va_arg(args.ap, typelst[n])
10337c478bd9Sstevel@tonic-gate * and set arglst[] to the appropriate values.
10347c478bd9Sstevel@tonic-gate * Assumptions: Cannot use %*$... to specify variable position.
10357c478bd9Sstevel@tonic-gate */
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate (void)memset((void *)typelst, 0, sizeof(typelst));
10387c478bd9Sstevel@tonic-gate maxnum = -1;
10397c478bd9Sstevel@tonic-gate curargno = 0;
10407c478bd9Sstevel@tonic-gate while ((fmt = strchr(fmt, '%')) != 0)
10417c478bd9Sstevel@tonic-gate {
10427c478bd9Sstevel@tonic-gate fmt++; /* skip % */
10437c478bd9Sstevel@tonic-gate if (fmt[n = strspn(fmt, digits)] == '$')
10447c478bd9Sstevel@tonic-gate {
10457c478bd9Sstevel@tonic-gate curargno = atoi(fmt) - 1; /* convert to zero base */
10467c478bd9Sstevel@tonic-gate fmt += n + 1;
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate flags = 0;
10497c478bd9Sstevel@tonic-gate again:;
10507c478bd9Sstevel@tonic-gate fmt += strspn(fmt, skips);
10517c478bd9Sstevel@tonic-gate switch (*fmt++)
10527c478bd9Sstevel@tonic-gate {
10537c478bd9Sstevel@tonic-gate case '%': /*there is no argument! */
10547c478bd9Sstevel@tonic-gate continue;
10557c478bd9Sstevel@tonic-gate case 'l':
10567c478bd9Sstevel@tonic-gate flags |= 0x1;
10577c478bd9Sstevel@tonic-gate goto again;
10587c478bd9Sstevel@tonic-gate case 'L':
10597c478bd9Sstevel@tonic-gate flags |= 0x8;
10607c478bd9Sstevel@tonic-gate goto again;
10617c478bd9Sstevel@tonic-gate case '*': /* int argument used for value */
10627c478bd9Sstevel@tonic-gate flags |= 0x2;
10637c478bd9Sstevel@tonic-gate curtype = INT;
10647c478bd9Sstevel@tonic-gate break;
10657c478bd9Sstevel@tonic-gate case 'e':
10667c478bd9Sstevel@tonic-gate case 'E':
10677c478bd9Sstevel@tonic-gate case 'f':
10687c478bd9Sstevel@tonic-gate case 'g':
10697c478bd9Sstevel@tonic-gate case 'G':
10707c478bd9Sstevel@tonic-gate if (flags & 0x8)
10717c478bd9Sstevel@tonic-gate curtype = LONG_DOUBLE;
10727c478bd9Sstevel@tonic-gate else
10737c478bd9Sstevel@tonic-gate curtype = DOUBLE;
10747c478bd9Sstevel@tonic-gate break;
10757c478bd9Sstevel@tonic-gate case 's':
10767c478bd9Sstevel@tonic-gate curtype = CHAR_PTR;
10777c478bd9Sstevel@tonic-gate break;
10787c478bd9Sstevel@tonic-gate case 'p':
10797c478bd9Sstevel@tonic-gate curtype = VOID_PTR;
10807c478bd9Sstevel@tonic-gate break;
10817c478bd9Sstevel@tonic-gate case 'n':
10827c478bd9Sstevel@tonic-gate if (flags & 0x1)
10837c478bd9Sstevel@tonic-gate curtype = LONG_PTR;
10847c478bd9Sstevel@tonic-gate else
10857c478bd9Sstevel@tonic-gate curtype = INT_PTR;
10867c478bd9Sstevel@tonic-gate break;
10877c478bd9Sstevel@tonic-gate default:
10887c478bd9Sstevel@tonic-gate if (flags & 0x1)
10897c478bd9Sstevel@tonic-gate curtype = LONG;
10907c478bd9Sstevel@tonic-gate else
10917c478bd9Sstevel@tonic-gate curtype = INT;
10927c478bd9Sstevel@tonic-gate break;
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate if (curargno >= 0 && curargno < MAXARGS)
10957c478bd9Sstevel@tonic-gate {
10967c478bd9Sstevel@tonic-gate typelst[curargno] = curtype;
10977c478bd9Sstevel@tonic-gate if (maxnum < curargno)
10987c478bd9Sstevel@tonic-gate maxnum = curargno;
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate curargno++; /* default to next in list */
11017c478bd9Sstevel@tonic-gate if (flags & 0x2) /* took care of *, keep going */
11027c478bd9Sstevel@tonic-gate {
11037c478bd9Sstevel@tonic-gate flags ^= 0x2;
11047c478bd9Sstevel@tonic-gate goto again;
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate for (n = 0 ; n <= maxnum; n++)
11087c478bd9Sstevel@tonic-gate {
11097c478bd9Sstevel@tonic-gate arglst[n] = args;
11107c478bd9Sstevel@tonic-gate if (typelst[n] == 0)
11117c478bd9Sstevel@tonic-gate typelst[n] = INT;
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate switch (typelst[n])
11147c478bd9Sstevel@tonic-gate {
11157c478bd9Sstevel@tonic-gate case INT:
11167c478bd9Sstevel@tonic-gate va_arg(args.ap, int);
11177c478bd9Sstevel@tonic-gate break;
11187c478bd9Sstevel@tonic-gate case LONG:
11197c478bd9Sstevel@tonic-gate va_arg(args.ap, long);
11207c478bd9Sstevel@tonic-gate break;
11217c478bd9Sstevel@tonic-gate case CHAR_PTR:
11227c478bd9Sstevel@tonic-gate va_arg(args.ap, char *);
11237c478bd9Sstevel@tonic-gate break;
11247c478bd9Sstevel@tonic-gate case DOUBLE:
11257c478bd9Sstevel@tonic-gate va_arg(args.ap, double);
11267c478bd9Sstevel@tonic-gate break;
11277c478bd9Sstevel@tonic-gate case LONG_DOUBLE:
11287c478bd9Sstevel@tonic-gate SKIPQVAL
11297c478bd9Sstevel@tonic-gate break;
11307c478bd9Sstevel@tonic-gate case VOID_PTR:
11317c478bd9Sstevel@tonic-gate va_arg(args.ap, void *);
11327c478bd9Sstevel@tonic-gate break;
11337c478bd9Sstevel@tonic-gate case LONG_PTR:
11347c478bd9Sstevel@tonic-gate va_arg(args.ap, long *);
11357c478bd9Sstevel@tonic-gate break;
11367c478bd9Sstevel@tonic-gate case INT_PTR:
11377c478bd9Sstevel@tonic-gate va_arg(args.ap, int *);
11387c478bd9Sstevel@tonic-gate break;
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate /*
11447c478bd9Sstevel@tonic-gate * This function is used to find the va_list value for arguments whose
11457c478bd9Sstevel@tonic-gate * position is greater than MAXARGS. This function is slow, so hopefully
11467c478bd9Sstevel@tonic-gate * MAXARGS will be big enough so that this function need only be called in
11477c478bd9Sstevel@tonic-gate * unusual circumstances.
11487c478bd9Sstevel@tonic-gate * pargs is assumed to contain the value of arglst[MAXARGS - 1].
11497c478bd9Sstevel@tonic-gate */
11507c478bd9Sstevel@tonic-gate void
_getarg(char * fmt,stva_list * pargs,int argno)1151*5d54f3d8Smuffin _getarg(char *fmt, stva_list *pargs, int argno)
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate static char *digits = "01234567890", *skips = "# +-.0123456789h$";
11547c478bd9Sstevel@tonic-gate int i, n, curargno, flags;
11557c478bd9Sstevel@tonic-gate char *sfmt = fmt;
11567c478bd9Sstevel@tonic-gate int found = 1;
11577c478bd9Sstevel@tonic-gate
11587c478bd9Sstevel@tonic-gate curargno = i = MAXARGS;
11597c478bd9Sstevel@tonic-gate while (found)
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate fmt = sfmt;
11627c478bd9Sstevel@tonic-gate found = 0;
11637c478bd9Sstevel@tonic-gate while ((i != argno) && (fmt = strchr(fmt, '%')) != 0)
11647c478bd9Sstevel@tonic-gate {
11657c478bd9Sstevel@tonic-gate fmt++; /* skip % */
11667c478bd9Sstevel@tonic-gate if (fmt[n = strspn(fmt, digits)] == '$')
11677c478bd9Sstevel@tonic-gate {
11687c478bd9Sstevel@tonic-gate curargno = atoi(fmt);
11697c478bd9Sstevel@tonic-gate fmt += n + 1;
11707c478bd9Sstevel@tonic-gate }
11717c478bd9Sstevel@tonic-gate
11727c478bd9Sstevel@tonic-gate /* find conversion specifier for next argument */
11737c478bd9Sstevel@tonic-gate if (i != curargno)
11747c478bd9Sstevel@tonic-gate {
11757c478bd9Sstevel@tonic-gate curargno++;
11767c478bd9Sstevel@tonic-gate continue;
11777c478bd9Sstevel@tonic-gate } else
11787c478bd9Sstevel@tonic-gate found = 1;
11797c478bd9Sstevel@tonic-gate flags = 0;
11807c478bd9Sstevel@tonic-gate again:;
11817c478bd9Sstevel@tonic-gate fmt += strspn(fmt, skips);
11827c478bd9Sstevel@tonic-gate switch (*fmt++)
11837c478bd9Sstevel@tonic-gate {
11847c478bd9Sstevel@tonic-gate case '%': /*there is no argument! */
11857c478bd9Sstevel@tonic-gate continue;
11867c478bd9Sstevel@tonic-gate case 'l':
11877c478bd9Sstevel@tonic-gate flags |= 0x1;
11887c478bd9Sstevel@tonic-gate goto again;
11897c478bd9Sstevel@tonic-gate case 'L':
11907c478bd9Sstevel@tonic-gate flags |= 0x8;
11917c478bd9Sstevel@tonic-gate goto again;
11927c478bd9Sstevel@tonic-gate case '*': /* int argument used for value */
11937c478bd9Sstevel@tonic-gate flags |= 0x2;
11947c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, int);
11957c478bd9Sstevel@tonic-gate break;
11967c478bd9Sstevel@tonic-gate case 'e':
11977c478bd9Sstevel@tonic-gate case 'E':
11987c478bd9Sstevel@tonic-gate case 'f':
11997c478bd9Sstevel@tonic-gate case 'g':
12007c478bd9Sstevel@tonic-gate case 'G':
12017c478bd9Sstevel@tonic-gate if (flags & 0x8) {
12027c478bd9Sstevel@tonic-gate #define args (*pargs)
12037c478bd9Sstevel@tonic-gate SKIPQVAL
12047c478bd9Sstevel@tonic-gate #undef args
12057c478bd9Sstevel@tonic-gate }
12067c478bd9Sstevel@tonic-gate else
12077c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, double);
12087c478bd9Sstevel@tonic-gate break;
12097c478bd9Sstevel@tonic-gate case 's':
12107c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, char *);
12117c478bd9Sstevel@tonic-gate break;
12127c478bd9Sstevel@tonic-gate case 'p':
12137c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, void *);
12147c478bd9Sstevel@tonic-gate break;
12157c478bd9Sstevel@tonic-gate case 'n':
12167c478bd9Sstevel@tonic-gate if (flags & 0x1)
12177c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, long *);
12187c478bd9Sstevel@tonic-gate else
12197c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, int *);
12207c478bd9Sstevel@tonic-gate break;
12217c478bd9Sstevel@tonic-gate default:
12227c478bd9Sstevel@tonic-gate if (flags & 0x1)
12237c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, long int);
12247c478bd9Sstevel@tonic-gate else
12257c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, int);
12267c478bd9Sstevel@tonic-gate break;
12277c478bd9Sstevel@tonic-gate }
12287c478bd9Sstevel@tonic-gate i++;
12297c478bd9Sstevel@tonic-gate curargno++; /* default to next in list */
12307c478bd9Sstevel@tonic-gate if (flags & 0x2) /* took care of *, keep going */
12317c478bd9Sstevel@tonic-gate {
12327c478bd9Sstevel@tonic-gate flags ^= 0x2;
12337c478bd9Sstevel@tonic-gate goto again;
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate }
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate /* missing specifier for parameter, assume parameter is an int */
12387c478bd9Sstevel@tonic-gate if (!found && i != argno) {
12397c478bd9Sstevel@tonic-gate (void)va_arg((*pargs).ap, int);
12407c478bd9Sstevel@tonic-gate i++;
12417c478bd9Sstevel@tonic-gate curargno++;
12427c478bd9Sstevel@tonic-gate found = 1;
12437c478bd9Sstevel@tonic-gate }
12447c478bd9Sstevel@tonic-gate }
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate /*
12497c478bd9Sstevel@tonic-gate * parse a string, mini parse
12507c478bd9Sstevel@tonic-gate */
12517c478bd9Sstevel@tonic-gate static char *
_check_dol(char * s,int * val)1252*5d54f3d8Smuffin _check_dol(char *s, int *val)
12537c478bd9Sstevel@tonic-gate {
12547c478bd9Sstevel@tonic-gate char *os; /* save old string */
12557c478bd9Sstevel@tonic-gate int tmp_val = 0;
12567c478bd9Sstevel@tonic-gate int flag = 0;
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate while (isdigit (*s)) {
12597c478bd9Sstevel@tonic-gate ++flag;
12607c478bd9Sstevel@tonic-gate tmp_val = tmp_val*10 + *s - '0';
12617c478bd9Sstevel@tonic-gate s++;
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate if (flag == 0)
12647c478bd9Sstevel@tonic-gate return ((char *)NULL);
12657c478bd9Sstevel@tonic-gate if (*s == '$') {
12667c478bd9Sstevel@tonic-gate *val = tmp_val;
12677c478bd9Sstevel@tonic-gate return(++s);
12687c478bd9Sstevel@tonic-gate }
12697c478bd9Sstevel@tonic-gate return ((char *)NULL);
12707c478bd9Sstevel@tonic-gate }
1271