"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/plp_snprintf.c" (9 Dec 2022, 17057 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "plp_snprintf.c" see the Fossies "Dox" file reference documentation.

    1 /**************************************************************************
    2  * LPRng IFHP Filter
    3  * Copyright 1994-1999 Patrick Powell, San Diego, CA <papowell@astart.com>
    4  **************************************************************************/
    5 
    6 /*
    7  * Overview:
    8  *
    9  * This version of snprintf was developed originally for printing
   10  * on a motley collection of specialized hardware that had NO IO
   11  * library.  Due to contractual restrictions,  a clean room implementation
   12  * of the printf() code had to be developed.
   13  *
   14  * The method chosen for printf was to be as paranoid as possible,
   15  * as these platforms had NO memory protection,  and very small
   16  * address spaces.  This made it possible to try to print
   17  * very long strings, i.e. - all of memory, very easily.  To guard
   18  * against this,  all printing was done via a buffer, generous enough
   19  * to hold strings,  but small enough to protect against overruns,
   20  * etc.
   21  *
   22  * Strangely enough,  this proved to be of immense importance when
   23  * SPRINTFing to a buffer on a stack...  The rest,  of course,  is
   24  * well known,  as buffer overruns in the stack are a common way to
   25  * do horrible things to operating systems, security, etc etc.
   26  *
   27  * This version of snprintf is VERY limited by modern standards.
   28  *
   29  * COPYRIGHT AND TERMS OF USE:
   30  *
   31  * You may use, copy, distribute, or otherwise incorporate this software
   32  * and documentation into any product or other item,  provided that
   33  * the copyright in the documentation and source code as well as the
   34  * source code generated constant strings in the object, executable
   35  * or other code remain in place and are present in executable modules
   36  * or objects.
   37  *
   38  * You may modify this code as appropriate to your usage; however the
   39  * modified version must be identified by changing the various source
   40  * and object code identification strings as is appropriately noted
   41  * in the source code.
   42  *
   43  * The next include line is expected to work in conjunction with the
   44  * GNU CONFIGURE utility.  You  should define the following macros
   45  * appropriately:
   46  *
   47  * HAVE_STDARG_H - if the <stdargs.h> include file is available
   48  * HAVE_VARARG_H - if the <varargs.h> include file is available
   49  *
   50  * HAVE_STRERROR - if the strerror() routine is available.
   51  *   If it is not available, then examine the lines containing
   52  *   the tests below.  You may need to fiddle with HAVE_SYS_NERR
   53  *   and  HAVE_SYS_NERR_DEF to make compilation work correctly.
   54  *        HAVE_SYS_NERR
   55  *        HAVE_SYS_NERR_DEF
   56  *
   57  * HAVE_QUAD_T   - if the quad_t type is defined
   58  * HAVE_LONG_LONG  - if the long long type is defined
   59  *
   60  *   If you are using the GNU configure (autoconf) facility, add the
   61  *   following line to the configure.in file, to force checking for the
   62  *   quad_t and long long  data types:
   63  *
   64  *     AC_CHECK_TYPE(quad_t,NONE)
   65  *
   66  *  dnl test to see if long long is defined
   67  *
   68  *  AC_MSG_CHECKING(checking for long long)
   69  *  AC_TRY_COMPILE([
   70  *  #include <sys/types.h>
   71  *  ],[long long x; x = 0],
   72  *  ac_cv_long_long=yes, ac_cv_long_long=no)
   73  *  AC_MSG_RESULT($ac_cv_long_long)
   74  *  if test $ac_cv_long_long = yes; then
   75  *    AC_DEFINE(HAVE_LONG_LONG)
   76  *  fi
   77  *
   78  *
   79  *   Add the following lines to the acconfig.h in the correct
   80  *   position.
   81  *
   82  *     / * Define if quad_t is NOT present on the system  * /
   83  *     #undef quad_t
   84  *
   85  *     / * Define if long long is present on the system  * /
   86  *     #undef HAVE_LONG_LONG
   87  *
   88  *   When you run configure, if quad_t is NOT defined, the config.h
   89  *   file will have in it:
   90  *     #define quad_t NONE
   91  *
   92  *   If it is defined, the config.h file will have
   93  *   / * #undef quad_t * /
   94  *
   95  *   If long long is defined, you will have:
   96  *     #define HAVE_LONG_LONG
   97  *
   98  *    This code is then used in the source code to enable quad quad
   99  *   and long long support.
  100  *
  101  */
  102 
  103 
  104 #ifndef TIN_H
  105 #   include "tin.h"
  106 #endif /* !TIN_H */
  107 
  108 #if !defined(HAVE_SNPRINTF) && !defined(HAVE_VSNPRINTF)
  109 
  110 #   if !defined(PLP_SNPRINTF_H) && !defined(TIN_H)
  111 #       include "plp_snprintf.h"
  112 #   endif /* !PLP_SNPRINTF_H && !TIN_H */
  113 
  114 /*
  115  * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS
  116  * i.e. - the LOCAL REVISIONS part is for your use
  117  */
  118 
  119 static const char *_id = "plp_snprintf V1999.02.20 Copyright Patrick Powell 1988-1999 <papowell@astart.com> \
  120 $Id: plp_snprintf.c,v 1.4 1999/02/20 17:44:16 papowell Exp papowell $\
  121  LOCAL REVISIONS: tin 1.9.5-01";
  122 
  123 /* varargs declarations: */
  124 
  125 #ifdef HAVE_STDARGS
  126 #   undef HAVE_STDARGS    /* let's hope that works everywhere (mj) */
  127 #endif /* HAVE_STDARGS */
  128 #ifdef VA_LOCAL_DECL
  129 #   undef VA_LOCAL_DECL
  130 #endif /* VA_LOCAL_DECL */
  131 #ifdef VA_START
  132 #   undef VA_START
  133 #endif /* VA_START */
  134 #ifdef VA_SHIFT
  135 #   undef VA_SHIFT
  136 #endif /* VA_SHIFT */
  137 #ifdef VA_END
  138 #   undef VA_END
  139 #endif /* VA_END */
  140 
  141 #ifdef HAVE_STDARG_H
  142 #   include <stdarg.h>
  143 #   define HAVE_STDARGS    /* let's hope that works everywhere (mj) */
  144 #   define VA_LOCAL_DECL   va_list ap;
  145 #   define VA_START(f)     va_start(ap, f)
  146 #   define VA_SHIFT(v,t)    ;   /* no-op for ANSI */
  147 #   define VA_END          va_end(ap)
  148 #else
  149 #   ifdef HAVE_VARARGS_H
  150 #       include <varargs.h>
  151 #       undef HAVE_STDARGS
  152 #       define VA_LOCAL_DECL   va_list ap;
  153 #       define VA_START(f)     va_start(ap)     /* f is ignored! */
  154 #       define VA_SHIFT(v,t)    v = va_arg(ap,t)
  155 #       define VA_END       va_end(ap)
  156 #   else
  157 XX ** NO VARARGS ** XX
  158 #   endif /* HAVE_VARARGS_H */
  159 #endif /* HAVE_STDARG_H */
  160 
  161 #if 0
  162 /* the dreaded QUAD_T strikes again... */
  163 #ifndef HAVE_QUAD_T
  164 #   if defined(quad_t) && qaud_t == NONE
  165 #       define HAVE_QUAD_T 0
  166 #   else
  167 #       define HAVE_QUAD_T 1
  168 #   endif /* quad_t && qaud_t== NONE */
  169 #endif /* HAVE_QUAD_T */
  170 #endif /* 0 */
  171 
  172 #if defined(HAVE_QUAD_T) && !defined(HAVE_LONG_LONG)
  173   ERROR you need long long
  174 #endif
  175 #ifdef HAVE_QUAD_T
  176    /* suspender and belts on this one */
  177    const union { quad_t t; long long v; } x;
  178 #endif
  179 
  180 union value {
  181 #if defined(HAVE_QUAD_T) || defined(HAVE_LONG_LONG)
  182     long long value;
  183 #else
  184     long value;
  185 #endif
  186     double dvalue;
  187 };
  188 
  189 #ifdef cval
  190 #   undef cval
  191 #endif /* cval */
  192 #define cval(s) (*((unsigned const char *)s))
  193 
  194 
  195 static char *plp_Errormsg(int err);
  196 static void plp_strcat(char *dest, const char *src);
  197 static void dopr(char *buffer, const char *format, va_list args);
  198 static void fmtstr(const char *value, int ljust, int len, int precision);
  199 static void fmtnum(union value *value, int plp_base, int dosign, int ljust, int len, int zpad);
  200 static void fmtdouble(int fmt, double value, int ljust, int len, int zpad, int precision);
  201 static void dostr(const char *);
  202 static void dopr_outch(int c);
  203 
  204 static char *output;
  205 static char *end;
  206 
  207 int visible_control = 1;
  208 
  209 
  210 int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  211 {
  212     str[0] = 0;
  213     end = str+count-1;
  214     dopr( str, fmt, args );
  215     if( count != 0 )
  216         end[0] = 0;
  217     return(strlen(str));
  218 }
  219 
  220 /* VARARGS3 */
  221 #ifdef HAVE_STDARGS
  222 int plp_snprintf(char *str,size_t count,const char *fmt,...)
  223 #else
  224 int plp_snprintf(va_alist) va_dcl
  225 #endif
  226 {
  227 #ifndef HAVE_STDARGS
  228     char *str;
  229     size_t count;
  230     char *fmt;
  231 #endif
  232     VA_LOCAL_DECL
  233 
  234     VA_START (fmt);
  235     VA_SHIFT (str, char *);
  236     VA_SHIFT (count, size_t );
  237     VA_SHIFT (fmt, char *);
  238     (void) plp_vsnprintf( str, count, fmt, ap);
  239     VA_END;
  240     return( strlen( str ) );
  241 }
  242 
  243 static void dopr( char *buffer, const char *format, va_list args )
  244 {
  245     int ch;
  246     union value value;
  247     int longflag = 0;
  248     int quadflag = 0;
  249     char *strvalue;
  250     int ljust;
  251     int len;
  252     int zpad;
  253     int precision;
  254     int set_precision;
  255     double dval;
  256     int err = errno;
  257     int plp_base = 0;
  258     int signed_val = 0;
  259 
  260     output = buffer;
  261     while( (ch = *format++) ){
  262         switch( ch ){
  263         case '%':
  264             longflag = quadflag =
  265             ljust = len = zpad = plp_base = signed_val = 0;
  266             precision = -1; set_precision = 0;
  267         nextch:
  268             ch = *format++;
  269             switch( ch ){
  270             case 0:
  271                 dostr( "**end of format**" );
  272                 return;
  273             case '-': ljust = 1; goto nextch;
  274             case '.': set_precision = 1; precision = 0; goto nextch;
  275             case '*':
  276                 if( set_precision ){
  277                     precision = va_arg( args, int );
  278                 } else {
  279                     len = va_arg( args, int );
  280                 }
  281                 goto nextch;
  282             case '0': /* set zero padding if len not set */
  283                 if(len==0 && set_precision == 0 ) zpad = '0';
  284                 /* FALLTHROUGH */
  285             case '1': /* FALLTHROUGH */
  286             case '2': /* FALLTHROUGH */
  287             case '3': /* FALLTHROUGH */
  288             case '4': /* FALLTHROUGH */
  289             case '5': /* FALLTHROUGH */
  290             case '6': /* FALLTHROUGH */
  291             case '7': /* FALLTHROUGH */
  292             case '8': /* FALLTHROUGH */
  293             case '9':
  294                 if( set_precision ){
  295                     precision = precision*10 + ch - '0';
  296                 } else {
  297                     len = len*10 + ch - '0';
  298                 }
  299                 goto nextch;
  300             case 'l': ++longflag; goto nextch;
  301             case 'q': quadflag = 1; goto nextch;
  302             case 'u': case 'U':
  303                 if( plp_base == 0 ){ plp_base = 10; signed_val = 0; }
  304                 /* FALLTHROUGH */
  305             case 'o': case 'O':
  306                 if( plp_base == 0 ){ plp_base = 8; signed_val = 0; }
  307                 /* FALLTHROUGH */
  308             case 'd': case 'D':
  309                 if( plp_base == 0 ){ plp_base = 10; signed_val = 1; }
  310                 /* FALLTHROUGH */
  311             case 'x':
  312                 if( plp_base == 0 ){ plp_base = 16; signed_val = 0; }
  313                 /* FALLTHROUGH */
  314             case 'X':
  315                 if( plp_base == 0 ){ plp_base = -16; signed_val = 0; }
  316                 if( quadflag || longflag > 1 ){
  317 #if defined(HAVE_LONG_LONG)
  318                     if( signed_val ){
  319                     value.value = va_arg( args, long long );
  320                     } else {
  321                     value.value = va_arg( args, unsigned long long );
  322                     }
  323 #else
  324                     if( signed_val ){
  325                     value.value = va_arg( args, long );
  326                     } else {
  327                     value.value = va_arg( args, unsigned long );
  328                     }
  329 #endif
  330                 } else if( longflag ){
  331                     if( signed_val ){
  332                         value.value = va_arg( args, long );
  333                     } else {
  334                         value.value = va_arg( args, unsigned long );
  335                     }
  336                 } else {
  337                     if( signed_val ){
  338                         value.value = va_arg( args, int );
  339                     } else {
  340                         value.value = va_arg( args, unsigned int );
  341                     }
  342                 }
  343                 fmtnum( &value,plp_base,signed_val, ljust, len, zpad );
  344                 break;
  345             case 's':
  346                 strvalue = va_arg( args, char *);
  347                 fmtstr(strvalue, ljust, len, precision);
  348                 break;
  349             case 'c':
  350                 ch = va_arg( args, int );
  351                 { char b[2];
  352                     int vsb = visible_control;
  353                     b[0] = ch;
  354                     b[1] = 0;
  355                     visible_control = 0;
  356                     fmtstr(b, ljust, len, precision);
  357                     visible_control = vsb;
  358                 }
  359                 break;
  360             case 'f': case 'g': case 'e':
  361                 dval = va_arg( args, double );
  362                 fmtdouble(ch, dval, ljust, len, zpad, precision);
  363                 break;
  364             case 'm':
  365                 fmtstr(plp_Errormsg(err), ljust, len, precision);
  366                 break;
  367             case '%': dopr_outch( ch ); continue;
  368             default:
  369                 dostr(  "???????" );
  370             }
  371             longflag = 0;
  372             break;
  373         default:
  374             dopr_outch( ch );
  375             break;
  376         }
  377     }
  378     *output = 0;
  379 }
  380 
  381 /*
  382  * Format '%[-]len[.precision]s'
  383  * -   = left justify (ljust)
  384  * len = minimum length
  385  * precision = numbers of chars in string to use
  386  */
  387 static void
  388 fmtstr(const char *value, int ljust, int len, int precision)
  389 {
  390     int padlen, slen, i, c; /* amount to pad */
  391 
  392     if( value == 0 ){
  393         value = "<NULL>";
  394     }
  395     if( precision > 0 ){
  396         slen = precision;
  397     } else {
  398         /* cheap slen so you do not have library call */
  399         for( slen = i = 0; (c=cval(value+i)); ++i ){
  400             if( visible_control && iscntrl( c ) && !isspace(c) ){
  401                 ++slen;
  402             }
  403             ++slen;
  404         }
  405     }
  406     padlen = len - slen;
  407     if( padlen < 0 ) padlen = 0;
  408     if( ljust ) padlen = -padlen;
  409     while( padlen > 0 ) {
  410         dopr_outch( ' ' );
  411         --padlen;
  412     }
  413     /* output characters */
  414     for( i = 0; (c = cval(value+i)); ++i ){
  415         if( visible_control && iscntrl( c ) && !isspace( c ) ){
  416             dopr_outch('^');
  417             c = ('@' | (c & 0x1F));
  418         }
  419         dopr_outch(c);
  420     }
  421     while( padlen < 0 ) {
  422         dopr_outch( ' ' );
  423         ++padlen;
  424     }
  425 }
  426 
  427 static void
  428 fmtnum(  union value *value, int plp_base, int dosign, int ljust,
  429     int len, int zpad )
  430 {
  431     int signvalue = 0;
  432 #ifdef HAVE_LONG_LONG
  433     unsigned long long uvalue;
  434 #else
  435     unsigned long uvalue;
  436 #endif /* HAVE_LONG_LONG */
  437     char convert[64];
  438     int place = 0;
  439     int padlen = 0; /* amount to pad */
  440     int caps = 0;
  441 
  442     /* fprintf(stderr,"value 0x%x, plp_base %d, dosign %d, ljust %d, len %d, zpad %d\n",
  443         value, plp_base, dosign, ljust, len, zpad );/ **/
  444     uvalue = value->value;
  445     if( dosign ){
  446         if( value->value < 0 ) {
  447             signvalue = '-';
  448             uvalue = -value->value;
  449         }
  450     }
  451     if( plp_base < 0 ){
  452         caps = 1;
  453         plp_base = -plp_base;
  454     }
  455     do{
  456         convert[place++] =
  457             (caps? "0123456789ABCDEF":"0123456789abcdef")
  458              [uvalue % (unsigned)plp_base  ];
  459         uvalue = (uvalue / (unsigned)plp_base );
  460     }while(uvalue);
  461     convert[place] = 0;
  462     padlen = len - place;
  463     if( padlen < 0 ) padlen = 0;
  464     if( ljust ) padlen = -padlen;
  465     /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n",
  466         convert,place,signvalue,padlen); / **/
  467     if( zpad && padlen > 0 ){
  468         if( signvalue ){
  469             dopr_outch( signvalue );
  470             --padlen;
  471             signvalue = 0;
  472         }
  473         while( padlen > 0 ){
  474             dopr_outch( zpad );
  475             --padlen;
  476         }
  477     }
  478     while( padlen > 0 ) {
  479         dopr_outch( ' ' );
  480         --padlen;
  481     }
  482     if( signvalue ) dopr_outch( signvalue );
  483     while( place > 0 ) dopr_outch( convert[--place] );
  484     while( padlen < 0 ){
  485         dopr_outch( ' ' );
  486         ++padlen;
  487     }
  488 }
  489 
  490 static void
  491 plp_strcat(char *dest, const char *src )
  492 {
  493     if( dest && src ){
  494         dest += strlen(dest);
  495         strcpy(dest,src);
  496     }
  497 }
  498 
  499 static void
  500 fmtdouble( int fmt, double value, int ljust, int len, int zpad, int precision )
  501 {
  502     char convert[128];
  503     char fmts[128];
  504     int l;
  505 
  506     if( len == 0 )
  507         len = 10;
  508     if( len > (int) (sizeof(convert) - 20) )
  509         len = sizeof(convert) - 20;
  510     if( precision > (int) sizeof(convert) - 20 )
  511         precision = sizeof(convert) - 20;
  512     if( precision > len )
  513         precision = len;
  514     strcpy( fmts, "%" );
  515     if( ljust )
  516         plp_strcat(fmts, "-" );
  517     if( zpad )
  518         plp_strcat(fmts, "0" );
  519     if( len )
  520         sprintf( fmts+strlen(fmts), "%d", len );
  521     if( precision > 0 )
  522         sprintf( fmts+strlen(fmts), ".%d", precision );
  523     l = strlen( fmts );
  524     fmts[l] = fmt;
  525     fmts[l+1] = 0;
  526     /* this is easier than trying to do the portable dtostr */
  527     sprintf( convert, fmts, value );
  528     dostr( convert );
  529 }
  530 
  531 static void dostr( const char *str )
  532 {
  533     while(*str) dopr_outch(*str++);
  534 }
  535 
  536 static void dopr_outch( int c )
  537 {
  538     if( end == 0 || output < end ){
  539         *output++ = c;
  540     }
  541 }
  542 
  543 
  544 /****************************************************************************
  545  * static char *plp_errormsg( int err )
  546  *  returns a printable form of the
  547  *  errormessage corresponding to the valie of err.
  548  *  This is the poor man's version of sperror(), not available on all systems
  549  *  Patrick Powell Tue Apr 11 08:05:05 PDT 1995
  550  ****************************************************************************/
  551 /****************************************************************************/
  552 #if !defined(HAVE_STRERROR)
  553 
  554 # if defined(HAVE_SYS_NERR)
  555 #  if !defined(HAVE_SYS_NERR_DEF)
  556      extern int sys_nerr;
  557 #  endif
  558 #  define num_errors    (sys_nerr)
  559 # else
  560 #  define num_errors    (-1)            /* always use "errno=%d" */
  561 # endif
  562 
  563 # if defined(HAVE_SYS_ERRLIST)
  564 #  if !defined(HAVE_SYS_ERRLIST_DEF)
  565      extern const char *const sys_errlist[];
  566 #  endif
  567 # else
  568 #  undef  num_errors
  569 #  define num_errors   (-1)            /* always use "errno=%d" */
  570 # endif
  571 
  572 #endif
  573 
  574 static char * plp_Errormsg ( int err )
  575 {
  576     char *cp;
  577 
  578 #if defined(HAVE_STRERROR)
  579     cp = (void *)strerror(err);
  580 #else
  581 # if defined(HAVE_SYS_ERRLIST)
  582     if (err >= 0 && err < num_errors) {
  583         cp = (void *)sys_errlist[err];
  584     } else
  585 # endif
  586     {
  587         static char msgbuf[32];     /* holds "errno=%d". */
  588         /* SAFE use of sprintf */
  589         (void) sprintf(msgbuf, "errno=%d", err);
  590         cp = msgbuf;
  591     }
  592 #endif
  593     return (cp);
  594 }
  595 
  596 #if defined(TEST)
  597 #include <stdio.h>
  598 int main( void )
  599 {
  600     char buffer[128];
  601     char *t;
  602     char *test1 = "01234";
  603     errno = 1;
  604     plp_snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "%s = '%s'\n", t, buffer );
  605     plp_snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "%s = '%s'\n", t, buffer );
  606     plp_snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "%s = '%s'\n", t, buffer );
  607     plp_snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "%s = '%s'\n", t, buffer );
  608     plp_snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "%s = '%s'\n", t, buffer );
  609     plp_snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "%s = '%s'\n", t, buffer );
  610     plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "%s = '%s'\n", t, buffer );
  611     plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "%s = '%s'\n", t, buffer );
  612     plp_snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "%s = '%s'\n", t, buffer );
  613     plp_snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "%s = '%s'\n", t, buffer );
  614     plp_snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "%s = '%s'\n", t, buffer );
  615 #if defined(HAVE_LONG_LONG)
  616     plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "%s = '%s'\n", t, buffer );
  617     plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "%s = '%s'\n", t, buffer );
  618     plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "%s = '%s'\n", t, buffer );
  619     plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "%s = '%s'\n", t, buffer );
  620 #endif
  621     return(0);
  622 }
  623 #endif
  624 #endif /* !HAVE_SNPRINTF && !HAVE_VSNPRINTF */