root/common/libc/printf/snprintf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __snprintf_send
  2. vsnprintf
  3. snprintf

   1 /*
   2  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
   3  *      The President and Fellows of Harvard College.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the University nor the names of its contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * This file is shared between libc and the kernel, so don't put anything
  32  * in here that won't work in both contexts.
  33  */
  34 
  35 #ifdef _KERNEL
  36 #include <types.h>
  37 #include <lib.h>
  38 
  39 #else
  40 #include <stdio.h>
  41 
  42 #endif /* _KERNEL */
  43 
  44 #include <stdarg.h>
  45 
  46 /*
  47  * Standard C string/IO function: printf into a character buffer.
  48  */
  49 
  50 
  51 /*
  52  * Context structure for snprintf: buffer to print into, maximum 
  53  * length, and index of the next character to write.
  54  *
  55  * Note that while the length argument to snprintf includes space for
  56  * a null terminator, SNP.buflen does not. This is to make something
  57  * vaguely reasonable happen if a length of 0 is passed to snprintf.
  58  */
  59 
  60 typedef struct {
  61         char *buf;
  62         size_t buflen;
  63         size_t bufpos;
  64 } SNP;
  65 
  66 /*
  67  * Send function for snprintf. This is the function handed to the
  68  * printf guts. It gets called with mydata pointing to the context,
  69  * and some string data of length LEN in DATA. DATA is not necessarily
  70  * null-terminated.
  71  */
  72 
  73 static
  74 void
  75 __snprintf_send(void *mydata, const char *data, size_t len)
  76 {
  77         SNP *snp = mydata;
  78         unsigned i;
  79 
  80         /* For each character we're sent... */
  81         for (i=0; i<len; i++) {
  82 
  83                 /* If we aren't past the length, */
  84                 if (snp->bufpos < snp->buflen) {
  85 
  86                         /* store the character */
  87                         snp->buf[snp->bufpos] = data[i];
  88 
  89                         /* and increment the position. */
  90                         snp->bufpos++;
  91                 }
  92         }
  93 }
  94 
  95 /*
  96  * The va_list version of snprintf.
  97  */
  98 int
  99 vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
 100 {
 101         int chars;
 102         SNP snp;
 103 
 104         /*
 105          * Fill in the context structure.
 106          * We set snp.buflen to the number of characters that can be
 107          * written (excluding the null terminator) so as not to have
 108          * to special-case the possibility that we got passed a length
 109          * of zero elsewhere.
 110          */
 111         snp.buf = buf;
 112         if (len==0) {
 113                 snp.buflen = 0;
 114         }
 115         else {
 116                 snp.buflen = len-1;
 117         }
 118         snp.bufpos = 0;
 119 
 120         /* Call __vprintf to do the actual work. */
 121         chars = __vprintf(__snprintf_send, &snp, fmt, ap);
 122 
 123         /*
 124          * Add a null terminator. If the length *we were passed* is greater
 125          * than zero, we reserved a space in the buffer for the terminator,
 126          * so this won't overflow. If the length we were passed is zero,
 127          * nothing will have been or should be written anyway, and buf
 128          * might even be NULL. (C99 explicitly endorses this possibility.)
 129          */
 130         if (len > 0) {
 131                 buf[snp.bufpos] = 0;
 132         }
 133 
 134         /*
 135          * Return the number of characters __vprintf processed.
 136          * According to C99, snprintf should return this number, not
 137          * the number of characters actually stored, and should not
 138          * return -1 on overflow but only on other errors. (All none
 139          * of them since we don't do multibyte characters...)
 140          */
 141         return chars;
 142 }
 143 
 144 /*
 145  * snprintf - hand off to vsnprintf.
 146  */
 147 int
 148 snprintf(char *buf, size_t len, const char *fmt, ...)
 149 {
 150         int chars;
 151         va_list ap;
 152         va_start(ap, fmt);
 153         chars = vsnprintf(buf, len, fmt, ap);
 154         va_end(ap);
 155         return chars;
 156 }
 157 

/* [<][>][^][v][top][bottom][index][help] */