4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
40 /* The pwb version this is based on */
41 static char *printf_id
= "@(#) printf.c:2.2 6/5/79";
42 /* The local sccs version within ex */
44 #pragma ident "%Z%%M% %I% %E% SMI"
49 extern short putoctal
;
51 * This version of printf is compatible with the Version 7 C
52 * printf. The differences are only minor except that
53 * viprintf assumes it is to print through putchar. Version 7
54 * printf is more general (and is much larger) and includes
55 * provisions for floating point.
59 #define MAXOCT 11 /* Maximum octal digits in a long */
60 #define MAXINT 32767 /* largest normal length positive integer */
61 #define BIG 1000000000 /* largest power of 10 less than an unsigned long */
62 #define MAXDIGS 10 /* number of digits in BIG */
64 static int width
, sign
, fill
;
66 unsigned char *_p_dconv();
67 void _p_emit(unsigned char *, unsigned char *);
71 viprintf(unsigned char *fmt
, ...)
77 int length
,mask1
,nbits
,n
;
82 unsigned char buf
[134];
86 /* process format string first */
88 length2
= mbtowc(&wfcode
, (char *)fmt
, MB_LEN_MAX
);
100 /* ordinary (non-%) character */
105 /* length modifier: -1 for h, 1 for l, 0 for none */
107 /* check for a leading - sign */
113 /* a '0' may follow the - sign */
114 /* this is the requested fill character */
121 /* Now comes a digit string which may be a '*' */
123 width
= va_arg(ap
, int);
132 while (*fmt
>='0' && *fmt
<='9')
133 width
= width
* 10 + (*fmt
++ - '0');
136 /* maybe a decimal point followed by more digits (or '*') */
139 prec
= va_arg(ap
, int);
144 while (*fmt
>='0' && *fmt
<='9')
145 prec
= prec
* 10 + (*fmt
++ - '0');
152 * At this point, "sign" is nonzero if there was
153 * a sign, "fill" is 0 if there was a leading
154 * zero and 1 otherwise, "width" and "prec"
155 * contain numbers corresponding to the digit
156 * strings before and after the decimal point,
157 * respectively, and "fmt" addresses the next
158 * character after the whole mess. If there was
159 * no decimal point, "prec" will be -1.
174 * At exit from the following switch, we will
175 * emit the characters starting at "bptr" and
176 * ending at "ptr"-1, unless fcode is '\0'.
178 switch (fcode
= *fmt
++) {
179 /* process characters and strings first */
181 buf
[0] = va_arg(ap
, int);
182 ptr
= bptr
= &buf
[0];
187 bptr
= va_arg(ap
,unsigned char *);
189 bptr
= (unsigned char *)"(null pointer)";
192 for (n
=0; *bptr
++ && n
< prec
; n
++) ;
204 num
= va_arg(ap
,long);
206 num
= (unsigned)va_arg(ap
,int);
218 bptr
= buf
+ MAXOCT
+ 3;
219 /* shift and mask for speed */
221 if (((int) num
& mask1
) < 10)
222 *--bptr
= ((int) num
& mask1
) + 060;
224 *--bptr
= ((int) num
& mask1
) + 0127;
225 while (num
= (num
>> nbits
) & mask2
);
232 if (!sign
&& fill
<= 0) {
241 ptr
= buf
+ MAXOCT
+ 3;
247 fcode
= fcode
+ 'a' - 'A';
253 num
= va_arg(ap
,long);
261 if (n
= (fcode
!= 'u' && num
< 0))
263 /* now convert to digits */
264 bptr
= _p_dconv(num
, buf
);
269 ptr
= buf
+ MAXDIGS
+ 1;
272 /* not a control character,
285 /* _p_dconv converts the unsigned long integer "value" to
286 * printable decimal and places it in "buffer", right-justified.
287 * The value returned is the address of the first non-zero character,
288 * or the address of the last character if all are zero.
289 * The result is NOT null terminated, and is MAXDIGS characters long,
290 * starting at buffer[1] (to allow for insertion of a sign).
292 * This program assumes it is running on 2's complement machine
293 * with reasonable overflow treatment.
296 _p_dconv(value
, buffer
)
298 unsigned char *buffer
;
307 /* zero is a special case */
314 /* develop the leading digit of the value in "n" */
317 value
-= BIG
; /* will eventually underflow */
320 while ((lval
= value
- BIG
) >= 0) {
325 /* stash it in buffer[1] to allow for a sign */
328 * Now develop the rest of the digits. Since speed counts here,
329 * we do it in two loops. The first gets "value" down until it
330 * is no larger than MAXINT. The second one uses integer divides
331 * rather than long divides to speed it up.
334 while (value
> MAXINT
) {
335 *--bp
= (int)(value
% 10) + '0';
339 /* cannot lose precision */
342 *--bp
= (svalue
% 10) + '0';
346 /* fill in intermediate zeroes if needed */
347 if (buffer
[1] != '0') {
348 while (bp
> buffer
+ 2)
356 * This program sends string "s" to putchar. The character after
357 * the end of "s" is given by "send". This allows the size of the
358 * field to be computed; it is stored in "alen". "width" contains the
359 * user specified length. If width<alen, the width will be taken to
360 * be alen. "sign" is zero if the string is to be right-justified
361 * in the field, nonzero if it is to be left-justified. "fill" is
362 * 0 if the string is to be padded with '0', positive if it is to be
363 * padded with ' ', and negative if an initial '-' should appear before
364 * any padding in right-justification (to avoid printing "-3" as
365 * "000-3" where "-0003" was intended).
368 _p_emit(unsigned char *s
, unsigned char *send
)
378 cfill
= fill
>0? ' ': '0';
380 /* we may want to print a leading '-' before anything */
381 if (*s
== '-' && fill
< 0) {
388 /* emit any leading pad characters */
393 /* emit the string itself */
394 while (--alen
>= 0) {
395 length
= mbtowc(&wchar
, (char *)s
, MB_LEN_MAX
);
398 putchar((unsigned char)*s
++);
403 alen
= alen
- length
+ 1;
406 /* emit trailing pad characters */