00001 /* 00002 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 00003 * The President and Fellows of Harvard College. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the University nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 */ 00029 00030 /* 00031 * This file is shared between libc and the kernel, so don't put anything 00032 * in here that won't work in both contexts. 00033 */ 00034 00035 #ifdef _KERNEL 00036 #include <types.h> 00037 #include <lib.h> 00038 00039 #else 00040 #include <stdio.h> 00041 00042 #endif /* _KERNEL */ 00043 00044 #include <stdarg.h> 00045 00046 /* 00047 * Standard C string/IO function: printf into a character buffer. 00048 */ 00049 00050 00051 /* 00052 * Context structure for snprintf: buffer to print into, maximum 00053 * length, and index of the next character to write. 00054 * 00055 * Note that while the length argument to snprintf includes space for 00056 * a null terminator, SNP.buflen does not. This is to make something 00057 * vaguely reasonable happen if a length of 0 is passed to snprintf. 00058 */ 00059 00060 typedef struct { 00061 char *buf; 00062 size_t buflen; 00063 size_t bufpos; 00064 } SNP; 00065 00066 /* 00067 * Send function for snprintf. This is the function handed to the 00068 * printf guts. It gets called with mydata pointing to the context, 00069 * and some string data of length LEN in DATA. DATA is not necessarily 00070 * null-terminated. 00071 */ 00072 00073 static 00074 void 00075 __snprintf_send(void *mydata, const char *data, size_t len) 00076 { 00077 SNP *snp = mydata; 00078 unsigned i; 00079 00080 /* For each character we're sent... */ 00081 for (i=0; i<len; i++) { 00082 00083 /* If we aren't past the length, */ 00084 if (snp->bufpos < snp->buflen) { 00085 00086 /* store the character */ 00087 snp->buf[snp->bufpos] = data[i]; 00088 00089 /* and increment the position. */ 00090 snp->bufpos++; 00091 } 00092 } 00093 } 00094 00095 /* 00096 * The va_list version of snprintf. 00097 */ 00098 int 00099 vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) 00100 { 00101 int chars; 00102 SNP snp; 00103 00104 /* 00105 * Fill in the context structure. 00106 * We set snp.buflen to the number of characters that can be 00107 * written (excluding the null terminator) so as not to have 00108 * to special-case the possibility that we got passed a length 00109 * of zero elsewhere. 00110 */ 00111 snp.buf = buf; 00112 if (len==0) { 00113 snp.buflen = 0; 00114 } 00115 else { 00116 snp.buflen = len-1; 00117 } 00118 snp.bufpos = 0; 00119 00120 /* Call __vprintf to do the actual work. */ 00121 chars = __vprintf(__snprintf_send, &snp, fmt, ap); 00122 00123 /* 00124 * Add a null terminator. If the length *we were passed* is greater 00125 * than zero, we reserved a space in the buffer for the terminator, 00126 * so this won't overflow. If the length we were passed is zero, 00127 * nothing will have been or should be written anyway, and buf 00128 * might even be NULL. (C99 explicitly endorses this possibility.) 00129 */ 00130 if (len > 0) { 00131 buf[snp.bufpos] = 0; 00132 } 00133 00134 /* 00135 * Return the number of characters __vprintf processed. 00136 * According to C99, snprintf should return this number, not 00137 * the number of characters actually stored, and should not 00138 * return -1 on overflow but only on other errors. (All none 00139 * of them since we don't do multibyte characters...) 00140 */ 00141 return chars; 00142 } 00143 00144 /* 00145 * snprintf - hand off to vsnprintf. 00146 */ 00147 int 00148 snprintf(char *buf, size_t len, const char *fmt, ...) 00149 { 00150 int chars; 00151 va_list ap; 00152 va_start(ap, fmt); 00153 chars = vsnprintf(buf, len, fmt, ap); 00154 va_end(ap); 00155 return chars; 00156 } 00157