]>
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. */
99 charstring_push_back (rev
, '-');
102 while (wid
-- > 0 && fill
!= 0) {
103 charstring_push_back (rev
, fill
);
105 if (num
< 0 && fill
== '0') {
106 charstring_push_back (rev
, '-');
110 /* Output the string in reverse. */
111 size_t b
= charstring_bytes (rev
);
112 const char *cp
= b
? &charstring_buffer (rev
)[b
] : NULL
;
115 charstring_push_back (dest
, *--cp
);
119 charstring_free (rev
);
124 * copy string from str to dest padding with the fill character to a
125 * size of wid characters. if wid is negative, the string is right
126 * aligned no more than max characters are copied
129 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
) {
130 int remaining
; /* remaining output width available */
132 size_t end
; /* number of input bytes remaining in str */
133 #ifdef MULTIBYTE_SUPPORT
134 int char_len
; /* bytes in current character */
139 char *sp
; /* current position in source string */
144 if ((remaining
= wid
) < 0) {
145 remaining
= -remaining
;
148 if (remaining
> (int) max
) { remaining
= max
; }
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 (dest
, ' ');
204 #ifdef MULTIBYTE_SUPPORT
205 if (w
>= 0 && remaining
>= w
) {
206 charstring_push_back_chars (dest
, altstr
? altstr
: sp
,
213 charstring_push_back (dest
, *sp
++);
221 /* copy string to the right */
222 charstring_t copy
= charstring_copy (dest
);
224 /* add padding at the beginning */
225 charstring_clear (dest
);
226 for (; remaining
> 0; --remaining
) {
227 charstring_push_back (dest
, fill
);
230 charstring_append (dest
, copy
);
232 charstring_free (copy
);
235 /* pad remaining space */
236 while (remaining
-- > 0) {
237 charstring_push_back (dest
, fill
);
243 cpstripped (charstring_t dest
, size_t max
, char *str
)
245 int prevCtrl
= 1; /* This is 1 so we strip out leading spaces */
247 #ifdef MULTIBYTE_SUPPORT
251 #endif /* MULTIBYTE_SUPPORT */
259 #ifdef MULTIBYTE_SUPPORT
260 if (mbtowc(NULL
, NULL
, 0)) {} /* Reset shift state */
261 #endif /* MULTIBYTE_SUPPORT */
264 * Process each character at a time; if we have multibyte support
265 * then deal with that here.
268 while (*str
!= '\0' && len
> 0 && max
> 0) {
269 #ifdef MULTIBYTE_SUPPORT
270 char_len
= mbtowc(&wide_char
, str
, len
);
271 w
= wcwidth(wide_char
);
274 * If mbrtowc() failed, then we have a character that isn't valid
275 * in the current encoding. Replace it with a '?'. We do that by
276 * setting the alstr variable to the value of the replacement string;
277 * altstr is used below when the bytes are copied into the output
283 char_len
= mbtowc(&wide_char
, altstr
, 1);
292 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
294 #else /* MULTIBYTE_SUPPORT */
295 int c
= (unsigned char) *str
;
297 if (iscntrl(c
) || isspace(c
)) {
299 #endif /* MULTIBYTE_SUPPORT */
301 charstring_push_back (dest
, ' ');
311 #ifdef MULTIBYTE_SUPPORT
312 charstring_push_back_chars (dest
, altstr
? altstr
: str
, char_len
, w
);
316 #else /* MULTIBYE_SUPPORT */
317 charstring_push_back (dest
, *str
++);
319 #endif /* MULTIBYTE_SUPPORT */
323 static char *lmonth
[] = { "January", "February","March", "April",
324 "May", "June", "July", "August",
325 "September","October", "November","December" };
328 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
330 char given
[BUFSIZ
], surname
[BUFSIZ
];
339 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
340 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
346 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
349 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
350 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
352 snprintf (buffer
, buffer_len
, "%s", surname
);
358 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
363 if ((idx
= stringdex (key
, mbox
)) < 0
364 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
367 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
372 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
373 struct fmt_callbacks
*callbacks
)
377 char buffer
[BUFSIZ
], buffer2
[BUFSIZ
];
388 * max is the same as width, but unsigned so comparisons
389 * with charstring_chars() won't raise compile warnings.
392 savestr
= str
= NULL
;
395 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
396 switch (fmt
->f_type
) {
399 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
404 case FT_LS_DECODECOMP
:
406 * Trim these components of any newlines.
408 * But don't trim the "body" and "text" components.
413 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
414 (i
= strlen(comp
->c_text
)) > 0) {
415 if (comp
->c_text
[i
- 1] == '\n' &&
416 strcmp(comp
->c_name
, "body") != 0 &&
417 strcmp(comp
->c_name
, "text") != 0)
418 comp
->c_text
[i
- 1] = '\0';
419 comp
->c_flags
|= CF_TRIMMED
;
426 for ( ; charstring_chars (scanlp
) < max
; ) {
427 switch (fmt
->f_type
) {
430 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
431 fmt
->f_comp
->c_text
);
434 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
435 fmt
->f_fill
, max
- charstring_chars (scanlp
));
440 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
441 charstring_push_back (scanlp
, c
);
450 rjust
++; /* XXX should do something with this */
452 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
453 charstring_push_back (scanlp
, c
);
455 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
456 charstring_push_back (scanlp
, fmt
->f_fill
);
461 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
464 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
465 max
- charstring_chars (scanlp
));
470 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
471 charstring_push_back (scanlp
, c
);
476 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
479 adios (NULL
, "internal error (FT_STRFW)");
485 for (wid
= num
<= 0 ? 1 : 0; num
; ++wid
, num
/= 10) {}
486 cpnumber (scanlp
, value
, wid
, ' ',
487 max
- charstring_chars (scanlp
));
494 unsigned int whole
, tenths
;
495 unsigned int scale
= 0;
496 unsigned int val
= (unsigned int)value
;
497 char *kibisuff
= NULL
;
499 switch (fmt
->f_type
) {
500 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
501 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
505 snprintf(buffer
, sizeof(buffer
), "%u", val
);
507 /* To prevent divide by 0, found by clang static
509 if (scale
== 0) { scale
= 1; }
511 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
512 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
518 strcpy(buffer
, "huge");
520 /* val is scale times too big. we want tenths */
528 tenths
= val
- (whole
* 10);
531 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
532 whole
, tenths
, *unitcp
, kibisuff
);
534 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
535 whole
, *unitcp
, kibisuff
);
543 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
544 max
- charstring_chars (scanlp
));
548 charstring_push_back (scanlp
, fmt
->f_char
);
552 if (callbacks
&& callbacks
->trace_func
)
553 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
554 str
, charstring_buffer (scanlp
));
558 if (!(value
= (str
&& *str
))) {
559 if (callbacks
&& callbacks
->trace_func
)
560 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
561 str
, charstring_buffer (scanlp
));
568 if (!(value
= (str
== NULL
|| *str
== 0))) {
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
<= fmt
->f_value
) {
599 if (callbacks
&& callbacks
->trace_func
)
600 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
601 str
, charstring_buffer (scanlp
));
608 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
609 if (callbacks
&& callbacks
->trace_func
)
610 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
611 str
, charstring_buffer (scanlp
));
619 value
= match (str
, fmt
->f_text
);
625 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
626 if (callbacks
&& callbacks
->trace_func
)
627 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
628 str
, charstring_buffer (scanlp
));
635 value
= uprf (str
, fmt
->f_text
);
639 value
= (str
!= NULL
&& *str
!= 0);
643 value
= (str
== NULL
|| *str
== 0);
647 value
= (fmt
->f_value
== value
);
651 value
= (fmt
->f_value
!= value
);
655 value
= (fmt
->f_value
> value
);
659 if (callbacks
&& callbacks
->trace_func
)
660 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
661 str
, charstring_buffer (scanlp
));
669 str
= fmt
->f_comp
->c_text
;
675 if (!(str
= getenv (fmt
->f_text
)))
679 if (!(str
= context_find (fmt
->f_text
)))
683 case FT_LS_DECODECOMP
:
684 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
687 str
= fmt
->f_comp
->c_text
;
691 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
700 strncpy(buffer
, str
, sizeof(buffer
));
701 buffer
[sizeof(buffer
)-1] = '\0';
703 while (isspace((unsigned char) *str
))
706 if ((i
= fmt
->f_width
) < 0) {
711 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
714 xp
+= strlen(str
) - 1;
715 while (xp
> str
&& isspace((unsigned char) *xp
))
717 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
718 str
+= strlen(str
) - i
;
723 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
726 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
729 value
= fmt
->f_value
;
732 value
= dat
[fmt
->f_value
];
740 case FT_LV_CHAR_LEFT
:
741 value
= max
- charstring_bytes (scanlp
);
744 value
+= fmt
->f_value
;
747 value
= fmt
->f_value
- value
;
749 case FT_LV_MULTIPLY_L
:
750 value
*= fmt
->f_value
;
754 value
= value
/ fmt
->f_value
;
760 value
= value
% fmt
->f_value
;
769 value
= fmt
->f_comp
->c_tws
->tw_sec
;
772 value
= fmt
->f_comp
->c_tws
->tw_min
;
775 value
= fmt
->f_comp
->c_tws
->tw_hour
;
778 value
= fmt
->f_comp
->c_tws
->tw_mday
;
781 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
784 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
787 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
790 str
= dtwszone (fmt
->f_comp
->c_tws
);
793 value
= fmt
->f_comp
->c_tws
->tw_year
;
796 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
798 value
= tws
->tw_wday
;
801 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
803 str
= tw_dotw
[tws
->tw_wday
];
806 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
808 str
= tw_ldotw
[tws
->tw_wday
];
811 value
= fmt
->f_comp
->c_tws
->tw_yday
;
814 value
= fmt
->f_comp
->c_tws
->tw_zone
;
817 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
818 value
= dmktime(fmt
->f_comp
->c_tws
);
821 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
822 value
= dmktime(fmt
->f_comp
->c_tws
);
823 value
= time((time_t *) 0) - value
;
826 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
828 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
838 if ((fmt
->f_comp
->c_tws
->tw_flags
& TW_SZONE
) == TW_SZEXP
)
844 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
847 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
850 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
854 str
= fmt
->f_comp
->c_mn
->m_pers
;
857 str
= fmt
->f_comp
->c_mn
->m_mbox
;
860 str
= fmt
->f_comp
->c_mn
->m_host
;
863 str
= fmt
->f_comp
->c_mn
->m_path
;
866 str
= fmt
->f_comp
->c_mn
->m_gname
;
869 str
= fmt
->f_comp
->c_mn
->m_note
;
872 str
= adrformat( fmt
->f_comp
->c_mn
);
875 value
= fmt
->f_comp
->c_mn
->m_type
;
878 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
881 value
= fmt
->f_comp
->c_mn
->m_nohost
;
885 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
886 str
= fmt
->f_comp
->c_text
;
889 if (fmt
->f_type
== FT_LS_ADDR
)
891 if ((str
= mn
->m_pers
) == NULL
) {
892 if ((str
= mn
->m_note
)) {
894 strncpy (buffer
, str
, sizeof(buffer
));
895 buffer
[sizeof(buffer
)-1] = '\0';
899 sp
= str
+ strlen(str
) - 1;
908 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
909 buffer
, sizeof(buffer
)))) {
911 switch (mn
->m_type
) {
916 snprintf (buffer
, sizeof(buffer
), "%s!%s",
917 mn
->m_host
, mn
->m_mbox
);
922 snprintf (buffer
, sizeof(buffer
), "%s@%s",
923 mn
->m_mbox
, mn
->m_host
);
935 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
939 strncpy(buffer
, str
, sizeof(buffer
));
940 /* strncpy doesn't NUL-terminate if it fills the buffer */
941 buffer
[sizeof(buffer
)-1] = '\0';
942 unquote_string(buffer
, buffer2
);
949 if ((t
= comp
->c_tws
->tw_clock
) == 0)
950 t
= dmktime(comp
->c_tws
);
951 tws
= dlocaltime(&t
);
957 if ((t
= comp
->c_tws
->tw_clock
) == 0)
958 t
= dmktime(comp
->c_tws
);
965 if (comp
->c_flags
& CF_PARSED
)
967 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
969 comp
->c_flags
&= ~CF_TRUE
;
970 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
971 memset (comp
->c_tws
, 0, sizeof *comp
->c_tws
);
972 comp
->c_flags
= CF_TRUE
;
974 comp
->c_flags
|= CF_PARSED
;
978 /* hook for custom address list formatting (see replsbr.c) */
979 if (callbacks
&& callbacks
->formataddr
)
980 str
= callbacks
->formataddr (savestr
, str
);
982 str
= formataddr (savestr
, str
);
986 /* The same as formataddr, but doesn't do duplicate suppression */
987 if (callbacks
&& callbacks
->concataddr
)
988 str
= callbacks
->concataddr (savestr
, str
);
990 str
= concataddr (savestr
, str
);
994 /* output the str register as an address component,
995 * splitting it into multiple lines if necessary. The
996 * value reg. contains the max line length. The lit.
997 * field may contain a string to prepend to the result
1002 int indent
, wid
, len
;
1006 len
= str
? strlen (str
) : 0;
1008 indent
= strlen (sp
);
1011 adios(NULL
, "putaddr -- num register (%d) must be greater "
1012 "than label width (%d)", value
, indent
);
1014 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1015 charstring_push_back (scanlp
, c
);
1018 /* try to break at a comma; failing that, break at a
1021 lastb
= 0; sp
= lp
+ wid
;
1022 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1023 if (! lastb
&& isspace(c
))
1027 if (! (sp
= lastb
)) {
1029 while (*sp
&& *sp
!= ',' &&
1030 !isspace((unsigned char) *sp
))
1037 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1038 charstring_push_back (scanlp
, *lp
++);
1040 while (isspace((unsigned char) *lp
))
1043 if (charstring_chars (scanlp
) < max
) {
1044 charstring_push_back (scanlp
, '\n');
1047 charstring_chars (scanlp
) < max
&& i
> 0;
1049 charstring_push_back (scanlp
, ' ');
1052 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1058 if (comp
->c_flags
& CF_PARSED
)
1060 if (comp
->c_mn
!= &fmt_mnull
)
1061 mnfree (comp
->c_mn
);
1062 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1063 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1067 comp
->c_flags
|= CF_PARSED
;
1069 while (getname("")) /* XXX */
1071 comp
->c_mn
= &fmt_mnull
;
1079 * if there's no component, we say true. Otherwise we
1080 * say "true" only if we can parse the address and it
1081 * matches one of our addresses.
1084 if (comp
->c_mn
!= &fmt_mnull
)
1085 mnfree (comp
->c_mn
);
1086 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1087 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1090 comp
->c_flags
|= CF_TRUE
;
1091 /* Set str for use with FT_GETMYMBOX. With
1092 FT_GETMYADDR, comp->c_mn will be run through
1093 FT_LS_ADDR, which will strip off any pers
1097 comp
->c_flags
&= ~CF_TRUE
;
1099 while ((sp
= getname(sp
)))
1100 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1101 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1103 comp
->c_flags
|= CF_TRUE
;
1104 /* Set str and comp->c_text for use with
1105 FT_GETMYMBOX. With FT_GETMYADDR,
1106 comp->c_mn will be run through
1107 FT_LS_ADDR, which will strip off any
1109 free (comp
->c_text
);
1110 comp
->c_text
= str
= strdup (mn
->m_text
);
1113 comp
->c_flags
|= CF_PARSED
;
1115 while (getname("")) /* XXX */
1117 if (comp
->c_text
== 0)
1118 comp
->c_flags
|= CF_TRUE
;
1120 comp
->c_flags
&= ~CF_TRUE
;
1122 comp
->c_mn
= &fmt_mnull
;
1124 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1125 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1126 /* Fool FT_LS_ADDR into not producing an address. */
1127 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1133 * Call our tracing callback function, if one was supplied
1136 if (callbacks
&& callbacks
->trace_func
)
1137 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1138 str
, charstring_buffer (scanlp
));
1142 /* Emit any trailing sequences of zero display length. */
1143 while (fmt
->f_type
!= FT_DONE
) {
1144 if (fmt
->f_type
== FT_LS_LIT
) {
1146 if (callbacks
&& callbacks
->trace_func
)
1147 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1148 str
, charstring_buffer (scanlp
));
1149 } else if (fmt
->f_type
== FT_STRLITZ
) {
1150 /* Don't want to emit part of an escape sequence. So if
1151 there isn't enough room in the buffer for the entire
1152 string, skip it completely. Need room for null
1153 terminator, and maybe trailing newline (added below). */
1155 for (sp
= str
; *sp
; ++sp
) {
1156 charstring_push_back (scanlp
, *sp
);
1159 if (callbacks
&& callbacks
->trace_func
)
1160 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1161 str
, charstring_buffer (scanlp
));
1167 if (charstring_bytes (scanlp
) > 0) {
1169 * Append a newline if the last character wasn't.
1171 #ifdef MULTIBYTE_SUPPORT
1173 * It's a little tricky because the last byte might be part of
1174 * a multibyte character, in which case we assume that wasn't
1177 size_t last_char_len
= charstring_last_char_len (scanlp
);
1178 #else /* ! MULTIBYTE_SUPPORT */
1179 size_t last_char_len
= 1;
1180 #endif /* ! MULTIBYTE_SUPPORT */
1182 if (last_char_len
> 1 ||
1183 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1184 charstring_push_back (scanlp
, '\n');
1188 return ((struct format
*)0);