1106191Smini/*-
2106191Smini * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>
3106191Smini * All rights reserved.
4106191Smini *
5106191Smini * Redistribution and use in source and binary forms, with or without
6106191Smini * modification, are permitted provided that the following conditions
7106191Smini * are met:
8106191Smini * 1. Redistributions of source code must retain the above copyright
9106191Smini *    notice, this list of conditions and the following disclaimer.
10106191Smini * 2. Redistributions in binary form must reproduce the above copyright
11106191Smini *    notice, this list of conditions and the following disclaimer in the
12106191Smini *    documentation and/or other materials provided with the distribution.
13106191Smini *
14106191Smini * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15106191Smini * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16106191Smini * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17106191Smini * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18106191Smini * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19106191Smini * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20106191Smini * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21106191Smini * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22106191Smini * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23106191Smini * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24106191Smini * SUCH DAMAGE.
25106191Smini */
26106191Smini
27106191Smini#include <sys/cdefs.h>
28106191Smini__FBSDID("$FreeBSD$");
29106191Smini
30106191Smini#include <stdarg.h>
31113658Sdeischen#include <string.h>
32106191Smini#include <unistd.h>
33106191Smini
34106191Smini#include "thr_private.h"
35106191Smini
36106191Sministatic void	pchar(int fd, char c);
37106191Sministatic void	pstr(int fd, const char *s);
38106191Smini
39106191Smini/*
40106191Smini * Write formatted output to stdout, in a thread-safe manner.
41106191Smini *
42106191Smini * Recognises the following conversions:
43106191Smini *	%c	-> char
44106191Smini *	%d	-> signed int (base 10)
45106191Smini *	%s	-> string
46106191Smini *	%u	-> unsigned int (base 10)
47106191Smini *	%x	-> unsigned int (base 16)
48106191Smini *	%p	-> unsigned int (base 16)
49106191Smini */
50106191Sminivoid
51106191Smini_thread_printf(int fd, const char *fmt, ...)
52106191Smini{
53106191Smini	static const char digits[16] = "0123456789abcdef";
54106191Smini	va_list	 ap;
55119117Sdavidxu	char buf[20];
56106191Smini	char *s;
57119117Sdavidxu	unsigned long r, u;
58119117Sdavidxu	int c;
59119117Sdavidxu	long d;
60119117Sdavidxu	int islong;
61106191Smini
62106191Smini	va_start(ap, fmt);
63106191Smini	while ((c = *fmt++)) {
64119117Sdavidxu		islong = 0;
65106191Smini		if (c == '%') {
66119117Sdavidxunext:			c = *fmt++;
67119117Sdavidxu			if (c == '\0')
68119117Sdavidxu				goto out;
69106191Smini			switch (c) {
70106191Smini			case 'c':
71106191Smini				pchar(fd, va_arg(ap, int));
72106191Smini				continue;
73106191Smini			case 's':
74106191Smini				pstr(fd, va_arg(ap, char *));
75106191Smini				continue;
76119117Sdavidxu			case 'l':
77119117Sdavidxu				islong = 1;
78119117Sdavidxu				goto next;
79119117Sdavidxu			case 'p':
80119117Sdavidxu				islong = 1;
81106191Smini			case 'd':
82106191Smini			case 'u':
83106191Smini			case 'x':
84106191Smini				r = ((c == 'u') || (c == 'd')) ? 10 : 16;
85106191Smini				if (c == 'd') {
86119117Sdavidxu					if (islong)
87119117Sdavidxu						d = va_arg(ap, unsigned long);
88119117Sdavidxu					else
89119117Sdavidxu						d = va_arg(ap, unsigned);
90106191Smini					if (d < 0) {
91106191Smini						pchar(fd, '-');
92119117Sdavidxu						u = (unsigned long)(d * -1);
93106191Smini					} else
94119117Sdavidxu						u = (unsigned long)d;
95119117Sdavidxu				} else {
96119117Sdavidxu					if (islong)
97119117Sdavidxu						u = va_arg(ap, unsigned long);
98119117Sdavidxu					else
99119117Sdavidxu						u = va_arg(ap, unsigned);
100119117Sdavidxu				}
101106191Smini				s = buf;
102106191Smini				do {
103106191Smini					*s++ = digits[u % r];
104106191Smini				} while (u /= r);
105106191Smini				while (--s >= buf)
106106191Smini					pchar(fd, *s);
107106191Smini				continue;
108106191Smini			}
109106191Smini		}
110106191Smini		pchar(fd, c);
111106191Smini	}
112119117Sdavidxuout:
113106191Smini	va_end(ap);
114106191Smini}
115106191Smini
116106191Smini/*
117106191Smini * Write a single character to stdout, in a thread-safe manner.
118106191Smini */
119106191Sministatic void
120106191Sminipchar(int fd, char c)
121106191Smini{
122106191Smini
123113658Sdeischen	__sys_write(fd, &c, 1);
124106191Smini}
125106191Smini
126106191Smini/*
127106191Smini * Write a string to stdout, in a thread-safe manner.
128106191Smini */
129106191Sministatic void
130106191Sminipstr(int fd, const char *s)
131106191Smini{
132106191Smini
133113658Sdeischen	__sys_write(fd, s, strlen(s));
134106191Smini}
135106191Smini
136