1/*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
32/*
33 * Mach Operating System
34 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
35 * All Rights Reserved.
36 *
37 * Permission to use, copy, modify and distribute this software and its
38 * documentation is hereby granted, provided that both the copyright
39 * notice and this permission notice appear in all copies of the
40 * software, derivative works or modified versions, and any portions
41 * thereof, and that both notices appear in supporting documentation.
42 *
43 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
44 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
45 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 *
47 * Carnegie Mellon requests users of this software to return to
48 *
49 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
50 *  School of Computer Science
51 *  Carnegie Mellon University
52 *  Pittsburgh PA 15213-3890
53 *
54 * any improvements or extensions that they make and grant Carnegie Mellon
55 * the rights to redistribute these changes.
56 */
57
58/*
59 *  Common code for printf et al.
60 *
61 *  The calling routine typically takes a variable number of arguments,
62 *  and passes the address of the first one.  This implementation
63 *  assumes a straightforward, stack implementation, aligned to the
64 *  machine's wordsize.  Increasing addresses are assumed to point to
65 *  successive arguments (left-to-right), as is the case for a machine
66 *  with a downward-growing stack with arguments pushed right-to-left.
67 *
68 *  To write, for example, fprintf() using this routine, the code
69 *
70 *	fprintf(fd, format, args)
71 *	FILE *fd;
72 *	char *format;
73 *	{
74 *	_doprnt(format, &args, fd);
75 *	}
76 *
77 *  would suffice.  (This example does not handle the fprintf's "return
78 *  value" correctly, but who looks at the return value of fprintf
79 *  anyway?)
80 *
81 *  This version implements the following printf features:
82 *
83 *	%d	decimal conversion
84 *	%u	unsigned conversion
85 *	%x	hexadecimal conversion
86 *	%X	hexadecimal conversion with capital letters
87 *      %D      hexdump, ptr & separator string ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
88 *              if you use, "%*D" then there's a length, the data ptr and then the separator
89 *	%o	octal conversion
90 *	%c	character
91 *	%s	string
92 *	%m.n	field width, precision
93 *	%-m.n	left adjustment
94 *	%0m.n	zero-padding
95 *	%*.*	width and precision taken from arguments
96 *
97 *  This version does not implement %f, %e, or %g.
98 *
99 *  As mentioned, this version does not return any reasonable value.
100 *
101 *  Permission is granted to use, modify, or propagate this code as
102 *  long as this notice is incorporated.
103 *
104 *  Steve Summit 3/25/87
105 *
106 *  Tweaked for long long support and extended to support the hexdump %D
107 *  specifier by dbg 05/02/02.
108 */
109
110/*
111 * Added formats for decoding device registers:
112 *
113 * printf("reg = %b", regval, "<base><arg>*")
114 *
115 * where <base> is the output base expressed as a control character:
116 * i.e. '\10' gives octal, '\20' gives hex.  Each <arg> is a sequence of
117 * characters, the first of which gives the bit number to be inspected
118 * (origin 1), and the rest (up to a control character (<= 32)) give the
119 * name of the register.  Thus
120 *	printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
121 * would produce
122 *	reg = 3<BITTWO,BITONE>
123 *
124 * If the second character in <arg> is also a control character, it
125 * indicates the last bit of a bit field.  In this case, printf will extract
126 * bits <1> to <2> and print it.  Characters following the second control
127 * character are printed before the bit field.
128 *	printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
129 * would produce
130 *	reg = b<FIELD1=2,BITONE>
131 *
132 * The %B format is like %b but the bits are numbered from the most
133 * significant (the bit weighted 31), which is called 1, to the least
134 * significant, called 32.
135 */
136/*
137 * Added for general use:
138 *	#	prefix for alternate format:
139 *		0x (0X) for hex
140 *		leading 0 for octal
141 *	+	print '+' if positive
142 *	blank	print ' ' if positive
143 *
144 *	z	signed hexadecimal
145 *	r	signed, 'radix'
146 *	n	unsigned, 'radix'
147 *
148 *	D,U,O,Z	same as corresponding lower-case versions
149 *		(compatibility)
150 */
151/*
152 * Added support for print long long (64-bit) integers.
153 * Use %lld, %Ld or %qd to print a 64-bit int.  Other
154 * output bases such as x, X, u, U, o, and O also work.
155 */
156
157#include <debug.h>
158#include <mach_kdp.h>
159#include <platforms.h>
160#include <mach/boolean.h>
161#include <kern/cpu_number.h>
162#include <kern/lock.h>
163#include <kern/thread.h>
164#include <kern/sched_prim.h>
165#include <kern/misc_protos.h>
166#include <stdarg.h>
167#include <string.h>
168#include <mach_assert.h>
169#ifdef  MACH_BSD
170#include <sys/msgbuf.h>
171#endif
172#include <console/serial_protos.h>
173
174#define isdigit(d) ((d) >= '0' && (d) <= '9')
175#define Ctod(c) ((c) - '0')
176
177#define MAXBUF (sizeof(long long int) * 8)	/* enough for binary */
178static char digs[] = "0123456789abcdef";
179
180#if CONFIG_NO_PRINTF_STRINGS
181/* Prevent CPP from breaking the definition below */
182#undef printf
183#endif
184
185int _consume_printf_args(int a __unused, ...)
186{
187    return 0;
188}
189void _consume_kprintf_args(int a __unused, ...)
190{
191}
192
193static int
194printnum(
195	unsigned long long int	u,	/* number to print */
196	int		base,
197	void			(*putc)(int, void *),
198	void                    *arg)
199{
200	char	buf[MAXBUF];	/* build number here */
201	char *	p = &buf[MAXBUF-1];
202	int nprinted = 0;
203
204	do {
205	    *p-- = digs[u % base];
206	    u /= base;
207	} while (u != 0);
208
209	while (++p != &buf[MAXBUF]) {
210	    (*putc)(*p, arg);
211	    nprinted++;
212	}
213
214	return nprinted;
215}
216
217boolean_t	_doprnt_truncates = FALSE;
218
219int
220__doprnt(
221	const char	*fmt,
222	va_list			argp,
223						/* character output routine */
224	void			(*putc)(int, void *arg),
225	void                    *arg,
226	int			radix)		/* default radix - for '%r' */
227{
228	int		length;
229	int		prec;
230	boolean_t	ladjust;
231	char		padc;
232	long long		n;
233	unsigned long long	u;
234	int		plus_sign;
235	int		sign_char;
236	boolean_t	altfmt, truncate;
237	int		base;
238	char	c;
239	int		capitals;
240	int		long_long;
241	int             nprinted = 0;
242
243	while ((c = *fmt) != '\0') {
244	    if (c != '%') {
245		(*putc)(c, arg);
246		nprinted++;
247		fmt++;
248		continue;
249	    }
250
251	    fmt++;
252
253	    long_long = 0;
254	    length = 0;
255	    prec = -1;
256	    ladjust = FALSE;
257	    padc = ' ';
258	    plus_sign = 0;
259	    sign_char = 0;
260	    altfmt = FALSE;
261
262	    while (TRUE) {
263		c = *fmt;
264		if (c == '#') {
265		    altfmt = TRUE;
266		}
267		else if (c == '-') {
268		    ladjust = TRUE;
269		}
270		else if (c == '+') {
271		    plus_sign = '+';
272		}
273		else if (c == ' ') {
274		    if (plus_sign == 0)
275			plus_sign = ' ';
276		}
277		else
278		    break;
279		fmt++;
280	    }
281
282	    if (c == '0') {
283		padc = '0';
284		c = *++fmt;
285	    }
286
287	    if (isdigit(c)) {
288		while(isdigit(c)) {
289		    length = 10 * length + Ctod(c);
290		    c = *++fmt;
291		}
292	    }
293	    else if (c == '*') {
294		length = va_arg(argp, int);
295		c = *++fmt;
296		if (length < 0) {
297		    ladjust = !ladjust;
298		    length = -length;
299		}
300	    }
301
302	    if (c == '.') {
303		c = *++fmt;
304		if (isdigit(c)) {
305		    prec = 0;
306		    while(isdigit(c)) {
307			prec = 10 * prec + Ctod(c);
308			c = *++fmt;
309		    }
310		}
311		else if (c == '*') {
312		    prec = va_arg(argp, int);
313		    c = *++fmt;
314		}
315	    }
316
317	    if (c == 'l') {
318		c = *++fmt;	/* need it if sizeof(int) < sizeof(long) */
319		if (sizeof(int)<sizeof(long))
320		    long_long = 1;
321		if (c == 'l') {
322		    long_long = 1;
323		    c = *++fmt;
324		}
325	    } else if (c == 'q' || c == 'L') {
326	    	long_long = 1;
327		c = *++fmt;
328	    }
329
330	    truncate = FALSE;
331	    capitals=0;		/* Assume lower case printing */
332
333	    switch(c) {
334		case 'b':
335		case 'B':
336		{
337		    register char *p;
338		    boolean_t	  any;
339		    register int  i;
340
341		    if (long_long) {
342			u = va_arg(argp, unsigned long long);
343		    } else {
344			u = va_arg(argp, unsigned int);
345		    }
346		    p = va_arg(argp, char *);
347		    base = *p++;
348		    nprinted += printnum(u, base, putc, arg);
349
350		    if (u == 0)
351			break;
352
353		    any = FALSE;
354		    while ((i = *p++) != '\0') {
355			if (*fmt == 'B')
356			    i = 33 - i;
357			if (*p <= 32) {
358			    /*
359			     * Bit field
360			     */
361			    register int j;
362			    if (any)
363				(*putc)(',', arg);
364			    else {
365				(*putc)('<', arg);
366				any = TRUE;
367			    }
368			    nprinted++;
369			    j = *p++;
370			    if (*fmt == 'B')
371				j = 32 - j;
372			    for (; (c = *p) > 32; p++) {
373				(*putc)(c, arg);
374				nprinted++;
375			    }
376			    nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
377						 base, putc, arg);
378			}
379			else if (u & (1<<(i-1))) {
380			    if (any)
381				(*putc)(',', arg);
382			    else {
383				(*putc)('<', arg);
384				any = TRUE;
385			    }
386			    nprinted++;
387			    for (; (c = *p) > 32; p++) {
388				(*putc)(c, arg);
389				nprinted++;
390			    }
391			}
392			else {
393			    for (; *p > 32; p++)
394				continue;
395			}
396		    }
397		    if (any) {
398			(*putc)('>', arg);
399			nprinted++;
400		    }
401		    break;
402		}
403
404		case 'c':
405		    c = va_arg(argp, int);
406		    (*putc)(c, arg);
407		    nprinted++;
408		    break;
409
410		case 's':
411		{
412		    register const char *p;
413		    register const char *p2;
414
415		    if (prec == -1)
416			prec = 0x7fffffff;	/* MAXINT */
417
418		    p = va_arg(argp, char *);
419
420		    if (p == NULL)
421			p = "";
422
423		    if (length > 0 && !ladjust) {
424			n = 0;
425			p2 = p;
426
427			for (; *p != '\0' && n < prec; p++)
428			    n++;
429
430			p = p2;
431
432			while (n < length) {
433			    (*putc)(' ', arg);
434			    n++;
435			    nprinted++;
436			}
437		    }
438
439		    n = 0;
440
441		    while ((n < prec) && (!(length > 0 && n >= length))) {
442			    if (*p == '\0') {
443				    break;
444			    }
445			    (*putc)(*p++, arg);
446			    nprinted++;
447			    n++;
448		    }
449
450		    if (n < length && ladjust) {
451			while (n < length) {
452			    (*putc)(' ', arg);
453			    n++;
454			    nprinted++;
455			}
456		    }
457
458		    break;
459		}
460
461		case 'o':
462		    truncate = _doprnt_truncates;
463		case 'O':
464		    base = 8;
465		    goto print_unsigned;
466
467		case 'D': {
468		    unsigned char *up;
469		    char *q, *p;
470
471			up = (unsigned char *)va_arg(argp, unsigned char *);
472			p = (char *)va_arg(argp, char *);
473			if (length == -1)
474				length = 16;
475			while(length--) {
476				(*putc)(digs[(*up >> 4)], arg);
477				(*putc)(digs[(*up & 0x0f)], arg);
478				nprinted += 2;
479				up++;
480				if (length) {
481				    for (q=p;*q;q++) {
482						(*putc)(*q, arg);
483						nprinted++;
484				    }
485				}
486			}
487			break;
488		}
489
490		case 'd':
491		    truncate = _doprnt_truncates;
492		    base = 10;
493		    goto print_signed;
494
495		case 'u':
496		    truncate = _doprnt_truncates;
497		case 'U':
498		    base = 10;
499		    goto print_unsigned;
500
501		case 'p':
502		    altfmt = TRUE;
503		    if (sizeof(int)<sizeof(void *)) {
504			long_long = 1;
505		    }
506		case 'x':
507		    truncate = _doprnt_truncates;
508		    base = 16;
509		    goto print_unsigned;
510
511		case 'X':
512		    base = 16;
513		    capitals=16;	/* Print in upper case */
514		    goto print_unsigned;
515
516		case 'z':
517		    truncate = _doprnt_truncates;
518		    base = 16;
519		    goto print_signed;
520
521		case 'Z':
522		    base = 16;
523		    capitals=16;	/* Print in upper case */
524		    goto print_signed;
525
526		case 'r':
527		    truncate = _doprnt_truncates;
528		case 'R':
529		    base = radix;
530		    goto print_signed;
531
532		case 'n':
533		    truncate = _doprnt_truncates;
534		case 'N':
535		    base = radix;
536		    goto print_unsigned;
537
538		print_signed:
539		    if (long_long) {
540			n = va_arg(argp, long long);
541		    } else {
542			n = va_arg(argp, int);
543		    }
544		    if (n >= 0) {
545			u = n;
546			sign_char = plus_sign;
547		    }
548		    else {
549			u = -n;
550			sign_char = '-';
551		    }
552		    goto print_num;
553
554		print_unsigned:
555		    if (long_long) {
556			u = va_arg(argp, unsigned long long);
557		    } else {
558			u = va_arg(argp, unsigned int);
559		    }
560		    goto print_num;
561
562		print_num:
563		{
564		    char	buf[MAXBUF];	/* build number here */
565		    register char *	p = &buf[MAXBUF-1];
566		    static char digits[] = "0123456789abcdef0123456789ABCDEF";
567		    const char *prefix = NULL;
568
569		    if (truncate) u = (long long)((int)(u));
570
571		    if (u != 0 && altfmt) {
572			if (base == 8)
573			    prefix = "0";
574			else if (base == 16)
575			    prefix = "0x";
576		    }
577
578		    do {
579			/* Print in the correct case */
580			*p-- = digits[(u % base)+capitals];
581			u /= base;
582		    } while (u != 0);
583
584		    length -= (int)(&buf[MAXBUF-1] - p);
585		    if (sign_char)
586			length--;
587		    if (prefix)
588			length -= (int)strlen(prefix);
589
590		    if (padc == ' ' && !ladjust) {
591			/* blank padding goes before prefix */
592			while (--length >= 0) {
593			    (*putc)(' ', arg);
594			    nprinted++;
595			}
596		    }
597		    if (sign_char) {
598			(*putc)(sign_char, arg);
599			nprinted++;
600		    }
601		    if (prefix) {
602			while (*prefix) {
603			    (*putc)(*prefix++, arg);
604			    nprinted++;
605			}
606		    }
607		    if (padc == '0') {
608			/* zero padding goes after sign and prefix */
609			while (--length >= 0) {
610			    (*putc)('0', arg);
611			    nprinted++;
612			}
613		    }
614		    while (++p != &buf[MAXBUF]) {
615			(*putc)(*p, arg);
616			nprinted++;
617		    }
618
619		    if (ladjust) {
620			while (--length >= 0) {
621			    (*putc)(' ', arg);
622			    nprinted++;
623			}
624		    }
625		    break;
626		}
627
628		case '\0':
629		    fmt--;
630		    break;
631
632		default:
633		    (*putc)(c, arg);
634		    nprinted++;
635	    }
636	fmt++;
637	}
638
639	return nprinted;
640}
641
642static void
643dummy_putc(int ch, void *arg)
644{
645    void (*real_putc)(char) = arg;
646
647    real_putc(ch);
648}
649
650void
651_doprnt(
652	register const char	*fmt,
653	va_list			*argp,
654						/* character output routine */
655	void			(*putc)(char),
656	int			radix)		/* default radix - for '%r' */
657{
658    __doprnt(fmt, *argp, dummy_putc, putc, radix);
659}
660
661#if	MP_PRINTF
662boolean_t	new_printf_cpu_number = FALSE;
663#endif	/* MP_PRINTF */
664
665
666decl_simple_lock_data(,printf_lock)
667decl_simple_lock_data(,bsd_log_spinlock)
668extern void bsd_log_init(void);
669void bsd_log_lock(void);
670void bsd_log_unlock(void);
671
672void
673printf_init(void)
674{
675	/*
676	 * Lock is only really needed after the first thread is created.
677	 */
678	simple_lock_init(&printf_lock, 0);
679	simple_lock_init(&bsd_log_spinlock, 0);
680	bsd_log_init();
681}
682
683void
684bsd_log_lock(void)
685{
686	simple_lock(&bsd_log_spinlock);
687}
688
689void
690bsd_log_unlock(void)
691{
692	simple_unlock(&bsd_log_spinlock);
693}
694
695/* derived from boot_gets */
696void
697safe_gets(
698	char	*str,
699	int	maxlen)
700{
701	register char *lp;
702	register int c;
703	char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
704
705	lp = str;
706	for (;;) {
707		c = cngetc();
708		switch (c) {
709		case '\n':
710		case '\r':
711			printf("\n");
712			*lp++ = 0;
713			return;
714
715		case '\b':
716		case '#':
717		case '\177':
718			if (lp > str) {
719				printf("\b \b");
720				lp--;
721			}
722			continue;
723
724		case '@':
725		case 'u'&037:
726			lp = str;
727			printf("\n\r");
728			continue;
729
730		default:
731			if (c >= ' ' && c < '\177') {
732				if (lp < strmax) {
733					*lp++ = c;
734					printf("%c", c);
735				}
736				else {
737					printf("%c", '\007'); /* beep */
738				}
739			}
740		}
741	}
742}
743
744extern int disableConsoleOutput;
745
746void
747conslog_putc(
748	char c)
749{
750	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
751		cnputc(c);
752
753#ifdef	MACH_BSD
754	if (debug_mode == 0)
755		log_putc(c);
756#endif
757}
758
759void
760cons_putc_locked(
761	char c)
762{
763	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
764		cnputc(c);
765}
766
767int
768printf(const char *fmt, ...)
769{
770	va_list	listp;
771
772	if (fmt) {
773		disable_preemption();
774		va_start(listp, fmt);
775		_doprnt(fmt, &listp, conslog_putc, 16);
776		va_end(listp);
777		enable_preemption();
778	}
779	return 0;
780}
781
782void
783consdebug_putc(char c)
784{
785	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
786		cnputc(c);
787
788	debug_putc(c);
789
790	if (!console_is_serial())
791		if (!disable_serial_output)
792			PE_kputc(c);
793}
794
795void
796consdebug_putc_unbuffered(char c)
797{
798	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
799		cnputc_unbuffered(c);
800
801	debug_putc(c);
802
803	if (!console_is_serial())
804		if (!disable_serial_output)
805			PE_kputc(c);
806}
807
808void
809consdebug_log(char c)
810{
811	debug_putc(c);
812}
813
814int
815kdb_printf(const char *fmt, ...)
816{
817	va_list	listp;
818
819	va_start(listp, fmt);
820	_doprnt(fmt, &listp, consdebug_putc, 16);
821	va_end(listp);
822	return 0;
823}
824
825int
826kdb_log(const char *fmt, ...)
827{
828	va_list	listp;
829
830	va_start(listp, fmt);
831	_doprnt(fmt, &listp, consdebug_log, 16);
832	va_end(listp);
833	return 0;
834}
835
836int
837kdb_printf_unbuffered(const char *fmt, ...)
838{
839	va_list	listp;
840
841	va_start(listp, fmt);
842	_doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
843	va_end(listp);
844	return 0;
845}
846
847
848static void
849copybyte(int c, void *arg)
850{
851	/*
852	 * arg is a pointer (outside pointer) to the pointer
853	 * (inside pointer) which points to the character.
854	 * We pass a double pointer, so that we can increment
855	 * the inside pointer.
856	 */
857	char** p = arg;	/* cast outside pointer */
858	**p = c;	/* store character */
859	(*p)++;		/* increment inside pointer */
860}
861
862/*
863 * Deprecation Warning:
864 *	sprintf() is being deprecated. Please use snprintf() instead.
865 */
866int
867sprintf(char *buf, const char *fmt, ...)
868{
869        va_list listp;
870	char *copybyte_str;
871
872        va_start(listp, fmt);
873        copybyte_str = buf;
874        __doprnt(fmt, listp, copybyte, &copybyte_str, 16);
875        va_end(listp);
876	*copybyte_str = '\0';
877        return (int)strlen(buf);
878}
879