X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=sbr%2Ffmt_scan.c;h=4921854610200f384f90c36160f926fa816aa637;hp=ae311621b22e098e70c6219cbb4f1c8ce8829a3a;hb=ebff0feca0d651c3d0c535a8147963f97807c17a;hpb=8563731b02ce9d750806f6b1769af8b399d964e8 diff --git a/sbr/fmt_scan.c b/sbr/fmt_scan.c index ae31162..4921854 100644 --- a/sbr/fmt_scan.c +++ b/sbr/fmt_scan.c @@ -3,12 +3,16 @@ * fmt_scan.c -- format string interpretation * * $Id$ + * + * This code is Copyright (c) 2002, by the authors of nmh. See the + * COPYRIGHT file in the root directory of the nmh distribution for + * complete copyright information. */ #include #include #include -#include +#include #include #ifdef TIME_WITH_SYS_TIME @@ -84,7 +88,6 @@ match (char *str, char *sub) /* * macros to format data */ - #define PUTDF(cp, num, wid, fill)\ if (cp + wid < ep) {\ if ((i = (num)) < 0)\ @@ -105,67 +108,42 @@ match (char *str, char *sub) cp += c;\ } -#define PUTD(cp, num)\ - if (cp < ep) {\ - if ((i = (num)) == 0)\ - *cp++ = '0';\ - else {\ - if ((i = (num)) < 0) {\ - *cp++ = '-';\ - i = -(num);\ - }\ - c = 10;\ - while (c <= i) \ - c *= 10;\ - while (cp < ep && c > 1) {\ - c /= 10;\ - *cp++ = (i / c) + '0';\ - i %= c;\ - }\ - }\ - } +char * PUTSF(char *cp, char *str, unsigned int wid, char fill) { + + unsigned int i, j; + unsigned int char_len; + unsigned int term_len = 0; + wchar_t wide_char; + + for (i = 0 ; i < wid && i < strlen(str) && term_len < wid; ) { + char_len = mblen(str + i, strlen(str + i)); + if (char_len <= 0) { + continue; + } + mbtowc(&wide_char, str + i, strlen(str + i)); + term_len += wcwidth(wide_char); + + for (j = 0 ; j < char_len ; j++) { + *(cp + i) = *(str + i); + i++; + } + } -#ifdef LOCALE -#define PUTSF(cp, str, wid, fill) {\ - ljust = 0;\ - if ((i = (wid)) < 0) {\ - i = -i;\ - ljust++;\ - }\ - if ((sp = (str))) {\ - if (ljust) {\ - c = strlen(sp);\ - if (c > i)\ - sp += c - i;\ - else {\ - while( --i >= c && cp < ep)\ - *cp++ = fill;\ - i++;\ - }\ - } else {\ - while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ - sp++;\ - }\ - while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\ - if (isgraph(c)) \ - *cp++ = c;\ - else {\ - while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ - sp++;\ - *cp++ = ' ';\ - }\ - }\ - if (!ljust)\ - while( --i >= 0 && cp < ep)\ - *cp++ = fill;\ - } + if (term_len < wid) { + for (j = term_len ; j <= wid ; j++) { + *(cp + i++) = fill; + } + } + + return cp + i; +} #define PUTS(cp, str) {\ if ((sp = (str))) {\ while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ sp++;\ while((c = (unsigned char) *sp++) && cp < ep)\ - if (isgraph(c)) \ + if (!iscntrl(c) && !isspace(c)) \ *cp++ = c;\ else {\ while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ @@ -175,59 +153,6 @@ match (char *str, char *sub) }\ } -#else /* LOCALE */ -#define PUTSF(cp, str, wid, fill) {\ - ljust = 0;\ - if ((i = (wid)) < 0) {\ - i = -i;\ - ljust++;\ - }\ - if (sp = (str)) {\ - if (ljust) {\ - c = strlen(sp);\ - if (c > i)\ - sp += c - i;\ - else {\ - while( --i >= c && cp < ep)\ - *cp++ = fill;\ - i++;\ - }\ - } else {\ - while ((c = *sp) && c <= 32)\ - sp++;\ - }\ - while ((c = *sp++) && --i >= 0 && cp < ep)\ - if (c > 32) \ - *cp++ = c;\ - else {\ - while ((c = *sp) && c <= 32)\ - sp++;\ - *cp++ = ' ';\ - }\ - }\ - if (!ljust)\ - while( --i >= 0 && cp < ep)\ - *cp++ = fill;\ - } - -#define PUTS(cp, str) {\ - if (sp = (str)) {\ - while ((c = *sp) && c <= 32)\ - sp++;\ - while( (c = *sp++) && cp < ep)\ - if ( c > 32 ) \ - *cp++ = c;\ - else {\ - while ( (c = *sp) && c <= 32 )\ - sp++;\ - *cp++ = ' ';\ - }\ - }\ - } - -#endif /* LOCALE */ - - static char *lmonth[] = { "January", "February","March", "April", "May", "June", "July", "August", "September","October", "November","December" }; @@ -282,7 +207,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) char *cp, *ep, *sp; char *savestr, *str = NULL; char buffer[BUFSIZ], buffer2[BUFSIZ]; - int i, c, ljust; + int i, c, ljust, n; int value = 0; time_t t; struct format *fmt; @@ -292,6 +217,15 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) cp = scanl; ep = scanl + width - 1; + + for (fmt = format; fmt->f_type != FT_DONE; fmt++) + switch (fmt->f_type) { + case FT_PARSEADDR: + case FT_PARSEDATE: + fmt->f_comp->c_flags &= ~CF_PARSED; + break; + } + fmt = format; while (cp < ep) { @@ -301,7 +235,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) PUTS (cp, fmt->f_comp->c_text); break; case FT_COMPF: - PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill); + cp = PUTSF(cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill); break; case FT_LIT: @@ -327,13 +261,14 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) PUTS (cp, str); break; case FT_STRF: - PUTSF (cp, str, fmt->f_width, fmt->f_fill); + cp =PUTSF (cp, str, fmt->f_width, fmt->f_fill); break; case FT_STRFW: adios (NULL, "internal error (FT_STRFW)"); case FT_NUM: - PUTD (cp, value); + n = snprintf(cp, ep - cp, "%d", value); + if (n >= 0) cp += n; break; case FT_NUMF: PUTDF (cp, value, fmt->f_width, fmt->f_fill); @@ -449,14 +384,14 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) break; case FT_LS_DECODECOMP: - if (decode_rfc2047(fmt->f_comp->c_text, buffer2)) + if (decode_rfc2047(fmt->f_comp->c_text, buffer2, sizeof(buffer2))) str = buffer2; else str = fmt->f_comp->c_text; break; case FT_LS_DECODE: - if (str && decode_rfc2047(str, buffer2)) + if (str && decode_rfc2047(str, buffer2, sizeof(buffer2))) str = buffer2; break; @@ -465,6 +400,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) char *xp; strncpy(buffer, str, sizeof(buffer)); + buffer[sizeof(buffer)-1] = '\0'; str = buffer; while (isspace(*str)) str++; @@ -486,7 +422,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) break; case FT_LV_COMPFLAG: - value = fmt->f_comp->c_flags; + value = (fmt->f_comp->c_flags & CF_TRUE) != 0; break; case FT_LV_COMP: value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0; @@ -498,7 +434,10 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) value = dat[fmt->f_value]; break; case FT_LV_STRLEN: - value = strlen(str); + if (str != NULL) + value = strlen(str); + else + value = 0; break; case FT_LV_CHAR_LEFT: value = width - (cp - scanl); @@ -650,6 +589,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) if ((str = mn->m_pers) == NULL) { if ((str = mn->m_note)) { strncpy (buffer, str, sizeof(buffer)); + buffer[sizeof(buffer)-1] = '\0'; str = buffer; if (*str == '(') str++; @@ -686,6 +626,40 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) } } } + break; + + + /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */ + case FT_LS_UNQUOTE: + if (str) { + int m; + strncpy(buffer, str, sizeof(buffer)); + /* strncpy doesn't NUL-terminate if it fills the buffer */ + buffer[sizeof(buffer)-1] = '\0'; + str = buffer; + + /* we will parse from buffer to buffer2 */ + n = 0; /* n is the input position in str */ + m = 0; /* m is the ouput position in buffer2 */ + + while ( str[n] != '\0') { + switch ( str[n] ) { + case '\\': + n++; + if ( str[n] != '\0') + buffer2[m++] = str[n++]; + break; + case '"': + n++; + break; + default: + buffer2[m++] = str[n++]; + break; + } + } + buffer2[m] = '\0'; + str = buffer2; + } break; case FT_LOCALDATE: @@ -706,13 +680,16 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) case FT_PARSEDATE: comp = fmt->f_comp; + if (comp->c_flags & CF_PARSED) + break; if ((sp = comp->c_text) && (tws = dparsetime(sp))) { *comp->c_tws = *tws; - comp->c_flags = 0; - } else if (comp->c_flags >= 0) { + comp->c_flags &= ~CF_TRUE; + } else if ((comp->c_flags & CF_DATEFAB) == 0) { memset ((char *) comp->c_tws, 0, sizeof *comp->c_tws); - comp->c_flags = 1; + comp->c_flags = CF_TRUE; } + comp->c_flags |= CF_PARSED; break; case FT_FORMATADDR: @@ -760,9 +737,6 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) len -= sp - lp + 1; while (cp < ep && lp <= sp) *cp++ = *lp++; - *cp++ = '\n'; - for (i=indent; cp < ep && i > 0; i--) - *cp++ = ' '; while (isspace(*lp)) lp++, len--; if (*lp) { @@ -778,6 +752,8 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) case FT_PARSEADDR: comp = fmt->f_comp; + if (comp->c_flags & CF_PARSED) + break; if (comp->c_mn != &fmt_mnull) mnfree (comp->c_mn); if ((sp = comp->c_text) && (sp = getname(sp)) && @@ -785,6 +761,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) comp->c_mn = mn; while (getname("")) ; + comp->c_flags |= CF_PARSED; } else { while (getname("")) /* XXX */ ; @@ -804,15 +781,22 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat) if ((sp = comp->c_text) && (sp = getname(sp)) && (mn = getm (sp, NULL, 0, AD_NAME, NULL))) { comp->c_mn = mn; - comp->c_flags = ismymbox(mn); + if (ismymbox(mn)) + comp->c_flags |= CF_TRUE; + else + comp->c_flags &= ~CF_TRUE; while ((sp = getname(sp))) - if (comp->c_flags == 0 && + if ((comp->c_flags & CF_TRUE) == 0 && (mn = getm (sp, NULL, 0, AD_NAME, NULL))) - comp->c_flags |= ismymbox(mn); + if (ismymbox(mn)) + comp->c_flags |= CF_TRUE; } else { while (getname("")) /* XXX */ ; - comp->c_flags = (comp->c_text == 0); + if (comp->c_text == 0) + comp->c_flags |= CF_TRUE; + else + comp->c_flags &= ~CF_TRUE; comp->c_mn = &fmt_mnull; } break;