]>
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).
15 #include "fmt_rfc2047.h"
17 #include "context_find.h"
19 #include "h/addrsbr.h"
20 #include "h/fmt_scan.h"
22 #include "h/fmt_compile.h"
26 #ifdef HAVE_SYS_TIME_H
27 # include <sys/time.h>
30 #ifdef MULTIBYTE_SUPPORT
35 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
41 static int match (char *, char *) PURE
;
42 static char *get_x400_friendly (char *, char *, int);
43 static int get_x400_comp (char *, char *, char *, int);
47 * test if string "sub" appears anywhere in
48 * string "str" (case insensitive).
52 match (char *str
, char *sub
)
58 c1
= tolower((unsigned char)c1
);
59 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
63 s1
= sub
+ 1; s2
= str
;
64 while ((c1
= *s1
++) &&
65 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
73 /* cpnumber formats num as a signed decimal,
74 * appending it to dest if the result doesn't exceed max.
75 * The absolute value of width is the minimum width to produce.
76 * A smaller string is padded;
77 * on the left if width is positive, else the right.
78 * Left-padding uses fill. It is either ' ' or '0'.
79 * Right-padding is always with space. */
81 cpnumber(charstring_t dest
, int num
, int width
, char fill
, size_t max
)
83 if (width
== 0 || width
== INT_MIN
) {
87 bool padright
= width
< 0;
89 width
= -width
; /* Can't overflow after above check. */
93 return; /* The padded result can't fit. */
95 if (num
< 0 && w
== 1) {
96 return; /* No room for `-' and a digit or `?'. */
100 size_t len
= strlen(s
);
102 charstring_append_cstring(dest
, s
);
106 bool neg
= *s
== '-';
109 charstring_append_cstring(dest
, s
);
111 charstring_push_back(dest
, ' ');
116 if (neg
&& fill
== '0') {
117 charstring_push_back(dest
, *s
++);
120 charstring_push_back(dest
, fill
);
122 charstring_append_cstring(dest
, s
);
126 /* Transform 1234567 -> 1234?67 and -1234567 -> 1234-?7. */
127 char *news
= s
+ len
- w
;
132 charstring_append_cstring(dest
, news
);
136 * copy string from str to dest padding with the fill character to a
137 * size of wid characters. if wid is negative, the string is right
138 * aligned no more than max characters are copied
141 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
)
143 int remaining
; /* remaining output width available */
145 struct charstring
*trimmed
;
146 size_t end
; /* number of input bytes remaining in str */
147 #ifdef MULTIBYTE_SUPPORT
148 int char_len
; /* bytes in current character */
153 char *sp
; /* current position in source string */
157 if ((remaining
= wid
) < 0) {
158 remaining
= -remaining
;
161 if (remaining
> (int) max
) { remaining
= max
; }
163 trimmed
= rjust
? charstring_create(remaining
) : dest
;
165 bool prevCtrl
= true;
167 #ifdef MULTIBYTE_SUPPORT
168 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
171 while (*sp
&& remaining
> 0 && end
> 0) {
172 #ifdef MULTIBYTE_SUPPORT
173 char_len
= mbtowc(&wide_char
, sp
, end
);
176 * See the relevant comments in cpstripped() to explain what's
177 * going on here; we want to handle the case where we get
178 * characters that mbtowc() cannot handle
183 char_len
= mbtowc(&wide_char
, altstr
, 1);
190 w
= wcwidth(wide_char
);
192 /* If w > remaining, w must be positive. */
199 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
204 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
205 intentionally warns if they are passed a char. */
206 c
= (unsigned char) *sp
;
207 if (iscntrl(c
) || isspace(c
)) {
211 charstring_push_back (trimmed
, ' ');
220 #ifdef MULTIBYTE_SUPPORT
221 if (w
>= 0 && remaining
>= w
) {
222 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
229 charstring_push_back (trimmed
, *sp
++);
235 while (remaining
-- > 0) {
236 charstring_push_back(dest
, fill
);
240 charstring_append(dest
, trimmed
);
241 charstring_free(trimmed
);
245 #ifdef MULTIBYTE_SUPPORT
247 cpstripped (charstring_t dest
, size_t max
, char *str
)
250 static char *oddchar
;
251 static size_t oddlen
;
252 static char *spacechar
;
253 static size_t spacelen
;
266 two
= MB_CUR_MAX
* 2; /* Varies at run-time. */
268 oddchar
= mh_xmalloc(two
);
269 oddlen
= wcstombs(oddchar
, L
"?", two
);
272 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
273 spacechar
= mh_xmalloc(two
);
274 spacelen
= wcstombs(spacechar
, L
" ", two
);
275 assert(spacelen
> 0);
279 return; /* It's unclear why no padding in this case. */
280 end
= str
+ strlen(str
);
282 if (mbtowc(NULL
, NULL
, 0))
283 {} /* Reset shift state. */
285 squash
= true; /* Trim `space' or `cntrl' from the start. */
288 return; /* It's unclear why no padding in this case. */
290 srclen
= mbtowc(&rune
, str
, end
- str
);
292 /* Invalid rune, or not enough bytes to finish it. */
296 str
++; /* Skip one byte. */
302 if (iswspace(rune
) || iswcntrl(rune
)) {
304 continue; /* Amidst a run of these. */
321 if ((size_t)w
> max
) {
322 /* No room for rune; pad. */
324 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
328 charstring_push_back_chars(dest
, src
, srclen
, w
);
334 #ifndef MULTIBYTE_SUPPORT
336 cpstripped (charstring_t dest
, size_t max
, char *str
)
344 squash
= true; /* Strip leading cases. */
346 c
= (unsigned char)*str
++;
350 if (isspace(c
) || iscntrl(c
)) {
358 charstring_push_back(dest
, (char)c
);
363 static char *lmonth
[] = { "January", "February","March", "April",
364 "May", "June", "July", "August",
365 "September","October", "November","December" };
368 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
370 char given
[BUFSIZ
], surname
[BUFSIZ
];
379 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
380 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
386 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
389 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
390 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
392 snprintf (buffer
, buffer_len
, "%s", surname
);
398 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
403 if ((idx
= stringdex (key
, mbox
)) < 0
404 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
407 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
412 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
413 struct fmt_callbacks
*callbacks
)
417 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
429 * max is the same as width, but unsigned so comparisons
430 * with charstring_chars() won't raise compile warnings.
433 savestr
= str
= NULL
;
436 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
437 switch (fmt
->f_type
) {
440 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
445 case FT_LS_DECODECOMP
:
447 * Trim these components of any newlines.
449 * But don't trim the "body" and "text" components.
454 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
455 (i
= strlen(comp
->c_text
)) > 0) {
456 if (comp
->c_text
[i
- 1] == '\n' &&
457 strcmp(comp
->c_name
, "body") != 0 &&
458 strcmp(comp
->c_name
, "text") != 0)
459 comp
->c_text
[i
- 1] = '\0';
460 comp
->c_flags
|= CF_TRIMMED
;
467 for ( ; charstring_chars (scanlp
) < max
; ) {
468 switch (fmt
->f_type
) {
471 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
472 fmt
->f_comp
->c_text
);
475 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
476 fmt
->f_fill
, max
- charstring_chars (scanlp
));
481 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
482 charstring_push_back (scanlp
, c
);
491 rjust
= true; /* XXX should do something with this */
493 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
494 charstring_push_back (scanlp
, c
);
496 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
497 charstring_push_back (scanlp
, fmt
->f_fill
);
502 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
505 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
506 max
- charstring_chars (scanlp
));
511 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
512 charstring_push_back (scanlp
, c
);
517 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
520 die("internal error (FT_STRFW)");
526 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
527 cpnumber (scanlp
, value
, wid
, ' ',
528 max
- charstring_chars (scanlp
));
535 unsigned int whole
, tenths
;
536 unsigned int scale
= 0;
537 unsigned int val
= (unsigned int)value
;
538 char *kibisuff
= NULL
;
540 switch (fmt
->f_type
) {
541 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
542 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
546 snprintf(buffer
, sizeof(buffer
), "%u", val
);
548 /* To prevent divide by 0, found by clang static
550 if (scale
== 0) { scale
= 1; }
552 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
553 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
559 strcpy(buffer
, "huge");
561 /* val is scale times too big. we want tenths */
569 tenths
= val
- (whole
* 10);
572 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
573 whole
, tenths
, *unitcp
, kibisuff
);
575 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
576 whole
, *unitcp
, kibisuff
);
584 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
585 max
- charstring_chars (scanlp
));
589 charstring_push_back (scanlp
, fmt
->f_char
);
593 if (callbacks
&& callbacks
->trace_func
)
594 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
595 str
, charstring_buffer (scanlp
));
599 if (!(value
= (str
&& *str
))) {
600 if (callbacks
&& callbacks
->trace_func
)
601 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
602 str
, charstring_buffer (scanlp
));
609 if (!(value
= (str
== NULL
|| *str
== 0))) {
610 if (callbacks
&& callbacks
->trace_func
)
611 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
612 str
, charstring_buffer (scanlp
));
619 if (value
!= fmt
->f_value
) {
620 if (callbacks
&& callbacks
->trace_func
)
621 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
622 str
, charstring_buffer (scanlp
));
629 if (value
== fmt
->f_value
) {
630 if (callbacks
&& callbacks
->trace_func
)
631 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
632 str
, charstring_buffer (scanlp
));
639 if (value
<= fmt
->f_value
) {
640 if (callbacks
&& callbacks
->trace_func
)
641 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
642 str
, charstring_buffer (scanlp
));
649 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
650 if (callbacks
&& callbacks
->trace_func
)
651 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
652 str
, charstring_buffer (scanlp
));
660 value
= match (str
, fmt
->f_text
);
666 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
667 if (callbacks
&& callbacks
->trace_func
)
668 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
669 str
, charstring_buffer (scanlp
));
676 value
= uprf (str
, fmt
->f_text
);
680 value
= (str
!= NULL
&& *str
!= 0);
684 value
= (str
== NULL
|| *str
== 0);
688 value
= (fmt
->f_value
== value
);
692 value
= (fmt
->f_value
!= value
);
696 value
= (fmt
->f_value
> value
);
700 if (callbacks
&& callbacks
->trace_func
)
701 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
702 str
, charstring_buffer (scanlp
));
710 str
= fmt
->f_comp
->c_text
;
716 if (!(str
= getenv (fmt
->f_text
)))
720 if (!(str
= context_find (fmt
->f_text
)))
724 case FT_LS_DECODECOMP
:
725 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
728 str
= fmt
->f_comp
->c_text
;
732 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
741 strncpy(buffer
, str
, sizeof(buffer
));
742 buffer
[sizeof(buffer
)-1] = '\0';
744 while (isspace((unsigned char) *str
))
747 if ((i
= fmt
->f_width
) < 0) {
752 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
755 xp
+= strlen(str
) - 1;
756 while (xp
> str
&& isspace((unsigned char) *xp
))
758 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
759 str
+= strlen(str
) - i
;
764 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
767 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
770 value
= fmt
->f_value
;
773 value
= dat
[fmt
->f_value
];
781 case FT_LV_CHAR_LEFT
:
782 value
= max
- charstring_bytes (scanlp
);
785 value
+= fmt
->f_value
;
788 value
= fmt
->f_value
- value
;
790 case FT_LV_MULTIPLY_L
:
791 value
*= fmt
->f_value
;
795 value
/= fmt
->f_value
;
801 value
%= fmt
->f_value
;
810 value
= fmt
->f_comp
->c_tws
->tw_sec
;
813 value
= fmt
->f_comp
->c_tws
->tw_min
;
816 value
= fmt
->f_comp
->c_tws
->tw_hour
;
819 value
= fmt
->f_comp
->c_tws
->tw_mday
;
822 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
825 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
828 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
831 str
= dtwszone (fmt
->f_comp
->c_tws
);
834 value
= fmt
->f_comp
->c_tws
->tw_year
;
837 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
839 value
= tws
->tw_wday
;
842 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
844 str
= tw_dotw
[tws
->tw_wday
];
847 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
849 str
= tw_ldotw
[tws
->tw_wday
];
852 value
= fmt
->f_comp
->c_tws
->tw_yday
;
855 value
= fmt
->f_comp
->c_tws
->tw_zone
;
858 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
859 value
= dmktime(fmt
->f_comp
->c_tws
);
862 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
863 value
= dmktime(fmt
->f_comp
->c_tws
);
864 value
= time(NULL
) - value
;
867 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
869 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
879 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
885 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
888 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
891 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
895 str
= fmt
->f_comp
->c_mn
->m_pers
;
898 str
= fmt
->f_comp
->c_mn
->m_mbox
;
901 str
= fmt
->f_comp
->c_mn
->m_host
;
904 str
= fmt
->f_comp
->c_mn
->m_path
;
907 str
= fmt
->f_comp
->c_mn
->m_gname
;
910 str
= fmt
->f_comp
->c_mn
->m_note
;
913 str
= adrformat( fmt
->f_comp
->c_mn
);
916 value
= fmt
->f_comp
->c_mn
->m_type
;
919 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
922 value
= fmt
->f_comp
->c_mn
->m_nohost
;
926 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
927 str
= fmt
->f_comp
->c_text
;
930 if (fmt
->f_type
== FT_LS_ADDR
)
932 if ((str
= mn
->m_pers
) == NULL
) {
933 if ((str
= mn
->m_note
)) {
935 strncpy (buffer
, str
, sizeof(buffer
));
936 buffer
[sizeof(buffer
)-1] = '\0';
940 sp
= str
+ strlen(str
) - 1;
949 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
950 buffer
, sizeof(buffer
)))) {
952 switch (mn
->m_type
) {
957 snprintf (buffer
, sizeof(buffer
), "%s!%s",
958 mn
->m_host
, mn
->m_mbox
);
963 snprintf (buffer
, sizeof(buffer
), "%s@%s",
964 mn
->m_mbox
, mn
->m_host
);
976 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
980 strncpy(buffer
, str
, sizeof(buffer
));
981 /* strncpy doesn't NUL-terminate if it fills the buffer */
982 buffer
[sizeof(buffer
)-1] = '\0';
983 unquote_string(buffer
, buffer2
);
990 if ((t
= comp
->c_tws
->tw_clock
) == 0)
991 t
= dmktime(comp
->c_tws
);
992 tws
= dlocaltime(&t
);
998 if ((t
= comp
->c_tws
->tw_clock
) == 0)
999 t
= dmktime(comp
->c_tws
);
1001 *comp
->c_tws
= *tws
;
1006 if (comp
->c_flags
& CF_PARSED
)
1008 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
1009 *comp
->c_tws
= *tws
;
1010 comp
->c_flags
&= ~CF_TRUE
;
1011 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
1013 comp
->c_flags
= CF_TRUE
;
1015 comp
->c_flags
|= CF_PARSED
;
1019 /* hook for custom address list formatting (see replsbr.c) */
1020 if (callbacks
&& callbacks
->formataddr
)
1021 str
= callbacks
->formataddr (savestr
, str
);
1023 str
= formataddr (savestr
, str
);
1027 /* The same as formataddr, but doesn't do duplicate suppression */
1028 if (callbacks
&& callbacks
->concataddr
)
1029 str
= callbacks
->concataddr (savestr
, str
);
1031 str
= concataddr (savestr
, str
);
1035 /* output the str register as an address component,
1036 * splitting it into multiple lines if necessary. The
1037 * value reg. contains the max line length. The lit.
1038 * field may contain a string to prepend to the result
1043 int indent
, wid
, len
;
1047 len
= str
? strlen (str
) : 0;
1049 indent
= strlen (sp
);
1052 die("putaddr -- num register (%d) must be greater "
1053 "than label width (%d)", value
, indent
);
1055 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1056 charstring_push_back (scanlp
, c
);
1059 /* try to break at a comma; failing that, break at a
1062 lastb
= 0; sp
= lp
+ wid
;
1063 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1064 if (! lastb
&& isspace(c
))
1068 if (! (sp
= lastb
)) {
1070 while (*sp
&& *sp
!= ',' &&
1071 !isspace((unsigned char) *sp
))
1078 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1079 charstring_push_back (scanlp
, *lp
++);
1081 while (isspace((unsigned char) *lp
))
1084 if (charstring_chars (scanlp
) < max
) {
1085 charstring_push_back (scanlp
, '\n');
1088 charstring_chars (scanlp
) < max
&& i
> 0;
1090 charstring_push_back (scanlp
, ' ');
1093 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1099 if (comp
->c_flags
& CF_PARSED
)
1101 if (comp
->c_mn
!= &fmt_mnull
)
1102 mnfree (comp
->c_mn
);
1103 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1104 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1108 comp
->c_flags
|= CF_PARSED
;
1110 while (getname("")) /* XXX */
1112 comp
->c_mn
= &fmt_mnull
;
1120 * if there's no component, we say true. Otherwise we
1121 * say "true" only if we can parse the address and it
1122 * matches one of our addresses.
1125 if (comp
->c_mn
!= &fmt_mnull
)
1126 mnfree (comp
->c_mn
);
1127 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1128 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1131 comp
->c_flags
|= CF_TRUE
;
1132 /* Set str for use with FT_GETMYMBOX. With
1133 FT_GETMYADDR, comp->c_mn will be run through
1134 FT_LS_ADDR, which will strip off any pers
1138 comp
->c_flags
&= ~CF_TRUE
;
1140 while ((sp
= getname(sp
)))
1141 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1142 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1144 comp
->c_flags
|= CF_TRUE
;
1145 /* Set str and comp->c_text for use with
1146 FT_GETMYMBOX. With FT_GETMYADDR,
1147 comp->c_mn will be run through
1148 FT_LS_ADDR, which will strip off any
1150 free (comp
->c_text
);
1151 comp
->c_text
= str
= strdup (mn
->m_text
);
1154 comp
->c_flags
|= CF_PARSED
;
1156 while (getname("")) /* XXX */
1158 if (comp
->c_text
== 0)
1159 comp
->c_flags
|= CF_TRUE
;
1161 comp
->c_flags
&= ~CF_TRUE
;
1163 comp
->c_mn
= &fmt_mnull
;
1165 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1166 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1167 /* Fool FT_LS_ADDR into not producing an address. */
1168 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1174 * Call our tracing callback function, if one was supplied
1177 if (callbacks
&& callbacks
->trace_func
)
1178 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1179 str
, charstring_buffer (scanlp
));
1183 /* Emit any trailing sequences of zero display length. */
1184 while (fmt
->f_type
!= FT_DONE
) {
1185 if (fmt
->f_type
== FT_LS_LIT
) {
1187 if (callbacks
&& callbacks
->trace_func
)
1188 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1189 str
, charstring_buffer (scanlp
));
1190 } else if (fmt
->f_type
== FT_STRLITZ
) {
1191 /* Don't want to emit part of an escape sequence. So if
1192 there isn't enough room in the buffer for the entire
1193 string, skip it completely. Need room for null
1194 terminator, and maybe trailing newline (added below). */
1196 for (sp
= str
; *sp
; ++sp
) {
1197 charstring_push_back (scanlp
, *sp
);
1200 if (callbacks
&& callbacks
->trace_func
)
1201 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1202 str
, charstring_buffer (scanlp
));
1208 if (charstring_bytes (scanlp
) > 0) {
1210 * Append a newline if the last character wasn't.
1212 #ifdef MULTIBYTE_SUPPORT
1214 * It's a little tricky because the last byte might be part of
1215 * a multibyte character, in which case we assume that wasn't
1218 size_t last_char_len
= charstring_last_char_len (scanlp
);
1219 #else /* ! MULTIBYTE_SUPPORT */
1220 size_t last_char_len
= 1;
1221 #endif /* ! MULTIBYTE_SUPPORT */
1223 if (last_char_len
> 1 ||
1224 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1225 charstring_push_back (scanlp
, '\n');