1112918Sjeff/*- 2112918Sjeff * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org> 3112918Sjeff * All rights reserved. 4112918Sjeff * 5112918Sjeff * Redistribution and use in source and binary forms, with or without 6112918Sjeff * modification, are permitted provided that the following conditions 7112918Sjeff * are met: 8112918Sjeff * 1. Redistributions of source code must retain the above copyright 9112918Sjeff * notice, this list of conditions and the following disclaimer. 10112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11112918Sjeff * notice, this list of conditions and the following disclaimer in the 12112918Sjeff * documentation and/or other materials provided with the distribution. 13112918Sjeff * 14112918Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17112918Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24112918Sjeff * SUCH DAMAGE. 25144518Sdavidxu * 26144518Sdavidxu * $FreeBSD: releng/10.3/lib/libthr/thread/thr_printf.c 277317 2015-01-18 11:54:20Z kib $ 27112918Sjeff */ 28112918Sjeff 29112918Sjeff#include <stdarg.h> 30115260Smtm#include <string.h> 31112918Sjeff#include <unistd.h> 32112918Sjeff#include <pthread.h> 33112918Sjeff 34277317Skib#include "libc_private.h" 35112918Sjeff#include "thr_private.h" 36112918Sjeff 37112918Sjeffstatic void pchar(int fd, char c); 38112918Sjeffstatic void pstr(int fd, const char *s); 39112918Sjeff 40112918Sjeff/* 41112918Sjeff * Write formatted output to stdout, in a thread-safe manner. 42112918Sjeff * 43112918Sjeff * Recognises the following conversions: 44112918Sjeff * %c -> char 45112918Sjeff * %d -> signed int (base 10) 46112918Sjeff * %s -> string 47112918Sjeff * %u -> unsigned int (base 10) 48112918Sjeff * %x -> unsigned int (base 16) 49112918Sjeff * %p -> unsigned int (base 16) 50112918Sjeff */ 51112918Sjeffvoid 52112918Sjeff_thread_printf(int fd, const char *fmt, ...) 53112918Sjeff{ 54112918Sjeff static const char digits[16] = "0123456789abcdef"; 55112918Sjeff va_list ap; 56144518Sdavidxu char buf[20]; 57112918Sjeff char *s; 58144518Sdavidxu unsigned long r, u; 59144518Sdavidxu int c; 60144518Sdavidxu long d; 61144518Sdavidxu int islong; 62112918Sjeff 63112918Sjeff va_start(ap, fmt); 64112918Sjeff while ((c = *fmt++)) { 65144518Sdavidxu islong = 0; 66112918Sjeff if (c == '%') { 67144518Sdavidxunext: c = *fmt++; 68144518Sdavidxu if (c == '\0') 69144518Sdavidxu goto out; 70112918Sjeff switch (c) { 71112918Sjeff case 'c': 72112918Sjeff pchar(fd, va_arg(ap, int)); 73112918Sjeff continue; 74112918Sjeff case 's': 75112918Sjeff pstr(fd, va_arg(ap, char *)); 76112918Sjeff continue; 77144518Sdavidxu case 'l': 78144518Sdavidxu islong = 1; 79144518Sdavidxu goto next; 80144518Sdavidxu case 'p': 81144518Sdavidxu islong = 1; 82112918Sjeff case 'd': 83112918Sjeff case 'u': 84112918Sjeff case 'x': 85112918Sjeff r = ((c == 'u') || (c == 'd')) ? 10 : 16; 86112918Sjeff if (c == 'd') { 87144518Sdavidxu if (islong) 88144518Sdavidxu d = va_arg(ap, unsigned long); 89144518Sdavidxu else 90144518Sdavidxu d = va_arg(ap, unsigned); 91112918Sjeff if (d < 0) { 92112918Sjeff pchar(fd, '-'); 93144518Sdavidxu u = (unsigned long)(d * -1); 94112918Sjeff } else 95144518Sdavidxu u = (unsigned long)d; 96144518Sdavidxu } else { 97144518Sdavidxu if (islong) 98144518Sdavidxu u = va_arg(ap, unsigned long); 99144518Sdavidxu else 100144518Sdavidxu u = va_arg(ap, unsigned); 101144518Sdavidxu } 102112918Sjeff s = buf; 103112918Sjeff do { 104112918Sjeff *s++ = digits[u % r]; 105112918Sjeff } while (u /= r); 106112918Sjeff while (--s >= buf) 107112918Sjeff pchar(fd, *s); 108112918Sjeff continue; 109112918Sjeff } 110112918Sjeff } 111112918Sjeff pchar(fd, c); 112112918Sjeff } 113144518Sdavidxuout: 114112918Sjeff va_end(ap); 115112918Sjeff} 116112918Sjeff 117112918Sjeff/* 118112918Sjeff * Write a single character to stdout, in a thread-safe manner. 119112918Sjeff */ 120112918Sjeffstatic void 121112918Sjeffpchar(int fd, char c) 122112918Sjeff{ 123112918Sjeff 124116103Smtm __sys_write(fd, &c, 1); 125112918Sjeff} 126112918Sjeff 127112918Sjeff/* 128112918Sjeff * Write a string to stdout, in a thread-safe manner. 129112918Sjeff */ 130112918Sjeffstatic void 131112918Sjeffpstr(int fd, const char *s) 132112918Sjeff{ 133112918Sjeff 134116103Smtm __sys_write(fd, s, strlen(s)); 135112918Sjeff} 136112918Sjeff 137