thr_printf.c revision 301135
1122687Sbms/*-
2122687Sbms * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>
3122687Sbms * All rights reserved.
4122687Sbms *
5122687Sbms * Redistribution and use in source and binary forms, with or without
6122687Sbms * modification, are permitted provided that the following conditions
7122687Sbms * are met:
8122687Sbms * 1. Redistributions of source code must retain the above copyright
9122687Sbms *    notice, this list of conditions and the following disclaimer.
10122687Sbms * 2. Redistributions in binary form must reproduce the above copyright
11122687Sbms *    notice, this list of conditions and the following disclaimer in the
12122687Sbms *    documentation and/or other materials provided with the distribution.
13122687Sbms *
14251475Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15251475Semaste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16251475Semaste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17251475Semaste * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18251475Semaste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19251475Semaste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20251475Semaste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21251475Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22251475Semaste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23251475Semaste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24251475Semaste * SUCH DAMAGE.
25122687Sbms */
26122687Sbms
27122687Sbms#include <sys/cdefs.h>
28122687Sbms__FBSDID("$FreeBSD: head/lib/libthr/thread/thr_printf.c 301135 2016-06-01 16:11:09Z cem $");
29122687Sbms
30122687Sbms#include <stdarg.h>
31122687Sbms#include <string.h>
32122687Sbms#include <unistd.h>
33122687Sbms#include <pthread.h>
34122687Sbms
35122687Sbms#include "libc_private.h"
36122687Sbms#include "thr_private.h"
37122687Sbms
38122687Sbmsstatic void	pchar(int fd, char c);
39122687Sbmsstatic void	pstr(int fd, const char *s);
40122687Sbms
41122687Sbms/*
42122687Sbms * Write formatted output to stdout, in a thread-safe manner.
43122687Sbms *
44122687Sbms * Recognises the following conversions:
45122687Sbms *	%c	-> char
46122687Sbms *	%d	-> signed int (base 10)
47122687Sbms *	%s	-> string
48122687Sbms *	%u	-> unsigned int (base 10)
49122687Sbms *	%x	-> unsigned int (base 16)
50122687Sbms *	%p	-> unsigned int (base 16)
51122687Sbms */
52122687Sbmsvoid
53122687Sbms_thread_printf(int fd, const char *fmt, ...)
54122687Sbms{
55122687Sbms	va_list	ap;
56122687Sbms
57122687Sbms	va_start(ap, fmt);
58122687Sbms	_thread_vprintf(fd, fmt, ap);
59122687Sbms	va_end(ap);
60122687Sbms}
61122687Sbms
62122687Sbmsvoid
63122687Sbms_thread_vprintf(int fd, const char *fmt, va_list ap)
64122687Sbms{
65122687Sbms	static const char digits[16] = "0123456789abcdef";
66122687Sbms	char buf[20];
67122687Sbms	char *s;
68122687Sbms	unsigned long r, u;
69122687Sbms	int c;
70122687Sbms	long d;
71122687Sbms	int islong, isalt;
72122687Sbms
73122687Sbms	while ((c = *fmt++)) {
74122687Sbms		isalt = 0;
75122687Sbms		islong = 0;
76122687Sbms		if (c == '%') {
77122687Sbmsnext:			c = *fmt++;
78122687Sbms			if (c == '\0')
79122687Sbms				return;
80122687Sbms			switch (c) {
81122687Sbms			case '#':
82122687Sbms				isalt = 1;
83122687Sbms				goto next;
84122687Sbms			case 'c':
85122687Sbms				pchar(fd, va_arg(ap, int));
86122687Sbms				continue;
87122687Sbms			case 's':
88122687Sbms				pstr(fd, va_arg(ap, char *));
89122687Sbms				continue;
90122687Sbms			case 'l':
91122687Sbms				islong = 1;
92122687Sbms				goto next;
93122687Sbms			case 'p':
94122687Sbms				pstr(fd, "0x");
95122687Sbms				islong = 1;
96122687Sbms			case 'd':
97122687Sbms			case 'u':
98122687Sbms			case 'x':
99122687Sbms				if (c == 'x' && isalt)
100122687Sbms					pstr(fd, "0x");
101122687Sbms				r = ((c == 'u') || (c == 'd')) ? 10 : 16;
102122687Sbms				if (c == 'd') {
103122687Sbms					if (islong)
104122687Sbms						d = va_arg(ap, unsigned long);
105122687Sbms					else
106122687Sbms						d = va_arg(ap, unsigned);
107122687Sbms					if (d < 0) {
108122687Sbms						pchar(fd, '-');
109122687Sbms						u = (unsigned long)(d * -1);
110122687Sbms					} else
111122687Sbms						u = (unsigned long)d;
112122687Sbms				} else {
113122687Sbms					if (islong)
114122687Sbms						u = va_arg(ap, unsigned long);
115122687Sbms					else
116122687Sbms						u = va_arg(ap, unsigned);
117122687Sbms				}
118122687Sbms				s = buf;
119122687Sbms				do {
120122687Sbms					*s++ = digits[u % r];
121122687Sbms				} while (u /= r);
122122687Sbms				while (--s >= buf)
123122687Sbms					pchar(fd, *s);
124122687Sbms				continue;
125122687Sbms			}
126122687Sbms		}
127122687Sbms		pchar(fd, c);
128122687Sbms	}
129122687Sbms}
130122687Sbms
131122687Sbms/*
132122687Sbms * Write a single character to stdout, in a thread-safe manner.
133122687Sbms */
134122687Sbmsstatic void
135122687Sbmspchar(int fd, char c)
136122687Sbms{
137122687Sbms
138122687Sbms	__sys_write(fd, &c, 1);
139122687Sbms}
140122687Sbms
141122687Sbms/*
142122687Sbms * Write a string to stdout, in a thread-safe manner.
143122687Sbms */
144122687Sbmsstatic void
145122687Sbmspstr(int fd, const char *s)
146122687Sbms{
147122687Sbms
148122687Sbms	__sys_write(fd, s, strlen(s));
149122687Sbms}
150122687Sbms
151122687Sbms