thr_printf.c revision 276630
1181344Sdfr/*- 2181344Sdfr * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org> 3181344Sdfr * All rights reserved. 4181344Sdfr * 5181344Sdfr * Redistribution and use in source and binary forms, with or without 6181344Sdfr * modification, are permitted provided that the following conditions 7181344Sdfr * are met: 8181344Sdfr * 1. Redistributions of source code must retain the above copyright 9181344Sdfr * notice, this list of conditions and the following disclaimer. 10181344Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11181344Sdfr * notice, this list of conditions and the following disclaimer in the 12181344Sdfr * documentation and/or other materials provided with the distribution. 13181344Sdfr * 14181344Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15181344Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16181344Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17181344Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18181344Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19181344Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20181344Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21181344Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22181344Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23181344Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24181344Sdfr * SUCH DAMAGE. 25181344Sdfr * 26181344Sdfr * $FreeBSD: head/lib/libthr/thread/thr_printf.c 276630 2015-01-03 18:38:46Z kib $ 27181344Sdfr */ 28181344Sdfr 29181344Sdfr#include <stdarg.h> 30181344Sdfr#include <string.h> 31181344Sdfr#include <unistd.h> 32181344Sdfr#include <pthread.h> 33181344Sdfr 34181344Sdfr#include "libc_private.h" 35181344Sdfr#include "thr_private.h" 36181344Sdfr 37181344Sdfrstatic void pchar(int fd, char c); 38181344Sdfrstatic void pstr(int fd, const char *s); 39181344Sdfr 40181344Sdfr/* 41181344Sdfr * Write formatted output to stdout, in a thread-safe manner. 42181344Sdfr * 43181344Sdfr * Recognises the following conversions: 44181344Sdfr * %c -> char 45181344Sdfr * %d -> signed int (base 10) 46181344Sdfr * %s -> string 47181344Sdfr * %u -> unsigned int (base 10) 48181344Sdfr * %x -> unsigned int (base 16) 49181344Sdfr * %p -> unsigned int (base 16) 50181344Sdfr */ 51181344Sdfrvoid 52181344Sdfr_thread_printf(int fd, const char *fmt, ...) 53181344Sdfr{ 54181344Sdfr static const char digits[16] = "0123456789abcdef"; 55181344Sdfr va_list ap; 56181344Sdfr char buf[20]; 57181344Sdfr char *s; 58181344Sdfr unsigned long r, u; 59181344Sdfr int c; 60181344Sdfr long d; 61181344Sdfr int islong; 62181344Sdfr 63181344Sdfr va_start(ap, fmt); 64181344Sdfr while ((c = *fmt++)) { 65181344Sdfr islong = 0; 66181344Sdfr if (c == '%') { 67181344Sdfrnext: c = *fmt++; 68181344Sdfr if (c == '\0') 69181344Sdfr goto out; 70181344Sdfr switch (c) { 71181344Sdfr case 'c': 72181344Sdfr pchar(fd, va_arg(ap, int)); 73181344Sdfr continue; 74181344Sdfr case 's': 75181344Sdfr pstr(fd, va_arg(ap, char *)); 76181344Sdfr continue; 77181344Sdfr case 'l': 78181344Sdfr islong = 1; 79181344Sdfr goto next; 80181344Sdfr case 'p': 81181344Sdfr islong = 1; 82181344Sdfr case 'd': 83181344Sdfr case 'u': 84181344Sdfr case 'x': 85181344Sdfr r = ((c == 'u') || (c == 'd')) ? 10 : 16; 86181344Sdfr if (c == 'd') { 87181344Sdfr if (islong) 88181344Sdfr d = va_arg(ap, unsigned long); 89181344Sdfr else 90181344Sdfr d = va_arg(ap, unsigned); 91181344Sdfr if (d < 0) { 92181344Sdfr pchar(fd, '-'); 93181344Sdfr u = (unsigned long)(d * -1); 94181344Sdfr } else 95181344Sdfr u = (unsigned long)d; 96 } else { 97 if (islong) 98 u = va_arg(ap, unsigned long); 99 else 100 u = va_arg(ap, unsigned); 101 } 102 s = buf; 103 do { 104 *s++ = digits[u % r]; 105 } while (u /= r); 106 while (--s >= buf) 107 pchar(fd, *s); 108 continue; 109 } 110 } 111 pchar(fd, c); 112 } 113out: 114 va_end(ap); 115} 116 117/* 118 * Write a single character to stdout, in a thread-safe manner. 119 */ 120static void 121pchar(int fd, char c) 122{ 123 124 __sys_write(fd, &c, 1); 125} 126 127/* 128 * Write a string to stdout, in a thread-safe manner. 129 */ 130static void 131pstr(int fd, const char *s) 132{ 133 134 __sys_write(fd, s, strlen(s)); 135} 136 137