"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/lwres/print.c" (7 Sep 2020, 10897 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


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 "print.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <config.h>
   13 
   14 #include <ctype.h>
   15 #include <inttypes.h>
   16 #include <stdio.h>      /* for sprintf */
   17 #include <string.h>
   18 
   19 #define LWRES__PRINT_SOURCE /* Used to get the lwres_print_* prototypes. */
   20 
   21 #include <lwres/stdlib.h>
   22 #include <lwres/string.h>
   23 
   24 #include "assert_p.h"
   25 #include "print_p.h"
   26 
   27 int
   28 lwres__print_sprintf(char *str, const char *format, ...) {
   29     va_list ap;
   30 
   31     va_start(ap, format);
   32     vsprintf(str, format, ap);
   33     va_end(ap);
   34     return (strlen(str));
   35 }
   36 
   37 /*
   38  * Return length of string that would have been written if not truncated.
   39  */
   40 
   41 int
   42 lwres__print_snprintf(char *str, size_t size, const char *format, ...) {
   43     va_list ap;
   44     int ret;
   45 
   46     va_start(ap, format);
   47     ret = vsnprintf(str, size, format, ap);
   48     va_end(ap);
   49     return (ret);
   50 
   51 }
   52 
   53 /*
   54  * Return length of string that would have been written if not truncated.
   55  */
   56 
   57 int
   58 lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
   59     int h;
   60     int l;
   61     int q;
   62     int z;
   63     int alt;
   64     int zero;
   65     int left;
   66     int plus;
   67     int space;
   68     long long tmpi;
   69     unsigned long long tmpui;
   70     unsigned long width;
   71     unsigned long precision;
   72     unsigned int length;
   73     char buf[1024];
   74     char c;
   75     void *v;
   76     char *save = str;
   77     const char *cp;
   78     const char *head;
   79     int count = 0;
   80     int pad;
   81     int zeropad;
   82     int dot;
   83     double dbl;
   84 #ifdef HAVE_LONG_DOUBLE
   85     long double ldbl;
   86 #endif
   87     char fmt[32];
   88 
   89     INSIST(str != NULL);
   90     INSIST(format != NULL);
   91 
   92     while (*format != '\0') {
   93         if (*format != '%') {
   94             if (size > 1U) {
   95                 *str++ = *format;
   96                 size--;
   97             }
   98             count++;
   99             format++;
  100             continue;
  101         }
  102         format++;
  103 
  104         /*
  105          * Reset flags.
  106          */
  107         dot = space = plus = left = zero = alt = h = l = q = z = 0;
  108         width = precision = 0;
  109         head = "";
  110         length = pad = zeropad = 0;
  111         POST(length);
  112 
  113         do {
  114             if (*format == '#') {
  115                 alt = 1;
  116                 format++;
  117             } else if (*format == '-') {
  118                 left = 1;
  119                 zero = 0;
  120                 format++;
  121             } else if (*format == ' ') {
  122                 if (!plus)
  123                     space = 1;
  124                 format++;
  125             } else if (*format == '+') {
  126                 plus = 1;
  127                 space = 0;
  128                 format++;
  129             } else if (*format == '0') {
  130                 if (!left)
  131                     zero = 1;
  132                 format++;
  133             } else
  134                 break;
  135         } while (1);
  136 
  137         /*
  138          * Width.
  139          */
  140         if (*format == '*') {
  141             width = va_arg(ap, int);
  142             format++;
  143         } else if (isdigit((unsigned char)*format)) {
  144             char *e;
  145             width = strtoul(format, &e, 10);
  146             format = e;
  147         }
  148 
  149         /*
  150          * Precision.
  151          */
  152         if (*format == '.') {
  153             format++;
  154             dot = 1;
  155             if (*format == '*') {
  156                 precision = va_arg(ap, int);
  157                 format++;
  158             } else if (isdigit((unsigned char)*format)) {
  159                 char *e;
  160                 precision = strtoul(format, &e, 10);
  161                 format = e;
  162             }
  163         }
  164 
  165         switch (*format) {
  166         case '\0':
  167             continue;
  168         case '%':
  169             if (size > 1U) {
  170                 *str++ = *format;
  171                 size--;
  172             }
  173             count++;
  174             break;
  175         case 'q':
  176             q = 1;
  177             format++;
  178             goto doint;
  179         case 'h':
  180             h = 1;
  181             format++;
  182             goto doint;
  183         case 'l':
  184             l = 1;
  185             format++;
  186             if (*format == 'l') {
  187                 q = 1;
  188                 format++;
  189             }
  190             goto doint;
  191         case 'z':
  192             z = 1;
  193             format++;
  194             goto doint;
  195         case 'n':
  196         case 'i':
  197         case 'd':
  198         case 'o':
  199         case 'u':
  200         case 'x':
  201         case 'X':
  202         doint:
  203             if (precision != 0U)
  204                 zero = 0;
  205             switch (*format) {
  206             case 'n':
  207                 if (h) {
  208                     short int *p;
  209                     p = va_arg(ap, short *);
  210                     REQUIRE(p != NULL);
  211                     *p = str - save;
  212                 } else if (l) {
  213                     long int *p;
  214                     p = va_arg(ap, long *);
  215                     REQUIRE(p != NULL);
  216                     *p = str - save;
  217                 } else if (z) {
  218                     size_t *p;
  219                     p = va_arg(ap, size_t *);
  220                     REQUIRE(p != NULL);
  221                     *p = str - save;
  222                 } else {
  223                     int *p;
  224                     p = va_arg(ap, int *);
  225                     REQUIRE(p != NULL);
  226                     *p = str - save;
  227                 }
  228                 break;
  229             case 'i':
  230             case 'd':
  231                 if (q)
  232                     tmpi = va_arg(ap, long long int);
  233                 else if (l)
  234                     tmpi = va_arg(ap, long int);
  235                 else if (z)
  236                     tmpi = va_arg(ap, size_t);
  237                 else
  238                     tmpi = va_arg(ap, int);
  239                 if (tmpi < 0) {
  240                     head = "-";
  241                     tmpui = -tmpi;
  242                 } else {
  243                     if (plus)
  244                         head = "+";
  245                     else if (space)
  246                         head = " ";
  247                     else
  248                         head = "";
  249                     tmpui = tmpi;
  250                 }
  251                 sprintf(buf, "%llu",
  252                     tmpui);
  253                 goto printint;
  254             case 'o':
  255                 if (q)
  256                     tmpui = va_arg(ap,
  257                                unsigned long long int);
  258                 else if (l)
  259                     tmpui = va_arg(ap, long int);
  260                 else if (z)
  261                     tmpui = va_arg(ap, size_t);
  262                 else
  263                     tmpui = va_arg(ap, int);
  264                 sprintf(buf,
  265                     alt ? "%#llo"
  266                         : "%llo",
  267                     tmpui);
  268                 goto printint;
  269             case 'u':
  270                 if (q)
  271                     tmpui = va_arg(ap,
  272                                unsigned long long int);
  273                 else if (l)
  274                     tmpui = va_arg(ap, unsigned long int);
  275                 else if (z)
  276                     tmpui = va_arg(ap, size_t);
  277                 else
  278                     tmpui = va_arg(ap, unsigned int);
  279                 sprintf(buf, "%llu",
  280                     tmpui);
  281                 goto printint;
  282             case 'x':
  283                 if (q)
  284                     tmpui = va_arg(ap,
  285                                unsigned long long int);
  286                 else if (l)
  287                     tmpui = va_arg(ap, unsigned long int);
  288                 else if (z)
  289                     tmpui = va_arg(ap, size_t);
  290                 else
  291                     tmpui = va_arg(ap, unsigned int);
  292                 if (alt) {
  293                     head = "0x";
  294                     if (precision > 2U)
  295                         precision -= 2;
  296                 }
  297                 sprintf(buf, "%llx",
  298                     tmpui);
  299                 goto printint;
  300             case 'X':
  301                 if (q)
  302                     tmpui = va_arg(ap,
  303                                unsigned long long int);
  304                 else if (l)
  305                     tmpui = va_arg(ap, unsigned long int);
  306                 else if (z)
  307                     tmpui = va_arg(ap, size_t);
  308                 else
  309                     tmpui = va_arg(ap, unsigned int);
  310                 if (alt) {
  311                     head = "0X";
  312                     if (precision > 2U)
  313                         precision -= 2;
  314                 }
  315                 sprintf(buf, "%llX",
  316                     tmpui);
  317                 goto printint;
  318             printint:
  319                 if (precision != 0U || width != 0U) {
  320                     length = strlen(buf);
  321                     if (length < precision)
  322                         zeropad = precision - length;
  323                     else if (length < width && zero)
  324                         zeropad = width - length;
  325                     if (width != 0U) {
  326                         pad = width - length -
  327                               zeropad - strlen(head);
  328                         if (pad < 0)
  329                             pad = 0;
  330                     }
  331                 }
  332                 count += strlen(head) + strlen(buf) + pad +
  333                      zeropad;
  334                 if (!left) {
  335                     while (pad > 0 && size > 1U) {
  336                         *str++ = ' ';
  337                         size--;
  338                         pad--;
  339                     }
  340                 }
  341                 cp = head;
  342                 while (*cp != '\0' && size > 1U) {
  343                     *str++ = *cp++;
  344                     size--;
  345                 }
  346                 while (zeropad > 0 && size > 1U) {
  347                     *str++ = '0';
  348                     size--;
  349                     zeropad--;
  350                 }
  351                 cp = buf;
  352                 while (*cp != '\0' && size > 1U) {
  353                     *str++ = *cp++;
  354                     size--;
  355                 }
  356                 while (pad > 0 && size > 1U) {
  357                     *str++ = ' ';
  358                     size--;
  359                     pad--;
  360                 }
  361                 break;
  362             default:
  363                 break;
  364             }
  365             break;
  366         case 's':
  367             cp = va_arg(ap, char *);
  368             REQUIRE(cp != NULL);
  369 
  370             if (precision != 0U) {
  371                 /*
  372                  * cp need not be NULL terminated.
  373                  */
  374                 const char *tp;
  375                 unsigned long n;
  376 
  377                 n = precision;
  378                 tp = cp;
  379                 while (n != 0U && *tp != '\0')
  380                     n--, tp++;
  381                 length = precision - n;
  382             } else {
  383                 length = strlen(cp);
  384             }
  385             if (width != 0U) {
  386                 pad = width - length;
  387                 if (pad < 0)
  388                     pad = 0;
  389             }
  390             count += pad + length;
  391             if (!left)
  392                 while (pad > 0 && size > 1U) {
  393                     *str++ = ' ';
  394                     size--;
  395                     pad--;
  396                 }
  397             if (precision != 0U)
  398                 while (precision > 0U && *cp != '\0' &&
  399                        size > 1U) {
  400                     *str++ = *cp++;
  401                     size--;
  402                     precision--;
  403                 }
  404             else
  405                 while (*cp != '\0' && size > 1U) {
  406                     *str++ = *cp++;
  407                     size--;
  408                 }
  409             while (pad > 0 && size > 1U) {
  410                 *str++ = ' ';
  411                 size--;
  412                 pad--;
  413             }
  414             break;
  415         case 'c':
  416             c = va_arg(ap, int);
  417             if (width > 0U) {
  418                 count += width;
  419                 width--;
  420                 if (left) {
  421                     *str++ = c;
  422                     size--;
  423                 }
  424                 while (width-- > 0U && size > 1U) {
  425                     *str++ = ' ';
  426                     size--;
  427                 }
  428                 if (!left && size > 1U) {
  429                     *str++ = c;
  430                     size--;
  431                 }
  432             } else {
  433                 count++;
  434                 if (size > 1U) {
  435                     *str++ = c;
  436                     size--;
  437                 }
  438             }
  439             break;
  440         case 'p':
  441             v = va_arg(ap, void *);
  442             sprintf(buf, "%p", v);
  443             length = strlen(buf);
  444             if (precision > length)
  445                 zeropad = precision - length;
  446             if (width > 0U) {
  447                 pad = width - length - zeropad;
  448                 if (pad < 0)
  449                     pad = 0;
  450             }
  451             count += length + pad + zeropad;
  452             if (!left)
  453                 while (pad > 0 && size > 1U) {
  454                     *str++ = ' ';
  455                     size--;
  456                     pad--;
  457                 }
  458             cp = buf;
  459             if (zeropad > 0 && buf[0] == '0' &&
  460                 (buf[1] == 'x' || buf[1] == 'X')) {
  461                 if (size > 1U) {
  462                     *str++ = *cp++;
  463                     size--;
  464                 }
  465                 if (size > 1U) {
  466                     *str++ = *cp++;
  467                     size--;
  468                 }
  469                 while (zeropad > 0 && size > 1U) {
  470                     *str++ = '0';
  471                     size--;
  472                     zeropad--;
  473                 }
  474             }
  475             while (*cp != '\0' && size > 1U) {
  476                 *str++ = *cp++;
  477                 size--;
  478             }
  479             while (pad > 0 && size > 1U) {
  480                 *str++ = ' ';
  481                 size--;
  482                 pad--;
  483             }
  484             break;
  485 
  486         case 'D':   /*deprecated*/
  487             /* cppcheck-suppress literalWithCharPtrCompare */
  488             INSIST("use %ld instead of %D" == NULL);
  489             break;
  490         case 'O':   /*deprecated*/
  491             /* cppcheck-suppress literalWithCharPtrCompare */
  492             INSIST("use %lo instead of %O" == NULL);
  493             break;
  494         case 'U':   /*deprecated*/
  495             /* cppcheck-suppress literalWithCharPtrCompare */
  496             INSIST("use %lu instead of %U" == NULL);
  497             break;
  498 
  499         case 'L':
  500 #ifdef HAVE_LONG_DOUBLE
  501             l = 1;
  502 #else
  503             /* cppcheck-suppress literalWithCharPtrCompare */
  504             INSIST("long doubles are not supported" == NULL);
  505 #endif
  506             /* FALLTHROUGH */
  507         case 'e':
  508         case 'E':
  509         case 'f':
  510         case 'g':
  511         case 'G':
  512             if (!dot)
  513                 precision = 6;
  514             /*
  515              * IEEE floating point.
  516              * MIN 2.2250738585072014E-308
  517              * MAX 1.7976931348623157E+308
  518              * VAX floating point has a smaller range than IEEE.
  519              *
  520              * precisions > 324 don't make much sense.
  521              * if we cap the precision at 512 we will not
  522              * overflow buf.
  523              */
  524             if (precision > 512U)
  525                 precision = 512;
  526             sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
  527                 plus ? "+" : space ? " " : "",
  528                 precision, l ? "L" : "", *format);
  529             switch (*format) {
  530             case 'e':
  531             case 'E':
  532             case 'f':
  533             case 'g':
  534             case 'G':
  535 #ifdef HAVE_LONG_DOUBLE
  536                 if (l) {
  537                     ldbl = va_arg(ap, long double);
  538                     sprintf(buf, fmt, ldbl);
  539                 } else
  540 #endif
  541                 {
  542                     dbl = va_arg(ap, double);
  543                     sprintf(buf, fmt, dbl);
  544                 }
  545                 length = strlen(buf);
  546                 if (width > 0U) {
  547                     pad = width - length;
  548                     if (pad < 0)
  549                         pad = 0;
  550                 }
  551                 count += length + pad;
  552                 if (!left)
  553                     while (pad > 0 && size > 1U) {
  554                         *str++ = ' ';
  555                         size--;
  556                         pad--;
  557                     }
  558                 cp = buf;
  559                 while (*cp != ' ' && size > 1U) {
  560                     *str++ = *cp++;
  561                     size--;
  562                 }
  563                 while (pad > 0 && size > 1U) {
  564                     *str++ = ' ';
  565                     size--;
  566                     pad--;
  567                 }
  568                 break;
  569             default:
  570                 continue;
  571             }
  572             break;
  573         default:
  574             continue;
  575         }
  576         format++;
  577     }
  578     if (size > 0U)
  579         *str = '\0';
  580     return (count);
  581 }