When compiling format strings, nmh attempts to avoid multiple parsing
[mmh] / sbr / fmt_scan.c
index 2086a94..0a2397b 100644 (file)
@@ -3,14 +3,29 @@
  * fmt_scan.c -- format string interpretation
  *
  * $Id$
+ *
+ * This code is Copyright (c) 2002, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
  */
 
 #include <h/mh.h>
 #include <h/addrsbr.h>
 #include <h/fmt_scan.h>
-#include <zotnet/tws/tws.h>
+#include <h/tws.h>
 #include <h/fmt_compile.h>
 
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef TM_IN_SYS_TIME
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
 #define        NFMTS MAXARGS
 
 extern char *formataddr ();    /* hook for custom address formatting */
@@ -234,7 +249,7 @@ get_x400_friendly (char *mbox, char *buffer, int buffer_len)
        return NULL;
 
     if (get_x400_comp (mbox, "/PN=", buffer, buffer_len)) {
-       for (mbox = buffer; mbox = strchr(mbox, '.'); )
+       for (mbox = buffer; (mbox = strchr(mbox, '.')); )
            *mbox++ = ' ';
 
        return buffer;
@@ -281,6 +296,15 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
 
     cp = scanl;
     ep = scanl + width - 1;
+
+    for (fmt = format; fmt->f_type != FT_DONE; fmt++)
+       switch (fmt->f_type) {
+       case FT_PARSEADDR:
+       case FT_PARSEDATE:
+           fmt->f_comp->c_flags &= ~CF_PARSED;
+           break;
+       }
+
     fmt = format;
 
     while (cp < ep) {
@@ -475,7 +499,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            break;
 
        case FT_LV_COMPFLAG:
-           value = fmt->f_comp->c_flags;
+           value = (fmt->f_comp->c_flags & CF_TRUE) != 0;
            break;
        case FT_LV_COMP:
            value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
@@ -636,7 +660,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            }
            if (fmt->f_type == FT_LS_ADDR)
                goto unfriendly;
-           if ((str = mn->m_pers) == NULL)
+           if ((str = mn->m_pers) == NULL) {
                if ((str = mn->m_note)) {
                    strncpy (buffer, str, sizeof(buffer));
                    str = buffer;
@@ -674,6 +698,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
                        break;
                  }
                }
+           }
            break;
 
        case FT_LOCALDATE:
@@ -694,13 +719,16 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
 
        case FT_PARSEDATE:
            comp = fmt->f_comp;
+           if (comp->c_flags & CF_PARSED)
+               break;
            if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
                *comp->c_tws = *tws;
-               comp->c_flags = 0;
-           } else if (comp->c_flags >= 0) {
+               comp->c_flags &= ~CF_TRUE;
+           } else if ((comp->c_flags & CF_DATEFAB) == 0) {
                memset ((char *) comp->c_tws, 0, sizeof *comp->c_tws);
-               comp->c_flags = 1;
+               comp->c_flags = CF_TRUE;
            }
+           comp->c_flags |= CF_PARSED;
            break;
 
        case FT_FORMATADDR:
@@ -729,24 +757,33 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
                *cp++ = c;
            while (len > wid) {
                /* try to break at a comma; failing that, break at a
-                * space, failing that, just split the line.
+                * space.
                 */
                lastb = 0; sp = lp + wid;
                while (sp > lp && (c = *--sp) != ',') {
                    if (! lastb && isspace(c))
                        lastb = sp - 1;
                }
-               if (sp == lp)
-                   if (! (sp = lastb))
+               if (sp == lp) {
+                   if (! (sp = lastb)) {
                        sp = lp + wid - 1;
+                       while (*sp && *sp != ',' && !isspace(*sp))
+                           sp++;
+                       if (*sp != ',')
+                           sp--;
+                   }
+               }
                len -= sp - lp + 1;
                while (cp < ep && lp <= sp)
                    *cp++ = *lp++;
-               *cp++ = '\n';
-               for (i=indent; cp < ep && i > 0; i--)
-                   *cp++ = ' ';
                while (isspace(*lp))
                    lp++, len--;
+               if (*lp) {
+                   if (cp < ep)
+                       *cp++ = '\n';
+                   for (i=indent; cp < ep && i > 0; i--)
+                       *cp++ = ' ';
+               }
            }
            PUTS (cp, lp);
            }
@@ -754,6 +791,8 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
 
        case FT_PARSEADDR:
            comp = fmt->f_comp;
+           if (comp->c_flags & CF_PARSED)
+               break;
            if (comp->c_mn != &fmt_mnull)
                mnfree (comp->c_mn);
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
@@ -761,6 +800,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
                comp->c_mn = mn;
                while (getname(""))
                    ;
+               comp->c_flags |= CF_PARSED;
            } else {
                while (getname(""))             /* XXX */
                    ;
@@ -780,15 +820,22 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
                (mn = getm (sp, NULL, 0, AD_NAME, NULL))) {
                comp->c_mn = mn;
-               comp->c_flags = ismymbox(mn);
+               if (ismymbox(mn))
+                   comp->c_flags |= CF_TRUE;
+               else
+                   comp->c_flags &= ~CF_TRUE;
                while ((sp = getname(sp)))
-                   if (comp->c_flags == 0 &&
+                   if ((comp->c_flags & CF_TRUE) == 0 &&
                        (mn = getm (sp, NULL, 0, AD_NAME, NULL)))
-                       comp->c_flags |= ismymbox(mn);
+                       if (ismymbox(mn))
+                           comp->c_flags |= CF_TRUE;
            } else {
                while (getname(""))             /* XXX */
                    ;
-               comp->c_flags = (comp->c_text == 0);
+               if (comp->c_text == 0)
+                   comp->c_flags |= CF_TRUE;
+               else
+                   comp->c_flags &= ~CF_TRUE;
                comp->c_mn = &fmt_mnull;
            }
            break;