vfprintf.c (180102) | vfprintf.c (180104) |
---|---|
1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#if defined(LIBC_SCCS) && !defined(lint) 34static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 35#endif /* LIBC_SCCS and not lint */ 36#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#if defined(LIBC_SCCS) && !defined(lint) 34static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 35#endif /* LIBC_SCCS and not lint */ 36#include <sys/cdefs.h> |
37__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 180102 2008-06-29 21:01:27Z das $"); | 37__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 180104 2008-06-29 21:52:40Z das $"); |
38 39/* 40 * Actual printf innards. 41 * 42 * This code is large and complicated... 43 */ 44 45#include "namespace.h" --- 11 unchanged lines hidden (view full) --- 57#include <printf.h> 58 59#include <stdarg.h> 60#include "un-namespace.h" 61 62#include "libc_private.h" 63#include "local.h" 64#include "fvwrite.h" | 38 39/* 40 * Actual printf innards. 41 * 42 * This code is large and complicated... 43 */ 44 45#include "namespace.h" --- 11 unchanged lines hidden (view full) --- 57#include <printf.h> 58 59#include <stdarg.h> 60#include "un-namespace.h" 61 62#include "libc_private.h" 63#include "local.h" 64#include "fvwrite.h" |
65#include "printflocal.h" |
|
65 | 66 |
66union arg { 67 int intarg; 68 u_int uintarg; 69 long longarg; 70 u_long ulongarg; 71 long long longlongarg; 72 unsigned long long ulonglongarg; 73 ptrdiff_t ptrdiffarg; 74 size_t sizearg; 75 intmax_t intmaxarg; 76 uintmax_t uintmaxarg; 77 void *pvoidarg; 78 char *pchararg; 79 signed char *pschararg; 80 short *pshortarg; 81 int *pintarg; 82 long *plongarg; 83 long long *plonglongarg; 84 ptrdiff_t *pptrdiffarg; 85 size_t *psizearg; 86 intmax_t *pintmaxarg; 87#ifndef NO_FLOATING_POINT 88 double doublearg; 89 long double longdoublearg; 90#endif 91 wint_t wintarg; 92 wchar_t *pwchararg; 93}; 94 95/* 96 * Type ids for argument type table. 97 */ 98enum typeid { 99 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT, 100 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG, 101 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET, 102 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR, 103 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR 104}; 105 106#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ 107 108/* An expandable array of types. */ 109struct typetable { 110 enum typeid *table; /* table of types */ 111 enum typeid stattable[STATIC_ARG_TBL_SIZE]; 112 int tablesize; /* current size of type table */ 113 int tablemax; /* largest used index in table */ 114 int nextarg; /* 1-based argument index */ 115}; 116 | |
117static int __sprint(FILE *, struct __suio *); 118static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); 119static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char, 120 const char *); 121static char *__ultoa(u_long, char *, int, int, const char *, int, char, 122 const char *); 123static char *__wcsconv(wchar_t *, int); | 67static int __sprint(FILE *, struct __suio *); 68static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); 69static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char, 70 const char *); 71static char *__ultoa(u_long, char *, int, int, const char *, int, char, 72 const char *); 73static char *__wcsconv(wchar_t *, int); |
124static void __find_arguments(const char *, va_list, union arg **); 125static void __grow_type_table(struct typetable *); | |
126 127/* 128 * Flush out all the vectors defined by the given uio, 129 * then reset it so that it can be reused. 130 */ 131static int 132__sprint(FILE *fp, struct __suio *uio) 133{ --- 39 unchanged lines hidden (view full) --- 173 if (ret >= 0 && __fflush(&fake)) 174 ret = EOF; 175 if (fake._flags & __SERR) 176 fp->_flags |= __SERR; 177 return (ret); 178} 179 180/* | 74 75/* 76 * Flush out all the vectors defined by the given uio, 77 * then reset it so that it can be reused. 78 */ 79static int 80__sprint(FILE *fp, struct __suio *uio) 81{ --- 39 unchanged lines hidden (view full) --- 121 if (ret >= 0 && __fflush(&fake)) 122 ret = EOF; 123 if (fake._flags & __SERR) 124 fp->_flags |= __SERR; 125 return (ret); 126} 127 128/* |
181 * Macros for converting digits to letters and vice versa 182 */ 183#define to_digit(c) ((c) - '0') 184#define is_digit(c) ((unsigned)to_digit(c) <= 9) 185#define to_char(n) ((n) + '0') 186 187/* | |
188 * Convert an unsigned long to ASCII for printf purposes, returning 189 * a pointer to the first character of the string representation. 190 * Octal numbers can be forced to have a leading zero; hex numbers 191 * use the given digits. 192 */ 193static char * 194__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs, 195 int needgrp, char thousep, const char *grp) --- 237 unchanged lines hidden (view full) --- 433 * conversions, among other things. Technically, we would need the 434 * most space for base 10 conversions with thousands' grouping 435 * characters between each pair of digits. 100 bytes is a 436 * conservative overestimate even for a 128-bit uintmax_t. 437 */ 438#define BUF 100 439 440/* | 129 * Convert an unsigned long to ASCII for printf purposes, returning 130 * a pointer to the first character of the string representation. 131 * Octal numbers can be forced to have a leading zero; hex numbers 132 * use the given digits. 133 */ 134static char * 135__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs, 136 int needgrp, char thousep, const char *grp) --- 237 unchanged lines hidden (view full) --- 374 * conversions, among other things. Technically, we would need the 375 * most space for base 10 conversions with thousands' grouping 376 * characters between each pair of digits. 100 bytes is a 377 * conservative overestimate even for a 128-bit uintmax_t. 378 */ 379#define BUF 100 380 381/* |
441 * Flags used during conversion. 442 */ 443#define ALT 0x001 /* alternate form */ 444#define LADJUST 0x004 /* left adjustment */ 445#define LONGDBL 0x008 /* long double */ 446#define LONGINT 0x010 /* long integer */ 447#define LLONGINT 0x020 /* long long integer */ 448#define SHORTINT 0x040 /* short integer */ 449#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ 450#define FPT 0x100 /* Floating point number */ 451#define GROUPING 0x200 /* use grouping ("'" flag) */ 452 /* C99 additional size modifiers: */ 453#define SIZET 0x400 /* size_t */ 454#define PTRDIFFT 0x800 /* ptrdiff_t */ 455#define INTMAXT 0x1000 /* intmax_t */ 456#define CHARINT 0x2000 /* print char using int format */ 457 458/* | |
459 * Non-MT-safe version 460 */ 461int 462__vfprintf(FILE *fp, const char *fmt0, va_list ap) 463{ 464 char *fmt; /* format string */ 465 int ch; /* character from fmt */ 466 int n, n2; /* handy integer (short term usage) */ --- 792 unchanged lines hidden (view full) --- 1259 if (__sferror(fp)) 1260 ret = EOF; 1261 if ((argtable != NULL) && (argtable != statargtable)) 1262 free (argtable); 1263 return (ret); 1264 /* NOTREACHED */ 1265} 1266 | 382 * Non-MT-safe version 383 */ 384int 385__vfprintf(FILE *fp, const char *fmt0, va_list ap) 386{ 387 char *fmt; /* format string */ 388 int ch; /* character from fmt */ 389 int n, n2; /* handy integer (short term usage) */ --- 792 unchanged lines hidden (view full) --- 1182 if (__sferror(fp)) 1183 ret = EOF; 1184 if ((argtable != NULL) && (argtable != statargtable)) 1185 free (argtable); 1186 return (ret); 1187 /* NOTREACHED */ 1188} 1189 |
1267/* 1268 * Initialize a struct typetable. 1269 */ 1270static inline void 1271inittypes(struct typetable *types) 1272{ 1273 int n; | |
1274 | 1190 |
1275 types->table = types->stattable; 1276 types->tablesize = STATIC_ARG_TBL_SIZE; 1277 types->tablemax = 0; 1278 types->nextarg = 1; 1279 for (n = 0; n < STATIC_ARG_TBL_SIZE; n++) 1280 types->table[n] = T_UNUSED; 1281} 1282 1283/* 1284 * struct typetable destructor. 1285 */ 1286static inline void 1287freetypes(struct typetable *types) 1288{ 1289 1290 if (types->table != types->stattable) 1291 free (types->table); 1292} 1293 1294/* 1295 * Add an argument type to the table, expanding if necessary. 1296 */ 1297static inline void 1298addtype(struct typetable *types, enum typeid type) 1299{ 1300 1301 if (types->nextarg >= types->tablesize) 1302 __grow_type_table(types); 1303 if (types->nextarg > types->tablemax) 1304 types->tablemax = types->nextarg; 1305 types->table[types->nextarg++] = type; 1306} 1307 1308static inline void 1309addsarg(struct typetable *types, int flags) 1310{ 1311 1312 if (flags & INTMAXT) 1313 addtype(types, T_INTMAXT); 1314 else if (flags & SIZET) 1315 addtype(types, T_SIZET); 1316 else if (flags & PTRDIFFT) 1317 addtype(types, T_PTRDIFFT); 1318 else if (flags & LLONGINT) 1319 addtype(types, T_LLONG); 1320 else if (flags & LONGINT) 1321 addtype(types, T_LONG); 1322 else 1323 addtype(types, T_INT); 1324} 1325 1326static inline void 1327adduarg(struct typetable *types, int flags) 1328{ 1329 1330 if (flags & INTMAXT) 1331 addtype(types, T_UINTMAXT); 1332 else if (flags & SIZET) 1333 addtype(types, T_SIZET); 1334 else if (flags & PTRDIFFT) 1335 addtype(types, T_PTRDIFFT); 1336 else if (flags & LLONGINT) 1337 addtype(types, T_U_LLONG); 1338 else if (flags & LONGINT) 1339 addtype(types, T_U_LONG); 1340 else 1341 addtype(types, T_U_INT); 1342} 1343 1344/* 1345 * Add * arguments to the type array. 1346 */ 1347static inline void 1348addaster(struct typetable *types, char **fmtp) 1349{ 1350 char *cp; 1351 int n2; 1352 1353 n2 = 0; 1354 cp = *fmtp; 1355 while (is_digit(*cp)) { 1356 n2 = 10 * n2 + to_digit(*cp); 1357 cp++; 1358 } 1359 if (*cp == '$') { 1360 int hold = types->nextarg; 1361 types->nextarg = n2; 1362 addtype(types, T_INT); 1363 types->nextarg = hold; 1364 *fmtp = ++cp; 1365 } else { 1366 addtype(types, T_INT); 1367 } 1368} 1369 1370/* 1371 * Find all arguments when a positional parameter is encountered. Returns a 1372 * table, indexed by argument number, of pointers to each arguments. The 1373 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. 1374 * It will be replaces with a malloc-ed one if it overflows. 1375 */ 1376static void 1377__find_arguments (const char *fmt0, va_list ap, union arg **argtable) 1378{ 1379 char *fmt; /* format string */ 1380 int ch; /* character from fmt */ 1381 int n; /* handy integer (short term usage) */ 1382 int flags; /* flags as above */ 1383 int width; /* width from format (%8d), or 0 */ 1384 struct typetable types; /* table of types */ 1385 1386 fmt = (char *)fmt0; 1387 inittypes(&types); 1388 1389 /* 1390 * Scan the format for conversions (`%' character). 1391 */ 1392 for (;;) { 1393 while ((ch = *fmt) != '\0' && ch != '%') 1394 fmt++; 1395 if (ch == '\0') 1396 goto done; 1397 fmt++; /* skip over '%' */ 1398 1399 flags = 0; 1400 width = 0; 1401 1402rflag: ch = *fmt++; 1403reswitch: switch (ch) { 1404 case ' ': 1405 case '#': 1406 goto rflag; 1407 case '*': 1408 addaster(&types, &fmt); 1409 goto rflag; 1410 case '-': 1411 case '+': 1412 case '\'': 1413 goto rflag; 1414 case '.': 1415 if ((ch = *fmt++) == '*') { 1416 addaster(&types, &fmt); 1417 goto rflag; 1418 } 1419 while (is_digit(ch)) { 1420 ch = *fmt++; 1421 } 1422 goto reswitch; 1423 case '0': 1424 goto rflag; 1425 case '1': case '2': case '3': case '4': 1426 case '5': case '6': case '7': case '8': case '9': 1427 n = 0; 1428 do { 1429 n = 10 * n + to_digit(ch); 1430 ch = *fmt++; 1431 } while (is_digit(ch)); 1432 if (ch == '$') { 1433 types.nextarg = n; 1434 goto rflag; 1435 } 1436 width = n; 1437 goto reswitch; | |
1438#ifndef NO_FLOATING_POINT | 1191#ifndef NO_FLOATING_POINT |
1439 case 'L': 1440 flags |= LONGDBL; 1441 goto rflag; 1442#endif 1443 case 'h': 1444 if (flags & SHORTINT) { 1445 flags &= ~SHORTINT; 1446 flags |= CHARINT; 1447 } else 1448 flags |= SHORTINT; 1449 goto rflag; 1450 case 'j': 1451 flags |= INTMAXT; 1452 goto rflag; 1453 case 'l': 1454 if (flags & LONGINT) { 1455 flags &= ~LONGINT; 1456 flags |= LLONGINT; 1457 } else 1458 flags |= LONGINT; 1459 goto rflag; 1460 case 'q': 1461 flags |= LLONGINT; /* not necessarily */ 1462 goto rflag; 1463 case 't': 1464 flags |= PTRDIFFT; 1465 goto rflag; 1466 case 'z': 1467 flags |= SIZET; 1468 goto rflag; 1469 case 'C': 1470 flags |= LONGINT; 1471 /*FALLTHROUGH*/ 1472 case 'c': 1473 if (flags & LONGINT) 1474 addtype(&types, T_WINT); 1475 else 1476 addtype(&types, T_INT); 1477 break; 1478 case 'D': 1479 flags |= LONGINT; 1480 /*FALLTHROUGH*/ 1481 case 'd': 1482 case 'i': 1483 addsarg(&types, flags); 1484 break; 1485#ifndef NO_FLOATING_POINT 1486 case 'a': 1487 case 'A': 1488 case 'e': 1489 case 'E': 1490 case 'f': 1491 case 'g': 1492 case 'G': 1493 if (flags & LONGDBL) 1494 addtype(&types, T_LONG_DOUBLE); 1495 else 1496 addtype(&types, T_DOUBLE); 1497 break; 1498#endif /* !NO_FLOATING_POINT */ 1499 case 'n': 1500 if (flags & INTMAXT) 1501 addtype(&types, TP_INTMAXT); 1502 else if (flags & PTRDIFFT) 1503 addtype(&types, TP_PTRDIFFT); 1504 else if (flags & SIZET) 1505 addtype(&types, TP_SIZET); 1506 else if (flags & LLONGINT) 1507 addtype(&types, TP_LLONG); 1508 else if (flags & LONGINT) 1509 addtype(&types, TP_LONG); 1510 else if (flags & SHORTINT) 1511 addtype(&types, TP_SHORT); 1512 else if (flags & CHARINT) 1513 addtype(&types, TP_SCHAR); 1514 else 1515 addtype(&types, TP_INT); 1516 continue; /* no output */ 1517 case 'O': 1518 flags |= LONGINT; 1519 /*FALLTHROUGH*/ 1520 case 'o': 1521 adduarg(&types, flags); 1522 break; 1523 case 'p': 1524 addtype(&types, TP_VOID); 1525 break; 1526 case 'S': 1527 flags |= LONGINT; 1528 /*FALLTHROUGH*/ 1529 case 's': 1530 if (flags & LONGINT) 1531 addtype(&types, TP_WCHAR); 1532 else 1533 addtype(&types, TP_CHAR); 1534 break; 1535 case 'U': 1536 flags |= LONGINT; 1537 /*FALLTHROUGH*/ 1538 case 'u': 1539 case 'X': 1540 case 'x': 1541 adduarg(&types, flags); 1542 break; 1543 default: /* "%?" prints ?, unless ? is NUL */ 1544 if (ch == '\0') 1545 goto done; 1546 break; 1547 } 1548 } 1549done: 1550 /* 1551 * Build the argument table. 1552 */ 1553 if (types.tablemax >= STATIC_ARG_TBL_SIZE) { 1554 *argtable = (union arg *) 1555 malloc (sizeof (union arg) * (types.tablemax + 1)); 1556 } | |
1557 | 1192 |
1558 (*argtable) [0].intarg = 0; 1559 for (n = 1; n <= types.tablemax; n++) { 1560 switch (types.table[n]) { 1561 case T_UNUSED: /* whoops! */ 1562 (*argtable) [n].intarg = va_arg (ap, int); 1563 break; 1564 case TP_SCHAR: 1565 (*argtable) [n].pschararg = va_arg (ap, signed char *); 1566 break; 1567 case TP_SHORT: 1568 (*argtable) [n].pshortarg = va_arg (ap, short *); 1569 break; 1570 case T_INT: 1571 (*argtable) [n].intarg = va_arg (ap, int); 1572 break; 1573 case T_U_INT: 1574 (*argtable) [n].uintarg = va_arg (ap, unsigned int); 1575 break; 1576 case TP_INT: 1577 (*argtable) [n].pintarg = va_arg (ap, int *); 1578 break; 1579 case T_LONG: 1580 (*argtable) [n].longarg = va_arg (ap, long); 1581 break; 1582 case T_U_LONG: 1583 (*argtable) [n].ulongarg = va_arg (ap, unsigned long); 1584 break; 1585 case TP_LONG: 1586 (*argtable) [n].plongarg = va_arg (ap, long *); 1587 break; 1588 case T_LLONG: 1589 (*argtable) [n].longlongarg = va_arg (ap, long long); 1590 break; 1591 case T_U_LLONG: 1592 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long); 1593 break; 1594 case TP_LLONG: 1595 (*argtable) [n].plonglongarg = va_arg (ap, long long *); 1596 break; 1597 case T_PTRDIFFT: 1598 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t); 1599 break; 1600 case TP_PTRDIFFT: 1601 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *); 1602 break; 1603 case T_SIZET: 1604 (*argtable) [n].sizearg = va_arg (ap, size_t); 1605 break; 1606 case TP_SIZET: 1607 (*argtable) [n].psizearg = va_arg (ap, size_t *); 1608 break; 1609 case T_INTMAXT: 1610 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t); 1611 break; 1612 case T_UINTMAXT: 1613 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t); 1614 break; 1615 case TP_INTMAXT: 1616 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *); 1617 break; 1618 case T_DOUBLE: 1619#ifndef NO_FLOATING_POINT 1620 (*argtable) [n].doublearg = va_arg (ap, double); 1621#endif 1622 break; 1623 case T_LONG_DOUBLE: 1624#ifndef NO_FLOATING_POINT 1625 (*argtable) [n].longdoublearg = va_arg (ap, long double); 1626#endif 1627 break; 1628 case TP_CHAR: 1629 (*argtable) [n].pchararg = va_arg (ap, char *); 1630 break; 1631 case TP_VOID: 1632 (*argtable) [n].pvoidarg = va_arg (ap, void *); 1633 break; 1634 case T_WINT: 1635 (*argtable) [n].wintarg = va_arg (ap, wint_t); 1636 break; 1637 case TP_WCHAR: 1638 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *); 1639 break; 1640 } 1641 } 1642 1643 freetypes(&types); 1644} 1645 1646/* 1647 * Increase the size of the type table. 1648 */ 1649static void 1650__grow_type_table(struct typetable *types) 1651{ 1652 enum typeid *const oldtable = types->table; 1653 const int oldsize = types->tablesize; 1654 enum typeid *newtable; 1655 int n, newsize = oldsize * 2; 1656 1657 if (newsize < types->nextarg + 1) 1658 newsize = types->nextarg + 1; 1659 if (oldsize == STATIC_ARG_TBL_SIZE) { 1660 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL) 1661 abort(); /* XXX handle better */ 1662 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid)); 1663 } else { 1664 newtable = reallocf(oldtable, newsize * sizeof(enum typeid)); 1665 if (newtable == NULL) 1666 abort(); /* XXX handle better */ 1667 } 1668 for (n = oldsize; n < newsize; n++) 1669 newtable[n] = T_UNUSED; 1670 1671 types->table = newtable; 1672 types->tablesize = newsize; 1673} 1674 1675 1676#ifndef NO_FLOATING_POINT 1677 | |
1678static int 1679exponent(char *p0, int exp, int fmtch) 1680{ 1681 char *p, *t; 1682 char expbuf[MAXEXPDIG]; 1683 1684 p = p0; 1685 *p++ = fmtch; --- 28 unchanged lines hidden --- | 1193static int 1194exponent(char *p0, int exp, int fmtch) 1195{ 1196 char *p, *t; 1197 char expbuf[MAXEXPDIG]; 1198 1199 p = p0; 1200 *p++ = fmtch; --- 28 unchanged lines hidden --- |