⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snprintf.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
字号:
/*
 * Copyright (c) 1983, 1995, 1996 Eric P. Allman
 * Copyright (c) 1988, 1993
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#if 0
static char sccsid[] = "@(#)$Id: snprintf.c,v 1.2 1998/05/11 09:18:44 bero Exp $ excerpted from conf.c 8.333 (Berkeley) 1/21/97";
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/socket.h>  /* __inline */

#define VA_LOCAL_DECL va_list ap;
#define VA_START(f)   va_start(ap, f)
#define VA_END        va_end(ap)

/*
 * **  SNPRINTF, VSNPRINT -- counted versions of printf
 * **
 * **   These versions have been grabbed off the net.  They have been
 * **   cleaned up to compile properly and support for .precision and
 * **   %lx has been added.
 */

/**************************************************************
 * Original:
 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
 * A bombproof version of doprnt (dopr) included.
 * Sigh.  This sort of thing is always nasty do deal with.  Note that
 * the version here does not include floating point...
 *
 * snprintf() is used instead of sprintf() as it does limit checks
 * for string length.  This covers a nasty loophole.
 *
 * The other functions are there to prevent NULL pointers from
 * causing nast effects.
 **************************************************************/

static void fmtstr (char *value, int ljust, int len, int zpad, int maxwidth);
static void fmtnum (long value, int base, int dosign, int ljust, int len, int zpad);
static void dostr  (char *, int);
static void dopr   (char *, const char *, va_list);

static char *output, *end;

int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
  str[0] = 0;
  end = str + count - 1;
  dopr (str, fmt, args);
  if (count > 0)
     end[0] = 0;
  return strlen (str);
}

int snprintf (char *str, size_t count, const char *fmt, ...)
{
  int len;

  VA_LOCAL_DECL VA_START (fmt);

  len = vsnprintf (str, count, fmt, ap);
  VA_END;
  return (len);
}


static __inline void dopr_outch (int c)
{
  if (end == 0 || output < end)
     *output++ = c;
}

static void dostr (char *str, int cut)
{
  if (cut)
       while (*str && cut-- > 0) dopr_outch (*str++);
  else while (*str) dopr_outch (*str++);
}

/*
 * dopr(): poor man's version of doprintf
 */
static void dopr (char *buffer, const char *format, va_list args)
{
  int   ch;
  long  value;
  int   longflag = 0;
  int   pointflag = 0;
  int   maxwidth = 0;
  char *strvalue;
  int   ljust;
  int   len;
  int   zpad;

  output = buffer;
  while ((ch = *format++) != '\0')
  {
    switch (ch)
    {
      case '%':
           ljust = len = zpad = maxwidth = 0;
           longflag = pointflag = 0;
         nextch:
           ch = *format++;
           switch (ch)
           {
             case 0:
                  dostr ("**end of format**", 0);
                  return;
             case '-':
                  ljust = 1;
                  goto nextch;
             case '0':       /* set zero padding if len not set */
                  if (len == 0 && !pointflag)
                    zpad = '0';
             case '1':
             case '2':
             case '3':
             case '4':
             case '5':
             case '6':
             case '7':
             case '8':
             case '9':
                  if (pointflag)
                       maxwidth = maxwidth * 10 + ch - '0';
                  else len = len * 10 + ch - '0';
                  goto nextch;
             case '*':
                  if (pointflag)
                       maxwidth = va_arg (args, int);
                  else len = va_arg (args, int);
                  goto nextch;
             case '.':
                  pointflag = 1;
                  goto nextch;
             case 'l':
                  longflag = 1;
                  goto nextch;
             case 'u':
             case 'U':
                  if (longflag)
                       value = va_arg (args, long);
                  else value = va_arg (args, int);
                  fmtnum (value, 10, 0, ljust, len, zpad);
                  break;
             case 'o':
             case 'O':
                  if (longflag)
                       value = va_arg (args, long);
                  else value = va_arg (args, int);
                  fmtnum (value, 8, 0, ljust, len, zpad);
                  break;
             case 'd':
             case 'D':
                  if (longflag)
                       value = va_arg (args, long);
                  else value = va_arg (args, int);
                  fmtnum (value, 10, 1, ljust, len, zpad);
                  break;
             case 'x':
                  if (longflag)
                       value = va_arg (args, long);
                  else value = va_arg (args, int);
                  fmtnum (value, 16, 0, ljust, len, zpad);
                  break;
             case 'X':
                  if (longflag)
                       value = va_arg (args, long);
                  else value = va_arg (args, int);
                  fmtnum (value, -16, 0, ljust, len, zpad);
                  break;
             case 's':
                  strvalue = va_arg (args, char *);
                  if (maxwidth > 0 || !pointflag)
                  {
                    if (pointflag && len > maxwidth)
                      len = maxwidth;        /* Adjust padding */
                    fmtstr (strvalue, ljust, len, zpad, maxwidth);
                  }
                  break;
             case 'c':
                  ch = va_arg (args, int);
                  dopr_outch (ch);
                  break;
             case '%':
                  dopr_outch (ch);
                  continue;
             default:
                  dostr ("???????", 0);
           }
           break;
      default:
           dopr_outch (ch);
           break;
    }
  }
  *output = 0;
}

static void fmtstr (char *value, int ljust, int len, int zpad, int maxwidth)
{
  int padlen, strlen;                /* amount to pad */

  if (value == 0)
     value = "<NULL>";

  for (strlen = 0; value[strlen]; ++strlen) ;        /* strlen */
  if (strlen > maxwidth && maxwidth)
     strlen = maxwidth;
  padlen = len - strlen;
  if (padlen < 0)
     padlen = 0;
  if (ljust)
     padlen = -padlen;

  while (padlen > 0)
  {
    dopr_outch (' ');
    --padlen;
  }
  dostr (value, maxwidth);
  while (padlen < 0)
  {
    dopr_outch (' ');
    ++padlen;
  }
}

static void fmtnum (long value, int base, int dosign, int ljust, int len, int zpad)
{
  unsigned long uvalue;
  char convert[20];
  int  signvalue = 0;
  int  place = 0;
  int  padlen = 0;               /* amount to pad */
  int  caps = 0;

  /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
   * value, base, dosign, ljust, len, zpad ));
   */
  uvalue = value;
  if (dosign)
  {
    if (value < 0)
    {
      signvalue = '-';
      uvalue = -value;
    }
  }
  if (base < 0)
  {
    caps = 1;
    base = -base;
  }
  do
  {
    convert[place++] = (caps ? "0123456789ABCDEF" :
                               "0123456789abcdef")[uvalue % (unsigned) base];
    uvalue = (uvalue / (unsigned) base);
  }
  while (uvalue);
  convert[place] = 0;
  padlen = len - place;
  if (padlen < 0)
     padlen = 0;

  if (ljust)
     padlen = -padlen;

  /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
   * convert,place,signvalue,padlen));
   */
  if (zpad && padlen > 0)
  {
    if (signvalue)
    {
      dopr_outch (signvalue);
      --padlen;
      signvalue = 0;
    }
    while (padlen > 0)
    {
      dopr_outch (zpad);
      --padlen;
    }
  }
  while (padlen > 0)
  {
    dopr_outch (' ');
    --padlen;
  }
  if (signvalue)
     dopr_outch (signvalue);

  while (place > 0)
     dopr_outch (convert[--place]);

  while (padlen < 0)
  {
    dopr_outch (' ');
    ++padlen;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -