| 238 | | //printf("flags = x%x\n", flags); |
|---|
| 239 | | int prepad = 0; |
|---|
| 240 | | int postpad = 0; |
|---|
| 241 | | int padding = field_width - (strlen(prefix) + s.length); |
|---|
| 242 | | if (padding > 0) |
|---|
| 243 | | { |
|---|
| 244 | | if (flags & FLdash) |
|---|
| 245 | | postpad = padding; |
|---|
| | 207 | bool vbit; |
|---|
| | 208 | ulong vnumber; |
|---|
| | 209 | char vchar; |
|---|
| | 210 | dchar vdchar; |
|---|
| | 211 | Object vobject; |
|---|
| | 212 | real vreal; |
|---|
| | 213 | creal vcreal; |
|---|
| | 214 | Mangle m2; |
|---|
| | 215 | int signed = 0; |
|---|
| | 216 | uint base = 10; |
|---|
| | 217 | int uc; |
|---|
| | 218 | char[ulong.sizeof * 8] tmpbuf; // long enough to print long in binary |
|---|
| | 219 | char* prefix = ""; |
|---|
| | 220 | string s; |
|---|
| | 221 | |
|---|
| | 222 | void putstr(char[] s) |
|---|
| | 223 | { |
|---|
| | 224 | //printf("flags = x%x\n", flags); |
|---|
| | 225 | int prepad = 0; |
|---|
| | 226 | int postpad = 0; |
|---|
| | 227 | int padding = field_width - (strlen(prefix) + s.length); |
|---|
| | 228 | if (padding > 0) |
|---|
| | 229 | { |
|---|
| | 230 | if (flags & FLdash) |
|---|
| | 231 | postpad = padding; |
|---|
| | 232 | else |
|---|
| | 233 | prepad = padding; |
|---|
| | 234 | } |
|---|
| | 235 | |
|---|
| | 236 | if (flags & FL0pad) |
|---|
| | 237 | { |
|---|
| | 238 | while (*prefix) |
|---|
| | 239 | putc(*prefix++); |
|---|
| | 240 | while (prepad--) |
|---|
| | 241 | putc('0'); |
|---|
| | 242 | } |
|---|
| | 243 | else |
|---|
| | 244 | { |
|---|
| | 245 | while (prepad--) |
|---|
| | 246 | putc(' '); |
|---|
| | 247 | while (*prefix) |
|---|
| | 248 | putc(*prefix++); |
|---|
| | 249 | } |
|---|
| | 250 | |
|---|
| | 251 | try { |
|---|
| | 252 | foreach (dchar c; s) |
|---|
| | 253 | putc(c); |
|---|
| | 254 | } catch (UnicodeException e) |
|---|
| | 255 | { foreach (char c; s) |
|---|
| | 256 | putc(c); |
|---|
| | 257 | } |
|---|
| | 258 | |
|---|
| | 259 | while (postpad--) |
|---|
| | 260 | putc(' '); |
|---|
| | 261 | } |
|---|
| | 262 | |
|---|
| | 263 | void putreal(real v) |
|---|
| | 264 | { |
|---|
| | 265 | //printf("putreal %Lg\n", vreal); |
|---|
| | 266 | |
|---|
| | 267 | switch (fc) |
|---|
| | 268 | { |
|---|
| | 269 | case 's': |
|---|
| | 270 | fc = 'g'; |
|---|
| | 271 | break; |
|---|
| | 272 | |
|---|
| | 273 | case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A': |
|---|
| | 274 | break; |
|---|
| | 275 | |
|---|
| | 276 | default: |
|---|
| | 277 | //printf("fc = '%c'\n", fc); |
|---|
| | 278 | Lerror: |
|---|
| | 279 | throw new FormatError("floating"); |
|---|
| | 280 | } |
|---|
| | 281 | version (DigitalMarsC) |
|---|
| | 282 | { |
|---|
| | 283 | int sl; |
|---|
| | 284 | char[] fbuf = tmpbuf; |
|---|
| | 285 | if (!(flags & FLprecision)) |
|---|
| | 286 | precision = 6; |
|---|
| | 287 | while (1) |
|---|
| | 288 | { |
|---|
| | 289 | sl = fbuf.length; |
|---|
| | 290 | prefix = (*__pfloatfmt)(fc, flags | FLlngdbl, |
|---|
| | 291 | precision, &v, cast(char*)fbuf, &sl, field_width); |
|---|
| | 292 | if (sl != -1) |
|---|
| | 293 | break; |
|---|
| | 294 | sl = fbuf.length * 2; |
|---|
| | 295 | fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; |
|---|
| | 296 | } |
|---|
| | 297 | putstr(fbuf[0 .. sl]); |
|---|
| | 298 | } |
|---|
| | 299 | else |
|---|
| | 300 | { |
|---|
| | 301 | int sl; |
|---|
| | 302 | char[] fbuf = tmpbuf; |
|---|
| | 303 | char[12] format; |
|---|
| | 304 | format[0] = '%'; |
|---|
| | 305 | int i = 1; |
|---|
| | 306 | if (flags & FLdash) |
|---|
| | 307 | format[i++] = '-'; |
|---|
| | 308 | if (flags & FLplus) |
|---|
| | 309 | format[i++] = '+'; |
|---|
| | 310 | if (flags & FLspace) |
|---|
| | 311 | format[i++] = ' '; |
|---|
| | 312 | if (flags & FLhash) |
|---|
| | 313 | format[i++] = '#'; |
|---|
| | 314 | if (flags & FL0pad) |
|---|
| | 315 | format[i++] = '0'; |
|---|
| | 316 | format[i + 0] = '*'; |
|---|
| | 317 | format[i + 1] = '.'; |
|---|
| | 318 | format[i + 2] = '*'; |
|---|
| | 319 | i += 3; |
|---|
| | 320 | version (GNU_MinGW_MSVCRT) |
|---|
| | 321 | { /* nothing: no support for long double */ } |
|---|
| | 322 | else |
|---|
| | 323 | static if (real.sizeof > double.sizeof) |
|---|
| | 324 | format[i++] = 'L'; |
|---|
| | 325 | format[i++] = fc; |
|---|
| | 326 | format[i] = 0; |
|---|
| | 327 | if (!(flags & FLprecision)) |
|---|
| | 328 | precision = -1; |
|---|
| | 329 | while (1) |
|---|
| | 330 | { int n; |
|---|
| | 331 | |
|---|
| | 332 | sl = fbuf.length; |
|---|
| | 333 | version (GNU_MinGW_MSVCRT) |
|---|
| | 334 | n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, cast(double) v); |
|---|
| | 335 | else |
|---|
| | 336 | n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); |
|---|
| | 337 | //printf("format = '%s', n = %d\n", cast(char*)format, n); |
|---|
| | 338 | if (n >= 0 && n < sl) |
|---|
| | 339 | { sl = n; |
|---|
| | 340 | break; |
|---|
| | 341 | } |
|---|
| | 342 | if (n < 0) |
|---|
| | 343 | sl = sl * 2; |
|---|
| | 344 | else |
|---|
| | 345 | sl = n + 1; |
|---|
| | 346 | fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; |
|---|
| | 347 | } |
|---|
| | 348 | putstr(fbuf[0 .. sl]); |
|---|
| | 349 | } |
|---|
| | 350 | return; |
|---|
| | 351 | } |
|---|
| | 352 | |
|---|
| | 353 | static Mangle getMan(TypeInfo ti) |
|---|
| | 354 | { |
|---|
| | 355 | auto m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| | 356 | if (ti.classinfo.name.length == 20 && |
|---|
| | 357 | ti.classinfo.name[9..20] == "StaticArray") |
|---|
| | 358 | m = cast(Mangle)'G'; |
|---|
| | 359 | return m; |
|---|
| | 360 | } |
|---|
| | 361 | |
|---|
| | 362 | void putArray(void* p, size_t len, TypeInfo valti) |
|---|
| | 363 | { |
|---|
| | 364 | putc('['); |
|---|
| | 365 | size_t tsize = valti.tsize(); |
|---|
| | 366 | version(DigitalMars) |
|---|
| | 367 | auto argptrSave = argptr; |
|---|
| | 368 | else |
|---|
| | 369 | auto argptrSave = p_args; |
|---|
| | 370 | auto tiSave = ti; |
|---|
| | 371 | auto mSave = m; |
|---|
| | 372 | ti = valti; |
|---|
| | 373 | m = getMan(valti); |
|---|
| | 374 | while (len--) |
|---|
| | 375 | { |
|---|
| | 376 | version (DigitalMars) |
|---|
| | 377 | argptr = cast(void*) p; |
|---|
| | 378 | else |
|---|
| | 379 | p_args = p; |
|---|
| | 380 | formatArg('s'); |
|---|
| | 381 | |
|---|
| | 382 | p += tsize; |
|---|
| | 383 | if (len > 0) putc(','); |
|---|
| | 384 | } |
|---|
| | 385 | m = mSave; |
|---|
| | 386 | ti = tiSave; |
|---|
| | 387 | version (DigitalMars) |
|---|
| | 388 | argptr = argptrSave; |
|---|
| | 389 | else |
|---|
| | 390 | p_args = argptrSave; |
|---|
| | 391 | putc(']'); |
|---|
| | 392 | } |
|---|
| | 393 | |
|---|
| | 394 | void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti) |
|---|
| | 395 | { |
|---|
| | 396 | // Copied from aaA.d |
|---|
| | 397 | size_t aligntsize(size_t tsize) |
|---|
| | 398 | { |
|---|
| | 399 | // Is pointer alignment on the x64 4 bytes or 8? |
|---|
| | 400 | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| | 401 | } |
|---|
| | 402 | |
|---|
| | 403 | putc('['); |
|---|
| | 404 | bool comma=false; |
|---|
| | 405 | version (DigitalMars) |
|---|
| | 406 | auto argptrSave = argptr; |
|---|
| | 407 | else |
|---|
| | 408 | auto argptrSave = p_args; |
|---|
| | 409 | auto tiSave = ti; |
|---|
| | 410 | auto mSave = m; |
|---|
| | 411 | foreach(inout fakevalue; vaa) |
|---|
| | 412 | { |
|---|
| | 413 | if (comma) putc(','); |
|---|
| | 414 | comma = true; |
|---|
| | 415 | // the key comes before the value |
|---|
| | 416 | ubyte* key = &fakevalue - long.sizeof; |
|---|
| | 417 | |
|---|
| | 418 | version (DigitalMars) |
|---|
| | 419 | argptr = cast(void*) key; |
|---|
| | 420 | else |
|---|
| | 421 | p_args = key; |
|---|
| | 422 | ti = keyti; |
|---|
| | 423 | m = getMan(keyti); |
|---|
| | 424 | formatArg('s'); |
|---|
| | 425 | |
|---|
| | 426 | putc(':'); |
|---|
| | 427 | ubyte* value = key + aligntsize(keyti.tsize); |
|---|
| | 428 | version (DigitalMars) |
|---|
| | 429 | argptr = cast(void*) value; |
|---|
| | 430 | else |
|---|
| | 431 | p_args = value; |
|---|
| | 432 | ti = valti; |
|---|
| | 433 | m = getMan(valti); |
|---|
| | 434 | formatArg('s'); |
|---|
| | 435 | } |
|---|
| | 436 | m = mSave; |
|---|
| | 437 | ti = tiSave; |
|---|
| | 438 | version (DigitalMars) |
|---|
| | 439 | argptr = argptrSave; |
|---|
| | 440 | else |
|---|
| | 441 | p_args = argptrSave; |
|---|
| | 442 | putc(']'); |
|---|
| | 443 | } |
|---|
| | 444 | |
|---|
| | 445 | if (! p_args) { |
|---|
| | 446 | switch (m) |
|---|
| | 447 | { |
|---|
| | 448 | case Mangle.Tbool: |
|---|
| | 449 | vbit = va_arg!(bool)(argptr); |
|---|
| | 450 | if (fc != 's') |
|---|
| | 451 | { vnumber = vbit; |
|---|
| | 452 | goto Lnumber; |
|---|
| | 453 | } |
|---|
| | 454 | putstr(vbit ? "true" : "false"); |
|---|
| | 455 | return; |
|---|
| | 456 | |
|---|
| | 457 | case Mangle.Tchar: |
|---|
| | 458 | vchar = va_arg!(char)(argptr); |
|---|
| | 459 | if (fc != 's') |
|---|
| | 460 | { vnumber = vchar; |
|---|
| | 461 | goto Lnumber; |
|---|
| | 462 | } |
|---|
| | 463 | L2: |
|---|
| | 464 | putstr((&vchar)[0 .. 1]); |
|---|
| | 465 | return; |
|---|
| | 466 | |
|---|
| | 467 | case Mangle.Twchar: |
|---|
| | 468 | vdchar = va_arg!(wchar)(argptr); |
|---|
| | 469 | goto L1; |
|---|
| | 470 | |
|---|
| | 471 | case Mangle.Tdchar: |
|---|
| | 472 | vdchar = va_arg!(dchar)(argptr); |
|---|
| | 473 | L1: |
|---|
| | 474 | if (fc != 's') |
|---|
| | 475 | { vnumber = vdchar; |
|---|
| | 476 | goto Lnumber; |
|---|
| | 477 | } |
|---|
| | 478 | if (vdchar <= 0x7F) |
|---|
| | 479 | { vchar = cast(char)vdchar; |
|---|
| | 480 | goto L2; |
|---|
| | 481 | } |
|---|
| | 482 | else |
|---|
| | 483 | { if (!isValid(vdchar)) |
|---|
| | 484 | throw new Exception("invalid dchar in format"); |
|---|
| | 485 | putstr(.toString([vdchar])); |
|---|
| | 486 | } |
|---|
| | 487 | return; |
|---|
| | 488 | |
|---|
| | 489 | case Mangle.Tbyte: |
|---|
| | 490 | signed = 1; |
|---|
| | 491 | vnumber = va_arg!(byte)(argptr); |
|---|
| | 492 | goto Lnumber; |
|---|
| | 493 | |
|---|
| | 494 | case Mangle.Tubyte: |
|---|
| | 495 | vnumber = va_arg!(ubyte)(argptr); |
|---|
| | 496 | goto Lnumber; |
|---|
| | 497 | |
|---|
| | 498 | case Mangle.Tshort: |
|---|
| | 499 | signed = 1; |
|---|
| | 500 | vnumber = va_arg!(short)(argptr); |
|---|
| | 501 | goto Lnumber; |
|---|
| | 502 | |
|---|
| | 503 | case Mangle.Tushort: |
|---|
| | 504 | vnumber = va_arg!(ushort)(argptr); |
|---|
| | 505 | goto Lnumber; |
|---|
| | 506 | |
|---|
| | 507 | case Mangle.Tint: |
|---|
| | 508 | signed = 1; |
|---|
| | 509 | vnumber = va_arg!(int)(argptr); |
|---|
| | 510 | goto Lnumber; |
|---|
| | 511 | |
|---|
| | 512 | case Mangle.Tuint: |
|---|
| | 513 | Luint: |
|---|
| | 514 | vnumber = va_arg!(uint)(argptr); |
|---|
| | 515 | goto Lnumber; |
|---|
| | 516 | |
|---|
| | 517 | case Mangle.Tlong: |
|---|
| | 518 | signed = 1; |
|---|
| | 519 | vnumber = cast(ulong)va_arg!(long)(argptr); |
|---|
| | 520 | goto Lnumber; |
|---|
| | 521 | |
|---|
| | 522 | case Mangle.Tulong: |
|---|
| | 523 | Lulong: |
|---|
| | 524 | vnumber = va_arg!(ulong)(argptr); |
|---|
| | 525 | goto Lnumber; |
|---|
| | 526 | |
|---|
| | 527 | case Mangle.Tclass: |
|---|
| | 528 | vobject = va_arg!(Object)(argptr); |
|---|
| | 529 | if (vobject is null) |
|---|
| | 530 | s = "null"; |
|---|
| | 531 | else |
|---|
| | 532 | s = vobject.toString(); |
|---|
| | 533 | goto Lputstr; |
|---|
| | 534 | |
|---|
| | 535 | case Mangle.Tpointer: |
|---|
| | 536 | vnumber = cast(size_t)va_arg!(void*)(argptr); |
|---|
| | 537 | uc = 1; |
|---|
| | 538 | flags |= FL0pad; |
|---|
| | 539 | if (!(flags & FLprecision)) |
|---|
| | 540 | { flags |= FLprecision; |
|---|
| | 541 | precision = (void*).sizeof; |
|---|
| | 542 | } |
|---|
| | 543 | base = 16; |
|---|
| | 544 | goto Lnumber; |
|---|
| | 545 | |
|---|
| | 546 | case Mangle.Tfloat: |
|---|
| | 547 | case Mangle.Tifloat: |
|---|
| | 548 | if (fc == 'x' || fc == 'X') |
|---|
| | 549 | { |
|---|
| | 550 | version (DigitalMars) |
|---|
| | 551 | goto Luint; |
|---|
| | 552 | else { |
|---|
| | 553 | float f = va_arg!(float)(argptr); |
|---|
| | 554 | vnumber = *cast(uint*)&f; |
|---|
| | 555 | goto Lnumber; |
|---|
| | 556 | } |
|---|
| | 557 | } |
|---|
| | 558 | vreal = va_arg!(float)(argptr); |
|---|
| | 559 | goto Lreal; |
|---|
| | 560 | |
|---|
| | 561 | case Mangle.Tdouble: |
|---|
| | 562 | case Mangle.Tidouble: |
|---|
| | 563 | if (fc == 'x' || fc == 'X') |
|---|
| | 564 | { |
|---|
| | 565 | version (DigitalMars) |
|---|
| | 566 | goto Lulong; |
|---|
| | 567 | else { |
|---|
| | 568 | double f = va_arg!(double)(argptr); |
|---|
| | 569 | vnumber = *cast(ulong*)&f; |
|---|
| | 570 | goto Lnumber; |
|---|
| | 571 | } |
|---|
| | 572 | } |
|---|
| | 573 | vreal = va_arg!(double)(argptr); |
|---|
| | 574 | goto Lreal; |
|---|
| | 575 | |
|---|
| | 576 | case Mangle.Treal: |
|---|
| | 577 | case Mangle.Tireal: |
|---|
| | 578 | vreal = va_arg!(real)(argptr); |
|---|
| | 579 | goto Lreal; |
|---|
| | 580 | |
|---|
| | 581 | case Mangle.Tcfloat: |
|---|
| | 582 | vcreal = va_arg!(cfloat)(argptr); |
|---|
| | 583 | goto Lcomplex; |
|---|
| | 584 | |
|---|
| | 585 | case Mangle.Tcdouble: |
|---|
| | 586 | vcreal = va_arg!(cdouble)(argptr); |
|---|
| | 587 | goto Lcomplex; |
|---|
| | 588 | |
|---|
| | 589 | case Mangle.Tcreal: |
|---|
| | 590 | vcreal = va_arg!(creal)(argptr); |
|---|
| | 591 | goto Lcomplex; |
|---|
| | 592 | |
|---|
| | 593 | case Mangle.Tsarray: |
|---|
| | 594 | version (DigitalMars) { |
|---|
| | 595 | putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); |
|---|
| | 596 | return; |
|---|
| | 597 | } |
|---|
| | 598 | version (GNU) { |
|---|
| | 599 | /* Static arrays are converted to dynamic arrays when |
|---|
| | 600 | passed as a variadic argument, so this code should |
|---|
| | 601 | never be executed with GDC. The case of an |
|---|
| | 602 | embedded static array is handled below. */ |
|---|
| | 603 | goto Lerror; |
|---|
| | 604 | } |
|---|
| | 605 | |
|---|
| | 606 | case Mangle.Tarray: |
|---|
| | 607 | int mi = 10; |
|---|
| | 608 | if (ti.classinfo.name.length == 14 && ti.classinfo.name[9..14] == "Array") |
|---|
| | 609 | { // array of non-primitive types |
|---|
| | 610 | TypeInfo tn = (cast(TypeInfo_Array)ti).next; |
|---|
| | 611 | switch (cast(Mangle)tn.classinfo.name[9]) |
|---|
| | 612 | { |
|---|
| | 613 | case Mangle.Tchar: goto LarrayChar; |
|---|
| | 614 | case Mangle.Twchar: goto LarrayWchar; |
|---|
| | 615 | case Mangle.Tdchar: goto LarrayDchar; |
|---|
| | 616 | default: |
|---|
| | 617 | break; |
|---|
| | 618 | } |
|---|
| | 619 | void[] va = va_arg!(void[])(argptr); |
|---|
| | 620 | putArray(va.ptr, va.length, tn); |
|---|
| | 621 | return; |
|---|
| | 622 | } |
|---|
| | 623 | if (ti.classinfo.name.length == 25 && |
|---|
| | 624 | ti.classinfo.name[9..25] == "AssociativeArray") |
|---|
| | 625 | { // associative array |
|---|
| | 626 | ubyte[long] vaa = va_arg!(ubyte[long])(argptr); |
|---|
| | 627 | putAArray(vaa, |
|---|
| | 628 | (cast(TypeInfo_AssociativeArray)ti).next, |
|---|
| | 629 | (cast(TypeInfo_AssociativeArray)ti).key); |
|---|
| | 630 | return; |
|---|
| | 631 | } |
|---|
| | 632 | |
|---|
| | 633 | while (1) |
|---|
| | 634 | { |
|---|
| | 635 | m2 = cast(Mangle)ti.classinfo.name[mi]; |
|---|
| | 636 | switch (m2) |
|---|
| | 637 | { |
|---|
| | 638 | case Mangle.Tchar: |
|---|
| | 639 | LarrayChar: |
|---|
| | 640 | s = va_arg!(char[])(argptr); |
|---|
| | 641 | goto Lputstr; |
|---|
| | 642 | |
|---|
| | 643 | case Mangle.Twchar: |
|---|
| | 644 | LarrayWchar: |
|---|
| | 645 | wchar[] sw = va_arg!(wchar[])(argptr); |
|---|
| | 646 | s = .toString(sw); |
|---|
| | 647 | goto Lputstr; |
|---|
| | 648 | |
|---|
| | 649 | case Mangle.Tdchar: |
|---|
| | 650 | LarrayDchar: |
|---|
| | 651 | dchar[] sd = va_arg!(dchar[])(argptr); |
|---|
| | 652 | s = .toString(sd); |
|---|
| | 653 | Lputstr: |
|---|
| | 654 | if (fc != 's') |
|---|
| | 655 | throw new FormatError("string"); |
|---|
| | 656 | if (flags & FLprecision && precision < s.length) |
|---|
| | 657 | s = s[0 .. precision]; |
|---|
| | 658 | putstr(s); |
|---|
| | 659 | break; |
|---|
| | 660 | |
|---|
| | 661 | case Mangle.Tconst: |
|---|
| | 662 | case Mangle.Tinvariant: |
|---|
| | 663 | mi++; |
|---|
| | 664 | continue; |
|---|
| | 665 | |
|---|
| | 666 | default: |
|---|
| | 667 | TypeInfo ti2 = primitiveTypeInfo(m2); |
|---|
| | 668 | if (!ti2) |
|---|
| | 669 | throw new FormatError("Can't get type info for type " ~ cast(char)m2); |
|---|
| | 670 | void[] va = va_arg!(void[])(argptr); |
|---|
| | 671 | putArray(va.ptr, va.length, ti2); |
|---|
| | 672 | } |
|---|
| | 673 | return; |
|---|
| | 674 | } |
|---|
| | 675 | case Mangle.Ttypedef: |
|---|
| | 676 | ti = (cast(TypeInfo_Typedef)ti).base; |
|---|
| | 677 | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| | 678 | formatArg(fc); |
|---|
| | 679 | return; |
|---|
| | 680 | |
|---|
| | 681 | case Mangle.Tenum: |
|---|
| | 682 | ti = (cast(TypeInfo_Enum)ti).base; |
|---|
| | 683 | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| | 684 | formatArg(fc); |
|---|
| | 685 | return; |
|---|
| | 686 | |
|---|
| | 687 | case Mangle.Tstruct: |
|---|
| | 688 | { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; |
|---|
| | 689 | if (tis.xtoString is null) |
|---|
| | 690 | throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); |
|---|
| | 691 | version(DigitalMars){ |
|---|
| | 692 | |
|---|
| | 693 | char[] delegate() toString; |
|---|
| | 694 | toString.ptr = argptr; |
|---|
| | 695 | toString.funcptr = cast(char[] function())tis.xtoString; |
|---|
| | 696 | s = Utf.fromString8 (toString(), s); |
|---|
| | 697 | // s = tis.xtoString(argptr); |
|---|
| | 698 | |
|---|
| | 699 | argptr += (tis.tsize() + 3) & ~3; |
|---|
| | 700 | } |
|---|
| | 701 | version (GNU){ |
|---|
| | 702 | static if (is( typeof(argptr): void[] ) || is( typeof(argptr) == struct )) |
|---|
| | 703 | { |
|---|
| | 704 | version(PPC) |
|---|
| | 705 | { |
|---|
| | 706 | // Structs are pass-by-reference in V4 ABI |
|---|
| | 707 | s = tis.xtoString(va_arg!(void*)(argptr)); |
|---|
| | 708 | } |
|---|
| | 709 | else version(X86_64) |
|---|
| | 710 | { |
|---|
| | 711 | throw new FormatError("cannot portably format a struct on this target"); |
|---|
| | 712 | } |
|---|
| | 713 | else |
|---|
| | 714 | { |
|---|
| | 715 | static assert(0, "unimplemented"); |
|---|
| | 716 | } |
|---|
| | 717 | } |
|---|
| | 718 | else |
|---|
| | 719 | { |
|---|
| | 720 | s = tis.xtoString(argptr); |
|---|
| | 721 | argptr += (tis.tsize() + 3) & ~3; // this looks like it should call aligntsize |
|---|
| | 722 | } |
|---|
| | 723 | } |
|---|
| | 724 | goto Lputstr; |
|---|
| | 725 | } |
|---|
| | 726 | |
|---|
| | 727 | default: |
|---|
| | 728 | if (m2=='v') |
|---|
| | 729 | throw new FormatError("Can't get type info for type void"); |
|---|
| | 730 | else |
|---|
| | 731 | throw new FormatError("Can't get type info for mangled type " ~ cast(char)m2); |
|---|
| | 732 | }} |
|---|
| 247 | | prepad = padding; |
|---|
| 248 | | } |
|---|
| 249 | | |
|---|
| 250 | | if (flags & FL0pad) |
|---|
| 251 | | { |
|---|
| 252 | | while (*prefix) |
|---|
| 253 | | putc(*prefix++); |
|---|
| 254 | | while (prepad--) |
|---|
| 255 | | putc('0'); |
|---|
| 256 | | } |
|---|
| 257 | | else |
|---|
| 258 | | { |
|---|
| 259 | | while (prepad--) |
|---|
| 260 | | putc(' '); |
|---|
| 261 | | while (*prefix) |
|---|
| 262 | | putc(*prefix++); |
|---|
| 263 | | } |
|---|
| 264 | | |
|---|
| 265 | | try { |
|---|
| 266 | | foreach (dchar c; s) |
|---|
| 267 | | putc(c); |
|---|
| 268 | | } catch (UnicodeException e) |
|---|
| 269 | | { foreach (char c; s) |
|---|
| 270 | | putc(c); |
|---|
| 271 | | } |
|---|
| 272 | | |
|---|
| 273 | | while (postpad--) |
|---|
| 274 | | putc(' '); |
|---|
| | 734 | { |
|---|
| | 735 | version (DigitalMars) assert(0); |
|---|
| | 736 | switch (m) |
|---|
| | 737 | { |
|---|
| | 738 | case Mangle.Tbool: |
|---|
| | 739 | vbit = *cast(bool*)(p_args); p_args += bool.sizeof; // int.sizeof, etc.? |
|---|
| | 740 | if (fc != 's') |
|---|
| | 741 | { vnumber = vbit; |
|---|
| | 742 | goto Lnumber; |
|---|
| | 743 | } |
|---|
| | 744 | putstr(vbit ? "true" : "false"); |
|---|
| | 745 | return; |
|---|
| | 746 | |
|---|
| | 747 | |
|---|
| | 748 | case Mangle.Tchar: |
|---|
| | 749 | vchar = *cast(char*)(p_args); p_args += char.sizeof; |
|---|
| | 750 | if (fc != 's') |
|---|
| | 751 | { vnumber = vchar; |
|---|
| | 752 | goto Lnumber; |
|---|
| | 753 | } |
|---|
| | 754 | PL2: // there is goto L2 outside of thise switch; it's okay to do that |
|---|
| | 755 | putstr((&vchar)[0 .. 1]); |
|---|
| | 756 | return; |
|---|
| | 757 | |
|---|
| | 758 | case Mangle.Twchar: |
|---|
| | 759 | vdchar = *cast(wchar*)(p_args); p_args += wchar.sizeof; |
|---|
| | 760 | goto PL1; |
|---|
| | 761 | |
|---|
| | 762 | case Mangle.Tdchar: |
|---|
| | 763 | vdchar = *cast(dchar*)(p_args); p_args += dchar.sizeof; |
|---|
| | 764 | PL1: |
|---|
| | 765 | if (fc != 's') |
|---|
| | 766 | { vnumber = vdchar; |
|---|
| | 767 | goto Lnumber; |
|---|
| | 768 | } |
|---|
| | 769 | if (vdchar <= 0x7F) |
|---|
| | 770 | { vchar = cast(char)vdchar; |
|---|
| | 771 | goto PL2; |
|---|
| | 772 | } |
|---|
| | 773 | else |
|---|
| | 774 | { if (!isValid(vdchar)) |
|---|
| | 775 | throw new Exception("invalid dchar in format"); |
|---|
| | 776 | putstr(.toString([vdchar])); |
|---|
| | 777 | } |
|---|
| | 778 | return; |
|---|
| | 779 | |
|---|
| | 780 | |
|---|
| | 781 | case Mangle.Tbyte: |
|---|
| | 782 | signed = 1; |
|---|
| | 783 | vnumber = *cast(byte*)p_args; p_args += byte.sizeof; |
|---|
| | 784 | goto Lnumber; |
|---|
| | 785 | |
|---|
| | 786 | case Mangle.Tubyte: |
|---|
| | 787 | vnumber = *cast(ubyte*)p_args; p_args += ubyte.sizeof; |
|---|
| | 788 | goto Lnumber; |
|---|
| | 789 | |
|---|
| | 790 | case Mangle.Tshort: |
|---|
| | 791 | signed = 1; |
|---|
| | 792 | vnumber = *cast(short*)p_args; p_args += short.sizeof; |
|---|
| | 793 | goto Lnumber; |
|---|
| | 794 | |
|---|
| | 795 | case Mangle.Tushort: |
|---|
| | 796 | vnumber = *cast(ushort*)p_args; p_args += ushort.sizeof; |
|---|
| | 797 | goto Lnumber; |
|---|
| | 798 | |
|---|
| | 799 | case Mangle.Tint: |
|---|
| | 800 | signed = 1; |
|---|
| | 801 | vnumber = *cast(int*)p_args; p_args += int.sizeof; |
|---|
| | 802 | goto Lnumber; |
|---|
| | 803 | |
|---|
| | 804 | case Mangle.Tuint: |
|---|
| | 805 | PLuint: |
|---|
| | 806 | vnumber = *cast(uint*)p_args; p_args += uint.sizeof; |
|---|
| | 807 | goto Lnumber; |
|---|
| | 808 | |
|---|
| | 809 | case Mangle.Tlong: |
|---|
| | 810 | signed = 1; |
|---|
| | 811 | vnumber = cast(ulong)*cast(long*)p_args; p_args += long.sizeof; |
|---|
| | 812 | goto Lnumber; |
|---|
| | 813 | |
|---|
| | 814 | case Mangle.Tulong: |
|---|
| | 815 | PLulong: |
|---|
| | 816 | vnumber = *cast(ulong*)p_args; p_args += ulong.sizeof; |
|---|
| | 817 | goto Lnumber; |
|---|
| | 818 | |
|---|
| | 819 | case Mangle.Tclass: |
|---|
| | 820 | vobject = *cast(Object*)p_args; p_args += Object.sizeof; |
|---|
| | 821 | s = vobject.toString(); |
|---|
| | 822 | goto Lputstr; |
|---|
| | 823 | |
|---|
| | 824 | case Mangle.Tpointer: |
|---|
| | 825 | alias void * void_ponter_t; |
|---|
| | 826 | vnumber = cast(size_t)*cast(void**)p_args; p_args += void_ponter_t.sizeof; |
|---|
| | 827 | uc = 1; |
|---|
| | 828 | flags |= FL0pad; |
|---|
| | 829 | if (!(flags & FLprecision)) |
|---|
| | 830 | { flags |= FLprecision; |
|---|
| | 831 | precision = (void*).sizeof; |
|---|
| | 832 | } |
|---|
| | 833 | base = 16; |
|---|
| | 834 | goto Lnumber; |
|---|
| | 835 | |
|---|
| | 836 | |
|---|
| | 837 | case Mangle.Tfloat: |
|---|
| | 838 | case Mangle.Tifloat: |
|---|
| | 839 | if (fc == 'x' || fc == 'X') |
|---|
| | 840 | goto PLuint; |
|---|
| | 841 | vreal = *cast(float*)p_args; p_args += float.sizeof; |
|---|
| | 842 | goto Lreal; |
|---|
| | 843 | |
|---|
| | 844 | case Mangle.Tdouble: |
|---|
| | 845 | case Mangle.Tidouble: |
|---|
| | 846 | if (fc == 'x' || fc == 'X') |
|---|
| | 847 | goto PLulong; |
|---|
| | 848 | vreal = *cast(double*)p_args; p_args += double.sizeof; |
|---|
| | 849 | goto Lreal; |
|---|
| | 850 | |
|---|
| | 851 | case Mangle.Treal: |
|---|
| | 852 | case Mangle.Tireal: |
|---|
| | 853 | vreal = *cast(real*)p_args; p_args += real.sizeof; |
|---|
| | 854 | goto Lreal; |
|---|
| | 855 | |
|---|
| | 856 | |
|---|
| | 857 | case Mangle.Tcfloat: |
|---|
| | 858 | vcreal = *cast(cfloat*)p_args; p_args += cfloat.sizeof; |
|---|
| | 859 | goto Lcomplex; |
|---|
| | 860 | |
|---|
| | 861 | case Mangle.Tcdouble: |
|---|
| | 862 | vcreal = *cast(cdouble*)p_args; p_args += cdouble.sizeof; |
|---|
| | 863 | goto Lcomplex; |
|---|
| | 864 | |
|---|
| | 865 | case Mangle.Tcreal: |
|---|
| | 866 | vcreal = *cast(creal*)p_args; p_args += creal.sizeof; |
|---|
| | 867 | goto Lcomplex; |
|---|
| | 868 | |
|---|
| | 869 | case Mangle.Tsarray: |
|---|
| | 870 | putArray(p_args, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); |
|---|
| | 871 | p_args += ti.tsize(); |
|---|
| | 872 | return; |
|---|
| | 873 | |
|---|
| | 874 | case Mangle.Tarray: |
|---|
| | 875 | alias void[] array_t; |
|---|
| | 876 | int mi = 10; |
|---|
| | 877 | if (ti.classinfo.name.length == 14 && |
|---|
| | 878 | ti.classinfo.name[9..14] == "Array") |
|---|
| | 879 | { // array of non-primitive types |
|---|
| | 880 | TypeInfo tn = (cast(TypeInfo_Array)ti).next; |
|---|
| | 881 | switch (cast(Mangle)tn.classinfo.name[9]) |
|---|
| | 882 | { |
|---|
| | 883 | case Mangle.Tchar: goto LarrayChar_p; |
|---|
| | 884 | case Mangle.Twchar: goto LarrayWchar_p; |
|---|
| | 885 | case Mangle.Tdchar: goto LarrayDchar_p; |
|---|
| | 886 | default: |
|---|
| | 887 | break; |
|---|
| | 888 | } |
|---|
| | 889 | void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; |
|---|
| | 890 | putArray(va.ptr, va.length, tn); |
|---|
| | 891 | return; |
|---|
| | 892 | } |
|---|
| | 893 | if (ti.classinfo.name.length == 25 && |
|---|
| | 894 | ti.classinfo.name[9..25] == "AssociativeArray") |
|---|
| | 895 | { // associative array |
|---|
| | 896 | ubyte[long] vaa = *cast(ubyte[long]*)p_args; p_args += vaa.sizeof; |
|---|
| | 897 | putAArray(vaa, |
|---|
| | 898 | (cast(TypeInfo_AssociativeArray)ti).next, |
|---|
| | 899 | (cast(TypeInfo_AssociativeArray)ti).key); |
|---|
| | 900 | return; |
|---|
| | 901 | } |
|---|
| | 902 | |
|---|
| | 903 | while (1) |
|---|
| | 904 | { |
|---|
| | 905 | m2 = cast(Mangle)ti.classinfo.name[mi]; |
|---|
| | 906 | switch (m2) |
|---|
| | 907 | { |
|---|
| | 908 | case Mangle.Tchar: |
|---|
| | 909 | LarrayChar_p: |
|---|
| | 910 | s = *cast(char[]*)p_args; p_args += array_t.sizeof; |
|---|
| | 911 | goto PLputstr; |
|---|
| | 912 | |
|---|
| | 913 | case Mangle.Twchar: |
|---|
| | 914 | LarrayWchar_p: |
|---|
| | 915 | wchar[] sw = *cast(wchar[]*)p_args; p_args += array_t.sizeof; |
|---|
| | 916 | s = .toString(sw); |
|---|
| | 917 | goto PLputstr; |
|---|
| | 918 | |
|---|
| | 919 | case Mangle.Tdchar: |
|---|
| | 920 | LarrayDchar_p: |
|---|
| | 921 | dchar[] sd = *cast(dchar[]*)p_args; p_args += array_t.sizeof; |
|---|
| | 922 | s = .toString(sd); |
|---|
| | 923 | PLputstr: |
|---|
| | 924 | if (fc != 's') |
|---|
| | 925 | throw new FormatError("string"); |
|---|
| | 926 | if (flags & FLprecision && precision < s.length) |
|---|
| | 927 | s = s[0 .. precision]; |
|---|
| | 928 | putstr(s); |
|---|
| | 929 | break; |
|---|
| | 930 | |
|---|
| | 931 | case Mangle.Tconst: |
|---|
| | 932 | case Mangle.Tinvariant: |
|---|
| | 933 | mi++; |
|---|
| | 934 | continue; |
|---|
| | 935 | |
|---|
| | 936 | default: |
|---|
| | 937 | TypeInfo ti2 = primitiveTypeInfo(m2); |
|---|
| | 938 | if (!ti2) |
|---|
| | 939 | throw new FormatError("Can't get type info for type " ~ cast(char)m2); |
|---|
| | 940 | void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; |
|---|
| | 941 | putArray(va.ptr, va.length, ti2); |
|---|
| | 942 | } |
|---|
| | 943 | return; |
|---|
| | 944 | } |
|---|
| | 945 | |
|---|
| | 946 | case Mangle.Ttypedef: |
|---|
| | 947 | ti = (cast(TypeInfo_Typedef)ti).base; |
|---|
| | 948 | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| | 949 | formatArg(fc); |
|---|
| | 950 | return; |
|---|
| | 951 | |
|---|
| | 952 | case Mangle.Tenum: |
|---|
| | 953 | ti = (cast(TypeInfo_Enum)ti).base; |
|---|
| | 954 | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| | 955 | formatArg(fc); |
|---|
| | 956 | return; |
|---|
| | 957 | |
|---|
| | 958 | case Mangle.Tstruct: |
|---|
| | 959 | { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; |
|---|
| | 960 | if (tis.xtoString is null) |
|---|
| | 961 | throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); |
|---|
| | 962 | |
|---|
| | 963 | |
|---|
| | 964 | char[] delegate() toString; |
|---|
| | 965 | toString.ptr = argptr; |
|---|
| | 966 | toString.funcptr = cast(char[] function())tis.xtoString; |
|---|
| | 967 | s = Utf.fromString8 (toString(), s); |
|---|
| | 968 | // s = tis.xtoString(p_args); |
|---|
| | 969 | |
|---|
| | 970 | |
|---|
| | 971 | |
|---|
| | 972 | p_args += tis.tsize(); |
|---|
| | 973 | goto Lputstr; |
|---|
| | 974 | } |
|---|
| | 975 | |
|---|
| | 976 | default: |
|---|
| | 977 | throw new FormatError("Could not format mangled type " ~ cast(char)m); |
|---|
| | 978 | } |
|---|
| | 979 | } |
|---|
| | 980 | |
|---|
| | 981 | Lnumber: |
|---|
| | 982 | switch (fc) |
|---|
| | 983 | { |
|---|
| | 984 | case 's': |
|---|
| | 985 | case 'd': |
|---|
| | 986 | if (signed) |
|---|
| | 987 | { if (cast(long)vnumber < 0) |
|---|
| | 988 | { prefix = "-"; |
|---|
| | 989 | vnumber = -vnumber; |
|---|
| | 990 | } |
|---|
| | 991 | else if (flags & FLplus) |
|---|
| | 992 | prefix = "+"; |
|---|
| | 993 | else if (flags & FLspace) |
|---|
| | 994 | prefix = " "; |
|---|
| | 995 | } |
|---|
| | 996 | break; |
|---|
| | 997 | |
|---|
| | 998 | case 'b': |
|---|
| | 999 | signed = 0; |
|---|
| | 1000 | base = 2; |
|---|
| | 1001 | break; |
|---|
| | 1002 | |
|---|
| | 1003 | case 'o': |
|---|
| | 1004 | signed = 0; |
|---|
| | 1005 | base = 8; |
|---|
| | 1006 | break; |
|---|
| | 1007 | |
|---|
| | 1008 | case 'X': |
|---|
| | 1009 | uc = 1; |
|---|
| | 1010 | if (flags & FLhash && vnumber) |
|---|
| | 1011 | prefix = "0X"; |
|---|
| | 1012 | signed = 0; |
|---|
| | 1013 | base = 16; |
|---|
| | 1014 | break; |
|---|
| | 1015 | |
|---|
| | 1016 | case 'x': |
|---|
| | 1017 | if (flags & FLhash && vnumber) |
|---|
| | 1018 | prefix = "0x"; |
|---|
| | 1019 | signed = 0; |
|---|
| | 1020 | base = 16; |
|---|
| | 1021 | break; |
|---|
| | 1022 | |
|---|
| | 1023 | default: |
|---|
| | 1024 | throw new FormatError("Could not format number of mangled type " ~ fc); |
|---|
| | 1025 | } |
|---|
| | 1026 | |
|---|
| | 1027 | if (!signed) |
|---|
| | 1028 | { |
|---|
| | 1029 | switch (m) |
|---|
| | 1030 | { |
|---|
| | 1031 | case Mangle.Tbyte: |
|---|
| | 1032 | vnumber &= 0xFF; |
|---|
| | 1033 | break; |
|---|
| | 1034 | |
|---|
| | 1035 | case Mangle.Tshort: |
|---|
| | 1036 | vnumber &= 0xFFFF; |
|---|
| | 1037 | break; |
|---|
| | 1038 | |
|---|
| | 1039 | case Mangle.Tint: |
|---|
| | 1040 | vnumber &= 0xFFFFFFFF; |
|---|
| | 1041 | break; |
|---|
| | 1042 | |
|---|
| | 1043 | default: |
|---|
| | 1044 | break; |
|---|
| | 1045 | } |
|---|
| | 1046 | } |
|---|
| | 1047 | |
|---|
| | 1048 | if (flags & FLprecision && fc != 'p') |
|---|
| | 1049 | flags &= ~FL0pad; |
|---|
| | 1050 | |
|---|
| | 1051 | if (vnumber < base) |
|---|
| | 1052 | { |
|---|
| | 1053 | if (vnumber == 0 && precision == 0 && flags & FLprecision && |
|---|
| | 1054 | !(fc == 'o' && flags & FLhash)) |
|---|
| | 1055 | { |
|---|
| | 1056 | putstr(null); |
|---|
| | 1057 | return; |
|---|
| | 1058 | } |
|---|
| | 1059 | if (precision == 0 || !(flags & FLprecision)) |
|---|
| | 1060 | { vchar = cast(char)('0' + vnumber); |
|---|
| | 1061 | if (vnumber < 10) |
|---|
| | 1062 | vchar = cast(char)('0' + vnumber); |
|---|
| | 1063 | else |
|---|
| | 1064 | vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber); |
|---|
| | 1065 | goto L2; |
|---|
| | 1066 | } |
|---|
| | 1067 | } |
|---|
| | 1068 | |
|---|
| | 1069 | int n = tmpbuf.length; |
|---|
| | 1070 | char c; |
|---|
| | 1071 | int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1)); |
|---|
| | 1072 | |
|---|
| | 1073 | while (vnumber) |
|---|
| | 1074 | { |
|---|
| | 1075 | c = cast(char)((vnumber % base) + '0'); |
|---|
| | 1076 | if (c > '9') |
|---|
| | 1077 | c += hexoffset; |
|---|
| | 1078 | vnumber /= base; |
|---|
| | 1079 | tmpbuf[--n] = c; |
|---|
| | 1080 | } |
|---|
| | 1081 | if (tmpbuf.length - n < precision && precision < tmpbuf.length) |
|---|
| | 1082 | { |
|---|
| | 1083 | int m = tmpbuf.length - precision; |
|---|
| | 1084 | tmpbuf[m .. n] = '0'; |
|---|
| | 1085 | n = m; |
|---|
| | 1086 | } |
|---|
| | 1087 | else if (flags & FLhash && fc == 'o') |
|---|
| | 1088 | prefix = "0"; |
|---|
| | 1089 | putstr(tmpbuf[n .. tmpbuf.length]); |
|---|
| | 1090 | return; |
|---|
| | 1091 | |
|---|
| | 1092 | Lreal: |
|---|
| | 1093 | putreal(vreal); |
|---|
| | 1094 | return; |
|---|
| | 1095 | |
|---|
| | 1096 | Lcomplex: |
|---|
| | 1097 | putreal(vcreal.re); |
|---|
| | 1098 | putc('+'); |
|---|
| | 1099 | putreal(vcreal.im); |
|---|
| | 1100 | putc('i'); |
|---|
| | 1101 | return; |
|---|
| | 1102 | |
|---|
| | 1103 | Lerror: |
|---|
| | 1104 | throw new FormatError("formatArg"); |
|---|
| 277 | | void putreal(real v) |
|---|
| 278 | | { |
|---|
| 279 | | //printf("putreal %Lg\n", vreal); |
|---|
| 280 | | |
|---|
| 281 | | switch (fc) |
|---|
| 282 | | { |
|---|
| 283 | | case 's': |
|---|
| 284 | | fc = 'g'; |
|---|
| 285 | | break; |
|---|
| 286 | | |
|---|
| 287 | | case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A': |
|---|
| 288 | | break; |
|---|
| 289 | | |
|---|
| 290 | | default: |
|---|
| 291 | | //printf("fc = '%c'\n", fc); |
|---|
| 292 | | Lerror: |
|---|
| 293 | | throw new FormatError("floating"); |
|---|
| 294 | | } |
|---|
| 295 | | version (DigitalMarsC) |
|---|
| 296 | | { |
|---|
| 297 | | int sl; |
|---|
| 298 | | char[] fbuf = tmpbuf; |
|---|
| 299 | | if (!(flags & FLprecision)) |
|---|
| 300 | | precision = 6; |
|---|
| 301 | | while (1) |
|---|
| 302 | | { |
|---|
| 303 | | sl = fbuf.length; |
|---|
| 304 | | prefix = (*__pfloatfmt)(fc, flags | FLlngdbl, |
|---|
| 305 | | precision, &v, cast(char*)fbuf, &sl, field_width); |
|---|
| 306 | | if (sl != -1) |
|---|
| 307 | | break; |
|---|
| 308 | | sl = fbuf.length * 2; |
|---|
| 309 | | fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; |
|---|
| 310 | | } |
|---|
| 311 | | putstr(fbuf[0 .. sl]); |
|---|
| 312 | | } |
|---|
| 313 | | else |
|---|
| 314 | | { |
|---|
| 315 | | int sl; |
|---|
| 316 | | char[] fbuf = tmpbuf; |
|---|
| 317 | | char[12] format; |
|---|
| 318 | | format[0] = '%'; |
|---|
| 319 | | int i = 1; |
|---|
| 320 | | if (flags & FLdash) |
|---|
| 321 | | format[i++] = '-'; |
|---|
| 322 | | if (flags & FLplus) |
|---|
| 323 | | format[i++] = '+'; |
|---|
| 324 | | if (flags & FLspace) |
|---|
| 325 | | format[i++] = ' '; |
|---|
| 326 | | if (flags & FLhash) |
|---|
| 327 | | format[i++] = '#'; |
|---|
| 328 | | if (flags & FL0pad) |
|---|
| 329 | | format[i++] = '0'; |
|---|
| 330 | | format[i + 0] = '*'; |
|---|
| 331 | | format[i + 1] = '.'; |
|---|
| 332 | | format[i + 2] = '*'; |
|---|
| 333 | | i += 3; |
|---|
| 334 | | version (GNU_MinGW_MSVCRT) |
|---|
| 335 | | { /* nothing: no support for long double */ } |
|---|
| 336 | | else |
|---|
| 337 | | static if (real.sizeof > double.sizeof) |
|---|
| 338 | | format[i++] = 'L'; |
|---|
| 339 | | format[i++] = fc; |
|---|
| 340 | | format[i] = 0; |
|---|
| 341 | | if (!(flags & FLprecision)) |
|---|
| 342 | | precision = -1; |
|---|
| 343 | | while (1) |
|---|
| 344 | | { int n; |
|---|
| 345 | | |
|---|
| 346 | | sl = fbuf.length; |
|---|
| 347 | | version (GNU_MinGW_MSVCRT) |
|---|
| 348 | | n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, cast(double) v); |
|---|
| 349 | | else |
|---|
| 350 | | n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); |
|---|
| 351 | | //printf("format = '%s', n = %d\n", cast(char*)format, n); |
|---|
| 352 | | if (n >= 0 && n < sl) |
|---|
| 353 | | { sl = n; |
|---|
| 354 | | break; |
|---|
| 355 | | } |
|---|
| 356 | | if (n < 0) |
|---|
| 357 | | sl = sl * 2; |
|---|
| 358 | | else |
|---|
| 359 | | sl = n + 1; |
|---|
| 360 | | fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; |
|---|
| 361 | | } |
|---|
| 362 | | putstr(fbuf[0 .. sl]); |
|---|
| 363 | | } |
|---|
| 364 | | return; |
|---|
| 365 | | } |
|---|
| 366 | | |
|---|
| 367 | | static Mangle getMan(TypeInfo ti) |
|---|
| 368 | | { |
|---|
| 369 | | auto m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| 370 | | if (ti.classinfo.name.length == 20 && |
|---|
| 371 | | ti.classinfo.name[9..20] == "StaticArray") |
|---|
| 372 | | m = cast(Mangle)'G'; |
|---|
| 373 | | return m; |
|---|
| 374 | | } |
|---|
| 375 | | |
|---|
| 376 | | void putArray(void* p, size_t len, TypeInfo valti) |
|---|
| 377 | | { |
|---|
| 378 | | putc('['); |
|---|
| 379 | | size_t tsize = valti.tsize(); |
|---|
| 380 | | version(DigitalMars) |
|---|
| 381 | | auto argptrSave = argptr; |
|---|
| 382 | | else |
|---|
| 383 | | auto argptrSave = p_args; |
|---|
| 384 | | auto tiSave = ti; |
|---|
| 385 | | auto mSave = m; |
|---|
| 386 | | ti = valti; |
|---|
| 387 | | m = getMan(valti); |
|---|
| 388 | | while (len--) |
|---|
| 389 | | { |
|---|
| 390 | | version (DigitalMars) |
|---|
| 391 | | argptr = cast(void*) p; |
|---|
| 392 | | else |
|---|
| 393 | | p_args = p; |
|---|
| 394 | | formatArg('s'); |
|---|
| 395 | | |
|---|
| 396 | | p += tsize; |
|---|
| 397 | | if (len > 0) putc(','); |
|---|
| 398 | | } |
|---|
| 399 | | m = mSave; |
|---|
| 400 | | ti = tiSave; |
|---|
| 401 | | version (DigitalMars) |
|---|
| 402 | | argptr = argptrSave; |
|---|
| 403 | | else |
|---|
| 404 | | p_args = argptrSave; |
|---|
| 405 | | putc(']'); |
|---|
| 406 | | } |
|---|
| 407 | | |
|---|
| 408 | | void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti) |
|---|
| 409 | | { |
|---|
| 410 | | // Copied from aaA.d |
|---|
| 411 | | size_t aligntsize(size_t tsize) |
|---|
| 412 | | { |
|---|
| 413 | | // Is pointer alignment on the x64 4 bytes or 8? |
|---|
| 414 | | return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); |
|---|
| 415 | | } |
|---|
| 416 | | |
|---|
| 417 | | putc('['); |
|---|
| 418 | | bool comma=false; |
|---|
| 419 | | version (DigitalMars) |
|---|
| 420 | | auto argptrSave = argptr; |
|---|
| 421 | | else |
|---|
| 422 | | auto argptrSave = p_args; |
|---|
| 423 | | auto tiSave = ti; |
|---|
| 424 | | auto mSave = m; |
|---|
| 425 | | foreach(inout fakevalue; vaa) |
|---|
| 426 | | { |
|---|
| 427 | | if (comma) putc(','); |
|---|
| 428 | | comma = true; |
|---|
| 429 | | // the key comes before the value |
|---|
| 430 | | ubyte* key = &fakevalue - long.sizeof; |
|---|
| 431 | | |
|---|
| 432 | | version (DigitalMars) |
|---|
| 433 | | argptr = cast(void*) key; |
|---|
| 434 | | else |
|---|
| 435 | | p_args = key; |
|---|
| 436 | | ti = keyti; |
|---|
| 437 | | m = getMan(keyti); |
|---|
| 438 | | formatArg('s'); |
|---|
| 439 | | |
|---|
| 440 | | putc(':'); |
|---|
| 441 | | ubyte* value = key + aligntsize(keyti.tsize); |
|---|
| 442 | | version (DigitalMars) |
|---|
| 443 | | argptr = cast(void*) value; |
|---|
| 444 | | else |
|---|
| 445 | | p_args = value; |
|---|
| 446 | | ti = valti; |
|---|
| 447 | | m = getMan(valti); |
|---|
| 448 | | formatArg('s'); |
|---|
| 449 | | } |
|---|
| 450 | | m = mSave; |
|---|
| 451 | | ti = tiSave; |
|---|
| 452 | | version (DigitalMars) |
|---|
| 453 | | argptr = argptrSave; |
|---|
| 454 | | else |
|---|
| 455 | | p_args = argptrSave; |
|---|
| 456 | | putc(']'); |
|---|
| 457 | | } |
|---|
| 458 | | |
|---|
| 459 | | if (! p_args) { |
|---|
| 460 | | switch (m) |
|---|
| 461 | | { |
|---|
| 462 | | case Mangle.Tbool: |
|---|
| 463 | | vbit = va_arg2!(bool)(argptr); |
|---|
| 464 | | if (fc != 's') |
|---|
| 465 | | { vnumber = vbit; |
|---|
| 466 | | goto Lnumber; |
|---|
| 467 | | } |
|---|
| 468 | | putstr(vbit ? "true" : "false"); |
|---|
| 469 | | return; |
|---|
| 470 | | |
|---|
| 471 | | case Mangle.Tchar: |
|---|
| 472 | | vchar = va_arg2!(char)(argptr); |
|---|
| 473 | | if (fc != 's') |
|---|
| 474 | | { vnumber = vchar; |
|---|
| 475 | | goto Lnumber; |
|---|
| 476 | | } |
|---|
| 477 | | L2: |
|---|
| 478 | | putstr((&vchar)[0 .. 1]); |
|---|
| 479 | | return; |
|---|
| 480 | | |
|---|
| 481 | | case Mangle.Twchar: |
|---|
| 482 | | vdchar = va_arg2!(wchar)(argptr); |
|---|
| 483 | | goto L1; |
|---|
| 484 | | |
|---|
| 485 | | case Mangle.Tdchar: |
|---|
| 486 | | vdchar = va_arg2!(dchar)(argptr); |
|---|
| 487 | | L1: |
|---|
| 488 | | if (fc != 's') |
|---|
| 489 | | { vnumber = vdchar; |
|---|
| 490 | | goto Lnumber; |
|---|
| 491 | | } |
|---|
| 492 | | if (vdchar <= 0x7F) |
|---|
| 493 | | { vchar = cast(char)vdchar; |
|---|
| 494 | | goto L2; |
|---|
| 495 | | } |
|---|
| 496 | | else |
|---|
| 497 | | { if (!isValid(vdchar)) |
|---|
| 498 | | throw new Exception("invalid dchar in format"); |
|---|
| 499 | | putstr(.toString([vdchar])); |
|---|
| 500 | | } |
|---|
| 501 | | return; |
|---|
| 502 | | |
|---|
| 503 | | case Mangle.Tbyte: |
|---|
| 504 | | signed = 1; |
|---|
| 505 | | vnumber = va_arg2!(byte)(argptr); |
|---|
| 506 | | goto Lnumber; |
|---|
| 507 | | |
|---|
| 508 | | case Mangle.Tubyte: |
|---|
| 509 | | vnumber = va_arg2!(ubyte)(argptr); |
|---|
| 510 | | goto Lnumber; |
|---|
| 511 | | |
|---|
| 512 | | case Mangle.Tshort: |
|---|
| 513 | | signed = 1; |
|---|
| 514 | | vnumber = va_arg2!(short)(argptr); |
|---|
| 515 | | goto Lnumber; |
|---|
| 516 | | |
|---|
| 517 | | case Mangle.Tushort: |
|---|
| 518 | | vnumber = va_arg2!(ushort)(argptr); |
|---|
| 519 | | goto Lnumber; |
|---|
| 520 | | |
|---|
| 521 | | case Mangle.Tint: |
|---|
| 522 | | signed = 1; |
|---|
| 523 | | vnumber = va_arg2!(int)(argptr); |
|---|
| 524 | | goto Lnumber; |
|---|
| 525 | | |
|---|
| 526 | | case Mangle.Tuint: |
|---|
| 527 | | Luint: |
|---|
| 528 | | vnumber = va_arg2!(uint)(argptr); |
|---|
| 529 | | goto Lnumber; |
|---|
| 530 | | |
|---|
| 531 | | case Mangle.Tlong: |
|---|
| 532 | | signed = 1; |
|---|
| 533 | | vnumber = cast(ulong)va_arg2!(long)(argptr); |
|---|
| 534 | | goto Lnumber; |
|---|
| 535 | | |
|---|
| 536 | | case Mangle.Tulong: |
|---|
| 537 | | Lulong: |
|---|
| 538 | | vnumber = va_arg2!(ulong)(argptr); |
|---|
| 539 | | goto Lnumber; |
|---|
| 540 | | |
|---|
| 541 | | case Mangle.Tclass: |
|---|
| 542 | | vobject = va_arg2!(Object)(argptr); |
|---|
| 543 | | if (vobject is null) |
|---|
| 544 | | s = "null"; |
|---|
| 545 | | else |
|---|
| 546 | | s = vobject.toString(); |
|---|
| 547 | | goto Lputstr; |
|---|
| 548 | | |
|---|
| 549 | | case Mangle.Tpointer: |
|---|
| 550 | | vnumber = cast(size_t)va_arg2!(void*)(argptr); |
|---|
| 551 | | uc = 1; |
|---|
| 552 | | flags |= FL0pad; |
|---|
| 553 | | if (!(flags & FLprecision)) |
|---|
| 554 | | { flags |= FLprecision; |
|---|
| 555 | | precision = (void*).sizeof; |
|---|
| 556 | | } |
|---|
| 557 | | base = 16; |
|---|
| 558 | | goto Lnumber; |
|---|
| 559 | | |
|---|
| 560 | | case Mangle.Tfloat: |
|---|
| 561 | | case Mangle.Tifloat: |
|---|
| 562 | | if (fc == 'x' || fc == 'X') |
|---|
| 563 | | { |
|---|
| 564 | | version (DigitalMars) |
|---|
| 565 | | goto Luint; |
|---|
| 566 | | else { |
|---|
| 567 | | float f = va_arg2!(float)(argptr); |
|---|
| 568 | | vnumber = *cast(uint*)&f; |
|---|
| 569 | | goto Lnumber; |
|---|
| 570 | | } |
|---|
| 571 | | } |
|---|
| 572 | | vreal = va_arg2!(float)(argptr); |
|---|
| 573 | | goto Lreal; |
|---|
| 574 | | |
|---|
| 575 | | case Mangle.Tdouble: |
|---|
| 576 | | case Mangle.Tidouble: |
|---|
| 577 | | if (fc == 'x' || fc == 'X') |
|---|
| 578 | | { |
|---|
| 579 | | version (DigitalMars) |
|---|
| 580 | | goto Lulong; |
|---|
| 581 | | else { |
|---|
| 582 | | double f = va_arg2!(double)(argptr); |
|---|
| 583 | | vnumber = *cast(ulong*)&f; |
|---|
| 584 | | goto Lnumber; |
|---|
| 585 | | } |
|---|
| 586 | | } |
|---|
| 587 | | vreal = va_arg2!(double)(argptr); |
|---|
| 588 | | goto Lreal; |
|---|
| 589 | | |
|---|
| 590 | | case Mangle.Treal: |
|---|
| 591 | | case Mangle.Tireal: |
|---|
| 592 | | vreal = va_arg2!(real)(argptr); |
|---|
| 593 | | goto Lreal; |
|---|
| 594 | | |
|---|
| 595 | | case Mangle.Tcfloat: |
|---|
| 596 | | vcreal = va_arg2!(cfloat)(argptr); |
|---|
| 597 | | goto Lcomplex; |
|---|
| 598 | | |
|---|
| 599 | | case Mangle.Tcdouble: |
|---|
| 600 | | vcreal = va_arg2!(cdouble)(argptr); |
|---|
| 601 | | goto Lcomplex; |
|---|
| 602 | | |
|---|
| 603 | | case Mangle.Tcreal: |
|---|
| 604 | | vcreal = va_arg2!(creal)(argptr); |
|---|
| 605 | | goto Lcomplex; |
|---|
| 606 | | |
|---|
| 607 | | case Mangle.Tsarray: |
|---|
| 608 | | version (DigitalMars) { |
|---|
| 609 | | putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); |
|---|
| 610 | | return; |
|---|
| 611 | | } |
|---|
| 612 | | version (GNU) { |
|---|
| 613 | | /* Static arrays are converted to dynamic arrays when |
|---|
| 614 | | passed as a variadic argument, so this code should |
|---|
| 615 | | never be executed with GDC. The case of an |
|---|
| 616 | | embedded static array is handled below. */ |
|---|
| 617 | | goto Lerror; |
|---|
| 618 | | } |
|---|
| 619 | | |
|---|
| 620 | | case Mangle.Tarray: |
|---|
| 621 | | int mi = 10; |
|---|
| 622 | | if (ti.classinfo.name.length == 14 && ti.classinfo.name[9..14] == "Array") |
|---|
| 623 | | { // array of non-primitive types |
|---|
| 624 | | TypeInfo tn = (cast(TypeInfo_Array)ti).next; |
|---|
| 625 | | switch (cast(Mangle)tn.classinfo.name[9]) |
|---|
| 626 | | { |
|---|
| 627 | | case Mangle.Tchar: goto LarrayChar; |
|---|
| 628 | | case Mangle.Twchar: goto LarrayWchar; |
|---|
| 629 | | case Mangle.Tdchar: goto LarrayDchar; |
|---|
| 630 | | default: |
|---|
| 631 | | break; |
|---|
| 632 | | } |
|---|
| 633 | | void[] va = va_arg2!(void[])(argptr); |
|---|
| 634 | | putArray(va.ptr, va.length, tn); |
|---|
| 635 | | return; |
|---|
| 636 | | } |
|---|
| 637 | | if (ti.classinfo.name.length == 25 && |
|---|
| 638 | | ti.classinfo.name[9..25] == "AssociativeArray") |
|---|
| 639 | | { // associative array |
|---|
| 640 | | ubyte[long] vaa = va_arg2!(ubyte[long])(argptr); |
|---|
| 641 | | putAArray(vaa, |
|---|
| 642 | | (cast(TypeInfo_AssociativeArray)ti).next, |
|---|
| 643 | | (cast(TypeInfo_AssociativeArray)ti).key); |
|---|
| 644 | | return; |
|---|
| 645 | | } |
|---|
| 646 | | |
|---|
| 647 | | while (1) |
|---|
| 648 | | { |
|---|
| 649 | | m2 = cast(Mangle)ti.classinfo.name[mi]; |
|---|
| 650 | | switch (m2) |
|---|
| 651 | | { |
|---|
| 652 | | case Mangle.Tchar: |
|---|
| 653 | | LarrayChar: |
|---|
| 654 | | s = va_arg2!(char[])(argptr); |
|---|
| 655 | | goto Lputstr; |
|---|
| 656 | | |
|---|
| 657 | | case Mangle.Twchar: |
|---|
| 658 | | LarrayWchar: |
|---|
| 659 | | wchar[] sw = va_arg2!(wchar[])(argptr); |
|---|
| 660 | | s = .toString(sw); |
|---|
| 661 | | goto Lputstr; |
|---|
| 662 | | |
|---|
| 663 | | case Mangle.Tdchar: |
|---|
| 664 | | LarrayDchar: |
|---|
| 665 | | dchar[] sd = va_arg2!(dchar[])(argptr); |
|---|
| 666 | | s = .toString(sd); |
|---|
| 667 | | Lputstr: |
|---|
| 668 | | if (fc != 's') |
|---|
| 669 | | throw new FormatError("string"); |
|---|
| 670 | | if (flags & FLprecision && precision < s.length) |
|---|
| 671 | | s = s[0 .. precision]; |
|---|
| 672 | | putstr(s); |
|---|
| 673 | | break; |
|---|
| 674 | | |
|---|
| 675 | | case Mangle.Tconst: |
|---|
| 676 | | case Mangle.Tinvariant: |
|---|
| 677 | | mi++; |
|---|
| 678 | | continue; |
|---|
| 679 | | |
|---|
| 680 | | default: |
|---|
| 681 | | TypeInfo ti2 = primitiveTypeInfo(m2); |
|---|
| 682 | | if (!ti2) |
|---|
| 683 | | throw new FormatError("Can't get type info for type " ~ cast(char)m2); |
|---|
| 684 | | void[] va = va_arg2!(void[])(argptr); |
|---|
| 685 | | putArray(va.ptr, va.length, ti2); |
|---|
| 686 | | } |
|---|
| 687 | | return; |
|---|
| 688 | | } |
|---|
| 689 | | case Mangle.Ttypedef: |
|---|
| 690 | | ti = (cast(TypeInfo_Typedef)ti).base; |
|---|
| 691 | | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| 692 | | formatArg(fc); |
|---|
| 693 | | return; |
|---|
| 694 | | |
|---|
| 695 | | case Mangle.Tenum: |
|---|
| 696 | | ti = (cast(TypeInfo_Enum)ti).base; |
|---|
| 697 | | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| 698 | | formatArg(fc); |
|---|
| 699 | | return; |
|---|
| 700 | | |
|---|
| 701 | | case Mangle.Tstruct: |
|---|
| 702 | | { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; |
|---|
| 703 | | if (tis.xtoString is null) |
|---|
| 704 | | throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); |
|---|
| 705 | | version(DigitalMars){ |
|---|
| 706 | | |
|---|
| 707 | | char[] delegate() toString; |
|---|
| 708 | | toString.ptr = argptr; |
|---|
| 709 | | toString.funcptr = cast(char[] function())tis.xtoString; |
|---|
| 710 | | s = Utf.fromString8 (toString(), s); |
|---|
| 711 | | // s = tis.xtoString(argptr); |
|---|
| 712 | | |
|---|
| 713 | | argptr += (tis.tsize() + 3) & ~3; |
|---|
| 714 | | } |
|---|
| 715 | | version (GNU){ |
|---|
| 716 | | static if (is( typeof(argptr): void[] ) || is( typeof(argptr) == struct )) |
|---|
| 717 | | { |
|---|
| 718 | | version(PPC) |
|---|
| 719 | | { |
|---|
| 720 | | // Structs are pass-by-reference in V4 ABI |
|---|
| 721 | | s = tis.xtoString(va_arg2!(void*)(argptr)); |
|---|
| 722 | | } |
|---|
| 723 | | else version(X86_64) |
|---|
| 724 | | { |
|---|
| 725 | | throw new FormatError("cannot portably format a struct on this target"); |
|---|
| 726 | | } |
|---|
| 727 | | else |
|---|
| 728 | | { |
|---|
| 729 | | static assert(0, "unimplemented"); |
|---|
| 730 | | } |
|---|
| 731 | | } |
|---|
| 732 | | else |
|---|
| 733 | | { |
|---|
| 734 | | s = tis.xtoString(argptr); |
|---|
| 735 | | argptr += (tis.tsize() + 3) & ~3; // this looks like it should call aligntsize |
|---|
| 736 | | } |
|---|
| 737 | | } |
|---|
| 738 | | goto Lputstr; |
|---|
| 739 | | } |
|---|
| 740 | | |
|---|
| 741 | | default: |
|---|
| 742 | | if (m2=='v') |
|---|
| 743 | | throw new FormatError("Can't get type info for type void"); |
|---|
| 744 | | else |
|---|
| 745 | | throw new FormatError("Can't get type info for mangled type " ~ cast(char)m2); |
|---|
| 746 | | }} |
|---|
| 747 | | else |
|---|
| 748 | | { |
|---|
| 749 | | version (DigitalMars) assert(0); |
|---|
| 750 | | switch (m) |
|---|
| 751 | | { |
|---|
| 752 | | case Mangle.Tbool: |
|---|
| 753 | | vbit = *cast(bool*)(p_args); p_args += bool.sizeof; // int.sizeof, etc.? |
|---|
| 754 | | if (fc != 's') |
|---|
| 755 | | { vnumber = vbit; |
|---|
| 756 | | goto Lnumber; |
|---|
| 757 | | } |
|---|
| 758 | | putstr(vbit ? "true" : "false"); |
|---|
| 759 | | return; |
|---|
| 760 | | |
|---|
| 761 | | |
|---|
| 762 | | case Mangle.Tchar: |
|---|
| 763 | | vchar = *cast(char*)(p_args); p_args += char.sizeof; |
|---|
| 764 | | if (fc != 's') |
|---|
| 765 | | { vnumber = vchar; |
|---|
| 766 | | goto Lnumber; |
|---|
| 767 | | } |
|---|
| 768 | | PL2: // there is goto L2 outside of thise switch; it's okay to do that |
|---|
| 769 | | putstr((&vchar)[0 .. 1]); |
|---|
| 770 | | return; |
|---|
| 771 | | |
|---|
| 772 | | case Mangle.Twchar: |
|---|
| 773 | | vdchar = *cast(wchar*)(p_args); p_args += wchar.sizeof; |
|---|
| 774 | | goto PL1; |
|---|
| 775 | | |
|---|
| 776 | | case Mangle.Tdchar: |
|---|
| 777 | | vdchar = *cast(dchar*)(p_args); p_args += dchar.sizeof; |
|---|
| 778 | | PL1: |
|---|
| 779 | | if (fc != 's') |
|---|
| 780 | | { vnumber = vdchar; |
|---|
| 781 | | goto Lnumber; |
|---|
| 782 | | } |
|---|
| 783 | | if (vdchar <= 0x7F) |
|---|
| 784 | | { vchar = cast(char)vdchar; |
|---|
| 785 | | goto PL2; |
|---|
| 786 | | } |
|---|
| 787 | | else |
|---|
| 788 | | { if (!isValid(vdchar)) |
|---|
| 789 | | throw new Exception("invalid dchar in format"); |
|---|
| 790 | | putstr(.toString([vdchar])); |
|---|
| 791 | | } |
|---|
| 792 | | return; |
|---|
| 793 | | |
|---|
| 794 | | |
|---|
| 795 | | case Mangle.Tbyte: |
|---|
| 796 | | signed = 1; |
|---|
| 797 | | vnumber = *cast(byte*)p_args; p_args += byte.sizeof; |
|---|
| 798 | | goto Lnumber; |
|---|
| 799 | | |
|---|
| 800 | | case Mangle.Tubyte: |
|---|
| 801 | | vnumber = *cast(ubyte*)p_args; p_args += ubyte.sizeof; |
|---|
| 802 | | goto Lnumber; |
|---|
| 803 | | |
|---|
| 804 | | case Mangle.Tshort: |
|---|
| 805 | | signed = 1; |
|---|
| 806 | | vnumber = *cast(short*)p_args; p_args += short.sizeof; |
|---|
| 807 | | goto Lnumber; |
|---|
| 808 | | |
|---|
| 809 | | case Mangle.Tushort: |
|---|
| 810 | | vnumber = *cast(ushort*)p_args; p_args += ushort.sizeof; |
|---|
| 811 | | goto Lnumber; |
|---|
| 812 | | |
|---|
| 813 | | case Mangle.Tint: |
|---|
| 814 | | signed = 1; |
|---|
| 815 | | vnumber = *cast(int*)p_args; p_args += int.sizeof; |
|---|
| 816 | | goto Lnumber; |
|---|
| 817 | | |
|---|
| 818 | | case Mangle.Tuint: |
|---|
| 819 | | PLuint: |
|---|
| 820 | | vnumber = *cast(uint*)p_args; p_args += uint.sizeof; |
|---|
| 821 | | goto Lnumber; |
|---|
| 822 | | |
|---|
| 823 | | case Mangle.Tlong: |
|---|
| 824 | | signed = 1; |
|---|
| 825 | | vnumber = cast(ulong)*cast(long*)p_args; p_args += long.sizeof; |
|---|
| 826 | | goto Lnumber; |
|---|
| 827 | | |
|---|
| 828 | | case Mangle.Tulong: |
|---|
| 829 | | PLulong: |
|---|
| 830 | | vnumber = *cast(ulong*)p_args; p_args += ulong.sizeof; |
|---|
| 831 | | goto Lnumber; |
|---|
| 832 | | |
|---|
| 833 | | case Mangle.Tclass: |
|---|
| 834 | | vobject = *cast(Object*)p_args; p_args += Object.sizeof; |
|---|
| 835 | | s = vobject.toString(); |
|---|
| 836 | | goto Lputstr; |
|---|
| 837 | | |
|---|
| 838 | | case Mangle.Tpointer: |
|---|
| 839 | | alias void * void_ponter_t; |
|---|
| 840 | | vnumber = cast(size_t)*cast(void**)p_args; p_args += void_ponter_t.sizeof; |
|---|
| 841 | | uc = 1; |
|---|
| 842 | | flags |= FL0pad; |
|---|
| 843 | | if (!(flags & FLprecision)) |
|---|
| 844 | | { flags |= FLprecision; |
|---|
| 845 | | precision = (void*).sizeof; |
|---|
| 846 | | } |
|---|
| 847 | | base = 16; |
|---|
| 848 | | goto Lnumber; |
|---|
| 849 | | |
|---|
| 850 | | |
|---|
| 851 | | case Mangle.Tfloat: |
|---|
| 852 | | case Mangle.Tifloat: |
|---|
| 853 | | if (fc == 'x' || fc == 'X') |
|---|
| 854 | | goto PLuint; |
|---|
| 855 | | vreal = *cast(float*)p_args; p_args += float.sizeof; |
|---|
| 856 | | goto Lreal; |
|---|
| 857 | | |
|---|
| 858 | | case Mangle.Tdouble: |
|---|
| 859 | | case Mangle.Tidouble: |
|---|
| 860 | | if (fc == 'x' || fc == 'X') |
|---|
| 861 | | goto PLulong; |
|---|
| 862 | | vreal = *cast(double*)p_args; p_args += double.sizeof; |
|---|
| 863 | | goto Lreal; |
|---|
| 864 | | |
|---|
| 865 | | case Mangle.Treal: |
|---|
| 866 | | case Mangle.Tireal: |
|---|
| 867 | | vreal = *cast(real*)p_args; p_args += real.sizeof; |
|---|
| 868 | | goto Lreal; |
|---|
| 869 | | |
|---|
| 870 | | |
|---|
| 871 | | case Mangle.Tcfloat: |
|---|
| 872 | | vcreal = *cast(cfloat*)p_args; p_args += cfloat.sizeof; |
|---|
| 873 | | goto Lcomplex; |
|---|
| 874 | | |
|---|
| 875 | | case Mangle.Tcdouble: |
|---|
| 876 | | vcreal = *cast(cdouble*)p_args; p_args += cdouble.sizeof; |
|---|
| 877 | | goto Lcomplex; |
|---|
| 878 | | |
|---|
| 879 | | case Mangle.Tcreal: |
|---|
| 880 | | vcreal = *cast(creal*)p_args; p_args += creal.sizeof; |
|---|
| 881 | | goto Lcomplex; |
|---|
| 882 | | |
|---|
| 883 | | case Mangle.Tsarray: |
|---|
| 884 | | putArray(p_args, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); |
|---|
| 885 | | p_args += ti.tsize(); |
|---|
| 886 | | return; |
|---|
| 887 | | |
|---|
| 888 | | case Mangle.Tarray: |
|---|
| 889 | | alias void[] array_t; |
|---|
| 890 | | int mi = 10; |
|---|
| 891 | | if (ti.classinfo.name.length == 14 && |
|---|
| 892 | | ti.classinfo.name[9..14] == "Array") |
|---|
| 893 | | { // array of non-primitive types |
|---|
| 894 | | TypeInfo tn = (cast(TypeInfo_Array)ti).next; |
|---|
| 895 | | switch (cast(Mangle)tn.classinfo.name[9]) |
|---|
| 896 | | { |
|---|
| 897 | | case Mangle.Tchar: goto LarrayChar_p; |
|---|
| 898 | | case Mangle.Twchar: goto LarrayWchar_p; |
|---|
| 899 | | case Mangle.Tdchar: goto LarrayDchar_p; |
|---|
| 900 | | default: |
|---|
| 901 | | break; |
|---|
| 902 | | } |
|---|
| 903 | | void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; |
|---|
| 904 | | putArray(va.ptr, va.length, tn); |
|---|
| 905 | | return; |
|---|
| 906 | | } |
|---|
| 907 | | if (ti.classinfo.name.length == 25 && |
|---|
| 908 | | ti.classinfo.name[9..25] == "AssociativeArray") |
|---|
| 909 | | { // associative array |
|---|
| 910 | | ubyte[long] vaa = *cast(ubyte[long]*)p_args; p_args += vaa.sizeof; |
|---|
| 911 | | putAArray(vaa, |
|---|
| 912 | | (cast(TypeInfo_AssociativeArray)ti).next, |
|---|
| 913 | | (cast(TypeInfo_AssociativeArray)ti).key); |
|---|
| 914 | | return; |
|---|
| 915 | | } |
|---|
| 916 | | |
|---|
| 917 | | while (1) |
|---|
| 918 | | { |
|---|
| 919 | | m2 = cast(Mangle)ti.classinfo.name[mi]; |
|---|
| 920 | | switch (m2) |
|---|
| 921 | | { |
|---|
| 922 | | case Mangle.Tchar: |
|---|
| 923 | | LarrayChar_p: |
|---|
| 924 | | s = *cast(char[]*)p_args; p_args += array_t.sizeof; |
|---|
| 925 | | goto PLputstr; |
|---|
| 926 | | |
|---|
| 927 | | case Mangle.Twchar: |
|---|
| 928 | | LarrayWchar_p: |
|---|
| 929 | | wchar[] sw = *cast(wchar[]*)p_args; p_args += array_t.sizeof; |
|---|
| 930 | | s = .toString(sw); |
|---|
| 931 | | goto PLputstr; |
|---|
| 932 | | |
|---|
| 933 | | case Mangle.Tdchar: |
|---|
| 934 | | LarrayDchar_p: |
|---|
| 935 | | dchar[] sd = *cast(dchar[]*)p_args; p_args += array_t.sizeof; |
|---|
| 936 | | s = .toString(sd); |
|---|
| 937 | | PLputstr: |
|---|
| 938 | | if (fc != 's') |
|---|
| 939 | | throw new FormatError("string"); |
|---|
| 940 | | if (flags & FLprecision && precision < s.length) |
|---|
| 941 | | s = s[0 .. precision]; |
|---|
| 942 | | putstr(s); |
|---|
| 943 | | break; |
|---|
| 944 | | |
|---|
| 945 | | case Mangle.Tconst: |
|---|
| 946 | | case Mangle.Tinvariant: |
|---|
| 947 | | mi++; |
|---|
| 948 | | continue; |
|---|
| 949 | | |
|---|
| 950 | | default: |
|---|
| 951 | | TypeInfo ti2 = primitiveTypeInfo(m2); |
|---|
| 952 | | if (!ti2) |
|---|
| 953 | | throw new FormatError("Can't get type info for type " ~ cast(char)m2); |
|---|
| 954 | | void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; |
|---|
| 955 | | putArray(va.ptr, va.length, ti2); |
|---|
| 956 | | } |
|---|
| 957 | | return; |
|---|
| 958 | | } |
|---|
| 959 | | |
|---|
| 960 | | case Mangle.Ttypedef: |
|---|
| 961 | | ti = (cast(TypeInfo_Typedef)ti).base; |
|---|
| 962 | | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| 963 | | formatArg(fc); |
|---|
| 964 | | return; |
|---|
| 965 | | |
|---|
| 966 | | case Mangle.Tenum: |
|---|
| 967 | | ti = (cast(TypeInfo_Enum)ti).base; |
|---|
| 968 | | m = cast(Mangle)ti.classinfo.name[9]; |
|---|
| 969 | | formatArg(fc); |
|---|
| 970 | | return; |
|---|
| 971 | | |
|---|
| 972 | | case Mangle.Tstruct: |
|---|
| 973 | | { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; |
|---|
| 974 | | if (tis.xtoString is null) |
|---|
| 975 | | throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); |
|---|
| 976 | | |
|---|
| 977 | | |
|---|
| 978 | | char[] delegate() toString; |
|---|
| 979 | | toString.ptr = argptr; |
|---|
| 980 | | toString.funcptr = cast(char[] function())tis.xtoString; |
|---|
| 981 | | s = Utf.fromString8 (toString(), s); |
|---|
| 982 | | // s = tis.xtoString(p_args); |
|---|
| 983 | | |
|---|
| 984 | | |
|---|
| 985 | | |
|---|
| 986 | | p_args += tis.tsize(); |
|---|
| 987 | | goto Lputstr; |
|---|
| 988 | | } |
|---|
| 989 | | |
|---|
| 990 | | default: |
|---|
| 991 | | throw new FormatError("Could not format mangled type " ~ cast(char)m); |
|---|
| 992 | | } |
|---|
| 993 | | } |
|---|
| 994 | | |
|---|
| 995 | | Lnumber: |
|---|
| 996 | | switch (fc) |
|---|
| 997 | | { |
|---|
| 998 | | case 's': |
|---|
| 999 | | case 'd': |
|---|
| 1000 | | if (signed) |
|---|
| 1001 | | { if (cast(long)vnumber < 0) |
|---|
| 1002 | | { prefix = "-"; |
|---|
| 1003 | | vnumber = -vnumber; |
|---|
| 1004 | | } |
|---|
| 1005 | | else if (flags & FLplus) |
|---|
| 1006 | | prefix = "+"; |
|---|
| 1007 | | else if (flags & FLspace) |
|---|
| 1008 | | prefix = " "; |
|---|
| 1009 | | } |
|---|
| 1010 | | break; |
|---|
| 1011 | | |
|---|
| 1012 | | case 'b': |
|---|
| 1013 | | signed = 0; |
|---|
| 1014 | | base = 2; |
|---|
| 1015 | | break; |
|---|
| 1016 | | |
|---|
| 1017 | | case 'o': |
|---|
| 1018 | | signed = 0; |
|---|
| 1019 | | base = 8; |
|---|
| 1020 | | break; |
|---|
| 1021 | | |
|---|
| 1022 | | case 'X': |
|---|
| 1023 | | uc = 1; |
|---|
| 1024 | | if (flags & FLhash && vnumber) |
|---|
| 1025 | | prefix = "0X"; |
|---|
| 1026 | | signed = 0; |
|---|
| 1027 | | base = 16; |
|---|
| 1028 | | break; |
|---|
| 1029 | | |
|---|
| 1030 | | case 'x': |
|---|
| 1031 | | if (flags & FLhash && vnumber) |
|---|
| 1032 | | prefix = "0x"; |
|---|
| 1033 | | signed = 0; |
|---|
| 1034 | | base = 16; |
|---|
| 1035 | | break; |
|---|
| 1036 | | |
|---|
| 1037 | | default: |
|---|
| 1038 | | throw new FormatError("Could not format number of mangled type " ~ fc); |
|---|
| 1039 | | } |
|---|
| 1040 | | |
|---|
| 1041 | | if (!signed) |
|---|
| 1042 | | { |
|---|
| 1043 | | switch (m) |
|---|
| 1044 | | { |
|---|
| 1045 | | case Mangle.Tbyte: |
|---|
| 1046 | | vnumber &= 0xFF; |
|---|
| 1047 | | break; |
|---|
| 1048 | | |
|---|
| 1049 | | case Mangle.Tshort: |
|---|
| 1050 | | vnumber &= 0xFFFF; |
|---|
| 1051 | | break; |
|---|
| 1052 | | |
|---|
| 1053 | | case Mangle.Tint: |
|---|
| 1054 | | vnumber &= 0xFFFFFFFF; |
|---|
| 1055 | | break; |
|---|
| 1056 | | |
|---|
| 1057 | | default: |
|---|
| 1058 | | break; |
|---|
| 1059 | | } |
|---|
| 1060 | | } |
|---|
| 1061 | | |
|---|
| 1062 | | if (flags & FLprecision && fc != 'p') |
|---|
| 1063 | | flags &= ~FL0pad; |
|---|
| 1064 | | |
|---|
| 1065 | | if (vnumber < base) |
|---|
| 1066 | | { |
|---|
| 1067 | | if (vnumber == 0 && precision == 0 && flags & FLprecision && |
|---|
| 1068 | | !(fc == 'o' && flags & FLhash)) |
|---|
| 1069 | | { |
|---|
| 1070 | | putstr(null); |
|---|
| 1071 | | return; |
|---|
| 1072 | | } |
|---|
| 1073 | | if (precision == 0 || !(flags & FLprecision)) |
|---|
| 1074 | | { vchar = cast(char)('0' + vnumber); |
|---|
| 1075 | | if (vnumber < 10) |
|---|
| 1076 | | vchar = cast(char)('0' + vnumber); |
|---|
| 1077 | | else |
|---|
| 1078 | | vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber); |
|---|
| 1079 | | goto L2; |
|---|
| 1080 | | } |
|---|
| 1081 | | } |
|---|
| 1082 | | |
|---|
| 1083 | | int n = tmpbuf.length; |
|---|
| 1084 | | char c; |
|---|
| 1085 | | int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1)); |
|---|
| 1086 | | |
|---|
| 1087 | | while (vnumber) |
|---|
| 1088 | | { |
|---|
| 1089 | | c = cast(char)((vnumber % base) + '0'); |
|---|
| 1090 | | if (c > '9') |
|---|
| 1091 | | c += hexoffset; |
|---|
| 1092 | | vnumber /= base; |
|---|
| 1093 | | tmpbuf[--n] = c; |
|---|
| 1094 | | } |
|---|
| 1095 | | if (tmpbuf.length - n < precision && precision < tmpbuf.length) |
|---|
| 1096 | | { |
|---|
| 1097 | | int m = tmpbuf.length - precision; |
|---|
| 1098 | | tmpbuf[m .. n] = '0'; |
|---|
| 1099 | | n = m; |
|---|
| 1100 | | } |
|---|
| 1101 | | else if (flags & FLhash && fc == 'o') |
|---|
| 1102 | | prefix = "0"; |
|---|
| 1103 | | putstr(tmpbuf[n .. tmpbuf.length]); |
|---|
| 1104 | | return; |
|---|
| 1105 | | |
|---|
| 1106 | | Lreal: |
|---|
| 1107 | | putreal(vreal); |
|---|
| 1108 | | return; |
|---|
| 1109 | | |
|---|
| 1110 | | Lcomplex: |
|---|
| 1111 | | putreal(vcreal.re); |
|---|
| 1112 | | putc('+'); |
|---|
| 1113 | | putreal(vcreal.im); |
|---|
| 1114 | | putc('i'); |
|---|
| 1115 | | return; |
|---|
| 1116 | | |
|---|
| 1117 | | Lerror: |
|---|
| 1118 | | throw new FormatError("formatArg"); |
|---|
| 1119 | | } |
|---|
| 1120 | | |
|---|
| 1121 | | for (j = 0; j < arguments.length; ) |
|---|
| 1122 | | { ti = arguments[j++]; |
|---|
| | 1107 | for (j = 0; j < arguments.length; ) |
|---|
| | 1108 | { ti = arguments[j++]; |
|---|
| 1393 | | else |
|---|
| 1394 | | assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan" || |
|---|
| 1395 | | s == "1.67 -0X1.47AE147AE147BP+0 nan"); |
|---|
| 1396 | | |
|---|
| 1397 | | s = swritef("%x %X", 0x1234AF, 0xAFAFAFAF); |
|---|
| 1398 | | assert(s == "1234af AFAFAFAF"); |
|---|
| 1399 | | |
|---|
| 1400 | | s = swritef("%b %o", 0x1234AF, 0xAFAFAFAF); |
|---|
| 1401 | | assert(s == "100100011010010101111 25753727657"); |
|---|
| 1402 | | |
|---|
| 1403 | | s = swritef("%d %s", 0x1234AF, 0xAFAFAFAF); |
|---|
| 1404 | | assert(s == "1193135 2947526575"); |
|---|
| 1405 | | |
|---|
| 1406 | | s = swritef("%s", 1.2 + 3.4i); |
|---|
| 1407 | | assert(s == "1.2+3.4i"); |
|---|
| 1408 | | |
|---|
| 1409 | | s = swritef("%x %X", 1.32, 6.78f); |
|---|
| 1410 | | assert(s == "3ff51eb851eb851f 40D8F5C3"); |
|---|
| 1411 | | |
|---|
| 1412 | | s = swritef("%#06.*f",2,12.345); |
|---|
| 1413 | | assert(s == "012.35"); |
|---|
| 1414 | | |
|---|
| 1415 | | s = swritef("%#0*.*f",6,2,12.345); |
|---|
| 1416 | | assert(s == "012.35"); |
|---|
| 1417 | | |
|---|
| 1418 | | s = swritef("%7.4g:", 12.678); |
|---|
| 1419 | | assert(s == " 12.68:"); |
|---|
| 1420 | | |
|---|
| 1421 | | s = swritef("%7.4g:", 12.678L); |
|---|
| 1422 | | assert(s == " 12.68:"); |
|---|
| 1423 | | |
|---|
| 1424 | | s = swritef("%04f|%05d|%#05x|%#5x",-4.,-10,1,1); |
|---|
| 1425 | | assert(s == "-4.000000|-0010|0x001| 0x1"); |
|---|
| 1426 | | |
|---|
| 1427 | | i = -10; |
|---|
| 1428 | | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| 1429 | | assert(s == "-10|-10|-10|-10|-10.0000"); |
|---|
| 1430 | | |
|---|
| 1431 | | i = -5; |
|---|
| 1432 | | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| 1433 | | assert(s == "-5| -5|-05|-5|-5.0000"); |
|---|
| 1434 | | |
|---|
| 1435 | | i = 0; |
|---|
| 1436 | | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| 1437 | | assert(s == "0| 0|000|0|0.0000"); |
|---|
| 1438 | | |
|---|
| 1439 | | i = 5; |
|---|
| 1440 | | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| 1441 | | assert(s == "5| 5|005|5|5.0000"); |
|---|
| 1442 | | |
|---|
| 1443 | | i = 10; |
|---|
| 1444 | | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| 1445 | | assert(s == "10| 10|010|10|10.0000"); |
|---|
| 1446 | | |
|---|
| 1447 | | s = swritef("%.0d", 0); |
|---|
| 1448 | | assert(s == ""); |
|---|
| 1449 | | |
|---|
| 1450 | | s = swritef("%.g", .34); |
|---|
| 1451 | | assert(s == "0.3"); |
|---|
| 1452 | | |
|---|
| 1453 | | s = swritef("%.0g", .34); |
|---|
| 1454 | | assert(s == "0.3"); |
|---|
| 1455 | | |
|---|
| 1456 | | s = swritef("%.2g", .34); |
|---|
| 1457 | | assert(s == "0.34"); |
|---|
| 1458 | | |
|---|
| 1459 | | s = swritef("%0.0008f", 1e-08); |
|---|
| 1460 | | assert(s == "0.00000001"); |
|---|
| 1461 | | |
|---|
| 1462 | | s = swritef("%0.0008f", 1e-05); |
|---|
| 1463 | | assert(s == "0.00001000"); |
|---|
| 1464 | | |
|---|
| 1465 | | s = "helloworld"; |
|---|
| 1466 | | string r; |
|---|
| 1467 | | r = swritef("%.2s", s[0..5]); |
|---|
| 1468 | | assert(r == "he"); |
|---|
| 1469 | | r = swritef("%.20s", s[0..5]); |
|---|
| 1470 | | assert(r == "hello"); |
|---|
| 1471 | | r = swritef("%8s", s[0..5]); |
|---|
| 1472 | | assert(r == " hello"); |
|---|
| 1473 | | |
|---|
| 1474 | | byte[] arrbyte = new byte[4]; |
|---|
| 1475 | | arrbyte[0] = 100; |
|---|
| 1476 | | arrbyte[1] = -99; |
|---|
| 1477 | | arrbyte[3] = 0; |
|---|
| 1478 | | r = swritef(arrbyte); |
|---|
| 1479 | | assert(r == "[100,-99,0,0]"); |
|---|
| 1480 | | |
|---|
| 1481 | | ubyte[] arrubyte = new ubyte[4]; |
|---|
| 1482 | | arrubyte[0] = 100; |
|---|
| 1483 | | arrubyte[1] = 200; |
|---|
| 1484 | | arrubyte[3] = 0; |
|---|
| 1485 | | r = swritef(arrubyte); |
|---|
| 1486 | | assert(r == "[100,200,0,0]"); |
|---|
| 1487 | | |
|---|
| 1488 | | short[] arrshort = new short[4]; |
|---|
| 1489 | | arrshort[0] = 100; |
|---|
| 1490 | | arrshort[1] = -999; |
|---|
| 1491 | | arrshort[3] = 0; |
|---|
| 1492 | | r = swritef(arrshort); |
|---|
| 1493 | | assert(r == "[100,-999,0,0]"); |
|---|
| 1494 | | r = swritef("%s",arrshort); |
|---|
| 1495 | | assert(r == "[100,-999,0,0]"); |
|---|
| 1496 | | |
|---|
| 1497 | | ushort[] arrushort = new ushort[4]; |
|---|
| 1498 | | arrushort[0] = 100; |
|---|
| 1499 | | arrushort[1] = 20_000; |
|---|
| 1500 | | arrushort[3] = 0; |
|---|
| 1501 | | r = swritef(arrushort); |
|---|
| 1502 | | assert(r == "[100,20000,0,0]"); |
|---|
| 1503 | | |
|---|
| 1504 | | int[] arrint = new int[4]; |
|---|
| 1505 | | arrint[0] = 100; |
|---|
| 1506 | | arrint[1] = -999; |
|---|
| 1507 | | arrint[3] = 0; |
|---|
| 1508 | | r = swritef(arrint); |
|---|
| 1509 | | assert(r == "[100,-999,0,0]"); |
|---|
| 1510 | | r = swritef("%s",arrint); |
|---|
| 1511 | | assert(r == "[100,-999,0,0]"); |
|---|
| 1512 | | |
|---|
| 1513 | | long[] arrlong = new long[4]; |
|---|
| 1514 | | arrlong[0] = 100; |
|---|
| 1515 | | arrlong[1] = -999; |
|---|
| 1516 | | arrlong[3] = 0; |
|---|
| 1517 | | r = swritef(arrlong); |
|---|
| 1518 | | assert(r == "[100,-999,0,0]"); |
|---|
| 1519 | | r = swritef("%s",arrlong); |
|---|
| 1520 | | assert(r == "[100,-999,0,0]"); |
|---|
| 1521 | | |
|---|
| 1522 | | ulong[] arrulong = new ulong[4]; |
|---|
| 1523 | | arrulong[0] = 100; |
|---|
| 1524 | | arrulong[1] = 999; |
|---|
| 1525 | | arrulong[3] = 0; |
|---|
| 1526 | | r = swritef(arrulong); |
|---|
| 1527 | | assert(r == "[100,999,0,0]"); |
|---|
| 1528 | | |
|---|
| 1529 | | string[] arr2 = new string[4]; |
|---|
| 1530 | | arr2[0] = "hello"; |
|---|
| 1531 | | arr2[1] = "world"; |
|---|
| 1532 | | arr2[3] = "foo"; |
|---|
| 1533 | | r = swritef(arr2); |
|---|
| 1534 | | assert(r == "[hello,world,,foo]"); |
|---|
| 1535 | | |
|---|
| 1536 | | r = swritef("%.8d", 7); |
|---|
| 1537 | | assert(r == "00000007"); |
|---|
| 1538 | | r = swritef("%.8x", 10); |
|---|
| 1539 | | assert(r == "0000000a"); |
|---|
| 1540 | | |
|---|
| 1541 | | r = swritef("%-3d", 7); |
|---|
| 1542 | | assert(r == "7 "); |
|---|
| 1543 | | |
|---|
| 1544 | | r = swritef("%*d", -3, 7); |
|---|
| 1545 | | assert(r == "7 "); |
|---|
| 1546 | | |
|---|
| 1547 | | r = swritef("%.*d", -3, 7); |
|---|
| 1548 | | assert(r == "7"); |
|---|
| 1549 | | |
|---|
| 1550 | | typedef int myint; |
|---|
| 1551 | | myint m = -7; |
|---|
| 1552 | | r = swritef(m); |
|---|
| 1553 | | assert(r == "-7"); |
|---|
| 1554 | | |
|---|
| 1555 | | r = swritef("abc"c); |
|---|
| 1556 | | assert(r == "abc"); |
|---|
| 1557 | | r = swritef("def"w); |
|---|
| 1558 | | assert(r == "def"); |
|---|
| 1559 | | r = swritef("ghi"d); |
|---|
| 1560 | | assert(r == "ghi"); |
|---|
| 1561 | | |
|---|
| 1562 | | void* p = cast(void*)0xDEADBEEF; |
|---|
| 1563 | | r = swritef(p); |
|---|
| 1564 | | assert(r == "DEADBEEF"); |
|---|
| 1565 | | |
|---|
| 1566 | | r = swritef("%#x", 0xabcd); |
|---|
| 1567 | | assert(r == "0xabcd"); |
|---|
| 1568 | | r = swritef("%#X", 0xABCD); |
|---|
| 1569 | | assert(r == "0XABCD"); |
|---|
| 1570 | | |
|---|
| 1571 | | r = swritef("%#o", 012345); |
|---|
| 1572 | | assert(r == "012345"); |
|---|
| 1573 | | r = swritef("%o", 9); |
|---|
| 1574 | | assert(r == "11"); |
|---|
| 1575 | | |
|---|
| 1576 | | r = swritef("%+d", 123); |
|---|
| 1577 | | assert(r == "+123"); |
|---|
| 1578 | | r = swritef("%+d", -123); |
|---|
| 1579 | | assert(r == "-123"); |
|---|
| 1580 | | r = swritef("% d", 123); |
|---|
| 1581 | | assert(r == " 123"); |
|---|
| 1582 | | r = swritef("% d", -123); |
|---|
| 1583 | | assert(r == "-123"); |
|---|
| 1584 | | |
|---|
| 1585 | | r = swritef("%%"); |
|---|
| 1586 | | assert(r == "%"); |
|---|
| 1587 | | |
|---|
| 1588 | | r = swritef("%d", true); |
|---|
| 1589 | | assert(r == "1"); |
|---|
| 1590 | | r = swritef("%d", false); |
|---|
| 1591 | | assert(r == "0"); |
|---|
| 1592 | | |
|---|
| 1593 | | r = swritef("%d", 'a'); |
|---|
| 1594 | | assert(r == "97"); |
|---|
| 1595 | | wchar wc = 'a'; |
|---|
| 1596 | | r = swritef("%d", wc); |
|---|
| 1597 | | assert(r == "97"); |
|---|
| 1598 | | dchar dc = 'a'; |
|---|
| 1599 | | r = swritef("%d", dc); |
|---|
| 1600 | | assert(r == "97"); |
|---|
| 1601 | | |
|---|
| 1602 | | byte b = byte.max; |
|---|
| 1603 | | r = swritef("%x", b); |
|---|
| 1604 | | assert(r == "7f"); |
|---|
| 1605 | | r = swritef("%x", ++b); |
|---|
| 1606 | | assert(r == "80"); |
|---|
| 1607 | | r = swritef("%x", ++b); |
|---|
| 1608 | | assert(r == "81"); |
|---|
| 1609 | | |
|---|
| 1610 | | short sh = short.max; |
|---|
| 1611 | | r = swritef("%x", sh); |
|---|
| 1612 | | assert(r == "7fff"); |
|---|
| 1613 | | r = swritef("%x", ++sh); |
|---|
| 1614 | | assert(r == "8000"); |
|---|
| 1615 | | r = swritef("%x", ++sh); |
|---|
| 1616 | | assert(r == "8001"); |
|---|
| 1617 | | |
|---|
| 1618 | | i = int.max; |
|---|
| 1619 | | r = swritef("%x", i); |
|---|
| 1620 | | assert(r == "7fffffff"); |
|---|
| 1621 | | r = swritef("%x", ++i); |
|---|
| 1622 | | assert(r == "80000000"); |
|---|
| 1623 | | r = swritef("%x", ++i); |
|---|
| 1624 | | assert(r == "80000001"); |
|---|
| 1625 | | |
|---|
| 1626 | | r = swritef("%x", 10); |
|---|
| 1627 | | assert(r == "a"); |
|---|
| 1628 | | r = swritef("%X", 10); |
|---|
| 1629 | | assert(r == "A"); |
|---|
| 1630 | | r = swritef("%x", 15); |
|---|
| 1631 | | assert(r == "f"); |
|---|
| 1632 | | r = swritef("%X", 15); |
|---|
| 1633 | | assert(r == "F"); |
|---|
| 1634 | | |
|---|
| 1635 | | Object c = null; |
|---|
| 1636 | | r = swritef(c); |
|---|
| 1637 | | assert(r == "null"); |
|---|
| 1638 | | |
|---|
| 1639 | | enum TestEnum |
|---|
| 1640 | | { |
|---|
| 1641 | | Value1, Value2 |
|---|
| 1642 | | } |
|---|
| 1643 | | r = swritef("%s", TestEnum.Value2); |
|---|
| 1644 | | assert(r == "1"); |
|---|
| 1645 | | |
|---|
| 1646 | | char[5][int] aa = ([3:"hello", 4:"betty"]); |
|---|
| 1647 | | r = swritef("%s", aa.values); |
|---|
| 1648 | | assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]"); |
|---|
| 1649 | | r = swritef("%s", aa); |
|---|
| 1650 | | assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]"); |
|---|
| 1651 | | |
|---|
| 1652 | | static const dchar[] ds = ['a','b']; |
|---|
| 1653 | | for (int j = 0; j < ds.length; ++j) |
|---|
| 1654 | | { |
|---|
| | 1378 | else |
|---|
| | 1379 | assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan" || |
|---|
| | 1380 | s == "1.67 -0X1.47AE147AE147BP+0 nan"); |
|---|
| | 1381 | |
|---|
| | 1382 | s = swritef("%x %X", 0x1234AF, 0xAFAFAFAF); |
|---|
| | 1383 | assert(s == "1234af AFAFAFAF"); |
|---|
| | 1384 | |
|---|
| | 1385 | s = swritef("%b %o", 0x1234AF, 0xAFAFAFAF); |
|---|
| | 1386 | assert(s == "100100011010010101111 25753727657"); |
|---|
| | 1387 | |
|---|
| | 1388 | s = swritef("%d %s", 0x1234AF, 0xAFAFAFAF); |
|---|
| | 1389 | assert(s == "1193135 2947526575"); |
|---|
| | 1390 | |
|---|
| | 1391 | s = swritef("%s", 1.2 + 3.4i); |
|---|
| | 1392 | assert(s == "1.2+3.4i"); |
|---|
| | 1393 | |
|---|
| | 1394 | s = swritef("%x %X", 1.32, 6.78f); |
|---|
| | 1395 | assert(s == "3ff51eb851eb851f 40D8F5C3"); |
|---|
| | 1396 | |
|---|
| | 1397 | s = swritef("%#06.*f",2,12.345); |
|---|
| | 1398 | assert(s == "012.35"); |
|---|
| | 1399 | |
|---|
| | 1400 | s = swritef("%#0*.*f",6,2,12.345); |
|---|
| | 1401 | assert(s == "012.35"); |
|---|
| | 1402 | |
|---|
| | 1403 | s = swritef("%7.4g:", 12.678); |
|---|
| | 1404 | assert(s == " 12.68:"); |
|---|
| | 1405 | |
|---|
| | 1406 | s = swritef("%7.4g:", 12.678L); |
|---|
| | 1407 | assert(s == " 12.68:"); |
|---|
| | 1408 | |
|---|
| | 1409 | s = swritef("%04f|%05d|%#05x|%#5x",-4.,-10,1,1); |
|---|
| | 1410 | assert(s == "-4.000000|-0010|0x001| 0x1"); |
|---|
| | 1411 | |
|---|
| | 1412 | i = -10; |
|---|
| | 1413 | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| | 1414 | assert(s == "-10|-10|-10|-10|-10.0000"); |
|---|
| | 1415 | |
|---|
| | 1416 | i = -5; |
|---|
| | 1417 | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| | 1418 | assert(s == "-5| -5|-05|-5|-5.0000"); |
|---|
| | 1419 | |
|---|
| | 1420 | i = 0; |
|---|
| | 1421 | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| | 1422 | assert(s == "0| 0|000|0|0.0000"); |
|---|
| | 1423 | |
|---|
| | 1424 | i = 5; |
|---|
| | 1425 | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| | 1426 | assert(s == "5| 5|005|5|5.0000"); |
|---|
| | 1427 | |
|---|
| | 1428 | i = 10; |
|---|
| | 1429 | s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); |
|---|
| | 1430 | assert(s == "10| 10|010|10|10.0000"); |
|---|
| | 1431 | |
|---|
| | 1432 | s = swritef("%.0d", 0); |
|---|
| | 1433 | assert(s == ""); |
|---|
| | 1434 | |
|---|
| | 1435 | s = swritef("%.g", .34); |
|---|
| | 1436 | assert(s == "0.3"); |
|---|
| | 1437 | |
|---|
| | 1438 | s = swritef("%.0g", .34); |
|---|
| | 1439 | assert(s == "0.3"); |
|---|
| | 1440 | |
|---|
| | 1441 | s = swritef("%.2g", .34); |
|---|
| | 1442 | assert(s == "0.34"); |
|---|
| | 1443 | |
|---|
| | 1444 | s = swritef("%0.0008f", 1e-08); |
|---|
| | 1445 | assert(s == "0.00000001"); |
|---|
| | 1446 | |
|---|
| | 1447 | s = swritef("%0.0008f", 1e-05); |
|---|
| | 1448 | assert(s == "0.00001000"); |
|---|
| | 1449 | |
|---|
| | 1450 | s = "helloworld"; |
|---|
| | 1451 | string r; |
|---|
| | 1452 | r = swritef("%.2s", s[0..5]); |
|---|
| | 1453 | assert(r == "he"); |
|---|
| | 1454 | r = swritef("%.20s", s[0..5]); |
|---|
| | 1455 | assert(r == "hello"); |
|---|
| | 1456 | r = swritef("%8s", s[0..5]); |
|---|
| | 1457 | assert(r == " hello"); |
|---|
| | 1458 | |
|---|
| | 1459 | byte[] arrbyte = new byte[4]; |
|---|
| | 1460 | arrbyte[0] = 100; |
|---|
| | 1461 | arrbyte[1] = -99; |
|---|
| | 1462 | arrbyte[3] = 0; |
|---|
| | 1463 | r = swritef(arrbyte); |
|---|
| | 1464 | assert(r == "[100,-99,0,0]"); |
|---|
| | 1465 | |
|---|
| | 1466 | ubyte[] arrubyte = new ubyte[4]; |
|---|
| | 1467 | arrubyte[0] = 100; |
|---|
| | 1468 | arrubyte[1] = 200; |
|---|
| | 1469 | arrubyte[3] = 0; |
|---|
| | 1470 | r = swritef(arrubyte); |
|---|
| | 1471 | assert(r == "[100,200,0,0]"); |
|---|
| | 1472 | |
|---|
| | 1473 | short[] arrshort = new short[4]; |
|---|
| | 1474 | arrshort[0] = 100; |
|---|
| | 1475 | arrshort[1] = -999; |
|---|
| | 1476 | arrshort[3] = 0; |
|---|
| | 1477 | r = swritef(arrshort); |
|---|
| | 1478 | assert(r == "[100,-999,0,0]"); |
|---|
| | 1479 | r = swritef("%s",arrshort); |
|---|
| | 1480 | assert(r == "[100,-999,0,0]"); |
|---|
| | 1481 | |
|---|
| | 1482 | ushort[] arrushort = new ushort[4]; |
|---|
| | 1483 | arrushort[0] = 100; |
|---|
| | 1484 | arrushort[1] = 20_000; |
|---|
| | 1485 | arrushort[3] = 0; |
|---|
| | 1486 | r = swritef(arrushort); |
|---|
| | 1487 | assert(r == "[100,20000,0,0]"); |
|---|
| | 1488 | |
|---|
| | 1489 | int[] arrint = new int[4]; |
|---|
| | 1490 | arrint[0] = 100; |
|---|
| | 1491 | arrint[1] = -999; |
|---|
| | 1492 | arrint[3] = 0; |
|---|
| | 1493 | r = swritef(arrint); |
|---|
| | 1494 | assert(r == "[100,-999,0,0]"); |
|---|
| | 1495 | r = swritef("%s",arrint); |
|---|
| | 1496 | assert(r == "[100,-999,0,0]"); |
|---|
| | 1497 | |
|---|
| | 1498 | long[] arrlong = new long[4]; |
|---|
| | 1499 | arrlong[0] = 100; |
|---|
| | 1500 | arrlong[1] = -999; |
|---|
| | 1501 | arrlong[3] = 0; |
|---|
| | 1502 | r = swritef(arrlong); |
|---|
| | 1503 | assert(r == "[100,-999,0,0]"); |
|---|
| | 1504 | r = swritef("%s",arrlong); |
|---|
| | 1505 | assert(r == "[100,-999,0,0]"); |
|---|
| | 1506 | |
|---|
| | 1507 | ulong[] arrulong = new ulong[4]; |
|---|
| | 1508 | arrulong[0] = 100; |
|---|
| | 1509 | arrulong[1] = 999; |
|---|
| | 1510 | arrulong[3] = 0; |
|---|
| | 1511 | r = swritef(arrulong); |
|---|
| | 1512 | assert(r == "[100,999,0,0]"); |
|---|
| | 1513 | |
|---|
| | 1514 | string[] arr2 = new string[4]; |
|---|
| | 1515 | arr2[0] = "hello"; |
|---|
| | 1516 | arr2[1] = "world"; |
|---|
| | 1517 | arr2[3] = "foo"; |
|---|
| | 1518 | r = swritef(arr2); |
|---|
| | 1519 | assert(r == "[hello,world,,foo]"); |
|---|
| | 1520 | |
|---|
| | 1521 | r = swritef("%.8d", 7); |
|---|
| | 1522 | assert(r == "00000007"); |
|---|
| | 1523 | r = swritef("%.8x", 10); |
|---|
| | 1524 | assert(r == "0000000a"); |
|---|
| | 1525 | |
|---|
| | 1526 | r = swritef("%-3d", 7); |
|---|
| | 1527 | assert(r == "7 "); |
|---|
| | 1528 | |
|---|
| | 1529 | r = swritef("%*d", -3, 7); |
|---|
| | 1530 | assert(r == "7 "); |
|---|
| | 1531 | |
|---|
| | 1532 | r = swritef("%.*d", -3, 7); |
|---|
| | 1533 | assert(r == "7"); |
|---|
| | 1534 | |
|---|
| | 1535 | typedef int myint; |
|---|
| | 1536 | myint m = -7; |
|---|
| | 1537 | r = swritef(m); |
|---|
| | 1538 | assert(r == "-7"); |
|---|
| | 1539 | |
|---|
| | 1540 | r = swritef("abc"c); |
|---|
| | 1541 | assert(r == "abc"); |
|---|
| | 1542 | r = swritef("def"w); |
|---|
| | 1543 | assert(r == "def"); |
|---|
| | 1544 | r = swritef("ghi"d); |
|---|
| | 1545 | assert(r == "ghi"); |
|---|
| | 1546 | |
|---|
| | 1547 | void* p = cast(void*)0xDEADBEEF; |
|---|
| | 1548 | r = swritef(p); |
|---|
| | 1549 | assert(r == "DEADBEEF"); |
|---|
| | 1550 | |
|---|
| | 1551 | r = swritef("%#x", 0xabcd); |
|---|
| | 1552 | assert(r == "0xabcd"); |
|---|
| | 1553 | r = swritef("%#X", 0xABCD); |
|---|
| | 1554 | assert(r == "0XABCD"); |
|---|
| | 1555 | |
|---|
| | 1556 | r = swritef("%#o", 012345); |
|---|
| | 1557 | assert(r == "012345"); |
|---|
| | 1558 | r = swritef("%o", 9); |
|---|
| | 1559 | assert(r == "11"); |
|---|
| | 1560 | |
|---|
| | 1561 | r = swritef("%+d", 123); |
|---|
| | 1562 | assert(r == "+123"); |
|---|
| | 1563 | r = swritef("%+d", -123); |
|---|
| | 1564 | assert(r == "-123"); |
|---|
| | 1565 | r = swritef("% d", 123); |
|---|
| | 1566 | assert(r == " 123"); |
|---|
| | 1567 | r = swritef("% d", -123); |
|---|
| | 1568 | assert(r == "-123"); |
|---|
| | 1569 | |
|---|
| | 1570 | r = swritef("%%"); |
|---|
| | 1571 | assert(r == "%"); |
|---|
| | 1572 | |
|---|
| | 1573 | r = swritef("%d", true); |
|---|
| | 1574 | assert(r == "1"); |
|---|
| | 1575 | r = swritef("%d", false); |
|---|
| | 1576 | assert(r == "0"); |
|---|
| | 1577 | |
|---|
| | 1578 | r = swritef("%d", 'a'); |
|---|
| | 1579 | assert(r == "97"); |
|---|
| | 1580 | wchar wc = 'a'; |
|---|
| | 1581 | r = swritef("%d", wc); |
|---|
| | 1582 | assert(r == "97"); |
|---|
| | 1583 | dchar dc = 'a'; |
|---|
| | 1584 | r = swritef("%d", dc); |
|---|
| | 1585 | assert(r == "97"); |
|---|
| | 1586 | |
|---|
| | 1587 | byte b = byte.max; |
|---|
| | 1588 | r = swritef("%x", b); |
|---|
| | 1589 | assert(r == "7f"); |
|---|
| | 1590 | r = swritef("%x", ++b); |
|---|
| | 1591 | assert(r == "80"); |
|---|
| | 1592 | r = swritef("%x", ++b); |
|---|
| | 1593 | assert(r == "81"); |
|---|
| | 1594 | |
|---|
| | 1595 | short sh = short.max; |
|---|
| | 1596 | r = swritef("%x", sh); |
|---|
| | 1597 | assert(r == "7fff"); |
|---|
| | 1598 | r = swritef("%x", ++sh); |
|---|
| | 1599 | assert(r == "8000"); |
|---|
| | 1600 | r = swritef("%x", ++sh); |
|---|
| | 1601 | assert(r == "8001"); |
|---|
| | 1602 | |
|---|
| | 1603 | i = int.max; |
|---|
| | 1604 | r = swritef("%x", i); |
|---|
| | 1605 | assert(r == "7fffffff"); |
|---|
| | 1606 | r = swritef("%x", ++i); |
|---|
| | 1607 | assert(r == "80000000"); |
|---|
| | 1608 | r = swritef("%x", ++i); |
|---|
| | 1609 | assert(r == "80000001"); |
|---|
| | 1610 | |
|---|
| | 1611 | r = swritef("%x", 10); |
|---|
| | 1612 | assert(r == "a"); |
|---|
| | 1613 | r = swritef("%X", 10); |
|---|
| | 1614 | assert(r == "A"); |
|---|
| | 1615 | r = swritef("%x", 15); |
|---|
| | 1616 | assert(r == "f"); |
|---|
| | 1617 | r = swritef("%X", 15); |
|---|
| | 1618 | assert(r == "F"); |
|---|
| | 1619 | |
|---|
| | 1620 | Object c = null; |
|---|
| | 1621 | r = swritef(c); |
|---|
| | 1622 | assert(r == "null"); |
|---|
| | 1623 | |
|---|
| | 1624 | enum TestEnum |
|---|
| | 1625 | { |
|---|
| | 1626 | Value1, Value2 |
|---|
| | 1627 | } |
|---|
| | 1628 | r = swritef("%s", TestEnum.Value2); |
|---|
| | 1629 | assert(r == "1"); |
|---|
| | 1630 | |
|---|
| | 1631 | char[5][int] aa = ([3:"hello", 4:"betty"]); |
|---|
| | 1632 | r = swritef("%s", aa.values); |
|---|
| | 1633 | assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]"); |
|---|
| | 1634 | r = swritef("%s", aa); |
|---|
| | 1635 | assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]"); |
|---|
| | 1636 | |
|---|
| | 1637 | static const dchar[] ds = ['a','b']; |
|---|
| | 1638 | for (int j = 0; j < ds.length; ++j) |
|---|
| | 1639 | { |
|---|