"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/isc/print.c" (7 Sep 2020, 13825 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 /*! \file */
   13 
   14 #include <config.h>
   15 
   16 #include <ctype.h>
   17 #include <inttypes.h>
   18 #include <stdbool.h>
   19 #include <stdio.h>      /* for sprintf() */
   20 #include <string.h>     /* for strlen() */
   21 #include <assert.h>     /* for assert() */
   22 
   23 #define ISC__PRINT_SOURCE   /* Used to get the isc_print_* prototypes. */
   24 
   25 #include <isc/assertions.h>
   26 #include <isc/msgs.h>
   27 #include <isc/print.h>
   28 #include <isc/stdlib.h>
   29 #include <isc/util.h>
   30 
   31 /*
   32  * We use the system's sprintf so we undef it here.
   33  */
   34 #undef sprintf
   35 
   36 static int
   37 isc__print_printf(void (*emit)(char, void *), void *arg,
   38           const char *format, va_list ap);
   39 
   40 static void
   41 file_emit(char c, void *arg) {
   42     FILE *fp = arg;
   43     int i = c & 0xff;
   44 
   45     putc(i, fp);
   46 }
   47 
   48 #if 0
   49 static int
   50 isc_print_vfprintf(FILE *fp, const char *format, va_list ap) {
   51     assert(fp != NULL);
   52     assert(format != NULL);
   53 
   54     return (isc__print_printf(file_emit, fp, format, ap));
   55 }
   56 #endif
   57 
   58 int
   59 isc_print_printf(const char *format, ...) {
   60     va_list ap;
   61     int n;
   62 
   63     assert(format != NULL);
   64 
   65     va_start(ap, format);
   66     n = isc__print_printf(file_emit, stdout, format, ap);
   67     va_end(ap);
   68     return (n);
   69 }
   70 
   71 int
   72 isc_print_fprintf(FILE *fp, const char *format, ...) {
   73     va_list ap;
   74     int n;
   75 
   76     assert(fp != NULL);
   77     assert(format != NULL);
   78 
   79     va_start(ap, format);
   80     n = isc__print_printf(file_emit, fp, format, ap);
   81     va_end(ap);
   82     return (n);
   83 }
   84 
   85 static void
   86 nocheck_emit(char c, void *arg) {
   87     struct { char *str; } *a = arg;
   88 
   89     *(a->str)++ = c;
   90 }
   91 
   92 int
   93 isc_print_sprintf(char *str, const char *format, ...) {
   94     struct { char *str; } arg;
   95     int n;
   96     va_list ap;
   97 
   98     arg.str = str;
   99 
  100     va_start(ap, format);
  101     n = isc__print_printf(nocheck_emit, &arg, format, ap);
  102     va_end(ap);
  103     return (n);
  104 }
  105 
  106 /*!
  107  * Return length of string that would have been written if not truncated.
  108  */
  109 
  110 int
  111 isc_print_snprintf(char *str, size_t size, const char *format, ...) {
  112     va_list ap;
  113     int ret;
  114 
  115     va_start(ap, format);
  116     ret = isc_print_vsnprintf(str, size, format, ap);
  117     va_end(ap);
  118     return (ret);
  119 
  120 }
  121 
  122 /*!
  123  * Return length of string that would have been written if not truncated.
  124  */
  125 
  126 static void
  127 string_emit(char c, void *arg) {
  128     struct { char *str; size_t size; } *p = arg;
  129 
  130     if (p->size > 0U) {
  131         *(p->str)++ = c;
  132         p->size--;
  133     }
  134 }
  135 
  136 int
  137 isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
  138     struct { char *str; size_t size; } arg;
  139     int n;
  140 
  141     assert(str != NULL);
  142     assert(format != NULL);
  143 
  144     arg.str = str;
  145     arg.size = size;
  146 
  147     n = isc__print_printf(string_emit, &arg, format, ap);
  148     if (arg.size > 0U)
  149         *arg.str = '\0';
  150     return (n);
  151 }
  152 
  153 static int
  154 isc__print_printf(void (*emit)(char, void *), void *arg,
  155           const char *format, va_list ap)
  156 {
  157     int h;
  158     int l;
  159     int z;
  160     int q;
  161     int alt;
  162     int zero;
  163     int left;
  164     int plus;
  165     int space;
  166     int64_t tmpi;
  167     uint64_t tmpui;
  168     unsigned long width;
  169     unsigned long precision;
  170     unsigned int length;
  171     char buf[1024];
  172     char c;
  173     void *v;
  174     const char *cp;
  175     const char *head;
  176     int count = 0;
  177     int pad;
  178     int zeropad;
  179     int dot;
  180     double dbl;
  181     bool precision_set;
  182 #ifdef HAVE_LONG_DOUBLE
  183     long double ldbl;
  184 #endif
  185     char fmt[32];
  186 
  187     assert(emit != NULL);
  188     assert(arg != NULL);
  189     assert(format != NULL);
  190 
  191     while (*format != '\0') {
  192         if (*format != '%') {
  193             emit(*format++, arg);
  194             count++;
  195             continue;
  196         }
  197         format++;
  198 
  199         /*
  200          * Reset flags.
  201          */
  202         dot = space = plus = left = zero = alt = h = l = q = z = 0;
  203         width = precision = 0;
  204         head = "";
  205         pad = zeropad = 0;
  206         precision_set = false;
  207 
  208         do {
  209             if (*format == '#') {
  210                 alt = 1;
  211                 format++;
  212             } else if (*format == '-') {
  213                 left = 1;
  214                 zero = 0;
  215                 format++;
  216             } else if (*format == ' ') {
  217                 if (!plus)
  218                     space = 1;
  219                 format++;
  220             } else if (*format == '+') {
  221                 plus = 1;
  222                 space = 0;
  223                 format++;
  224             } else if (*format == '0') {
  225                 if (!left)
  226                     zero = 1;
  227                 format++;
  228             } else
  229                 break;
  230         } while (1);
  231 
  232         /*
  233          * Width.
  234          */
  235         if (*format == '*') {
  236             width = va_arg(ap, int);
  237             format++;
  238         } else if (isdigit((unsigned char)*format)) {
  239             char *e;
  240             width = strtoul(format, &e, 10);
  241             format = e;
  242         }
  243 
  244         /*
  245          * Precision.
  246          */
  247         if (*format == '.') {
  248             format++;
  249             dot = 1;
  250             if (*format == '*') {
  251                 precision = va_arg(ap, int);
  252                 precision_set = true;
  253                 format++;
  254             } else if (isdigit((unsigned char)*format)) {
  255                 char *e;
  256                 precision = strtoul(format, &e, 10);
  257                 precision_set = true;
  258                 format = e;
  259             }
  260         }
  261 
  262         switch (*format) {
  263         case '\0':
  264             continue;
  265         case '%':
  266             emit(*format, arg);
  267             count++;
  268             break;
  269         case 'q':
  270             q = 1;
  271             format++;
  272             goto doint;
  273         case 'h':
  274             h = 1;
  275             format++;
  276             goto doint;
  277         case 'l':
  278             l = 1;
  279             format++;
  280             if (*format == 'l') {
  281                 q = 1;
  282                 format++;
  283             }
  284             goto doint;
  285         case 'z':
  286             z = 1;
  287             format++;
  288             goto doint;
  289 #ifdef WIN32
  290         case 'I':
  291             /* Windows has I64 as a modifier for a quad. */
  292             if (format[1] == '6' && format[2] == '4') {
  293                 q = 1;
  294                 format += 3;
  295                 goto doint;
  296             }
  297             continue;
  298 #endif
  299         case 'n':
  300         case 'i':
  301         case 'd':
  302         case 'o':
  303         case 'u':
  304         case 'x':
  305         case 'X':
  306         doint:
  307             if (precision != 0U)
  308                 zero = 0;
  309             switch (*format) {
  310             case 'n':
  311                 if (h) {
  312                     short int *p;
  313                     p = va_arg(ap, short *);
  314                     assert(p != NULL);
  315                     *p = count;
  316                 } else if (l) {
  317                     long int *p;
  318                     p = va_arg(ap, long *);
  319                     assert(p != NULL);
  320                     *p = count;
  321                 } else if (z) {
  322                     size_t *p;
  323                     p = va_arg(ap, size_t *);
  324                     assert(p != NULL);
  325                     *p = count;
  326                 } else {
  327                     int *p;
  328                     p = va_arg(ap, int *);
  329                     assert(p != NULL);
  330                     *p = count;
  331                 }
  332                 break;
  333             case 'i':
  334             case 'd':
  335                 if (q)
  336                     tmpi = va_arg(ap, int64_t);
  337                 else if (l)
  338                     tmpi = va_arg(ap, long int);
  339                 else if (z)
  340                     tmpi = va_arg(ap, ssize_t);
  341                 else
  342                     tmpi = va_arg(ap, int);
  343                 if (tmpi < 0) {
  344                     head = "-";
  345                     tmpui = -tmpi;
  346                 } else {
  347                     if (plus)
  348                         head = "+";
  349                     else if (space)
  350                         head = " ";
  351                     else
  352                         head = "";
  353                     tmpui = tmpi;
  354                 }
  355                 if (tmpui <= 0xffffffffU)
  356                     sprintf(buf, "%lu",
  357                         (unsigned long)tmpui);
  358                 else {
  359                     unsigned long mid;
  360                     unsigned long lo;
  361                     unsigned long hi;
  362                     lo = tmpui % 1000000000;
  363                     tmpui /= 1000000000;
  364                     mid = tmpui % 1000000000;
  365                     hi = tmpui / 1000000000;
  366                     if (hi != 0U) {
  367                         sprintf(buf, "%lu", hi);
  368                         sprintf(buf + strlen(buf),
  369                             "%09lu", mid);
  370                     } else
  371                         sprintf(buf, "%lu", mid);
  372                     sprintf(buf + strlen(buf), "%09lu",
  373                         lo);
  374                 }
  375                 goto printint;
  376             case 'o':
  377                 if (q)
  378                     tmpui = va_arg(ap, uint64_t);
  379                 else if (l)
  380                     tmpui = va_arg(ap, long int);
  381                 else if (z)
  382                     tmpui = va_arg(ap, size_t);
  383                 else
  384                     tmpui = va_arg(ap, int);
  385                 if (tmpui <= 0xffffffffU)
  386                     sprintf(buf, alt ?  "%#lo" : "%lo",
  387                         (unsigned long)tmpui);
  388                 else {
  389                     unsigned long mid;
  390                     unsigned long lo;
  391                     unsigned long hi;
  392                     lo = tmpui % 010000000000;
  393                     tmpui /= 010000000000;
  394                     mid = tmpui % 010000000000;
  395                     hi = tmpui / 010000000000;
  396                     if (hi != 0U) {
  397                         sprintf(buf,
  398                             alt ?  "%#lo" : "%lo",
  399                             hi);
  400                         sprintf(buf + strlen(buf),
  401                             "%09lo", mid);
  402                     } else
  403                         sprintf(buf,
  404                             alt ?  "%#lo" : "%lo",
  405                             mid);
  406                     sprintf(buf + strlen(buf), "%09lo", lo);
  407                 }
  408                 goto printint;
  409             case 'u':
  410                 if (q)
  411                     tmpui = va_arg(ap, uint64_t);
  412                 else if (l)
  413                     tmpui = va_arg(ap, unsigned long int);
  414                 else if (z)
  415                     tmpui = va_arg(ap, size_t);
  416                 else
  417                     tmpui = va_arg(ap, unsigned int);
  418                 if (tmpui <= 0xffffffffU)
  419                     sprintf(buf, "%lu",
  420                         (unsigned long)tmpui);
  421                 else {
  422                     unsigned long mid;
  423                     unsigned long lo;
  424                     unsigned long hi;
  425                     lo = tmpui % 1000000000;
  426                     tmpui /= 1000000000;
  427                     mid = tmpui % 1000000000;
  428                     hi = tmpui / 1000000000;
  429                     if (hi != 0U) {
  430                         sprintf(buf, "%lu", hi);
  431                         sprintf(buf + strlen(buf),
  432                             "%09lu", mid);
  433                      } else
  434                         sprintf(buf, "%lu", mid);
  435                     sprintf(buf + strlen(buf), "%09lu",
  436                         lo);
  437                 }
  438                 goto printint;
  439             case 'x':
  440                 if (q)
  441                     tmpui = va_arg(ap, uint64_t);
  442                 else if (l)
  443                     tmpui = va_arg(ap, unsigned long int);
  444                 else if (z)
  445                     tmpui = va_arg(ap, size_t);
  446                 else
  447                     tmpui = va_arg(ap, unsigned int);
  448                 if (alt) {
  449                     head = "0x";
  450                     if (precision > 2U)
  451                         precision -= 2;
  452                 }
  453                 if (tmpui <= 0xffffffffU)
  454                     sprintf(buf, "%lx",
  455                         (unsigned long)tmpui);
  456                 else {
  457                     unsigned long hi = tmpui>>32;
  458                     unsigned long lo = tmpui & 0xffffffff;
  459                     sprintf(buf, "%lx", hi);
  460                     sprintf(buf + strlen(buf), "%08lx", lo);
  461                 }
  462                 goto printint;
  463             case 'X':
  464                 if (q)
  465                     tmpui = va_arg(ap, uint64_t);
  466                 else if (l)
  467                     tmpui = va_arg(ap, unsigned long int);
  468                 else if (z)
  469                     tmpui = va_arg(ap, size_t);
  470                 else
  471                     tmpui = va_arg(ap, unsigned int);
  472                 if (alt) {
  473                     head = "0X";
  474                     if (precision > 2U)
  475                         precision -= 2;
  476                 }
  477                 if (tmpui <= 0xffffffffU)
  478                     sprintf(buf, "%lX",
  479                         (unsigned long)tmpui);
  480                 else  {
  481                     unsigned long hi = tmpui>>32;
  482                     unsigned long lo = tmpui & 0xffffffff;
  483                     sprintf(buf, "%lX", hi);
  484                     sprintf(buf + strlen(buf), "%08lX", lo);
  485                 }
  486                 goto printint;
  487             printint:
  488                 if (precision_set || width != 0U) {
  489                     length = strlen(buf);
  490                     if (length < precision)
  491                         zeropad = precision - length;
  492                     else if (length < width && zero)
  493                         zeropad = width - length;
  494                     if (width != 0U) {
  495                         pad = width - length -
  496                               zeropad - strlen(head);
  497                         if (pad < 0)
  498                             pad = 0;
  499                     }
  500                 }
  501                 count += strlen(head) + strlen(buf) + pad +
  502                      zeropad;
  503                 if (!left) {
  504                     while (pad > 0) {
  505                         emit(' ', arg);
  506                         pad--;
  507                     }
  508                 }
  509                 cp = head;
  510                 while (*cp != '\0')
  511                     emit(*cp++, arg);
  512                 while (zeropad > 0) {
  513                     emit('0', arg);
  514                     zeropad--;
  515                 }
  516                 cp = buf;
  517                 while (*cp != '\0')
  518                     emit(*cp++, arg);
  519                 while (pad > 0) {
  520                     emit(' ', arg);
  521                     pad--;
  522                 }
  523                 break;
  524             default:
  525                 break;
  526             }
  527             break;
  528         case 's':
  529             cp = va_arg(ap, char *);
  530 
  531             if (precision_set) {
  532                 /*
  533                  * cp need not be NULL terminated.
  534                  */
  535                 const char *tp;
  536                 unsigned long n;
  537 
  538                 if (precision != 0U)
  539                     assert(cp != NULL);
  540                 n = precision;
  541                 tp = cp;
  542                 while (n != 0U && *tp != '\0')
  543                     n--, tp++;
  544                 length = precision - n;
  545             } else {
  546                 assert(cp != NULL);
  547                 length = strlen(cp);
  548             }
  549             if (width != 0U) {
  550                 pad = width - length;
  551                 if (pad < 0)
  552                     pad = 0;
  553             }
  554             count += pad + length;
  555             if (!left)
  556                 while (pad > 0) {
  557                     emit(' ', arg);
  558                     pad--;
  559                 }
  560             if (precision_set)
  561                 while (precision > 0U && *cp != '\0') {
  562                     emit(*cp++, arg);
  563                     precision--;
  564                 }
  565             else
  566                 while (*cp != '\0')
  567                     emit(*cp++, arg);
  568             while (pad > 0) {
  569                 emit(' ', arg);
  570                 pad--;
  571             }
  572             break;
  573         case 'c':
  574             c = va_arg(ap, int);
  575             if (width > 0U) {
  576                 count += width;
  577                 width--;
  578                 if (left)
  579                     emit(c, arg);
  580                 while (width-- > 0U)
  581                     emit(' ', arg);
  582                 if (!left)
  583                     emit(c, arg);
  584             } else {
  585                 count++;
  586                 emit(c, arg);
  587             }
  588             break;
  589         case 'p':
  590             v = va_arg(ap, void *);
  591             sprintf(buf, "%p", v);
  592             length = strlen(buf);
  593             if (precision > length)
  594                 zeropad = precision - length;
  595             if (width > 0U) {
  596                 pad = width - length - zeropad;
  597                 if (pad < 0)
  598                     pad = 0;
  599             }
  600             count += length + pad + zeropad;
  601             if (!left)
  602                 while (pad > 0) {
  603                     emit(' ', arg);
  604                     pad--;
  605                 }
  606             cp = buf;
  607             if (zeropad > 0 && buf[0] == '0' &&
  608                 (buf[1] == 'x' || buf[1] == 'X')) {
  609                 emit(*cp++, arg);
  610                 emit(*cp++, arg);
  611                 while (zeropad > 0) {
  612                     emit('0', arg);
  613                     zeropad--;
  614                 }
  615             }
  616             while (*cp != '\0')
  617                 emit(*cp++, arg);
  618             while (pad > 0) {
  619                 emit(' ', arg);
  620                 pad--;
  621             }
  622             break;
  623         case 'D':   /*deprecated*/
  624             /* cppcheck-suppress literalWithCharPtrCompare */
  625             assert("use %ld instead of %D" == NULL);
  626         case 'O':   /*deprecated*/
  627             /* cppcheck-suppress literalWithCharPtrCompare */
  628             assert("use %lo instead of %O" == NULL);
  629         case 'U':   /*deprecated*/
  630             /* cppcheck-suppress literalWithCharPtrCompare */
  631             assert("use %lu instead of %U" == NULL);
  632 
  633         case 'L':
  634 #ifdef HAVE_LONG_DOUBLE
  635             l = 1;
  636 #else
  637             /* cppcheck-suppress literalWithCharPtrCompare */
  638             assert("long doubles are not supported" == NULL);
  639 #endif
  640             /* FALLTHROUGH */
  641         case 'e':
  642         case 'E':
  643         case 'f':
  644         case 'g':
  645         case 'G':
  646             if (!dot)
  647                 precision = 6;
  648             /*
  649              * IEEE floating point.
  650              * MIN 2.2250738585072014E-308
  651              * MAX 1.7976931348623157E+308
  652              * VAX floating point has a smaller range than IEEE.
  653              *
  654              * precisions > 324 don't make much sense.
  655              * if we cap the precision at 512 we will not
  656              * overflow buf.
  657              */
  658             if (precision > 512U)
  659                 precision = 512;
  660             sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
  661                 plus ? "+" : space ? " " : "",
  662                 precision, l ? "L" : "", *format);
  663             switch (*format) {
  664             case 'e':
  665             case 'E':
  666             case 'f':
  667             case 'g':
  668             case 'G':
  669 #ifdef HAVE_LONG_DOUBLE
  670                 if (l) {
  671                     ldbl = va_arg(ap, long double);
  672                     sprintf(buf, fmt, ldbl);
  673                 } else
  674 #endif
  675                 {
  676                     dbl = va_arg(ap, double);
  677                     sprintf(buf, fmt, dbl);
  678                 }
  679                 length = strlen(buf);
  680                 if (width > 0U) {
  681                     pad = width - length;
  682                     if (pad < 0)
  683                         pad = 0;
  684                 }
  685                 count += length + pad;
  686                 if (!left)
  687                     while (pad > 0) {
  688                         emit(' ', arg);
  689                         pad--;
  690                     }
  691                 cp = buf;
  692                 while (*cp != '\0')
  693                     emit(*cp++, arg);
  694                 while (pad > 0) {
  695                     emit(' ', arg);
  696                     pad--;
  697                 }
  698                 break;
  699             default:
  700                 continue;
  701             }
  702             break;
  703         default:
  704             continue;
  705         }
  706         format++;
  707     }
  708     return (count);
  709 }