171b3fa15SDavid Xu /*- 271b3fa15SDavid Xu * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org> 371b3fa15SDavid Xu * All rights reserved. 471b3fa15SDavid Xu * 571b3fa15SDavid Xu * Redistribution and use in source and binary forms, with or without 671b3fa15SDavid Xu * modification, are permitted provided that the following conditions 771b3fa15SDavid Xu * are met: 871b3fa15SDavid Xu * 1. Redistributions of source code must retain the above copyright 971b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer. 1071b3fa15SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright 1171b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer in the 1271b3fa15SDavid Xu * documentation and/or other materials provided with the distribution. 1371b3fa15SDavid Xu * 1471b3fa15SDavid Xu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1571b3fa15SDavid Xu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1671b3fa15SDavid Xu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1771b3fa15SDavid Xu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1871b3fa15SDavid Xu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1971b3fa15SDavid Xu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2071b3fa15SDavid Xu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2171b3fa15SDavid Xu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2271b3fa15SDavid Xu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2371b3fa15SDavid Xu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2471b3fa15SDavid Xu * SUCH DAMAGE. 2571b3fa15SDavid Xu */ 2671b3fa15SDavid Xu 2771b3fa15SDavid Xu #include <stdarg.h> 2871b3fa15SDavid Xu #include <string.h> 2971b3fa15SDavid Xu #include <unistd.h> 3071b3fa15SDavid Xu #include <pthread.h> 3171b3fa15SDavid Xu 3271b3fa15SDavid Xu #include "thr_private.h" 3371b3fa15SDavid Xu 3471b3fa15SDavid Xu static void pchar(int fd, char c); 3571b3fa15SDavid Xu static void pstr(int fd, const char *s); 3671b3fa15SDavid Xu 3771b3fa15SDavid Xu /* 3871b3fa15SDavid Xu * Write formatted output to stdout, in a thread-safe manner. 3971b3fa15SDavid Xu * 4071b3fa15SDavid Xu * Recognises the following conversions: 4171b3fa15SDavid Xu * %c -> char 4271b3fa15SDavid Xu * %d -> signed int (base 10) 4371b3fa15SDavid Xu * %s -> string 4471b3fa15SDavid Xu * %u -> unsigned int (base 10) 4571b3fa15SDavid Xu * %x -> unsigned int (base 16) 4671b3fa15SDavid Xu * %p -> unsigned int (base 16) 4771b3fa15SDavid Xu */ 4871b3fa15SDavid Xu void 4971b3fa15SDavid Xu _thread_printf(int fd, const char *fmt, ...) 5071b3fa15SDavid Xu { 5171b3fa15SDavid Xu va_list ap; 52*4a9b8501Szrj 53*4a9b8501Szrj va_start(ap, fmt); 54*4a9b8501Szrj _thread_vprintf(fd, fmt, ap); 55*4a9b8501Szrj va_end(ap); 56*4a9b8501Szrj } 57*4a9b8501Szrj 58*4a9b8501Szrj void 59*4a9b8501Szrj _thread_vprintf(int fd, const char *fmt, va_list ap) 60*4a9b8501Szrj { 61*4a9b8501Szrj static const char digits[16] = "0123456789abcdef"; 6271b3fa15SDavid Xu char buf[20]; 6371b3fa15SDavid Xu char *s; 6471b3fa15SDavid Xu unsigned long r, u; 6571b3fa15SDavid Xu int c; 6671b3fa15SDavid Xu long d; 6771b3fa15SDavid Xu int islong; 6871b3fa15SDavid Xu 6971b3fa15SDavid Xu while ((c = *fmt++)) { 7071b3fa15SDavid Xu islong = 0; 7171b3fa15SDavid Xu if (c == '%') { 7271b3fa15SDavid Xu next: c = *fmt++; 7371b3fa15SDavid Xu if (c == '\0') 74*4a9b8501Szrj return; 7571b3fa15SDavid Xu switch (c) { 7671b3fa15SDavid Xu case 'c': 7771b3fa15SDavid Xu pchar(fd, va_arg(ap, int)); 7871b3fa15SDavid Xu continue; 7971b3fa15SDavid Xu case 's': 8071b3fa15SDavid Xu pstr(fd, va_arg(ap, char *)); 8171b3fa15SDavid Xu continue; 8271b3fa15SDavid Xu case 'l': 8371b3fa15SDavid Xu islong = 1; 8471b3fa15SDavid Xu goto next; 8571b3fa15SDavid Xu case 'p': 8671b3fa15SDavid Xu islong = 1; 8771b3fa15SDavid Xu case 'd': 8871b3fa15SDavid Xu case 'u': 8971b3fa15SDavid Xu case 'x': 9071b3fa15SDavid Xu r = ((c == 'u') || (c == 'd')) ? 10 : 16; 9171b3fa15SDavid Xu if (c == 'd') { 9271b3fa15SDavid Xu if (islong) 9371b3fa15SDavid Xu d = va_arg(ap, unsigned long); 9471b3fa15SDavid Xu else 9571b3fa15SDavid Xu d = va_arg(ap, unsigned); 9671b3fa15SDavid Xu if (d < 0) { 9771b3fa15SDavid Xu pchar(fd, '-'); 9871b3fa15SDavid Xu u = (unsigned long)(d * -1); 9971b3fa15SDavid Xu } else 10071b3fa15SDavid Xu u = (unsigned long)d; 10171b3fa15SDavid Xu } else { 10271b3fa15SDavid Xu if (islong) 10371b3fa15SDavid Xu u = va_arg(ap, unsigned long); 10471b3fa15SDavid Xu else 10571b3fa15SDavid Xu u = va_arg(ap, unsigned); 10671b3fa15SDavid Xu } 10771b3fa15SDavid Xu s = buf; 10871b3fa15SDavid Xu do { 10971b3fa15SDavid Xu *s++ = digits[u % r]; 11071b3fa15SDavid Xu } while (u /= r); 11171b3fa15SDavid Xu while (--s >= buf) 11271b3fa15SDavid Xu pchar(fd, *s); 11371b3fa15SDavid Xu continue; 11471b3fa15SDavid Xu } 11571b3fa15SDavid Xu } 11671b3fa15SDavid Xu pchar(fd, c); 11771b3fa15SDavid Xu } 11871b3fa15SDavid Xu } 11971b3fa15SDavid Xu 12071b3fa15SDavid Xu /* 12171b3fa15SDavid Xu * Write a single character to stdout, in a thread-safe manner. 12271b3fa15SDavid Xu */ 12371b3fa15SDavid Xu static void 12471b3fa15SDavid Xu pchar(int fd, char c) 12571b3fa15SDavid Xu { 12671b3fa15SDavid Xu 12771b3fa15SDavid Xu __sys_write(fd, &c, 1); 12871b3fa15SDavid Xu } 12971b3fa15SDavid Xu 13071b3fa15SDavid Xu /* 13171b3fa15SDavid Xu * Write a string to stdout, in a thread-safe manner. 13271b3fa15SDavid Xu */ 13371b3fa15SDavid Xu static void 13471b3fa15SDavid Xu pstr(int fd, const char *s) 13571b3fa15SDavid Xu { 13671b3fa15SDavid Xu 13771b3fa15SDavid Xu __sys_write(fd, s, strlen(s)); 13871b3fa15SDavid Xu } 13971b3fa15SDavid Xu 140