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 */
22*f6db9f27Scf46844 /*
23*f6db9f27Scf46844 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*f6db9f27Scf46844 * Use is subject to license terms.
25*f6db9f27Scf46844 */
26*f6db9f27Scf46844
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
327c478bd9Sstevel@tonic-gate * The Regents of the University of California
337c478bd9Sstevel@tonic-gate * All Rights Reserved
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
367c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
377c478bd9Sstevel@tonic-gate * contributors.
387c478bd9Sstevel@tonic-gate */
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate /* The pwb version this is based on */
417c478bd9Sstevel@tonic-gate static char *printf_id = "@(#) printf.c:2.2 6/5/79";
427c478bd9Sstevel@tonic-gate /* The local sccs version within ex */
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include <stdarg.h>
477c478bd9Sstevel@tonic-gate #include <stdlib.h>
487c478bd9Sstevel@tonic-gate #include <limits.h>
497c478bd9Sstevel@tonic-gate extern short putoctal;
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate * This version of printf is compatible with the Version 7 C
52*f6db9f27Scf46844 * printf. The differences are only minor except that
53*f6db9f27Scf46844 * viprintf assumes it is to print through putchar. Version 7
547c478bd9Sstevel@tonic-gate * printf is more general (and is much larger) and includes
557c478bd9Sstevel@tonic-gate * provisions for floating point.
567c478bd9Sstevel@tonic-gate */
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate #define MAXOCT 11 /* Maximum octal digits in a long */
607c478bd9Sstevel@tonic-gate #define MAXINT 32767 /* largest normal length positive integer */
617c478bd9Sstevel@tonic-gate #define BIG 1000000000 /* largest power of 10 less than an unsigned long */
627c478bd9Sstevel@tonic-gate #define MAXDIGS 10 /* number of digits in BIG */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static int width, sign, fill;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate unsigned char *_p_dconv();
67*f6db9f27Scf46844 void _p_emit(unsigned char *, unsigned char *);
687c478bd9Sstevel@tonic-gate
69*f6db9f27Scf46844 /*VARARGS*/
70*f6db9f27Scf46844 void
viprintf(unsigned char * fmt,...)71*f6db9f27Scf46844 viprintf(unsigned char *fmt, ...)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate va_list ap;
747c478bd9Sstevel@tonic-gate unsigned char fcode;
757c478bd9Sstevel@tonic-gate wchar_t wfcode;
767c478bd9Sstevel@tonic-gate int prec;
777c478bd9Sstevel@tonic-gate int length,mask1,nbits,n;
787c478bd9Sstevel@tonic-gate int length2;
797c478bd9Sstevel@tonic-gate long int mask2, num;
80*f6db9f27Scf46844 unsigned char *bptr;
817c478bd9Sstevel@tonic-gate unsigned char *ptr;
827c478bd9Sstevel@tonic-gate unsigned char buf[134];
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate va_start(ap, fmt);
857c478bd9Sstevel@tonic-gate for (;;) {
867c478bd9Sstevel@tonic-gate /* process format string first */
877c478bd9Sstevel@tonic-gate for (;;) {
887c478bd9Sstevel@tonic-gate length2 = mbtowc(&wfcode, (char *)fmt, MB_LEN_MAX);
897c478bd9Sstevel@tonic-gate if(length2 <= 0) {
907c478bd9Sstevel@tonic-gate if (*fmt == '\0') {
917c478bd9Sstevel@tonic-gate fmt++;
927c478bd9Sstevel@tonic-gate return;
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate putchar(*fmt++);
957c478bd9Sstevel@tonic-gate } else {
967c478bd9Sstevel@tonic-gate if (wfcode == '%') {
977c478bd9Sstevel@tonic-gate fmt++;
987c478bd9Sstevel@tonic-gate break;
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate /* ordinary (non-%) character */
1017c478bd9Sstevel@tonic-gate putchar(wfcode);
1027c478bd9Sstevel@tonic-gate fmt += length2;
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate /* length modifier: -1 for h, 1 for l, 0 for none */
1067c478bd9Sstevel@tonic-gate length = 0;
1077c478bd9Sstevel@tonic-gate /* check for a leading - sign */
1087c478bd9Sstevel@tonic-gate sign = 0;
1097c478bd9Sstevel@tonic-gate if (*fmt == '-') {
1107c478bd9Sstevel@tonic-gate sign++;
1117c478bd9Sstevel@tonic-gate fmt++;
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate /* a '0' may follow the - sign */
1147c478bd9Sstevel@tonic-gate /* this is the requested fill character */
1157c478bd9Sstevel@tonic-gate fill = 1;
1167c478bd9Sstevel@tonic-gate if (*fmt == '0') {
1177c478bd9Sstevel@tonic-gate fill--;
1187c478bd9Sstevel@tonic-gate fmt++;
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /* Now comes a digit string which may be a '*' */
1227c478bd9Sstevel@tonic-gate if (*fmt == '*') {
1237c478bd9Sstevel@tonic-gate width = va_arg(ap, int);
1247c478bd9Sstevel@tonic-gate if (width < 0) {
1257c478bd9Sstevel@tonic-gate width = -width;
1267c478bd9Sstevel@tonic-gate sign = !sign;
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate fmt++;
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate else {
1317c478bd9Sstevel@tonic-gate width = 0;
1327c478bd9Sstevel@tonic-gate while (*fmt>='0' && *fmt<='9')
1337c478bd9Sstevel@tonic-gate width = width * 10 + (*fmt++ - '0');
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate /* maybe a decimal point followed by more digits (or '*') */
1377c478bd9Sstevel@tonic-gate if (*fmt=='.') {
1387c478bd9Sstevel@tonic-gate if (*++fmt == '*') {
1397c478bd9Sstevel@tonic-gate prec = va_arg(ap, int);
1407c478bd9Sstevel@tonic-gate fmt++;
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate else {
1437c478bd9Sstevel@tonic-gate prec = 0;
1447c478bd9Sstevel@tonic-gate while (*fmt>='0' && *fmt<='9')
1457c478bd9Sstevel@tonic-gate prec = prec * 10 + (*fmt++ - '0');
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate else
1497c478bd9Sstevel@tonic-gate prec = -1;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * At this point, "sign" is nonzero if there was
1537c478bd9Sstevel@tonic-gate * a sign, "fill" is 0 if there was a leading
1547c478bd9Sstevel@tonic-gate * zero and 1 otherwise, "width" and "prec"
1557c478bd9Sstevel@tonic-gate * contain numbers corresponding to the digit
1567c478bd9Sstevel@tonic-gate * strings before and after the decimal point,
1577c478bd9Sstevel@tonic-gate * respectively, and "fmt" addresses the next
1587c478bd9Sstevel@tonic-gate * character after the whole mess. If there was
1597c478bd9Sstevel@tonic-gate * no decimal point, "prec" will be -1.
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate switch (*fmt) {
1627c478bd9Sstevel@tonic-gate case 'L':
1637c478bd9Sstevel@tonic-gate case 'l':
1647c478bd9Sstevel@tonic-gate length = 2;
1657c478bd9Sstevel@tonic-gate /* no break!! */
1667c478bd9Sstevel@tonic-gate case 'h':
1677c478bd9Sstevel@tonic-gate case 'H':
1687c478bd9Sstevel@tonic-gate length--;
1697c478bd9Sstevel@tonic-gate fmt++;
1707c478bd9Sstevel@tonic-gate break;
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate * At exit from the following switch, we will
1757c478bd9Sstevel@tonic-gate * emit the characters starting at "bptr" and
1767c478bd9Sstevel@tonic-gate * ending at "ptr"-1, unless fcode is '\0'.
1777c478bd9Sstevel@tonic-gate */
1787c478bd9Sstevel@tonic-gate switch (fcode = *fmt++) {
1797c478bd9Sstevel@tonic-gate /* process characters and strings first */
1807c478bd9Sstevel@tonic-gate case 'c':
1817c478bd9Sstevel@tonic-gate buf[0] = va_arg(ap, int);
1827c478bd9Sstevel@tonic-gate ptr = bptr = &buf[0];
1837c478bd9Sstevel@tonic-gate if (buf[0] != '\0')
1847c478bd9Sstevel@tonic-gate ptr++;
1857c478bd9Sstevel@tonic-gate break;
1867c478bd9Sstevel@tonic-gate case 's':
1877c478bd9Sstevel@tonic-gate bptr = va_arg(ap,unsigned char *);
1887c478bd9Sstevel@tonic-gate if (bptr==0)
1897c478bd9Sstevel@tonic-gate bptr = (unsigned char *)"(null pointer)";
1907c478bd9Sstevel@tonic-gate if (prec < 0)
1917c478bd9Sstevel@tonic-gate prec = MAXINT;
1927c478bd9Sstevel@tonic-gate for (n=0; *bptr++ && n < prec; n++) ;
1937c478bd9Sstevel@tonic-gate ptr = --bptr;
1947c478bd9Sstevel@tonic-gate bptr -= n;
1957c478bd9Sstevel@tonic-gate break;
1967c478bd9Sstevel@tonic-gate case 'O':
1977c478bd9Sstevel@tonic-gate length = 1;
1987c478bd9Sstevel@tonic-gate fcode = 'o';
1997c478bd9Sstevel@tonic-gate /* no break */
2007c478bd9Sstevel@tonic-gate case 'o':
2017c478bd9Sstevel@tonic-gate case 'X':
2027c478bd9Sstevel@tonic-gate case 'x':
2037c478bd9Sstevel@tonic-gate if (length > 0)
2047c478bd9Sstevel@tonic-gate num = va_arg(ap,long);
2057c478bd9Sstevel@tonic-gate else
2067c478bd9Sstevel@tonic-gate num = (unsigned)va_arg(ap,int);
2077c478bd9Sstevel@tonic-gate if (fcode=='o') {
2087c478bd9Sstevel@tonic-gate mask1 = 0x7;
2097c478bd9Sstevel@tonic-gate mask2 = 0x1fffffffL;
2107c478bd9Sstevel@tonic-gate nbits = 3;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate else {
2137c478bd9Sstevel@tonic-gate mask1 = 0xf;
2147c478bd9Sstevel@tonic-gate mask2 = 0x0fffffffL;
2157c478bd9Sstevel@tonic-gate nbits = 4;
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate n = (num!=0);
2187c478bd9Sstevel@tonic-gate bptr = buf + MAXOCT + 3;
2197c478bd9Sstevel@tonic-gate /* shift and mask for speed */
2207c478bd9Sstevel@tonic-gate do
2217c478bd9Sstevel@tonic-gate if (((int) num & mask1) < 10)
2227c478bd9Sstevel@tonic-gate *--bptr = ((int) num & mask1) + 060;
2237c478bd9Sstevel@tonic-gate else
2247c478bd9Sstevel@tonic-gate *--bptr = ((int) num & mask1) + 0127;
2257c478bd9Sstevel@tonic-gate while (num = (num >> nbits) & mask2);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate if (fcode=='o') {
2287c478bd9Sstevel@tonic-gate if (n)
2297c478bd9Sstevel@tonic-gate *--bptr = '0';
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate else
2327c478bd9Sstevel@tonic-gate if (!sign && fill <= 0) {
2337c478bd9Sstevel@tonic-gate putchar('0');
2347c478bd9Sstevel@tonic-gate putchar(fcode);
2357c478bd9Sstevel@tonic-gate width -= 2;
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate else {
2387c478bd9Sstevel@tonic-gate *--bptr = fcode;
2397c478bd9Sstevel@tonic-gate *--bptr = '0';
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate ptr = buf + MAXOCT + 3;
2427c478bd9Sstevel@tonic-gate break;
2437c478bd9Sstevel@tonic-gate case 'D':
2447c478bd9Sstevel@tonic-gate case 'U':
2457c478bd9Sstevel@tonic-gate case 'I':
2467c478bd9Sstevel@tonic-gate length = 1;
2477c478bd9Sstevel@tonic-gate fcode = fcode + 'a' - 'A';
2487c478bd9Sstevel@tonic-gate /* no break */
2497c478bd9Sstevel@tonic-gate case 'd':
2507c478bd9Sstevel@tonic-gate case 'i':
2517c478bd9Sstevel@tonic-gate case 'u':
2527c478bd9Sstevel@tonic-gate if (length > 0)
2537c478bd9Sstevel@tonic-gate num = va_arg(ap,long);
2547c478bd9Sstevel@tonic-gate else {
2557c478bd9Sstevel@tonic-gate n = va_arg(ap,int);
2567c478bd9Sstevel@tonic-gate if (fcode=='u')
2577c478bd9Sstevel@tonic-gate num = (unsigned) n;
2587c478bd9Sstevel@tonic-gate else
2597c478bd9Sstevel@tonic-gate num = (long) n;
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate if (n = (fcode != 'u' && num < 0))
2627c478bd9Sstevel@tonic-gate num = -num;
2637c478bd9Sstevel@tonic-gate /* now convert to digits */
2647c478bd9Sstevel@tonic-gate bptr = _p_dconv(num, buf);
2657c478bd9Sstevel@tonic-gate if (n)
2667c478bd9Sstevel@tonic-gate *--bptr = '-';
2677c478bd9Sstevel@tonic-gate if (fill == 0)
2687c478bd9Sstevel@tonic-gate fill = -1;
2697c478bd9Sstevel@tonic-gate ptr = buf + MAXDIGS + 1;
2707c478bd9Sstevel@tonic-gate break;
2717c478bd9Sstevel@tonic-gate default:
2727c478bd9Sstevel@tonic-gate /* not a control character,
2737c478bd9Sstevel@tonic-gate * print it.
2747c478bd9Sstevel@tonic-gate */
2757c478bd9Sstevel@tonic-gate ptr = bptr = &fcode;
2767c478bd9Sstevel@tonic-gate ptr++;
2777c478bd9Sstevel@tonic-gate break;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate if (fcode != '\0')
2807c478bd9Sstevel@tonic-gate _p_emit(bptr,ptr);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate va_end(ap);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate /* _p_dconv converts the unsigned long integer "value" to
2867c478bd9Sstevel@tonic-gate * printable decimal and places it in "buffer", right-justified.
2877c478bd9Sstevel@tonic-gate * The value returned is the address of the first non-zero character,
2887c478bd9Sstevel@tonic-gate * or the address of the last character if all are zero.
2897c478bd9Sstevel@tonic-gate * The result is NOT null terminated, and is MAXDIGS characters long,
2907c478bd9Sstevel@tonic-gate * starting at buffer[1] (to allow for insertion of a sign).
2917c478bd9Sstevel@tonic-gate *
2927c478bd9Sstevel@tonic-gate * This program assumes it is running on 2's complement machine
2937c478bd9Sstevel@tonic-gate * with reasonable overflow treatment.
2947c478bd9Sstevel@tonic-gate */
2957c478bd9Sstevel@tonic-gate unsigned char *
_p_dconv(value,buffer)2967c478bd9Sstevel@tonic-gate _p_dconv(value, buffer)
2977c478bd9Sstevel@tonic-gate long value;
2987c478bd9Sstevel@tonic-gate unsigned char *buffer;
2997c478bd9Sstevel@tonic-gate {
300*f6db9f27Scf46844 unsigned char *bp;
301*f6db9f27Scf46844 int svalue;
3027c478bd9Sstevel@tonic-gate int n;
3037c478bd9Sstevel@tonic-gate long lval;
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate bp = buffer;
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /* zero is a special case */
3087c478bd9Sstevel@tonic-gate if (value == 0) {
3097c478bd9Sstevel@tonic-gate bp += MAXDIGS;
3107c478bd9Sstevel@tonic-gate *bp = '0';
3117c478bd9Sstevel@tonic-gate return(bp);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /* develop the leading digit of the value in "n" */
3157c478bd9Sstevel@tonic-gate n = 0;
3167c478bd9Sstevel@tonic-gate while (value < 0) {
3177c478bd9Sstevel@tonic-gate value -= BIG; /* will eventually underflow */
3187c478bd9Sstevel@tonic-gate n++;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate while ((lval = value - BIG) >= 0) {
3217c478bd9Sstevel@tonic-gate value = lval;
3227c478bd9Sstevel@tonic-gate n++;
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /* stash it in buffer[1] to allow for a sign */
3267c478bd9Sstevel@tonic-gate bp[1] = n + '0';
3277c478bd9Sstevel@tonic-gate /*
3287c478bd9Sstevel@tonic-gate * Now develop the rest of the digits. Since speed counts here,
3297c478bd9Sstevel@tonic-gate * we do it in two loops. The first gets "value" down until it
3307c478bd9Sstevel@tonic-gate * is no larger than MAXINT. The second one uses integer divides
3317c478bd9Sstevel@tonic-gate * rather than long divides to speed it up.
3327c478bd9Sstevel@tonic-gate */
3337c478bd9Sstevel@tonic-gate bp += MAXDIGS + 1;
3347c478bd9Sstevel@tonic-gate while (value > MAXINT) {
3357c478bd9Sstevel@tonic-gate *--bp = (int)(value % 10) + '0';
3367c478bd9Sstevel@tonic-gate value /= 10;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /* cannot lose precision */
3407c478bd9Sstevel@tonic-gate svalue = value;
3417c478bd9Sstevel@tonic-gate while (svalue > 0) {
3427c478bd9Sstevel@tonic-gate *--bp = (svalue % 10) + '0';
3437c478bd9Sstevel@tonic-gate svalue /= 10;
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate /* fill in intermediate zeroes if needed */
3477c478bd9Sstevel@tonic-gate if (buffer[1] != '0') {
3487c478bd9Sstevel@tonic-gate while (bp > buffer + 2)
3497c478bd9Sstevel@tonic-gate *--bp = '0';
3507c478bd9Sstevel@tonic-gate --bp;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate return(bp);
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate /*
3567c478bd9Sstevel@tonic-gate * This program sends string "s" to putchar. The character after
3577c478bd9Sstevel@tonic-gate * the end of "s" is given by "send". This allows the size of the
3587c478bd9Sstevel@tonic-gate * field to be computed; it is stored in "alen". "width" contains the
3597c478bd9Sstevel@tonic-gate * user specified length. If width<alen, the width will be taken to
3607c478bd9Sstevel@tonic-gate * be alen. "sign" is zero if the string is to be right-justified
3617c478bd9Sstevel@tonic-gate * in the field, nonzero if it is to be left-justified. "fill" is
3627c478bd9Sstevel@tonic-gate * 0 if the string is to be padded with '0', positive if it is to be
3637c478bd9Sstevel@tonic-gate * padded with ' ', and negative if an initial '-' should appear before
3647c478bd9Sstevel@tonic-gate * any padding in right-justification (to avoid printing "-3" as
3657c478bd9Sstevel@tonic-gate * "000-3" where "-0003" was intended).
3667c478bd9Sstevel@tonic-gate */
367*f6db9f27Scf46844 void
_p_emit(unsigned char * s,unsigned char * send)368*f6db9f27Scf46844 _p_emit(unsigned char *s, unsigned char *send)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate unsigned char cfill;
371*f6db9f27Scf46844 int alen;
3727c478bd9Sstevel@tonic-gate int npad, length;
3737c478bd9Sstevel@tonic-gate wchar_t wchar;
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate alen = send - s;
3767c478bd9Sstevel@tonic-gate if (alen > width)
3777c478bd9Sstevel@tonic-gate width = alen;
3787c478bd9Sstevel@tonic-gate cfill = fill>0? ' ': '0';
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate /* we may want to print a leading '-' before anything */
3817c478bd9Sstevel@tonic-gate if (*s == '-' && fill < 0) {
3827c478bd9Sstevel@tonic-gate putchar(*s++);
3837c478bd9Sstevel@tonic-gate alen--;
3847c478bd9Sstevel@tonic-gate width--;
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate npad = width - alen;
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /* emit any leading pad characters */
3897c478bd9Sstevel@tonic-gate if (!sign)
3907c478bd9Sstevel@tonic-gate while (--npad >= 0)
3917c478bd9Sstevel@tonic-gate putchar(cfill);
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate /* emit the string itself */
3947c478bd9Sstevel@tonic-gate while (--alen >= 0) {
3957c478bd9Sstevel@tonic-gate length = mbtowc(&wchar, (char *)s, MB_LEN_MAX);
3967c478bd9Sstevel@tonic-gate if(length <= 0) {
3977c478bd9Sstevel@tonic-gate putoctal = 1;
3987c478bd9Sstevel@tonic-gate putchar((unsigned char)*s++);
3997c478bd9Sstevel@tonic-gate putoctal = 0;
4007c478bd9Sstevel@tonic-gate } else {
4017c478bd9Sstevel@tonic-gate putchar(wchar);
4027c478bd9Sstevel@tonic-gate s += length;
4037c478bd9Sstevel@tonic-gate alen = alen - length + 1;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate /* emit trailing pad characters */
4077c478bd9Sstevel@tonic-gate if (sign)
4087c478bd9Sstevel@tonic-gate while (--npad >= 0)
4097c478bd9Sstevel@tonic-gate putchar(cfill);
4107c478bd9Sstevel@tonic-gate }
411