]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
cd148ed70ca2d0fe4c46371cc828700e8a893fc1
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).
13 #include "h/addrsbr.h"
14 #include "h/fmt_scan.h"
16 #include "h/fmt_compile.h"
20 #ifdef HAVE_SYS_TIME_H
21 # include <sys/time.h>
24 #ifdef MULTIBYTE_SUPPORT
29 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
35 static int match (char *, char *) PURE
;
36 static char *get_x400_friendly (char *, char *, int);
37 static int get_x400_comp (char *, char *, char *, int);
41 * test if string "sub" appears anywhere in
42 * string "str" (case insensitive).
46 match (char *str
, char *sub
)
52 c1
= tolower((unsigned char)c1
);
53 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
57 s1
= sub
+ 1; s2
= str
;
58 while ((c1
= *s1
++) &&
59 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
68 * copy a number to the destination subject to a maximum width
71 cpnumber(charstring_t dest
, int num
, int wid
, char fill
, size_t max
)
73 /* Maybe we should handle left padding at some point? */
77 wid
= -wid
; /* OK because wid originally a short. */
78 if ((size_t)wid
< (num
>= 0 ? max
: max
-1)) {
79 /* Build up the string representation of num in reverse. */
80 charstring_t rev
= charstring_create (0);
81 int i
= num
>= 0 ? num
: -num
;
84 charstring_push_back (rev
, i
% 10 + '0');
86 } while (--wid
> 0 && i
> 0);
88 /* Overflowed the field (wid). */
89 charstring_push_back (rev
, '?');
90 } else if (num
< 0 && wid
> 0) {
91 /* Shouldn't need the wid > 0 check, that's why the condition
92 at the top checks wid < max-1 when num < 0. */
95 charstring_push_back (rev
, '-');
98 while (wid
-- > 0 && fill
!= 0) {
99 charstring_push_back (rev
, fill
);
101 if (num
< 0 && fill
== '0') {
102 charstring_push_back (rev
, '-');
106 /* Output the string in reverse. */
107 size_t b
= charstring_bytes (rev
);
108 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
111 charstring_push_back (dest
, *--cp
);
115 charstring_free (rev
);
120 * copy string from str to dest padding with the fill character to a
121 * size of wid characters. if wid is negative, the string is right
122 * aligned no more than max characters are copied
125 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
)
127 int remaining
; /* remaining output width available */
129 struct charstring
*trimmed
;
130 size_t end
; /* number of input bytes remaining in str */
131 #ifdef MULTIBYTE_SUPPORT
132 int char_len
; /* bytes in current character */
137 char *sp
; /* current position in source string */
141 if ((remaining
= wid
) < 0) {
142 remaining
= -remaining
;
145 if (remaining
> (int) max
) { remaining
= max
; }
147 trimmed
= rjust
? charstring_create(remaining
) : dest
;
149 bool prevCtrl
= true;
151 #ifdef MULTIBYTE_SUPPORT
152 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
155 while (*sp
&& remaining
> 0 && end
> 0) {
156 #ifdef MULTIBYTE_SUPPORT
157 char_len
= mbtowc(&wide_char
, sp
, end
);
160 * See the relevant comments in cpstripped() to explain what's
161 * going on here; we want to handle the case where we get
162 * characters that mbtowc() cannot handle
167 char_len
= mbtowc(&wide_char
, altstr
, 1);
174 w
= wcwidth(wide_char
);
176 /* If w > remaining, w must be positive. */
183 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
188 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
189 intentionally warns if they are passed a char. */
190 c
= (unsigned char) *sp
;
191 if (iscntrl(c
) || isspace(c
)) {
195 charstring_push_back (trimmed
, ' ');
204 #ifdef MULTIBYTE_SUPPORT
205 if (w
>= 0 && remaining
>= w
) {
206 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
213 charstring_push_back (trimmed
, *sp
++);
219 while (remaining
-- > 0) {
220 charstring_push_back(dest
, fill
);
224 charstring_append(dest
, trimmed
);
225 charstring_free(trimmed
);
229 #ifdef MULTIBYTE_SUPPORT
231 cpstripped (charstring_t dest
, size_t max
, char *str
)
234 static char *oddchar
;
235 static size_t oddlen
;
236 static char *spacechar
;
237 static size_t spacelen
;
250 two
= MB_CUR_MAX
* 2; /* Varies at run-time. */
252 oddchar
= mh_xmalloc(two
);
253 oddlen
= wcstombs(oddchar
, L
"?", two
);
256 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
257 spacechar
= mh_xmalloc(two
);
258 spacelen
= wcstombs(spacechar
, L
" ", two
);
259 assert(spacelen
> 0);
263 return; /* It's unclear why no padding in this case. */
264 end
= str
+ strlen(str
);
266 if (mbtowc(NULL
, NULL
, 0))
267 {} /* Reset shift state. */
269 squash
= true; /* Trim `space' or `cntrl' from the start. */
272 return; /* It's unclear why no padding in this case. */
274 srclen
= mbtowc(&rune
, str
, end
- str
);
276 /* Invalid rune, or not enough bytes to finish it. */
280 str
++; /* Skip one byte. */
286 if (iswspace(rune
) || iswcntrl(rune
)) {
288 continue; /* Amidst a run of these. */
305 if ((size_t)w
> max
) {
306 /* No room for rune; pad. */
308 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
312 charstring_push_back_chars(dest
, src
, srclen
, w
);
318 #ifndef MULTIBYTE_SUPPORT
320 cpstripped (charstring_t dest
, size_t max
, char *str
)
328 squash
= true; /* Strip leading cases. */
330 c
= (unsigned char)*str
++;
334 if (isspace(c
) || iscntrl(c
)) {
342 charstring_push_back(dest
, (char)c
);
347 static char *lmonth
[] = { "January", "February","March", "April",
348 "May", "June", "July", "August",
349 "September","October", "November","December" };
352 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
354 char given
[BUFSIZ
], surname
[BUFSIZ
];
363 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
364 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
370 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
373 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
374 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
376 snprintf (buffer
, buffer_len
, "%s", surname
);
382 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
387 if ((idx
= stringdex (key
, mbox
)) < 0
388 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
391 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
396 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
397 struct fmt_callbacks
*callbacks
)
401 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
413 * max is the same as width, but unsigned so comparisons
414 * with charstring_chars() won't raise compile warnings.
417 savestr
= str
= NULL
;
420 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
421 switch (fmt
->f_type
) {
424 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
429 case FT_LS_DECODECOMP
:
431 * Trim these components of any newlines.
433 * But don't trim the "body" and "text" components.
438 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
439 (i
= strlen(comp
->c_text
)) > 0) {
440 if (comp
->c_text
[i
- 1] == '\n' &&
441 strcmp(comp
->c_name
, "body") != 0 &&
442 strcmp(comp
->c_name
, "text") != 0)
443 comp
->c_text
[i
- 1] = '\0';
444 comp
->c_flags
|= CF_TRIMMED
;
451 for ( ; charstring_chars (scanlp
) < max
; ) {
452 switch (fmt
->f_type
) {
455 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
456 fmt
->f_comp
->c_text
);
459 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
460 fmt
->f_fill
, max
- charstring_chars (scanlp
));
465 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
466 charstring_push_back (scanlp
, c
);
475 rjust
= true; /* XXX should do something with this */
477 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
478 charstring_push_back (scanlp
, c
);
480 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
481 charstring_push_back (scanlp
, fmt
->f_fill
);
486 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
489 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
490 max
- charstring_chars (scanlp
));
495 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
496 charstring_push_back (scanlp
, c
);
501 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
504 die("internal error (FT_STRFW)");
510 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
511 cpnumber (scanlp
, value
, wid
, ' ',
512 max
- charstring_chars (scanlp
));
519 unsigned int whole
, tenths
;
520 unsigned int scale
= 0;
521 unsigned int val
= (unsigned int)value
;
522 char *kibisuff
= NULL
;
524 switch (fmt
->f_type
) {
525 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
526 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
530 snprintf(buffer
, sizeof(buffer
), "%u", val
);
532 /* To prevent divide by 0, found by clang static
534 if (scale
== 0) { scale
= 1; }
536 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
537 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
543 strcpy(buffer
, "huge");
545 /* val is scale times too big. we want tenths */
553 tenths
= val
- (whole
* 10);
556 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
557 whole
, tenths
, *unitcp
, kibisuff
);
559 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
560 whole
, *unitcp
, kibisuff
);
568 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
569 max
- charstring_chars (scanlp
));
573 charstring_push_back (scanlp
, fmt
->f_char
);
577 if (callbacks
&& callbacks
->trace_func
)
578 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
579 str
, charstring_buffer (scanlp
));
583 if (!(value
= (str
&& *str
))) {
584 if (callbacks
&& callbacks
->trace_func
)
585 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
586 str
, charstring_buffer (scanlp
));
593 if (!(value
= (str
== NULL
|| *str
== 0))) {
594 if (callbacks
&& callbacks
->trace_func
)
595 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
596 str
, charstring_buffer (scanlp
));
603 if (value
!= fmt
->f_value
) {
604 if (callbacks
&& callbacks
->trace_func
)
605 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
606 str
, charstring_buffer (scanlp
));
613 if (value
== fmt
->f_value
) {
614 if (callbacks
&& callbacks
->trace_func
)
615 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
616 str
, charstring_buffer (scanlp
));
623 if (value
<= fmt
->f_value
) {
624 if (callbacks
&& callbacks
->trace_func
)
625 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
626 str
, charstring_buffer (scanlp
));
633 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
634 if (callbacks
&& callbacks
->trace_func
)
635 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
636 str
, charstring_buffer (scanlp
));
644 value
= match (str
, fmt
->f_text
);
650 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
651 if (callbacks
&& callbacks
->trace_func
)
652 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
653 str
, charstring_buffer (scanlp
));
660 value
= uprf (str
, fmt
->f_text
);
664 value
= (str
!= NULL
&& *str
!= 0);
668 value
= (str
== NULL
|| *str
== 0);
672 value
= (fmt
->f_value
== value
);
676 value
= (fmt
->f_value
!= value
);
680 value
= (fmt
->f_value
> value
);
684 if (callbacks
&& callbacks
->trace_func
)
685 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
686 str
, charstring_buffer (scanlp
));
694 str
= fmt
->f_comp
->c_text
;
700 if (!(str
= getenv (fmt
->f_text
)))
704 if (!(str
= context_find (fmt
->f_text
)))
708 case FT_LS_DECODECOMP
:
709 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
712 str
= fmt
->f_comp
->c_text
;
716 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
725 strncpy(buffer
, str
, sizeof(buffer
));
726 buffer
[sizeof(buffer
)-1] = '\0';
728 while (isspace((unsigned char) *str
))
731 if ((i
= fmt
->f_width
) < 0) {
736 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
739 xp
+= strlen(str
) - 1;
740 while (xp
> str
&& isspace((unsigned char) *xp
))
742 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
743 str
+= strlen(str
) - i
;
748 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
751 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
754 value
= fmt
->f_value
;
757 value
= dat
[fmt
->f_value
];
765 case FT_LV_CHAR_LEFT
:
766 value
= max
- charstring_bytes (scanlp
);
769 value
+= fmt
->f_value
;
772 value
= fmt
->f_value
- value
;
774 case FT_LV_MULTIPLY_L
:
775 value
*= fmt
->f_value
;
779 value
/= fmt
->f_value
;
785 value
%= fmt
->f_value
;
794 value
= fmt
->f_comp
->c_tws
->tw_sec
;
797 value
= fmt
->f_comp
->c_tws
->tw_min
;
800 value
= fmt
->f_comp
->c_tws
->tw_hour
;
803 value
= fmt
->f_comp
->c_tws
->tw_mday
;
806 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
809 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
812 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
815 str
= dtwszone (fmt
->f_comp
->c_tws
);
818 value
= fmt
->f_comp
->c_tws
->tw_year
;
821 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
823 value
= tws
->tw_wday
;
826 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
828 str
= tw_dotw
[tws
->tw_wday
];
831 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
833 str
= tw_ldotw
[tws
->tw_wday
];
836 value
= fmt
->f_comp
->c_tws
->tw_yday
;
839 value
= fmt
->f_comp
->c_tws
->tw_zone
;
842 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
843 value
= dmktime(fmt
->f_comp
->c_tws
);
846 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
847 value
= dmktime(fmt
->f_comp
->c_tws
);
848 value
= time(NULL
) - value
;
851 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
853 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
863 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
869 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
872 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
875 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
879 str
= fmt
->f_comp
->c_mn
->m_pers
;
882 str
= fmt
->f_comp
->c_mn
->m_mbox
;
885 str
= fmt
->f_comp
->c_mn
->m_host
;
888 str
= fmt
->f_comp
->c_mn
->m_path
;
891 str
= fmt
->f_comp
->c_mn
->m_gname
;
894 str
= fmt
->f_comp
->c_mn
->m_note
;
897 str
= adrformat( fmt
->f_comp
->c_mn
);
900 value
= fmt
->f_comp
->c_mn
->m_type
;
903 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
906 value
= fmt
->f_comp
->c_mn
->m_nohost
;
910 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
911 str
= fmt
->f_comp
->c_text
;
914 if (fmt
->f_type
== FT_LS_ADDR
)
916 if ((str
= mn
->m_pers
) == NULL
) {
917 if ((str
= mn
->m_note
)) {
919 strncpy (buffer
, str
, sizeof(buffer
));
920 buffer
[sizeof(buffer
)-1] = '\0';
924 sp
= str
+ strlen(str
) - 1;
933 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
934 buffer
, sizeof(buffer
)))) {
936 switch (mn
->m_type
) {
941 snprintf (buffer
, sizeof(buffer
), "%s!%s",
942 mn
->m_host
, mn
->m_mbox
);
947 snprintf (buffer
, sizeof(buffer
), "%s@%s",
948 mn
->m_mbox
, mn
->m_host
);
960 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
964 strncpy(buffer
, str
, sizeof(buffer
));
965 /* strncpy doesn't NUL-terminate if it fills the buffer */
966 buffer
[sizeof(buffer
)-1] = '\0';
967 unquote_string(buffer
, buffer2
);
974 if ((t
= comp
->c_tws
->tw_clock
) == 0)
975 t
= dmktime(comp
->c_tws
);
976 tws
= dlocaltime(&t
);
982 if ((t
= comp
->c_tws
->tw_clock
) == 0)
983 t
= dmktime(comp
->c_tws
);
990 if (comp
->c_flags
& CF_PARSED
)
992 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
994 comp
->c_flags
&= ~CF_TRUE
;
995 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
997 comp
->c_flags
= CF_TRUE
;
999 comp
->c_flags
|= CF_PARSED
;
1003 /* hook for custom address list formatting (see replsbr.c) */
1004 if (callbacks
&& callbacks
->formataddr
)
1005 str
= callbacks
->formataddr (savestr
, str
);
1007 str
= formataddr (savestr
, str
);
1011 /* The same as formataddr, but doesn't do duplicate suppression */
1012 if (callbacks
&& callbacks
->concataddr
)
1013 str
= callbacks
->concataddr (savestr
, str
);
1015 str
= concataddr (savestr
, str
);
1019 /* output the str register as an address component,
1020 * splitting it into multiple lines if necessary. The
1021 * value reg. contains the max line length. The lit.
1022 * field may contain a string to prepend to the result
1027 int indent
, wid
, len
;
1031 len
= str
? strlen (str
) : 0;
1033 indent
= strlen (sp
);
1036 die("putaddr -- num register (%d) must be greater "
1037 "than label width (%d)", value
, indent
);
1039 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1040 charstring_push_back (scanlp
, c
);
1043 /* try to break at a comma; failing that, break at a
1046 lastb
= 0; sp
= lp
+ wid
;
1047 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1048 if (! lastb
&& isspace(c
))
1052 if (! (sp
= lastb
)) {
1054 while (*sp
&& *sp
!= ',' &&
1055 !isspace((unsigned char) *sp
))
1062 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1063 charstring_push_back (scanlp
, *lp
++);
1065 while (isspace((unsigned char) *lp
))
1068 if (charstring_chars (scanlp
) < max
) {
1069 charstring_push_back (scanlp
, '\n');
1072 charstring_chars (scanlp
) < max
&& i
> 0;
1074 charstring_push_back (scanlp
, ' ');
1077 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1083 if (comp
->c_flags
& CF_PARSED
)
1085 if (comp
->c_mn
!= &fmt_mnull
)
1086 mnfree (comp
->c_mn
);
1087 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1088 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1092 comp
->c_flags
|= CF_PARSED
;
1094 while (getname("")) /* XXX */
1096 comp
->c_mn
= &fmt_mnull
;
1104 * if there's no component, we say true. Otherwise we
1105 * say "true" only if we can parse the address and it
1106 * matches one of our addresses.
1109 if (comp
->c_mn
!= &fmt_mnull
)
1110 mnfree (comp
->c_mn
);
1111 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1112 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1115 comp
->c_flags
|= CF_TRUE
;
1116 /* Set str for use with FT_GETMYMBOX. With
1117 FT_GETMYADDR, comp->c_mn will be run through
1118 FT_LS_ADDR, which will strip off any pers
1122 comp
->c_flags
&= ~CF_TRUE
;
1124 while ((sp
= getname(sp
)))
1125 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1126 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1128 comp
->c_flags
|= CF_TRUE
;
1129 /* Set str and comp->c_text for use with
1130 FT_GETMYMBOX. With FT_GETMYADDR,
1131 comp->c_mn will be run through
1132 FT_LS_ADDR, which will strip off any
1134 free (comp
->c_text
);
1135 comp
->c_text
= str
= strdup (mn
->m_text
);
1138 comp
->c_flags
|= CF_PARSED
;
1140 while (getname("")) /* XXX */
1142 if (comp
->c_text
== 0)
1143 comp
->c_flags
|= CF_TRUE
;
1145 comp
->c_flags
&= ~CF_TRUE
;
1147 comp
->c_mn
= &fmt_mnull
;
1149 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1150 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1151 /* Fool FT_LS_ADDR into not producing an address. */
1152 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1158 * Call our tracing callback function, if one was supplied
1161 if (callbacks
&& callbacks
->trace_func
)
1162 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1163 str
, charstring_buffer (scanlp
));
1167 /* Emit any trailing sequences of zero display length. */
1168 while (fmt
->f_type
!= FT_DONE
) {
1169 if (fmt
->f_type
== FT_LS_LIT
) {
1171 if (callbacks
&& callbacks
->trace_func
)
1172 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1173 str
, charstring_buffer (scanlp
));
1174 } else if (fmt
->f_type
== FT_STRLITZ
) {
1175 /* Don't want to emit part of an escape sequence. So if
1176 there isn't enough room in the buffer for the entire
1177 string, skip it completely. Need room for null
1178 terminator, and maybe trailing newline (added below). */
1180 for (sp
= str
; *sp
; ++sp
) {
1181 charstring_push_back (scanlp
, *sp
);
1184 if (callbacks
&& callbacks
->trace_func
)
1185 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1186 str
, charstring_buffer (scanlp
));
1192 if (charstring_bytes (scanlp
) > 0) {
1194 * Append a newline if the last character wasn't.
1196 #ifdef MULTIBYTE_SUPPORT
1198 * It's a little tricky because the last byte might be part of
1199 * a multibyte character, in which case we assume that wasn't
1202 size_t last_char_len
= charstring_last_char_len (scanlp
);
1203 #else /* ! MULTIBYTE_SUPPORT */
1204 size_t last_char_len
= 1;
1205 #endif /* ! MULTIBYTE_SUPPORT */
1207 if (last_char_len
> 1 ||
1208 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1209 charstring_push_back (scanlp
, '\n');