00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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
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':
00450 INSIST("use %ld instead of %D" == NULL);
00451 case 'O':
00452 INSIST("use %lo instead of %O" == NULL);
00453 case 'U':
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
00463 case 'e':
00464 case 'E':
00465 case 'f':
00466 case 'g':
00467 case 'G':
00468 if (!dot)
00469 precision = 6;
00470
00471
00472
00473
00474
00475
00476
00477
00478
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