thr_printf.c revision 277317
172169Sphantom/*-
2116875Sphantom * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>
372169Sphantom * All rights reserved.
472169Sphantom *
5227753Stheraven * Redistribution and use in source and binary forms, with or without
6227753Stheraven * modification, are permitted provided that the following conditions
7227753Stheraven * are met:
8227753Stheraven * 1. Redistributions of source code must retain the above copyright
9227753Stheraven *    notice, this list of conditions and the following disclaimer.
1072169Sphantom * 2. Redistributions in binary form must reproduce the above copyright
1172169Sphantom *    notice, this list of conditions and the following disclaimer in the
1272169Sphantom *    documentation and/or other materials provided with the distribution.
1372169Sphantom *
1472169Sphantom * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1572169Sphantom * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1672169Sphantom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1772169Sphantom * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1872169Sphantom * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1972169Sphantom * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2072169Sphantom * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2172169Sphantom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2272169Sphantom * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2372169Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2472169Sphantom * SUCH DAMAGE.
2572169Sphantom *
2672169Sphantom * $FreeBSD: stable/10/lib/libthr/thread/thr_printf.c 277317 2015-01-18 11:54:20Z kib $
2772169Sphantom */
2872169Sphantom
2972169Sphantom#include <stdarg.h>
3072169Sphantom#include <string.h>
3172169Sphantom#include <unistd.h>
3292986Sobrien#include <pthread.h>
3392986Sobrien
3492986Sobrien#include "libc_private.h"
3572263Sache#include "thr_private.h"
3672561Sache
37116875Sphantomstatic void	pchar(int fd, char c);
3872561Sachestatic void	pstr(int fd, const char *s);
3972263Sache
4087658Sphantom/*
4172169Sphantom * Write formatted output to stdout, in a thread-safe manner.
42116875Sphantom *
4372169Sphantom * Recognises the following conversions:
44116875Sphantom *	%c	-> char
4572169Sphantom *	%d	-> signed int (base 10)
4672169Sphantom *	%s	-> string
4772169Sphantom *	%u	-> unsigned int (base 10)
4872169Sphantom *	%x	-> unsigned int (base 16)
49227753Stheraven *	%p	-> unsigned int (base 16)
50116875Sphantom */
51227753Stheravenvoid
52227753Stheraven_thread_printf(int fd, const char *fmt, ...)
53227753Stheraven{
5472169Sphantom	static const char digits[16] = "0123456789abcdef";
5572169Sphantom	va_list	 ap;
5672169Sphantom	char buf[20];
5772263Sache	char *s;
58227753Stheraven	unsigned long r, u;
59116134Sache	int c;
6072263Sache	long d;
61116134Sache	int islong;
62116134Sache
6372263Sache	va_start(ap, fmt);
6472263Sache	while ((c = *fmt++)) {
6572169Sphantom		islong = 0;
6672169Sphantom		if (c == '%') {
67227753Stheravennext:			c = *fmt++;
6872169Sphantom			if (c == '\0')
6972169Sphantom				goto out;
70227753Stheraven			switch (c) {
7172169Sphantom			case 'c':
7272169Sphantom				pchar(fd, va_arg(ap, int));
73227753Stheraven				continue;
7472169Sphantom			case 's':
7572169Sphantom				pstr(fd, va_arg(ap, char *));
76227753Stheraven				continue;
7772169Sphantom			case 'l':
7872169Sphantom				islong = 1;
79227753Stheraven				goto next;
8072169Sphantom			case 'p':
8172169Sphantom				islong = 1;
82227753Stheraven			case 'd':
8372169Sphantom			case 'u':
8472169Sphantom			case 'x':
8572169Sphantom				r = ((c == 'u') || (c == 'd')) ? 10 : 16;
86227753Stheraven				if (c == 'd') {
8772169Sphantom					if (islong)
8872169Sphantom						d = va_arg(ap, unsigned long);
8972169Sphantom					else
90227753Stheraven						d = va_arg(ap, unsigned);
9172169Sphantom					if (d < 0) {
9272169Sphantom						pchar(fd, '-');
9372169Sphantom						u = (unsigned long)(d * -1);
9472169Sphantom					} else
95227753Stheraven						u = (unsigned long)d;
9672169Sphantom				} else {
9772169Sphantom					if (islong)
9872169Sphantom						u = va_arg(ap, unsigned long);
9972169Sphantom					else
100227753Stheraven						u = va_arg(ap, unsigned);
10172169Sphantom				}
102197765Sedwin				s = buf;
103197765Sedwin				do {
104197765Sedwin					*s++ = digits[u % r];
105197765Sedwin				} while (u /= r);
106227753Stheraven				while (--s >= buf)
107197765Sedwin					pchar(fd, *s);
10872169Sphantom				continue;
10972706Sphantom			}
11072169Sphantom		}
11172169Sphantom		pchar(fd, c);
11272169Sphantom	}
11372706Sphantomout:
11472169Sphantom	va_end(ap);
11572169Sphantom}
11672169Sphantom
11772706Sphantom/*
11872169Sphantom * Write a single character to stdout, in a thread-safe manner.
11972169Sphantom */
12072169Sphantomstatic void
12172706Sphantompchar(int fd, char c)
12272169Sphantom{
12372169Sphantom
12472169Sphantom	__sys_write(fd, &c, 1);
12572706Sphantom}
12672169Sphantom
12772169Sphantom/*
12872706Sphantom * Write a string to stdout, in a thread-safe manner.
129227753Stheraven */
13072169Sphantomstatic void
13172706Sphantompstr(int fd, const char *s)
132227753Stheraven{
13372169Sphantom
13472169Sphantom	__sys_write(fd, s, strlen(s));
135227753Stheraven}
13672169Sphantom
13772169Sphantom