]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
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 struct charstring
*trimmed
;
121 size_t end
; /* number of input bytes remaining in str */
122 #ifdef MULTIBYTE_SUPPORT
123 int char_len
; /* bytes in current character */
128 char *sp
; /* current position in source string */
133 if ((remaining
= wid
) < 0) {
134 remaining
= -remaining
;
137 if (remaining
> (int) max
) { remaining
= max
; }
139 trimmed
= rjust
? charstring_create(remaining
) : dest
;
142 #ifdef MULTIBYTE_SUPPORT
143 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
146 while (*sp
&& remaining
> 0 && end
> 0) {
147 #ifdef MULTIBYTE_SUPPORT
148 char_len
= mbtowc(&wide_char
, sp
, end
);
151 * See the relevant comments in cpstripped() to explain what's
152 * going on here; we want to handle the case where we get
153 * characters that mbtowc() cannot handle
158 char_len
= mbtowc(&wide_char
, altstr
, 1);
165 w
= wcwidth(wide_char
);
167 /* If w > remaining, w must be positive. */
174 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
179 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
180 intentionally warns if they are passed a char. */
181 c
= (unsigned char) *sp
;
182 if (iscntrl(c
) || isspace(c
)) {
186 charstring_push_back (trimmed
, ' ');
195 #ifdef MULTIBYTE_SUPPORT
196 if (w
>= 0 && remaining
>= w
) {
197 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
204 charstring_push_back (trimmed
, *sp
++);
210 while (remaining
-- > 0) {
211 charstring_push_back(dest
, fill
);
215 charstring_append(dest
, trimmed
);
216 charstring_free(trimmed
);
221 cpstripped (charstring_t dest
, size_t max
, char *str
)
223 int prevCtrl
= 1; /* This is 1 so we strip out leading spaces */
225 #ifdef MULTIBYTE_SUPPORT
229 #endif /* MULTIBYTE_SUPPORT */
237 #ifdef MULTIBYTE_SUPPORT
238 if (mbtowc(NULL
, NULL
, 0)) {} /* Reset shift state */
239 #endif /* MULTIBYTE_SUPPORT */
242 * Process each character at a time; if we have multibyte support
243 * then deal with that here.
246 while (*str
!= '\0' && len
> 0 && max
> 0) {
247 #ifdef MULTIBYTE_SUPPORT
248 char_len
= mbtowc(&wide_char
, str
, len
);
251 * If mbrtowc() failed, then we have a character that isn't valid
252 * in the current encoding, or len wasn't enough for the whole
253 * multi-byte rune to be read. Replace it with a '?'. We do that by
254 * setting the alstr variable to the value of the replacement string;
255 * altstr is used below when the bytes are copied into the output
260 char_len
= mbtowc(&wide_char
, altstr
, 1);
269 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
271 #else /* MULTIBYTE_SUPPORT */
272 int c
= (unsigned char) *str
;
274 if (iscntrl(c
) || isspace(c
)) {
276 #endif /* MULTIBYTE_SUPPORT */
278 charstring_push_back (dest
, ' ');
288 #ifdef MULTIBYTE_SUPPORT
289 w
= wcwidth(wide_char
);
291 if (max
>= (size_t) w
) {
292 charstring_push_back_chars (dest
, altstr
? altstr
: str
, char_len
, w
);
297 /* Not enough width available for the last character. Output
300 charstring_push_back (dest
, ' ');
304 #else /* MULTIBYE_SUPPORT */
305 charstring_push_back (dest
, *str
++);
307 #endif /* MULTIBYTE_SUPPORT */
311 static char *lmonth
[] = { "January", "February","March", "April",
312 "May", "June", "July", "August",
313 "September","October", "November","December" };
316 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
318 char given
[BUFSIZ
], surname
[BUFSIZ
];
327 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
328 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
334 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
337 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
338 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
340 snprintf (buffer
, buffer_len
, "%s", surname
);
346 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
351 if ((idx
= stringdex (key
, mbox
)) < 0
352 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
355 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
360 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
361 struct fmt_callbacks
*callbacks
)
365 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
376 * max is the same as width, but unsigned so comparisons
377 * with charstring_chars() won't raise compile warnings.
380 savestr
= str
= NULL
;
383 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
384 switch (fmt
->f_type
) {
387 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
392 case FT_LS_DECODECOMP
:
394 * Trim these components of any newlines.
396 * But don't trim the "body" and "text" components.
401 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
402 (i
= strlen(comp
->c_text
)) > 0) {
403 if (comp
->c_text
[i
- 1] == '\n' &&
404 strcmp(comp
->c_name
, "body") != 0 &&
405 strcmp(comp
->c_name
, "text") != 0)
406 comp
->c_text
[i
- 1] = '\0';
407 comp
->c_flags
|= CF_TRIMMED
;
414 for ( ; charstring_chars (scanlp
) < max
; ) {
415 switch (fmt
->f_type
) {
418 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
419 fmt
->f_comp
->c_text
);
422 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
423 fmt
->f_fill
, max
- charstring_chars (scanlp
));
428 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
429 charstring_push_back (scanlp
, c
);
438 rjust
++; /* XXX should do something with this */
440 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
441 charstring_push_back (scanlp
, c
);
443 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
444 charstring_push_back (scanlp
, fmt
->f_fill
);
449 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
452 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
453 max
- charstring_chars (scanlp
));
458 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
459 charstring_push_back (scanlp
, c
);
464 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
467 adios (NULL
, "internal error (FT_STRFW)");
473 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
474 cpnumber (scanlp
, value
, wid
, ' ',
475 max
- charstring_chars (scanlp
));
482 unsigned int whole
, tenths
;
483 unsigned int scale
= 0;
484 unsigned int val
= (unsigned int)value
;
485 char *kibisuff
= NULL
;
487 switch (fmt
->f_type
) {
488 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
489 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
493 snprintf(buffer
, sizeof(buffer
), "%u", val
);
495 /* To prevent divide by 0, found by clang static
497 if (scale
== 0) { scale
= 1; }
499 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
500 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
506 strcpy(buffer
, "huge");
508 /* val is scale times too big. we want tenths */
516 tenths
= val
- (whole
* 10);
519 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
520 whole
, tenths
, *unitcp
, kibisuff
);
522 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
523 whole
, *unitcp
, kibisuff
);
531 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
532 max
- charstring_chars (scanlp
));
536 charstring_push_back (scanlp
, fmt
->f_char
);
540 if (callbacks
&& callbacks
->trace_func
)
541 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
542 str
, charstring_buffer (scanlp
));
546 if (!(value
= (str
&& *str
))) {
547 if (callbacks
&& callbacks
->trace_func
)
548 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
549 str
, charstring_buffer (scanlp
));
556 if (!(value
= (str
== NULL
|| *str
== 0))) {
557 if (callbacks
&& callbacks
->trace_func
)
558 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
559 str
, charstring_buffer (scanlp
));
566 if (value
!= fmt
->f_value
) {
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
= (str
&& match (str
, fmt
->f_text
)))) {
597 if (callbacks
&& callbacks
->trace_func
)
598 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
599 str
, charstring_buffer (scanlp
));
607 value
= match (str
, fmt
->f_text
);
613 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
614 if (callbacks
&& callbacks
->trace_func
)
615 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
616 str
, charstring_buffer (scanlp
));
623 value
= uprf (str
, fmt
->f_text
);
627 value
= (str
!= NULL
&& *str
!= 0);
631 value
= (str
== NULL
|| *str
== 0);
635 value
= (fmt
->f_value
== value
);
639 value
= (fmt
->f_value
!= value
);
643 value
= (fmt
->f_value
> value
);
647 if (callbacks
&& callbacks
->trace_func
)
648 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
649 str
, charstring_buffer (scanlp
));
657 str
= fmt
->f_comp
->c_text
;
663 if (!(str
= getenv (fmt
->f_text
)))
667 if (!(str
= context_find (fmt
->f_text
)))
671 case FT_LS_DECODECOMP
:
672 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
675 str
= fmt
->f_comp
->c_text
;
679 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
688 strncpy(buffer
, str
, sizeof(buffer
));
689 buffer
[sizeof(buffer
)-1] = '\0';
691 while (isspace((unsigned char) *str
))
694 if ((i
= fmt
->f_width
) < 0) {
699 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
702 xp
+= strlen(str
) - 1;
703 while (xp
> str
&& isspace((unsigned char) *xp
))
705 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
706 str
+= strlen(str
) - i
;
711 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
714 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
717 value
= fmt
->f_value
;
720 value
= dat
[fmt
->f_value
];
728 case FT_LV_CHAR_LEFT
:
729 value
= max
- charstring_bytes (scanlp
);
732 value
+= fmt
->f_value
;
735 value
= fmt
->f_value
- value
;
737 case FT_LV_MULTIPLY_L
:
738 value
*= fmt
->f_value
;
742 value
/= fmt
->f_value
;
748 value
%= fmt
->f_value
;
757 value
= fmt
->f_comp
->c_tws
->tw_sec
;
760 value
= fmt
->f_comp
->c_tws
->tw_min
;
763 value
= fmt
->f_comp
->c_tws
->tw_hour
;
766 value
= fmt
->f_comp
->c_tws
->tw_mday
;
769 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
772 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
775 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
778 str
= dtwszone (fmt
->f_comp
->c_tws
);
781 value
= fmt
->f_comp
->c_tws
->tw_year
;
784 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
786 value
= tws
->tw_wday
;
789 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
791 str
= tw_dotw
[tws
->tw_wday
];
794 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
796 str
= tw_ldotw
[tws
->tw_wday
];
799 value
= fmt
->f_comp
->c_tws
->tw_yday
;
802 value
= fmt
->f_comp
->c_tws
->tw_zone
;
805 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
806 value
= dmktime(fmt
->f_comp
->c_tws
);
809 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
810 value
= dmktime(fmt
->f_comp
->c_tws
);
811 value
= time((time_t *) 0) - value
;
814 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
816 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
826 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
832 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
835 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
838 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
842 str
= fmt
->f_comp
->c_mn
->m_pers
;
845 str
= fmt
->f_comp
->c_mn
->m_mbox
;
848 str
= fmt
->f_comp
->c_mn
->m_host
;
851 str
= fmt
->f_comp
->c_mn
->m_path
;
854 str
= fmt
->f_comp
->c_mn
->m_gname
;
857 str
= fmt
->f_comp
->c_mn
->m_note
;
860 str
= adrformat( fmt
->f_comp
->c_mn
);
863 value
= fmt
->f_comp
->c_mn
->m_type
;
866 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
869 value
= fmt
->f_comp
->c_mn
->m_nohost
;
873 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
874 str
= fmt
->f_comp
->c_text
;
877 if (fmt
->f_type
== FT_LS_ADDR
)
879 if ((str
= mn
->m_pers
) == NULL
) {
880 if ((str
= mn
->m_note
)) {
882 strncpy (buffer
, str
, sizeof(buffer
));
883 buffer
[sizeof(buffer
)-1] = '\0';
887 sp
= str
+ strlen(str
) - 1;
896 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
897 buffer
, sizeof(buffer
)))) {
899 switch (mn
->m_type
) {
904 snprintf (buffer
, sizeof(buffer
), "%s!%s",
905 mn
->m_host
, mn
->m_mbox
);
910 snprintf (buffer
, sizeof(buffer
), "%s@%s",
911 mn
->m_mbox
, mn
->m_host
);
923 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
927 strncpy(buffer
, str
, sizeof(buffer
));
928 /* strncpy doesn't NUL-terminate if it fills the buffer */
929 buffer
[sizeof(buffer
)-1] = '\0';
930 unquote_string(buffer
, buffer2
);
937 if ((t
= comp
->c_tws
->tw_clock
) == 0)
938 t
= dmktime(comp
->c_tws
);
939 tws
= dlocaltime(&t
);
945 if ((t
= comp
->c_tws
->tw_clock
) == 0)
946 t
= dmktime(comp
->c_tws
);
953 if (comp
->c_flags
& CF_PARSED
)
955 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
957 comp
->c_flags
&= ~CF_TRUE
;
958 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
959 memset (comp
->c_tws
, 0, sizeof *comp
->c_tws
);
960 comp
->c_flags
= CF_TRUE
;
962 comp
->c_flags
|= CF_PARSED
;
966 /* hook for custom address list formatting (see replsbr.c) */
967 if (callbacks
&& callbacks
->formataddr
)
968 str
= callbacks
->formataddr (savestr
, str
);
970 str
= formataddr (savestr
, str
);
974 /* The same as formataddr, but doesn't do duplicate suppression */
975 if (callbacks
&& callbacks
->concataddr
)
976 str
= callbacks
->concataddr (savestr
, str
);
978 str
= concataddr (savestr
, str
);
982 /* output the str register as an address component,
983 * splitting it into multiple lines if necessary. The
984 * value reg. contains the max line length. The lit.
985 * field may contain a string to prepend to the result
990 int indent
, wid
, len
;
994 len
= str
? strlen (str
) : 0;
996 indent
= strlen (sp
);
999 adios(NULL
, "putaddr -- num register (%d) must be greater "
1000 "than label width (%d)", value
, indent
);
1002 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1003 charstring_push_back (scanlp
, c
);
1006 /* try to break at a comma; failing that, break at a
1009 lastb
= 0; sp
= lp
+ wid
;
1010 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1011 if (! lastb
&& isspace(c
))
1015 if (! (sp
= lastb
)) {
1017 while (*sp
&& *sp
!= ',' &&
1018 !isspace((unsigned char) *sp
))
1025 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1026 charstring_push_back (scanlp
, *lp
++);
1028 while (isspace((unsigned char) *lp
))
1031 if (charstring_chars (scanlp
) < max
) {
1032 charstring_push_back (scanlp
, '\n');
1035 charstring_chars (scanlp
) < max
&& i
> 0;
1037 charstring_push_back (scanlp
, ' ');
1040 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1046 if (comp
->c_flags
& CF_PARSED
)
1048 if (comp
->c_mn
!= &fmt_mnull
)
1049 mnfree (comp
->c_mn
);
1050 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1051 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1055 comp
->c_flags
|= CF_PARSED
;
1057 while (getname("")) /* XXX */
1059 comp
->c_mn
= &fmt_mnull
;
1067 * if there's no component, we say true. Otherwise we
1068 * say "true" only if we can parse the address and it
1069 * matches one of our addresses.
1072 if (comp
->c_mn
!= &fmt_mnull
)
1073 mnfree (comp
->c_mn
);
1074 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1075 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1078 comp
->c_flags
|= CF_TRUE
;
1079 /* Set str for use with FT_GETMYMBOX. With
1080 FT_GETMYADDR, comp->c_mn will be run through
1081 FT_LS_ADDR, which will strip off any pers
1085 comp
->c_flags
&= ~CF_TRUE
;
1087 while ((sp
= getname(sp
)))
1088 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1089 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1091 comp
->c_flags
|= CF_TRUE
;
1092 /* Set str and comp->c_text for use with
1093 FT_GETMYMBOX. With FT_GETMYADDR,
1094 comp->c_mn will be run through
1095 FT_LS_ADDR, which will strip off any
1097 free (comp
->c_text
);
1098 comp
->c_text
= str
= strdup (mn
->m_text
);
1101 comp
->c_flags
|= CF_PARSED
;
1103 while (getname("")) /* XXX */
1105 if (comp
->c_text
== 0)
1106 comp
->c_flags
|= CF_TRUE
;
1108 comp
->c_flags
&= ~CF_TRUE
;
1110 comp
->c_mn
= &fmt_mnull
;
1112 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1113 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1114 /* Fool FT_LS_ADDR into not producing an address. */
1115 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1121 * Call our tracing callback function, if one was supplied
1124 if (callbacks
&& callbacks
->trace_func
)
1125 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1126 str
, charstring_buffer (scanlp
));
1130 /* Emit any trailing sequences of zero display length. */
1131 while (fmt
->f_type
!= FT_DONE
) {
1132 if (fmt
->f_type
== FT_LS_LIT
) {
1134 if (callbacks
&& callbacks
->trace_func
)
1135 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1136 str
, charstring_buffer (scanlp
));
1137 } else if (fmt
->f_type
== FT_STRLITZ
) {
1138 /* Don't want to emit part of an escape sequence. So if
1139 there isn't enough room in the buffer for the entire
1140 string, skip it completely. Need room for null
1141 terminator, and maybe trailing newline (added below). */
1143 for (sp
= str
; *sp
; ++sp
) {
1144 charstring_push_back (scanlp
, *sp
);
1147 if (callbacks
&& callbacks
->trace_func
)
1148 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1149 str
, charstring_buffer (scanlp
));
1155 if (charstring_bytes (scanlp
) > 0) {
1157 * Append a newline if the last character wasn't.
1159 #ifdef MULTIBYTE_SUPPORT
1161 * It's a little tricky because the last byte might be part of
1162 * a multibyte character, in which case we assume that wasn't
1165 size_t last_char_len
= charstring_last_char_len (scanlp
);
1166 #else /* ! MULTIBYTE_SUPPORT */
1167 size_t last_char_len
= 1;
1168 #endif /* ! MULTIBYTE_SUPPORT */
1170 if (last_char_len
> 1 ||
1171 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1172 charstring_push_back (scanlp
, '\n');