]>
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 *) PURE
;
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
, int wid
, char fill
, size_t max
) {
71 /* Maybe we should handle left padding at some point? */
75 wid
= -wid
; /* OK because wid originally a short. */
76 if ((size_t)wid
< (num
>= 0 ? max
: max
-1)) {
77 /* Build up the string representation of num in reverse. */
78 charstring_t rev
= charstring_create (0);
79 int i
= num
>= 0 ? num
: -num
;
82 charstring_push_back (rev
, i
% 10 + '0');
84 } while (--wid
> 0 && i
> 0);
86 /* Overflowed the field (wid). */
87 charstring_push_back (rev
, '?');
88 } else if (num
< 0 && wid
> 0) {
89 /* Shouldn't need the wid > 0 check, that's why the condition
90 at the top checks wid < max-1 when num < 0. */
93 charstring_push_back (rev
, '-');
96 while (wid
-- > 0 && fill
!= 0) {
97 charstring_push_back (rev
, fill
);
99 if (num
< 0 && fill
== '0') {
100 charstring_push_back (rev
, '-');
104 /* Output the string in reverse. */
105 size_t b
= charstring_bytes (rev
);
106 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
109 charstring_push_back (dest
, *--cp
);
113 charstring_free (rev
);
118 * copy string from str to dest padding with the fill character to a
119 * size of wid characters. if wid is negative, the string is right
120 * aligned no more than max characters are copied
123 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
) {
124 int remaining
; /* remaining output width available */
126 struct charstring
*trimmed
;
127 size_t end
; /* number of input bytes remaining in str */
128 #ifdef MULTIBYTE_SUPPORT
129 int char_len
; /* bytes in current character */
134 char *sp
; /* current position in source string */
139 if ((remaining
= wid
) < 0) {
140 remaining
= -remaining
;
143 if (remaining
> (int) max
) { remaining
= max
; }
145 trimmed
= rjust
? charstring_create(remaining
) : dest
;
148 #ifdef MULTIBYTE_SUPPORT
149 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
152 while (*sp
&& remaining
> 0 && end
> 0) {
153 #ifdef MULTIBYTE_SUPPORT
154 char_len
= mbtowc(&wide_char
, sp
, end
);
157 * See the relevant comments in cpstripped() to explain what's
158 * going on here; we want to handle the case where we get
159 * characters that mbtowc() cannot handle
164 char_len
= mbtowc(&wide_char
, altstr
, 1);
171 w
= wcwidth(wide_char
);
173 /* If w > remaining, w must be positive. */
180 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
185 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
186 intentionally warns if they are passed a char. */
187 c
= (unsigned char) *sp
;
188 if (iscntrl(c
) || isspace(c
)) {
192 charstring_push_back (trimmed
, ' ');
201 #ifdef MULTIBYTE_SUPPORT
202 if (w
>= 0 && remaining
>= w
) {
203 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
210 charstring_push_back (trimmed
, *sp
++);
216 while (remaining
-- > 0) {
217 charstring_push_back(dest
, fill
);
221 charstring_append(dest
, trimmed
);
222 charstring_free(trimmed
);
226 #ifdef MULTIBYTE_SUPPORT
228 cpstripped (charstring_t dest
, size_t max
, char *str
)
231 static char *oddchar
;
232 static size_t oddlen
;
233 static char *spacechar
;
234 static size_t spacelen
;
247 two
= MB_CUR_MAX
* 2; /* Varies at run-time. */
249 oddchar
= mh_xmalloc(two
);
250 oddlen
= wcstombs(oddchar
, L
"?", two
);
253 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
254 spacechar
= mh_xmalloc(two
);
255 spacelen
= wcstombs(spacechar
, L
" ", two
);
256 assert(spacelen
> 0);
260 return; /* It's unclear why no padding in this case. */
261 end
= str
+ strlen(str
);
263 if (mbtowc(NULL
, NULL
, 0))
264 {} /* Reset shift state. */
266 squash
= true; /* Trim `space' or `cntrl' from the start. */
269 return; /* It's unclear why no padding in this case. */
271 srclen
= mbtowc(&rune
, str
, end
- str
);
273 /* Invalid rune, or not enough bytes to finish it. */
277 str
++; /* Skip one byte. */
283 if (iswspace(rune
) || iswcntrl(rune
)) {
285 continue; /* Amidst a run of these. */
302 if ((size_t)w
> max
) {
303 /* No room for rune; pad. */
305 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
309 charstring_push_back_chars(dest
, src
, srclen
, w
);
315 #ifndef MULTIBYTE_SUPPORT
317 cpstripped (charstring_t dest
, size_t max
, char *str
)
325 squash
= true; /* Strip leading cases. */
327 c
= (unsigned char)*str
++;
331 if (isspace(c
) || iscntrl(c
)) {
339 charstring_push_back(dest
, (char)c
);
344 static char *lmonth
[] = { "January", "February","March", "April",
345 "May", "June", "July", "August",
346 "September","October", "November","December" };
349 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
351 char given
[BUFSIZ
], surname
[BUFSIZ
];
360 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
361 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
367 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
370 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
371 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
373 snprintf (buffer
, buffer_len
, "%s", surname
);
379 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
384 if ((idx
= stringdex (key
, mbox
)) < 0
385 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
388 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
393 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
394 struct fmt_callbacks
*callbacks
)
398 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
409 * max is the same as width, but unsigned so comparisons
410 * with charstring_chars() won't raise compile warnings.
413 savestr
= str
= NULL
;
416 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
417 switch (fmt
->f_type
) {
420 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
425 case FT_LS_DECODECOMP
:
427 * Trim these components of any newlines.
429 * But don't trim the "body" and "text" components.
434 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
435 (i
= strlen(comp
->c_text
)) > 0) {
436 if (comp
->c_text
[i
- 1] == '\n' &&
437 strcmp(comp
->c_name
, "body") != 0 &&
438 strcmp(comp
->c_name
, "text") != 0)
439 comp
->c_text
[i
- 1] = '\0';
440 comp
->c_flags
|= CF_TRIMMED
;
447 for ( ; charstring_chars (scanlp
) < max
; ) {
448 switch (fmt
->f_type
) {
451 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
452 fmt
->f_comp
->c_text
);
455 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
456 fmt
->f_fill
, max
- charstring_chars (scanlp
));
461 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
462 charstring_push_back (scanlp
, c
);
471 rjust
++; /* XXX should do something with this */
473 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
474 charstring_push_back (scanlp
, c
);
476 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
477 charstring_push_back (scanlp
, fmt
->f_fill
);
482 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
485 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
486 max
- charstring_chars (scanlp
));
491 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
492 charstring_push_back (scanlp
, c
);
497 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
500 adios (NULL
, "internal error (FT_STRFW)");
506 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
507 cpnumber (scanlp
, value
, wid
, ' ',
508 max
- charstring_chars (scanlp
));
515 unsigned int whole
, tenths
;
516 unsigned int scale
= 0;
517 unsigned int val
= (unsigned int)value
;
518 char *kibisuff
= NULL
;
520 switch (fmt
->f_type
) {
521 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
522 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
526 snprintf(buffer
, sizeof(buffer
), "%u", val
);
528 /* To prevent divide by 0, found by clang static
530 if (scale
== 0) { scale
= 1; }
532 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
533 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
539 strcpy(buffer
, "huge");
541 /* val is scale times too big. we want tenths */
549 tenths
= val
- (whole
* 10);
552 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
553 whole
, tenths
, *unitcp
, kibisuff
);
555 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
556 whole
, *unitcp
, kibisuff
);
564 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
565 max
- charstring_chars (scanlp
));
569 charstring_push_back (scanlp
, fmt
->f_char
);
573 if (callbacks
&& callbacks
->trace_func
)
574 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
575 str
, charstring_buffer (scanlp
));
579 if (!(value
= (str
&& *str
))) {
580 if (callbacks
&& callbacks
->trace_func
)
581 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
582 str
, charstring_buffer (scanlp
));
589 if (!(value
= (str
== NULL
|| *str
== 0))) {
590 if (callbacks
&& callbacks
->trace_func
)
591 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
592 str
, charstring_buffer (scanlp
));
599 if (value
!= fmt
->f_value
) {
600 if (callbacks
&& callbacks
->trace_func
)
601 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
602 str
, charstring_buffer (scanlp
));
609 if (value
== fmt
->f_value
) {
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
= (str
&& match (str
, fmt
->f_text
)))) {
630 if (callbacks
&& callbacks
->trace_func
)
631 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
632 str
, charstring_buffer (scanlp
));
640 value
= match (str
, fmt
->f_text
);
646 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
647 if (callbacks
&& callbacks
->trace_func
)
648 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
649 str
, charstring_buffer (scanlp
));
656 value
= uprf (str
, fmt
->f_text
);
660 value
= (str
!= NULL
&& *str
!= 0);
664 value
= (str
== NULL
|| *str
== 0);
668 value
= (fmt
->f_value
== value
);
672 value
= (fmt
->f_value
!= value
);
676 value
= (fmt
->f_value
> value
);
680 if (callbacks
&& callbacks
->trace_func
)
681 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
682 str
, charstring_buffer (scanlp
));
690 str
= fmt
->f_comp
->c_text
;
696 if (!(str
= getenv (fmt
->f_text
)))
700 if (!(str
= context_find (fmt
->f_text
)))
704 case FT_LS_DECODECOMP
:
705 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
708 str
= fmt
->f_comp
->c_text
;
712 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
721 strncpy(buffer
, str
, sizeof(buffer
));
722 buffer
[sizeof(buffer
)-1] = '\0';
724 while (isspace((unsigned char) *str
))
727 if ((i
= fmt
->f_width
) < 0) {
732 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
735 xp
+= strlen(str
) - 1;
736 while (xp
> str
&& isspace((unsigned char) *xp
))
738 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
739 str
+= strlen(str
) - i
;
744 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
747 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
750 value
= fmt
->f_value
;
753 value
= dat
[fmt
->f_value
];
761 case FT_LV_CHAR_LEFT
:
762 value
= max
- charstring_bytes (scanlp
);
765 value
+= fmt
->f_value
;
768 value
= fmt
->f_value
- value
;
770 case FT_LV_MULTIPLY_L
:
771 value
*= fmt
->f_value
;
775 value
/= fmt
->f_value
;
781 value
%= fmt
->f_value
;
790 value
= fmt
->f_comp
->c_tws
->tw_sec
;
793 value
= fmt
->f_comp
->c_tws
->tw_min
;
796 value
= fmt
->f_comp
->c_tws
->tw_hour
;
799 value
= fmt
->f_comp
->c_tws
->tw_mday
;
802 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
805 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
808 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
811 str
= dtwszone (fmt
->f_comp
->c_tws
);
814 value
= fmt
->f_comp
->c_tws
->tw_year
;
817 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
819 value
= tws
->tw_wday
;
822 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
824 str
= tw_dotw
[tws
->tw_wday
];
827 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
829 str
= tw_ldotw
[tws
->tw_wday
];
832 value
= fmt
->f_comp
->c_tws
->tw_yday
;
835 value
= fmt
->f_comp
->c_tws
->tw_zone
;
838 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
839 value
= dmktime(fmt
->f_comp
->c_tws
);
842 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
843 value
= dmktime(fmt
->f_comp
->c_tws
);
844 value
= time(NULL
) - value
;
847 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
849 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
859 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
865 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
868 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
871 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
875 str
= fmt
->f_comp
->c_mn
->m_pers
;
878 str
= fmt
->f_comp
->c_mn
->m_mbox
;
881 str
= fmt
->f_comp
->c_mn
->m_host
;
884 str
= fmt
->f_comp
->c_mn
->m_path
;
887 str
= fmt
->f_comp
->c_mn
->m_gname
;
890 str
= fmt
->f_comp
->c_mn
->m_note
;
893 str
= adrformat( fmt
->f_comp
->c_mn
);
896 value
= fmt
->f_comp
->c_mn
->m_type
;
899 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
902 value
= fmt
->f_comp
->c_mn
->m_nohost
;
906 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
907 str
= fmt
->f_comp
->c_text
;
910 if (fmt
->f_type
== FT_LS_ADDR
)
912 if ((str
= mn
->m_pers
) == NULL
) {
913 if ((str
= mn
->m_note
)) {
915 strncpy (buffer
, str
, sizeof(buffer
));
916 buffer
[sizeof(buffer
)-1] = '\0';
920 sp
= str
+ strlen(str
) - 1;
929 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
930 buffer
, sizeof(buffer
)))) {
932 switch (mn
->m_type
) {
937 snprintf (buffer
, sizeof(buffer
), "%s!%s",
938 mn
->m_host
, mn
->m_mbox
);
943 snprintf (buffer
, sizeof(buffer
), "%s@%s",
944 mn
->m_mbox
, mn
->m_host
);
956 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
960 strncpy(buffer
, str
, sizeof(buffer
));
961 /* strncpy doesn't NUL-terminate if it fills the buffer */
962 buffer
[sizeof(buffer
)-1] = '\0';
963 unquote_string(buffer
, buffer2
);
970 if ((t
= comp
->c_tws
->tw_clock
) == 0)
971 t
= dmktime(comp
->c_tws
);
972 tws
= dlocaltime(&t
);
978 if ((t
= comp
->c_tws
->tw_clock
) == 0)
979 t
= dmktime(comp
->c_tws
);
986 if (comp
->c_flags
& CF_PARSED
)
988 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
990 comp
->c_flags
&= ~CF_TRUE
;
991 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
993 comp
->c_flags
= CF_TRUE
;
995 comp
->c_flags
|= CF_PARSED
;
999 /* hook for custom address list formatting (see replsbr.c) */
1000 if (callbacks
&& callbacks
->formataddr
)
1001 str
= callbacks
->formataddr (savestr
, str
);
1003 str
= formataddr (savestr
, str
);
1007 /* The same as formataddr, but doesn't do duplicate suppression */
1008 if (callbacks
&& callbacks
->concataddr
)
1009 str
= callbacks
->concataddr (savestr
, str
);
1011 str
= concataddr (savestr
, str
);
1015 /* output the str register as an address component,
1016 * splitting it into multiple lines if necessary. The
1017 * value reg. contains the max line length. The lit.
1018 * field may contain a string to prepend to the result
1023 int indent
, wid
, len
;
1027 len
= str
? strlen (str
) : 0;
1029 indent
= strlen (sp
);
1032 adios(NULL
, "putaddr -- num register (%d) must be greater "
1033 "than label width (%d)", value
, indent
);
1035 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1036 charstring_push_back (scanlp
, c
);
1039 /* try to break at a comma; failing that, break at a
1042 lastb
= 0; sp
= lp
+ wid
;
1043 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1044 if (! lastb
&& isspace(c
))
1048 if (! (sp
= lastb
)) {
1050 while (*sp
&& *sp
!= ',' &&
1051 !isspace((unsigned char) *sp
))
1058 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1059 charstring_push_back (scanlp
, *lp
++);
1061 while (isspace((unsigned char) *lp
))
1064 if (charstring_chars (scanlp
) < max
) {
1065 charstring_push_back (scanlp
, '\n');
1068 charstring_chars (scanlp
) < max
&& i
> 0;
1070 charstring_push_back (scanlp
, ' ');
1073 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1079 if (comp
->c_flags
& CF_PARSED
)
1081 if (comp
->c_mn
!= &fmt_mnull
)
1082 mnfree (comp
->c_mn
);
1083 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1084 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1088 comp
->c_flags
|= CF_PARSED
;
1090 while (getname("")) /* XXX */
1092 comp
->c_mn
= &fmt_mnull
;
1100 * if there's no component, we say true. Otherwise we
1101 * say "true" only if we can parse the address and it
1102 * matches one of our addresses.
1105 if (comp
->c_mn
!= &fmt_mnull
)
1106 mnfree (comp
->c_mn
);
1107 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1108 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1111 comp
->c_flags
|= CF_TRUE
;
1112 /* Set str for use with FT_GETMYMBOX. With
1113 FT_GETMYADDR, comp->c_mn will be run through
1114 FT_LS_ADDR, which will strip off any pers
1118 comp
->c_flags
&= ~CF_TRUE
;
1120 while ((sp
= getname(sp
)))
1121 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1122 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1124 comp
->c_flags
|= CF_TRUE
;
1125 /* Set str and comp->c_text for use with
1126 FT_GETMYMBOX. With FT_GETMYADDR,
1127 comp->c_mn will be run through
1128 FT_LS_ADDR, which will strip off any
1130 free (comp
->c_text
);
1131 comp
->c_text
= str
= strdup (mn
->m_text
);
1134 comp
->c_flags
|= CF_PARSED
;
1136 while (getname("")) /* XXX */
1138 if (comp
->c_text
== 0)
1139 comp
->c_flags
|= CF_TRUE
;
1141 comp
->c_flags
&= ~CF_TRUE
;
1143 comp
->c_mn
= &fmt_mnull
;
1145 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1146 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1147 /* Fool FT_LS_ADDR into not producing an address. */
1148 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1154 * Call our tracing callback function, if one was supplied
1157 if (callbacks
&& callbacks
->trace_func
)
1158 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1159 str
, charstring_buffer (scanlp
));
1163 /* Emit any trailing sequences of zero display length. */
1164 while (fmt
->f_type
!= FT_DONE
) {
1165 if (fmt
->f_type
== FT_LS_LIT
) {
1167 if (callbacks
&& callbacks
->trace_func
)
1168 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1169 str
, charstring_buffer (scanlp
));
1170 } else if (fmt
->f_type
== FT_STRLITZ
) {
1171 /* Don't want to emit part of an escape sequence. So if
1172 there isn't enough room in the buffer for the entire
1173 string, skip it completely. Need room for null
1174 terminator, and maybe trailing newline (added below). */
1176 for (sp
= str
; *sp
; ++sp
) {
1177 charstring_push_back (scanlp
, *sp
);
1180 if (callbacks
&& callbacks
->trace_func
)
1181 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1182 str
, charstring_buffer (scanlp
));
1188 if (charstring_bytes (scanlp
) > 0) {
1190 * Append a newline if the last character wasn't.
1192 #ifdef MULTIBYTE_SUPPORT
1194 * It's a little tricky because the last byte might be part of
1195 * a multibyte character, in which case we assume that wasn't
1198 size_t last_char_len
= charstring_last_char_len (scanlp
);
1199 #else /* ! MULTIBYTE_SUPPORT */
1200 size_t last_char_len
= 1;
1201 #endif /* ! MULTIBYTE_SUPPORT */
1203 if (last_char_len
> 1 ||
1204 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1205 charstring_push_back (scanlp
, '\n');