]>
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
= (isascii((unsigned char) c1
) && isalpha((unsigned char) c1
) &&
53 isupper((unsigned char) c1
)) ? tolower((unsigned char) c1
) : c1
;
54 while ((c2
= *str
++) && c1
!= ((isascii((unsigned char) c2
) &&
55 isalpha((unsigned char) c2
) &&
56 isupper((unsigned char) c2
)) ?
57 tolower((unsigned char) c2
) : c2
))
61 s1
= sub
+ 1; s2
= str
;
62 while ((c1
= *s1
++) && ((isascii((unsigned char) c1
) &&
63 isalpha((unsigned char) c1
) &&
64 isupper((unsigned char) c1
)) ?
66 ((isascii((unsigned char) (c2
=*s2
++)) &&
67 isalpha((unsigned char) c2
) &&
68 isupper((unsigned char) c2
)) ?
69 tolower((unsigned char) c2
) : c2
))
78 * copy a number to the destination subject to a maximum width
81 cpnumber(charstring_t dest
, int num
, unsigned int wid
, char fill
, size_t max
) {
82 if (wid
< (num
>= 0 ? max
: max
-1)) {
83 /* Build up the string representation of num in reverse. */
84 charstring_t rev
= charstring_create (0);
85 int i
= num
>= 0 ? num
: -num
;
88 charstring_push_back (rev
, i
% 10 + '0');
90 } while (--wid
> 0 && i
> 0);
92 /* Overflowed the field (wid). */
93 charstring_push_back (rev
, '?');
94 } else if (num
< 0 && wid
> 0) {
95 /* Shouldn't need the wid > 0 check, that's why the condition
96 at the top checks wid < max-1 when num < 0. */
97 charstring_push_back (rev
, '-');
100 while (wid
-- > 0 && fill
!= 0) {
101 charstring_push_back (rev
, fill
);
105 /* Output the string in reverse. */
106 size_t b
= charstring_bytes (rev
);
107 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
110 charstring_push_back (dest
, *--cp
);
114 charstring_free (rev
);
119 * copy string from str to dest padding with the fill character to a
120 * size of wid characters. if wid is negative, the string is right
121 * aligned no more than max characters are copied
124 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
) {
125 int remaining
; /* remaining output width available */
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
; }
146 #ifdef MULTIBYTE_SUPPORT
147 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
150 while (*sp
&& remaining
> 0 && end
> 0) {
151 #ifdef MULTIBYTE_SUPPORT
152 char_len
= mbtowc(&wide_char
, sp
, end
);
155 * See the relevant comments in cpstripped() to explain what's
156 * going on here; we want to handle the case where we get
157 * characters that mbtowc() cannot handle
162 char_len
= mbtowc(&wide_char
, altstr
, 1);
169 w
= wcwidth(wide_char
);
171 /* If w > remaining, w must be positive. */
178 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
183 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
184 intentionally warns if they are passed a char. */
185 c
= (unsigned char) *sp
;
186 if (iscntrl(c
) || isspace(c
)) {
190 charstring_push_back (dest
, ' ');
199 #ifdef MULTIBYTE_SUPPORT
200 if (w
>= 0 && remaining
>= w
) {
201 charstring_push_back_chars (dest
, altstr
? altstr
: sp
,
208 charstring_push_back (dest
, *sp
++);
216 /* copy string to the right */
217 charstring_t copy
= charstring_copy (dest
);
219 /* add padding at the beginning */
220 charstring_clear (dest
);
221 for (; remaining
> 0; --remaining
) {
222 charstring_push_back (dest
, fill
);
225 charstring_append (dest
, copy
);
227 charstring_free (copy
);
230 /* pad remaining space */
231 while (remaining
-- > 0) {
232 charstring_push_back (dest
, fill
);
238 cpstripped (charstring_t dest
, size_t max
, char *str
)
240 int prevCtrl
= 1; /* This is 1 so we strip out leading spaces */
242 #ifdef MULTIBYTE_SUPPORT
246 #endif /* MULTIBYTE_SUPPORT */
254 #ifdef MULTIBYTE_SUPPORT
255 if (mbtowc(NULL
, NULL
, 0)) {} /* Reset shift state */
256 #endif /* MULTIBYTE_SUPPORT */
259 * Process each character at a time; if we have multibyte support
260 * then deal with that here.
263 while (*str
!= '\0' && len
> 0 && max
> 0) {
264 #ifdef MULTIBYTE_SUPPORT
265 char_len
= mbtowc(&wide_char
, str
, len
);
266 w
= wcwidth(wide_char
);
269 * If mbrtowc() failed, then we have a character that isn't valid
270 * in the current encoding. Replace it with a '?'. We do that by
271 * setting the alstr variable to the value of the replacement string;
272 * altstr is used below when the bytes are copied into the output
278 char_len
= mbtowc(&wide_char
, altstr
, 1);
287 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
289 #else /* MULTIBYTE_SUPPORT */
290 int c
= (unsigned char) *str
;
292 if (iscntrl(c
) || isspace(c
)) {
294 #endif /* MULTIBYTE_SUPPORT */
296 charstring_push_back (dest
, ' ');
306 #ifdef MULTIBYTE_SUPPORT
307 charstring_push_back_chars (dest
, altstr
? altstr
: str
, char_len
, w
);
311 #else /* MULTIBYE_SUPPORT */
312 charstring_push_back (dest
, *str
++);
314 #endif /* MULTIBYTE_SUPPORT */
318 static char *lmonth
[] = { "January", "February","March", "April",
319 "May", "June", "July", "August",
320 "September","October", "November","December" };
323 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
325 char given
[BUFSIZ
], surname
[BUFSIZ
];
334 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
335 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
341 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
344 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
345 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
347 snprintf (buffer
, buffer_len
, "%s", surname
);
353 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
358 if ((idx
= stringdex (key
, mbox
)) < 0
359 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
362 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
367 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
368 struct fmt_callbacks
*callbacks
)
372 char buffer
[BUFSIZ
], buffer2
[BUFSIZ
];
383 * max is the same as width, but unsigned so comparisons
384 * with charstring_chars() won't raise compile warnings.
387 savestr
= str
= NULL
;
390 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
391 switch (fmt
->f_type
) {
394 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
399 case FT_LS_DECODECOMP
:
401 * Trim these components of any newlines.
403 * But don't trim the "body" and "text" components.
408 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
409 (i
= strlen(comp
->c_text
)) > 0) {
410 if (comp
->c_text
[i
- 1] == '\n' &&
411 strcmp(comp
->c_name
, "body") != 0 &&
412 strcmp(comp
->c_name
, "text") != 0)
413 comp
->c_text
[i
- 1] = '\0';
414 comp
->c_flags
|= CF_TRIMMED
;
421 for ( ; charstring_chars (scanlp
) < max
; ) {
422 switch (fmt
->f_type
) {
425 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
426 fmt
->f_comp
->c_text
);
429 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
430 fmt
->f_fill
, max
- charstring_chars (scanlp
));
435 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
436 charstring_push_back (scanlp
, c
);
445 rjust
++; /* XXX should do something with this */
447 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
448 charstring_push_back (scanlp
, c
);
450 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
451 charstring_push_back (scanlp
, fmt
->f_fill
);
456 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
459 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
460 max
- charstring_chars (scanlp
));
465 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
466 charstring_push_back (scanlp
, c
);
471 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
474 adios (NULL
, "internal error (FT_STRFW)");
480 for (wid
= num
<= 0 ? 1 : 0; num
; ++wid
, num
/= 10) {}
481 cpnumber (scanlp
, value
, wid
, ' ',
482 max
- charstring_chars (scanlp
));
489 unsigned int whole
, tenths
;
490 unsigned int scale
= 0;
491 unsigned int val
= (unsigned int)value
;
492 char *kibisuff
= NULL
;
494 switch (fmt
->f_type
) {
495 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
496 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
500 snprintf(buffer
, sizeof(buffer
), "%u", val
);
502 /* To prevent divide by 0, found by clang static
504 if (scale
== 0) { scale
= 1; }
506 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
507 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
513 strcpy(buffer
, "huge");
515 /* val is scale times too big. we want tenths */
523 tenths
= val
- (whole
* 10);
526 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
527 whole
, tenths
, *unitcp
, kibisuff
);
529 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
530 whole
, *unitcp
, kibisuff
);
538 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
539 max
- charstring_chars (scanlp
));
543 charstring_push_back (scanlp
, fmt
->f_char
);
547 if (callbacks
&& callbacks
->trace_func
)
548 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
549 str
, charstring_buffer (scanlp
));
553 if (!(value
= (str
&& *str
))) {
554 if (callbacks
&& callbacks
->trace_func
)
555 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
556 str
, charstring_buffer (scanlp
));
563 if (!(value
= (str
== NULL
|| *str
== 0))) {
564 if (callbacks
&& callbacks
->trace_func
)
565 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
566 str
, charstring_buffer (scanlp
));
573 if (value
!= fmt
->f_value
) {
574 if (callbacks
&& callbacks
->trace_func
)
575 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
576 str
, charstring_buffer (scanlp
));
583 if (value
== fmt
->f_value
) {
584 if (callbacks
&& callbacks
->trace_func
)
585 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
586 str
, charstring_buffer (scanlp
));
593 if (value
<= fmt
->f_value
) {
594 if (callbacks
&& callbacks
->trace_func
)
595 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
596 str
, charstring_buffer (scanlp
));
603 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
604 if (callbacks
&& callbacks
->trace_func
)
605 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
606 str
, charstring_buffer (scanlp
));
614 value
= match (str
, fmt
->f_text
);
620 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
621 if (callbacks
&& callbacks
->trace_func
)
622 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
623 str
, charstring_buffer (scanlp
));
630 value
= uprf (str
, fmt
->f_text
);
634 value
= (str
!= NULL
&& *str
!= 0);
638 value
= (str
== NULL
|| *str
== 0);
642 value
= (fmt
->f_value
== value
);
646 value
= (fmt
->f_value
!= value
);
650 value
= (fmt
->f_value
> value
);
654 if (callbacks
&& callbacks
->trace_func
)
655 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
656 str
, charstring_buffer (scanlp
));
664 str
= fmt
->f_comp
->c_text
;
670 if (!(str
= getenv (fmt
->f_text
)))
674 if (!(str
= context_find (fmt
->f_text
)))
678 case FT_LS_DECODECOMP
:
679 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
682 str
= fmt
->f_comp
->c_text
;
686 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
694 strncpy(buffer
, str
, sizeof(buffer
));
695 buffer
[sizeof(buffer
)-1] = '\0';
697 while (isspace((unsigned char) *str
))
700 if ((i
= fmt
->f_width
) < 0) {
705 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
708 xp
+= strlen(str
) - 1;
709 while (xp
> str
&& isspace((unsigned char) *xp
))
711 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
712 str
+= strlen(str
) - i
;
717 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
720 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
723 value
= fmt
->f_value
;
726 value
= dat
[fmt
->f_value
];
734 case FT_LV_CHAR_LEFT
:
735 value
= max
- charstring_bytes (scanlp
);
738 value
+= fmt
->f_value
;
741 value
= fmt
->f_value
- value
;
745 value
= value
/ fmt
->f_value
;
751 value
= value
% fmt
->f_value
;
760 value
= fmt
->f_comp
->c_tws
->tw_sec
;
763 value
= fmt
->f_comp
->c_tws
->tw_min
;
766 value
= fmt
->f_comp
->c_tws
->tw_hour
;
769 value
= fmt
->f_comp
->c_tws
->tw_mday
;
772 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
775 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
778 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
781 str
= dtwszone (fmt
->f_comp
->c_tws
);
784 value
= fmt
->f_comp
->c_tws
->tw_year
;
787 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
789 value
= tws
->tw_wday
;
792 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
794 str
= tw_dotw
[tws
->tw_wday
];
797 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
799 str
= tw_ldotw
[tws
->tw_wday
];
802 value
= fmt
->f_comp
->c_tws
->tw_yday
;
805 value
= fmt
->f_comp
->c_tws
->tw_zone
;
808 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
809 value
= dmktime(fmt
->f_comp
->c_tws
);
812 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
813 value
= dmktime(fmt
->f_comp
->c_tws
);
814 value
= time((time_t *) 0) - value
;
817 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
819 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
829 if ((fmt
->f_comp
->c_tws
->tw_flags
& TW_SZONE
) == TW_SZEXP
)
835 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
838 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
841 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
845 str
= fmt
->f_comp
->c_mn
->m_pers
;
848 str
= fmt
->f_comp
->c_mn
->m_mbox
;
851 str
= fmt
->f_comp
->c_mn
->m_host
;
854 str
= fmt
->f_comp
->c_mn
->m_path
;
857 str
= fmt
->f_comp
->c_mn
->m_gname
;
860 str
= fmt
->f_comp
->c_mn
->m_note
;
863 str
= adrformat( fmt
->f_comp
->c_mn
);
866 value
= fmt
->f_comp
->c_mn
->m_type
;
869 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
872 value
= fmt
->f_comp
->c_mn
->m_nohost
;
876 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
877 str
= fmt
->f_comp
->c_text
;
880 if (fmt
->f_type
== FT_LS_ADDR
)
882 if ((str
= mn
->m_pers
) == NULL
) {
883 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 */
928 strncpy(buffer
, str
, sizeof(buffer
));
929 /* strncpy doesn't NUL-terminate if it fills the buffer */
930 buffer
[sizeof(buffer
)-1] = '\0';
931 unquote_string(buffer
, buffer2
);
938 if ((t
= comp
->c_tws
->tw_clock
) == 0)
939 t
= dmktime(comp
->c_tws
);
940 tws
= dlocaltime(&t
);
946 if ((t
= comp
->c_tws
->tw_clock
) == 0)
947 t
= dmktime(comp
->c_tws
);
954 if (comp
->c_flags
& CF_PARSED
)
956 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
958 comp
->c_flags
&= ~CF_TRUE
;
959 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
960 memset (comp
->c_tws
, 0, sizeof *comp
->c_tws
);
961 comp
->c_flags
= CF_TRUE
;
963 comp
->c_flags
|= CF_PARSED
;
967 /* hook for custom address list formatting (see replsbr.c) */
968 if (callbacks
&& callbacks
->formataddr
)
969 str
= callbacks
->formataddr (savestr
, str
);
971 str
= formataddr (savestr
, str
);
975 /* The same as formataddr, but doesn't do duplicate suppression */
976 if (callbacks
&& callbacks
->concataddr
)
977 str
= callbacks
->concataddr (savestr
, str
);
979 str
= concataddr (savestr
, str
);
983 /* output the str register as an address component,
984 * splitting it into multiple lines if necessary. The
985 * value reg. contains the max line length. The lit.
986 * field may contain a string to prepend to the result
991 int indent
, wid
, len
;
995 len
= str
? strlen (str
) : 0;
997 indent
= strlen (sp
);
1000 adios(NULL
, "putaddr -- num register (%d) must be greater "
1001 "than label width (%d)", value
, indent
);
1003 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1004 charstring_push_back (scanlp
, c
);
1007 /* try to break at a comma; failing that, break at a
1010 lastb
= 0; sp
= lp
+ wid
;
1011 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1012 if (! lastb
&& isspace(c
))
1016 if (! (sp
= lastb
)) {
1018 while (*sp
&& *sp
!= ',' &&
1019 !isspace((unsigned char) *sp
))
1026 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1027 charstring_push_back (scanlp
, *lp
++);
1029 while (isspace((unsigned char) *lp
))
1032 if (charstring_chars (scanlp
) < max
) {
1033 charstring_push_back (scanlp
, '\n');
1036 charstring_chars (scanlp
) < max
&& i
> 0;
1038 charstring_push_back (scanlp
, ' ');
1041 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1047 if (comp
->c_flags
& CF_PARSED
)
1049 if (comp
->c_mn
!= &fmt_mnull
)
1050 mnfree (comp
->c_mn
);
1051 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1052 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1056 comp
->c_flags
|= CF_PARSED
;
1058 while (getname("")) /* XXX */
1060 comp
->c_mn
= &fmt_mnull
;
1068 * if there's no component, we say true. Otherwise we
1069 * say "true" only if we can parse the address and it
1070 * matches one of our addresses.
1073 if (comp
->c_mn
!= &fmt_mnull
)
1074 mnfree (comp
->c_mn
);
1075 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1076 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1079 comp
->c_flags
|= CF_TRUE
;
1080 /* Set str for use with FT_GETMYMBOX. With
1081 FT_GETMYADDR, comp->c_mn will be run through
1082 FT_LS_ADDR, which will strip off any pers
1086 comp
->c_flags
&= ~CF_TRUE
;
1088 while ((sp
= getname(sp
)))
1089 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1090 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1092 comp
->c_flags
|= CF_TRUE
;
1093 /* Set str and comp->c_text for use with
1094 FT_GETMYMBOX. With FT_GETMYADDR,
1095 comp->c_mn will be run through
1096 FT_LS_ADDR, which will strip off any
1098 free (comp
->c_text
);
1099 comp
->c_text
= str
= strdup (mn
->m_text
);
1102 comp
->c_flags
|= CF_PARSED
;
1104 while (getname("")) /* XXX */
1106 if (comp
->c_text
== 0)
1107 comp
->c_flags
|= CF_TRUE
;
1109 comp
->c_flags
&= ~CF_TRUE
;
1111 comp
->c_mn
= &fmt_mnull
;
1113 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1114 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1115 /* Fool FT_LS_ADDR into not producing an address. */
1116 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1122 * Call our tracing callback function, if one was supplied
1125 if (callbacks
&& callbacks
->trace_func
)
1126 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1127 str
, charstring_buffer (scanlp
));
1131 /* Emit any trailing sequences of zero display length. */
1132 while (fmt
->f_type
!= FT_DONE
) {
1133 if (fmt
->f_type
== FT_LS_LIT
) {
1135 if (callbacks
&& callbacks
->trace_func
)
1136 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1137 str
, charstring_buffer (scanlp
));
1138 } else if (fmt
->f_type
== FT_STRLITZ
) {
1139 /* Don't want to emit part of an escape sequence. So if
1140 there isn't enough room in the buffer for the entire
1141 string, skip it completely. Need room for null
1142 terminator, and maybe trailing newline (added below). */
1144 for (sp
= str
; *sp
; ++sp
) {
1145 charstring_push_back (scanlp
, *sp
);
1148 if (callbacks
&& callbacks
->trace_func
)
1149 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1150 str
, charstring_buffer (scanlp
));
1156 if (charstring_bytes (scanlp
) > 0) {
1158 * Append a newline if the last character wasn't.
1160 #ifdef MULTIBYTE_SUPPORT
1162 * It's a little tricky because the last byte might be part of
1163 * a multibyte character, in which case we assume that wasn't
1166 size_t last_char_len
= charstring_last_char_len (scanlp
);
1167 #else /* ! MULTIBYTE_SUPPORT */
1168 size_t last_char_len
= 1;
1169 #endif /* ! MULTIBYTE_SUPPORT */
1171 if (last_char_len
> 1 ||
1172 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1173 charstring_push_back (scanlp
, '\n');
1177 return ((struct format
*)0);