]> diplodocus.org Git - nmh/blobdiff - sbr/fmt_scan.c
dtimezone(): Explain abs(3) is undefined on INT_MIN.
[nmh] / sbr / fmt_scan.c
index cc5c192d3904b86520bb37f1e22c3fdcd30c8534..c75db3ec95fb0c6953dad86efd7d9e259b667e74 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * fmt_scan.c -- format string interpretation
+/* fmt_scan.c -- format string interpretation
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -16,6 +14,7 @@
 #include <h/tws.h>
 #include <h/fmt_compile.h>
 #include <h/utils.h>
 #include <h/tws.h>
 #include <h/fmt_compile.h>
 #include <h/utils.h>
+#include "unquote.h"
 
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
@@ -49,24 +48,14 @@ match (char *str, char *sub)
     char *s1, *s2;
 
     while ((c1 = *sub)) {
     char *s1, *s2;
 
     while ((c1 = *sub)) {
-       c1 = (isascii((unsigned char) c1) && isalpha((unsigned char) c1) &&
-             isupper((unsigned char) c1)) ? tolower((unsigned char) c1) : c1;
-       while ((c2 = *str++) && c1 != ((isascii((unsigned char) c2) &&
-                                       isalpha((unsigned char) c2) &&
-                                       isupper((unsigned char) c2)) ?
-                                           tolower((unsigned char) c2) : c2))
+       c1 = tolower((unsigned char)c1);
+       while ((c2 = *str++) && c1 != tolower((unsigned char)c2))
            ;
        if (! c2)
            return 0;
        s1 = sub + 1; s2 = str;
            ;
        if (! c2)
            return 0;
        s1 = sub + 1; s2 = str;
-       while ((c1 = *s1++) && ((isascii((unsigned char) c1) &&
-                                isalpha((unsigned char) c1) &&
-                                isupper((unsigned char) c1)) ?
-                                       tolower(c1) : c1) ==
-                       ((isascii((unsigned char) (c2 =*s2++)) &&
-                         isalpha((unsigned char) c2) &&
-                         isupper((unsigned char) c2)) ?
-                               tolower((unsigned char) c2) : c2))
+       while ((c1 = *s1++) &&
+            tolower((unsigned char)c1) == tolower((unsigned char)(c2 = *s2++)))
            ;
        if (! c1)
            return 1;
            ;
        if (! c1)
            return 1;
@@ -93,13 +82,18 @@ cpnumber(charstring_t dest, int num, unsigned int wid, char fill, size_t max) {
            charstring_push_back (rev, '?');
        } else if (num < 0  &&  wid > 0) {
            /* Shouldn't need the wid > 0 check, that's why the condition
            charstring_push_back (rev, '?');
        } else if (num < 0  &&  wid > 0) {
            /* Shouldn't need the wid > 0 check, that's why the condition
-               at the top checks wid < max-1 when num < 0. */
-           charstring_push_back (rev, '-');
+              at the top checks wid < max-1 when num < 0. */
            --wid;
            --wid;
+           if (fill == ' ') {
+               charstring_push_back (rev, '-');
+           }
        }
        while (wid-- > 0  &&  fill != 0) {
            charstring_push_back (rev, fill);
        }
        }
        while (wid-- > 0  &&  fill != 0) {
            charstring_push_back (rev, fill);
        }
