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