]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
3 * fmt_scan.c -- format string interpretation
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
9 * This is the engine that processes the format instructions created by
10 * fmt_compile (found in fmt_compile.c).
14 #include <h/addrsbr.h>
15 #include <h/fmt_scan.h>
17 #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 *);
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
, unsigned int wid
, char fill
, size_t max
) {
72 if (wid
< (num
>= 0 ? max
: max
-1)) {
73 /* Build up the string representation of num in reverse. */
74 charstring_t rev
= charstring_create (0);
75 int i
= num
>= 0 ? num
: -num
;
78 charstring_push_back (rev
, i
% 10 + '0');
80 } while (--wid
> 0 && i
> 0);
82 /* Overflowed the field (wid). */
83 charstring_push_back (rev
, '?');
84 } else if (num
< 0 && wid
> 0) {
85 /* Shouldn't need the wid > 0 check, that's why the condition
86 at the top checks wid < max-1 when num < 0. */
89 charstring_push_back (rev
, '-');
92 while (wid
-- > 0 && fill
!= 0) {
93 charstring_push_back (rev
, fill
);
95 if (num
< 0 && fill
== '0') {
96 charstring_push_back (rev
, '-');
100 /* Output the string in reverse. */
101 size_t b
= charstring_bytes (rev
);
102 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
105 charstring_push_back (dest
, *--cp
);
109 charstring_free (rev
);
114 * copy string from str to dest padding with the fill character to a
115 * size of wid characters. if wid is negative, the string is right
116 * aligned no more than max characters are copied
119 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
) {
120 int remaining
; /* remaining output width available */
122 size_t end
; /* number of input bytes remaining in str */
123 #ifdef MULTIBYTE_SUPPORT
124 int char_len
; /* bytes in current character */
129 char *sp
; /* current position in source string */
134 if ((remaining
= wid
) < 0) {
135 remaining
= -remaining
;
138 if (remaining
> (int) max
) { remaining
= max
; }
141 #ifdef MULTIBYTE_SUPPORT
142 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
145 while (*sp
&& remaining
> 0 && end
> 0) {
146 #ifdef MULTIBYTE_SUPPORT
147 char_len
= mbtowc(&wide_char
, sp
, end
);
150 * See the relevant comments in cpstripped() to explain what's
151 * going on here; we want to handle the case where we get
152 * characters that mbtowc() cannot handle
157 char_len
= mbtowc(&wide_char
, altstr
, 1);
164 w
= wcwidth(wide_char
);
166 /* If w > remaining, w must be positive. */
173 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
178 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
179 intentionally warns if they are passed a char. */
180 c
= (unsigned char) *sp
;
181 if (iscntrl(c
) || isspace(c
)) {
185 charstring_push_back (dest
, ' ');
194 #ifdef MULTIBYTE_SUPPORT
195 if (w
>= 0 && remaining
>= w
) {
196 charstring_push_back_chars (dest
, altstr
? altstr
: sp
,
203 charstring_push_back (dest
, *sp
++);
211 /* copy string to the right */
212 charstring_t copy
= charstring_copy (dest
);
214 /* add padding at the beginning */
215 charstring_clear (dest
);
216 for (; remaining
> 0; --remaining
) {
217 charstring_push_back (dest
, fill
);
220 charstring_append (dest
, copy
);
222 charstring_free (copy
);
225 /* pad remaining space */
226 while (remaining
-- > 0) {
227 charstring_push_back (dest
, fill
);
233 cpstripped (charstring_t dest
, size_t max
, char *str
)
235 int prevCtrl
= 1; /* This is 1 so we strip out leading spaces */
237 #ifdef MULTIBYTE_SUPPORT
241 #endif /* MULTIBYTE_SUPPORT */
249 #ifdef MULTIBYTE_SUPPORT
250 if (mbtowc(NULL
, NULL
, 0)) {} /* Reset shift state */
251 #endif /* MULTIBYTE_SUPPORT */
254 * Process each character at a time; if we have multibyte support
255 * then deal with that here.
258 while (*str
!= '\0' && len
> 0 && max
> 0) {
259 #ifdef MULTIBYTE_SUPPORT
260 char_len
= mbtowc(&wide_char
, str
, len
);
261 w
= wcwidth(wide_char
);
264 * If mbrtowc() failed, then we have a character that isn't valid
265 * in the current encoding. Replace it with a '?'. We do that by
266 * setting the alstr variable to the value of the replacement string;
267 * altstr is used below when the bytes are copied into the output
273 char_len
= mbtowc(&wide_char
, altstr
, 1);
282 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
284 #else /* MULTIBYTE_SUPPORT */
285 int c
= (unsigned char) *str
;
287 if (iscntrl(c
) || isspace(c
)) {
289 #endif /* MULTIBYTE_SUPPORT */
291 charstring_push_back (dest
, ' ');
301 #ifdef MULTIBYTE_SUPPORT
302 charstring_push_back_chars (dest
, altstr
? altstr
: str
, char_len
, w
);
306 #else /* MULTIBYE_SUPPORT */
307 charstring_push_back (dest
, *str
++);
309 #endif /* MULTIBYTE_SUPPORT */
313 static char *lmonth
[] = { "January", "February","March", "April",
314 "May", "June", "July", "August",
315 "September","October", "November","December" };
318 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
320 char given
[BUFSIZ
], surname
[BUFSIZ
];
329 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
330 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
336 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
339 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
340 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
342 snprintf (buffer
, buffer_len
, "%s", surname
);
348 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
353 if ((idx
= stringdex (key
, mbox
)) < 0
354 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
357 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
362 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
363 struct fmt_callbacks
*callbacks
)
367 char buffer
[BUFSIZ
], buffer2
[BUFSIZ
];
378 * max is the same as width, but unsigned so comparisons
379 * with charstring_chars() won't raise compile warnings.
382 savestr
= str
= NULL
;
385 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
386 switch (fmt
->f_type
) {
389 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
394 case FT_LS_DECODECOMP
:
396 * Trim these components of any newlines.
398 * But don't trim the "body" and "text" components.
403 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
404 (i
= strlen(comp
->c_text
)) > 0) {
405 if (comp
->c_text
[i
- 1] == '\n' &&
406 strcmp(comp
->c_name
, "body") != 0 &&
407 strcmp(comp
->c_name
, "text") != 0)
408 comp
->c_text
[i
- 1] = '\0';
409 comp
->c_flags
|= CF_TRIMMED
;
416 for ( ; charstring_chars (scanlp
) < max
; ) {
417 switch (fmt
->f_type
) {
420 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
421 fmt
->f_comp
->c_text
);
424 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
425 fmt
->f_fill
, max
- charstring_chars (scanlp
));
430 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
431 charstring_push_back (scanlp
, c
);
440 rjust
++; /* XXX should do something with this */
442 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
443 charstring_push_back (scanlp
, c
);
445 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
446 charstring_push_back (scanlp
, fmt
->f_fill
);
451 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
454 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
455 max
- charstring_chars (scanlp
));
460 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
461 charstring_push_back (scanlp
, c
);
466 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
469 adios (NULL
, "internal error (FT_STRFW)");
475 for (wid
= num
<= 0 ? 1 : 0; num
; ++wid
, num
/= 10) {}
476 cpnumber (scanlp
, value
, wid
, ' ',
477 max
- charstring_chars (scanlp
));
484 unsigned int whole
, tenths
;
485 unsigned int scale
= 0;
486 unsigned int val
= (unsigned int)value
;
487 char *kibisuff
= NULL
;
489 switch (fmt
->f_type
) {
490 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
491 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
495 snprintf(buffer
, sizeof(buffer
), "%u", val
);
497 /* To prevent divide by 0, found by clang static
499 if (scale
== 0) { scale
= 1; }
501 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
502 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
508 strcpy(buffer
, "huge");
510 /* val is scale times too big. we want tenths */
518 tenths
= val
- (whole
* 10);
521 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
522 whole
, tenths
, *unitcp
, kibisuff
);
524 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
525 whole
, *unitcp
, kibisuff
);
533 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
534 max
- charstring_chars (scanlp
));
538 charstring_push_back (scanlp
, fmt
->f_char
);
542 if (callbacks
&& callbacks
->trace_func
)
543 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
544 str
, charstring_buffer (scanlp
));
548 if (!(value
= (str
&& *str
))) {
549 if (callbacks
&& callbacks
->trace_func
)
550 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
551 str
, charstring_buffer (scanlp
));
558 if (!(value
= (str
== NULL
|| *str
== 0))) {
559 if (callbacks
&& callbacks
->trace_func
)
560 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
561 str
, charstring_buffer (scanlp
));
568 if (value
!= fmt
->f_value
) {
569 if (callbacks
&& callbacks
->trace_func
)
570 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
571 str
, charstring_buffer (scanlp
));
578 if (value
== fmt
->f_value
) {
579 if (callbacks
&& callbacks
->trace_func
)
580 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
581 str
, charstring_buffer (scanlp
));
588 if (value
<= fmt
->f_value
) {
589 if (callbacks
&& callbacks
->trace_func
)
590 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
591 str
, charstring_buffer (scanlp
));
598 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
599 if (callbacks
&& callbacks
->trace_func
)
600 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
601 str
, charstring_buffer (scanlp
));
609 value
= match (str
, fmt
->f_text
);
615 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
616 if (callbacks
&& callbacks
->trace_func
)
617 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
618 str
, charstring_buffer (scanlp
));
625 value
= uprf (str
, fmt
->f_text
);
629 value
= (str
!= NULL
&& *str
!= 0);
633 value
= (str
== NULL
|| *str
== 0);
637 value
= (fmt
->f_value
== value
);
641 value
= (fmt
->f_value
!= value
);
645 value
= (fmt
->f_value
> value
);
649 if (callbacks
&& callbacks
->trace_func
)
650 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
651 str
, charstring_buffer (scanlp
));
659 str
= fmt
->f_comp
->c_text
;
665 if (!(str
= getenv (fmt
->f_text
)))
669 if (!(str
= context_find (fmt
->f_text
)))
673 case FT_LS_DECODECOMP
:
674 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
677 str
= fmt
->f_comp
->c_text
;
681 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
690 strncpy(buffer
, str
, sizeof(buffer
));
691 buffer
[sizeof(buffer
)-1] = '\0';
693 while (isspace((unsigned char) *str
))
696 if ((i
= fmt
->f_width
) < 0) {
701 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
704 xp
+= strlen(str
) - 1;
705 while (xp
> str
&& isspace((unsigned char) *xp
))
707 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
708 str
+= strlen(str
) - i
;
713 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
716 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
719 value
= fmt
->f_value
;
722 value
= dat
[fmt
->f_value
];
730 case FT_LV_CHAR_LEFT
:
731 value
= max
- charstring_bytes (scanlp
);
734 value
+= fmt
->f_value
;
737 value
= fmt
->f_value
- value
;
739 case FT_LV_MULTIPLY_L
:
740 value
*= fmt
->f_value
;
744 value
= value
/ fmt
->f_value
;
750 value
= value
% fmt
->f_value
;
759 value
= fmt
->f_comp
->c_tws
->tw_sec
;
762 value
= fmt
->f_comp
->c_tws
->tw_min
;
765 value
= fmt
->f_comp
->c_tws
->tw_hour
;
768 value
= fmt
->f_comp
->c_tws
->tw_mday
;
771 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
774 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
777 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
780 str
= dtwszone (fmt
->f_comp
->c_tws
);
783 value
= fmt
->f_comp
->c_tws
->tw_year
;
786 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
788 value
= tws
->tw_wday
;
791 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
793 str
= tw_dotw
[tws
->tw_wday
];
796 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
798 str
= tw_ldotw
[tws
->tw_wday
];
801 value
= fmt
->f_comp
->c_tws
->tw_yday
;
804 value
= fmt
->f_comp
->c_tws
->tw_zone
;
807 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
808 value
= dmktime(fmt
->f_comp
->c_tws
);
811 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
812 value
= dmktime(fmt
->f_comp
->c_tws
);
813 value
= time((time_t *) 0) - value
;
816 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
818 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
828 if ((fmt
->f_comp
->c_tws
->tw_flags
& TW_SZONE
) == TW_SZEXP
)
834 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
837 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
840 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
844 str
= fmt
->f_comp
->c_mn
->m_pers
;
847 str
= fmt
->f_comp
->c_mn
->m_mbox
;
850 str
= fmt
->f_comp
->c_mn
->m_host
;
853 str
= fmt
->f_comp
->c_mn
->m_path
;
856 str
= fmt
->f_comp
->c_mn
->m_gname
;
859 str
= fmt
->f_comp
->c_mn
->m_note
;
862 str
= adrformat( fmt
->f_comp
->c_mn
);
865 value
= fmt
->f_comp
->c_mn
->m_type
;
868 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
871 value
= fmt
->f_comp
->c_mn
->m_nohost
;
875 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
876 str
= fmt
->f_comp
->c_text
;
879 if (fmt
->f_type
== FT_LS_ADDR
)
881 if ((str
= mn
->m_pers
) == NULL
) {
882 if ((str
= mn
->m_note
)) {
884 strncpy (buffer
, str
, sizeof(buffer
));
885 buffer
[sizeof(buffer
)-1] = '\0';
889 sp
= str
+ strlen(str
) - 1;
898 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
899 buffer
, sizeof(buffer
)))) {
901 switch (mn
->m_type
) {
906 snprintf (buffer
, sizeof(buffer
), "%s!%s",
907 mn
->m_host
, mn
->m_mbox
);
912 snprintf (buffer
, sizeof(buffer
), "%s@%s",
913 mn
->m_mbox
, mn
->m_host
);
925 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
929 strncpy(buffer
, str
, sizeof(buffer
));
930 /* strncpy doesn't NUL-terminate if it fills the buffer */
931 buffer
[sizeof(buffer
)-1] = '\0';
932 unquote_string(buffer
, buffer2
);
939 if ((t
= comp
->c_tws
->tw_clock
) == 0)
940 t
= dmktime(comp
->c_tws
);
941 tws
= dlocaltime(&t
);
947 if ((t
= comp
->c_tws
->tw_clock
) == 0)
948 t
= dmktime(comp
->c_tws
);
955 if (comp
->c_flags
& CF_PARSED
)
957 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
959 comp
->c_flags
&= ~CF_TRUE
;
960 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
961 memset (comp
->c_tws
, 0, sizeof *comp
->c_tws
);
962 comp
->c_flags
= CF_TRUE
;
964 comp
->c_flags
|= CF_PARSED
;
968 /* hook for custom address list formatting (see replsbr.c) */
969 if (callbacks
&& callbacks
->formataddr
)
970 str
= callbacks
->formataddr (savestr
, str
);
972 str
= formataddr (savestr
, str
);
976 /* The same as formataddr, but doesn't do duplicate suppression */
977 if (callbacks
&& callbacks
->concataddr
)
978 str
= callbacks
->concataddr (savestr
, str
);
980 str
= concataddr (savestr
, str
);
984 /* output the str register as an address component,
985 * splitting it into multiple lines if necessary. The
986 * value reg. contains the max line length. The lit.
987 * field may contain a string to prepend to the result
992 int indent
, wid
, len
;
996 len
= str
? strlen (str
) : 0;
998 indent
= strlen (sp
);
1001 adios(NULL
, "putaddr -- num register (%d) must be greater "
1002 "than label width (%d)", value
, indent
);
1004 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1005 charstring_push_back (scanlp
, c
);
1008 /* try to break at a comma; failing that, break at a
1011 lastb
= 0; sp
= lp
+ wid
;
1012 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1013 if (! lastb
&& isspace(c
))
1017 if (! (sp
= lastb
)) {
1019 while (*sp
&& *sp
!= ',' &&
1020 !isspace((unsigned char) *sp
))
1027 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1028 charstring_push_back (scanlp
, *lp
++);
1030 while (isspace((unsigned char) *lp
))
1033 if (charstring_chars (scanlp
) < max
) {
1034 charstring_push_back (scanlp
, '\n');
1037 charstring_chars (scanlp
) < max
&& i
> 0;
1039 charstring_push_back (scanlp
, ' ');
1042 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1048 if (comp
->c_flags
& CF_PARSED
)
1050 if (comp
->c_mn
!= &fmt_mnull
)
1051 mnfree (comp
->c_mn
);
1052 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1053 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1057 comp
->c_flags
|= CF_PARSED
;
1059 while (getname("")) /* XXX */
1061 comp
->c_mn
= &fmt_mnull
;
1069 * if there's no component, we say true. Otherwise we
1070 * say "true" only if we can parse the address and it
1071 * matches one of our addresses.
1074 if (comp
->c_mn
!= &fmt_mnull
)
1075 mnfree (comp
->c_mn
);
1076 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1077 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1080 comp
->c_flags
|= CF_TRUE
;
1081 /* Set str for use with FT_GETMYMBOX. With
1082 FT_GETMYADDR, comp->c_mn will be run through
1083 FT_LS_ADDR, which will strip off any pers
1087 comp
->c_flags
&= ~CF_TRUE
;
1089 while ((sp
= getname(sp
)))
1090 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1091 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1093 comp
->c_flags
|= CF_TRUE
;
1094 /* Set str and comp->c_text for use with
1095 FT_GETMYMBOX. With FT_GETMYADDR,
1096 comp->c_mn will be run through
1097 FT_LS_ADDR, which will strip off any
1099 free (comp
->c_text
);
1100 comp
->c_text
= str
= strdup (mn
->m_text
);
1103 comp
->c_flags
|= CF_PARSED
;
1105 while (getname("")) /* XXX */
1107 if (comp
->c_text
== 0)
1108 comp
->c_flags
|= CF_TRUE
;
1110 comp
->c_flags
&= ~CF_TRUE
;
1112 comp
->c_mn
= &fmt_mnull
;
1114 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1115 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1116 /* Fool FT_LS_ADDR into not producing an address. */
1117 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1123 * Call our tracing callback function, if one was supplied
1126 if (callbacks
&& callbacks
->trace_func
)
1127 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1128 str
, charstring_buffer (scanlp
));
1132 /* Emit any trailing sequences of zero display length. */
1133 while (fmt
->f_type
!= FT_DONE
) {
1134 if (fmt
->f_type
== FT_LS_LIT
) {
1136 if (callbacks
&& callbacks
->trace_func
)
1137 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1138 str
, charstring_buffer (scanlp
));
1139 } else if (fmt
->f_type
== FT_STRLITZ
) {
1140 /* Don't want to emit part of an escape sequence. So if
1141 there isn't enough room in the buffer for the entire
1142 string, skip it completely. Need room for null
1143 terminator, and maybe trailing newline (added below). */
1145 for (sp
= str
; *sp
; ++sp
) {
1146 charstring_push_back (scanlp
, *sp
);
1149 if (callbacks
&& callbacks
->trace_func
)
1150 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1151 str
, charstring_buffer (scanlp
));
1157 if (charstring_bytes (scanlp
) > 0) {
1159 * Append a newline if the last character wasn't.
1161 #ifdef MULTIBYTE_SUPPORT
1163 * It's a little tricky because the last byte might be part of
1164 * a multibyte character, in which case we assume that wasn't
1167 size_t last_char_len
= charstring_last_char_len (scanlp
);
1168 #else /* ! MULTIBYTE_SUPPORT */
1169 size_t last_char_len
= 1;
1170 #endif /* ! MULTIBYTE_SUPPORT */
1172 if (last_char_len
> 1 ||
1173 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1174 charstring_push_back (scanlp
, '\n');