]>
diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
b8e59e050504d841628dc24dc7ea302890bd13b5
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).
15 #include "fmt_rfc2047.h"
17 #include "context_find.h"
19 #include "h/addrsbr.h"
20 #include "h/fmt_scan.h"
22 #include "h/fmt_compile.h"
26 #ifdef HAVE_SYS_TIME_H
27 # include <sys/time.h>
30 #ifdef MULTIBYTE_SUPPORT
35 struct mailname fmt_mnull
= { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0, 0, 0, 0,
41 static int match (char *, char *) PURE
;
42 static char *get_x400_friendly (char *, char *, int);
43 static int get_x400_comp (char *, char *, char *, int);
47 * test if string "sub" appears anywhere in
48 * string "str" (case insensitive).
52 match (char *str
, char *sub
)
58 c1
= tolower((unsigned char)c1
);
59 while ((c2
= *str
++) && c1
!= tolower((unsigned char)c2
))
63 s1
= sub
+ 1; s2
= str
;
64 while ((c1
= *s1
++) &&
65 tolower((unsigned char)c1
) == tolower((unsigned char)(c2
= *s2
++)))
73 /* cpnumber formats num as a signed decimal,
74 * appending it to dest if the result doesn't exceed max.
75 * The absolute value of width is the minimum width to produce.
76 * A smaller string is padded;
77 * on the left if width is positive, else the right.
78 * Left-padding uses fill. It is either ' ' or '0'.
79 * Right-padding is always with space. */
81 cpnumber(charstring_t dest
, int num
, int width
, char fill
, size_t max
)
83 if (width
== 0 || width
== INT_MIN
) {
87 bool padright
= width
< 0;
89 width
= -width
; /* Can't overflow after above check. */
93 return; /* The padded result can't fit. */
95 if (num
< 0 && w
== 1) {
96 return; /* No room for `-' and a digit or `?'. */
100 size_t len
= strlen(s
);
102 charstring_append_cstring(dest
, s
);
106 bool neg
= *s
== '-';
109 charstring_append_cstring(dest
, s
);
111 charstring_push_back(dest
, ' ');
116 if (neg
&& fill
== '0') {
117 charstring_push_back(dest
, *s
++);
120 charstring_push_back(dest
, fill
);
122 charstring_append_cstring(dest
, s
);
126 /* Transform 1234567 -> 1234?67 and -1234567 -> 1234-?7. */
127 char *news
= s
+ len
- w
;
132 charstring_append_cstring(dest
, news
);
136 * copy string from str to dest padding with the fill character to a
137 * size of wid characters. if wid is negative, the string is right
138 * aligned no more than max characters are copied
141 cptrimmed(charstring_t dest
, char *str
, int wid
, char fill
, size_t max
)
143 int remaining
; /* remaining output width available */
145 struct charstring
*trimmed
;
146 size_t end
; /* number of input bytes remaining in str */
147 #ifdef MULTIBYTE_SUPPORT
148 int char_len
; /* bytes in current character */
153 char *sp
; /* current position in source string */
157 if ((remaining
= wid
) < 0) {
158 remaining
= -remaining
;
161 if (remaining
> (int) max
) { remaining
= max
; }
163 trimmed
= rjust
? charstring_create(remaining
) : dest
;
165 bool prevCtrl
= true;
167 #ifdef MULTIBYTE_SUPPORT
168 if (mbtowc(NULL
, NULL
, 0)) {} /* reset shift state */
171 while (*sp
&& remaining
> 0 && end
> 0) {
172 #ifdef MULTIBYTE_SUPPORT
173 char_len
= mbtowc(&wide_char
, sp
, end
);
176 * See the relevant comments in cpstripped() to explain what's
177 * going on here; we want to handle the case where we get
178 * characters that mbtowc() cannot handle
183 char_len
= mbtowc(&wide_char
, altstr
, 1);
190 w
= wcwidth(wide_char
);
192 /* If w > remaining, w must be positive. */
199 if (iswcntrl(wide_char
) || iswspace(wide_char
)) {
204 /* isnctrl(), etc., take an int argument. Cygwin's ctype.h
205 intentionally warns if they are passed a char. */
206 c
= (unsigned char) *sp
;
207 if (iscntrl(c
) || isspace(c
)) {
211 charstring_push_back (trimmed
, ' ');
220 #ifdef MULTIBYTE_SUPPORT
221 if (w
>= 0 && remaining
>= w
) {
222 charstring_push_back_chars (trimmed
, altstr
? altstr
: sp
,
229 charstring_push_back (trimmed
, *sp
++);
235 while (remaining
-- > 0) {
236 charstring_push_back(dest
, fill
);
240 charstring_append(dest
, trimmed
);
241 charstring_free(trimmed
);
245 #ifdef MULTIBYTE_SUPPORT
247 cpstripped (charstring_t dest
, size_t max
, char *str
)
250 static char oddchar
[MB_LEN_MAX
* 2];
251 static size_t oddlen
;
252 static char spacechar
[MB_LEN_MAX
* 2];
253 static size_t spacelen
;
264 oddlen
= wcstombs(oddchar
, L
"?", sizeof oddchar
);
266 assert(wcwidth(L
' ') == 1); /* Need to pad in ones. */
267 spacelen
= wcstombs(spacechar
, L
" ", sizeof spacechar
);
268 assert(spacelen
> 0);
272 return; /* It's unclear why no padding in this case. */
273 end
= str
+ strlen(str
);
275 if (mbtowc(NULL
, NULL
, 0))
276 {} /* Reset shift state. */
278 squash
= true; /* Trim `space' or `cntrl' from the start. */
281 return; /* It's unclear why no padding in this case. */
283 srclen
= mbtowc(&rune
, str
, end
- str
);
285 /* Invalid rune, or not enough bytes to finish it. */
289 str
++; /* Skip one byte. */
295 if (iswspace(rune
) || iswcntrl(rune
)) {
297 continue; /* Amidst a run of these. */
314 if ((size_t)w
> max
) {
315 /* No room for rune; pad. */
317 charstring_push_back_chars(dest
, spacechar
, spacelen
, 1);
321 charstring_push_back_chars(dest
, src
, srclen
, w
);
327 #ifndef MULTIBYTE_SUPPORT
329 cpstripped (charstring_t dest
, size_t max
, char *str
)
337 squash
= true; /* Strip leading cases. */
339 c
= (unsigned char)*str
++;
343 if (isspace(c
) || iscntrl(c
)) {
351 charstring_push_back(dest
, (char)c
);
356 static char *lmonth
[] = { "January", "February","March", "April",
357 "May", "June", "July", "August",
358 "September","October", "November","December" };
361 get_x400_friendly (char *mbox
, char *buffer
, int buffer_len
)
363 char given
[BUFSIZ
], surname
[BUFSIZ
];
372 if (get_x400_comp (mbox
, "/PN=", buffer
, buffer_len
)) {
373 for (mbox
= buffer
; (mbox
= strchr(mbox
, '.')); )
379 if (!get_x400_comp (mbox
, "/S=", surname
, sizeof(surname
)))
382 if (get_x400_comp (mbox
, "/G=", given
, sizeof(given
)))
383 snprintf (buffer
, buffer_len
, "%s %s", given
, surname
);
385 snprintf (buffer
, buffer_len
, "%s", surname
);
391 get_x400_comp (char *mbox
, char *key
, char *buffer
, int buffer_len
)
396 if ((idx
= stringdex (key
, mbox
)) < 0
397 || !(cp
= strchr(mbox
+= idx
+ strlen (key
), '/')))
400 snprintf (buffer
, buffer_len
, "%*.*s", (int)(cp
- mbox
), (int)(cp
- mbox
), mbox
);
405 fmt_scan (struct format
*format
, charstring_t scanlp
, int width
, int *dat
,
406 struct fmt_callbacks
*callbacks
)
409 /* If str points to part of buffer[] or buffer2[] then it must only
410 * ever point at their first element as otherwise undefined
411 * behaviour from overlapping strncpy(3)s can result. */
413 char buffer
[NMH_BUFSIZ
], buffer2
[NMH_BUFSIZ
];
425 * max is the same as width, but unsigned so comparisons
426 * with charstring_chars() won't raise compile warnings.
429 savestr
= str
= NULL
;
432 for (fmt
= format
; fmt
->f_type
!= FT_DONE
; fmt
++)
433 switch (fmt
->f_type
) {
436 fmt
->f_comp
->c_flags
&= ~CF_PARSED
;
441 case FT_LS_DECODECOMP
:
443 * Trim these components of any newlines.
445 * But don't trim the "body" and "text" components.
450 if (! (comp
->c_flags
& CF_TRIMMED
) && comp
->c_text
&&
451 (i
= strlen(comp
->c_text
)) > 0) {
452 if (comp
->c_text
[i
- 1] == '\n' &&
453 strcmp(comp
->c_name
, "body") != 0 &&
454 strcmp(comp
->c_name
, "text") != 0)
455 comp
->c_text
[i
- 1] = '\0';
456 comp
->c_flags
|= CF_TRIMMED
;
463 for ( ; charstring_chars (scanlp
) < max
; ) {
464 switch (fmt
->f_type
) {
467 cpstripped (scanlp
, max
- charstring_chars (scanlp
),
468 fmt
->f_comp
->c_text
);
471 cptrimmed (scanlp
, fmt
->f_comp
->c_text
, fmt
->f_width
,
472 fmt
->f_fill
, max
- charstring_chars (scanlp
));
477 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
478 charstring_push_back (scanlp
, c
);
487 rjust
= true; /* XXX should do something with this */
489 while ((c
= *sp
++) && --i
>= 0 && charstring_chars (scanlp
) < max
) {
490 charstring_push_back (scanlp
, c
);
492 while (--i
>= 0 && charstring_chars (scanlp
) < max
) {
493 charstring_push_back (scanlp
, fmt
->f_fill
);
498 cpstripped (scanlp
, max
- charstring_chars (scanlp
), str
);
501 cptrimmed (scanlp
, str
, fmt
->f_width
, fmt
->f_fill
,
502 max
- charstring_chars (scanlp
));
507 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
508 charstring_push_back (scanlp
, c
);
513 if (str
) charstring_push_back_chars (scanlp
, str
, strlen (str
), 0);
516 die("internal error (FT_STRFW)");
522 for (wid
= num
<= 0; num
; ++wid
, num
/= 10) {}
523 cpnumber (scanlp
, value
, wid
, ' ',
524 max
- charstring_chars (scanlp
));
531 unsigned int whole
, tenths
;
532 unsigned int scale
= 0;
533 unsigned int val
= (unsigned int)value
;
534 char *kibisuff
= NULL
;
536 switch (fmt
->f_type
) {
537 case FT_LS_KILO
: scale
= 1000; kibisuff
= ""; break;
538 case FT_LS_KIBI
: scale
= 1024; kibisuff
= "i"; break;
542 snprintf(buffer
, sizeof(buffer
), "%u", val
);
544 /* To prevent divide by 0, found by clang static
546 if (scale
== 0) { scale
= 1; }
548 /* find correct scale for size (Kilo/Mega/Giga/Tera) */
549 for (unitcp
= "KMGT"; val
> (scale
* scale
); val
/= scale
) {
555 strcpy(buffer
, "huge");
557 /* val is scale times too big. we want tenths */
565 tenths
= val
- (whole
* 10);
568 snprintf(buffer
, sizeof(buffer
), "%u.%u%c%s",
569 whole
, tenths
, *unitcp
, kibisuff
);
571 snprintf(buffer
, sizeof(buffer
), "%u%c%s",
572 whole
, *unitcp
, kibisuff
);
580 cpnumber (scanlp
, value
, fmt
->f_width
, fmt
->f_fill
,
581 max
- charstring_chars (scanlp
));
585 charstring_push_back (scanlp
, fmt
->f_char
);
589 if (callbacks
&& callbacks
->trace_func
)
590 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
591 str
, charstring_buffer (scanlp
));
595 if (!(value
= (str
&& *str
))) {
596 if (callbacks
&& callbacks
->trace_func
)
597 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
598 str
, charstring_buffer (scanlp
));
605 if (!(value
= (str
== NULL
|| *str
== 0))) {
606 if (callbacks
&& callbacks
->trace_func
)
607 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
608 str
, charstring_buffer (scanlp
));
615 if (value
!= fmt
->f_value
) {
616 if (callbacks
&& callbacks
->trace_func
)
617 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
618 str
, charstring_buffer (scanlp
));
625 if (value
== fmt
->f_value
) {
626 if (callbacks
&& callbacks
->trace_func
)
627 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
628 str
, charstring_buffer (scanlp
));
635 if (value
<= fmt
->f_value
) {
636 if (callbacks
&& callbacks
->trace_func
)
637 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
638 str
, charstring_buffer (scanlp
));
645 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
646 if (callbacks
&& callbacks
->trace_func
)
647 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
648 str
, charstring_buffer (scanlp
));
656 value
= match (str
, fmt
->f_text
);
662 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
663 if (callbacks
&& callbacks
->trace_func
)
664 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
665 str
, charstring_buffer (scanlp
));
672 value
= uprf (str
, fmt
->f_text
);
676 value
= (str
!= NULL
&& *str
!= 0);
680 value
= (str
== NULL
|| *str
== 0);
684 value
= (fmt
->f_value
== value
);
688 value
= (fmt
->f_value
!= value
);
692 value
= (fmt
->f_value
> value
);
696 if (callbacks
&& callbacks
->trace_func
)
697 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
698 str
, charstring_buffer (scanlp
));
706 str
= fmt
->f_comp
->c_text
;
712 if (!(str
= getenv (fmt
->f_text
)))
716 if (!(str
= context_find (fmt
->f_text
)))
720 case FT_LS_DECODECOMP
:
721 if (decode_rfc2047(fmt
->f_comp
->c_text
, buffer2
, sizeof(buffer2
)))
724 str
= fmt
->f_comp
->c_text
;
728 if (str
&& decode_rfc2047(str
, buffer2
, sizeof(buffer2
)))
737 strncpy(buffer
, str
, sizeof(buffer
));
738 buffer
[sizeof(buffer
)-1] = '\0';
740 while (isspace((unsigned char) *str
))
743 if ((i
= fmt
->f_width
) < 0) {
748 if (!rjust
&& i
> 0 && (int) strlen(str
) > i
)
751 xp
+= strlen(str
) - 1;
752 while (xp
> str
&& isspace((unsigned char) *xp
))
754 if (rjust
&& i
> 0 && (int) strlen(str
) > i
)
755 str
+= strlen(str
) - i
;
756 str
= memmove(buffer
, str
, strlen(str
) + 1);
761 value
= (fmt
->f_comp
->c_flags
& CF_TRUE
) != 0;
764 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
767 value
= fmt
->f_value
;
770 value
= dat
[fmt
->f_value
];
778 case FT_LV_CHAR_LEFT
:
779 value
= max
- charstring_bytes (scanlp
);
782 value
+= fmt
->f_value
;
785 value
= fmt
->f_value
- value
;
787 case FT_LV_MULTIPLY_L
:
788 value
*= fmt
->f_value
;
791 if (fmt
->f_value
== 0 || (fmt
->f_value
== -1 && value
== INT_MIN
)) {
792 // FIXME: Tell the user, and probably stop.
795 value
/= fmt
->f_value
;
800 value
%= fmt
->f_value
;
802 // FIXME: Tell the user, and probably stop.
810 value
= fmt
->f_comp
->c_tws
->tw_sec
;
813 value
= fmt
->f_comp
->c_tws
->tw_min
;
816 value
= fmt
->f_comp
->c_tws
->tw_hour
;
819 value
= fmt
->f_comp
->c_tws
->tw_mday
;
822 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
825 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
828 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
831 str
= dtwszone (fmt
->f_comp
->c_tws
);
834 value
= fmt
->f_comp
->c_tws
->tw_year
;
837 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
839 value
= tws
->tw_wday
;
842 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
844 str
= tw_dotw
[tws
->tw_wday
];
847 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
849 str
= tw_ldotw
[tws
->tw_wday
];
852 value
= fmt
->f_comp
->c_tws
->tw_yday
;
855 value
= fmt
->f_comp
->c_tws
->tw_zone
;
858 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
859 value
= dmktime(fmt
->f_comp
->c_tws
);
862 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
863 value
= dmktime(fmt
->f_comp
->c_tws
);
864 value
= time(NULL
) - value
;
867 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
869 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
879 if (fmt
->f_comp
->c_tws
->tw_flags
& TW_SZEXP
)
885 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
? 1 : 0;
888 str
= dasctime (fmt
->f_comp
->c_tws
, TW_ZONE
);
891 str
= dasctime (fmt
->f_comp
->c_tws
, TW_NULL
);
895 str
= fmt
->f_comp
->c_mn
->m_pers
;
898 str
= fmt
->f_comp
->c_mn
->m_mbox
;
901 str
= fmt
->f_comp
->c_mn
->m_host
;
904 str
= fmt
->f_comp
->c_mn
->m_path
;
907 str
= fmt
->f_comp
->c_mn
->m_gname
;
910 str
= fmt
->f_comp
->c_mn
->m_note
;
913 str
= adrformat( fmt
->f_comp
->c_mn
);
916 value
= fmt
->f_comp
->c_mn
->m_type
;
919 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
922 value
= fmt
->f_comp
->c_mn
->m_nohost
;
926 if ((mn
= fmt
->f_comp
->c_mn
) == &fmt_mnull
) {
927 str
= fmt
->f_comp
->c_text
;
930 if (fmt
->f_type
== FT_LS_ADDR
)
932 if ((str
= mn
->m_pers
) == NULL
) {
933 if ((str
= mn
->m_note
)) {
935 strncpy (buffer
, str
, sizeof(buffer
));
936 buffer
[sizeof(buffer
)-1] = '\0';
940 sp
= str
+ strlen(str
) - 1;
949 str
= memmove(buffer
, str
, strlen(str
) + 1);
950 } else if (!(str
= get_x400_friendly (mn
->m_mbox
,
951 buffer
, sizeof(buffer
)))) {
953 switch (mn
->m_type
) {
958 snprintf (buffer
, sizeof(buffer
), "%s!%s",
959 mn
->m_host
, mn
->m_mbox
);
964 snprintf (buffer
, sizeof(buffer
), "%s@%s",
965 mn
->m_mbox
, mn
->m_host
);
977 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
981 strncpy(buffer
, str
, sizeof(buffer
));
982 /* strncpy doesn't NUL-terminate if it fills the buffer */
983 buffer
[sizeof(buffer
)-1] = '\0';
984 unquote_string(buffer
, buffer2
);
991 if ((t
= comp
->c_tws
->tw_clock
) == 0)
992 t
= dmktime(comp
->c_tws
);
993 tws
= dlocaltime(&t
);
999 if ((t
= comp
->c_tws
->tw_clock
) == 0)
1000 t
= dmktime(comp
->c_tws
);
1002 *comp
->c_tws
= *tws
;
1007 if (comp
->c_flags
& CF_PARSED
)
1009 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
1010 *comp
->c_tws
= *tws
;
1011 comp
->c_flags
&= ~CF_TRUE
;
1012 } else if ((comp
->c_flags
& CF_DATEFAB
) == 0) {
1014 comp
->c_flags
= CF_TRUE
;
1016 comp
->c_flags
|= CF_PARSED
;
1020 /* hook for custom address list formatting (see replsbr.c) */
1021 if (callbacks
&& callbacks
->formataddr
)
1022 str
= callbacks
->formataddr (savestr
, str
);
1024 str
= formataddr (savestr
, str
);
1028 /* The same as formataddr, but doesn't do duplicate suppression */
1029 if (callbacks
&& callbacks
->concataddr
)
1030 str
= callbacks
->concataddr (savestr
, str
);
1032 str
= concataddr (savestr
, str
);
1036 /* output the str register as an address component,
1037 * splitting it into multiple lines if necessary. The
1038 * value reg. contains the max line length. The lit.
1039 * field may contain a string to prepend to the result
1044 int indent
, wid
, len
;
1048 len
= str
? strlen (str
) : 0;
1050 indent
= strlen (sp
);
1053 die("putaddr -- num register (%d) must be greater "
1054 "than label width (%d)", value
, indent
);
1056 while ((c
= *sp
++) && charstring_chars (scanlp
) < max
) {
1057 charstring_push_back (scanlp
, c
);
1060 /* try to break at a comma; failing that, break at a
1063 lastb
= 0; sp
= lp
+ wid
;
1064 while (sp
> lp
&& (c
= (unsigned char) *--sp
) != ',') {
1065 if (! lastb
&& isspace(c
))
1069 if (! (sp
= lastb
)) {
1071 while (*sp
&& *sp
!= ',' &&
1072 !isspace((unsigned char) *sp
))
1079 while (lp
<= sp
&& charstring_chars (scanlp
) < max
) {
1080 charstring_push_back (scanlp
, *lp
++);
1082 while (isspace((unsigned char) *lp
))
1085 if (charstring_chars (scanlp
) < max
) {
1086 charstring_push_back (scanlp
, '\n');
1089 charstring_chars (scanlp
) < max
&& i
> 0;
1091 charstring_push_back (scanlp
, ' ');
1094 cpstripped (scanlp
, max
- charstring_chars (scanlp
), lp
);
1100 if (comp
->c_flags
& CF_PARSED
)
1102 if (comp
->c_mn
!= &fmt_mnull
)
1103 mnfree (comp
->c_mn
);
1104 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1105 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1109 comp
->c_flags
|= CF_PARSED
;
1111 while (getname("")) /* XXX */
1113 comp
->c_mn
= &fmt_mnull
;
1121 * if there's no component, we say true. Otherwise we
1122 * say "true" only if we can parse the address and it
1123 * matches one of our addresses.
1126 if (comp
->c_mn
!= &fmt_mnull
)
1127 mnfree (comp
->c_mn
);
1128 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
1129 (mn
= getm (sp
, NULL
, 0, NULL
, 0))) {
1132 comp
->c_flags
|= CF_TRUE
;
1133 /* Set str for use with FT_GETMYMBOX. With
1134 FT_GETMYADDR, comp->c_mn will be run through
1135 FT_LS_ADDR, which will strip off any pers
1139 comp
->c_flags
&= ~CF_TRUE
;
1141 while ((sp
= getname(sp
)))
1142 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1143 (mn
= getm (sp
, NULL
, 0, NULL
, 0)))
1145 comp
->c_flags
|= CF_TRUE
;
1146 /* Set str and comp->c_text for use with
1147 FT_GETMYMBOX. With FT_GETMYADDR,
1148 comp->c_mn will be run through
1149 FT_LS_ADDR, which will strip off any
1151 free (comp
->c_text
);
1152 comp
->c_text
= str
= strdup (mn
->m_text
);
1155 comp
->c_flags
|= CF_PARSED
;
1157 while (getname("")) /* XXX */
1159 if (comp
->c_text
== 0)
1160 comp
->c_flags
|= CF_TRUE
;
1162 comp
->c_flags
&= ~CF_TRUE
;
1164 comp
->c_mn
= &fmt_mnull
;
1166 if ((comp
->c_flags
& CF_TRUE
) == 0 &&
1167 (fmt
->f_type
== FT_GETMYMBOX
|| fmt
->f_type
== FT_GETMYADDR
)) {
1168 /* Fool FT_LS_ADDR into not producing an address. */
1169 comp
->c_mn
= &fmt_mnull
; comp
->c_text
= NULL
;
1175 * Call our tracing callback function, if one was supplied
1178 if (callbacks
&& callbacks
->trace_func
)
1179 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1180 str
, charstring_buffer (scanlp
));
1184 /* Emit any trailing sequences of zero display length. */
1185 while (fmt
->f_type
!= FT_DONE
) {
1186 if (fmt
->f_type
== FT_LS_LIT
) {
1188 if (callbacks
&& callbacks
->trace_func
)
1189 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1190 str
, charstring_buffer (scanlp
));
1191 } else if (fmt
->f_type
== FT_STRLITZ
) {
1192 /* Don't want to emit part of an escape sequence. So if
1193 there isn't enough room in the buffer for the entire
1194 string, skip it completely. Need room for null
1195 terminator, and maybe trailing newline (added below). */
1197 for (sp
= str
; *sp
; ++sp
) {
1198 charstring_push_back (scanlp
, *sp
);
1201 if (callbacks
&& callbacks
->trace_func
)
1202 callbacks
->trace_func(callbacks
->trace_context
, fmt
, value
,
1203 str
, charstring_buffer (scanlp
));
1209 if (charstring_bytes (scanlp
) > 0) {
1211 * Append a newline if the last character wasn't.
1213 #ifdef MULTIBYTE_SUPPORT
1215 * It's a little tricky because the last byte might be part of
1216 * a multibyte character, in which case we assume that wasn't
1219 size_t last_char_len
= charstring_last_char_len (scanlp
);
1220 #else /* ! MULTIBYTE_SUPPORT */
1221 size_t last_char_len
= 1;
1222 #endif /* ! MULTIBYTE_SUPPORT */
1224 if (last_char_len
> 1 ||
1225 charstring_buffer (scanlp
)[charstring_bytes (scanlp
) - 1] != '\n') {
1226 charstring_push_back (scanlp
, '\n');