]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Uefi/compat.c
StdLib: Fix dirent structure members to be of the correct type.
[mirror_edk2.git] / StdLib / LibC / Uefi / compat.c
CommitLineData
d7ce7006 1/*\r
2 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>\r
3 * All rights reserved.\r
4 *\r
5 * Redistribution and use in source and binary forms, with or without\r
6 * modification, are permitted provided that the following conditions\r
7 * are met:\r
8 * 1. Redistributions of source code must retain the above copyright\r
9 * notice, this list of conditions and the following disclaimer.\r
10 * 2. Redistributions in binary form must reproduce the above copyright\r
11 * notice, this list of conditions and the following disclaimer in the\r
12 * documentation and/or other materials provided with the distribution.\r
13 * 3. The name of the author may not be used to endorse or promote products\r
14 * derived from this software without specific prior written permission.\r
15 *\r
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,\r
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
26 *\r
27 * $Id: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $\r
28\r
29 * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.\r
30 * All rights reserved.\r
31 *\r
32 * This code is derived from software contributed to The NetBSD Foundation\r
33 * by Klaus Klein and Jason R. Thorpe.\r
34 *\r
35 * Redistribution and use in source and binary forms, with or without\r
36 * modification, are permitted provided that the following conditions\r
37 * are met:\r
38 * 1. Redistributions of source code must retain the above copyright\r
39 * notice, this list of conditions and the following disclaimer.\r
40 * 2. Redistributions in binary form must reproduce the above copyright\r
41 * notice, this list of conditions and the following disclaimer in the\r
42 * documentation and/or other materials provided with the distribution.\r
43 * 3. All advertising materials mentioning features or use of this software\r
44 * must display the following acknowledgement:\r
45 * This product includes software developed by the NetBSD\r
46 * Foundation, Inc. and its contributors.\r
47 * 4. Neither the name of The NetBSD Foundation nor the names of its\r
48 * contributors may be used to endorse or promote products derived\r
49 * from this software without specific prior written permission.\r
50 *\r
51 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS\r
52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\r
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS\r
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
61 * POSSIBILITY OF SUCH DAMAGE.\r
62 *\r
63 * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $\r
64\r
65 * Copyright (c) 1987, 1993\r
66 * The Regents of the University of California. All rights reserved.\r
67 *\r
68 * Redistribution and use in source and binary forms, with or without\r
69 * modification, are permitted provided that the following conditions\r
70 * are met:\r
71 * 1. Redistributions of source code must retain the above copyright\r
72 * notice, this list of conditions and the following disclaimer.\r
73 * 2. Redistributions in binary form must reproduce the above copyright\r
74 * notice, this list of conditions and the following disclaimer in the\r
75 * documentation and/or other materials provided with the distribution.\r
76 * 3. Neither the name of the University nor the names of its contributors\r
77 * may be used to endorse or promote products derived from this software\r
78 * without specific prior written permission.\r
79 *\r
80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
90 * SUCH DAMAGE.\r
91 *\r
92 * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $\r
93 */\r
94#include <LibConfig.h>\r
95#include <string.h>\r
96#include <fcntl.h>\r
41b152c5 97#include <sys/syslimits.h>\r
d7ce7006 98\r
99#ifndef HAVE_GETOPT\r
100char *optarg;\r
101int optind = 1;\r
102int\r
103getopt(int argc, char **argv, char *args)\r
104{\r
105 size_t n;\r
106 size_t nlen = strlen(args);\r
107 char cmd;\r
108 char rv;\r
109\r
110 if (argv[optind] && *argv[optind] == '-') {\r
111 cmd = *(argv[optind] + 1);\r
112\r
113 for (n = 0; n < nlen; n++) {\r
114 if (args[n] == ':')\r
115 continue;\r
116 if (args[n] == cmd) {\r
117 rv = *(argv[optind] + 1);\r
118 if (args[n+1] == ':') {\r
119 if (*(argv[optind] + 2) != '\0') {\r
120 optarg = argv[optind] + 2;\r
121 optind += 1;\r
122 } else {\r
123 optarg = argv[optind + 1];\r
124 optind += 2;\r
125 }\r
126 if (!optarg)\r
127 optarg="";\r
128 return rv;\r
129 } else {\r
130 optarg = NULL;\r
131 optind += 1;\r
132 return rv;\r
133 }\r
134 }\r
135 }\r
136 }\r
137\r
138 return -1;\r
139}\r
140#endif\r
141\r
d7ce7006 142#define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))\r
d7ce7006 143\r
144#ifndef HAVE_BASENAME\r
145#ifndef PATH_MAX\r
146#define PATH_MAX 5000\r
147#endif\r
148\r
149char *\r
150basename(char *path)\r
151{\r
152 static char singledot[] = ".";\r
153 static char result[PATH_MAX];\r
154 char *p, *lastp;\r
155 size_t len;\r
156\r
157 /*\r
158 * If `path' is a null pointer or points to an empty string,\r
159 * return a pointer to the string ".".\r
160 */\r
161 if ((path == NULL) || (*path == '\0'))\r
162 return (singledot);\r
163\r
164 /* Strip trailing slashes, if any. */\r
165 lastp = path + strlen(path) - 1;\r
166 while (lastp != path && ISPATHSEPARATOR(*lastp))\r
167 lastp--;\r
168\r
169 /* Now find the beginning of this (final) component. */\r
170 p = lastp;\r
171 while (p != path && !ISPATHSEPARATOR(*(p - 1)))\r
172 p--;\r
173\r
174 /* ...and copy the result into the result buffer. */\r
175 len = (lastp - p) + 1 /* last char */;\r
176 if (len > (PATH_MAX - 1))\r
177 len = PATH_MAX - 1;\r
178\r
179 memcpy(result, p, len);\r
180 result[len] = '\0';\r
181\r
182 return (result);\r
183}\r
184#endif\r
185\r
186#if !defined(HAVE_MKSTEMP) && !defined(WIN32)\r
187int\r
188mkstemp(char *path)\r
189{\r
190 char *start, *trv;\r
191 unsigned int pid;\r
192\r
193 /* To guarantee multiple calls generate unique names even if\r
194 the file is not created. 676 different possibilities with 7\r
195 or more X's, 26 with 6 or less. */\r
196 static char xtra[2] = "aa";\r
197 int xcnt = 0;\r
198\r
199 pid = getpid();\r
200\r
201 /* Move to end of path and count trailing X's. */\r
202 for (trv = path; *trv; ++trv)\r
203 if (*trv == 'X')\r
204 xcnt++;\r
205 else\r
206 xcnt = 0;\r
207\r
208 /* Use at least one from xtra. Use 2 if more than 6 X's. */\r
209 if (*(trv - 1) == 'X')\r
210 *--trv = xtra[0];\r
211 if (xcnt > 6 && *(trv - 1) == 'X')\r
212 *--trv = xtra[1];\r
213\r
214 /* Set remaining X's to pid digits with 0's to the left. */\r
215 while (*--trv == 'X') {\r
216 *trv = (pid % 10) + '0';\r
217 pid /= 10;\r
218 }\r
219\r
220 /* update xtra for next call. */\r
221 if (xtra[0] != 'z')\r
222 xtra[0]++;\r
223 else {\r
224 xtra[0] = 'a';\r
225 if (xtra[1] != 'z')\r
226 xtra[1]++;\r
227 else\r
228 xtra[1] = 'a';\r
229 }\r
230\r
231 return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);\r
232}\r
233#endif\r
234\r
235#ifndef HAVE_FFS\r
236int\r
237ffs(int x)\r
238{\r
239 int r = 1;\r
240 if (!x) return 0;\r
241 if (!(x & 0xffff)) { x >>= 16; r += 16; }\r
242 if (!(x & 0xff)) { x >>= 8; r += 8; }\r
243 if (!(x & 0xf)) { x >>= 4; r += 4; }\r
244 if (!(x & 3)) { x >>= 2; r += 2; }\r
245 if (!(x & 1)) { x >>= 1; r += 1; }\r
246\r
247 return r;\r
248}\r
249#endif\r
250\r
251/*\r
252 * Copyright Patrick Powell 1995\r
253 * This code is based on code written by Patrick Powell (papowell@astart.com)\r
254 * It may be used for any purpose as long as this notice remains intact\r
255 * on all source code distributions\r
256 */\r
257\r
258#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)\r
259\r
260static void\r
261dopr(char *buffer, size_t maxlen, const char *format, va_list args);\r
262\r
263static void\r
264fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,\r
265 int min, int max);\r
266\r
267static void\r
268fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,\r
269 int min, int max, int flags);\r
270\r
271static void\r
272fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,\r
273 int min, int max, int flags);\r
274\r
275static void\r
276dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);\r
277\r
278/*\r
279 * dopr(): poor man's version of doprintf\r
280 */\r
281\r
282/* format read states */\r
283#define DP_S_DEFAULT 0\r
284#define DP_S_FLAGS 1\r
285#define DP_S_MIN 2\r
286#define DP_S_DOT 3\r
287#define DP_S_MAX 4\r
288#define DP_S_MOD 5\r
289#define DP_S_CONV 6\r
290#define DP_S_DONE 7\r
291\r
292/* format flags - Bits */\r
293#define DP_F_MINUS (1 << 0)\r
294#define DP_F_PLUS (1 << 1)\r
295#define DP_F_SPACE (1 << 2)\r
296#define DP_F_NUM (1 << 3)\r
297#define DP_F_ZERO (1 << 4)\r
298#define DP_F_UP (1 << 5)\r
299#define DP_F_UNSIGNED (1 << 6)\r
300\r
301/* Conversion Flags */\r
302#define DP_C_SHORT 1\r
303#define DP_C_LONG 2\r
304#define DP_C_LDOUBLE 3\r
305#define DP_C_LONG_LONG 4\r
306\r
307#define char_to_int(p) (p - '0')\r
308#define abs_val(p) (p < 0 ? -p : p)\r
309\r
310\r
311static void\r
312dopr(char *buffer, size_t maxlen, const char *format, va_list args)\r
313{\r
314 char *strvalue, ch;\r
315 long value;\r
316 long double fvalue;\r
317 int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;\r
318 size_t currlen = 0;\r
319\r
320 ch = *format++;\r
321\r
322 while (state != DP_S_DONE) {\r
323 if ((ch == '\0') || (currlen >= maxlen))\r
324 state = DP_S_DONE;\r
325\r
326 switch(state) {\r
327 case DP_S_DEFAULT:\r
328 if (ch == '%')\r
329 state = DP_S_FLAGS;\r
330 else\r
331 dopr_outch(buffer, &currlen, maxlen, ch);\r
332 ch = *format++;\r
333 break;\r
334 case DP_S_FLAGS:\r
335 switch (ch) {\r
336 case '-':\r
337 flags |= DP_F_MINUS;\r
338 ch = *format++;\r
339 break;\r
340 case '+':\r
341 flags |= DP_F_PLUS;\r
342 ch = *format++;\r
343 break;\r
344 case ' ':\r
345 flags |= DP_F_SPACE;\r
346 ch = *format++;\r
347 break;\r
348 case '#':\r
349 flags |= DP_F_NUM;\r
350 ch = *format++;\r
351 break;\r
352 case '0':\r
353 flags |= DP_F_ZERO;\r
354 ch = *format++;\r
355 break;\r
356 default:\r
357 state = DP_S_MIN;\r
358 break;\r
359 }\r
360 break;\r
361 case DP_S_MIN:\r
362 if (isdigit((unsigned char)ch)) {\r
363 min = 10 * min + char_to_int (ch);\r
364 ch = *format++;\r
365 } else if (ch == '*') {\r
366 min = va_arg (args, int);\r
367 ch = *format++;\r
368 state = DP_S_DOT;\r
369 } else\r
370 state = DP_S_DOT;\r
371 break;\r
372 case DP_S_DOT:\r
373 if (ch == '.') {\r
374 state = DP_S_MAX;\r
375 ch = *format++;\r
376 } else\r
377 state = DP_S_MOD;\r
378 break;\r
379 case DP_S_MAX:\r
380 if (isdigit((unsigned char)ch)) {\r
381 if (max < 0)\r
382 max = 0;\r
383 max = 10 * max + char_to_int(ch);\r
384 ch = *format++;\r
385 } else if (ch == '*') {\r
386 max = va_arg (args, int);\r
387 ch = *format++;\r
388 state = DP_S_MOD;\r
389 } else\r
390 state = DP_S_MOD;\r
391 break;\r
392 case DP_S_MOD:\r
393 switch (ch) {\r
394 case 'h':\r
395 cflags = DP_C_SHORT;\r
396 ch = *format++;\r
397 break;\r
398 case 'l':\r
399 cflags = DP_C_LONG;\r
400 ch = *format++;\r
401 if (ch == 'l') {\r
402 cflags = DP_C_LONG_LONG;\r
403 ch = *format++;\r
404 }\r
405 break;\r
406 case 'q':\r
407 cflags = DP_C_LONG_LONG;\r
408 ch = *format++;\r
409 break;\r
410 case 'L':\r
411 cflags = DP_C_LDOUBLE;\r
412 ch = *format++;\r
413 break;\r
414 default:\r
415 break;\r
416 }\r
417 state = DP_S_CONV;\r
418 break;\r
419 case DP_S_CONV:\r
420 switch (ch) {\r
421 case 'd':\r
422 case 'i':\r
423 if (cflags == DP_C_SHORT)\r
424 value = va_arg(args, int);\r
425 else if (cflags == DP_C_LONG)\r
426 value = va_arg(args, long int);\r
427 else if (cflags == DP_C_LONG_LONG)\r
428 value = va_arg (args, long long);\r
429 else\r
430 value = va_arg (args, int);\r
431 fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);\r
432 break;\r
433 case 'o':\r
434 flags |= DP_F_UNSIGNED;\r
435 if (cflags == DP_C_SHORT)\r
436 value = va_arg(args, unsigned int);\r
437 else if (cflags == DP_C_LONG)\r
438 value = va_arg(args, unsigned long int);\r
439 else if (cflags == DP_C_LONG_LONG)\r
440 value = va_arg(args, unsigned long long);\r
441 else\r
442 value = va_arg(args, unsigned int);\r
443 fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);\r
444 break;\r
445 case 'u':\r
446 flags |= DP_F_UNSIGNED;\r
447 if (cflags == DP_C_SHORT)\r
448 value = va_arg(args, unsigned int);\r
449 else if (cflags == DP_C_LONG)\r
450 value = va_arg(args, unsigned long int);\r
451 else if (cflags == DP_C_LONG_LONG)\r
452 value = va_arg(args, unsigned long long);\r
453 else\r
454 value = va_arg(args, unsigned int);\r
455 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);\r
456 break;\r
457 case 'X':\r
458 flags |= DP_F_UP;\r
459 case 'x':\r
460 flags |= DP_F_UNSIGNED;\r
461 if (cflags == DP_C_SHORT)\r
462 value = va_arg(args, unsigned int);\r
463 else if (cflags == DP_C_LONG)\r
464 value = va_arg(args, unsigned long int);\r
465 else if (cflags == DP_C_LONG_LONG)\r
466 value = va_arg(args, unsigned long long);\r
467 else\r
468 value = va_arg(args, unsigned int);\r
469 fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);\r
470 break;\r
471 case 'f':\r
472 if (cflags == DP_C_LDOUBLE)\r
473 fvalue = va_arg(args, long double);\r
474 else\r
475 fvalue = va_arg(args, double);\r
476 /* um, floating point? */\r
477 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);\r
478 break;\r
479 case 'E':\r
480 flags |= DP_F_UP;\r
481 case 'e':\r
482 if (cflags == DP_C_LDOUBLE)\r
483 fvalue = va_arg(args, long double);\r
484 else\r
485 fvalue = va_arg(args, double);\r
486 break;\r
487 case 'G':\r
488 flags |= DP_F_UP;\r
489 case 'g':\r
490 if (cflags == DP_C_LDOUBLE)\r
491 fvalue = va_arg(args, long double);\r
492 else\r
493 fvalue = va_arg(args, double);\r
494 break;\r
495 case 'c':\r
496 dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));\r
497 break;\r
498 case 's':\r
499 strvalue = va_arg(args, char *);\r
500 if (max < 0)\r
501 max = maxlen; /* ie, no max */\r
502 fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);\r
503 break;\r
504 case 'p':\r
505 strvalue = va_arg(args, void *);\r
506 fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);\r
507 break;\r
508 case 'n':\r
509 if (cflags == DP_C_SHORT) {\r
510 short int *num;\r
511 num = va_arg(args, short int *);\r
512 *num = currlen;\r
513 } else if (cflags == DP_C_LONG) {\r
514 long int *num;\r
515 num = va_arg(args, long int *);\r
516 *num = currlen;\r
517 } else if (cflags == DP_C_LONG_LONG) {\r
518 long long *num;\r
519 num = va_arg(args, long long *);\r
520 *num = currlen;\r
521 } else {\r
522 int *num;\r
523 num = va_arg(args, int *);\r
524 *num = currlen;\r
525 }\r
526 break;\r
527 case '%':\r
528 dopr_outch(buffer, &currlen, maxlen, ch);\r
529 break;\r
530 case 'w': /* not supported yet, treat as next char */\r
531 ch = *format++;\r
532 break;\r
533 default: /* Unknown, skip */\r
534 break;\r
535 }\r
536 ch = *format++;\r
537 state = DP_S_DEFAULT;\r
538 flags = cflags = min = 0;\r
539 max = -1;\r
540 break;\r
541 case DP_S_DONE:\r
542 break;\r
543 default: /* hmm? */\r
544 break; /* some picky compilers need this */\r
545 }\r
546 }\r
547 if (currlen < maxlen - 1)\r
548 buffer[currlen] = '\0';\r
549 else\r
550 buffer[maxlen - 1] = '\0';\r
551}\r
552\r
553static void\r
554fmtstr(char *buffer, size_t *currlen, size_t maxlen,\r
555 char *value, int flags, int min, int max)\r
556{\r
557 int cnt = 0, padlen, strln; /* amount to pad */\r
558\r
559 if (value == 0)\r
560 value = "<NULL>";\r
561\r
562 for (strln = 0; value[strln]; ++strln); /* strlen */\r
563 padlen = min - strln;\r
564 if (padlen < 0)\r
565 padlen = 0;\r
566 if (flags & DP_F_MINUS)\r
567 padlen = -padlen; /* Left Justify */\r
568\r
569 while ((padlen > 0) && (cnt < max)) {\r
570 dopr_outch(buffer, currlen, maxlen, ' ');\r
571 --padlen;\r
572 ++cnt;\r
573 }\r
574 while (*value && (cnt < max)) {\r
575 dopr_outch(buffer, currlen, maxlen, *value++);\r
576 ++cnt;\r
577 }\r
578 while ((padlen < 0) && (cnt < max)) {\r
579 dopr_outch(buffer, currlen, maxlen, ' ');\r
580 ++padlen;\r
581 ++cnt;\r
582 }\r
583}\r
584\r
585/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */\r
586\r
587static void\r
588fmtint(char *buffer, size_t *currlen, size_t maxlen,\r
589 long value, int base, int min, int max, int flags)\r
590{\r
591 unsigned long uvalue;\r
592 char convert[20];\r
593 int signvalue = 0, place = 0, caps = 0;\r
594 int spadlen = 0; /* amount to space pad */\r
595 int zpadlen = 0; /* amount to zero pad */\r
596\r
597#define PADMAX(x,y) ((x) > (y) ? (x) : (y))\r
598\r
599 if (max < 0)\r
600 max = 0;\r
601\r
602 uvalue = value;\r
603\r
604 if (!(flags & DP_F_UNSIGNED)) {\r
605 if (value < 0) {\r
606 signvalue = '-';\r
607 uvalue = -value;\r
608 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */\r
609 signvalue = '+';\r
610 else if (flags & DP_F_SPACE)\r
611 signvalue = ' ';\r
612 }\r
613\r
614 if (flags & DP_F_UP)\r
615 caps = 1; /* Should characters be upper case? */\r
616 do {\r
617 convert[place++] =\r
618 (caps ? "0123456789ABCDEF" : "0123456789abcdef")\r
619 [uvalue % (unsigned)base];\r
620 uvalue = (uvalue / (unsigned)base );\r
621 } while (uvalue && (place < 20));\r
622 if (place == 20)\r
623 place--;\r
624 convert[place] = 0;\r
625\r
626 zpadlen = max - place;\r
627 spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);\r
628 if (zpadlen < 0)\r
629 zpadlen = 0;\r
630 if (spadlen < 0)\r
631 spadlen = 0;\r
632 if (flags & DP_F_ZERO) {\r
633 zpadlen = PADMAX(zpadlen, spadlen);\r
634 spadlen = 0;\r
635 }\r
636 if (flags & DP_F_MINUS)\r
637 spadlen = -spadlen; /* Left Justifty */\r
638\r
639 /* Spaces */\r
640 while (spadlen > 0) {\r
641 dopr_outch(buffer, currlen, maxlen, ' ');\r
642 --spadlen;\r
643 }\r
644\r
645 /* Sign */\r
646 if (signvalue)\r
647 dopr_outch(buffer, currlen, maxlen, signvalue);\r
648\r
649 /* Zeros */\r
650 if (zpadlen > 0) {\r
651 while (zpadlen > 0) {\r
652 dopr_outch(buffer, currlen, maxlen, '0');\r
653 --zpadlen;\r
654 }\r
655 }\r
656\r
657 /* Digits */\r
658 while (place > 0)\r
659 dopr_outch(buffer, currlen, maxlen, convert[--place]);\r
660\r
661 /* Left Justified spaces */\r
662 while (spadlen < 0) {\r
663 dopr_outch (buffer, currlen, maxlen, ' ');\r
664 ++spadlen;\r
665 }\r
666}\r
667\r
668static long double\r
669pow10(int exp)\r
670{\r
671 long double result = 1;\r
672\r
673 while (exp) {\r
674 result *= 10;\r
675 exp--;\r
676 }\r
677\r
678 return result;\r
679}\r
680\r
681static long\r
682round(long double value)\r
683{\r
684 long intpart = value;\r
685\r
686 value -= intpart;\r
687 if (value >= 0.5)\r
688 intpart++;\r
689\r
690 return intpart;\r
691}\r
692\r
693static void\r
694fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,\r
695 int min, int max, int flags)\r
696{\r
697 char iconvert[20], fconvert[20];\r
698 int signvalue = 0, iplace = 0, fplace = 0;\r
699 int padlen = 0; /* amount to pad */\r
700 int zpadlen = 0, caps = 0;\r
701 long intpart, fracpart;\r
702 long double ufvalue;\r
703\r
704 /*\r
705 * AIX manpage says the default is 0, but Solaris says the default\r
706 * is 6, and sprintf on AIX defaults to 6\r
707 */\r
708 if (max < 0)\r
709 max = 6;\r
710\r
711 ufvalue = abs_val(fvalue);\r
712\r
713 if (fvalue < 0)\r
714 signvalue = '-';\r
715 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */\r
716 signvalue = '+';\r
717 else if (flags & DP_F_SPACE)\r
718 signvalue = ' ';\r
719\r
720 intpart = ufvalue;\r
721\r
722 /*\r
723 * Sorry, we only support 9 digits past the decimal because of our\r
724 * conversion method\r
725 */\r
726 if (max > 9)\r
727 max = 9;\r
728\r
729 /* We "cheat" by converting the fractional part to integer by\r
730 * multiplying by a factor of 10\r
731 */\r
732 fracpart = round((pow10 (max)) * (ufvalue - intpart));\r
733\r
734 if (fracpart >= pow10 (max)) {\r
735 intpart++;\r
736 fracpart -= pow10 (max);\r
737 }\r
738\r
739 /* Convert integer part */\r
740 do {\r
741 iconvert[iplace++] =\r
742 (caps ? "0123456789ABCDEF" : "0123456789abcdef")\r
743 [intpart % 10];\r
744 intpart = (intpart / 10);\r
745 } while(intpart && (iplace < 20));\r
746 if (iplace == 20)\r
747 iplace--;\r
748 iconvert[iplace] = 0;\r
749\r
750 /* Convert fractional part */\r
751 do {\r
752 fconvert[fplace++] =\r
753 (caps ? "0123456789ABCDEF" : "0123456789abcdef")\r
754 [fracpart % 10];\r
755 fracpart = (fracpart / 10);\r
756 } while(fracpart && (fplace < 20));\r
757 if (fplace == 20)\r
758 fplace--;\r
759 fconvert[fplace] = 0;\r
760\r
761 /* -1 for decimal point, another -1 if we are printing a sign */\r
762 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);\r
763 zpadlen = max - fplace;\r
764 if (zpadlen < 0)\r
765 zpadlen = 0;\r
766 if (padlen < 0)\r
767 padlen = 0;\r
768 if (flags & DP_F_MINUS)\r
769 padlen = -padlen; /* Left Justifty */\r
770\r
771 if ((flags & DP_F_ZERO) && (padlen > 0)) {\r
772 if (signvalue) {\r
773 dopr_outch(buffer, currlen, maxlen, signvalue);\r
774 --padlen;\r
775 signvalue = 0;\r
776 }\r
777 while (padlen > 0) {\r
778 dopr_outch(buffer, currlen, maxlen, '0');\r
779 --padlen;\r
780 }\r
781 }\r
782 while (padlen > 0) {\r
783 dopr_outch(buffer, currlen, maxlen, ' ');\r
784 --padlen;\r
785 }\r
786 if (signvalue)\r
787 dopr_outch(buffer, currlen, maxlen, signvalue);\r
788\r
789 while (iplace > 0)\r
790 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);\r
791\r
792 /*\r
793 * Decimal point. This should probably use locale to find the\r
794 * correct char to print out.\r
795 */\r
796 dopr_outch(buffer, currlen, maxlen, '.');\r
797\r
798 while (fplace > 0)\r
799 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);\r
800\r
801 while (zpadlen > 0) {\r
802 dopr_outch(buffer, currlen, maxlen, '0');\r
803 --zpadlen;\r
804 }\r
805\r
806 while (padlen < 0) {\r
807 dopr_outch(buffer, currlen, maxlen, ' ');\r
808 ++padlen;\r
809 }\r
810}\r
811\r
812static void\r
813dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)\r
814{\r
815 if (*currlen < maxlen)\r
816 buffer[(*currlen)++] = c;\r
817}\r
818#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */\r
819\r
820#ifndef HAVE_VSNPRINTF\r
821int\r
822vsnprintf(char *str, size_t count, const char *fmt, va_list args)\r
823{\r
824 str[0] = 0;\r
825 dopr(str, count, fmt, args);\r
826\r
827 return(strlen(str));\r
828}\r
829#endif /* !HAVE_VSNPRINTF */\r
830\r
831#ifndef HAVE_SNPRINTF\r
832int\r
833snprintf(char *str,size_t count,const char *fmt,...)\r
834{\r
835 va_list ap;\r
836\r
837 va_start(ap, fmt);\r
838 (void) vsnprintf(str, count, fmt, ap);\r
839 va_end(ap);\r
840\r
841 return(strlen(str));\r
842}\r
843\r
844#endif /* !HAVE_SNPRINTF */\r