]> diplodocus.org Git - nmh/blob - sbr/fmt_scan.c
Fix stupid accidental dependence on a bash quirk in previous
[nmh] / sbr / fmt_scan.c
1
2 /*
3 * fmt_scan.c -- format string interpretation
4 *
5 * $Id$
6 *
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
10 */
11
12 #include <h/mh.h>
13 #include <h/addrsbr.h>
14 #include <h/fmt_scan.h>
15 #include <h/tws.h>
16 #include <h/fmt_compile.h>
17
18 #ifdef TIME_WITH_SYS_TIME
19 # include <sys/time.h>
20 # include <time.h>
21 #else
22 # ifdef TM_IN_SYS_TIME
23 # include <sys/time.h>
24 # else
25 # include <time.h>
26 # endif
27 #endif
28
29 #define NFMTS MAXARGS
30
31 extern char *formataddr (); /* hook for custom address formatting */
32
33 #ifdef LBL
34 struct msgs *fmt_current_folder; /* current folder (set by main program) */
35 #endif
36
37 extern int fmt_norm; /* defined in sbr/fmt_def.c = AD_NAME */
38 struct mailname fmt_mnull;
39
40 /*
41 * static prototypes
42 */
43 static int match (char *, char *);
44 static char *get_x400_friendly (char *, char *, int);
45 static int get_x400_comp (char *, char *, char *, int);
46
47
48 /*
49 * test if string "sub" appears anywhere in
50 * string "str" (case insensitive).
51 */
52
53 static int
54 match (char *str, char *sub)
55 {
56 int c1, c2;
57 char *s1, *s2;
58
59 #ifdef LOCALE
60 while ((c1 = *sub)) {
61 c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1;
62 while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2))
63 ;
64 if (! c2)
65 return 0;
66 s1 = sub + 1; s2 = str;
67 while ((c1 = *s1++) && ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) == ((isalpha(c2 =*s2++) && isupper(c2)) ? tolower(c2) : c2))
68 ;
69 if (! c1)
70 return 1;
71 }
72 #else
73 while ((c1 = *sub)) {
74 while ((c2 = *str++) && (c1 | 040) != (c2 | 040))
75 ;
76 if (! c2)
77 return 0;
78 s1 = sub + 1; s2 = str;
79 while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040))
80 ;
81 if (! c1)
82 return 1;
83 }
84 #endif
85 return 1;
86 }
87
88 /*
89 * macros to format data
90 */
91 #define PUTDF(cp, num, wid, fill)\
92 if (cp + wid < ep) {\
93 if ((i = (num)) < 0)\
94 i = -(num);\
95 if ((c = (wid)) < 0)\
96 c = -c;\
97 sp = cp + c;\
98 do {\
99 *--sp = (i % 10) + '0';\
100 i /= 10;\
101 } while (i > 0 && sp > cp);\
102 if (i > 0)\
103 *sp = '?';\
104 else if ((num) < 0 && sp > cp)\
105 *--sp = '-';\
106 while (sp > cp)\
107 *--sp = fill;\
108 cp += c;\
109 }
110
111 #ifdef LOCALE
112 #define PUTSF(cp, str, wid, fill) {\
113 ljust = 0;\
114 if ((i = (wid)) < 0) {\
115 i = -i;\
116 ljust++;\
117 }\
118 if ((sp = (str))) {\
119 if (ljust) {\
120 c = strlen(sp);\
121 if (c > i)\
122 sp += c - i;\
123 else {\
124 while( --i >= c && cp < ep)\
125 *cp++ = fill;\
126 i++;\
127 }\
128 } else {\
129 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
130 sp++;\
131 }\
132 while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\
133 if (!iscntrl(c) && !isspace(c)) \
134 *cp++ = c;\
135 else {\
136 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
137 sp++;\
138 *cp++ = ' ';\
139 }\
140 }\
141 if (!ljust)\
142 while( --i >= 0 && cp < ep)\
143 *cp++ = fill;\
144 }
145
146 #define PUTS(cp, str) {\
147 if ((sp = (str))) {\
148 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
149 sp++;\
150 while((c = (unsigned char) *sp++) && cp < ep)\
151 if (!iscntrl(c) && !isspace(c)) \
152 *cp++ = c;\
153 else {\
154 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
155 sp++;\
156 *cp++ = ' ';\
157 }\
158 }\
159 }
160
161 #else /* LOCALE */
162 #define PUTSF(cp, str, wid, fill) {\
163 ljust = 0;\
164 if ((i = (wid)) < 0) {\
165 i = -i;\
166 ljust++;\
167 }\
168 if (sp = (str)) {\
169 if (ljust) {\
170 c = strlen(sp);\
171 if (c > i)\
172 sp += c - i;\
173 else {\
174 while( --i >= c && cp < ep)\
175 *cp++ = fill;\
176 i++;\
177 }\
178 } else {\
179 while ((c = *sp) && c <= 32)\
180 sp++;\
181 }\
182 while ((c = *sp++) && --i >= 0 && cp < ep)\
183 if (c > 32) \
184 *cp++ = c;\
185 else {\
186 while ((c = *sp) && c <= 32)\
187 sp++;\
188 *cp++ = ' ';\
189 }\
190 }\
191 if (!ljust)\
192 while( --i >= 0 && cp < ep)\
193 *cp++ = fill;\
194 }
195
196 #define PUTS(cp, str) {\
197 if (sp = (str)) {\
198 while ((c = *sp) && c <= 32)\
199 sp++;\
200 while( (c = *sp++) && cp < ep)\
201 if ( c > 32 ) \
202 *cp++ = c;\
203 else {\
204 while ( (c = *sp) && c <= 32 )\
205 sp++;\
206 *cp++ = ' ';\
207 }\
208 }\
209 }
210
211 #endif /* LOCALE */
212
213
214 static char *lmonth[] = { "January", "February","March", "April",
215 "May", "June", "July", "August",
216 "September","October", "November","December" };
217
218 static char *
219 get_x400_friendly (char *mbox, char *buffer, int buffer_len)
220 {
221 char given[BUFSIZ], surname[BUFSIZ];
222
223 if (mbox == NULL)
224 return NULL;
225 if (*mbox == '"')
226 mbox++;
227 if (*mbox != '/')
228 return NULL;
229
230 if (get_x400_comp (mbox, "/PN=", buffer, buffer_len)) {
231 for (mbox = buffer; (mbox = strchr(mbox, '.')); )
232 *mbox++ = ' ';
233
234 return buffer;
235 }
236
237 if (!get_x400_comp (mbox, "/S=", surname, sizeof(surname)))
238 return NULL;
239
240 if (get_x400_comp (mbox, "/G=", given, sizeof(given)))
241 snprintf (buffer, buffer_len, "%s %s", given, surname);
242 else
243 snprintf (buffer, buffer_len, "%s", surname);
244
245 return buffer;
246 }
247
248 static int
249 get_x400_comp (char *mbox, char *key, char *buffer, int buffer_len)
250 {
251 int idx;
252 char *cp;
253
254 if ((idx = stringdex (key, mbox)) < 0
255 || !(cp = strchr(mbox += idx + strlen (key), '/')))
256 return 0;
257
258 snprintf (buffer, buffer_len, "%*.*s", cp - mbox, cp - mbox, mbox);
259 return 1;
260 }
261
262 struct format *
263 fmt_scan (struct format *format, char *scanl, int width, int *dat)
264 {
265 char *cp, *ep, *sp;
266 char *savestr, *str = NULL;
267 char buffer[BUFSIZ], buffer2[BUFSIZ];
268 int i, c, ljust, n;
269 int value = 0;
270 time_t t;
271 struct format *fmt;
272 struct comp *comp;
273 struct tws *tws;
274 struct mailname *mn;
275
276 cp = scanl;
277 ep = scanl + width - 1;
278
279 for (fmt = format; fmt->f_type != FT_DONE; fmt++)
280 switch (fmt->f_type) {
281 case FT_PARSEADDR:
282 case FT_PARSEDATE:
283 fmt->f_comp->c_flags &= ~CF_PARSED;
284 break;
285 }
286
287 fmt = format;
288
289 while (cp < ep) {
290 switch (fmt->f_type) {
291
292 case FT_COMP:
293 PUTS (cp, fmt->f_comp->c_text);
294 break;
295 case FT_COMPF:
296 PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill);
297 break;
298
299 case FT_LIT:
300 sp = fmt->f_text;
301 while( (c = *sp++) && cp < ep)
302 *cp++ = c;
303 break;
304 case FT_LITF:
305 sp = fmt->f_text;
306 ljust = 0;
307 i = fmt->f_width;
308 if (i < 0) {
309 i = -i;
310 ljust++; /* XXX should do something with this */
311 }
312 while( (c = *sp++) && --i >= 0 && cp < ep)
313 *cp++ = c;
314 while( --i >= 0 && cp < ep)
315 *cp++ = fmt->f_fill;
316 break;
317
318 case FT_STR:
319 PUTS (cp, str);
320 break;
321 case FT_STRF:
322 PUTSF (cp, str, fmt->f_width, fmt->f_fill);
323 break;
324 case FT_STRFW:
325 adios (NULL, "internal error (FT_STRFW)");
326
327 case FT_NUM:
328 n = snprintf(cp, ep - cp, "%d", value);
329 if (n >= 0) cp += n;
330 break;
331 case FT_NUMF:
332 PUTDF (cp, value, fmt->f_width, fmt->f_fill);
333 break;
334
335 case FT_CHAR:
336 *cp++ = fmt->f_char;
337 break;
338
339 case FT_DONE:
340 goto finished;
341
342 case FT_IF_S:
343 if (!(value = (str && *str))) {
344 fmt += fmt->f_skip;
345 continue;
346 }
347 break;
348
349 case FT_IF_S_NULL:
350 if (!(value = (str == NULL || *str == 0))) {
351 fmt += fmt->f_skip;
352 continue;
353 }
354 break;
355
356 case FT_IF_V_EQ:
357 if (value != fmt->f_value) {
358 fmt += fmt->f_skip;
359 continue;
360 }
361 break;
362
363 case FT_IF_V_NE:
364 if (value == fmt->f_value) {
365 fmt += fmt->f_skip;
366 continue;
367 }
368 break;
369
370 case FT_IF_V_GT:
371 if (value <= fmt->f_value) {
372 fmt += fmt->f_skip;
373 continue;
374 }
375 break;
376
377 case FT_IF_MATCH:
378 if (!(value = (str && match (str, fmt->f_text)))) {
379 fmt += fmt->f_skip;
380 continue;
381 }
382 break;
383
384 case FT_V_MATCH:
385 if (str)
386 value = match (str, fmt->f_text);
387 else
388 value = 0;
389 break;
390
391 case FT_IF_AMATCH:
392 if (!(value = (str && uprf (str, fmt->f_text)))) {
393 fmt += fmt->f_skip;
394 continue;
395 }
396 break;
397
398 case FT_V_AMATCH:
399 value = uprf (str, fmt->f_text);
400 break;
401
402 case FT_S_NONNULL:
403 value = (str != NULL && *str != 0);
404 break;
405
406 case FT_S_NULL:
407 value = (str == NULL || *str == 0);
408 break;
409
410 case FT_V_EQ:
411 value = (fmt->f_value == value);
412 break;
413
414 case FT_V_NE:
415 value = (fmt->f_value != value);
416 break;
417
418 case FT_V_GT:
419 value = (fmt->f_value > value);
420 break;
421
422 case FT_GOTO:
423 fmt += fmt->f_skip;
424 continue;
425
426 case FT_NOP:
427 break;
428
429 case FT_LS_COMP:
430 str = fmt->f_comp->c_text;
431 break;
432 case FT_LS_LIT:
433 str = fmt->f_text;
434 break;
435 case FT_LS_GETENV:
436 if (!(str = getenv (fmt->f_text)))
437 str = "";
438 break;
439 case FT_LS_CFIND:
440 if (!(str = context_find (fmt->f_text)))
441 str = "";
442 break;
443
444 case FT_LS_DECODECOMP:
445 if (decode_rfc2047(fmt->f_comp->c_text, buffer2, sizeof(buffer2)))
446 str = buffer2;
447 else
448 str = fmt->f_comp->c_text;
449 break;
450
451 case FT_LS_DECODE:
452 if (str && decode_rfc2047(str, buffer2, sizeof(buffer2)))
453 str = buffer2;
454 break;
455
456 case FT_LS_TRIM:
457 if (str) {
458 char *xp;
459
460 strncpy(buffer, str, sizeof(buffer));
461 buffer[sizeof(buffer)-1] = '\0';
462 str = buffer;
463 while (isspace(*str))
464 str++;
465 ljust = 0;
466 if ((i = fmt->f_width) < 0) {
467 i = -i;
468 ljust++;
469 }
470
471 if (!ljust && i > 0 && strlen(str) > i)
472 str[i] = '\0';
473 xp = str;
474 xp += strlen(str) - 1;
475 while (xp > str && isspace(*xp))
476 *xp-- = '\0';
477 if (ljust && i > 0 && strlen(str) > i)
478 str += strlen(str) - i;
479 }
480 break;
481
482 case FT_LV_COMPFLAG:
483 value = (fmt->f_comp->c_flags & CF_TRUE) != 0;
484 break;
485 case FT_LV_COMP:
486 value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
487 break;
488 case FT_LV_LIT:
489 value = fmt->f_value;
490 break;
491 case FT_LV_DAT:
492 value = dat[fmt->f_value];
493 break;
494 case FT_LV_STRLEN:
495 if (str != NULL)
496 value = strlen(str);
497 else
498 value = 0;
499 break;
500 case FT_LV_CHAR_LEFT:
501 value = width - (cp - scanl);
502 break;
503 case FT_LV_PLUS_L:
504 value += fmt->f_value;
505 break;
506 case FT_LV_MINUS_L:
507 value = fmt->f_value - value;
508 break;
509 case FT_LV_DIVIDE_L:
510 if (fmt->f_value)
511 value = value / fmt->f_value;
512 else
513 value = 0;
514 break;
515 case FT_LV_MODULO_L:
516 if (fmt->f_value)
517 value = value % fmt->f_value;
518 else
519 value = 0;
520 break;
521 case FT_SAVESTR:
522 savestr = str;
523 break;
524
525 case FT_LV_SEC:
526 value = fmt->f_comp->c_tws->tw_sec;
527 break;
528 case FT_LV_MIN:
529 value = fmt->f_comp->c_tws->tw_min;
530 break;
531 case FT_LV_HOUR:
532 value = fmt->f_comp->c_tws->tw_hour;
533 break;
534 case FT_LV_MDAY:
535 value = fmt->f_comp->c_tws->tw_mday;
536 break;
537 case FT_LV_MON:
538 value = fmt->f_comp->c_tws->tw_mon + 1;
539 break;
540 case FT_LS_MONTH:
541 str = tw_moty[fmt->f_comp->c_tws->tw_mon];
542 break;
543 case FT_LS_LMONTH:
544 str = lmonth[fmt->f_comp->c_tws->tw_mon];
545 break;
546 case FT_LS_ZONE:
547 str = dtwszone (fmt->f_comp->c_tws);
548 break;
549 case FT_LV_YEAR:
550 value = fmt->f_comp->c_tws->tw_year;
551 break;
552 case FT_LV_WDAY:
553 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
554 set_dotw (tws);
555 value = tws->tw_wday;
556 break;
557 case FT_LS_DAY:
558 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
559 set_dotw (tws);
560 str = tw_dotw[tws->tw_wday];
561 break;
562 case FT_LS_WEEKDAY:
563 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
564 set_dotw (tws);
565 str = tw_ldotw[tws->tw_wday];
566 break;
567 case FT_LV_YDAY:
568 value = fmt->f_comp->c_tws->tw_yday;
569 break;
570 case FT_LV_ZONE:
571 value = fmt->f_comp->c_tws->tw_zone;
572 break;
573 case FT_LV_CLOCK:
574 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
575 value = dmktime(fmt->f_comp->c_tws);
576 break;
577 case FT_LV_RCLOCK:
578 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
579 value = dmktime(fmt->f_comp->c_tws);
580 value = time((time_t *) 0) - value;
581 break;
582 case FT_LV_DAYF:
583 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
584 set_dotw (tws);
585 switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) {
586 case TW_SEXP:
587 value = 1; break;
588 case TW_SIMP:
589 value = 0; break;
590 default:
591 value = -1; break;
592 }
593 case FT_LV_ZONEF:
594 if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) == TW_SZEXP)
595 value = 1;
596 else
597 value = -1;
598 break;
599 case FT_LV_DST:
600 value = fmt->f_comp->c_tws->tw_flags & TW_DST;
601 break;
602 case FT_LS_822DATE:
603 str = dasctime (fmt->f_comp->c_tws , TW_ZONE);
604 break;
605 case FT_LS_PRETTY:
606 str = dasctime (fmt->f_comp->c_tws, TW_NULL);
607 break;
608
609 case FT_LS_PERS:
610 str = fmt->f_comp->c_mn->m_pers;
611 break;
612 case FT_LS_MBOX:
613 str = fmt->f_comp->c_mn->m_mbox;
614 break;
615 case FT_LS_HOST:
616 str = fmt->f_comp->c_mn->m_host;
617 break;
618 case FT_LS_PATH:
619 str = fmt->f_comp->c_mn->m_path;
620 break;
621 case FT_LS_GNAME:
622 str = fmt->f_comp->c_mn->m_gname;
623 break;
624 case FT_LS_NOTE:
625 str = fmt->f_comp->c_mn->m_note;
626 break;
627 case FT_LS_822ADDR:
628 str = adrformat( fmt->f_comp->c_mn );
629 break;
630 case FT_LV_HOSTTYPE:
631 value = fmt->f_comp->c_mn->m_type;
632 break;
633 case FT_LV_INGRPF:
634 value = fmt->f_comp->c_mn->m_ingrp;
635 break;
636 case FT_LV_NOHOSTF:
637 value = fmt->f_comp->c_mn->m_nohost;
638 break;
639 case FT_LS_ADDR:
640 case FT_LS_FRIENDLY:
641 if ((mn = fmt->f_comp->c_mn) == &fmt_mnull) {
642 str = fmt->f_comp->c_text;
643 break;
644 }
645 if (fmt->f_type == FT_LS_ADDR)
646 goto unfriendly;
647 if ((str = mn->m_pers) == NULL) {
648 if ((str = mn->m_note)) {
649 strncpy (buffer, str, sizeof(buffer));
650 buffer[sizeof(buffer)-1] = '\0';
651 str = buffer;
652 if (*str == '(')
653 str++;
654 sp = str + strlen(str) - 1;
655 if (*sp == ')') {
656 *sp-- = '\0';
657 while (sp >= str)
658 if (*sp == ' ')
659 *sp-- = '\0';
660 else
661 break;
662 }
663 } else if (!(str = get_x400_friendly (mn->m_mbox,
664 buffer, sizeof(buffer)))) {
665 unfriendly: ;
666 switch (mn->m_type) {
667 case LOCALHOST:
668 str = mn->m_mbox;
669 break;
670 case UUCPHOST:
671 snprintf (buffer, sizeof(buffer), "%s!%s",
672 mn->m_host, mn->m_mbox);
673 str = buffer;
674 break;
675 default:
676 if (mn->m_mbox) {
677 snprintf (buffer, sizeof(buffer), "%s@%s",
678 mn->m_mbox, mn->m_host);
679 str= buffer;
680 }
681 else
682 str = mn->m_text;
683 break;
684 }
685 }
686 }
687 break;
688
689
690 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
691 case FT_LS_UNQUOTE:
692 if (str) {
693 int m;
694 strncpy(buffer, str, sizeof(buffer));
695 /* strncpy doesn't NUL-terminate if it fills the buffer */
696 buffer[sizeof(buffer)-1] = '\0';
697 str = buffer;
698
699 /* we will parse from buffer to buffer2 */
700 n = 0; /* n is the input position in str */
701 m = 0; /* m is the ouput position in buffer2 */
702
703 while ( str[n] != '\0') {
704 switch ( str[n] ) {
705 case '\\':
706 n++;
707 if ( str[n] != '\0')
708 buffer2[m++] = str[n++];
709 break;
710 case '"':
711 n++;
712 break;
713 default:
714 buffer2[m++] = str[n++];
715 break;
716 }
717 }
718 buffer2[m] = '\0';
719 str = buffer2;
720 }
721 break;
722
723 case FT_LOCALDATE:
724 comp = fmt->f_comp;
725 if ((t = comp->c_tws->tw_clock) == 0)
726 t = dmktime(comp->c_tws);
727 tws = dlocaltime(&t);
728 *comp->c_tws = *tws;
729 break;
730
731 case FT_GMTDATE:
732 comp = fmt->f_comp;
733 if ((t = comp->c_tws->tw_clock) == 0)
734 t = dmktime(comp->c_tws);
735 tws = dgmtime(&t);
736 *comp->c_tws = *tws;
737 break;
738
739 case FT_PARSEDATE:
740 comp = fmt->f_comp;
741 if (comp->c_flags & CF_PARSED)
742 break;
743 if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
744 *comp->c_tws = *tws;
745 comp->c_flags &= ~CF_TRUE;
746 } else if ((comp->c_flags & CF_DATEFAB) == 0) {
747 memset ((char *) comp->c_tws, 0, sizeof *comp->c_tws);
748 comp->c_flags = CF_TRUE;
749 }
750 comp->c_flags |= CF_PARSED;
751 break;
752
753 case FT_FORMATADDR:
754 /* hook for custom address list formatting (see replsbr.c) */
755 str = formataddr (savestr, str);
756 break;
757
758 case FT_PUTADDR:
759 /* output the str register as an address component,
760 * splitting it into multiple lines if necessary. The
761 * value reg. contains the max line length. The lit.
762 * field may contain a string to prepend to the result
763 * (e.g., "To: ")
764 */
765 {
766 char *lp, *lastb;
767 int indent, wid, len;
768
769 lp = str;
770 wid = value;
771 len = strlen (str);
772 sp = fmt->f_text;
773 indent = strlen (sp);
774 wid -= indent;
775 while( (c = *sp++) && cp < ep)
776 *cp++ = c;
777 while (len > wid) {
778 /* try to break at a comma; failing that, break at a
779 * space.
780 */
781 lastb = 0; sp = lp + wid;
782 while (sp > lp && (c = *--sp) != ',') {
783 if (! lastb && isspace(c))
784 lastb = sp - 1;
785 }
786 if (sp == lp) {
787 if (! (sp = lastb)) {
788 sp = lp + wid - 1;
789 while (*sp && *sp != ',' && !isspace(*sp))
790 sp++;
791 if (*sp != ',')
792 sp--;
793 }
794 }
795 len -= sp - lp + 1;
796 while (cp < ep && lp <= sp)
797 *cp++ = *lp++;
798 while (isspace(*lp))
799 lp++, len--;
800 if (*lp) {
801 if (cp < ep)
802 *cp++ = '\n';
803 for (i=indent; cp < ep && i > 0; i--)
804 *cp++ = ' ';
805 }
806 }
807 PUTS (cp, lp);
808 }
809 break;
810
811 case FT_PARSEADDR:
812 comp = fmt->f_comp;
813 if (comp->c_flags & CF_PARSED)
814 break;
815 if (comp->c_mn != &fmt_mnull)
816 mnfree (comp->c_mn);
817 if ((sp = comp->c_text) && (sp = getname(sp)) &&
818 (mn = getm (sp, NULL, 0, fmt_norm, NULL))) {
819 comp->c_mn = mn;
820 while (getname(""))
821 ;
822 comp->c_flags |= CF_PARSED;
823 } else {
824 while (getname("")) /* XXX */
825 ;
826 comp->c_mn = &fmt_mnull;
827 }
828 break;
829
830 case FT_MYMBOX:
831 /*
832 * if there's no component, we say true. Otherwise we
833 * say "true" only if we can parse the address and it
834 * matches one of our addresses.
835 */
836 comp = fmt->f_comp;
837 if (comp->c_mn != &fmt_mnull)
838 mnfree (comp->c_mn);
839 if ((sp = comp->c_text) && (sp = getname(sp)) &&
840 (mn = getm (sp, NULL, 0, AD_NAME, NULL))) {
841 comp->c_mn = mn;
842 if (ismymbox(mn))
843 comp->c_flags |= CF_TRUE;
844 else
845 comp->c_flags &= ~CF_TRUE;
846 while ((sp = getname(sp)))
847 if ((comp->c_flags & CF_TRUE) == 0 &&
848 (mn = getm (sp, NULL, 0, AD_NAME, NULL)))
849 if (ismymbox(mn))
850 comp->c_flags |= CF_TRUE;
851 } else {
852 while (getname("")) /* XXX */
853 ;
854 if (comp->c_text == 0)
855 comp->c_flags |= CF_TRUE;
856 else
857 comp->c_flags &= ~CF_TRUE;
858 comp->c_mn = &fmt_mnull;
859 }
860 break;
861
862 case FT_ADDTOSEQ:
863 #ifdef LBL
864 /* If we're working on a folder (as opposed to a file), add the
865 * current msg to sequence given in literal field. Don't
866 * disturb string or value registers.
867 */
868 if (fmt_current_folder)
869 seq_addmsg(fmt_current_folder, fmt->f_text, dat[0], -1);
870 #endif
871 break;
872 }
873 fmt++;
874 }
875 #ifndef JLR
876 finished:;
877 if (cp[-1] != '\n')
878 *cp++ = '\n';
879 *cp = 0;
880 return ((struct format *)0);
881 #else /* JLR */
882 if (cp[-1] != '\n')
883 *cp++ = '\n';
884 while (fmt->f_type != FT_DONE)
885 fmt++;
886
887 finished:;
888 *cp = '\0';
889 return (fmt->f_value ? ++fmt : (struct format *) 0);
890
891 #endif /* JLR */
892 }