Mercurial > hg > xemacs-beta
comparison src/doprnt.c @ 446:1ccc32a20af4 r21-2-38
Import from CVS: tag r21-2-38
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:37:21 +0200 |
parents | 576fb035e263 |
children | 3078fd1074e8 |
comparison
equal
deleted
inserted
replaced
445:34f3776fcf0e | 446:1ccc32a20af4 |
---|---|
29 #include "lisp.h" | 29 #include "lisp.h" |
30 | 30 |
31 #include "buffer.h" | 31 #include "buffer.h" |
32 #include "lstream.h" | 32 #include "lstream.h" |
33 | 33 |
34 static const char *valid_flags = "-+ #0"; | 34 static const char * const valid_flags = "-+ #0"; |
35 | 35 static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS"; |
36 static const char *valid_converters = "diouxXfeEgGcsS"; | 36 static const char * const int_converters = "dic"; |
37 static const char *int_converters = "dic"; | 37 static const char * const unsigned_int_converters = "ouxX"; |
38 static const char *unsigned_int_converters = "ouxX"; | 38 static const char * const double_converters = "feEgG"; |
39 static const char *double_converters = "feEgG"; | 39 static const char * const string_converters = "sS"; |
40 static const char *string_converters = "sS"; | |
41 | 40 |
42 typedef struct printf_spec printf_spec; | 41 typedef struct printf_spec printf_spec; |
43 struct printf_spec | 42 struct printf_spec |
44 { | 43 { |
45 int argnum; /* which argument does this spec want? This is one-based: | 44 int argnum; /* which argument does this spec want? This is one-based: |
64 }; | 63 }; |
65 | 64 |
66 typedef union printf_arg printf_arg; | 65 typedef union printf_arg printf_arg; |
67 union printf_arg | 66 union printf_arg |
68 { | 67 { |
69 int i; | |
70 unsigned int ui; | |
71 long l; | 68 long l; |
72 unsigned long ul; | 69 unsigned long ul; |
73 double d; | 70 double d; |
74 Bufbyte *bp; | 71 Bufbyte *bp; |
75 }; | 72 }; |
235 NEXT_ASCII_BYTE (ch); | 232 NEXT_ASCII_BYTE (ch); |
236 while (strchr (valid_flags, ch)) | 233 while (strchr (valid_flags, ch)) |
237 { | 234 { |
238 switch (ch) | 235 switch (ch) |
239 { | 236 { |
240 case '-': spec.minus_flag = 1; break; | 237 case '-': spec.minus_flag = 1; break; |
241 case '+': spec.plus_flag = 1; break; | 238 case '+': spec.plus_flag = 1; break; |
242 case ' ': spec.space_flag = 1; break; | 239 case ' ': spec.space_flag = 1; break; |
243 case '#': spec.number_flag = 1; break; | 240 case '#': spec.number_flag = 1; break; |
244 case '0': spec.zero_flag = 1; break; | 241 case '0': spec.zero_flag = 1; break; |
245 default: abort (); | 242 default: abort (); |
246 } | 243 } |
247 NEXT_ASCII_BYTE (ch); | 244 NEXT_ASCII_BYTE (ch); |
248 } | 245 } |
249 | 246 |
378 if (j == Dynarr_length (specs)) | 375 if (j == Dynarr_length (specs)) |
379 error ("No conversion spec for argument %d", i); | 376 error ("No conversion spec for argument %d", i); |
380 | 377 |
381 ch = spec->converter; | 378 ch = spec->converter; |
382 | 379 |
383 /* int even if ch == 'c': "the type used in va_arg is supposed to | |
384 match the actual type **after default promotions**." */ | |
385 | |
386 if (strchr (int_converters, ch)) | 380 if (strchr (int_converters, ch)) |
387 { | 381 { |
388 if (spec->h_flag) | 382 if (spec->l_flag) |
389 arg.i = va_arg (vargs, int /* short */); | |
390 else if (spec->l_flag) | |
391 arg.l = va_arg (vargs, long); | 383 arg.l = va_arg (vargs, long); |
392 else | 384 else |
393 arg.i = va_arg (vargs, int); | 385 /* int even if ch == 'c' or spec->h_flag: |
386 "the type used in va_arg is supposed to match the | |
387 actual type **after default promotions**." | |
388 Hence we read an int, not a short, if spec->h_flag. */ | |
389 arg.l = va_arg (vargs, int); | |
394 } | 390 } |
395 else if (strchr (unsigned_int_converters, ch)) | 391 else if (strchr (unsigned_int_converters, ch)) |
396 { | 392 { |
397 if (spec->h_flag) | 393 if (spec->l_flag) |
398 arg.ui = va_arg (vargs, unsigned int /* unsigned short */); | |
399 else if (spec->l_flag) | |
400 arg.ul = va_arg (vargs, unsigned long); | 394 arg.ul = va_arg (vargs, unsigned long); |
401 else | 395 else |
402 arg.ui = va_arg (vargs, unsigned int); | 396 /* unsigned int even if ch == 'c' or spec->h_flag */ |
397 arg.ul = (unsigned long) va_arg (vargs, unsigned int); | |
403 } | 398 } |
404 else if (strchr (double_converters, ch)) | 399 else if (strchr (double_converters, ch)) |
405 arg.d = va_arg (vargs, double); | 400 arg.d = va_arg (vargs, double); |
406 else if (strchr (string_converters, ch)) | 401 else if (strchr (string_converters, ch)) |
407 arg.bp = va_arg (vargs, Bufbyte *); | 402 arg.bp = va_arg (vargs, Bufbyte *); |
443 format_length = (Bytecount) strlen ((const char *) format_nonreloc); | 438 format_length = (Bytecount) strlen ((const char *) format_nonreloc); |
444 | 439 |
445 specs = parse_doprnt_spec (format_nonreloc, format_length); | 440 specs = parse_doprnt_spec (format_nonreloc, format_length); |
446 if (largs) | 441 if (largs) |
447 { | 442 { |
448 /* allow too many args for string, but not too few */ | 443 /* allow too many args for string, but not too few */ |
449 if (nargs < get_args_needed (specs)) | 444 if (nargs < get_args_needed (specs)) |
450 signal_error (Qwrong_number_of_arguments, | 445 signal_error (Qwrong_number_of_arguments, |
451 list3 (Qformat, | 446 list3 (Qformat, |
452 make_int (nargs), | 447 make_int (nargs), |
453 !NILP (format_reloc) ? format_reloc : | 448 !NILP (format_reloc) ? format_reloc : |
464 char ch; | 459 char ch; |
465 | 460 |
466 /* Copy the text before */ | 461 /* Copy the text before */ |
467 if (!NILP (format_reloc)) /* refetch in case of GC below */ | 462 if (!NILP (format_reloc)) /* refetch in case of GC below */ |
468 format_nonreloc = XSTRING_DATA (format_reloc); | 463 format_nonreloc = XSTRING_DATA (format_reloc); |
469 doprnt_1 (stream, format_nonreloc + spec->text_before, | 464 |
470 spec->text_before_len, 0, -1, 0, 0); | 465 doprnt_1 (stream, format_nonreloc + spec->text_before, |
466 spec->text_before_len, 0, -1, 0, 0); | |
471 | 467 |
472 ch = spec->converter; | 468 ch = spec->converter; |
473 | 469 |
474 if (!ch) | 470 if (!ch) |
475 continue; | 471 continue; |
496 nextspec->minwidth = spec->minwidth; | 492 nextspec->minwidth = spec->minwidth; |
497 } | 493 } |
498 else | 494 else |
499 { | 495 { |
500 nextspec->minwidth = XINT (obj); | 496 nextspec->minwidth = XINT (obj); |
501 if (XINT(obj) < 0) | 497 if (XINT (obj) < 0) |
502 { | 498 { |
503 spec->minus_flag = 1; | 499 spec->minus_flag = 1; |
504 nextspec->minwidth = - nextspec->minwidth; | 500 nextspec->minwidth = - nextspec->minwidth; |
505 } | 501 } |
506 } | 502 } |
507 nextspec->minus_flag = spec->minus_flag; | 503 nextspec->minus_flag = spec->minus_flag; |
508 nextspec->plus_flag = spec->plus_flag; | 504 nextspec->plus_flag = spec->plus_flag; |
509 nextspec->space_flag = spec->space_flag; | 505 nextspec->space_flag = spec->space_flag; |
510 nextspec->number_flag = spec->number_flag; | 506 nextspec->number_flag = spec->number_flag; |
511 nextspec->zero_flag = spec->zero_flag; | 507 nextspec->zero_flag = spec->zero_flag; |
512 } | 508 } |
513 continue; | 509 continue; |
514 } | 510 } |
515 | 511 |
516 if (largs && (spec->argnum < 1 || spec->argnum > nargs)) | 512 if (largs && (spec->argnum < 1 || spec->argnum > nargs)) |
584 } | 580 } |
585 else if (strchr (double_converters, ch)) | 581 else if (strchr (double_converters, ch)) |
586 arg.d = XFLOATINT (obj); | 582 arg.d = XFLOATINT (obj); |
587 else | 583 else |
588 { | 584 { |
589 int val; | |
590 | |
591 if (FLOATP (obj)) | 585 if (FLOATP (obj)) |
592 val = XINT (Ftruncate (obj)); | 586 obj = Ftruncate (obj); |
587 | |
588 if (strchr (unsigned_int_converters, ch)) | |
589 arg.ul = (unsigned long) XINT (obj); | |
593 else | 590 else |
594 val = XINT (obj); | 591 arg.l = XINT (obj); |
595 if (strchr (unsigned_int_converters, ch)) | |
596 { | |
597 if (spec->l_flag) | |
598 arg.ul = (unsigned long) val; | |
599 else | |
600 arg.ui = (unsigned int) val; | |
601 } | |
602 else | |
603 { | |
604 if (spec->l_flag) | |
605 arg.l = (long) val; | |
606 else | |
607 arg.i = val; | |
608 } | |
609 } | 592 } |
610 } | 593 } |
611 | 594 |
612 | 595 |
613 if (ch == 'c') | 596 if (ch == 'c') |
614 { | 597 { |
615 Emchar a; | 598 Emchar a; |
616 Bytecount charlen; | 599 Bytecount charlen; |
617 Bufbyte charbuf[MAX_EMCHAR_LEN]; | 600 Bufbyte charbuf[MAX_EMCHAR_LEN]; |
618 | 601 |
619 if (spec->l_flag) | 602 a = (Emchar) arg.l; |
620 a = (Emchar) arg.l; | |
621 else | |
622 a = (Emchar) arg.i; | |
623 | 603 |
624 if (!valid_char_p (a)) | 604 if (!valid_char_p (a)) |
625 error ("invalid character value %d to %%c spec", a); | 605 error ("invalid character value %d to %%c spec", a); |
626 | 606 |
627 charlen = set_charptr_emchar (charbuf, a); | 607 charlen = set_charptr_emchar (charbuf, a); |
628 doprnt_1 (stream, charbuf, charlen, spec->minwidth, | 608 doprnt_1 (stream, charbuf, charlen, spec->minwidth, |
629 -1, spec->minus_flag, spec->zero_flag); | 609 -1, spec->minus_flag, spec->zero_flag); |
630 } | 610 } |
631 | |
632 else | 611 else |
633 { | 612 { |
634 char text_to_print[500]; | 613 char text_to_print[500]; |
635 char constructed_spec[100]; | 614 char constructed_spec[100]; |
615 char *p = constructed_spec; | |
636 | 616 |
637 /* Partially reconstruct the spec and use sprintf() to | 617 /* Partially reconstruct the spec and use sprintf() to |
638 format the string. */ | 618 format the string. */ |
639 | 619 |
640 /* Make sure nothing stupid happens */ | 620 /* Make sure nothing stupid happens */ |
641 /* DO NOT REMOVE THE (int) CAST! Incorrect results will | 621 /* DO NOT REMOVE THE (int) CAST! Incorrect results will |
642 follow! */ | 622 follow! */ |
643 spec->precision = min (spec->precision, | 623 spec->precision = min (spec->precision, |
644 (int) (sizeof (text_to_print) - 50)); | 624 (int) (sizeof (text_to_print) - 50)); |
645 | 625 |
646 constructed_spec[0] = 0; | 626 *p++ = '%'; |
647 strcat (constructed_spec, "%"); | 627 if (spec->plus_flag) *p++ = '+'; |
648 if (spec->plus_flag) | 628 if (spec->space_flag) *p++ = ' '; |
649 strcat (constructed_spec, "+"); | 629 if (spec->number_flag) *p++ = '#'; |
650 if (spec->space_flag) | 630 |
651 strcat (constructed_spec, " "); | |
652 if (spec->number_flag) | |
653 strcat (constructed_spec, "#"); | |
654 if (spec->precision >= 0 && !spec->minwidth) | 631 if (spec->precision >= 0 && !spec->minwidth) |
655 { | 632 { |
656 strcat (constructed_spec, "."); | 633 *p++ = '.'; |
657 long_to_string (constructed_spec + strlen (constructed_spec), | 634 p = long_to_string (p, spec->precision); |
658 spec->precision); | |
659 } | 635 } |
660 | 636 |
661 /* sprintf the mofo */ | 637 /* sprintf the mofo */ |
662 /* we have to use separate calls to sprintf(), rather than | 638 /* we have to use separate calls to sprintf(), rather than |
663 a single big conditional, because of the different types | 639 a single big conditional, because of the different types |
664 of the arguments */ | 640 of the arguments */ |
665 if (strchr (double_converters, ch)) | 641 if (strchr (double_converters, ch)) |
666 { | 642 { |
667 sprintf (constructed_spec + strlen (constructed_spec), | 643 *p++ = ch; |
668 "%c", ch); | 644 *p++ = '\0'; |
669 sprintf (text_to_print, constructed_spec, arg.d); | 645 sprintf (text_to_print, constructed_spec, arg.d); |
670 } | 646 } |
671 else if (strchr (unsigned_int_converters, ch)) | 647 else |
672 { | 648 { |
673 sprintf (constructed_spec + strlen (constructed_spec), | 649 if (spec->zero_flag && spec->minwidth) |
674 "%c", ch); | 650 sprintf (p, "0%dl%c", spec->minwidth, ch); |
675 if (spec->l_flag) | 651 else |
652 sprintf (p, "l%c", ch); | |
653 | |
654 if (strchr (unsigned_int_converters, ch)) | |
676 sprintf (text_to_print, constructed_spec, arg.ul); | 655 sprintf (text_to_print, constructed_spec, arg.ul); |
677 else | 656 else |
678 sprintf (text_to_print, constructed_spec, arg.ui); | |
679 } | |
680 else | |
681 { | |
682 if (spec->zero_flag && spec->minwidth) | |
683 sprintf (constructed_spec + strlen (constructed_spec), | |
684 "0%d%c", spec->minwidth, ch); | |
685 else | |
686 sprintf (constructed_spec + strlen (constructed_spec), | |
687 "%c", ch); | |
688 if (spec->l_flag) | |
689 sprintf (text_to_print, constructed_spec, arg.l); | 657 sprintf (text_to_print, constructed_spec, arg.l); |
690 else | |
691 sprintf (text_to_print, constructed_spec, arg.i); | |
692 } | 658 } |
693 | 659 |
694 doprnt_1 (stream, (Bufbyte *) text_to_print, | 660 doprnt_1 (stream, (Bufbyte *) text_to_print, |
695 strlen (text_to_print), | 661 strlen (text_to_print), |
696 spec->minwidth, -1, spec->minus_flag, spec->zero_flag); | 662 spec->minwidth, -1, spec->minus_flag, spec->zero_flag); |