/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* This file is shared between libc and the kernel, so don't put anything31* in here that won't work in both contexts.32*/3334#ifdef _KERNEL35#include <types.h>36#include <lib.h>3738#else39#include <stdio.h>4041#endif /* _KERNEL */4243#include <stdarg.h>4445/*46* Standard C string/IO function: printf into a character buffer.47*/484950/*51* Context structure for snprintf: buffer to print into, maximum52* length, and index of the next character to write.53*54* Note that while the length argument to snprintf includes space for55* a null terminator, SNP.buflen does not. This is to make something56* vaguely reasonable happen if a length of 0 is passed to snprintf.57*/5859typedef struct {60char *buf;61size_t buflen;62size_t bufpos;63} SNP;6465/*66* Send function for snprintf. This is the function handed to the67* printf guts. It gets called with mydata pointing to the context,68* and some string data of length LEN in DATA. DATA is not necessarily69* null-terminated.70*/7172static73void74__snprintf_send(void *mydata, const char *data, size_t len)75{76SNP *snp = mydata;77unsigned i;7879/* For each character we're sent... */80for (i=0; i<len; i++) {8182/* If we aren't past the length, */83if (snp->bufpos < snp->buflen) {8485/* store the character */86snp->buf[snp->bufpos] = data[i];8788/* and increment the position. */89snp->bufpos++;90}91}92}9394/*95* The va_list version of snprintf.96*/97int98vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)99{100int chars;101SNP snp;102103/*104* Fill in the context structure.105* We set snp.buflen to the number of characters that can be106* written (excluding the null terminator) so as not to have107* to special-case the possibility that we got passed a length108* of zero elsewhere.109*/110snp.buf = buf;111if (len==0) {112snp.buflen = 0;113}114else {115snp.buflen = len-1;116}117snp.bufpos = 0;118119/* Call __vprintf to do the actual work. */120chars = __vprintf(__snprintf_send, &snp, fmt, ap);121122/*123* Add a null terminator. If the length *we were passed* is greater124* than zero, we reserved a space in the buffer for the terminator,125* so this won't overflow. If the length we were passed is zero,126* nothing will have been or should be written anyway, and buf127* might even be NULL. (C99 explicitly endorses this possibility.)128*/129if (len > 0) {130buf[snp.bufpos] = 0;131}132133/*134* Return the number of characters __vprintf processed.135* According to C99, snprintf should return this number, not136* the number of characters actually stored, and should not137* return -1 on overflow but only on other errors. (All none138* of them since we don't do multibyte characters...)139*/140return chars;141}142143/*144* snprintf - hand off to vsnprintf.145*/146int147snprintf(char *buf, size_t len, const char *fmt, ...)148{149int chars;150va_list ap;151va_start(ap, fmt);152chars = vsnprintf(buf, len, fmt, ap);153va_end(ap);154return chars;155}156157158159