]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
1d8dd29c9ffa5621394b5b52b76ceffd156827d0
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 "context_find.h"
14 #include "h/addrsbr.h"
15 #include "h/fmt_scan.h"
17 #include "h/fmt_compile.h"
21 #ifdef HAVE_SYS_TIME_H
22 # include <sys/time.h>
25 #ifdef MULTIBYTE_SUPPORT
30 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
36 static int match (char *, char *) PURE
;
37 static char *get_x400_friendly (char *, char *, int);
38 static int get_x400_comp (char *, char *, char *, int);
42 * test if string "sub" appears anywhere in
43 * string "str" (case insensitive).
47 match (char *str
, char *sub
)
53 c1
= tolower((unsigned char)c1
);
54 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
58 s1
= sub
+ 1; s2
= str
;
59 while ((c1
= *s1
++) &&
60 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
69 * copy a number to the destination subject to a maximum width
72 cpnumber(charstring_t dest
, int num
, int wid
, char fill
, size_t max
)
74 /* Maybe we should handle left padding at some point? */
78 wid
= -wid
; /* OK because wid originally a short. */
79 if ((size_t)wid
< (num
>= 0 ? max
: max
-1)) {
80 /* Build up the string representation of num in reverse. */
81 charstring_t rev
= charstring_create (0);
82 int i
= num
>= 0 ? num
: -num
;
85 charstring_push_back (rev
, i
% 10 + '0');
87 } while (--wid
> 0 && i
> 0);
89 /* Overflowed the field (wid). */
90 charstring_push_back (rev
, '?');
91 } else if (num
< 0 && wid
> 0) {
92 /* Shouldn't need the wid > 0 check, that's why the condition
93 at the top checks wid < max-1 when num < 0. */
96 charstring_push_back (rev
, '-');
99 while (wid
-- > 0 && fill
!= 0) {
100 charstring_push_back (rev
, fill
);
102 if (num
< 0 && fill
== '0') {
103 charstring_push_back (rev
, '-');
107 /* Output the string in reverse. */
108 size_t b
= charstring_bytes (rev
);
109 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
112 charstring_push_back (dest
, *--cp
);
116 charstring_free (rev
);
121 * copy string from str to dest padding with the fill character to a
122 * size of wid characters. if wid is negative, the string is right
123 * aligned no more than max characters are copied
126 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
)
128 int remaining
; /* remaining output width available */
130 struct charstring
*trimmed
;
131 size_t end
; /* number of input bytes remaining in str */
132 #ifdef MULTIBYTE_SUPPORT
133 int char_len
; /* bytes in current character */
138 char *sp
; /* current position in source string */
142 if ((remaining
= wid
) < 0) {
143 remaining
= -remaining
;
146 if (remaining
> (int) max
) { remaining
= max
; }
148 trimmed
= rjust
? charstring_create(remaining
) : dest
;
150 bool prevCtrl
= true;
152 #ifdef MULTIBYTE_SUPPORT
153 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
156 while (*sp
&& remaining
> 0 && end
> 0) {
157 #ifdef MULTIBYTE_SUPPORT
158 char_len
= mbtowc(&wide_char
, sp
, end
);
161 * See the relevant comments in cpstripped() to explain what's
162 * going on here; we want to handle the case where we get
163 * characters that mbtowc() cannot handle
168 char_len
= mbtowc(&wide_char
, altstr
, 1);
175 w
= wcwidth(wide_char
);
177 /* If w > remaining, w must be positive. */
184 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
189 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
190 intentionally warns if they are passed a char. */
191 c
= (unsigned char) *sp
;
192 if (iscntrl(c
) || isspace(c
)) {
196 charstring_push_back (trimmed
, ' ');
205 #ifdef MULTIBYTE_SUPPORT
206 if (w
>= 0 && remaining
>= w
) {
207 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
214 charstring_push_back (trimmed
, *sp
++);
220 while (remaining
-- > 0) {
221 charstring_push_back(dest
, fill
);
225 charstring_append(dest
, trimmed
);
226 charstring_free(trimmed
);
230 #ifdef MULTIBYTE_SUPPORT
232 cpstripped (charstring_t dest
, size_t max
, char *str
)
235 static char *oddchar
;
236 static size_t oddlen
;
237 static char *spacechar
;
238 static size_t spacelen
;
251 two
= MB_CUR_MAX
* 2; /* Varies at run-time. */
253 oddchar
= mh_xmalloc(two
);
254 oddlen
= wcstombs(oddchar
, L
"?", two
);
257 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
258 spacechar
= mh_xmalloc(two
);
259 spacelen
= wcstombs(spacechar
, L
" ", two
);
260 assert(spacelen
> 0);
264 return; /* It's unclear why no padding in this case. */
265 end
= str
+ strlen(str
);
267 if (mbtowc(NULL
, NULL
, 0))
268 {} /* Reset shift state. */
270 squash
= true; /* Trim `space' or `cntrl' from the start. */
273 return; /* It's unclear why no padding in this case. */
275 srclen
= mbtowc(&rune
, str
, end
- str
);
277 /* Invalid rune, or not enough bytes to finish it. */
281 str
++; /* Skip one byte. */
287 if (iswspace(rune
) || iswcntrl(rune
)) {
289 continue; /* Amidst a run of these. */
306 if ((size_t)w
> max
) {
307 /* No room for rune; pad. */
309 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
313 charstring_push_back_chars(dest
, src
, srclen
, w
);
319 #ifndef MULTIBYTE_SUPPORT
321 cpstripped (charstring_t dest
, size_t max
, char *str
)
329 squash
= true; /* Strip leading cases. */
331 c
= (unsigned char)*str
++;
335 if (isspace(c
) || iscntrl(c
)) {
343 charstring_push_back(dest
, (char)c
);
348 static char *lmonth
[] = { "January", "February","March", "April",
349 "May", "June", "July", "August",
350 "September","October", "November","December" };
353 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
355 char given
[BUFSIZ
], surname
[BUFSIZ
];
364 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
365 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
371 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
374 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
375 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
377 snprintf (buffer
, buffer_len
, "%s", surname
);
383 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
388 if ((idx
= stringdex (key
, mbox
)) < 0
389 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
392 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
397 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
398 struct fmt_callbacks
*callbacks
)
402 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
414 * max is the same as width, but unsigned so comparisons
415 * with charstring_chars() won't raise compile warnings.
418 savestr
= str
= NULL
;
421 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
422 switch (fmt
->f_type
) {
425 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
430 case FT_LS_DECODECOMP
:
432 * Trim these components of any newlines.
434 * But don't trim the "body" and "text" components.
439 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
440 (i
= strlen(comp
->c_text
)) > 0) {
441 if (comp
->c_text
[i
- 1] == '\n' &&
442 strcmp(comp
->c_name
, "body") != 0 &&
443 strcmp(comp
->c_name
, "text") != 0)
444 comp
->c_text
[i
- 1] = '\0';
445 comp
->c_flags
|= CF_TRIMMED
;
452 for ( ; charstring_chars (scanlp
) < max
; ) {
453 switch (fmt
->f_type
) {
456 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
457 fmt
->f_comp
->c_text
);
460 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
461 fmt
->f_fill
, max
- charstring_chars (scanlp
));
466 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
467 charstring_push_back (scanlp
, c
);
476 rjust
= true; /* XXX should do something with this */
478 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
479 charstring_push_back (scanlp
, c
);
481 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
482 charstring_push_back (scanlp
, fmt
->f_fill
);
487 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
490 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
491 max
- charstring_chars (scanlp
));
496 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
497 charstring_push_back (scanlp
, c
);
502 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
505 die("internal error (FT_STRFW)");
511 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
512 cpnumber (scanlp
, value
, wid
, ' ',
513 max
- charstring_chars (scanlp
));
520 unsigned int whole
, tenths
;
521 unsigned int scale
= 0;
522 unsigned int val
= (unsigned int)value
;
523 char *kibisuff
= NULL
;
525 switch (fmt
->f_type
) {
526 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
527 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
531 snprintf(buffer
, sizeof(buffer
), "%u", val
);
533 /* To prevent divide by 0, found by clang static
535 if (scale
== 0) { scale
= 1; }
537 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
538 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
544 strcpy(buffer
, "huge");
546 /* val is scale times too big. we want tenths */
554 tenths
= val
- (whole
* 10);
557 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
558 whole
, tenths
, *unitcp
, kibisuff
);
560 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
561 whole
, *unitcp
, kibisuff
);
569 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
570 max
- charstring_chars (scanlp
));
574 charstring_push_back (scanlp
, fmt
->f_char
);
578 if (callbacks
&& callbacks
->trace_func
)
579 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
580 str
, charstring_buffer (scanlp
));
584 if (!(value
= (str
&& *str
))) {
585 if (callbacks
&& callbacks
->trace_func
)
586 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
587 str
, charstring_buffer (scanlp
));
594 if (!(value
= (str
== NULL
|| *str
== 0))) {
595 if (callbacks
&& callbacks
->trace_func
)
596 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
597 str
, charstring_buffer (scanlp
));
604 if (value
!= fmt
->f_value
) {
605 if (callbacks
&& callbacks
->trace_func
)
606 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
607 str
, charstring_buffer (scanlp
));
614 if (value
== fmt
->f_value
) {
615 if (callbacks
&& callbacks
->trace_func
)
616 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
617 str
, charstring_buffer (scanlp
));
624 if (value
<= fmt
->f_value
) {
625 if (callbacks
&& callbacks
->trace_func
)
626 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
627 str
, charstring_buffer (scanlp
));
634 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
635 if (callbacks
&& callbacks
->trace_func
)
636 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
637 str
, charstring_buffer (scanlp
));
645 value
= match (str
, fmt
->f_text
);
651 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
652 if (callbacks
&& callbacks
->trace_func
)
653 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
654 str
, charstring_buffer (scanlp
));
661 value
= uprf (str
, fmt
->f_text
);
665 value
= (str
!= NULL
&& *str
!= 0);
669 value
= (str
== NULL
|| *str
== 0);
673 value
= (fmt
->f_value
== value
);
677 value
= (fmt
->f_value
!= value
);
681 value
= (fmt
->f_value
> value
);
685 if (callbacks
&& callbacks
->trace_func
)
686 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
687 str
, charstring_buffer (scanlp
));
695 str
= fmt
->f_comp
->c_text
;
701 if (!(str
= getenv (fmt
->f_text
)))
705 if (!(str
= context_find (fmt
->f_text
)))
709 case FT_LS_DECODECOMP
:
710 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
713 str
= fmt
->f_comp
->c_text
;
717 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
726 strncpy(buffer
, str
, sizeof(buffer
));
727 buffer
[sizeof(buffer
)-1] = '\0';
729 while (isspace((unsigned char) *str
))
732 if ((i
= fmt
->f_width
) < 0) {
737 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
740 xp
+= strlen(str
) - 1;
741 while (xp
> str
&& isspace((unsigned char) *xp
))
743 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
744 str
+= strlen(str
) - i
;
749 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
752 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
755 value
= fmt
->f_value
;
758 value
= dat
[fmt
->f_value
];
766 case FT_LV_CHAR_LEFT
:
767 value
= max
- charstring_bytes (scanlp
);
770 value
+= fmt
->f_value
;
773 value
= fmt
->f_value
- value
;
775 case FT_LV_MULTIPLY_L
:
776 value
*= fmt
->f_value
;
780 value
/= fmt
->f_value
;
786 value
%= fmt
->f_value
;
795 value
= fmt
->f_comp
->c_tws
->tw_sec
;
798 value
= fmt
->f_comp
->c_tws
->tw_min
;
801 value
= fmt
->f_comp
->c_tws
->tw_hour
;
804 value
= fmt
->f_comp
->c_tws
->tw_mday
;
807 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
810 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
813 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
816 str
= dtwszone (fmt
->f_comp
->c_tws
);
819 value
= fmt
->f_comp
->c_tws
->tw_year
;
822 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
824 value
= tws
->tw_wday
;
827 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
829 str
= tw_dotw
[tws
->tw_wday
];
832 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
834 str
= tw_ldotw
[tws
->tw_wday
];
837 value
= fmt
->f_comp
->c_tws
->tw_yday
;
840 value
= fmt
->f_comp
->c_tws
->tw_zone
;
843 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
844 value
= dmktime(fmt
->f_comp
->c_tws
);
847 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
848 value
= dmktime(fmt
->f_comp
->c_tws
);
849 value
= time(NULL
) - value
;
852 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
854 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
864 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
870 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
873 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
876 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
880 str
= fmt
->f_comp
->c_mn
->m_pers
;
883 str
= fmt
->f_comp
->c_mn
->m_mbox
;
886 str
= fmt
->f_comp
->c_mn
->m_host
;
889 str
= fmt
->f_comp
->c_mn
->m_path
;
892 str
= fmt
->f_comp
->c_mn
->m_gname
;
895 str
= fmt
->f_comp
->c_mn
->m_note
;
898 str
= adrformat( fmt
->f_comp
->c_mn
);
901 value
= fmt
->f_comp
->c_mn
->m_type
;
904 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
907 value
= fmt
->f_comp
->c_mn
->m_nohost
;
911 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
912 str
= fmt
->f_comp
->c_text
;
915 if (fmt
->f_type
== FT_LS_ADDR
)
917 if ((str
= mn
->m_pers
) == NULL
) {
918 if ((str
= mn
->m_note
)) {
920 strncpy (buffer
, str
, sizeof(buffer
));
921 buffer
[sizeof(buffer
)-1] = '\0';
925 sp
= str
+ strlen(str
) - 1;
934 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
935 buffer
, sizeof(buffer
)))) {
937 switch (mn
->m_type
) {
942 snprintf (buffer
, sizeof(buffer
), "%s!%s",
943 mn
->m_host
, mn
->m_mbox
);
948 snprintf (buffer
, sizeof(buffer
), "%s@%s",
949 mn
->m_mbox
, mn
->m_host
);
961 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
965 strncpy(buffer
, str
, sizeof(buffer
));
966 /* strncpy doesn't NUL-terminate if it fills the buffer */
967 buffer
[sizeof(buffer
)-1] = '\0';
968 unquote_string(buffer
, buffer2
);
975 if ((t
= comp
->c_tws
->tw_clock
) == 0)
976 t
= dmktime(comp
->c_tws
);
977 tws
= dlocaltime(&t
);
983 if ((t
= comp
->c_tws
->tw_clock
) == 0)
984 t
= dmktime(comp
->c_tws
);
991 if (comp
->c_flags
& CF_PARSED
)
993 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
995 comp
->c_flags
&= ~CF_TRUE
;
996 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
998 comp
->c_flags
= CF_TRUE
;
1000 comp
->c_flags
|= CF_PARSED
;
1004 /* hook for custom address list formatting (see replsbr.c) */
1005 if (callbacks
&& callbacks
->formataddr
)
1006 str
= callbacks
->formataddr (savestr
, str
);
1008 str
= formataddr (savestr
, str
);
1012 /* The same as formataddr, but doesn't do duplicate suppression */
1013 if (callbacks
&& callbacks
->concataddr
)
1014 str
= callbacks
->concataddr (savestr
, str
);
1016 str
= concataddr (savestr
, str
);
1020 /* output the str register as an address component,
1021 * splitting it into multiple lines if necessary. The
1022 * value reg. contains the max line length. The lit.
1023 * field may contain a string to prepend to the result
1028 int indent
, wid
, len
;
1032 len
= str
? strlen (str
) : 0;
1034 indent
= strlen (sp
);
1037 die("putaddr -- num register (%d) must be greater "
1038 "than label width (%d)", value
, indent
);
1040 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1041 charstring_push_back (scanlp
, c
);
1044 /* try to break at a comma; failing that, break at a
1047 lastb
= 0; sp
= lp
+ wid
;
1048 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1049 if (! lastb
&& isspace(c
))
1053 if (! (sp
= lastb
)) {
1055 while (*sp
&& *sp
!= ',' &&
1056 !isspace((unsigned char) *sp
))
1063 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1064 charstring_push_back (scanlp
, *lp
++);
1066 while (isspace((unsigned char) *lp
))
1069 if (charstring_chars (scanlp
) < max
) {
1070 charstring_push_back (scanlp
, '\n');
1073 charstring_chars (scanlp
) < max
&& i
> 0;
1075 charstring_push_back (scanlp
, ' ');
1078 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1084 if (comp
->c_flags
& CF_PARSED
)
1086 if (comp
->c_mn
!= &fmt_mnull
)
1087 mnfree (comp
->c_mn
);
1088 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1089 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1093 comp
->c_flags
|= CF_PARSED
;
1095 while (getname("")) /* XXX */
1097 comp
->c_mn
= &fmt_mnull
;
1105 * if there's no component, we say true. Otherwise we
1106 * say "true" only if we can parse the address and it
1107 * matches one of our addresses.
1110 if (comp
->c_mn
!= &fmt_mnull
)
1111 mnfree (comp
->c_mn
);
1112 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1113 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1116 comp
->c_flags
|= CF_TRUE
;
1117 /* Set str for use with FT_GETMYMBOX. With
1118 FT_GETMYADDR, comp->c_mn will be run through
1119 FT_LS_ADDR, which will strip off any pers
1123 comp
->c_flags
&= ~CF_TRUE
;
1125 while ((sp
= getname(sp
)))
1126 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1127 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1129 comp
->c_flags
|= CF_TRUE
;
1130 /* Set str and comp->c_text for use with
1131 FT_GETMYMBOX. With FT_GETMYADDR,
1132 comp->c_mn will be run through
1133 FT_LS_ADDR, which will strip off any
1135 free (comp
->c_text
);
1136 comp
->c_text
= str
= strdup (mn
->m_text
);
1139 comp
->c_flags
|= CF_PARSED
;
1141 while (getname("")) /* XXX */
1143 if (comp
->c_text
== 0)
1144 comp
->c_flags
|= CF_TRUE
;
1146 comp
->c_flags
&= ~CF_TRUE
;
1148 comp
->c_mn
= &fmt_mnull
;
1150 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1151 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1152 /* Fool FT_LS_ADDR into not producing an address. */
1153 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1159 * Call our tracing callback function, if one was supplied
1162 if (callbacks
&& callbacks
->trace_func
)
1163 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1164 str
, charstring_buffer (scanlp
));
1168 /* Emit any trailing sequences of zero display length. */
1169 while (fmt
->f_type
!= FT_DONE
) {
1170 if (fmt
->f_type
== FT_LS_LIT
) {
1172 if (callbacks
&& callbacks
->trace_func
)
1173 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1174 str
, charstring_buffer (scanlp
));
1175 } else if (fmt
->f_type
== FT_STRLITZ
) {
1176 /* Don't want to emit part of an escape sequence. So if
1177 there isn't enough room in the buffer for the entire
1178 string, skip it completely. Need room for null
1179 terminator, and maybe trailing newline (added below). */
1181 for (sp
= str
; *sp
; ++sp
) {
1182 charstring_push_back (scanlp
, *sp
);
1185 if (callbacks
&& callbacks
->trace_func
)
1186 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1187 str
, charstring_buffer (scanlp
));
1193 if (charstring_bytes (scanlp
) > 0) {
1195 * Append a newline if the last character wasn't.
1197 #ifdef MULTIBYTE_SUPPORT
1199 * It's a little tricky because the last byte might be part of
1200 * a multibyte character, in which case we assume that wasn't
1203 size_t last_char_len
= charstring_last_char_len (scanlp
);
1204 #else /* ! MULTIBYTE_SUPPORT */
1205 size_t last_char_len
= 1;
1206 #endif /* ! MULTIBYTE_SUPPORT */
1208 if (last_char_len
> 1 ||
1209 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1210 charstring_push_back (scanlp
, '\n');