|
|
1.1 ! root 1: /* xpprintf.c */ ! 2: ! 3: /* Deuce's vs[n]printf() replacement */ ! 4: ! 5: /* $Id: xpprintf.c,v 1.34 2006/12/21 21:32:12 deuce Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This library is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU Lesser General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU Lesser General Public License for more details: lgpl.txt or * ! 18: * http://www.fsf.org/copyleft/lesser.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include <stdarg.h> ! 39: #include <stdio.h> ! 40: #include <string.h> ! 41: #include <stdlib.h> ! 42: #if defined(_WIN32) ! 43: #include <malloc.h> /* alloca() on Win32 */ ! 44: #endif ! 45: ! 46: #include "xpprintf.h" ! 47: ! 48: /* MSVC Sucks - can't tell the required len of a *printf() */ ! 49: #define MAX_ARG_LEN 1024 /* MAX_ARG_LEN is the maximum length ! 50: * possible as a result of a format ! 51: * which is not %s ! 52: */ ! 53: ! 54: /* Maximum length of a format specifier including the % */ ! 55: #define MAX_FORMAT_LEN 256 ! 56: ! 57: void xp_asprintf_free(char *format) ! 58: { ! 59: free(format); ! 60: } ! 61: ! 62: int xp_printf_get_type(const char *format) ! 63: { ! 64: const char *p; ! 65: int modifier=0; ! 66: int j; ! 67: int correct_type; ! 68: ! 69: if(!*(size_t *)format) ! 70: return(0); ! 71: p=format+*(size_t *)format; ! 72: if(*p!='%') ! 73: return(0); ! 74: p++; ! 75: ! 76: /* ! 77: * Skip flags (zero or more) ! 78: */ ! 79: j=1; ! 80: while(j) { ! 81: switch(*p) { ! 82: case '#': ! 83: p++; ! 84: break; ! 85: case '-': ! 86: p++; ! 87: break; ! 88: case '+': ! 89: p++; ! 90: break; ! 91: case ' ': ! 92: p++; ! 93: break; ! 94: case '0': ! 95: p++; ! 96: break; ! 97: case '\'': ! 98: p++; ! 99: break; ! 100: default: ! 101: j=0; ! 102: break; ! 103: } ! 104: } ! 105: if(*p=='*') ! 106: return(XP_PRINTF_TYPE_INT); ! 107: while(*p>= '0' && *p <= '9') ! 108: p++; ! 109: if(*p=='.') { ! 110: p++; ! 111: if(*p=='*') ! 112: return(XP_PRINTF_TYPE_INT); ! 113: } ! 114: while(*p>= '0' && *p <= '9') ! 115: p++; ! 116: switch(*p) { ! 117: case 'h': ! 118: modifier='h'; ! 119: p++; ! 120: if(*p=='h') { ! 121: p++; ! 122: modifier+='h'<<8; ! 123: } ! 124: break; ! 125: case 'l': ! 126: modifier='h'; ! 127: p++; ! 128: if(*p=='l') { ! 129: p++; ! 130: modifier+='l'<<8; ! 131: } ! 132: break; ! 133: case 'j': ! 134: modifier='j'; ! 135: p++; ! 136: break; ! 137: case 't': ! 138: modifier='t'; ! 139: p++; ! 140: break; ! 141: case 'z': ! 142: modifier='z'; ! 143: p++; ! 144: break; ! 145: case 'L': ! 146: modifier='L'; ! 147: p++; ! 148: break; ! 149: } ! 150: /* ! 151: * The next char is now the type... if type is auto, ! 152: * set type to what it SHOULD be ! 153: */ ! 154: switch(*p) { ! 155: /* INT types */ ! 156: case 'd': ! 157: case 'i': ! 158: switch(modifier) { ! 159: case 'h'|'h'<<8: ! 160: correct_type=XP_PRINTF_TYPE_SCHAR; ! 161: break; ! 162: case 'h': ! 163: correct_type=XP_PRINTF_TYPE_SHORT; ! 164: break; ! 165: case 'l': ! 166: correct_type=XP_PRINTF_TYPE_LONG; ! 167: break; ! 168: #if defined(XP_PRINTF_TYPE_ULONGLONG) ! 169: case 'l'|'l'<<8: ! 170: correct_type=XP_PRINTF_TYPE_LONGLONG; ! 171: break; ! 172: #endif ! 173: case 'j': ! 174: correct_type=XP_PRINTF_TYPE_INTMAX; ! 175: break; ! 176: case 't': ! 177: correct_type=XP_PRINTF_TYPE_PTRDIFF; ! 178: break; ! 179: case 'z': ! 180: /* ! 181: * ToDo this is a signed type of same size ! 182: * as size_t ! 183: */ ! 184: correct_type=XP_PRINTF_TYPE_LONG; ! 185: break; ! 186: default: ! 187: correct_type=XP_PRINTF_TYPE_INT; ! 188: break; ! 189: } ! 190: break; ! 191: case 'o': ! 192: case 'u': ! 193: case 'x': ! 194: case 'X': ! 195: switch(modifier) { ! 196: case 'h'|'h'<<8: ! 197: correct_type=XP_PRINTF_TYPE_UCHAR; ! 198: break; ! 199: case 'h': ! 200: correct_type=XP_PRINTF_TYPE_USHORT; ! 201: break; ! 202: case 'l': ! 203: correct_type=XP_PRINTF_TYPE_ULONG; ! 204: break; ! 205: #if defined(XP_PRINTF_TYPE_ULONGLONG) ! 206: case 'l'|'l'<<8: ! 207: correct_type=XP_PRINTF_TYPE_ULONGLONG; ! 208: break; ! 209: #endif ! 210: case 'j': ! 211: correct_type=XP_PRINTF_TYPE_UINTMAX; ! 212: break; ! 213: case 't': ! 214: /* ! 215: * ToDo this is an unsigned type of same size ! 216: * as ptrdiff_t ! 217: */ ! 218: correct_type=XP_PRINTF_TYPE_ULONG; ! 219: break; ! 220: case 'z': ! 221: correct_type=XP_PRINTF_TYPE_SIZET; ! 222: break; ! 223: default: ! 224: correct_type=XP_PRINTF_TYPE_UINT; ! 225: break; ! 226: } ! 227: break; ! 228: case 'a': ! 229: case 'A': ! 230: case 'e': ! 231: case 'E': ! 232: case 'f': ! 233: case 'F': ! 234: case 'g': ! 235: case 'G': ! 236: switch(modifier) { ! 237: case 'L': ! 238: correct_type=XP_PRINTF_TYPE_LONGDOUBLE; ! 239: break; ! 240: case 'l': ! 241: default: ! 242: correct_type=XP_PRINTF_TYPE_DOUBLE; ! 243: break; ! 244: } ! 245: break; ! 246: case 'C': ! 247: /* ToDo wide chars... not yet supported */ ! 248: correct_type=XP_PRINTF_TYPE_CHAR; ! 249: break; ! 250: case 'c': ! 251: switch(modifier) { ! 252: case 'l': ! 253: /* ToDo wide chars... not yet supported */ ! 254: default: ! 255: correct_type=XP_PRINTF_TYPE_CHAR; ! 256: } ! 257: break; ! 258: case 'S': ! 259: /* ToDo wide chars... not yet supported */ ! 260: correct_type=XP_PRINTF_TYPE_CHARP; ! 261: break; ! 262: case 's': ! 263: switch(modifier) { ! 264: case 'l': ! 265: /* ToDo wide chars... not yet supported */ ! 266: default: ! 267: correct_type=XP_PRINTF_TYPE_CHARP; ! 268: } ! 269: break; ! 270: case 'p': ! 271: correct_type=XP_PRINTF_TYPE_VOIDP; ! 272: break; ! 273: } ! 274: return(correct_type); ! 275: } ! 276: ! 277: /* ! 278: * Performs the next replacement in format using the variable ! 279: * specified as the only vararg which is currently the type ! 280: * specified in type (defined in xpprintf.h). ! 281: * ! 282: * Does not currently support the $ argument selector. ! 283: * ! 284: * Currently, the type is not overly usefull, but this could be used for ! 285: * automatic type conversions (ie: int to char *). Right now it just assures ! 286: * that the type passed to sprintf() is the type passed to ! 287: * xp_asprintf_next(). ! 288: */ ! 289: char *xp_asprintf_next(char *format, int type, ...) ! 290: { ! 291: va_list vars; ! 292: char *p; ! 293: char *newbuf; ! 294: int i,j; ! 295: unsigned int ui; ! 296: long int l; ! 297: unsigned long int ul; ! 298: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 299: long long int ll; ! 300: unsigned long long int ull; ! 301: #endif ! 302: double d; ! 303: long double ld; ! 304: char* cp; ! 305: void* pntr; ! 306: size_t s; ! 307: unsigned long offset=0; ! 308: unsigned long offset2=0; ! 309: size_t format_len; ! 310: size_t this_format_len; ! 311: char entry_buf[MAX_ARG_LEN]; ! 312: char *entry; ! 313: char this_format[MAX_FORMAT_LEN]; ! 314: char *fmt; ! 315: int modifier=0; ! 316: int correct_type=0; ! 317: char num_str[128]; /* More than enough room for a 256-bit int */ ! 318: size_t width=0; ! 319: size_t precision=0; ! 320: ! 321: /* ! 322: * Check if we're already done... ! 323: */ ! 324: if(!*(size_t *) format) ! 325: return(format); ! 326: ! 327: p=format+*(size_t *)format; ! 328: offset=p-format; ! 329: format_len=*(size_t *)(format+sizeof(size_t))+sizeof(size_t)*2+1; ! 330: this_format[0]=0; ! 331: fmt=this_format; ! 332: *(fmt++)=*(p++); ! 333: ! 334: /* ! 335: * Skip flags (zero or more) ! 336: */ ! 337: j=1; ! 338: while(j) { ! 339: switch(*p) { ! 340: case '#': ! 341: *(fmt++)=*(p++); ! 342: break; ! 343: case '-': ! 344: *(fmt++)=*(p++); ! 345: break; ! 346: case '+': ! 347: *(fmt++)=*(p++); ! 348: break; ! 349: case ' ': ! 350: *(fmt++)=*(p++); ! 351: break; ! 352: case '0': ! 353: *(fmt++)=*(p++); ! 354: break; ! 355: case '\'': ! 356: *(fmt++)=*(p++); ! 357: break; ! 358: default: ! 359: j=0; ! 360: break; ! 361: } ! 362: } ! 363: ! 364: /* ! 365: * If width is '*' then the argument is an int ! 366: * which specifies the width. ! 367: */ ! 368: if(*p=='*') { /* The argument is this width */ ! 369: va_start(vars, type); ! 370: i=sprintf(entry_buf,"%d", va_arg(vars, int)); ! 371: va_end(vars); ! 372: if(i > 1) { ! 373: /* ! 374: * We must calculate this before we go mucking about ! 375: * with format and p ! 376: */ ! 377: offset2=p-format; ! 378: newbuf=(char *)realloc(format, format_len+i-1 /* -1 for the '*' that's already there */); ! 379: if(newbuf==NULL) ! 380: return(NULL); ! 381: format=newbuf; ! 382: p=format+offset2; ! 383: /* ! 384: * Move trailing end to make space... leaving the * where it ! 385: * is so it can be overwritten ! 386: */ ! 387: memmove(p+i, p+1, format-p+format_len); ! 388: memcpy(p, entry_buf, i); ! 389: } ! 390: else ! 391: *p=entry_buf[0]; ! 392: p=format+offset; ! 393: *(size_t *)format=p-format; ! 394: return(format); ! 395: } ! 396: /* Skip width */ ! 397: if(*p >= '0' && *p <= '9') ! 398: width=strtoul(p, NULL, 10); ! 399: while(*p >= '0' && *p <= '9') ! 400: *(fmt++)=*(p++); ! 401: /* Check for precision */ ! 402: if(*p=='.') { ! 403: *(fmt++)=*(p++); ! 404: /* ! 405: * If the precision is '*' then the argument is an int which ! 406: * specifies the precision. ! 407: */ ! 408: if(*p=='*') { ! 409: va_start(vars, type); ! 410: i=sprintf(entry_buf,"%d", va_arg(vars, int)); ! 411: va_end(vars); ! 412: if(i > 1) { ! 413: /* ! 414: * We must calculate this before we go mucking about ! 415: * with format and p ! 416: */ ! 417: offset2=p-format; ! 418: newbuf=(char *)realloc(format, format_len+i-1 /* -1 for the '*' that's already there */); ! 419: if(newbuf==NULL) ! 420: return(NULL); ! 421: format=newbuf; ! 422: p=format+offset2; ! 423: /* ! 424: * Move trailing end to make space... leaving the * where it ! 425: * is so it can be overwritten ! 426: */ ! 427: memmove(p+i, p+1, format-p+format_len); ! 428: memcpy(p, entry_buf, i); ! 429: } ! 430: else ! 431: *p=entry_buf[0]; ! 432: p=format+offset; ! 433: *(size_t *)format=p-format; ! 434: return(format); ! 435: } ! 436: /* Skip precision */ ! 437: if(*p >= '0' && *p <= '9') ! 438: precision=strtoul(p, NULL, 10); ! 439: while(*p >= '0' && *p <= '9') ! 440: *(fmt++)=*(p++); ! 441: } ! 442: ! 443: /* Skip/Translate length modifiers */ ! 444: /* ! 445: * ToDo: This could (should?) convert the standard ll modifier ! 446: * to the MSVC equivilant (I64 or something?) ! 447: * if you do this, the calculations using this_format_len will need ! 448: * rewriting. ! 449: */ ! 450: switch(*p) { ! 451: case 'h': ! 452: modifier='h'; ! 453: *(fmt++)=*(p++); ! 454: if(*p=='h') { ! 455: *(fmt++)=*(p++); ! 456: modifier+='h'<<8; ! 457: } ! 458: break; ! 459: case 'l': ! 460: modifier='h'; ! 461: *(fmt++)=*(p++); ! 462: if(*p=='l') { ! 463: *(fmt++)=*(p++); ! 464: modifier+='l'<<8; ! 465: } ! 466: break; ! 467: case 'j': ! 468: modifier='j'; ! 469: *(fmt++)=*(p++); ! 470: break; ! 471: case 't': ! 472: modifier='t'; ! 473: *(fmt++)=*(p++); ! 474: break; ! 475: case 'z': ! 476: modifier='z'; ! 477: *(fmt++)=*(p++); ! 478: break; ! 479: case 'L': ! 480: modifier='L'; ! 481: *(fmt++)=*(p++); ! 482: break; ! 483: } ! 484: ! 485: /* ! 486: * The next char is now the type... if type is auto, ! 487: * set type to what it SHOULD be ! 488: */ ! 489: if(type==XP_PRINTF_TYPE_AUTO || type & XP_PRINTF_CONVERT) { ! 490: switch(*p) { ! 491: /* INT types */ ! 492: case 'd': ! 493: case 'i': ! 494: switch(modifier) { ! 495: case 'h'|'h'<<8: ! 496: correct_type=XP_PRINTF_TYPE_SCHAR; ! 497: break; ! 498: case 'h': ! 499: correct_type=XP_PRINTF_TYPE_SHORT; ! 500: break; ! 501: case 'l': ! 502: correct_type=XP_PRINTF_TYPE_LONG; ! 503: break; ! 504: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 505: case 'l'|'l'<<8: ! 506: correct_type=XP_PRINTF_TYPE_LONGLONG; ! 507: break; ! 508: #endif ! 509: case 'j': ! 510: correct_type=XP_PRINTF_TYPE_INTMAX; ! 511: break; ! 512: case 't': ! 513: correct_type=XP_PRINTF_TYPE_PTRDIFF; ! 514: break; ! 515: case 'z': ! 516: /* ! 517: * ToDo this is a signed type of same size ! 518: * as size_t ! 519: */ ! 520: correct_type=XP_PRINTF_TYPE_LONG; ! 521: break; ! 522: default: ! 523: correct_type=XP_PRINTF_TYPE_INT; ! 524: break; ! 525: } ! 526: break; ! 527: case 'o': ! 528: case 'u': ! 529: case 'x': ! 530: case 'X': ! 531: switch(modifier) { ! 532: case 'h'|'h'<<8: ! 533: correct_type=XP_PRINTF_TYPE_UCHAR; ! 534: break; ! 535: case 'h': ! 536: correct_type=XP_PRINTF_TYPE_USHORT; ! 537: break; ! 538: case 'l': ! 539: correct_type=XP_PRINTF_TYPE_ULONG; ! 540: break; ! 541: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 542: case 'l'|'l'<<8: ! 543: correct_type=XP_PRINTF_TYPE_ULONGLONG; ! 544: break; ! 545: #endif ! 546: case 'j': ! 547: correct_type=XP_PRINTF_TYPE_UINTMAX; ! 548: break; ! 549: case 't': ! 550: /* ! 551: * ToDo this is an unsigned type of same size ! 552: * as ptrdiff_t ! 553: */ ! 554: correct_type=XP_PRINTF_TYPE_ULONG; ! 555: break; ! 556: case 'z': ! 557: correct_type=XP_PRINTF_TYPE_SIZET; ! 558: break; ! 559: default: ! 560: correct_type=XP_PRINTF_TYPE_UINT; ! 561: break; ! 562: } ! 563: break; ! 564: case 'a': ! 565: case 'A': ! 566: case 'e': ! 567: case 'E': ! 568: case 'f': ! 569: case 'F': ! 570: case 'g': ! 571: case 'G': ! 572: switch(modifier) { ! 573: case 'L': ! 574: correct_type=XP_PRINTF_TYPE_LONGDOUBLE; ! 575: break; ! 576: case 'l': ! 577: default: ! 578: correct_type=XP_PRINTF_TYPE_DOUBLE; ! 579: break; ! 580: } ! 581: break; ! 582: case 'C': ! 583: /* ToDo wide chars... not yet supported */ ! 584: correct_type=XP_PRINTF_TYPE_CHAR; ! 585: break; ! 586: case 'c': ! 587: switch(modifier) { ! 588: case 'l': ! 589: /* ToDo wide chars... not yet supported */ ! 590: default: ! 591: correct_type=XP_PRINTF_TYPE_CHAR; ! 592: } ! 593: break; ! 594: case 'S': ! 595: /* ToDo wide chars... not yet supported */ ! 596: correct_type=XP_PRINTF_TYPE_CHARP; ! 597: break; ! 598: case 's': ! 599: switch(modifier) { ! 600: case 'l': ! 601: /* ToDo wide chars... not yet supported */ ! 602: default: ! 603: correct_type=XP_PRINTF_TYPE_CHARP; ! 604: } ! 605: break; ! 606: case 'p': ! 607: correct_type=XP_PRINTF_TYPE_VOIDP; ! 608: break; ! 609: } ! 610: } ! 611: if(type==XP_PRINTF_TYPE_AUTO) ! 612: type=correct_type; ! 613: ! 614: /* ! 615: * Copy the arg to the passed type. ! 616: */ ! 617: va_start(vars, type); ! 618: switch(type & ~XP_PRINTF_CONVERT) { ! 619: case XP_PRINTF_TYPE_CHAR: ! 620: case XP_PRINTF_TYPE_INT: /* Also includes char and short */ ! 621: i=va_arg(vars, int); ! 622: break; ! 623: case XP_PRINTF_TYPE_UINT: /* Also includes char and short */ ! 624: /* ! 625: * ToDo: If it's a %c, and the value is 0, should it output [null] ! 626: * or should it terminate the string? ! 627: */ ! 628: ui=va_arg(vars, unsigned int); ! 629: break; ! 630: case XP_PRINTF_TYPE_LONG: ! 631: l=va_arg(vars, long); ! 632: break; ! 633: case XP_PRINTF_TYPE_ULONG: ! 634: ul=va_arg(vars, unsigned long int); ! 635: break; ! 636: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 637: case XP_PRINTF_TYPE_LONGLONG: ! 638: ll=va_arg(vars, long long int); ! 639: break; ! 640: case XP_PRINTF_TYPE_ULONGLONG: ! 641: ull=va_arg(vars, unsigned long long int); ! 642: break; ! 643: #endif ! 644: case XP_PRINTF_TYPE_CHARP: ! 645: cp=va_arg(vars, char*); ! 646: break; ! 647: case XP_PRINTF_TYPE_DOUBLE: ! 648: d=va_arg(vars, double); ! 649: break; ! 650: case XP_PRINTF_TYPE_LONGDOUBLE: ! 651: ld=va_arg(vars, long double); ! 652: break; ! 653: case XP_PRINTF_TYPE_VOIDP: ! 654: pntr=va_arg(vars, void*); ! 655: break; ! 656: case XP_PRINTF_TYPE_SIZET: ! 657: s=va_arg(vars, size_t); ! 658: break; ! 659: } ! 660: va_end(vars); ! 661: ! 662: if(type & XP_PRINTF_CONVERT) { ! 663: type=type & ~XP_PRINTF_CONVERT; ! 664: if(type != correct_type) { ! 665: switch(correct_type) { ! 666: case XP_PRINTF_TYPE_CHAR: ! 667: switch(type) { ! 668: case XP_PRINTF_TYPE_CHAR: ! 669: case XP_PRINTF_TYPE_INT: ! 670: i=i; ! 671: break; ! 672: case XP_PRINTF_TYPE_UINT: ! 673: i=ui; ! 674: break; ! 675: case XP_PRINTF_TYPE_LONG: ! 676: i=l; ! 677: break; ! 678: case XP_PRINTF_TYPE_ULONG: ! 679: i=ul; ! 680: break; ! 681: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 682: case XP_PRINTF_TYPE_LONGLONG: ! 683: i=ll; ! 684: break; ! 685: case XP_PRINTF_TYPE_ULONGLONG: ! 686: i=ull; ! 687: break; ! 688: #endif ! 689: case XP_PRINTF_TYPE_CHARP: ! 690: if(cp) ! 691: i=*cp; ! 692: else ! 693: i=0; ! 694: break; ! 695: case XP_PRINTF_TYPE_DOUBLE: ! 696: i=(int)d; ! 697: break; ! 698: case XP_PRINTF_TYPE_LONGDOUBLE: ! 699: i=(int)ld; ! 700: break; ! 701: case XP_PRINTF_TYPE_VOIDP: ! 702: i=(int)pntr; ! 703: break; ! 704: case XP_PRINTF_TYPE_SIZET: ! 705: i=s; ! 706: break; ! 707: } ! 708: break; ! 709: case XP_PRINTF_TYPE_INT: ! 710: switch(type) { ! 711: case XP_PRINTF_TYPE_CHAR: ! 712: case XP_PRINTF_TYPE_INT: ! 713: i=i; ! 714: break; ! 715: case XP_PRINTF_TYPE_UINT: ! 716: i=ui; ! 717: break; ! 718: case XP_PRINTF_TYPE_LONG: ! 719: i=l; ! 720: break; ! 721: case XP_PRINTF_TYPE_ULONG: ! 722: i=ul; ! 723: break; ! 724: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 725: case XP_PRINTF_TYPE_LONGLONG: ! 726: i=ll; ! 727: break; ! 728: case XP_PRINTF_TYPE_ULONGLONG: ! 729: i=ull; ! 730: break; ! 731: #endif ! 732: case XP_PRINTF_TYPE_CHARP: ! 733: i=strtol(cp, NULL, 0); ! 734: break; ! 735: case XP_PRINTF_TYPE_DOUBLE: ! 736: i=(int)d; ! 737: break; ! 738: case XP_PRINTF_TYPE_LONGDOUBLE: ! 739: i=(int)ld; ! 740: break; ! 741: case XP_PRINTF_TYPE_VOIDP: ! 742: i=(int)pntr; ! 743: break; ! 744: case XP_PRINTF_TYPE_SIZET: ! 745: i=s; ! 746: break; ! 747: } ! 748: break; ! 749: case XP_PRINTF_TYPE_UINT: ! 750: switch(type) { ! 751: case XP_PRINTF_TYPE_CHAR: ! 752: case XP_PRINTF_TYPE_INT: ! 753: ui=i; ! 754: break; ! 755: case XP_PRINTF_TYPE_UINT: ! 756: ui=ui; ! 757: break; ! 758: case XP_PRINTF_TYPE_LONG: ! 759: ui=l; ! 760: break; ! 761: case XP_PRINTF_TYPE_ULONG: ! 762: ui=ul; ! 763: break; ! 764: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 765: case XP_PRINTF_TYPE_LONGLONG: ! 766: ui=ll; ! 767: break; ! 768: case XP_PRINTF_TYPE_ULONGLONG: ! 769: ui=ull; ! 770: break; ! 771: #endif ! 772: case XP_PRINTF_TYPE_CHARP: ! 773: ui=strtoul(cp, NULL, 0); ! 774: break; ! 775: case XP_PRINTF_TYPE_DOUBLE: ! 776: ui=(unsigned)d; ! 777: break; ! 778: case XP_PRINTF_TYPE_LONGDOUBLE: ! 779: ui=(unsigned)ld; ! 780: break; ! 781: case XP_PRINTF_TYPE_VOIDP: ! 782: ui=(unsigned int)pntr; ! 783: break; ! 784: case XP_PRINTF_TYPE_SIZET: ! 785: ui=s; ! 786: break; ! 787: } ! 788: break; ! 789: case XP_PRINTF_TYPE_LONG: ! 790: switch(type) { ! 791: case XP_PRINTF_TYPE_CHAR: ! 792: case XP_PRINTF_TYPE_INT: ! 793: l=i; ! 794: break; ! 795: case XP_PRINTF_TYPE_UINT: ! 796: l=ui; ! 797: break; ! 798: case XP_PRINTF_TYPE_LONG: ! 799: l=l; ! 800: break; ! 801: case XP_PRINTF_TYPE_ULONG: ! 802: l=ul; ! 803: break; ! 804: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 805: case XP_PRINTF_TYPE_LONGLONG: ! 806: l=ll; ! 807: break; ! 808: case XP_PRINTF_TYPE_ULONGLONG: ! 809: l=ull; ! 810: break; ! 811: #endif ! 812: case XP_PRINTF_TYPE_CHARP: ! 813: l=strtol(cp, NULL, 0); ! 814: break; ! 815: case XP_PRINTF_TYPE_DOUBLE: ! 816: l=(long)d; ! 817: break; ! 818: case XP_PRINTF_TYPE_LONGDOUBLE: ! 819: l=(long)ld; ! 820: break; ! 821: case XP_PRINTF_TYPE_VOIDP: ! 822: l=(long)pntr; ! 823: break; ! 824: case XP_PRINTF_TYPE_SIZET: ! 825: l=s; ! 826: break; ! 827: } ! 828: break; ! 829: case XP_PRINTF_TYPE_ULONG: ! 830: switch(type) { ! 831: case XP_PRINTF_TYPE_CHAR: ! 832: case XP_PRINTF_TYPE_INT: ! 833: ul=i; ! 834: break; ! 835: case XP_PRINTF_TYPE_UINT: ! 836: ul=ui; ! 837: break; ! 838: case XP_PRINTF_TYPE_LONG: ! 839: ul=l; ! 840: break; ! 841: case XP_PRINTF_TYPE_ULONG: ! 842: ul=ul; ! 843: break; ! 844: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 845: case XP_PRINTF_TYPE_LONGLONG: ! 846: ul=ll; ! 847: break; ! 848: case XP_PRINTF_TYPE_ULONGLONG: ! 849: ul=ull; ! 850: break; ! 851: #endif ! 852: case XP_PRINTF_TYPE_CHARP: ! 853: ul=strtoul(cp, NULL, 0); ! 854: break; ! 855: case XP_PRINTF_TYPE_DOUBLE: ! 856: ul=(unsigned long)d; ! 857: break; ! 858: case XP_PRINTF_TYPE_LONGDOUBLE: ! 859: ul=(unsigned long)ld; ! 860: break; ! 861: case XP_PRINTF_TYPE_VOIDP: ! 862: ul=(unsigned long)pntr; ! 863: break; ! 864: case XP_PRINTF_TYPE_SIZET: ! 865: ul=s; ! 866: break; ! 867: } ! 868: break; ! 869: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 870: case XP_PRINTF_TYPE_LONGLONG: ! 871: switch(type) { ! 872: case XP_PRINTF_TYPE_CHAR: ! 873: case XP_PRINTF_TYPE_INT: ! 874: ll=i; ! 875: break; ! 876: case XP_PRINTF_TYPE_UINT: ! 877: ll=ui; ! 878: break; ! 879: case XP_PRINTF_TYPE_LONG: ! 880: ll=l; ! 881: break; ! 882: case XP_PRINTF_TYPE_ULONG: ! 883: ll=ul; ! 884: break; ! 885: case XP_PRINTF_TYPE_LONGLONG: ! 886: ll=ll; ! 887: break; ! 888: case XP_PRINTF_TYPE_ULONGLONG: ! 889: ll=ull; ! 890: break; ! 891: case XP_PRINTF_TYPE_CHARP: ! 892: ll=strtoll(cp, NULL, 0); ! 893: break; ! 894: case XP_PRINTF_TYPE_DOUBLE: ! 895: ll=d; ! 896: break; ! 897: case XP_PRINTF_TYPE_LONGDOUBLE: ! 898: ll=ld; ! 899: break; ! 900: case XP_PRINTF_TYPE_VOIDP: ! 901: ll=(long long)pntr; ! 902: break; ! 903: case XP_PRINTF_TYPE_SIZET: ! 904: ll=s; ! 905: break; ! 906: } ! 907: break; ! 908: case XP_PRINTF_TYPE_ULONGLONG: ! 909: switch(type) { ! 910: case XP_PRINTF_TYPE_CHAR: ! 911: case XP_PRINTF_TYPE_INT: ! 912: ull=i; ! 913: break; ! 914: case XP_PRINTF_TYPE_UINT: ! 915: ull=ui; ! 916: break; ! 917: case XP_PRINTF_TYPE_LONG: ! 918: ull=l; ! 919: break; ! 920: case XP_PRINTF_TYPE_ULONG: ! 921: ull=ul; ! 922: break; ! 923: case XP_PRINTF_TYPE_LONGLONG: ! 924: ull=ll; ! 925: break; ! 926: case XP_PRINTF_TYPE_ULONGLONG: ! 927: ull=ull; ! 928: break; ! 929: case XP_PRINTF_TYPE_CHARP: ! 930: ull=strtoull(cp, NULL, 0); ! 931: break; ! 932: case XP_PRINTF_TYPE_DOUBLE: ! 933: ull=d; ! 934: break; ! 935: case XP_PRINTF_TYPE_LONGDOUBLE: ! 936: ull=ld; ! 937: break; ! 938: case XP_PRINTF_TYPE_VOIDP: ! 939: ull=(unsigned long long int)pntr; ! 940: break; ! 941: case XP_PRINTF_TYPE_SIZET: ! 942: ull=s; ! 943: break; ! 944: } ! 945: break; ! 946: #endif ! 947: case XP_PRINTF_TYPE_CHARP: ! 948: num_str[0]=0; ! 949: switch(type) { ! 950: case XP_PRINTF_TYPE_CHAR: ! 951: case XP_PRINTF_TYPE_INT: ! 952: sprintf(num_str, "%d", i); ! 953: cp=num_str; ! 954: break; ! 955: case XP_PRINTF_TYPE_UINT: ! 956: sprintf(num_str, "%u", i); ! 957: cp=num_str; ! 958: break; ! 959: case XP_PRINTF_TYPE_LONG: ! 960: sprintf(num_str, "%ld", l); ! 961: cp=num_str; ! 962: break; ! 963: case XP_PRINTF_TYPE_ULONG: ! 964: sprintf(num_str, "%lu", ul); ! 965: cp=num_str; ! 966: break; ! 967: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 968: case XP_PRINTF_TYPE_LONGLONG: ! 969: /* ToDo MSVC doesn't like this */ ! 970: sprintf(num_str, "%lld", ll); ! 971: cp=num_str; ! 972: break; ! 973: case XP_PRINTF_TYPE_ULONGLONG: ! 974: /* ToDo MSVC doesn't like this */ ! 975: sprintf(num_str, "%llu", ull); ! 976: cp=num_str; ! 977: break; ! 978: #endif ! 979: case XP_PRINTF_TYPE_CHARP: ! 980: cp=cp; ! 981: break; ! 982: case XP_PRINTF_TYPE_DOUBLE: ! 983: sprintf(num_str, "%f", d); ! 984: cp=num_str; ! 985: break; ! 986: case XP_PRINTF_TYPE_LONGDOUBLE: ! 987: sprintf(num_str, "%Lf", d); ! 988: cp=num_str; ! 989: break; ! 990: case XP_PRINTF_TYPE_VOIDP: ! 991: /* ToDo: Or should this pretend it's a char *? */ ! 992: sprintf(num_str, "%p", pntr); ! 993: cp=num_str; ! 994: break; ! 995: case XP_PRINTF_TYPE_SIZET: ! 996: sprintf(num_str, "%zu", s); ! 997: cp=num_str; ! 998: break; ! 999: } ! 1000: break; ! 1001: case XP_PRINTF_TYPE_DOUBLE: ! 1002: switch(type) { ! 1003: case XP_PRINTF_TYPE_CHAR: ! 1004: case XP_PRINTF_TYPE_INT: ! 1005: d=i; ! 1006: break; ! 1007: case XP_PRINTF_TYPE_UINT: ! 1008: d=ui; ! 1009: break; ! 1010: case XP_PRINTF_TYPE_LONG: ! 1011: d=l; ! 1012: break; ! 1013: case XP_PRINTF_TYPE_ULONG: ! 1014: d=ul; ! 1015: break; ! 1016: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1017: case XP_PRINTF_TYPE_LONGLONG: ! 1018: d=ll; ! 1019: break; ! 1020: case XP_PRINTF_TYPE_ULONGLONG: ! 1021: d=ull; ! 1022: break; ! 1023: #endif ! 1024: case XP_PRINTF_TYPE_CHARP: ! 1025: d=strtod(cp, NULL); ! 1026: break; ! 1027: case XP_PRINTF_TYPE_DOUBLE: ! 1028: d=d; ! 1029: break; ! 1030: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1031: d=ld; ! 1032: break; ! 1033: case XP_PRINTF_TYPE_VOIDP: ! 1034: d=(double)((long int)pntr); ! 1035: break; ! 1036: case XP_PRINTF_TYPE_SIZET: ! 1037: d=s; ! 1038: break; ! 1039: } ! 1040: break; ! 1041: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1042: switch(type) { ! 1043: case XP_PRINTF_TYPE_CHAR: ! 1044: case XP_PRINTF_TYPE_INT: ! 1045: ld=i; ! 1046: break; ! 1047: case XP_PRINTF_TYPE_UINT: ! 1048: ld=ui; ! 1049: break; ! 1050: case XP_PRINTF_TYPE_LONG: ! 1051: ld=l; ! 1052: break; ! 1053: case XP_PRINTF_TYPE_ULONG: ! 1054: ld=ul; ! 1055: break; ! 1056: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1057: case XP_PRINTF_TYPE_LONGLONG: ! 1058: ld=ll; ! 1059: break; ! 1060: case XP_PRINTF_TYPE_ULONGLONG: ! 1061: ld=ull; ! 1062: break; ! 1063: #endif ! 1064: case XP_PRINTF_TYPE_CHARP: ! 1065: /* strtold() isn't ubiquitous yet */ ! 1066: ld=strtod(cp, NULL); ! 1067: break; ! 1068: case XP_PRINTF_TYPE_DOUBLE: ! 1069: ld=d; ! 1070: break; ! 1071: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1072: ld=ld; ! 1073: break; ! 1074: case XP_PRINTF_TYPE_VOIDP: ! 1075: ld=(long double)((long int)pntr); ! 1076: break; ! 1077: case XP_PRINTF_TYPE_SIZET: ! 1078: ld=s; ! 1079: break; ! 1080: } ! 1081: break; ! 1082: case XP_PRINTF_TYPE_VOIDP: ! 1083: /* ToDo: this is nasty... */ ! 1084: switch(type) { ! 1085: case XP_PRINTF_TYPE_CHAR: ! 1086: case XP_PRINTF_TYPE_INT: ! 1087: pntr=(void *)i; ! 1088: break; ! 1089: case XP_PRINTF_TYPE_UINT: ! 1090: pntr=(void *)ui; ! 1091: break; ! 1092: case XP_PRINTF_TYPE_LONG: ! 1093: pntr=(void *)l; ! 1094: break; ! 1095: case XP_PRINTF_TYPE_ULONG: ! 1096: pntr=(void *)ul; ! 1097: break; ! 1098: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1099: case XP_PRINTF_TYPE_LONGLONG: ! 1100: pntr=(void *)ll; ! 1101: break; ! 1102: case XP_PRINTF_TYPE_ULONGLONG: ! 1103: pntr=(void *)ull; ! 1104: break; ! 1105: #endif ! 1106: case XP_PRINTF_TYPE_CHARP: ! 1107: pntr=(void *)cp; ! 1108: break; ! 1109: case XP_PRINTF_TYPE_DOUBLE: ! 1110: pntr=(void *)(long int)d; ! 1111: break; ! 1112: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1113: pntr=(void *)(long int)ld; ! 1114: break; ! 1115: case XP_PRINTF_TYPE_VOIDP: ! 1116: pntr=pntr; ! 1117: break; ! 1118: case XP_PRINTF_TYPE_SIZET: ! 1119: pntr=(void *)s; ! 1120: break; ! 1121: } ! 1122: break; ! 1123: case XP_PRINTF_TYPE_SIZET: ! 1124: switch(type) { ! 1125: case XP_PRINTF_TYPE_CHAR: ! 1126: case XP_PRINTF_TYPE_INT: ! 1127: s=i; ! 1128: break; ! 1129: case XP_PRINTF_TYPE_UINT: ! 1130: s=ui; ! 1131: break; ! 1132: case XP_PRINTF_TYPE_LONG: ! 1133: s=l; ! 1134: break; ! 1135: case XP_PRINTF_TYPE_ULONG: ! 1136: s=ul; ! 1137: break; ! 1138: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1139: case XP_PRINTF_TYPE_LONGLONG: ! 1140: s=ll; ! 1141: break; ! 1142: case XP_PRINTF_TYPE_ULONGLONG: ! 1143: s=ull; ! 1144: break; ! 1145: #endif ! 1146: case XP_PRINTF_TYPE_CHARP: ! 1147: s=strtol(cp, NULL, 0); /* was strtoll */ ! 1148: break; ! 1149: case XP_PRINTF_TYPE_DOUBLE: ! 1150: s=(size_t)d; ! 1151: break; ! 1152: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1153: s=(size_t)ld; ! 1154: break; ! 1155: case XP_PRINTF_TYPE_VOIDP: ! 1156: s=(size_t)pntr; ! 1157: break; ! 1158: case XP_PRINTF_TYPE_SIZET: ! 1159: s=s; ! 1160: break; ! 1161: } ! 1162: break; ! 1163: } ! 1164: type=correct_type; ! 1165: } ! 1166: } ! 1167: ! 1168: /* The next char is now the type... perform native sprintf() using it */ ! 1169: *(fmt++)=*p; ! 1170: *fmt=0; ! 1171: entry=entry_buf; ! 1172: switch(type) { ! 1173: case XP_PRINTF_TYPE_CHAR: /* Also includes char and short */ ! 1174: case XP_PRINTF_TYPE_INT: /* Also includes char and short */ ! 1175: j=sprintf(entry, this_format, i); ! 1176: break; ! 1177: case XP_PRINTF_TYPE_UINT: /* Also includes char and short */ ! 1178: j=sprintf(entry, this_format, ui); ! 1179: break; ! 1180: case XP_PRINTF_TYPE_LONG: ! 1181: j=sprintf(entry, this_format, l); ! 1182: break; ! 1183: case XP_PRINTF_TYPE_ULONG: ! 1184: j=sprintf(entry, this_format, ul); ! 1185: break; ! 1186: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1187: case XP_PRINTF_TYPE_LONGLONG: ! 1188: j=sprintf(entry, this_format, ll); ! 1189: break; ! 1190: case XP_PRINTF_TYPE_ULONGLONG: ! 1191: j=sprintf(entry, this_format, ull); ! 1192: break; ! 1193: #endif ! 1194: case XP_PRINTF_TYPE_CHARP: ! 1195: if(cp==NULL) ! 1196: j=sprintf(entry, this_format, "<null>"); ! 1197: else { ! 1198: s=strlen(cp); ! 1199: if(s<width) ! 1200: s=width; ! 1201: if(s<precision) ! 1202: s=precision; ! 1203: if(s>=MAX_ARG_LEN) ! 1204: entry=(char *)alloca(s+1); ! 1205: if(entry==NULL) ! 1206: return(NULL); ! 1207: j=sprintf(entry, this_format, cp); ! 1208: } ! 1209: break; ! 1210: case XP_PRINTF_TYPE_DOUBLE: ! 1211: j=sprintf(entry, this_format, d); ! 1212: break; ! 1213: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1214: j=sprintf(entry, this_format, ld); ! 1215: break; ! 1216: case XP_PRINTF_TYPE_VOIDP: ! 1217: j=sprintf(entry, this_format, pntr); ! 1218: break; ! 1219: case XP_PRINTF_TYPE_SIZET: ! 1220: j=sprintf(entry, this_format, s); ! 1221: break; ! 1222: } ! 1223: ! 1224: this_format_len=strlen(this_format); ! 1225: if(j>=0) { ! 1226: /* ! 1227: * This isn't necessary if it's already the right size, ! 1228: * or it's too large... this realloc() should only need to grow ! 1229: * the string. ! 1230: */ ! 1231: if(format_len < (format_len-this_format_len+j)) { ! 1232: newbuf=(char *)realloc(format, format_len-this_format_len+j); ! 1233: if(newbuf==NULL) ! 1234: return(NULL); ! 1235: format=newbuf; ! 1236: } ! 1237: /* Move trailing end to make space */ ! 1238: memmove(format+offset+j, format+offset+this_format_len, format_len-offset-this_format_len); ! 1239: memcpy(format+offset, entry, j); ! 1240: p=format+offset+j; ! 1241: } ! 1242: else ! 1243: p=format+offset+this_format_len; ! 1244: ! 1245: *(size_t *)(format+sizeof(size_t))=format_len-this_format_len+j-sizeof(size_t)*2-1; ! 1246: ! 1247: /* ! 1248: * Search for next non-%% separateor and set offset ! 1249: * to zero if none found for wrappers to know when ! 1250: * they're done. ! 1251: */ ! 1252: for(; *p; p++) { ! 1253: if(*p=='%') { ! 1254: if(*(p+1) == '%') ! 1255: p++; ! 1256: else ! 1257: break; ! 1258: } ! 1259: } ! 1260: if(!*p) ! 1261: *(size_t *)format=0; ! 1262: else ! 1263: *(size_t *)format=p-format; ! 1264: return(format); ! 1265: } ! 1266: ! 1267: char *xp_asprintf_start(const char *format) ! 1268: { ! 1269: char *ret; ! 1270: char *p; ! 1271: ! 1272: ret=(char *)malloc(strlen(format)+1+((sizeof(size_t)*2))); ! 1273: if(ret==NULL) ! 1274: return(NULL); ! 1275: /* Place current offset at the start of the buffer */ ! 1276: strcpy(ret+sizeof(size_t)*2,format); ! 1277: /* Place the current length after the offset */ ! 1278: *(size_t *)(ret+sizeof(size_t))=strlen(format); ! 1279: ! 1280: /* ! 1281: * Find the next non %% format, leaving %% as it is ! 1282: */ ! 1283: for(p=ret+sizeof(size_t)*2; *p; p++) { ! 1284: if(*p=='%') { ! 1285: if(*(p+1) == '%') ! 1286: p++; ! 1287: else ! 1288: break; ! 1289: } ! 1290: } ! 1291: if(!*p) ! 1292: *(size_t *)ret=0; ! 1293: else ! 1294: *(size_t *)ret=p-ret; ! 1295: return(ret); ! 1296: } ! 1297: ! 1298: char *xp_asprintf_end(char *format, size_t *lenret) ! 1299: { ! 1300: char *p; ! 1301: size_t len; ! 1302: size_t end_len; ! 1303: ! 1304: len=*(size_t *)(format+sizeof(size_t)); ! 1305: end_len=len; ! 1306: for(p=format+sizeof(size_t)*2; len; p++, len--) { ! 1307: if(*p=='%' && *(p+1)=='%') { ! 1308: memmove(p, p+1, len--); ! 1309: end_len--; ! 1310: } ! 1311: } ! 1312: memmove(format, format+sizeof(size_t)*2, end_len+1); ! 1313: if(lenret) ! 1314: *lenret=end_len; ! 1315: return(format); ! 1316: } ! 1317: ! 1318: char *xp_vasprintf(const char *format, va_list va) ! 1319: { ! 1320: char *working; ! 1321: char *next; ! 1322: int type; ! 1323: ! 1324: next=xp_asprintf_start(format); ! 1325: if(next==NULL) ! 1326: return(NULL); ! 1327: working=next; ! 1328: while(*(size_t *)working) { ! 1329: type=xp_printf_get_type(working); ! 1330: switch(type) { ! 1331: case 0: ! 1332: free(working); ! 1333: return(NULL); ! 1334: case XP_PRINTF_TYPE_CHAR: ! 1335: case XP_PRINTF_TYPE_INT: /* Also includes char and short */ ! 1336: next=xp_asprintf_next(working, type, va_arg(va, int)); ! 1337: break; ! 1338: case XP_PRINTF_TYPE_UINT: /* Also includes char and short */ ! 1339: next=xp_asprintf_next(working, type, va_arg(va, unsigned int)); ! 1340: break; ! 1341: case XP_PRINTF_TYPE_LONG: ! 1342: next=xp_asprintf_next(working, type, va_arg(va, long)); ! 1343: break; ! 1344: case XP_PRINTF_TYPE_ULONG: ! 1345: next=xp_asprintf_next(working, type, va_arg(va, unsigned long)); ! 1346: break; ! 1347: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1348: case XP_PRINTF_TYPE_LONGLONG: ! 1349: next=xp_asprintf_next(working, type, va_arg(va, long long)); ! 1350: break; ! 1351: case XP_PRINTF_TYPE_ULONGLONG: ! 1352: next=xp_asprintf_next(working, type, va_arg(va, unsigned long long)); ! 1353: break; ! 1354: #endif ! 1355: case XP_PRINTF_TYPE_CHARP: ! 1356: next=xp_asprintf_next(working, type, va_arg(va, char *)); ! 1357: break; ! 1358: case XP_PRINTF_TYPE_DOUBLE: ! 1359: next=xp_asprintf_next(working, type, va_arg(va, double)); ! 1360: break; ! 1361: case XP_PRINTF_TYPE_LONGDOUBLE: ! 1362: next=xp_asprintf_next(working, type, va_arg(va, long double)); ! 1363: break; ! 1364: case XP_PRINTF_TYPE_VOIDP: ! 1365: next=xp_asprintf_next(working, type, va_arg(va, void *)); ! 1366: break; ! 1367: case XP_PRINTF_TYPE_SIZET: ! 1368: next=xp_asprintf_next(working, type, va_arg(va, size_t)); ! 1369: break; ! 1370: } ! 1371: if(next==NULL) { ! 1372: free(working); ! 1373: return(NULL); ! 1374: } ! 1375: working=next; ! 1376: } ! 1377: next=xp_asprintf_end(working, NULL); ! 1378: if(next==NULL) { ! 1379: free(working); ! 1380: return(NULL); ! 1381: } ! 1382: return(next); ! 1383: } ! 1384: ! 1385: char *xp_asprintf(const char *format, ...) ! 1386: { ! 1387: char *ret; ! 1388: va_list va; ! 1389: ! 1390: va_start(va, format); ! 1391: ret=xp_vasprintf(format, va); ! 1392: va_end(va); ! 1393: return(ret); ! 1394: } ! 1395: ! 1396: #if defined(XP_PRINTF_TEST) ! 1397: ! 1398: int main(int argc, char *argv[]) ! 1399: { ! 1400: char *format; ! 1401: char *p; ! 1402: int i,j; ! 1403: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1404: long long L; ! 1405: #endif ! 1406: long l; ! 1407: char *cp; ! 1408: double d; ! 1409: float f; ! 1410: long double D; ! 1411: ! 1412: p=xp_asprintf("%%%%%*.*f %% %%%ss %cs %*.*lu",3,3,123.123456789,"%llutesting%",32,3,3,123); ! 1413: printf("%s\n",p); ! 1414: free(p); ! 1415: if(argc < 2) ! 1416: return(1); ! 1417: ! 1418: format=argv[1]; ! 1419: format=xp_asprintf_start(format); ! 1420: for(j=2; j<argc; j++) { ! 1421: switch(argv[j][0]) { ! 1422: case 'f': ! 1423: f=(float)atof(argv[j]+1); ! 1424: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_FLOAT,f); ! 1425: break; ! 1426: case 'd': ! 1427: d=atof(argv[j]+1); ! 1428: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_DOUBLE,d); ! 1429: break; ! 1430: case 'D': ! 1431: /* Don't know of a thing that converts a string to a long double */ ! 1432: D=atof(argv[j]+1); ! 1433: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_LONGDOUBLE,D); ! 1434: break; ! 1435: case 'i': ! 1436: i=atoi(argv[j]+1); ! 1437: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,i); ! 1438: break; ! 1439: case 'l': ! 1440: l=atol(argv[j]+1); ! 1441: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_LONG,l); ! 1442: break; ! 1443: #if defined(XP_PRINTF_TYPE_LONGLONG) ! 1444: case 'L': ! 1445: L=strtoll(argv[j]+1, NULL, 10); ! 1446: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_LONGLONG,L); ! 1447: break; ! 1448: #endif ! 1449: case 's': ! 1450: cp=argv[j]+1; ! 1451: p=xp_asprintf_next(format,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_CHARP,cp); ! 1452: break; ! 1453: } ! 1454: if(p==NULL) { ! 1455: printf("Failed converting on item after %s\n",format); ! 1456: return(1); ! 1457: } ! 1458: format=p; ! 1459: } ! 1460: p=xp_asprintf_end(format, NULL); ! 1461: printf("At end, value is: '%s'\n",p); ! 1462: free(p); ! 1463: } ! 1464: ! 1465: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.