nmh-workers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nmh-workers] [PATCH] mhbuild: implement #on/#off/#pop, and the -[no]dir


From: Paul Fox
Subject: [Nmh-workers] [PATCH] mhbuild: implement #on/#off/#pop, and the -[no]directives switch
Date: Thu, 31 May 2012 14:17:16 -0400

ken wrote:
 > > > I'm fine with the #on/#off directives; I can see their usefulness.
 > > > Send in the code and we'll add it.
 > >
 > >i'm looking at it.  no promises!  :-)
 > 
 > One additional thing occurs to me.
 > 
 > We have a few tools right now which put in mhbuild directives in drafts
 > for you (forw -mime, the attach WhatNow? command).  It occurs to me that
 > instead of #on/#off, maybe it should really be something like:
 > 
 > #push on
 > <mhbuild directives>
 > #pop
 > 
 > #push off would also work.  You get the idea ... that way automatically
 > inserted directives wouldn't mess up your current process/no process state.

i've implemented this as #on, #off, and #pop.  i have no attachment to
the names, or whether there should be a "push" in front of "on" or
"off".  it's lightly tested -- there may well be corner cases in
complicated drafts that will get it confused.  it works for my simple
usages.  comments/suggestions welcome.

paul
---
 man/mhbuild.man  |   31 +++++++++++++++++--
 uip/mhbuild.c    |   57 +++++++++++++++++++++--------------
 uip/mhbuildsbr.c |   86 ++++++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 129 insertions(+), 45 deletions(-)

diff --git a/man/mhbuild.man b/man/mhbuild.man
index cd7e7fd..7ee13a2 100644
--- a/man/mhbuild.man
+++ b/man/mhbuild.man
@@ -12,6 +12,7 @@ mhbuild \- translate MIME composition draft
 .RB [ \-list " | " \-nolist ]
 .RB [ \-realsize " | " \-norealsize ]
 .RB [ \-headers " | " \-noheaders ]
+.RB [ \-directives " | " \-nodirectives ]
 .RB [ \-ebcdicsafe " | " \-noebcdicsafe ]
 .RB [ \-rfc934mode " | " \-norfc934mode ]
 .RB [ \-contentid " | " \-nocontentid ]
@@ -115,12 +116,36 @@ than one line, e.g.,
 .fi
 .RE
 .PP
