#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;
- 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;
* 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 */
#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 */
ljust++;
}
if ((sp = (str))) {
+#ifdef MULTIBYTE_SUPPORT
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);
- /* 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;
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
prevCtrl = 0;
#ifdef MULTIBYTE_SUPPORT
- w = wcwidth(wide_char);
if (w >= 0 && remaining >= w) {
strncpy(cp, sp, char_len);
cp += char_len;
}
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)
for (c=remaining; c>0; c--)
*cp-- = fill;
}
- *dest = ep;
+ *dest = endfield;
} else {
/* pad remaining space */
- while (remaining-- > 0 && cp < ep)
+ while (remaining-- > 0 && cp < *ep)
*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 char_len;
+ int char_len, w;
wchar_t wide_char;
#endif /* MULTIBYTE_SUPPORT */
* 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);
-
- /* 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;
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++;
}
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;
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:
- 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_STR:
- cpstripped (&cp, ep, scanl + max - 1, str);
+ cpstripped (&cp, &ep, scanl + max - 1, str);
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_DONE:
+ if (callbacks && callbacks->trace_func)
+ callbacks->trace_func(callbacks->trace_context, fmt, value,
+ str, scanl);
goto finished;
case FT_IF_S:
case FT_LS_TRIM:
if (str) {
- unsigned char *xp;
+ char *xp;
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[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;
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 */
- str = concataddr (savestr, str);
+ if (callbacks && callbacks->concataddr)
+ str = callbacks->concataddr (savestr, str);
+ else
+ str = concataddr (savestr, str);
break;
case FT_PUTADDR:
* (e.g., "To: ")
*/
{
- unsigned char *lp;
- char *lastb;
+ char *lp, *lastb;
int indent, wid, len;
lp = str;
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 (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;
- while (*sp && *sp != ',' && !isspace(*sp))
+ while (*sp && *sp != ',' &&
+ !isspace((unsigned char) *sp))
sp++;
if (*sp != ',')
sp--;
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)
*cp++ = ' ';
}
}
- cpstripped (&cp, ep, scanl + max - 1, lp);
+ cpstripped (&cp, &ep, scanl + max - 1, lp);
}
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++;
}
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
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++;
}