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