-There are four kinds of directives: \*(lqtype\*(rq directives, which
+There are five kinds of directives: \*(lqtype\*(rq directives, which
 name the type and subtype of the content; \*(lqexternal-type\*(rq
 directives, which also name the type and subtype of the content; the
 \*(lqmessage\*(rq directive (#forw), which is used to forward one or
-more messages; and, the \*(lqbegin\*(rq directive (#begin), which is
-used to create a multipart content.
+more messages; the \*(lqbegin\*(rq directive (#begin), which is
+used to create a multipart content; and the \*(lqon/off/pop\*(rq 
+directives (#on, #off, #pop) which control whether any other
+directives are honored at all.
+.PP
+The 
+.B \-directives
+switch allows control over whether mhbuild will honor any of the
+\*(lq#\*(rq-directives.  This can also be affected with the #on or
+#off directives, and #pop, which restores the state of processing to
+that preceding the most recent #on or #off.  (The #on, #off, and #pop
+directives are always honored, of course.) This allows inclusion of
+plain text which looks like mhbuild directives, without causing
+errors:
+.PP
+.RS 5
+.nf
+#off
+#include <stdio.h>
+
+printf("Hello, World!);
+#pop
+.fi
+.RE
+.PP
+Currently the stack depth for the #on/off/pop directives is 32.
 .PP
 The \*(lqtype\*(rq directive is used to directly specify the type and
 subtype of a content.  You may only specify discrete types in this manner
diff --git a/uip/mhbuild.c b/uip/mhbuild.c
index ad674f4..020512d 100644
--- a/uip/mhbuild.c
+++ b/uip/mhbuild.c
@@ -25,43 +25,47 @@ static struct swit switches[] = {
     { "check", 0 },
 #define        NCHECKSW                1
     { "nocheck", 0 },
-#define        EBCDICSW                2
+#define        DIRECTIVES              2
+    { "directives", 0 },
+#define        NDIRECTIVES             3
+    { "nodirectives", 0 },
+#define        EBCDICSW                4
     { "ebcdicsafe", 0 },
-#define        NEBCDICSW               3
+#define        NEBCDICSW               5
     { "noebcdicsafe", 0 },
-#define        HEADSW                  4
+#define        HEADSW                  6
     { "headers", 0 },
-#define        NHEADSW                 5
+#define        NHEADSW                 7
     { "noheaders", 0 },
-#define        LISTSW                  6
+#define        LISTSW                  8
     { "list", 0 },
-#define        NLISTSW                 7
+#define        NLISTSW                 9
     { "nolist", 0 },
-#define        SIZESW                  8
+#define        SIZESW                 10
     { "realsize", 0 },
-#define        NSIZESW                 9
+#define        NSIZESW                11
     { "norealsize", 0 },
-#define        RFC934SW               10
+#define        RFC934SW               12
     { "rfc934mode", 0 },
-#define        NRFC934SW              11
+#define        NRFC934SW              13
     { "norfc934mode", 0 },
-#define        VERBSW                 12
+#define        VERBSW                 14
     { "verbose", 0 },
-#define        NVERBSW                13
+#define        NVERBSW                15
     { "noverbose", 0 },
-#define        RCACHESW               14
+#define        RCACHESW               16
     { "rcache policy", 0 },
-#define        WCACHESW               15
+#define        WCACHESW               17
     { "wcache policy", 0 },
-#define        CONTENTIDSW            16
+#define        CONTENTIDSW            18
     { "contentid", 0 },
-#define        NCONTENTIDSW           17
+#define        NCONTENTIDSW           19
     { "nocontentid", 0 },
-#define VERSIONSW              18
+#define VERSIONSW              20
     { "version", 0 },
-#define        HELPSW                 19
+#define        HELPSW                 21
     { "help", 0 },
-#define        DEBUGSW                20
+#define        DEBUGSW                22
     { "debug", -5 },
     { NULL, 0 }
 };
@@ -96,7 +100,7 @@ static int unlink_outfile = 0;
 static void unlink_done (int) NORETURN;
 
 /* mhbuildsbr.c */
-CT build_mime (char *);
+CT build_mime (char *, int);
 int output_message (CT, char *);
 int output_message_fp (CT, FILE *, char*);
 
@@ -110,7 +114,7 @@ void free_content (CT);
 int
 main (int argc, char **argv)
 {
-    int sizesw = 1, headsw = 1;
+    int sizesw = 1, headsw = 1, directives = 1;
     int *icachesw;
     char *cp, buf[BUFSIZ];
     char buffer[BUFSIZ], *compfile = NULL;
@@ -198,6 +202,13 @@ main (int argc, char **argv)
                headsw = 0;
                continue;
 
+           case DIRECTIVES:
+               directives = 1;
+               continue;
+           case NDIRECTIVES:
+               directives = 0;
+               continue;
+
            case LISTSW:
                listsw++;
                continue;
@@ -306,7 +317,7 @@ main (int argc, char **argv)
        unlink_infile = 1;
 
        /* build the content structures for MIME message */
-       ct = build_mime (infile);
+       ct = build_mime (infile, directives);
        cts[0] = ct;
        cts[1] = NULL;
 
@@ -340,7 +351,7 @@ main (int argc, char **argv)
      */
 
     /* build the content structures for MIME message */
-    ct = build_mime (compfile);
+    ct = build_mime (compfile, directives);
     cts[0] = ct;
     cts[1] = NULL;
 
diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c
index fd6a974..8a47dd5 100644
--- a/uip/mhbuildsbr.c
+++ b/uip/mhbuildsbr.c
@@ -72,7 +72,7 @@ void free_encoding (CT, int);
 /*
  * prototypes
  */
-CT build_mime (char *);
+CT build_mime (char *, int);
 
 /*
  * static prototypes
@@ -87,6 +87,38 @@ static int build_headers (CT);
 static char *calculate_digest (CT, int);
 
 
+static unsigned char directives_stack[32];
+static unsigned int directives_index;
+
+static int do_direct(void)
+{
+    return directives_stack[directives_index];
+}
+
+static void directive_onoff(int onoff)
+{
+    if (directives_index >= sizeof(directives_stack)) {
+       fprintf(stderr, "mhbuild: #on/off overflow, continuing\n");
+       return;
+    }
+    directives_stack[++directives_index] = onoff;
+}
+
+static void directive_init(int onoff)
+{
+    directives_index = 0;
+    directives_stack[0] = onoff;
+}
+
+static void directive_pop(void)
+{
+    if (directives_index > 0)
+       directives_index--;
+    else
+       fprintf(stderr, "mhbuild: #pop underflow, continuing\n");
+    
+}
+
 /*
  * Main routine for translating composition file
  * into valid MIME message.  It translates the draft
@@ -97,7 +129,7 @@ static char *calculate_digest (CT, int);
  */
 
 CT
-build_mime (char *infile)
+build_mime (char *infile, int directives)
 {
     int        compnum, state;
     char buf[BUFSIZ], name[NAMESZ];
@@ -107,6 +139,8 @@ build_mime (char *infile)
     CT ct;
     FILE *in;
 
+    directive_init(directives);
+
     umask (~m_gmprot ());
 
     /* open the composition draft */
@@ -327,20 +361,34 @@ static char *
 fgetstr (char *s, int n, FILE *stream)
 {
     char *cp, *ep;
+    int o_n = n;
+
+    while(1) {
+       for (ep = (cp = s) + o_n; cp < ep; ) {
+           int i;
 
-    for (ep = (cp = s) + n; cp < ep; ) {
-       int i;
+           if (!fgets (cp, n, stream))
+               return (cp != s ? s : NULL);
 
-       if (!fgets (cp, n, stream))
-           return (cp != s ? s : NULL);
-       if (cp == s && *cp != '#')
-           return s;
+           if (cp == s && *cp != '#')
+               return s;
 
-       cp += (i = strlen (cp)) - 1;
-       if (i <= 1 || *cp-- != '\n' || *cp != '\\')
+           cp += (i = strlen (cp)) - 1;
+           if (i <= 1 || *cp-- != '\n' || *cp != '\\')
+               break;
+           *cp = '\0';
+           n -= (i - 2);
+       }
+
+       if (strcmp(s, "#on\n") == 0) {
+           directive_onoff(1);
+       } else if (strcmp(s, "#off\n") == 0) {
+           directive_onoff(0);
+       } else if (strcmp(s, "#pop\n") == 0) {
+           directive_pop();
+       } else {
            break;
-       *cp = '\0';
-       n -= (i - 2);
+       }
     }
 
     return s;
@@ -367,7 +415,7 @@ user_content (FILE *in, char *file, char *buf, CT *ctp)
     CT ct;
     CE ce;
 
-    if (buf[0] == '\n' || strcmp (buf, "#\n") == 0) {
+    if (buf[0] == '\n' || (do_direct() && strcmp (buf, "#\n") == 0)) {
        *ctp = NULL;
        return OK;
     }
@@ -392,7 +440,7 @@ user_content (FILE *in, char *file, char *buf, CT *ctp)
      * 2) begins with "##"             (implicit directive)
      * 3) begins with "#<"
      */
-    if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
+    if (!do_direct() || buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
        int headers;
        int inlineD;
        long pos;
@@ -407,7 +455,7 @@ user_content (FILE *in, char *file, char *buf, CT *ctp)
        ce->ce_file = add (cp, NULL);
        ce->ce_unlink = 1;
 
-       if (buf[0] == '#' && buf[1] == '<') {
+       if (do_direct() && (buf[0] == '#' && buf[1] == '<')) {
            strncpy (content, buf + 2, sizeof(content));
            inlineD = 1;
            goto rock_and_roll;
@@ -418,11 +466,11 @@ user_content (FILE *in, char *file, char *buf, CT *ctp)
        /* the directive is implicit */
        strncpy (content, "text/plain", sizeof(content));
        headers = 0;
-       strncpy (buffer, buf[0] != '#' ? buf : buf + 1, sizeof(buffer));
+       strncpy (buffer, (!do_direct() || buf[0] != '#') ? buf : buf + 1, 
sizeof(buffer));
        for (;;) {
            int i;
 
-           if (headers >= 0 && uprf (buffer, DESCR_FIELD)
+           if (headers >= 0 && do_direct() && uprf (buffer, DESCR_FIELD)
                && buffer[i = strlen (DESCR_FIELD)] == ':') {
                headers = 1;
 
@@ -445,7 +493,7 @@ again_descr:
                }
            }
 
-           if (headers >= 0 && uprf (buffer, DISPO_FIELD)
+           if (headers >= 0 && do_direct() && uprf (buffer, DISPO_FIELD)
                && buffer[i = strlen (DISPO_FIELD)] == ':') {
                headers = 1;
 
@@ -476,7 +524,7 @@ rock_and_roll:
            pos = ftell (in);
            if ((cp = fgetstr (buffer, sizeof(buffer) - 1, in)) == NULL)
                break;
-           if (buffer[0] == '#') {
+           if (do_direct() && buffer[0] == '#') {
                char *bp;
 
                if (buffer[1] != '#')
-- 
1.7.4.1


=---------------------
 paul fox, address@hidden (arlington, ma, where it's 75.9 degrees)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]