]> diplodocus.org Git - nmh/blobdiff - uip/mhlsbr.c
Remove trailing spaces from lines in man pages.
[nmh] / uip / mhlsbr.c
index 81704d0ed58f9567dc9470ee814ca70b80957996..f07d786dae3dbcd53123d150d2ec1963b770545f 100644 (file)
@@ -93,7 +93,9 @@ DEFINE_SWITCH_ARRAY(MHL, mhlswitches);
 #define        NONEWLINE   0x020000    /* don't write trailing newline      */
 #define NOWRAP      0x040000   /* Don't wrap lines ever             */
 #define FMTFILTER   0x080000   /* Filter through format filter      */
-#define        LBITS   "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017RTRIM\021SPLIT\022NONEWLINE\023NOWRAP\024FMTFILTER"
+#define INVISIBLE   0x100000   /* count byte in display columns?    */
+#define FORCE7BIT   0x200000   /* don't display 8-bit bytes         */
+#define        LBITS   "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017RTRIM\021SPLIT\022NONEWLINE\023NOWRAP\024FMTFILTER\025INVISIBLE\026FORCE7BIT"
 #define        GFLAGS  (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS | SPLIT | NOWRAP)
 
 /*
@@ -161,7 +163,7 @@ struct mcomp {
     int c_width;               /* width of field          */
     int c_cwidth;              /* width of component      */
     int c_length;              /* length in lines         */
-    long c_flags;
+    unsigned long c_flags;
     struct mcomp *c_next;
 };
 
