]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
74000876e86ae5f26a47534864bf3088a01c00bd
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).
13 #include "context_find.h"
15 #include "h/addrsbr.h"
16 #include "h/fmt_scan.h"
18 #include "h/fmt_compile.h"
22 #ifdef HAVE_SYS_TIME_H
23 # include <sys/time.h>
26 #ifdef MULTIBYTE_SUPPORT
31 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
37 static int match (char *, char *) PURE
;
38 static char *get_x400_friendly (char *, char *, int);
39 static int get_x400_comp (char *, char *, char *, int);
43 * test if string "sub" appears anywhere in
44 * string "str" (case insensitive).
48 match (char *str
, char *sub
)
54 c1
= tolower((unsigned char)c1
);
55 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
59 s1
= sub
+ 1; s2
= str
;
60 while ((c1
= *s1
++) &&
61 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
70 * copy a number to the destination subject to a maximum width
73 cpnumber(charstring_t dest
, int num
, int wid
, char fill
, size_t max
)
75 /* Maybe we should handle left padding at some point? */
79 wid
= -wid
; /* OK because wid originally a short. */
80 if ((size_t)wid
< (num
>= 0 ? max
: max
-1)) {
81 /* Build up the string representation of num in reverse. */
82 charstring_t rev
= charstring_create (0);
83 int i
= num
>= 0 ? num
: -num
;
86 charstring_push_back (rev
, i
% 10 + '0');
88 } while (--wid
> 0 && i
> 0);
90 /* Overflowed the field (wid). */
91 charstring_push_back (rev
, '?');
92 } else if (num
< 0 && wid
> 0) {
93 /* Shouldn't need the wid > 0 check, that's why the condition
94 at the top checks wid < max-1 when num < 0. */
97 charstring_push_back (rev
, '-');
100 while (wid
-- > 0 && fill
!= 0) {
101 charstring_push_back (rev
, fill
);
103 if (num
< 0 && fill
== '0') {
104 charstring_push_back (rev
, '-');
108 /* Output the string in reverse. */
109 size_t b
= charstring_bytes (rev
);
110 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
113 charstring_push_back (dest
, *--cp
);
117 charstring_free (rev
);
122 * copy string from str to dest padding with the fill character to a
123 * size of wid characters. if wid is negative, the string is right
124 * aligned no more than max characters are copied
127 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
)
129 int remaining
; /* remaining output width available */
131 struct charstring
*trimmed
;
132 size_t end
; /* number of input bytes remaining in str */
133 #ifdef MULTIBYTE_SUPPORT
134 int char_len
; /* bytes in current character */
139 char *sp
; /* current position in source string */
143 if ((remaining
= wid
) < 0) {
144 remaining
= -remaining
;
147 if (remaining
> (int) max
) { remaining
= max
; }
149 trimmed
= rjust
? charstring_create(remaining
) : dest
;
151 bool prevCtrl
= true;
153 #ifdef MULTIBYTE_SUPPORT
154 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
157 while (*sp
&& remaining
> 0 && end
> 0) {
158 #ifdef MULTIBYTE_SUPPORT
159 char_len
= mbtowc(&wide_char
, sp
, end
);
162 * See the relevant comments in cpstripped() to explain what's
163 * going on here; we want to handle the case where we get
164 * characters that mbtowc() cannot handle
169 char_len
= mbtowc(&wide_char
, altstr
, 1);
176 w
= wcwidth(wide_char
);
178 /* If w > remaining, w must be positive. */
185 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
190 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
191 intentionally warns if they are passed a char. */
192 c
= (unsigned char) *sp
;
193 if (iscntrl(c
) || isspace(c
)) {
197 charstring_push_back (trimmed
, ' ');
206 #ifdef MULTIBYTE_SUPPORT
207 if (w
>= 0 && remaining
>= w
) {
208 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
215 charstring_push_back (trimmed
, *sp
++);
221 while (remaining
-- > 0) {
222 charstring_push_back(dest
, fill
);
226 charstring_append(dest
, trimmed
);
227 charstring_free(trimmed
);
231 #ifdef MULTIBYTE_SUPPORT
233 cpstripped (charstring_t dest
, size_t max
, char *str
)
236 static char *oddchar
;
237 static size_t oddlen
;
238 static char *spacechar
;
239 static size_t spacelen
;
252 two
= MB_CUR_MAX
* 2; /* Varies at run-time. */
254 oddchar
= mh_xmalloc(two
);
255 oddlen
= wcstombs(oddchar
, L
"?", two
);
258 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
259 spacechar
= mh_xmalloc(two
);
260 spacelen
= wcstombs(spacechar
, L
" ", two
);
261 assert(spacelen
> 0);
265 return; /* It's unclear why no padding in this case. */
266 end
= str
+ strlen(str
);
268 if (mbtowc(NULL
, NULL
, 0))
269 {} /* Reset shift state. */
271 squash
= true; /* Trim `space' or `cntrl' from the start. */
274 return; /* It's unclear why no padding in this case. */
276 srclen
= mbtowc(&rune
, str
, end
- str
);
278 /* Invalid rune, or not enough bytes to finish it. */
282 str
++; /* Skip one byte. */
288 if (iswspace(rune
) || iswcntrl(rune
)) {
290 continue; /* Amidst a run of these. */
307 if ((size_t)w
> max
) {
308 /* No room for rune; pad. */
310 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
314 charstring_push_back_chars(dest
, src
, srclen
, w
);
320 #ifndef MULTIBYTE_SUPPORT
322 cpstripped (charstring_t dest
, size_t max
, char *str
)
330 squash
= true; /* Strip leading cases. */
332 c
= (unsigned char)*str
++;
336 if (isspace(c
) || iscntrl(c
)) {
344 charstring_push_back(dest
, (char)c
);
349 static char *lmonth
[] = { "January", "February","March", "April",
350 "May", "June", "July", "August",
351 "September","October", "November","December" };
354 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
356 char given
[BUFSIZ
], surname
[BUFSIZ
];
365 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
366 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
372 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
375 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
376 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
378 snprintf (buffer
, buffer_len
, "%s", surname
);
384 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
389 if ((idx
= stringdex (key
, mbox
)) < 0
390 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
393 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
398 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
399 struct fmt_callbacks
*callbacks
)
403 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
415 * max is the same as width, but unsigned so comparisons
416 * with charstring_chars() won't raise compile warnings.
419 savestr
= str
= NULL
;
422 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
423 switch (fmt
->f_type
) {
426 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
431 case FT_LS_DECODECOMP
:
433 * Trim these components of any newlines.
435 * But don't trim the "body" and "text" components.
440 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
441 (i
= strlen(comp
->c_text
)) > 0) {
442 if (comp
->c_text
[i
- 1] == '\n' &&
443 strcmp(comp
->c_name
, "body") != 0 &&
444 strcmp(comp
->c_name
, "text") != 0)
445 comp
->c_text
[i
- 1] = '\0';
446 comp
->c_flags
|= CF_TRIMMED
;
453 for ( ; charstring_chars (scanlp
) < max
; ) {
454 switch (fmt
->f_type
) {
457 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
458 fmt
->f_comp
->c_text
);
461 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
462 fmt
->f_fill
, max
- charstring_chars (scanlp
));
467 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
468 charstring_push_back (scanlp
, c
);
477 rjust
= true; /* XXX should do something with this */
479 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
480 charstring_push_back (scanlp
, c
);
482 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
483 charstring_push_back (scanlp
, fmt
->f_fill
);
488 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
491 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
492 max
- charstring_chars (scanlp
));
497 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
498 charstring_push_back (scanlp
, c
);
503 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
506 die("internal error (FT_STRFW)");
512 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
513 cpnumber (scanlp
, value
, wid
, ' ',
514 max
- charstring_chars (scanlp
));
521 unsigned int whole
, tenths
;
522 unsigned int scale
= 0;
523 unsigned int val
= (unsigned int)value
;
524 char *kibisuff
= NULL
;
526 switch (fmt
->f_type
) {
527 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
528 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
532 snprintf(buffer
, sizeof(buffer
), "%u", val
);
534 /* To prevent divide by 0, found by clang static
536 if (scale
== 0) { scale
= 1; }
538 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
539 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
545 strcpy(buffer
, "huge");
547 /* val is scale times too big. we want tenths */
555 tenths
= val
- (whole
* 10);
558 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
559 whole
, tenths
, *unitcp
, kibisuff
);
561 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
562 whole
, *unitcp
, kibisuff
);
570 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
571 max
- charstring_chars (scanlp
));
575 charstring_push_back (scanlp
, fmt
->f_char
);
579 if (callbacks
&& callbacks
->trace_func
)
580 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
581 str
, charstring_buffer (scanlp
));
585 if (!(value
= (str
&& *str
))) {
586 if (callbacks
&& callbacks
->trace_func
)
587 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
588 str
, charstring_buffer (scanlp
));
595 if (!(value
= (str
== NULL
|| *str
== 0))) {
596 if (callbacks
&& callbacks
->trace_func
)
597 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
598 str
, charstring_buffer (scanlp
));
605 if (value
!= fmt
->f_value
) {
606 if (callbacks
&& callbacks
->trace_func
)
607 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
608 str
, charstring_buffer (scanlp
));
615 if (value
== fmt
->f_value
) {
616 if (callbacks
&& callbacks
->trace_func
)
617 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
618 str
, charstring_buffer (scanlp
));
625 if (value
<= fmt
->f_value
) {
626 if (callbacks
&& callbacks
->trace_func
)
627 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
628 str
, charstring_buffer (scanlp
));
635 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
636 if (callbacks
&& callbacks
->trace_func
)
637 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
638 str
, charstring_buffer (scanlp
));
646 value
= match (str
, fmt
->f_text
);
652 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
653 if (callbacks
&& callbacks
->trace_func
)
654 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
655 str
, charstring_buffer (scanlp
));
662 value
= uprf (str
, fmt
->f_text
);
666 value
= (str
!= NULL
&& *str
!= 0);
670 value
= (str
== NULL
|| *str
== 0);
674 value
= (fmt
->f_value
== value
);
678 value
= (fmt
->f_value
!= value
);
682 value
= (fmt
->f_value
> value
);
686 if (callbacks
&& callbacks
->trace_func
)
687 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
688 str
, charstring_buffer (scanlp
));
696 str
= fmt
->f_comp
->c_text
;
702 if (!(str
= getenv (fmt
->f_text
)))
706 if (!(str
= context_find (fmt
->f_text
)))
710 case FT_LS_DECODECOMP
:
711 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
714 str
= fmt
->f_comp
->c_text
;
718 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
727 strncpy(buffer
, str
, sizeof(buffer
));
728 buffer
[sizeof(buffer
)-1] = '\0';
730 while (isspace((unsigned char) *str
))
733 if ((i
= fmt
->f_width
) < 0) {
738 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
741 xp
+= strlen(str
) - 1;
742 while (xp
> str
&& isspace((unsigned char) *xp
))
744 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
745 str
+= strlen(str
) - i
;
750 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
753 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
756 value
= fmt
->f_value
;
759 value
= dat
[fmt
->f_value
];
767 case FT_LV_CHAR_LEFT
:
768 value
= max
- charstring_bytes (scanlp
);
771 value
+= fmt
->f_value
;
774 value
= fmt
->f_value
- value
;
776 case FT_LV_MULTIPLY_L
:
777 value
*= fmt
->f_value
;
781 value
/= fmt
->f_value
;
787 value
%= fmt
->f_value
;
796 value
= fmt
->f_comp
->c_tws
->tw_sec
;
799 value
= fmt
->f_comp
->c_tws
->tw_min
;
802 value
= fmt
->f_comp
->c_tws
->tw_hour
;
805 value
= fmt
->f_comp
->c_tws
->tw_mday
;
808 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
811 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
814 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
817 str
= dtwszone (fmt
->f_comp
->c_tws
);
820 value
= fmt
->f_comp
->c_tws
->tw_year
;
823 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
825 value
= tws
->tw_wday
;
828 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
830 str
= tw_dotw
[tws
->tw_wday
];
833 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
835 str
= tw_ldotw
[tws
->tw_wday
];
838 value
= fmt
->f_comp
->c_tws
->tw_yday
;
841 value
= fmt
->f_comp
->c_tws
->tw_zone
;
844 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
845 value
= dmktime(fmt
->f_comp
->c_tws
);
848 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
849 value
= dmktime(fmt
->f_comp
->c_tws
);
850 value
= time(NULL
) - value
;
853 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
855 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
865 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
871 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
874 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
877 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
881 str
= fmt
->f_comp
->c_mn
->m_pers
;
884 str
= fmt
->f_comp
->c_mn
->m_mbox
;
887 str
= fmt
->f_comp
->c_mn
->m_host
;
890 str
= fmt
->f_comp
->c_mn
->m_path
;
893 str
= fmt
->f_comp
->c_mn
->m_gname
;
896 str
= fmt
->f_comp
->c_mn
->m_note
;
899 str
= adrformat( fmt
->f_comp
->c_mn
);
902 value
= fmt
->f_comp
->c_mn
->m_type
;
905 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
908 value
= fmt
->f_comp
->c_mn
->m_nohost
;
912 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
913 str
= fmt
->f_comp
->c_text
;
916 if (fmt
->f_type
== FT_LS_ADDR
)
918 if ((str
= mn
->m_pers
) == NULL
) {
919 if ((str
= mn
->m_note
)) {
921 strncpy (buffer
, str
, sizeof(buffer
));
922 buffer
[sizeof(buffer
)-1] = '\0';
926 sp
= str
+ strlen(str
) - 1;
935 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
936 buffer
, sizeof(buffer
)))) {
938 switch (mn
->m_type
) {
943 snprintf (buffer
, sizeof(buffer
), "%s!%s",
944 mn
->m_host
, mn
->m_mbox
);
949 snprintf (buffer
, sizeof(buffer
), "%s@%s",
950 mn
->m_mbox
, mn
->m_host
);
962 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
966 strncpy(buffer
, str
, sizeof(buffer
));
967 /* strncpy doesn't NUL-terminate if it fills the buffer */
968 buffer
[sizeof(buffer
)-1] = '\0';
969 unquote_string(buffer
, buffer2
);
976 if ((t
= comp
->c_tws
->tw_clock
) == 0)
977 t
= dmktime(comp
->c_tws
);
978 tws
= dlocaltime(&t
);
984 if ((t
= comp
->c_tws
->tw_clock
) == 0)
985 t
= dmktime(comp
->c_tws
);
992 if (comp
->c_flags
& CF_PARSED
)
994 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
996 comp
->c_flags
&= ~CF_TRUE
;
997 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
999 comp
->c_flags
= CF_TRUE
;
1001 comp
->c_flags
|= CF_PARSED
;
1005 /* hook for custom address list formatting (see replsbr.c) */
1006 if (callbacks
&& callbacks
->formataddr
)
1007 str
= callbacks
->formataddr (savestr
, str
);
1009 str
= formataddr (savestr
, str
);
1013 /* The same as formataddr, but doesn't do duplicate suppression */
1014 if (callbacks
&& callbacks
->concataddr
)
1015 str
= callbacks
->concataddr (savestr
, str
);
1017 str
= concataddr (savestr
, str
);
1021 /* output the str register as an address component,
1022 * splitting it into multiple lines if necessary. The
1023 * value reg. contains the max line length. The lit.
1024 * field may contain a string to prepend to the result
1029 int indent
, wid
, len
;
1033 len
= str
? strlen (str
) : 0;
1035 indent
= strlen (sp
);
1038 die("putaddr -- num register (%d) must be greater "
1039 "than label width (%d)", value
, indent
);
1041 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1042 charstring_push_back (scanlp
, c
);
1045 /* try to break at a comma; failing that, break at a
1048 lastb
= 0; sp
= lp
+ wid
;
1049 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1050 if (! lastb
&& isspace(c
))
1054 if (! (sp
= lastb
)) {
1056 while (*sp
&& *sp
!= ',' &&
1057 !isspace((unsigned char) *sp
))
1064 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1065 charstring_push_back (scanlp
, *lp
++);
1067 while (isspace((unsigned char) *lp
))
1070 if (charstring_chars (scanlp
) < max
) {
1071 charstring_push_back (scanlp
, '\n');
1074 charstring_chars (scanlp
) < max
&& i
> 0;
1076 charstring_push_back (scanlp
, ' ');
1079 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1085 if (comp
->c_flags
& CF_PARSED
)
1087 if (comp
->c_mn
!= &fmt_mnull
)
1088 mnfree (comp
->c_mn
);
1089 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1090 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1094 comp
->c_flags
|= CF_PARSED
;
1096 while (getname("")) /* XXX */
1098 comp
->c_mn
= &fmt_mnull
;
1106 * if there's no component, we say true. Otherwise we
1107 * say "true" only if we can parse the address and it
1108 * matches one of our addresses.
1111 if (comp
->c_mn
!= &fmt_mnull
)
1112 mnfree (comp
->c_mn
);
1113 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1114 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1117 comp
->c_flags
|= CF_TRUE
;
1118 /* Set str for use with FT_GETMYMBOX. With
1119 FT_GETMYADDR, comp->c_mn will be run through
1120 FT_LS_ADDR, which will strip off any pers
1124 comp
->c_flags
&= ~CF_TRUE
;
1126 while ((sp
= getname(sp
)))
1127 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1128 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1130 comp
->c_flags
|= CF_TRUE
;
1131 /* Set str and comp->c_text for use with
1132 FT_GETMYMBOX. With FT_GETMYADDR,
1133 comp->c_mn will be run through
1134 FT_LS_ADDR, which will strip off any
1136 free (comp
->c_text
);
1137 comp
->c_text
= str
= strdup (mn
->m_text
);
1140 comp
->c_flags
|= CF_PARSED
;
1142 while (getname("")) /* XXX */
1144 if (comp
->c_text
== 0)
1145 comp
->c_flags
|= CF_TRUE
;
1147 comp
->c_flags
&= ~CF_TRUE
;
1149 comp
->c_mn
= &fmt_mnull
;
1151 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1152 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1153 /* Fool FT_LS_ADDR into not producing an address. */
1154 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1160 * Call our tracing callback function, if one was supplied
1163 if (callbacks
&& callbacks
->trace_func
)
1164 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1165 str
, charstring_buffer (scanlp
));
1169 /* Emit any trailing sequences of zero display length. */
1170 while (fmt
->f_type
!= FT_DONE
) {
1171 if (fmt
->f_type
== FT_LS_LIT
) {
1173 if (callbacks
&& callbacks
->trace_func
)
1174 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1175 str
, charstring_buffer (scanlp
));
1176 } else if (fmt
->f_type
== FT_STRLITZ
) {
1177 /* Don't want to emit part of an escape sequence. So if
1178 there isn't enough room in the buffer for the entire
1179 string, skip it completely. Need room for null
1180 terminator, and maybe trailing newline (added below). */
1182 for (sp
= str
; *sp
; ++sp
) {
1183 charstring_push_back (scanlp
, *sp
);
1186 if (callbacks
&& callbacks
->trace_func
)
1187 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1188 str
, charstring_buffer (scanlp
));
1194 if (charstring_bytes (scanlp
) > 0) {
1196 * Append a newline if the last character wasn't.
1198 #ifdef MULTIBYTE_SUPPORT
1200 * It's a little tricky because the last byte might be part of
1201 * a multibyte character, in which case we assume that wasn't
1204 size_t last_char_len
= charstring_last_char_len (scanlp
);
1205 #else /* ! MULTIBYTE_SUPPORT */
1206 size_t last_char_len
= 1;
1207 #endif /* ! MULTIBYTE_SUPPORT */
1209 if (last_char_len
> 1 ||
1210 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1211 charstring_push_back (scanlp
, '\n');