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