]>
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>
19 #ifdef HAVE_SYS_TIME_H
20 # include <sys/time.h>
23 #ifdef MULTIBYTE_SUPPORT
28 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
34 static int match (char *, char *);
35 static char *get_x400_friendly (char *, char *, int);
36 static int get_x400_comp (char *, char *, char *, int);
40 * test if string "sub" appears anywhere in
41 * string "str" (case insensitive).
45 match (char *str
, char *sub
)
51 c1
= tolower((unsigned char)c1
);
52 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
56 s1
= sub
+ 1; s2
= str
;
57 while ((c1
= *s1
++) &&
58 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
67 * copy a number to the destination subject to a maximum width
70 cpnumber(charstring_t dest
, int num
, unsigned int wid
, char fill
, size_t max
) {
71 if (wid
< (num
>= 0 ? max
: max
-1)) {
72 /* Build up the string representation of num in reverse. */
73 charstring_t rev
= charstring_create (0);
74 int i
= num
>= 0 ? num
: -num
;
77 charstring_push_back (rev
, i
% 10 + '0');
79 } while (--wid
> 0 && i
> 0);
81 /* Overflowed the field (wid). */
82 charstring_push_back (rev
, '?');
83 } else if (num
< 0 && wid
> 0) {
84 /* Shouldn't need the wid > 0 check, that's why the condition
85 at the top checks wid < max-1 when num < 0. */
88 charstring_push_back (rev
, '-');
91 while (wid
-- > 0 && fill
!= 0) {
92 charstring_push_back (rev
, fill
);
94 if (num
< 0 && fill
== '0') {
95 charstring_push_back (rev
, '-');
99 /* Output the string in reverse. */
100 size_t b
= charstring_bytes (rev
);
101 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
104 charstring_push_back (dest
, *--cp
);
108 charstring_free (rev
);
113 * copy string from str to dest padding with the fill character to a
114 * size of wid characters. if wid is negative, the string is right
115 * aligned no more than max characters are copied
118 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
) {
119 int remaining
; /* remaining output width available */
121 struct charstring
*trimmed
;
122 size_t end
; /* number of input bytes remaining in str */
123 #ifdef MULTIBYTE_SUPPORT
124 int char_len
; /* bytes in current character */
129 char *sp
; /* current position in source string */
134 if ((remaining
= wid
) < 0) {
135 remaining
= -remaining
;
138 if (remaining
> (int) max
) { remaining
= max
; }
140 trimmed
= rjust
? charstring_create(remaining
) : dest
;
143 #ifdef MULTIBYTE_SUPPORT
144 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
147 while (*sp
&& remaining
> 0 && end
> 0) {
148 #ifdef MULTIBYTE_SUPPORT
149 char_len
= mbtowc(&wide_char
, sp
, end
);
152 * See the relevant comments in cpstripped() to explain what's
153 * going on here; we want to handle the case where we get
154 * characters that mbtowc() cannot handle
159 char_len
= mbtowc(&wide_char
, altstr
, 1);
166 w
= wcwidth(wide_char
);
168 /* If w > remaining, w must be positive. */
175 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
180 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
181 intentionally warns if they are passed a char. */
182 c
= (unsigned char) *sp
;
183 if (iscntrl(c
) || isspace(c
)) {
187 charstring_push_back (trimmed
, ' ');
196 #ifdef MULTIBYTE_SUPPORT
197 if (w
>= 0 && remaining
>= w
) {
198 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
205 charstring_push_back (trimmed
, *sp
++);
211 while (remaining
-- > 0) {
212 charstring_push_back(dest
, fill
);
216 charstring_append(dest
, trimmed
);
217 charstring_free(trimmed
);
222 cpstripped (charstring_t dest
, size_t max
, char *str
)
224 int prevCtrl
= 1; /* This is 1 so we strip out leading spaces */
226 #ifdef MULTIBYTE_SUPPORT
230 #endif /* MULTIBYTE_SUPPORT */
238 #ifdef MULTIBYTE_SUPPORT
239 if (mbtowc(NULL
, NULL
, 0)) {} /* Reset shift state */
240 #endif /* MULTIBYTE_SUPPORT */
243 * Process each character at a time; if we have multibyte support
244 * then deal with that here.
247 while (*str
!= '\0' && len
> 0 && max
> 0) {
248 #ifdef MULTIBYTE_SUPPORT
249 char_len
= mbtowc(&wide_char
, str
, len
);
252 * If mbrtowc() failed, then we have a character that isn't valid
253 * in the current encoding, or len wasn't enough for the whole
254 * multi-byte rune to be read. Replace it with a '?'. We do that by
255 * setting the alstr variable to the value of the replacement string;
256 * altstr is used below when the bytes are copied into the output
261 char_len
= mbtowc(&wide_char
, altstr
, 1);
270 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
272 #else /* MULTIBYTE_SUPPORT */
273 int c
= (unsigned char) *str
;
275 if (iscntrl(c
) || isspace(c
)) {
277 #endif /* MULTIBYTE_SUPPORT */
279 charstring_push_back (dest
, ' ');
289 #ifdef MULTIBYTE_SUPPORT
290 w
= wcwidth(wide_char
);
292 if (max
>= (size_t) w
) {
293 charstring_push_back_chars (dest
, altstr
? altstr
: str
, char_len
, w
);
298 /* Not enough width available for the last character. Output
301 charstring_push_back (dest
, ' ');
305 #else /* MULTIBYE_SUPPORT */
306 charstring_push_back (dest
, *str
++);
308 #endif /* MULTIBYTE_SUPPORT */
312 static char *lmonth
[] = { "January", "February","March", "April",
313 "May", "June", "July", "August",
314 "September","October", "November","December" };
317 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
319 char given
[BUFSIZ
], surname
[BUFSIZ
];
328 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
329 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
335 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
338 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
339 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
341 snprintf (buffer
, buffer_len
, "%s", surname
);
347 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
352 if ((idx
= stringdex (key
, mbox
)) < 0
353 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
356 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
361 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
362 struct fmt_callbacks
*callbacks
)
366 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
377 * max is the same as width, but unsigned so comparisons
378 * with charstring_chars() won't raise compile warnings.
381 savestr
= str
= NULL
;
384 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
385 switch (fmt
->f_type
) {
388 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
393 case FT_LS_DECODECOMP
:
395 * Trim these components of any newlines.
397 * But don't trim the "body" and "text" components.
402 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
403 (i
= strlen(comp
->c_text
)) > 0) {
404 if (comp
->c_text
[i
- 1] == '\n' &&
405 strcmp(comp
->c_name
, "body") != 0 &&
406 strcmp(comp
->c_name
, "text") != 0)
407 comp
->c_text
[i
- 1] = '\0';
408 comp
->c_flags
|= CF_TRIMMED
;
415 for ( ; charstring_chars (scanlp
) < max
; ) {
416 switch (fmt
->f_type
) {
419 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
420 fmt
->f_comp
->c_text
);
423 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
424 fmt
->f_fill
, max
- charstring_chars (scanlp
));
429 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
430 charstring_push_back (scanlp
, c
);
439 rjust
++; /* XXX should do something with this */
441 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
442 charstring_push_back (scanlp
, c
);
444 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
445 charstring_push_back (scanlp
, fmt
->f_fill
);
450 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
453 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
454 max
- charstring_chars (scanlp
));
459 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
460 charstring_push_back (scanlp
, c
);
465 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
468 adios (NULL
, "internal error (FT_STRFW)");
474 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
475 cpnumber (scanlp
, value
, wid
, ' ',
476 max
- charstring_chars (scanlp
));
483 unsigned int whole
, tenths
;
484 unsigned int scale
= 0;
485 unsigned int val
= (unsigned int)value
;
486 char *kibisuff
= NULL
;
488 switch (fmt
->f_type
) {
489 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
490 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
494 snprintf(buffer
, sizeof(buffer
), "%u", val
);
496 /* To prevent divide by 0, found by clang static
498 if (scale
== 0) { scale
= 1; }
500 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
501 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
507 strcpy(buffer
, "huge");
509 /* val is scale times too big. we want tenths */
517 tenths
= val
- (whole
* 10);
520 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
521 whole
, tenths
, *unitcp
, kibisuff
);
523 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
524 whole
, *unitcp
, kibisuff
);
532 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
533 max
- charstring_chars (scanlp
));
537 charstring_push_back (scanlp
, fmt
->f_char
);
541 if (callbacks
&& callbacks
->trace_func
)
542 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
543 str
, charstring_buffer (scanlp
));
547 if (!(value
= (str
&& *str
))) {
548 if (callbacks
&& callbacks
->trace_func
)
549 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
550 str
, charstring_buffer (scanlp
));
557 if (!(value
= (str
== NULL
|| *str
== 0))) {
558 if (callbacks
&& callbacks
->trace_func
)
559 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
560 str
, charstring_buffer (scanlp
));
567 if (value
!= fmt
->f_value
) {
568 if (callbacks
&& callbacks
->trace_func
)
569 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
570 str
, charstring_buffer (scanlp
));
577 if (value
== fmt
->f_value
) {
578 if (callbacks
&& callbacks
->trace_func
)
579 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
580 str
, charstring_buffer (scanlp
));
587 if (value
<= fmt
->f_value
) {
588 if (callbacks
&& callbacks
->trace_func
)
589 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
590 str
, charstring_buffer (scanlp
));
597 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
598 if (callbacks
&& callbacks
->trace_func
)
599 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
600 str
, charstring_buffer (scanlp
));
608 value
= match (str
, fmt
->f_text
);
614 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
615 if (callbacks
&& callbacks
->trace_func
)
616 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
617 str
, charstring_buffer (scanlp
));
624 value
= uprf (str
, fmt
->f_text
);
628 value
= (str
!= NULL
&& *str
!= 0);
632 value
= (str
== NULL
|| *str
== 0);
636 value
= (fmt
->f_value
== value
);
640 value
= (fmt
->f_value
!= value
);
644 value
= (fmt
->f_value
> value
);
648 if (callbacks
&& callbacks
->trace_func
)
649 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
650 str
, charstring_buffer (scanlp
));
658 str
= fmt
->f_comp
->c_text
;
664 if (!(str
= getenv (fmt
->f_text
)))
668 if (!(str
= context_find (fmt
->f_text
)))
672 case FT_LS_DECODECOMP
:
673 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
676 str
= fmt
->f_comp
->c_text
;
680 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
689 strncpy(buffer
, str
, sizeof(buffer
));
690 buffer
[sizeof(buffer
)-1] = '\0';
692 while (isspace((unsigned char) *str
))
695 if ((i
= fmt
->f_width
) < 0) {
700 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
703 xp
+= strlen(str
) - 1;
704 while (xp
> str
&& isspace((unsigned char) *xp
))
706 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
707 str
+= strlen(str
) - i
;
712 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
715 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
718 value
= fmt
->f_value
;
721 value
= dat
[fmt
->f_value
];
729 case FT_LV_CHAR_LEFT
:
730 value
= max
- charstring_bytes (scanlp
);
733 value
+= fmt
->f_value
;
736 value
= fmt
->f_value
- value
;
738 case FT_LV_MULTIPLY_L
:
739 value
*= fmt
->f_value
;
743 value
/= fmt
->f_value
;
749 value
%= fmt
->f_value
;
758 value
= fmt
->f_comp
->c_tws
->tw_sec
;
761 value
= fmt
->f_comp
->c_tws
->tw_min
;
764 value
= fmt
->f_comp
->c_tws
->tw_hour
;
767 value
= fmt
->f_comp
->c_tws
->tw_mday
;
770 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
773 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
776 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
779 str
= dtwszone (fmt
->f_comp
->c_tws
);
782 value
= fmt
->f_comp
->c_tws
->tw_year
;
785 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
787 value
= tws
->tw_wday
;
790 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
792 str
= tw_dotw
[tws
->tw_wday
];
795 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
797 str
= tw_ldotw
[tws
->tw_wday
];
800 value
= fmt
->f_comp
->c_tws
->tw_yday
;
803 value
= fmt
->f_comp
->c_tws
->tw_zone
;
806 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
807 value
= dmktime(fmt
->f_comp
->c_tws
);
810 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
811 value
= dmktime(fmt
->f_comp
->c_tws
);
812 value
= time((time_t *) 0) - value
;
815 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
817 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
827 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
833 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
836 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
839 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
843 str
= fmt
->f_comp
->c_mn
->m_pers
;
846 str
= fmt
->f_comp
->c_mn
->m_mbox
;
849 str
= fmt
->f_comp
->c_mn
->m_host
;
852 str
= fmt
->f_comp
->c_mn
->m_path
;
855 str
= fmt
->f_comp
->c_mn
->m_gname
;
858 str
= fmt
->f_comp
->c_mn
->m_note
;
861 str
= adrformat( fmt
->f_comp
->c_mn
);
864 value
= fmt
->f_comp
->c_mn
->m_type
;
867 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
870 value
= fmt
->f_comp
->c_mn
->m_nohost
;
874 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
875 str
= fmt
->f_comp
->c_text
;
878 if (fmt
->f_type
== FT_LS_ADDR
)
880 if ((str
= mn
->m_pers
) == NULL
) {
881 if ((str
= mn
->m_note
)) {
883 strncpy (buffer
, str
, sizeof(buffer
));
884 buffer
[sizeof(buffer
)-1] = '\0';
888 sp
= str
+ strlen(str
) - 1;
897 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
898 buffer
, sizeof(buffer
)))) {
900 switch (mn
->m_type
) {
905 snprintf (buffer
, sizeof(buffer
), "%s!%s",
906 mn
->m_host
, mn
->m_mbox
);
911 snprintf (buffer
, sizeof(buffer
), "%s@%s",
912 mn
->m_mbox
, mn
->m_host
);
924 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
928 strncpy(buffer
, str
, sizeof(buffer
));
929 /* strncpy doesn't NUL-terminate if it fills the buffer */
930 buffer
[sizeof(buffer
)-1] = '\0';
931 unquote_string(buffer
, buffer2
);
938 if ((t
= comp
->c_tws
->tw_clock
) == 0)
939 t
= dmktime(comp
->c_tws
);
940 tws
= dlocaltime(&t
);
946 if ((t
= comp
->c_tws
->tw_clock
) == 0)
947 t
= dmktime(comp
->c_tws
);
954 if (comp
->c_flags
& CF_PARSED
)
956 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
958 comp
->c_flags
&= ~CF_TRUE
;
959 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
960 memset (comp
->c_tws
, 0, sizeof *comp
->c_tws
);
961 comp
->c_flags
= CF_TRUE
;
963 comp
->c_flags
|= CF_PARSED
;
967 /* hook for custom address list formatting (see replsbr.c) */
968 if (callbacks
&& callbacks
->formataddr
)
969 str
= callbacks
->formataddr (savestr
, str
);
971 str
= formataddr (savestr
, str
);
975 /* The same as formataddr, but doesn't do duplicate suppression */
976 if (callbacks
&& callbacks
->concataddr
)
977 str
= callbacks
->concataddr (savestr
, str
);
979 str
= concataddr (savestr
, str
);
983 /* output the str register as an address component,
984 * splitting it into multiple lines if necessary. The
985 * value reg. contains the max line length. The lit.
986 * field may contain a string to prepend to the result
991 int indent
, wid
, len
;
995 len
= str
? strlen (str
) : 0;
997 indent
= strlen (sp
);
1000 adios(NULL
, "putaddr -- num register (%d) must be greater "
1001 "than label width (%d)", value
, indent
);
1003 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1004 charstring_push_back (scanlp
, c
);
1007 /* try to break at a comma; failing that, break at a
1010 lastb
= 0; sp
= lp
+ wid
;
1011 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1012 if (! lastb
&& isspace(c
))
1016 if (! (sp
= lastb
)) {
1018 while (*sp
&& *sp
!= ',' &&
1019 !isspace((unsigned char) *sp
))
1026 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1027 charstring_push_back (scanlp
, *lp
++);
1029 while (isspace((unsigned char) *lp
))
1032 if (charstring_chars (scanlp
) < max
) {
1033 charstring_push_back (scanlp
, '\n');
1036 charstring_chars (scanlp
) < max
&& i
> 0;
1038 charstring_push_back (scanlp
, ' ');
1041 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1047 if (comp
->c_flags
& CF_PARSED
)
1049 if (comp
->c_mn
!= &fmt_mnull
)
1050 mnfree (comp
->c_mn
);
1051 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1052 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1056 comp
->c_flags
|= CF_PARSED
;
1058 while (getname("")) /* XXX */
1060 comp
->c_mn
= &fmt_mnull
;
1068 * if there's no component, we say true. Otherwise we
1069 * say "true" only if we can parse the address and it
1070 * matches one of our addresses.
1073 if (comp
->c_mn
!= &fmt_mnull
)
1074 mnfree (comp
->c_mn
);
1075 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1076 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1079 comp
->c_flags
|= CF_TRUE
;
1080 /* Set str for use with FT_GETMYMBOX. With
1081 FT_GETMYADDR, comp->c_mn will be run through
1082 FT_LS_ADDR, which will strip off any pers
1086 comp
->c_flags
&= ~CF_TRUE
;
1088 while ((sp
= getname(sp
)))
1089 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1090 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1092 comp
->c_flags
|= CF_TRUE
;
1093 /* Set str and comp->c_text for use with
1094 FT_GETMYMBOX. With FT_GETMYADDR,
1095 comp->c_mn will be run through
1096 FT_LS_ADDR, which will strip off any
1098 free (comp
->c_text
);
1099 comp
->c_text
= str
= strdup (mn
->m_text
);
1102 comp
->c_flags
|= CF_PARSED
;
1104 while (getname("")) /* XXX */
1106 if (comp
->c_text
== 0)
1107 comp
->c_flags
|= CF_TRUE
;
1109 comp
->c_flags
&= ~CF_TRUE
;
1111 comp
->c_mn
= &fmt_mnull
;
1113 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1114 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1115 /* Fool FT_LS_ADDR into not producing an address. */
1116 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1122 * Call our tracing callback function, if one was supplied
1125 if (callbacks
&& callbacks
->trace_func
)
1126 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1127 str
, charstring_buffer (scanlp
));
1131 /* Emit any trailing sequences of zero display length. */
1132 while (fmt
->f_type
!= FT_DONE
) {
1133 if (fmt
->f_type
== FT_LS_LIT
) {
1135 if (callbacks
&& callbacks
->trace_func
)
1136 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1137 str
, charstring_buffer (scanlp
));
1138 } else if (fmt
->f_type
== FT_STRLITZ
) {
1139 /* Don't want to emit part of an escape sequence. So if
1140 there isn't enough room in the buffer for the entire
1141 string, skip it completely. Need room for null
1142 terminator, and maybe trailing newline (added below). */
1144 for (sp
= str
; *sp
; ++sp
) {
1145 charstring_push_back (scanlp
, *sp
);
1148 if (callbacks
&& callbacks
->trace_func
)
1149 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1150 str
, charstring_buffer (scanlp
));
1156 if (charstring_bytes (scanlp
) > 0) {
1158 * Append a newline if the last character wasn't.
1160 #ifdef MULTIBYTE_SUPPORT
1162 * It's a little tricky because the last byte might be part of
1163 * a multibyte character, in which case we assume that wasn't
1166 size_t last_char_len
= charstring_last_char_len (scanlp
);
1167 #else /* ! MULTIBYTE_SUPPORT */
1168 size_t last_char_len
= 1;
1169 #endif /* ! MULTIBYTE_SUPPORT */
1171 if (last_char_len
> 1 ||
1172 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1173 charstring_push_back (scanlp
, '\n');