]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
9377b393e4237199b50bbb8fc774427bce307a19
1 /* fmt_scan.c -- format string interpretation
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
7 * This is the engine that processes the format instructions created by
8 * fmt_compile (found in fmt_compile.c).
12 #include <h/addrsbr.h>
13 #include <h/fmt_scan.h>
15 #include <h/fmt_compile.h>
18 #ifdef HAVE_SYS_TIME_H
19 # include <sys/time.h>
22 #ifdef MULTIBYTE_SUPPORT
27 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
33 static int match (char *, char *);
34 static char *get_x400_friendly (char *, char *, int);
35 static int get_x400_comp (char *, char *, char *, int);
39 * test if string "sub" appears anywhere in
40 * string "str" (case insensitive).
44 match (char *str
, char *sub
)
50 c1
= tolower((unsigned char)c1
);
51 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
55 s1
= sub
+ 1; s2
= str
;
56 while ((c1
= *s1
++) &&
57 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
66 * copy a number to the destination subject to a maximum width
69 cpnumber(charstring_t dest
, int num
, unsigned int wid
, char fill
, size_t max
) {
70 if (wid
< (num
>= 0 ? max
: max
-1)) {
71 /* Build up the string representation of num in reverse. */
72 charstring_t rev
= charstring_create (0);
73 int i
= num
>= 0 ? num
: -num
;
76 charstring_push_back (rev
, i
% 10 + '0');
78 } while (--wid
> 0 && i
> 0);
80 /* Overflowed the field (wid). */
81 charstring_push_back (rev
, '?');
82 } else if (num
< 0 && wid
> 0) {
83 /* Shouldn't need the wid > 0 check, that's why the condition
84 at the top checks wid < max-1 when num < 0. */
87 charstring_push_back (rev
, '-');
90 while (wid
-- > 0 && fill
!= 0) {
91 charstring_push_back (rev
, fill
);
93 if (num
< 0 && fill
== '0') {
94 charstring_push_back (rev
, '-');
98 /* Output the string in reverse. */
99 size_t b
= charstring_bytes (rev
);
100 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
103 charstring_push_back (dest
, *--cp
);
107 charstring_free (rev
);
112 * copy string from str to dest padding with the fill character to a
113 * size of wid characters. if wid is negative, the string is right
114 * aligned no more than max characters are copied
117 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
) {
118 int remaining
; /* remaining output width available */
120 size_t end
; /* number of input bytes remaining in str */
121 #ifdef MULTIBYTE_SUPPORT
122 int char_len
; /* bytes in current character */
127 char *sp
; /* current position in source string */
132 if ((remaining
= wid
) < 0) {
133 remaining
= -remaining
;
136 if (remaining
> (int) max
) { remaining
= max
; }
139 #ifdef MULTIBYTE_SUPPORT
140 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
143 while (*sp
&& remaining
> 0 && end
> 0) {
144 #ifdef MULTIBYTE_SUPPORT
145 char_len
= mbtowc(&wide_char
, sp
, end
);
148 * See the relevant comments in cpstripped() to explain what's
149 * going on here; we want to handle the case where we get
150 * characters that mbtowc() cannot handle
155 char_len
= mbtowc(&wide_char
, altstr
, 1);
162 w
= wcwidth(wide_char
);
164 /* If w > remaining, w must be positive. */
171 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
176 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
177 intentionally warns if they are passed a char. */
178 c
= (unsigned char) *sp
;
179 if (iscntrl(c
) || isspace(c
)) {
183 charstring_push_back (dest
, ' ');
192 #ifdef MULTIBYTE_SUPPORT
193 if (w
>= 0 && remaining
>= w
) {
194 charstring_push_back_chars (dest
, altstr
? altstr
: sp
,
201 charstring_push_back (dest
, *sp
++);
209 /* copy string to the right */
210 charstring_t copy
= charstring_copy (dest
);
212 /* add padding at the beginning */
213 charstring_clear (dest
);
214 for (; remaining
> 0; --remaining
) {
215 charstring_push_back (dest
, fill
);
218 charstring_append (dest
, copy
);
220 charstring_free (copy
);
223 /* pad remaining space */
224 while (remaining
-- > 0) {
225 charstring_push_back (dest
, fill
);
231 cpstripped (charstring_t dest
, size_t max
, char *str
)
233 int prevCtrl
= 1; /* This is 1 so we strip out leading spaces */
235 #ifdef MULTIBYTE_SUPPORT
239 #endif /* MULTIBYTE_SUPPORT */
247 #ifdef MULTIBYTE_SUPPORT
248 if (mbtowc(NULL
, NULL
, 0)) {} /* Reset shift state */
249 #endif /* MULTIBYTE_SUPPORT */
252 * Process each character at a time; if we have multibyte support
253 * then deal with that here.
256 while (*str
!= '\0' && len
> 0 && max
> 0) {
257 #ifdef MULTIBYTE_SUPPORT
258 char_len
= mbtowc(&wide_char
, str
, len
);
261 * If mbrtowc() failed, then we have a character that isn't valid
262 * in the current encoding, or len wasn't enough for the whole
263 * multi-byte rune to be read. Replace it with a '?'. We do that by
264 * setting the alstr variable to the value of the replacement string;
265 * altstr is used below when the bytes are copied into the output
270 char_len
= mbtowc(&wide_char
, altstr
, 1);
279 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
281 #else /* MULTIBYTE_SUPPORT */
282 int c
= (unsigned char) *str
;
284 if (iscntrl(c
) || isspace(c
)) {
286 #endif /* MULTIBYTE_SUPPORT */
288 charstring_push_back (dest
, ' ');
298 #ifdef MULTIBYTE_SUPPORT
299 w
= wcwidth(wide_char
);
301 if (max
>= (size_t) w
) {
302 charstring_push_back_chars (dest
, altstr
? altstr
: str
, char_len
, w
);
307 /* Not enough width available for the last character. Output
310 charstring_push_back (dest
, ' ');
314 #else /* MULTIBYE_SUPPORT */
315 charstring_push_back (dest
, *str
++);
317 #endif /* MULTIBYTE_SUPPORT */
321 static char *lmonth
[] = { "January", "February","March", "April",
322 "May", "June", "July", "August",
323 "September","October", "November","December" };
326 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
328 char given
[BUFSIZ
], surname
[BUFSIZ
];
337 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
338 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
344 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
347 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
348 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
350 snprintf (buffer
, buffer_len
, "%s", surname
);
356 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
361 if ((idx
= stringdex (key
, mbox
)) < 0
362 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
365 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
370 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
371 struct fmt_callbacks
*callbacks
)
375 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
386 * max is the same as width, but unsigned so comparisons
387 * with charstring_chars() won't raise compile warnings.
390 savestr
= str
= NULL
;
393 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
394 switch (fmt
->f_type
) {
397 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
402 case FT_LS_DECODECOMP
:
404 * Trim these components of any newlines.
406 * But don't trim the "body" and "text" components.
411 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
412 (i
= strlen(comp
->c_text
)) > 0) {
413 if (comp
->c_text
[i
- 1] == '\n' &&
414 strcmp(comp
->c_name
, "body") != 0 &&
415 strcmp(comp
->c_name
, "text") != 0)
416 comp
->c_text
[i
- 1] = '\0';
417 comp
->c_flags
|= CF_TRIMMED
;
424 for ( ; charstring_chars (scanlp
) < max
; ) {
425 switch (fmt
->f_type
) {
428 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
429 fmt
->f_comp
->c_text
);
432 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
433 fmt
->f_fill
, max
- charstring_chars (scanlp
));
438 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
439 charstring_push_back (scanlp
, c
);
448 rjust
++; /* XXX should do something with this */
450 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
451 charstring_push_back (scanlp
, c
);
453 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
454 charstring_push_back (scanlp
, fmt
->f_fill
);
459 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
462 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
463 max
- charstring_chars (scanlp
));
468 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
469 charstring_push_back (scanlp
, c
);
474 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
477 adios (NULL
, "internal error (FT_STRFW)");
483 for (wid
= num
<= 0 ? 1 : 0; num
; ++wid
, num
/= 10) {}
484 cpnumber (scanlp
, value
, wid
, ' ',
485 max
- charstring_chars (scanlp
));
492 unsigned int whole
, tenths
;
493 unsigned int scale
= 0;
494 unsigned int val
= (unsigned int)value
;
495 char *kibisuff
= NULL
;
497 switch (fmt
->f_type
) {
498 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
499 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
503 snprintf(buffer
, sizeof(buffer
), "%u", val
);
505 /* To prevent divide by 0, found by clang static
507 if (scale
== 0) { scale
= 1; }
509 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
510 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
516 strcpy(buffer
, "huge");
518 /* val is scale times too big. we want tenths */
526 tenths
= val
- (whole
* 10);
529 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
530 whole
, tenths
, *unitcp
, kibisuff
);
532 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
533 whole
, *unitcp
, kibisuff
);
541 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
542 max
- charstring_chars (scanlp
));
546 charstring_push_back (scanlp
, fmt
->f_char
);
550 if (callbacks
&& callbacks
->trace_func
)
551 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
552 str
, charstring_buffer (scanlp
));
556 if (!(value
= (str
&& *str
))) {
557 if (callbacks
&& callbacks
->trace_func
)
558 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
559 str
, charstring_buffer (scanlp
));
566 if (!(value
= (str
== NULL
|| *str
== 0))) {
567 if (callbacks
&& callbacks
->trace_func
)
568 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
569 str
, charstring_buffer (scanlp
));
576 if (value
!= fmt
->f_value
) {
577 if (callbacks
&& callbacks
->trace_func
)
578 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
579 str
, charstring_buffer (scanlp
));
586 if (value
== fmt
->f_value
) {
587 if (callbacks
&& callbacks
->trace_func
)
588 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
589 str
, charstring_buffer (scanlp
));
596 if (value
<= fmt
->f_value
) {
597 if (callbacks
&& callbacks
->trace_func
)
598 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
599 str
, charstring_buffer (scanlp
));
606 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
607 if (callbacks
&& callbacks
->trace_func
)
608 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
609 str
, charstring_buffer (scanlp
));
617 value
= match (str
, fmt
->f_text
);
623 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
624 if (callbacks
&& callbacks
->trace_func
)
625 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
626 str
, charstring_buffer (scanlp
));
633 value
= uprf (str
, fmt
->f_text
);
637 value
= (str
!= NULL
&& *str
!= 0);
641 value
= (str
== NULL
|| *str
== 0);
645 value
= (fmt
->f_value
== value
);
649 value
= (fmt
->f_value
!= value
);
653 value
= (fmt
->f_value
> value
);
657 if (callbacks
&& callbacks
->trace_func
)
658 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
659 str
, charstring_buffer (scanlp
));
667 str
= fmt
->f_comp
->c_text
;
673 if (!(str
= getenv (fmt
->f_text
)))
677 if (!(str
= context_find (fmt
->f_text
)))
681 case FT_LS_DECODECOMP
:
682 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
685 str
= fmt
->f_comp
->c_text
;
689 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
698 strncpy(buffer
, str
, sizeof(buffer
));
699 buffer
[sizeof(buffer
)-1] = '\0';
701 while (isspace((unsigned char) *str
))
704 if ((i
= fmt
->f_width
) < 0) {
709 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
712 xp
+= strlen(str
) - 1;
713 while (xp
> str
&& isspace((unsigned char) *xp
))
715 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
716 str
+= strlen(str
) - i
;
721 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
724 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
727 value
= fmt
->f_value
;
730 value
= dat
[fmt
->f_value
];
738 case FT_LV_CHAR_LEFT
:
739 value
= max
- charstring_bytes (scanlp
);
742 value
+= fmt
->f_value
;
745 value
= fmt
->f_value
- value
;
747 case FT_LV_MULTIPLY_L
:
748 value
*= fmt
->f_value
;
752 value
/= fmt
->f_value
;
758 value
%= fmt
->f_value
;
767 value
= fmt
->f_comp
->c_tws
->tw_sec
;
770 value
= fmt
->f_comp
->c_tws
->tw_min
;
773 value
= fmt
->f_comp
->c_tws
->tw_hour
;
776 value
= fmt
->f_comp
->c_tws
->tw_mday
;
779 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
782 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
785 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
788 str
= dtwszone (fmt
->f_comp
->c_tws
);
791 value
= fmt
->f_comp
->c_tws
->tw_year
;
794 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
796 value
= tws
->tw_wday
;
799 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
801 str
= tw_dotw
[tws
->tw_wday
];
804 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
806 str
= tw_ldotw
[tws
->tw_wday
];
809 value
= fmt
->f_comp
->c_tws
->tw_yday
;
812 value
= fmt
->f_comp
->c_tws
->tw_zone
;
815 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
816 value
= dmktime(fmt
->f_comp
->c_tws
);
819 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
820 value
= dmktime(fmt
->f_comp
->c_tws
);
821 value
= time((time_t *) 0) - value
;
824 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
826 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
836 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
842 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
845 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
848 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
852 str
= fmt
->f_comp
->c_mn
->m_pers
;
855 str
= fmt
->f_comp
->c_mn
->m_mbox
;
858 str
= fmt
->f_comp
->c_mn
->m_host
;
861 str
= fmt
->f_comp
->c_mn
->m_path
;
864 str
= fmt
->f_comp
->c_mn
->m_gname
;
867 str
= fmt
->f_comp
->c_mn
->m_note
;
870 str
= adrformat( fmt
->f_comp
->c_mn
);
873 value
= fmt
->f_comp
->c_mn
->m_type
;
876 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
879 value
= fmt
->f_comp
->c_mn
->m_nohost
;
883 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
884 str
= fmt
->f_comp
->c_text
;
887 if (fmt
->f_type
== FT_LS_ADDR
)
889 if ((str
= mn
->m_pers
) == NULL
) {
890 if ((str
= mn
->m_note
)) {
892 strncpy (buffer
, str
, sizeof(buffer
));
893 buffer
[sizeof(buffer
)-1] = '\0';
897 sp
= str
+ strlen(str
) - 1;
906 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
907 buffer
, sizeof(buffer
)))) {
909 switch (mn
->m_type
) {
914 snprintf (buffer
, sizeof(buffer
), "%s!%s",
915 mn
->m_host
, mn
->m_mbox
);
920 snprintf (buffer
, sizeof(buffer
), "%s@%s",
921 mn
->m_mbox
, mn
->m_host
);
933 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
937 strncpy(buffer
, str
, sizeof(buffer
));
938 /* strncpy doesn't NUL-terminate if it fills the buffer */
939 buffer
[sizeof(buffer
)-1] = '\0';
940 unquote_string(buffer
, buffer2
);
947 if ((t
= comp
->c_tws
->tw_clock
) == 0)
948 t
= dmktime(comp
->c_tws
);
949 tws
= dlocaltime(&t
);
955 if ((t
= comp
->c_tws
->tw_clock
) == 0)
956 t
= dmktime(comp
->c_tws
);
963 if (comp
->c_flags
& CF_PARSED
)
965 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
967 comp
->c_flags
&= ~CF_TRUE
;
968 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
969 memset (comp
->c_tws
, 0, sizeof *comp
->c_tws
);
970 comp
->c_flags
= CF_TRUE
;
972 comp
->c_flags
|= CF_PARSED
;
976 /* hook for custom address list formatting (see replsbr.c) */
977 if (callbacks
&& callbacks
->formataddr
)
978 str
= callbacks
->formataddr (savestr
, str
);
980 str
= formataddr (savestr
, str
);
984 /* The same as formataddr, but doesn't do duplicate suppression */
985 if (callbacks
&& callbacks
->concataddr
)
986 str
= callbacks
->concataddr (savestr
, str
);
988 str
= concataddr (savestr
, str
);
992 /* output the str register as an address component,
993 * splitting it into multiple lines if necessary. The
994 * value reg. contains the max line length. The lit.
995 * field may contain a string to prepend to the result
1000 int indent
, wid
, len
;
1004 len
= str
? strlen (str
) : 0;
1006 indent
= strlen (sp
);
1009 adios(NULL
, "putaddr -- num register (%d) must be greater "
1010 "than label width (%d)", value
, indent
);
1012 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1013 charstring_push_back (scanlp
, c
);
1016 /* try to break at a comma; failing that, break at a
1019 lastb
= 0; sp
= lp
+ wid
;
1020 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1021 if (! lastb
&& isspace(c
))
1025 if (! (sp
= lastb
)) {
1027 while (*sp
&& *sp
!= ',' &&
1028 !isspace((unsigned char) *sp
))
1035 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1036 charstring_push_back (scanlp
, *lp
++);
1038 while (isspace((unsigned char) *lp
))
1041 if (charstring_chars (scanlp
) < max
) {
1042 charstring_push_back (scanlp
, '\n');
1045 charstring_chars (scanlp
) < max
&& i
> 0;
1047 charstring_push_back (scanlp
, ' ');
1050 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1056 if (comp
->c_flags
& CF_PARSED
)
1058 if (comp
->c_mn
!= &fmt_mnull
)
1059 mnfree (comp
->c_mn
);
1060 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1061 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1065 comp
->c_flags
|= CF_PARSED
;
1067 while (getname("")) /* XXX */
1069 comp
->c_mn
= &fmt_mnull
;
1077 * if there's no component, we say true. Otherwise we
1078 * say "true" only if we can parse the address and it
1079 * matches one of our addresses.
1082 if (comp
->c_mn
!= &fmt_mnull
)
1083 mnfree (comp
->c_mn
);
1084 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1085 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1088 comp
->c_flags
|= CF_TRUE
;
1089 /* Set str for use with FT_GETMYMBOX. With
1090 FT_GETMYADDR, comp->c_mn will be run through
1091 FT_LS_ADDR, which will strip off any pers
1095 comp
->c_flags
&= ~CF_TRUE
;
1097 while ((sp
= getname(sp
)))
1098 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1099 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1101 comp
->c_flags
|= CF_TRUE
;
1102 /* Set str and comp->c_text for use with
1103 FT_GETMYMBOX. With FT_GETMYADDR,
1104 comp->c_mn will be run through
1105 FT_LS_ADDR, which will strip off any
1107 free (comp
->c_text
);
1108 comp
->c_text
= str
= strdup (mn
->m_text
);
1111 comp
->c_flags
|= CF_PARSED
;
1113 while (getname("")) /* XXX */
1115 if (comp
->c_text
== 0)
1116 comp
->c_flags
|= CF_TRUE
;
1118 comp
->c_flags
&= ~CF_TRUE
;
1120 comp
->c_mn
= &fmt_mnull
;
1122 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1123 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1124 /* Fool FT_LS_ADDR into not producing an address. */
1125 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1131 * Call our tracing callback function, if one was supplied
1134 if (callbacks
&& callbacks
->trace_func
)
1135 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1136 str
, charstring_buffer (scanlp
));
1140 /* Emit any trailing sequences of zero display length. */
1141 while (fmt
->f_type
!= FT_DONE
) {
1142 if (fmt
->f_type
== FT_LS_LIT
) {
1144 if (callbacks
&& callbacks
->trace_func
)
1145 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1146 str
, charstring_buffer (scanlp
));
1147 } else if (fmt
->f_type
== FT_STRLITZ
) {
1148 /* Don't want to emit part of an escape sequence. So if
1149 there isn't enough room in the buffer for the entire
1150 string, skip it completely. Need room for null
1151 terminator, and maybe trailing newline (added below). */
1153 for (sp
= str
; *sp
; ++sp
) {
1154 charstring_push_back (scanlp
, *sp
);
1157 if (callbacks
&& callbacks
->trace_func
)
1158 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1159 str
, charstring_buffer (scanlp
));
1165 if (charstring_bytes (scanlp
) > 0) {
1167 * Append a newline if the last character wasn't.
1169 #ifdef MULTIBYTE_SUPPORT
1171 * It's a little tricky because the last byte might be part of
1172 * a multibyte character, in which case we assume that wasn't
1175 size_t last_char_len
= charstring_last_char_len (scanlp
);
1176 #else /* ! MULTIBYTE_SUPPORT */
1177 size_t last_char_len
= 1;
1178 #endif /* ! MULTIBYTE_SUPPORT */
1180 if (last_char_len
> 1 ||
1181 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1182 charstring_push_back (scanlp
, '\n');