omapip/iscprint.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: iscprint.c,v 1.2 2005/03/17 20:30:41 dhankins Exp $ */
00019 
00020 #include "dhcpd.h"
00021 
00022 #ifdef NO_SNPRINTF
00023 
00024 #ifndef LINT
00025 static char copyright[] =
00026 "$Id: iscprint.c,v 1.2 2005/03/17 20:30:41 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium, Inc.  All rights reserved.";
00027 #endif
00028 
00029 #define INSIST(cond)    REQUIRE(cond)
00030 #define REQUIRE(cond)   if (!(cond)) { return 0; }
00031 
00032 /*
00033  * Return length of string that would have been written if not truncated.
00034  */
00035 
00036 int
00037 isc_print_snprintf(char *str, size_t size, const char *format, ...) {
00038         va_list ap;
00039         int ret;
00040 
00041         va_start(ap, format);
00042         ret = vsnprintf(str, size, format, ap);
00043         va_end(ap);
00044         return (ret);
00045 }
00046 
00047 /*
00048  * Return length of string that would have been written if not truncated.
00049  */
00050 
00051 int
00052 isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
00053         int h;
00054         int l;
00055         int q;
00056         int alt;
00057         int zero;
00058         int left;
00059         int plus;
00060         int space;
00061         int neg;
00062         isc_int64_t tmpi;
00063         isc_uint64_t tmpui;
00064         unsigned long width;
00065         unsigned long precision;
00066         unsigned int length;
00067         char buf[1024];
00068         char c;
00069         void *v;
00070         char *save = str;
00071         const char *cp;
00072         const char *head;
00073         int count = 0;
00074         int pad;
00075         int zeropad;
00076         int dot;
00077         double dbl;
00078 #ifdef HAVE_LONG_DOUBLE
00079         long double ldbl;
00080 #endif
00081         char fmt[32];
00082 
00083         INSIST(str != NULL);
00084         INSIST(format != NULL);
00085 
00086         while (*format != '\0') {
00087                 if (*format != '%') {
00088                         if (size > 1) {
00089                                 *str++ = *format;
00090                                 size--;
00091                         }
00092                         count++;
00093                         format++;
00094                         continue;
00095                 }
00096                 format++;
00097 
00098                 /*
00099                  * Reset flags.
00100                  */
00101                 dot = neg = space = plus = left = zero = alt = h = l = q = 0;
00102                 width = precision = 0;
00103                 head = "";
00104                 length = pad = zeropad = 0;
00105 
00106                 do {
00107                         if (*format == '#') {
00108                                 alt = 1;
00109                                 format++;
00110                         } else if (*format == '-') {
00111                                 left = 1;
00112                                 zero = 0;
00113                                 format++;
00114                         } else if (*format == ' ') {
00115                                 if (!plus)
00116                                         space = 1;
00117                                 format++;
00118                         } else if (*format == '+') {
00119                                 plus = 1;
00120                                 space = 0;
00121                                 format++;
00122                         } else if (*format == '0') {
00123                                 if (!left)
00124                                         zero = 1;
00125                                 format++;
00126                         } else
00127                                 break;
00128                 } while (1);
00129 
00130                 /*
00131                  * Width.
00132                  */
00133                 if (*format == '*') {
00134                         width = va_arg(ap, int);
00135                         format++;
00136                 } else if (isdigit((unsigned char)*format)) {
00137                         char *e;
00138                         width = strtoul(format, &e, 10);
00139                         format = e;
00140                 }
00141 
00142                 /*
00143                  * Precision.
00144                  */
00145                 if (*format == '.') {
00146                         format++;
00147                         dot = 1;
00148                         if (*format == '*') {
00149                                 precision = va_arg(ap, int);
00150                                 format++;
00151                         } else if (isdigit((unsigned char)*format)) {
00152                                 char *e;
00153                                 precision = strtoul(format, &e, 10);
00154                                 format = e;
00155                         }
00156                 }
00157 
00158                 switch (*format) {
00159                 case '\0':
00160                         continue;
00161                 case '%':
00162                         if (size > 1) {
00163                                 *str++ = *format;
00164                                 size--;
00165                         }
00166                         count++;
00167                         break;
00168                 case 'q':
00169                         q = 1;
00170                         format++;
00171                         goto doint;
00172                 case 'h':
00173                         h = 1;
00174                         format++;
00175                         goto doint;
00176                 case 'l':
00177                         l = 1;
00178                         format++;
00179                         if (*format == 'l') {
00180                                 q = 1;
00181                                 format++;
00182                         }
00183                         goto doint;
00184                 case 'n':
00185                 case 'i':
00186                 case 'd':
00187                 case 'o':
00188                 case 'u':
00189                 case 'x':
00190                 case 'X':
00191                 doint:
00192                         if (precision != 0)
00193                                 zero = 0;
00194                         switch (*format) {
00195                         case 'n':
00196                                 if (h) {
00197                                         short int *p;
00198                                         p = va_arg(ap, short *);
00199                                         REQUIRE(p != NULL);
00200                                         *p = str - save;
00201                                 } else if (l) {
00202                                         long int *p;
00203                                         p = va_arg(ap, long *);
00204                                         REQUIRE(p != NULL);
00205                                         *p = str - save;
00206                                 } else {
00207                                         int *p;
00208                                         p = va_arg(ap, int *);
00209                                         REQUIRE(p != NULL);
00210                                         *p = str - save;
00211                                 }
00212                                 break;
00213                         case 'i':
00214                         case 'd':
00215                                 if (q)
00216                                         tmpi = va_arg(ap, isc_int64_t);
00217                                 else if (l)
00218                                         tmpi = va_arg(ap, long int);
00219                                 else
00220                                         tmpi = va_arg(ap, int);
00221                                 if (tmpi < 0) {
00222                                         head = "-";
00223                                         tmpui = -tmpi;
00224                                 } else {
00225                                         if (plus)
00226                                                 head = "+";
00227                                         else if (space)
00228                                                 head = " ";
00229                                         else
00230                                                 head = "";
00231                                         tmpui = tmpi;
00232                                 }
00233                                 sprintf(buf, "%u", tmpui);
00234                                 goto printint;
00235                         case 'o':
00236                                 if (q)
00237                                         tmpui = va_arg(ap, isc_uint64_t);
00238                                 else if (l)
00239                                         tmpui = va_arg(ap, long int);
00240                                 else
00241                                         tmpui = va_arg(ap, int);
00242                                 sprintf(buf, alt ? "%#o"
00243                                                  : "%o", tmpui);
00244                                 goto printint;
00245                         case 'u':
00246                                 if (q)
00247                                         tmpui = va_arg(ap, isc_uint64_t);
00248                                 else if (l)
00249                                         tmpui = va_arg(ap, unsigned long int);
00250                                 else
00251                                         tmpui = va_arg(ap, unsigned int);
00252                                 sprintf(buf, "%u", tmpui);
00253                                 goto printint;
00254                         case 'x':
00255                                 if (q)
00256                                         tmpui = va_arg(ap, isc_uint64_t);
00257                                 else if (l)
00258                                         tmpui = va_arg(ap, unsigned long int);
00259                                 else
00260                                         tmpui = va_arg(ap, unsigned int);
00261                                 if (alt) {
00262                                         head = "0x";
00263                                         if (precision > 2)
00264                                                 precision -= 2;
00265                                 }
00266                                 sprintf(buf, "%x", tmpui);
00267                                 goto printint;
00268                         case 'X':
00269                                 if (q)
00270                                         tmpui = va_arg(ap, isc_uint64_t);
00271                                 else if (l)
00272                                         tmpui = va_arg(ap, unsigned long int);
00273                                 else
00274                                         tmpui = va_arg(ap, unsigned int);
00275                                 if (alt) {
00276                                         head = "0X";
00277                                         if (precision > 2)
00278                                                 precision -= 2;
00279                                 }
00280                                 sprintf(buf, "%X", tmpui);
00281                                 goto printint;
00282                         printint:
00283                                 if (precision != 0 || width != 0) {
00284                                         length = strlen(buf);
00285                                         if (length < precision)
00286                                                 zeropad = precision - length;
00287                                         else if (length < width && zero)
00288                                                 zeropad = width - length;
00289                                         if (width != 0) {
00290                                                 pad = width - length -
00291                                                       zeropad - strlen(head);
00292                                                 if (pad < 0)
00293                                                         pad = 0;
00294                                         }
00295                                 }
00296                                 count += strlen(head) + strlen(buf) + pad +
00297                                          zeropad;
00298                                 if (!left) {
00299                                         while (pad > 0 && size > 1) {
00300                                                 *str++ = ' ';
00301                                                 size--;
00302                                                 pad--;
00303                                         }
00304                                 }
00305                                 cp = head;
00306                                 while (*cp != '\0' && size > 1) {
00307                                         *str++ = *cp++;
00308                                         size--;
00309                                 }
00310                                 while (zeropad > 0 && size > 1) {
00311                                         *str++ = '0';
00312                                         size--;
00313                                         zeropad--;
00314                                 }
00315                                 cp = buf;
00316                                 while (*cp != '\0' && size > 1) {
00317                                         *str++ = *cp++;
00318                                         size--;
00319                                 }
00320                                 while (pad > 0 && size > 1) {
00321                                         *str++ = ' ';
00322                                         size--;
00323                                         pad--;
00324                                 }
00325                                 break;
00326                         default:
00327                                 break;
00328                         }
00329                         break;
00330                 case 's':
00331                         cp = va_arg(ap, char *);
00332                         REQUIRE(cp != NULL);
00333 
00334                         if (precision != 0) {
00335                                 /*
00336                                  * cp need not be NULL terminated.
00337                                  */
00338                                 const char *tp;
00339                                 unsigned long n;
00340 
00341                                 n = precision;
00342                                 tp = cp;
00343                                 while (n != 0 && *tp != '\0')
00344                                         n--, tp++;
00345                                 length = precision - n;
00346                         } else {
00347                                 length = strlen(cp);
00348                         }
00349                         if (width != 0) {
00350                                 pad = width - length;
00351                                 if (pad < 0)
00352                                         pad = 0;
00353                         }
00354                         count += pad + length;
00355                         if (!left)
00356                                 while (pad > 0 && size > 1) {
00357                                         *str++ = ' ';
00358                                         size--;
00359                                         pad--;
00360                                 }
00361                         if (precision != 0)
00362                                 while (precision > 0 && *cp != '\0' &&
00363                                        size > 1) {
00364                                         *str++ = *cp++;
00365                                         size--;
00366                                         precision--;
00367                                 }
00368                         else
00369                                 while (*cp != '\0' && size > 1) {
00370                                         *str++ = *cp++;
00371                                         size--;
00372                                 }
00373                         while (pad > 0 && size > 1) {
00374                                 *str++ = ' ';
00375                                 size--;
00376                                 pad--;
00377                         }
00378                         break;
00379                 case 'c':
00380                         c = va_arg(ap, int);
00381                         if (width > 0) {
00382                                 count += width;
00383                                 width--;
00384                                 if (left) {
00385                                         *str++ = c;
00386                                         size--;
00387                                 }
00388                                 while (width-- > 0 && size > 1) {
00389                                         *str++ = ' ';
00390                                         size--;
00391                                 }
00392                                 if (!left && size > 1) {
00393                                         *str++ = c;
00394                                         size--;
00395                                 }
00396                         } else {
00397                                 count++;
00398                                 if (size > 1) {
00399                                         *str++ = c;
00400                                         size--;
00401                                 }
00402                         }
00403                         break;
00404                 case 'p':
00405                         v = va_arg(ap, void *);
00406                         sprintf(buf, "%p", v);
00407                         length = strlen(buf);
00408                         if (precision > length)
00409                                 zeropad = precision - length;
00410                         if (width > 0) {
00411                                 pad = width - length - zeropad;
00412                                 if (pad < 0)
00413                                         pad = 0;
00414                         }
00415                         count += length + pad + zeropad;
00416                         if (!left)
00417                                 while (pad > 0 && size > 1) {
00418                                         *str++ = ' ';
00419                                         size--;
00420                                         pad--;
00421                                 }
00422                         cp = buf;
00423                         if (zeropad > 0 && buf[0] == '0' &&
00424                             (buf[1] == 'x' || buf[1] == 'X')) {
00425                                 if (size > 1) {
00426                                         *str++ = *cp++;
00427                                         size--;
00428                                 }
00429                                 if (size > 1) {
00430                                         *str++ = *cp++;
00431                                         size--;
00432                                 }
00433                                 while (zeropad > 0 && size > 1) {
00434                                         *str++ = '0';
00435                                         size--;
00436                                         zeropad--;
00437                                 }
00438                         }
00439                         while (*cp != '\0' && size > 1) {
00440                                 *str++ = *cp++;
00441                                 size--;
00442                         }
00443                         while (pad > 0 && size > 1) {
00444                                 *str++ = ' ';
00445                                 size--;
00446                                 pad--;
00447                         }
00448                         break;
00449                 case 'D':       /*deprecated*/
00450                         INSIST("use %ld instead of %D" == NULL);
00451                 case 'O':       /*deprecated*/
00452                         INSIST("use %lo instead of %O" == NULL);
00453                 case 'U':       /*deprecated*/
00454                         INSIST("use %lu instead of %U" == NULL);
00455 
00456                 case 'L':
00457 #ifdef HAVE_LONG_DOUBLE
00458                         l = 1;
00459 #else
00460                         INSIST("long doubles are not supported" == NULL);
00461 #endif
00462                         /*FALLTHROUGH*/
00463                 case 'e':
00464                 case 'E':
00465                 case 'f':
00466                 case 'g':
00467                 case 'G':
00468                         if (!dot)
00469                                 precision = 6;
00470                         /*
00471                          * IEEE floating point.
00472                          * MIN 2.2250738585072014E-308
00473                          * MAX 1.7976931348623157E+308
00474                          * VAX floating point has a smaller range than IEEE.
00475                          *
00476                          * precisions > 324 don't make much sense.
00477                          * if we cap the precision at 512 we will not
00478                          * overflow buf.
00479                          */
00480                         if (precision > 512)
00481                                 precision = 512;
00482                         sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
00483                                 plus ? "+" : space ? " " : "",
00484                                 precision, l ? "L" : "", *format);
00485                         switch (*format) {
00486                         case 'e':
00487                         case 'E':
00488                         case 'f':
00489                         case 'g':
00490                         case 'G':
00491 #ifdef HAVE_LONG_DOUBLE
00492                                 if (l) {
00493                                         ldbl = va_arg(ap, long double);
00494                                         sprintf(buf, fmt, ldbl);
00495                                 } else
00496 #endif
00497                                 {
00498                                         dbl = va_arg(ap, double);
00499                                         sprintf(buf, fmt, dbl);
00500                                 }
00501                                 length = strlen(buf);
00502                                 if (width > 0) {
00503                                         pad = width - length;
00504                                         if (pad < 0)
00505                                                 pad = 0;
00506                                 }
00507                                 count += length + pad;
00508                                 if (!left)
00509                                         while (pad > 0 && size > 1) {
00510                                                 *str++ = ' ';
00511                                                 size--;
00512                                                 pad--;
00513                                         }
00514                                 cp = buf;
00515                                 while (*cp != ' ' && size > 1) {
00516                                         *str++ = *cp++;
00517                                         size--;
00518                                 }
00519                                 while (pad > 0 && size > 1) {
00520                                         *str++ = ' ';
00521                                         size--;
00522                                         pad--;
00523                                 }
00524                                 break;
00525                         default:
00526                                 continue;
00527                         }
00528                         break;
00529                 default:
00530                         continue;
00531                 }
00532                 format++;
00533         }
00534         if (size > 0)
00535                 *str = '\0';
00536         return (count);
00537 }
00538 
00539 #endif

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1