@@ -180,7 +182,7 @@ static struct mcomp holder = {
 
 struct pair {
     char *p_name;
-    long p_flags;
+    unsigned long p_flags;
 };
 
 static struct pair pairs[] = {
@@ -203,8 +205,8 @@ static struct pair pairs[] = {
 
 struct triple {
     char *t_name;
-    long t_on;
-    long t_off;
+    unsigned long t_on;
+    unsigned long t_off;
 };
 
 static struct triple triples[] = {
@@ -304,13 +306,6 @@ static char delim4[] = "\n------------------------------\n\n";
 
 static FILE *(*mhl_action) () = (FILE *(*) ()) 0;
 
-/*
- * Redefine a couple of functions.
- * These are undefined later in the code.
- */
-#define        adios mhladios
-#define        done  mhldone
-
 /*
  * prototypes
  */
@@ -322,14 +317,14 @@ static char *parse (void);
 static void process (char *, char *, int, int);
 static void mhlfile (FILE *, char *, int, int);
 static int mcomp_flags (char *);
-static char *mcomp_add (long, char *, char *);
+static char *mcomp_add (unsigned long, char *, char *);
 static void mcomp_format (struct mcomp *, struct mcomp *);
 static struct mcomp *add_queue (struct mcomp **, struct mcomp **, char *, char *, int);
 static void free_queue (struct mcomp **, struct mcomp **);
 static void putcomp (struct mcomp *, struct mcomp *, int);
-static char *oneline (char *, long);
-static void putstr (char *, long);
-static void putch (char, long);
+static char *oneline (char *, unsigned long);
+static void putstr (char *, unsigned long);
+static void putch (char, unsigned long);
 static void intrser (int);
 static void pipeser (int);
 static void quitser (int);
@@ -365,17 +360,21 @@ mhl (int argc, char **argv)
            switch (smatch (++cp, mhlswitches)) {
                case AMBIGSW: 
                    ambigsw (cp, mhlswitches);
-                   done (1);
+                   mhldone (1);
+                   /* FALLTHRU */
                case UNKWNSW: 
-                   adios (NULL, "-%s unknown\n", cp);
+                   mhladios (NULL, "-%s unknown\n", cp);
+                   /* FALLTHRU */
 
                case HELPSW: 
                    snprintf (buf, sizeof(buf), "%s [switches] [files ...]", invo_name);
                    print_help (buf, mhlswitches, 1);
-                   done (0);
+                   mhldone (0);
+                   /* FALLTHRU */
                case VERSIONSW:
                    print_version(invo_name);
-                   done (0);
+                   mhldone (0);
+                   /* FALLTHRU */
 
                case BELLSW: 
                    bellflg = 1;
@@ -393,23 +392,23 @@ mhl (int argc, char **argv)
 
                case FOLDSW: 
                    if (!(folder = *argp++) || *folder == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    continue;
                case FORMSW: 
                    if (!(form = *argp++) || *form == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    continue;
 
                case SLEEPSW:
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    else
                        sleepsw = atoi (cp);/* ZERO ok! */
                    continue;
 
                case PROGSW:
                    if (!(moreproc = *argp++) || *moreproc == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    continue;
                case NPROGSW:
                    nomore++;
@@ -417,7 +416,7 @@ mhl (int argc, char **argv)
 
                case FMTPROCSW:
                    if (!(formatproc = *argp++) || *formatproc == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    continue;
                case NFMTPROCSW:
                    formatproc = NULL;
@@ -425,36 +424,37 @@ mhl (int argc, char **argv)
 
                case LENSW: 
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    else if ((length = atoi (cp)) < 1)
-                       adios (NULL, "bad argument %s %s", argp[-2], cp);
+                       mhladios (NULL, "bad argument %s %s", argp[-2], cp);
                    continue;
                case WIDTHSW: 
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    else if ((width = atoi (cp)) < 1)
-                       adios (NULL, "bad argument %s %s", argp[-2], cp);
+                       mhladios (NULL, "bad argument %s %s", argp[-2], cp);
                    continue;
 
                case DGSTSW: 
                    if (!(digest = *argp++) || *digest == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    continue;
                case ISSUESW:
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    else if ((issue = atoi (cp)) < 1)
-                       adios (NULL, "bad argument %s %s", argp[-2], cp);
+                       mhladios (NULL, "bad argument %s %s", argp[-2], cp);
                    continue;
                case VOLUMSW:
                    if (!(cp = *argp++) || *cp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
+                       mhladios (NULL, "missing argument to %s", argp[-2]);
                    else if ((volume = atoi (cp)) < 1)
-                       adios (NULL, "bad argument %s %s", argp[-2], cp);
+                       mhladios (NULL, "bad argument %s %s", argp[-2], cp);
                    continue;
 
                case FORW2SW: 
-                   forwall++;  /* fall */
+                   forwall++;
+                   /* FALLTHRU */
                case FORW1SW: 
                    forwflg++;
                    clearflg = -1;/* XXX */
@@ -507,7 +507,7 @@ mhl (int argc, char **argv)
 
     if (forwall) {
        if (digest) {
-           printf ("%s", delim4);
+           fputs(delim4, stdout);
            if (volume == 0) {
                snprintf (buf, sizeof(buf), "End of %s Digest\n", digest);
            } else {
@@ -519,7 +519,7 @@ mhl (int argc, char **argv)
                *cp++ = '*';
            *cp++ = '\n';
            *cp = 0;
-           printf ("%s", buf);
+           fputs(buf, stdout);
        }
        else
            printf ("\n------- End of Forwarded Message%s\n",
@@ -528,7 +528,7 @@ mhl (int argc, char **argv)
 
     fflush(stdout);
     if(ferror(stdout)){
-           adios("output", "error writing");
+           mhladios("output", "error writing");
     }
     
     if (clearflg > 0 && ontty == NOTTY)
@@ -564,7 +564,7 @@ mhl_format (char *file, int length, int width)
     }
 
     if ((fp = fopen (etcpath (file), "r")) == NULL)
-       adios (file, "unable to open format file");
+       mhladios (file, "unable to open format file");
 
     if (fstat (fileno (fp), &st) != NOTOK) {
        mtime = st.st_mtime;
@@ -590,7 +590,7 @@ mhl_format (char *file, int length, int width)
        if (*bp == ';')
            continue;
 
-        TrimSuffixC(bp, '\n');
+        trim_suffix_c(bp, '\n');
 
        if (*bp == ':') {
            (void) add_queue (&fmthd, &fmttl, NULL, bp + 1, CLEARTEXT);
@@ -627,7 +627,7 @@ mhl_format (char *file, int length, int width)
                parptr = bp;
                while (*parptr) {
                    if (evalvar (&global))
-                       adios (NULL, "format file syntax error: %s", bp);
+                       mhladios (NULL, "format file syntax error: %s", bp);
                    if (*parptr)
                        parptr++;
                }
@@ -638,7 +638,7 @@ mhl_format (char *file, int length, int width)
                while (*parptr == ':' || *parptr == ',') {
                    parptr++;
                    if (evalvar (c1))
-                       adios (NULL, "format file syntax error: %s", bp);
+                       mhladios (NULL, "format file syntax error: %s", bp);
                }
                if (!c1->c_nfs && global.c_nfs) {
                    if (c1->c_flags & DATEFMT) {
@@ -658,7 +658,7 @@ mhl_format (char *file, int length, int width)
                continue;
 
            default: 
-               adios (NULL, "format file syntax error: %s", bp);
+               mhladios (NULL, "format file syntax error: %s", bp);
        }
     }
     fclose (fp);
@@ -905,7 +905,7 @@ process (char *folder, char *fname, int ofilen, int ofilec)
            cp = folder ? concat (folder, ":", fname2, NULL) : mh_xstrdup(fname2);
            if (ontty != PITTY)
                SIGNAL (SIGINT, intrser);
-           mhlfile (fp, cp, ofilen, ofilec);  /* FALL THROUGH! */
+           mhlfile (fp, cp, ofilen, ofilec);
             free (cp);
 
            for (ap = arglist_head; ap; ap = ap->a_next) {
@@ -914,17 +914,16 @@ process (char *folder, char *fname, int ofilen, int ofilec)
            }
 
            if (arglist_head)
-               fmt_free(NULL, 1);
+               fmt_free(NULL, 1);
+           /* FALLTHRU */
 
        default:
            if (ontty != PITTY)
                SIGNAL (SIGINT, SIG_IGN);
            if (mhl_action == NULL && fp != stdin && fp != NULL)
                fclose (fp);
-           if (holder.c_text) {
-               free (holder.c_text);
-               holder.c_text = NULL;
-           }
+            mh_xfree(holder.c_text);
+            holder.c_text = NULL;
            free_queue (&msghd, &msgtl);
            for (c1 = fmthd; c1; c1 = c1->c_next)
                c1->c_flags &= ~HDROUTPUT;
@@ -946,7 +945,7 @@ mhlfile (FILE *fp, char *mname, int ofilen, int ofilec)
 
     if (forwall) {
        if (digest)
-           printf ("%s", ofilen == 1 ? delim3 : delim4);
+           fputs(ofilen == 1 ? delim3 : delim4, stdout);
        else {
            printf ("\n-------");
            if (ofilen == 1)
@@ -1107,7 +1106,7 @@ mhlfile (FILE *fp, char *mname, int ofilen, int ofilec)
                return;
 
            default: 
-               adios (NULL, "getfld() returned %d", state);
+               mhladios (NULL, "getfld() returned %d", state);
        }
     }
 }
@@ -1127,7 +1126,7 @@ mcomp_flags (char *name)
 
 
 static char *
-mcomp_add (long flags, char *s1, char *s2)
+mcomp_add (unsigned long flags, char *s1, char *s2)
 {
     char *dp;
 
@@ -1221,12 +1220,10 @@ mcomp_format (struct mcomp *c1, struct mcomp *c2)
        }
        charstring_free (scanl);
 
-       if (p->pq_text)
-           free (p->pq_text);
-       if (p->pq_error)
-           free (p->pq_error);
+        mh_xfree(p->pq_text);
+        mh_xfree(p->pq_error);
        q = p->pq_next;
-       free ((char *) p);
+       free(p);
     }
 
     c2->c_text = add ("\n", c2->c_text);
@@ -1270,17 +1267,13 @@ free_queue (struct mcomp **head, struct mcomp **tail)
 
     for (c1 = *head; c1; c1 = c2) {
        c2 = c1->c_next;
-       if (c1->c_name)
-           free (c1->c_name);
-       if (c1->c_text)
-           free (c1->c_text);
-       if (c1->c_ovtxt)
-           free (c1->c_ovtxt);
-       if (c1->c_nfs)
-           free (c1->c_nfs);
+        mh_xfree(c1->c_name);
+        mh_xfree(c1->c_text);
+        mh_xfree(c1->c_ovtxt);
+        mh_xfree(c1->c_nfs);
        if (c1->c_fmt)
            fmt_free (c1->c_fmt, 0);
-       free ((char *) c1);
+       free(c1);
     }
 
     *head = *tail = NULL;
@@ -1290,14 +1283,22 @@ free_queue (struct mcomp **head, struct mcomp **tail)
 static void
 putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
 {
+    char *text; /* c1's text, or the name as a fallback. */
+    char *trimmed_prefix;
     int count, cchdr;
     char *cp;
-    /*
-     * Create a copy of c1->c_text with trailing whitespace
-     * trimmed, for use with blank lines.
-     */
-    char *trimmed_prefix =
-       rtrim (add (c1->c_text ? c1->c_text : c1->c_name, NULL));
+    const int utf8 = strcasecmp(get_charset(), "UTF-8") == 0;
+
+    if (! utf8  &&  flag != BODYCOMP) {
+        /* Don't print 8-bit bytes in header field values if not in a
+           UTF-8 locale, as required by RFC 6532. */
+       c1->c_flags |= FORCE7BIT;
+    }
+
+    text = c1->c_text ? c1->c_text : c1->c_name;
+    /* Create a copy with trailing whitespace trimmed, for use with
+     * blank lines. */
+    trimmed_prefix = rtrim(add(text, NULL));
 
     cchdr = 0;
     lm = 0;
@@ -1308,7 +1309,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
     if ((ovtxt = c1->c_ovtxt ? c1->c_ovtxt : global.c_ovtxt) == NULL)
        ovtxt = "";
     if (wid < ovoff + strlen (ovtxt) + 5)
-       adios (NULL, "component: %s width(%d) too small for overflow(%d)",
+       mhladios (NULL, "component: %s width(%d) too small for overflow(%d)",
                c1->c_name, wid, ovoff + strlen (ovtxt) + 5);
     onelp = NULL;
 
@@ -1326,7 +1327,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
        count = (c1->c_width ? c1->c_width : global.c_width)
            - c1->c_offset - strlen (c2->c_text);
        if (!(c1->c_flags & HDROUTPUT) && !(c1->c_flags & NOCOMPONENT))
-           count -= strlen (c1->c_text ? c1->c_text : c1->c_name) + 2;
+           count -= strlen(text) + 2;
        lm = c1->c_offset + (count / 2);
     } else {
        if (c1->c_offset)
@@ -1335,18 +1336,15 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
 
     if (!(c1->c_flags & HDROUTPUT) && !(c1->c_flags & NOCOMPONENT)) {
         if (c1->c_flags & UPPERCASE)           /* uppercase component also */
-           for (cp = (c1->c_text ? c1->c_text : c1->c_name); *cp; cp++)
-               if (islower ((unsigned char) *cp))
-                   *cp = toupper ((unsigned char) *cp);
-       putstr (c1->c_text ? c1->c_text : c1->c_name, c1->c_flags);
+            to_upper(text);
+       putstr(text, c1->c_flags);
        if (flag != BODYCOMP) {
            putstr (": ", c1->c_flags);
            if (!(c1->c_flags & SPLIT))
                c1->c_flags |= HDROUTPUT;
 
        cchdr++;
-       if ((count = c1->c_cwidth -
-               strlen (c1->c_text ? c1->c_text : c1->c_name) - 2) > 0)
+       if ((count = c1->c_cwidth - strlen(text) - 2) > 0)
            while (count--)
                putstr (" ", c1->c_flags);
        }
@@ -1358,9 +1356,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
            && !(c2->c_flags & HDROUTPUT)
            && !(c2->c_flags & NOCOMPONENT)) {
         if (c1->c_flags & UPPERCASE)
-           for (cp = c2->c_name; *cp; cp++)
-               if (islower ((unsigned char) *cp))
-                   *cp = toupper ((unsigned char) *cp);
+            to_upper(c2->c_name);
        putstr (c2->c_name, c1->c_flags);
        putstr (": ", c1->c_flags);
        if (!(c1->c_flags & SPLIT))
@@ -1372,9 +1368,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
                putstr (" ", c1->c_flags);
     }
     if (c1->c_flags & UPPERCASE)
-       for (cp = c2->c_text; *cp; cp++)
-           if (islower ((unsigned char) *cp))
-               *cp = toupper ((unsigned char) *cp);
+        to_upper(c2->c_text);
 
     count = 0;
     if (cchdr) {
@@ -1383,7 +1377,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
                        : (int) strlen (c2->c_name) + 2;
        else
            count = (c1->c_cwidth >= 0) ? (size_t) c1->c_cwidth
-                       : strlen (c1->c_text ? c1->c_text : c1->c_name) + 2;
+                       : strlen(text) + 2;
     }
     count += c1->c_offset;
 
@@ -1399,7 +1393,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
            /* Output component, trimming trailing whitespace if there
               is no text on the line. */
            if (*cp) {
-               putstr (c1->c_text ? c1->c_text : c1->c_name, c1->c_flags);
+               putstr(text, c1->c_flags);
            } else {
                putstr (trimmed_prefix, c1->c_flags);
            }
@@ -1419,7 +1413,7 @@ putcomp (struct mcomp *c1, struct mcomp *c2, int flag)
 
 
 static char *
-oneline (char *stuff, long flags)
+oneline (char *stuff, unsigned long flags)
 {
     int spc;
     char *cp, *ret;
@@ -1471,8 +1465,12 @@ oneline (char *stuff, long flags)
 
 
 static void
-putstr (char *string, long flags)
+putstr (char *string, unsigned long flags)
 {
+    /* To not count, for the purpose of counting columns, all of
+       the bytes of a multibyte character. */
+    int char_len;
+
     if (!column && lm > 0) {
        while (lm > 0)
            if (lm >= 8) {
@@ -1485,13 +1483,38 @@ putstr (char *string, long flags)
            }
     }
     lm = 0;
-    while (*string)
-       putch (*string++, flags);
+
+#ifdef MULTIBYTE_SUPPORT
+    if (mbtowc (NULL, NULL, 0)) {} /* reset shift state */
+    char_len = 0;
+#else
+    NMH_UNUSED (char_len);
+#endif
+
+    while (*string) {
+        flags &= ~INVISIBLE;
+#ifdef MULTIBYTE_SUPPORT
+        /* mbtowc should never return 0, because *string is non-NULL. */
+        if (char_len <= 0) {
+            /* Find number of bytes in next character. */
+            if ((char_len =
+                 mbtowc (NULL, string, (size_t) MB_CUR_MAX)) == -1) {
+                char_len = 1;
+            }
+        } else {
+            /* Multibyte character, after the first byte. */
+            flags |= INVISIBLE;
+        }
+
+        --char_len;
+#endif
+        putch (*string++, flags);
+    }
 }
 
 
 static void
-putch (char ch, long flags)
+putch (char ch, unsigned long flags)
 {
     char buf[BUFSIZ];
 
@@ -1545,8 +1568,25 @@ putch (char ch, long flags)
                putchar ('-');
                putchar (' ');
            }
-           if (ch >= ' ')
-               column++;
+            /*
+             * Increment the character count, unless
+             * 1) In UTF-8 locale, this is other than the last byte of
+                  a multibyte character, or
+             * 2) In C locale, will print a non-printable character.
+             */
+            if ((flags & FORCE7BIT) == 0) {
+                /* UTF-8 locale */
+                if ((flags & INVISIBLE) == 0) {
+                    /* If multibyte character, its first byte only. */
+                    ++column;
+                }
+            } else {
+                /* If not an ASCII character, the replace character will be
+                   displayed.  Count it. */
+                if (! isascii((unsigned char) ch) || isprint((unsigned char) ch)) {
+                    ++column;
+                }
+            }
            break;
     }
 
@@ -1559,7 +1599,11 @@ putch (char ch, long flags)
        return;
     }
 
-    putchar (ch);
+    if (flags & FORCE7BIT  &&  ! isascii((unsigned char) ch)) {
+        putchar ('?');
+    } else {
+        putchar (ch);
+    }
 }
 
 
@@ -1579,7 +1623,7 @@ pipeser (int i)
 {
     NMH_UNUSED (i);
 
-    done (NOTOK);
+    mhldone (NOTOK);
 }
 
 
@@ -1590,13 +1634,10 @@ quitser (int i)
 
     putchar ('\n');
     fflush (stdout);
-    done (NOTOK);
+    mhldone (NOTOK);
 }
 
 
-#undef adios
-#undef done
-
 static void
 mhladios (char *what, char *fmt, ...)
 {