]> diplodocus.org Git - nmh/blobdiff - sbr/fmt_scan.c
More replacements of mh_strcasecmp() with strcasecmp().
[nmh] / sbr / fmt_scan.c
index 879f7716af6ee286b2a3919e5c1ed61f7ef01637..dad7a3c6a08c56700b2392a0af291bb548ceb928 100644 (file)
@@ -50,13 +50,24 @@ match (char *str, char *sub)
 
 #ifdef LOCALE
     while ((c1 = *sub)) {
 
 #ifdef LOCALE
     while ((c1 = *sub)) {
-       c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1;
-       while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2))
+       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))
            ;
        if (! c2)
            return 0;
        s1 = sub + 1; s2 = str;
            ;
        if (! c2)
            return 0;
        s1 = sub + 1; s2 = str;
-       while ((c1 = *s1++) && ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) == ((isalpha(c2 =*s2++) && isupper(c2)) ? tolower(c2) : c2))
+       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))
            ;
        if (! c1)
            return 1;
            ;
        if (! c1)
            return 1;
@@ -114,8 +125,8 @@ cpnumber(char **dest, int num, unsigned int wid, char fill, size_t n) {
  * no more than n bytes are copied
  */
 static void
  * no more than n bytes are copied
  */
 static void
-cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
-         size_t max) {
+cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill,
+         char *epmax) {
     int remaining;     /* remaining output width available */
     int c, ljust;
     int end;           /* number of input bytes remaining in str */
     int remaining;     /* remaining output width available */
     int c, ljust;
     int end;           /* number of input bytes remaining in str */
@@ -126,8 +137,6 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
 #endif
     char *sp;          /* current position in source string */
     char *cp = *dest;  /* current position in destination string */
 #endif
     char *sp;          /* current position in source string */
     char *cp = *dest;  /* current position in destination string */
-    char *ep = cp + n; /* end of destination buffer based on desired width */
-    char *epmax = cp + max; /* true end of destination buffer */
     int prevCtrl = 1;
 
     /* get alignment */
     int prevCtrl = 1;
 
     /* get alignment */
@@ -137,19 +146,29 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
        ljust++;
     }
     if ((sp = (str))) {
        ljust++;
     }
     if ((sp = (str))) {
+#ifdef MULTIBYTE_SUPPORT
        mbtowc(NULL, NULL, 0); /* reset shift state */
        mbtowc(NULL, NULL, 0); /* reset shift state */
+#endif
        end = strlen(str);
        while (*sp && remaining > 0 && end > 0) {
 #ifdef MULTIBYTE_SUPPORT
            char_len = mbtowc(&wide_char, sp, end);
 
        end = strlen(str);
        while (*sp && remaining > 0 && end > 0) {
 #ifdef MULTIBYTE_SUPPORT
            char_len = mbtowc(&wide_char, sp, end);
 
-           /* Account for multibyte characters taking only one character's
-              width of output. */
-           if (char_len > 1  &&  epmax - ep >= char_len - 1) {
-               ep += char_len - 1;
+           if (char_len <= 0)
+               break;
+
+           w = wcwidth(wide_char);
+
+           /*
+            * Multibyte characters can have a variable number of column
+            * widths, so use the column width to bump the end pointer when
+            * appropriate.
+            */
+           if (char_len > 1 && epmax - *ep >= char_len - w) {
+               *ep += char_len - w;
            }
 
            }
 
-           if (char_len <= 0 || (cp + char_len > ep))
+           if (cp + w > *ep)
                break;
 
            end -= char_len;
                break;
 
            end -= char_len;
@@ -161,7 +180,7 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
            end--;
             /* isnctrl(), etc., take an int argument.  Cygwin's ctype.h
                intentionally warns if they are passed a char. */
            end--;
             /* isnctrl(), etc., take an int argument.  Cygwin's ctype.h
                intentionally warns if they are passed a char. */
-            c = *sp;
+            c = (unsigned char) *sp;
            if (iscntrl(c) || isspace(c)) {
                sp++;
 #endif
            if (iscntrl(c) || isspace(c)) {
                sp++;
 #endif
@@ -176,7 +195,6 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
            prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
            prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
-           w = wcwidth(wide_char);
            if (w >= 0 && remaining >= w) {
                strncpy(cp, sp, char_len);
                cp += char_len;
            if (w >= 0 && remaining >= w) {
                strncpy(cp, sp, char_len);
                cp += char_len;
@@ -191,9 +209,10 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
     }
 
     if (ljust) {
     }
 
     if (ljust) {
-       if (cp + remaining > ep)
-           remaining = ep - cp;
-       ep = cp + remaining;
+        char *endfield;
+       if (cp + remaining > *ep)
+           remaining = *ep - cp;
+       endfield = cp + remaining;
        if (remaining > 0) {
            /* copy string to the right */
            while (--cp >= *dest)
        if (remaining > 0) {
            /* copy string to the right */
            while (--cp >= *dest)
@@ -203,22 +222,22 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n,
            for (c=remaining; c>0; c--)
                *cp-- = fill;
        }
            for (c=remaining; c>0; c--)
                *cp-- = fill;
        }
-       *dest = ep;
+       *dest = endfield;
     } else {
        /* pad remaining space */
     } else {
        /* pad remaining space */
-       while (remaining-- > 0 && cp < ep)
+       while (remaining-- > 0 && cp < *ep)
                *cp++ = fill;
        *dest = cp;
     }
 }
 
 static void
                *cp++ = fill;
        *dest = cp;
     }
 }
 
 static void
-cpstripped (char **dest, char *end, char *max, char *str)
+cpstripped (char **dest, char **end, char *max, char *str)
 {
     int prevCtrl = 1;  /* This is 1 so we strip out leading spaces */
     int len;
 #ifdef MULTIBYTE_SUPPORT
 {
     int prevCtrl = 1;  /* This is 1 so we strip out leading spaces */
     int len;
 #ifdef MULTIBYTE_SUPPORT
-    int char_len;
+    int char_len, w;
     wchar_t wide_char;
 #endif /* MULTIBYTE_SUPPORT */
 
     wchar_t wide_char;
 #endif /* MULTIBYTE_SUPPORT */
 
@@ -236,17 +255,21 @@ cpstripped (char **dest, char *end, char *max, char *str)
      * then deal with that here.
      */
 
      * then deal with that here.
      */
 
-    while (*str != '\0' && len > 0 && *dest < end) {
+    while (*str != '\0' && len > 0 && *dest < *end) {
 #ifdef MULTIBYTE_SUPPORT
        char_len = mbtowc(&wide_char, str, len);
 #ifdef MULTIBYTE_SUPPORT
        char_len = mbtowc(&wide_char, str, len);
-
-       /* Account for multibyte characters taking only one character's
-          width of output. */
-       if (char_len > 1  &&  max - end >= char_len - 1) {
-           end += char_len - 1;
+       w = wcwidth(wide_char);
+
+       /*
+        * Account for multibyte characters, and increment the end pointer
+        * by the number of "extra" bytes in this character.  That's the
+        * character length (char_len) minus the column width (w).
+        */
+       if (char_len > 1  &&  max - *end >= char_len - w) {
+           *end += char_len - w;
        }
 
        }
 
-       if (char_len <= 0 || *dest + char_len > end)
+       if (char_len <= 0 || *dest + char_len > *end)
            break;
 
        len -= char_len;
            break;
 
        len -= char_len;
@@ -254,7 +277,7 @@ cpstripped (char **dest, char *end, char *max, char *str)
        if (iswcntrl(wide_char) || iswspace(wide_char)) {
            str += char_len;
 #else /* MULTIBYTE_SUPPORT */
        if (iswcntrl(wide_char) || iswspace(wide_char)) {
            str += char_len;
 #else /* MULTIBYTE_SUPPORT */
-       int c = *str;
+       int c = (unsigned char) *str;
        len--;
        if (iscntrl(c) || isspace(c)) {
            str++;
        len--;
        if (iscntrl(c) || isspace(c)) {
            str++;
@@ -328,12 +351,11 @@ get_x400_comp (char *mbox, char *key, char *buffer, int buffer_len)
 }
 
 struct format *
 }
 
 struct format *
-fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
+fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat,
+         struct fmt_callbacks *callbacks)
 {
 {
-    char *cp, *ep;
-    unsigned char *sp;
-    char *savestr = NULL;
-    unsigned char *str = NULL;
+    char *cp, *ep, *sp;
+    char *savestr = NULL, *str = NULL;
     char buffer[BUFSIZ], buffer2[BUFSIZ];
     int i, c, ljust, n;
     int value = 0;
     char buffer[BUFSIZ], buffer2[BUFSIZ];
     int i, c, ljust, n;
     int value = 0;
@@ -384,11 +406,11 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
        switch (fmt->f_type) {
 
        case FT_COMP:
        switch (fmt->f_type) {
 
        case FT_COMP:
-           cpstripped (&cp, ep, scanl + max - 1, fmt->f_comp->c_text);
+           cpstripped (&cp, &ep, scanl + max - 1, fmt->f_comp->c_text);
            break;
        case FT_COMPF:
            break;
        case FT_COMPF:
-           cptrimmed (&cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill,
-                      ep - cp, scanl - cp + max - 1);
+           cptrimmed (&cp, &ep, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill,
+                      scanl + max - 1);
            break;
 
        case FT_LIT:
            break;
 
        case FT_LIT:
@@ -411,11 +433,11 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            break;
 
        case FT_STR:
            break;
 
        case FT_STR:
-           cpstripped (&cp, ep, scanl + max - 1, str);
+           cpstripped (&cp, &ep, scanl + max - 1, str);
            break;
        case FT_STRF:
            break;
        case FT_STRF:
-           cptrimmed (&cp, str, fmt->f_width, fmt->f_fill, ep - cp,
-                      scanl - cp + max - 1);
+           cptrimmed (&cp, &ep, str, fmt->f_width, fmt->f_fill, 
+                      scanl + max - 1);
            break;
        case FT_STRLIT:
            sp = str;
            break;
        case FT_STRLIT:
            sp = str;
@@ -462,6 +484,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            break;
 
        case FT_DONE:
            break;
 
        case FT_DONE:
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
            goto finished;
 
        case FT_IF_S:
            goto finished;
 
        case FT_IF_S:
@@ -580,12 +605,12 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_LS_TRIM:
            if (str) {
 
        case FT_LS_TRIM:
            if (str) {
-                   unsigned char *xp;
+                   char *xp;
 
                    strncpy(buffer, str, sizeof(buffer));
                    buffer[sizeof(buffer)-1] = '\0';
                    str = buffer;
 
                    strncpy(buffer, str, sizeof(buffer));
                    buffer[sizeof(buffer)-1] = '\0';
                    str = buffer;
-                   while (isspace(*str))
+                   while (isspace((unsigned char) *str))
                            str++;
                    ljust = 0;
                    if ((i = fmt->f_width) < 0) {
                            str++;
                    ljust = 0;
                    if ((i = fmt->f_width) < 0) {
@@ -597,7 +622,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
                            str[i] = '\0';
                    xp = str;
                    xp += strlen(str) - 1;
                            str[i] = '\0';
                    xp = str;
                    xp += strlen(str) - 1;
-                   while (xp > str && isspace(*xp))
+                   while (xp > str && isspace((unsigned char) *xp))
                            *xp-- = '\0';
                    if (ljust && i > 0 && (int) strlen(str) > i)
                        str += strlen(str) - i;
                            *xp-- = '\0';
                    if (ljust && i > 0 && (int) strlen(str) > i)
                        str += strlen(str) - i;
@@ -877,12 +902,18 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_FORMATADDR:
            /* hook for custom address list formatting (see replsbr.c) */
 
        case FT_FORMATADDR:
            /* hook for custom address list formatting (see replsbr.c) */
-           str = formataddr (savestr, str);
+           if (callbacks && callbacks->formataddr)
+               str = callbacks->formataddr (savestr, str);
+           else
+               str = formataddr (savestr, str);
            break;
 
        case FT_CONCATADDR:
            /* The same as formataddr, but doesn't do duplicate suppression */
            break;
 
        case FT_CONCATADDR:
            /* The same as formataddr, but doesn't do duplicate suppression */
-           str = concataddr (savestr, str);
+           if (callbacks && callbacks->concataddr)
+               str = callbacks->concataddr (savestr, str);
+           else
+               str = concataddr (savestr, str);
            break;
 
        case FT_PUTADDR:
            break;
 
        case FT_PUTADDR:
@@ -893,8 +924,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
             * (e.g., "To: ")
             */
            {
             * (e.g., "To: ")
             */
            {
-           unsigned char *lp;
-           char *lastb;
+           char *lp, *lastb;
            int indent, wid, len;
 
            lp = str;
            int indent, wid, len;
 
            lp = str;
@@ -907,21 +937,22 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
                adios(NULL, "putaddr -- num register (%d) must be greater "
                            "than label width (%d)", value, indent);
            }
                adios(NULL, "putaddr -- num register (%d) must be greater "
                            "than label width (%d)", value, indent);
            }
-           while( (c = *sp++) && cp < ep)
-               *cp++ = c;
+           while( (c = (unsigned char) *sp++) && cp < ep)
+               *cp++ = (char) c;
            while (len > wid) {
                /* try to break at a comma; failing that, break at a
                 * space.
                 */
                lastb = 0; sp = lp + wid;
            while (len > wid) {
                /* try to break at a comma; failing that, break at a
                 * space.
                 */
                lastb = 0; sp = lp + wid;
-               while (sp > lp && (c = *--sp) != ',') {
+               while (sp > lp && (c = (unsigned char) *--sp) != ',') {
                    if (! lastb && isspace(c))
                        lastb = sp - 1;
                }
                if (sp == lp) {
                    if (! (sp = lastb)) {
                        sp = lp + wid - 1;
                    if (! lastb && isspace(c))
                        lastb = sp - 1;
                }
                if (sp == lp) {
                    if (! (sp = lastb)) {
                        sp = lp + wid - 1;
-                       while (*sp && *sp != ',' && !isspace(*sp))
+                       while (*sp && *sp != ',' &&
+                                               !isspace((unsigned char) *sp))
                            sp++;
                        if (*sp != ',')
                            sp--;
                            sp++;
                        if (*sp != ',')
                            sp--;
@@ -930,7 +961,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
                len -= sp - lp + 1;
                while (cp < ep && lp <= sp)
                    *cp++ = *lp++;
                len -= sp - lp + 1;
                while (cp < ep && lp <= sp)
                    *cp++ = *lp++;
-               while (isspace(*lp))
+               while (isspace((unsigned char) *lp))
                    lp++, len--;
                if (*lp) {
                    if (cp < ep)
                    lp++, len--;
                if (*lp) {
                    if (cp < ep)
@@ -939,7 +970,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
                        *cp++ = ' ';
                }
            }
                        *cp++ = ' ';
                }
            }
-           cpstripped (&cp, ep, scanl + max - 1, lp);
+           cpstripped (&cp, &ep, scanl + max - 1, lp);
            }
            break;
 
            }
            break;
 
@@ -994,6 +1025,14 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            }
            break;
        }
            }
            break;
        }
+
+       /*
+        * Call our tracing callback function, if one was supplied
+        */
+
+       if (callbacks && callbacks->trace_func)
+           callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                 str, scanl);
        fmt++;
     }
 
        fmt++;
     }
 
@@ -1001,6 +1040,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
     while (fmt->f_type != FT_DONE) {
        if (fmt->f_type == FT_LS_LIT) {
            str = fmt->f_text;
     while (fmt->f_type != FT_DONE) {
        if (fmt->f_type == FT_LS_LIT) {
            str = fmt->f_text;
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
        } else if (fmt->f_type == FT_STRLITZ) {
            /* Don't want to emit part of an escape sequence.  So if
               there isn't enough room in the buffer for the entire
        } else if (fmt->f_type == FT_STRLITZ) {
            /* Don't want to emit part of an escape sequence.  So if
               there isn't enough room in the buffer for the entire
@@ -1009,6 +1051,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            if (cp - scanl + strlen (str) + 1 < max) {
                for (sp = str; *sp; *cp++ = *sp++) continue;
            }
            if (cp - scanl + strlen (str) + 1 < max) {
                for (sp = str; *sp; *cp++ = *sp++) continue;
            }
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
        }
        fmt++;
     }
        }
        fmt++;
     }