]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
869a278ef69287a6696011b793d9294c70878844
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).
14 #include "fmt_rfc2047.h"
16 #include "context_find.h"
18 #include "h/addrsbr.h"
19 #include "h/fmt_scan.h"
21 #include "h/fmt_compile.h"
25 #ifdef HAVE_SYS_TIME_H
26 # include <sys/time.h>
29 #ifdef MULTIBYTE_SUPPORT
34 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
40 static int match (char *, char *) PURE
;
41 static char *get_x400_friendly (char *, char *, int);
42 static int get_x400_comp (char *, char *, char *, int);
46 * test if string "sub" appears anywhere in
47 * string "str" (case insensitive).
51 match (char *str
, char *sub
)
57 c1
= tolower((unsigned char)c1
);
58 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
62 s1
= sub
+ 1; s2
= str
;
63 while ((c1
= *s1
++) &&
64 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
73 * copy a number to the destination subject to a maximum width
76 cpnumber(charstring_t dest
, int num
, int wid
, char fill
, size_t max
)
78 /* Maybe we should handle left padding at some point? */
82 wid
= -wid
; /* OK because wid originally a short. */
83 if ((size_t)wid
< (num
>= 0 ? max
: max
-1)) {
84 /* Build up the string representation of num in reverse. */
85 charstring_t rev
= charstring_create (0);
86 int i
= num
>= 0 ? num
: -num
;
89 charstring_push_back (rev
, i
% 10 + '0');
91 } while (--wid
> 0 && i
> 0);
93 /* Overflowed the field (wid). */
94 charstring_push_back (rev
, '?');
95 } else if (num
< 0 && wid
> 0) {
96 /* Shouldn't need the wid > 0 check, that's why the condition
97 at the top checks wid < max-1 when num < 0. */
100 charstring_push_back (rev
, '-');
103 while (wid
-- > 0 && fill
!= 0) {
104 charstring_push_back (rev
, fill
);
106 if (num
< 0 && fill
== '0') {
107 charstring_push_back (rev
, '-');
111 /* Output the string in reverse. */
112 size_t b
= charstring_bytes (rev
);
113 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
116 charstring_push_back (dest
, *--cp
);
120 charstring_free (rev
);
125 * copy string from str to dest padding with the fill character to a
126 * size of wid characters. if wid is negative, the string is right
127 * aligned no more than max characters are copied
130 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
)
132 int remaining
; /* remaining output width available */
134 struct charstring
*trimmed
;
135 size_t end
; /* number of input bytes remaining in str */
136 #ifdef MULTIBYTE_SUPPORT
137 int char_len
; /* bytes in current character */
142 char *sp
; /* current position in source string */
146 if ((remaining
= wid
) < 0) {
147 remaining
= -remaining
;
150 if (remaining
> (int) max
) { remaining
= max
; }
152 trimmed
= rjust
? charstring_create(remaining
) : dest
;
154 bool prevCtrl
= true;
156 #ifdef MULTIBYTE_SUPPORT
157 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
160 while (*sp
&& remaining
> 0 && end
> 0) {
161 #ifdef MULTIBYTE_SUPPORT
162 char_len
= mbtowc(&wide_char
, sp
, end
);
165 * See the relevant comments in cpstripped() to explain what's
166 * going on here; we want to handle the case where we get
167 * characters that mbtowc() cannot handle
172 char_len
= mbtowc(&wide_char
, altstr
, 1);
179 w
= wcwidth(wide_char
);
181 /* If w > remaining, w must be positive. */
188 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
193 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
194 intentionally warns if they are passed a char. */
195 c
= (unsigned char) *sp
;
196 if (iscntrl(c
) || isspace(c
)) {
200 charstring_push_back (trimmed
, ' ');
209 #ifdef MULTIBYTE_SUPPORT
210 if (w
>= 0 && remaining
>= w
) {
211 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
218 charstring_push_back (trimmed
, *sp
++);
224 while (remaining
-- > 0) {
225 charstring_push_back(dest
, fill
);
229 charstring_append(dest
, trimmed
);
230 charstring_free(trimmed
);
234 #ifdef MULTIBYTE_SUPPORT
236 cpstripped (charstring_t dest
, size_t max
, char *str
)
239 static char *oddchar
;
240 static size_t oddlen
;
241 static char *spacechar
;
242 static size_t spacelen
;
255 two
= MB_CUR_MAX
* 2; /* Varies at run-time. */
257 oddchar
= mh_xmalloc(two
);
258 oddlen
= wcstombs(oddchar
, L
"?", two
);
261 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
262 spacechar
= mh_xmalloc(two
);
263 spacelen
= wcstombs(spacechar
, L
" ", two
);
264 assert(spacelen
> 0);
268 return; /* It's unclear why no padding in this case. */
269 end
= str
+ strlen(str
);
271 if (mbtowc(NULL
, NULL
, 0))
272 {} /* Reset shift state. */
274 squash
= true; /* Trim `space' or `cntrl' from the start. */
277 return; /* It's unclear why no padding in this case. */
279 srclen
= mbtowc(&rune
, str
, end
- str
);
281 /* Invalid rune, or not enough bytes to finish it. */
285 str
++; /* Skip one byte. */
291 if (iswspace(rune
) || iswcntrl(rune
)) {
293 continue; /* Amidst a run of these. */
310 if ((size_t)w
> max
) {
311 /* No room for rune; pad. */
313 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
317 charstring_push_back_chars(dest
, src
, srclen
, w
);
323 #ifndef MULTIBYTE_SUPPORT
325 cpstripped (charstring_t dest
, size_t max
, char *str
)
333 squash
= true; /* Strip leading cases. */
335 c
= (unsigned char)*str
++;
339 if (isspace(c
) || iscntrl(c
)) {
347 charstring_push_back(dest
, (char)c
);
352 static char *lmonth
[] = { "January", "February","March", "April",
353 "May", "June", "July", "August",
354 "September","October", "November","December" };
357 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
359 char given
[BUFSIZ
], surname
[BUFSIZ
];
368 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
369 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
375 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
378 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
379 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
381 snprintf (buffer
, buffer_len
, "%s", surname
);
387 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
392 if ((idx
= stringdex (key
, mbox
)) < 0
393 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
396 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
401 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
402 struct fmt_callbacks
*callbacks
)
406 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
418 * max is the same as width, but unsigned so comparisons
419 * with charstring_chars() won't raise compile warnings.
422 savestr
= str
= NULL
;
425 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
426 switch (fmt
->f_type
) {
429 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
434 case FT_LS_DECODECOMP
:
436 * Trim these components of any newlines.
438 * But don't trim the "body" and "text" components.
443 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
444 (i
= strlen(comp
->c_text
)) > 0) {
445 if (comp
->c_text
[i
- 1] == '\n' &&
446 strcmp(comp
->c_name
, "body") != 0 &&
447 strcmp(comp
->c_name
, "text") != 0)
448 comp
->c_text
[i
- 1] = '\0';
449 comp
->c_flags
|= CF_TRIMMED
;
456 for ( ; charstring_chars (scanlp
) < max
; ) {
457 switch (fmt
->f_type
) {
460 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
461 fmt
->f_comp
->c_text
);
464 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
465 fmt
->f_fill
, max
- charstring_chars (scanlp
));
470 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
471 charstring_push_back (scanlp
, c
);
480 rjust
= true; /* XXX should do something with this */
482 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
483 charstring_push_back (scanlp
, c
);
485 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
486 charstring_push_back (scanlp
, fmt
->f_fill
);
491 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
494 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
495 max
- charstring_chars (scanlp
));
500 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
501 charstring_push_back (scanlp
, c
);
506 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
509 die("internal error (FT_STRFW)");
515 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
516 cpnumber (scanlp
, value
, wid
, ' ',
517 max
- charstring_chars (scanlp
));
524 unsigned int whole
, tenths
;
525 unsigned int scale
= 0;
526 unsigned int val
= (unsigned int)value
;
527 char *kibisuff
= NULL
;
529 switch (fmt
->f_type
) {
530 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
531 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
535 snprintf(buffer
, sizeof(buffer
), "%u", val
);
537 /* To prevent divide by 0, found by clang static
539 if (scale
== 0) { scale
= 1; }
541 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
542 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
548 strcpy(buffer
, "huge");
550 /* val is scale times too big. we want tenths */
558 tenths
= val
- (whole
* 10);
561 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
562 whole
, tenths
, *unitcp
, kibisuff
);
564 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
565 whole
, *unitcp
, kibisuff
);
573 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
574 max
- charstring_chars (scanlp
));
578 charstring_push_back (scanlp
, fmt
->f_char
);
582 if (callbacks
&& callbacks
->trace_func
)
583 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
584 str
, charstring_buffer (scanlp
));
588 if (!(value
= (str
&& *str
))) {
589 if (callbacks
&& callbacks
->trace_func
)
590 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
591 str
, charstring_buffer (scanlp
));
598 if (!(value
= (str
== NULL
|| *str
== 0))) {
599 if (callbacks
&& callbacks
->trace_func
)
600 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
601 str
, charstring_buffer (scanlp
));
608 if (value
!= fmt
->f_value
) {
609 if (callbacks
&& callbacks
->trace_func
)
610 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
611 str
, charstring_buffer (scanlp
));
618 if (value
== fmt
->f_value
) {
619 if (callbacks
&& callbacks
->trace_func
)
620 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
621 str
, charstring_buffer (scanlp
));
628 if (value
<= fmt
->f_value
) {
629 if (callbacks
&& callbacks
->trace_func
)
630 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
631 str
, charstring_buffer (scanlp
));
638 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
639 if (callbacks
&& callbacks
->trace_func
)
640 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
641 str
, charstring_buffer (scanlp
));
649 value
= match (str
, fmt
->f_text
);
655 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
656 if (callbacks
&& callbacks
->trace_func
)
657 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
658 str
, charstring_buffer (scanlp
));
665 value
= uprf (str
, fmt
->f_text
);
669 value
= (str
!= NULL
&& *str
!= 0);
673 value
= (str
== NULL
|| *str
== 0);
677 value
= (fmt
->f_value
== value
);
681 value
= (fmt
->f_value
!= value
);
685 value
= (fmt
->f_value
> value
);
689 if (callbacks
&& callbacks
->trace_func
)
690 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
691 str
, charstring_buffer (scanlp
));
699 str
= fmt
->f_comp
->c_text
;
705 if (!(str
= getenv (fmt
->f_text
)))
709 if (!(str
= context_find (fmt
->f_text
)))
713 case FT_LS_DECODECOMP
:
714 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
717 str
= fmt
->f_comp
->c_text
;
721 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
730 strncpy(buffer
, str
, sizeof(buffer
));
731 buffer
[sizeof(buffer
)-1] = '\0';
733 while (isspace((unsigned char) *str
))
736 if ((i
= fmt
->f_width
) < 0) {
741 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
744 xp
+= strlen(str
) - 1;
745 while (xp
> str
&& isspace((unsigned char) *xp
))
747 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
748 str
+= strlen(str
) - i
;
753 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
756 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
759 value
= fmt
->f_value
;
762 value
= dat
[fmt
->f_value
];
770 case FT_LV_CHAR_LEFT
:
771 value
= max
- charstring_bytes (scanlp
);
774 value
+= fmt
->f_value
;
777 value
= fmt
->f_value
- value
;
779 case FT_LV_MULTIPLY_L
:
780 value
*= fmt
->f_value
;
784 value
/= fmt
->f_value
;
790 value
%= fmt
->f_value
;
799 value
= fmt
->f_comp
->c_tws
->tw_sec
;
802 value
= fmt
->f_comp
->c_tws
->tw_min
;
805 value
= fmt
->f_comp
->c_tws
->tw_hour
;
808 value
= fmt
->f_comp
->c_tws
->tw_mday
;
811 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
814 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
817 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
820 str
= dtwszone (fmt
->f_comp
->c_tws
);
823 value
= fmt
->f_comp
->c_tws
->tw_year
;
826 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
828 value
= tws
->tw_wday
;
831 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
833 str
= tw_dotw
[tws
->tw_wday
];
836 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
838 str
= tw_ldotw
[tws
->tw_wday
];
841 value
= fmt
->f_comp
->c_tws
->tw_yday
;
844 value
= fmt
->f_comp
->c_tws
->tw_zone
;
847 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
848 value
= dmktime(fmt
->f_comp
->c_tws
);
851 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
852 value
= dmktime(fmt
->f_comp
->c_tws
);
853 value
= time(NULL
) - value
;
856 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
858 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
868 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
874 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
877 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
880 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
884 str
= fmt
->f_comp
->c_mn
->m_pers
;
887 str
= fmt
->f_comp
->c_mn
->m_mbox
;
890 str
= fmt
->f_comp
->c_mn
->m_host
;
893 str
= fmt
->f_comp
->c_mn
->m_path
;
896 str
= fmt
->f_comp
->c_mn
->m_gname
;
899 str
= fmt
->f_comp
->c_mn
->m_note
;
902 str
= adrformat( fmt
->f_comp
->c_mn
);
905 value
= fmt
->f_comp
->c_mn
->m_type
;
908 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
911 value
= fmt
->f_comp
->c_mn
->m_nohost
;
915 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
916 str
= fmt
->f_comp
->c_text
;
919 if (fmt
->f_type
== FT_LS_ADDR
)
921 if ((str
= mn
->m_pers
) == NULL
) {
922 if ((str
= mn
->m_note
)) {
924 strncpy (buffer
, str
, sizeof(buffer
));
925 buffer
[sizeof(buffer
)-1] = '\0';
929 sp
= str
+ strlen(str
) - 1;
938 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
939 buffer
, sizeof(buffer
)))) {
941 switch (mn
->m_type
) {
946 snprintf (buffer
, sizeof(buffer
), "%s!%s",
947 mn
->m_host
, mn
->m_mbox
);
952 snprintf (buffer
, sizeof(buffer
), "%s@%s",
953 mn
->m_mbox
, mn
->m_host
);
965 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
969 strncpy(buffer
, str
, sizeof(buffer
));
970 /* strncpy doesn't NUL-terminate if it fills the buffer */
971 buffer
[sizeof(buffer
)-1] = '\0';
972 unquote_string(buffer
, buffer2
);
979 if ((t
= comp
->c_tws
->tw_clock
) == 0)
980 t
= dmktime(comp
->c_tws
);
981 tws
= dlocaltime(&t
);
987 if ((t
= comp
->c_tws
->tw_clock
) == 0)
988 t
= dmktime(comp
->c_tws
);
995 if (comp
->c_flags
& CF_PARSED
)
997 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
999 comp
->c_flags
&= ~CF_TRUE
;
1000 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
1002 comp
->c_flags
= CF_TRUE
;
1004 comp
->c_flags
|= CF_PARSED
;
1008 /* hook for custom address list formatting (see replsbr.c) */
1009 if (callbacks
&& callbacks
->formataddr
)
1010 str
= callbacks
->formataddr (savestr
, str
);
1012 str
= formataddr (savestr
, str
);
1016 /* The same as formataddr, but doesn't do duplicate suppression */
1017 if (callbacks
&& callbacks
->concataddr
)
1018 str
= callbacks
->concataddr (savestr
, str
);
1020 str
= concataddr (savestr
, str
);
1024 /* output the str register as an address component,
1025 * splitting it into multiple lines if necessary. The
1026 * value reg. contains the max line length. The lit.
1027 * field may contain a string to prepend to the result
1032 int indent
, wid
, len
;
1036 len
= str
? strlen (str
) : 0;
1038 indent
= strlen (sp
);
1041 die("putaddr -- num register (%d) must be greater "
1042 "than label width (%d)", value
, indent
);
1044 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1045 charstring_push_back (scanlp
, c
);
1048 /* try to break at a comma; failing that, break at a
1051 lastb
= 0; sp
= lp
+ wid
;
1052 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1053 if (! lastb
&& isspace(c
))
1057 if (! (sp
= lastb
)) {
1059 while (*sp
&& *sp
!= ',' &&
1060 !isspace((unsigned char) *sp
))
1067 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1068 charstring_push_back (scanlp
, *lp
++);
1070 while (isspace((unsigned char) *lp
))
1073 if (charstring_chars (scanlp
) < max
) {
1074 charstring_push_back (scanlp
, '\n');
1077 charstring_chars (scanlp
) < max
&& i
> 0;
1079 charstring_push_back (scanlp
, ' ');
1082 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1088 if (comp
->c_flags
& CF_PARSED
)
1090 if (comp
->c_mn
!= &fmt_mnull
)
1091 mnfree (comp
->c_mn
);
1092 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1093 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1097 comp
->c_flags
|= CF_PARSED
;
1099 while (getname("")) /* XXX */
1101 comp
->c_mn
= &fmt_mnull
;
1109 * if there's no component, we say true. Otherwise we
1110 * say "true" only if we can parse the address and it
1111 * matches one of our addresses.
1114 if (comp
->c_mn
!= &fmt_mnull
)
1115 mnfree (comp
->c_mn
);
1116 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1117 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1120 comp
->c_flags
|= CF_TRUE
;
1121 /* Set str for use with FT_GETMYMBOX. With
1122 FT_GETMYADDR, comp->c_mn will be run through
1123 FT_LS_ADDR, which will strip off any pers
1127 comp
->c_flags
&= ~CF_TRUE
;
1129 while ((sp
= getname(sp
)))
1130 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1131 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1133 comp
->c_flags
|= CF_TRUE
;
1134 /* Set str and comp->c_text for use with
1135 FT_GETMYMBOX. With FT_GETMYADDR,
1136 comp->c_mn will be run through
1137 FT_LS_ADDR, which will strip off any
1139 free (comp
->c_text
);
1140 comp
->c_text
= str
= strdup (mn
->m_text
);
1143 comp
->c_flags
|= CF_PARSED
;
1145 while (getname("")) /* XXX */
1147 if (comp
->c_text
== 0)
1148 comp
->c_flags
|= CF_TRUE
;
1150 comp
->c_flags
&= ~CF_TRUE
;
1152 comp
->c_mn
= &fmt_mnull
;
1154 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1155 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1156 /* Fool FT_LS_ADDR into not producing an address. */
1157 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1163 * Call our tracing callback function, if one was supplied
1166 if (callbacks
&& callbacks
->trace_func
)
1167 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1168 str
, charstring_buffer (scanlp
));
1172 /* Emit any trailing sequences of zero display length. */
1173 while (fmt
->f_type
!= FT_DONE
) {
1174 if (fmt
->f_type
== FT_LS_LIT
) {
1176 if (callbacks
&& callbacks
->trace_func
)
1177 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1178 str
, charstring_buffer (scanlp
));
1179 } else if (fmt
->f_type
== FT_STRLITZ
) {
1180 /* Don't want to emit part of an escape sequence. So if
1181 there isn't enough room in the buffer for the entire
1182 string, skip it completely. Need room for null
1183 terminator, and maybe trailing newline (added below). */
1185 for (sp
= str
; *sp
; ++sp
) {
1186 charstring_push_back (scanlp
, *sp
);
1189 if (callbacks
&& callbacks
->trace_func
)
1190 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1191 str
, charstring_buffer (scanlp
));
1197 if (charstring_bytes (scanlp
) > 0) {
1199 * Append a newline if the last character wasn't.
1201 #ifdef MULTIBYTE_SUPPORT
1203 * It's a little tricky because the last byte might be part of
1204 * a multibyte character, in which case we assume that wasn't
1207 size_t last_char_len
= charstring_last_char_len (scanlp
);
1208 #else /* ! MULTIBYTE_SUPPORT */
1209 size_t last_char_len
= 1;
1210 #endif /* ! MULTIBYTE_SUPPORT */
1212 if (last_char_len
> 1 ||
1213 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1214 charstring_push_back (scanlp
, '\n');