+       if (num < 0  &&  fill == '0') {
+           charstring_push_back (rev, '-');
+       }
 
        {
            /* Output the string in reverse. */
 
        {
            /* Output the string in reverse. */
@@ -124,6 +118,7 @@ void
 cptrimmed(charstring_t dest, char *str, int wid, char fill, size_t max) {
     int remaining;     /* remaining output width available */
     int rjust;
 cptrimmed(charstring_t dest, char *str, int wid, char fill, size_t max) {
     int remaining;     /* remaining output width available */
     int rjust;
+    struct charstring *trimmed;
     size_t end;        /* number of input bytes remaining in str */
 #ifdef MULTIBYTE_SUPPORT
     int char_len;      /* bytes in current character */
     size_t end;        /* number of input bytes remaining in str */
 #ifdef MULTIBYTE_SUPPORT
     int char_len;      /* bytes in current character */
@@ -142,6 +137,8 @@ cptrimmed(charstring_t dest, char *str, int wid, char fill, size_t max) {
     }
     if (remaining > (int) max) { remaining = max; }
 
     }
     if (remaining > (int) max) { remaining = max; }
 
+    trimmed = rjust ? charstring_create(remaining) : dest;
+
     if ((sp = str)) {
 #ifdef MULTIBYTE_SUPPORT
        if (mbtowc(NULL, NULL, 0)) {} /* reset shift state */
     if ((sp = str)) {
 #ifdef MULTIBYTE_SUPPORT
        if (mbtowc(NULL, NULL, 0)) {} /* reset shift state */
@@ -187,7 +184,7 @@ cptrimmed(charstring_t dest, char *str, int wid, char fill, size_t max) {
                sp++;
 #endif
                if (!prevCtrl) {
                sp++;
 #endif
                if (!prevCtrl) {
-                   charstring_push_back (dest, ' ');
+                    charstring_push_back (trimmed, ' ');
                    remaining--;
                }
 
                    remaining--;
                }
 
@@ -198,39 +195,26 @@ cptrimmed(charstring_t dest, char *str, int wid, char fill, size_t max) {
 
 #ifdef MULTIBYTE_SUPPORT
            if (w >= 0 && remaining >= w) {
 
 #ifdef MULTIBYTE_SUPPORT
            if (w >= 0 && remaining >= w) {
-               charstring_push_back_chars (dest, altstr ? altstr : sp,
+                charstring_push_back_chars (trimmed, altstr ? altstr : sp,
                                            char_len, w);
                remaining -= w;
                altstr = NULL;
            }
            sp += char_len;
 #else
                                            char_len, w);
                remaining -= w;
                altstr = NULL;
            }
            sp += char_len;
 #else
-           charstring_push_back (dest, *sp++);
+            charstring_push_back (trimmed, *sp++);
            remaining--;
 #endif
        }
     }
 
            remaining--;
 #endif
        }
     }
 
-    if (rjust) {
-       if (remaining > 0) {
-           /* copy string to the right */
-           charstring_t copy = charstring_copy (dest);
-
-           /* add padding at the beginning */
-           charstring_clear (dest);
-           for (; remaining > 0; --remaining) {
-               charstring_push_back (dest, fill);
-           }
-
-           charstring_append (dest, copy);
+    while (remaining-- > 0) {
+        charstring_push_back(dest, fill);
+    }
 
 
-           charstring_free (copy);
-       }
-    } else {
-       /* pad remaining space */
-       while (remaining-- > 0) {
-           charstring_push_back (dest, fill);
-       }
+    if (rjust) {
+        charstring_append(dest, trimmed);
+        charstring_free(trimmed);
     }
 }
 
     }
 }
 
@@ -263,16 +247,15 @@ cpstripped (charstring_t dest, size_t max, char *str)
     while (*str != '\0' && len > 0 && max > 0) {
 #ifdef MULTIBYTE_SUPPORT
        char_len = mbtowc(&wide_char, str, len);
     while (*str != '\0' && len > 0 && max > 0) {
 #ifdef MULTIBYTE_SUPPORT
        char_len = mbtowc(&wide_char, str, len);
-       w = wcwidth(wide_char);
 
        /*
         * If mbrtowc() failed, then we have a character that isn't valid
 
        /*
         * If mbrtowc() failed, then we have a character that isn't valid
-        * in the current encoding.  Replace it with a '?'.  We do that by
+        * in the current encoding, or len wasn't enough for the whole
+        * multi-byte rune to be read.  Replace it with a '?'.  We do that by
         * setting the alstr variable to the value of the replacement string;
         * altstr is used below when the bytes are copied into the output
         * buffer.
         */
         * setting the alstr variable to the value of the replacement string;
         * altstr is used below when the bytes are copied into the output
         * buffer.
         */
-
        if (char_len < 0) {
            altstr = "?";
            char_len = mbtowc(&wide_char, altstr, 1);
        if (char_len < 0) {
            altstr = "?";
            char_len = mbtowc(&wide_char, altstr, 1);
@@ -304,10 +287,21 @@ cpstripped (charstring_t dest, size_t max, char *str)
        prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
        prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
-       charstring_push_back_chars (dest, altstr ? altstr : str, char_len, w);
-        max -= w;
-       str += char_len;
-       altstr = NULL;
+       w = wcwidth(wide_char);
+       assert(w >= 0);
+       if (max >= (size_t) w) {
+           charstring_push_back_chars (dest, altstr ? altstr : str, char_len, w);
+           max -= w;
+           str += char_len;
+           altstr = NULL;
+       } else {
+           /* Not enough width available for the last character.  Output
+              space(s) to fill. */
+           while (max-- > 0) {
+               charstring_push_back (dest, ' ');
+           }
+           break;
+       }
 #else /* MULTIBYE_SUPPORT */
        charstring_push_back (dest, *str++);
         --max;
 #else /* MULTIBYE_SUPPORT */
        charstring_push_back (dest, *str++);
         --max;
@@ -369,7 +363,7 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
 {
     char *sp;
     char *savestr, *str;
 {
     char *sp;
     char *savestr, *str;
-    char buffer[BUFSIZ], buffer2[BUFSIZ];
+    char buffer[NMH_BUFSIZ], buffer2[NMH_BUFSIZ];
     int i, c, rjust;
     int value;
     time_t t;
     int i, c, rjust;
     int value;
     time_t t;
@@ -477,7 +471,7 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
            int num = value;
            unsigned int wid;
 
            int num = value;
            unsigned int wid;
 
-           for (wid = num <= 0  ?  1  :  0; num; ++wid, num /= 10) {}
+            for (wid = num <= 0; num; ++wid, num /= 10) {}
            cpnumber (scanlp, value, wid, ' ',
                      max - charstring_chars (scanlp));
            break;
            cpnumber (scanlp, value, wid, ' ',
                      max - charstring_chars (scanlp));
            break;
@@ -499,6 +493,9 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
                if (val < scale) {
                    snprintf(buffer, sizeof(buffer), "%u", val);
                } else {
                if (val < scale) {
                    snprintf(buffer, sizeof(buffer), "%u", val);
                } else {
+                   /* To prevent divide by 0, found by clang static
+                      analyzer. */
+                   if (scale == 0) { scale = 1; }
 
                    /* find correct scale for size (Kilo/Mega/Giga/Tera) */
                    for (unitcp = "KMGT"; val > (scale * scale); val /= scale) {
 
                    /* find correct scale for size (Kilo/Mega/Giga/Tera) */
                    for (unitcp = "KMGT"; val > (scale * scale); val /= scale) {
@@ -688,7 +685,8 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
            if (str) {
                    char *xp;
 
            if (str) {
                    char *xp;
 
-                   strncpy(buffer, str, sizeof(buffer));
+                   if (str != buffer)
+                       strncpy(buffer, str, sizeof(buffer));
                    buffer[sizeof(buffer)-1] = '\0';
                    str = buffer;
                    while (isspace((unsigned char) *str))
                    buffer[sizeof(buffer)-1] = '\0';
                    str = buffer;
                    while (isspace((unsigned char) *str))
@@ -737,15 +735,18 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
        case FT_LV_MINUS_L:
            value = fmt->f_value - value;
            break;
        case FT_LV_MINUS_L:
            value = fmt->f_value - value;
            break;
+       case FT_LV_MULTIPLY_L:
+           value *= fmt->f_value;
+           break;
        case FT_LV_DIVIDE_L:
            if (fmt->f_value)
        case FT_LV_DIVIDE_L:
            if (fmt->f_value)
-               value = value / fmt->f_value;
+               value /= fmt->f_value;
            else
                value = 0;
            break;
        case FT_LV_MODULO_L:
            if (fmt->f_value)
            else
                value = 0;
            break;
        case FT_LV_MODULO_L:
            if (fmt->f_value)
-               value = value % fmt->f_value;
+               value %= fmt->f_value;
            else
                value = 0;
            break;
            else
                value = 0;
            break;
@@ -821,14 +822,15 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
                default:
                    value = -1; break;
            }
                default:
                    value = -1; break;
            }
+           break;
        case FT_LV_ZONEF:
        case FT_LV_ZONEF:
-           if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) == TW_SZEXP)
+           if (fmt->f_comp->c_tws->tw_flags & TW_SZEXP)
                    value = 1;
            else
                    value = -1;
            break;
        case FT_LV_DST:
                    value = 1;
            else
                    value = -1;
            break;
        case FT_LV_DST:
-           value = fmt->f_comp->c_tws->tw_flags & TW_DST;
+           value = fmt->f_comp->c_tws->tw_flags & TW_DST ? 1 : 0;
            break;
        case FT_LS_822DATE:
            str = dasctime (fmt->f_comp->c_tws , TW_ZONE);
            break;
        case FT_LS_822DATE:
            str = dasctime (fmt->f_comp->c_tws , TW_ZONE);
@@ -877,7 +879,8 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
                goto unfriendly;
            if ((str = mn->m_pers) == NULL) {
                if ((str = mn->m_note)) {
                goto unfriendly;
            if ((str = mn->m_pers) == NULL) {
                if ((str = mn->m_note)) {
-                   strncpy (buffer, str, sizeof(buffer));
+                   if (str != buffer)
+                       strncpy (buffer, str, sizeof(buffer));
                    buffer[sizeof(buffer)-1] = '\0';
                    str = buffer;
                    if (*str == '(')
                    buffer[sizeof(buffer)-1] = '\0';
                    str = buffer;
                    if (*str == '(')
@@ -921,7 +924,8 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
                /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
        case FT_LS_UNQUOTE:
            if (str) {          
                /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
        case FT_LS_UNQUOTE:
            if (str) {          
-               strncpy(buffer, str, sizeof(buffer));
+               if (str != buffer)
+                   strncpy(buffer, str, sizeof(buffer));
                /* strncpy doesn't NUL-terminate if it fills the buffer */
                buffer[sizeof(buffer)-1] = '\0';
                unquote_string(buffer, buffer2);
                /* strncpy doesn't NUL-terminate if it fills the buffer */
                buffer[sizeof(buffer)-1] = '\0';
                unquote_string(buffer, buffer2);
@@ -988,7 +992,7 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
 
            lp = str;
            wid = value;
 
            lp = str;
            wid = value;
-           len = strlen (str);
+           len = str ? strlen (str) : 0;
            sp = fmt->f_text;
            indent = strlen (sp);
            wid -= indent;
            sp = fmt->f_text;
            indent = strlen (sp);
            wid -= indent;
@@ -1058,6 +1062,8 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
            break;
 
        case FT_MYMBOX:
            break;
 
        case FT_MYMBOX:
+       case FT_GETMYMBOX:
+       case FT_GETMYADDR:
            /*
             * if there's no component, we say true.  Otherwise we
             * say "true" only if we can parse the address and it
            /*
             * if there's no component, we say true.  Otherwise we
             * say "true" only if we can parse the address and it
@@ -1069,24 +1075,46 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
                (mn = getm (sp, NULL, 0, NULL, 0))) {
                comp->c_mn = mn;
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
                (mn = getm (sp, NULL, 0, NULL, 0))) {
                comp->c_mn = mn;
-               if (ismymbox(mn))
+               if (ismymbox(mn)) {
                    comp->c_flags |= CF_TRUE;
                    comp->c_flags |= CF_TRUE;
-               else
+                   /* Set str for use with FT_GETMYMBOX.  With
+                      FT_GETMYADDR, comp->c_mn will be run through
+                      FT_LS_ADDR, which will strip off any pers
+                      name. */
+                   str = mn->m_text;
+               } else {
                    comp->c_flags &= ~CF_TRUE;
                    comp->c_flags &= ~CF_TRUE;
+               }
                while ((sp = getname(sp)))
                    if ((comp->c_flags & CF_TRUE) == 0 &&
                        (mn = getm (sp, NULL, 0, NULL, 0)))
                while ((sp = getname(sp)))
                    if ((comp->c_flags & CF_TRUE) == 0 &&
                        (mn = getm (sp, NULL, 0, NULL, 0)))
-                       if (ismymbox(mn))
+                       if (ismymbox(mn)) {
                            comp->c_flags |= CF_TRUE;
                            comp->c_flags |= CF_TRUE;
+                           /* Set str and comp->c_text for use with
+                              FT_GETMYMBOX.  With FT_GETMYADDR,
+                              comp->c_mn will be run through
+                              FT_LS_ADDR, which will strip off any
+                              pers name. */
+                           free (comp->c_text);
+                           comp->c_text = str = strdup (mn->m_text);
+                           comp->c_mn = mn;
+                       }
+               comp->c_flags |= CF_PARSED;
            } else {
                while (getname(""))             /* XXX */
                    ;
                if (comp->c_text == 0)
                    comp->c_flags |= CF_TRUE;
            } else {
                while (getname(""))             /* XXX */
                    ;
                if (comp->c_text == 0)
                    comp->c_flags |= CF_TRUE;
-               else
+               else {
                    comp->c_flags &= ~CF_TRUE;
                    comp->c_flags &= ~CF_TRUE;
+               }
                comp->c_mn = &fmt_mnull;
            }
                comp->c_mn = &fmt_mnull;
            }
+           if ((comp->c_flags & CF_TRUE) == 0  &&
+               (fmt->f_type == FT_GETMYMBOX || fmt->f_type == FT_GETMYADDR)) {
+               /* Fool FT_LS_ADDR into not producing an address. */
+               comp->c_mn = &fmt_mnull; comp->c_text = NULL;
+           }
            break;
        }
 
            break;
        }
 
@@ -1146,5 +1174,5 @@ fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat,
        }
     }
 
        }
     }
 
-    return ((struct format *)0);
+    return (NULL);
 }
 }