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);