From: Bruno Haible Date: Wed, 26 Dec 2007 15:44:50 +0000 (+0000) Subject: Avoid breaking line in the middle of a format directive. X-Git-Tag: v0.18~486 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50e9478d19d7264481e61bfa9385c4b6c8666123;p=thirdparty%2Fgettext.git Avoid breaking line in the middle of a format directive. --- diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index 500e65ced..a7aac4093 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,9 @@ +2007-12-22 Bruno Haible + + * write-po.c (wrap): Avoid breaking line in the middle of a format + directive. + Reported by Dwayne Bailey . + 2007-11-07 Jim Meyering Bruno Haible diff --git a/gettext-tools/src/write-po.c b/gettext-tools/src/write-po.c index 105d062cd..5961fa92c 100644 --- a/gettext-tools/src/write-po.c +++ b/gettext-tools/src/write-po.c @@ -522,6 +522,7 @@ wrap (const message_ty *mp, ostream_t stream, { const char *canon_charset; char *fmtdir; + char *fmtdirattr; const char *s; bool first_line; #if HAVE_ICONV @@ -583,7 +584,8 @@ wrap (const message_ty *mp, ostream_t stream, /* Determine the extent of format string directives. */ fmtdir = NULL; - if (is_stylable (stream) && value[0] != '\0') + fmtdirattr = NULL; + if (value[0] != '\0') { bool is_msgstr = (strlen (name) >= 6 && memcmp (name, "msgstr", 6) == 0); @@ -597,8 +599,9 @@ wrap (const message_ty *mp, ostream_t stream, struct formatstring_parser *parser = formatstring_parsers[i]; char *invalid_reason = NULL; void *descr; - char *fdp; - char *fd_end; + const char *fdp; + const char *fd_end; + char *fdap; fmtdir = XCALLOC (len, char); descr = parser->parse (value, is_msgstr, fmtdir, &invalid_reason); @@ -607,11 +610,13 @@ wrap (const message_ty *mp, ostream_t stream, /* Locate the FMTDIR_* bits and transform the array to an array of attributes. */ + fmtdirattr = XCALLOC (len, char); + fdap = fmtdirattr; fd_end = fmtdir + len; - for (fdp = fmtdir; fdp < fd_end; fdp++) + for (fdp = fmtdir, fdap = fmtdirattr; fdp < fd_end; fdp++, fdap++) if (*fdp & FMTDIR_START) { - char *fdq; + const char *fdq; for (fdq = fdp; fdq < fd_end; fdq++) if (*fdq & (FMTDIR_END | FMTDIR_ERROR)) break; @@ -621,13 +626,14 @@ wrap (const message_ty *mp, ostream_t stream, its end. It is a bug in the ->parse method. */ abort (); if (*fdq & FMTDIR_ERROR) - memset (fdp, ATTR_INVALID_FORMAT_DIRECTIVE, fdq - fdp + 1); + memset (fdap, ATTR_INVALID_FORMAT_DIRECTIVE, fdq - fdp + 1); else - memset (fdp, ATTR_FORMAT_DIRECTIVE, fdq - fdp + 1); + memset (fdap, ATTR_FORMAT_DIRECTIVE, fdq - fdp + 1); + fdap += fdq - fdp; fdp = fdq; } else - *fdp = 0; + *fdap = 0; break; } @@ -733,12 +739,16 @@ wrap (const message_ty *mp, ostream_t stream, } portion = XNMALLOC (portion_len, char); overrides = XNMALLOC (portion_len, char); - memset (overrides, UC_BREAK_UNDEFINED, portion_len); attributes = XNMALLOC (portion_len, char); for (ep = s, pp = portion, op = overrides, ap = attributes; ep < es; ep++) { char c = *ep; - char attr = (fmtdir != NULL ? fmtdir[ep - value] : 0); + char attr = (fmtdirattr != NULL ? fmtdirattr[ep - value] : 0); + char brk = UC_BREAK_UNDEFINED; + /* Don't break inside format directives. */ + if (attr == ATTR_FORMAT_DIRECTIVE + && (fmtdir[ep - value] & FMTDIR_START) == 0) + brk = UC_BREAK_PROHIBITED; if (is_escape (c)) { switch (c) @@ -754,7 +764,7 @@ wrap (const message_ty *mp, ostream_t stream, } *pp++ = '\\'; *pp++ = c; - op++; + *op++ = brk; *op++ = UC_BREAK_PROHIBITED; *ap++ = attr | ATTR_ESCAPE_SEQUENCE; *ap++ = attr | ATTR_ESCAPE_SEQUENCE; @@ -777,7 +787,7 @@ internationalized messages should not contain the `\\%c' escape sequence"), *pp++ = '0' + (((unsigned char) c >> 6) & 7); *pp++ = '0' + (((unsigned char) c >> 3) & 7); *pp++ = '0' + ((unsigned char) c & 7); - op++; + *op++ = brk; *op++ = UC_BREAK_PROHIBITED; *op++ = UC_BREAK_PROHIBITED; *op++ = UC_BREAK_PROHIBITED; @@ -790,7 +800,7 @@ internationalized messages should not contain the `\\%c' escape sequence"), { *pp++ = '\\'; *pp++ = c; - op++; + *op++ = brk; *op++ = UC_BREAK_PROHIBITED; *ap++ = attr | ATTR_ESCAPE_SEQUENCE; *ap++ = attr | ATTR_ESCAPE_SEQUENCE; @@ -838,6 +848,8 @@ internationalized messages should not contain the `\\%c' escape sequence"), insize = inptr - ep; memcpy_small (pp, ep, insize); pp += insize; + *op = brk; + memset_small (op + 1, UC_BREAK_PROHIBITED, insize - 1); op += insize; memset_small (ap, attr, insize); ap += insize; @@ -855,14 +867,15 @@ internationalized messages should not contain the `\\%c' escape sequence"), *pp++ = c; ep += 1; *pp++ = *ep; - op += 2; + *op++ = brk; + *op++ = UC_BREAK_PROHIBITED; *ap++ = attr; *ap++ = attr; } else { *pp++ = c; - op++; + *op++ = brk; *ap++ = attr; } } @@ -1118,6 +1131,8 @@ internationalized messages should not contain the `\\%c' escape sequence"), } while (*s); + if (fmtdirattr != NULL) + free (fmtdirattr); if (fmtdir != NULL) free (fmtdir); diff --git a/gettext-tools/tests/ChangeLog b/gettext-tools/tests/ChangeLog index d048b214d..7386cfabc 100644 --- a/gettext-tools/tests/ChangeLog +++ b/gettext-tools/tests/ChangeLog @@ -1,3 +1,8 @@ +2007-12-22 Bruno Haible + + * msgcat-17: New file. + * Makefile.am (TESTS): Add it. + 2007-11-15 Bruno Haible * gettext-8-prg.c: New file. diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index ebd03f9cb..a88d13830 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -29,7 +29,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \ msgattrib-properties-1 \ msgcat-1 msgcat-2 msgcat-3 msgcat-4 msgcat-5 msgcat-6 msgcat-7 \ msgcat-8 msgcat-9 msgcat-10 msgcat-11 msgcat-12 msgcat-13 msgcat-14 \ - msgcat-15 msgcat-16 \ + msgcat-15 msgcat-16 msgcat-17 \ msgcat-properties-1 msgcat-properties-2 \ msgcat-stringtable-1 \ msgcmp-1 msgcmp-2 msgcmp-3 msgcmp-4 \ diff --git a/gettext-tools/tests/msgcat-17 b/gettext-tools/tests/msgcat-17 new file mode 100755 index 000000000..1bc47b395 --- /dev/null +++ b/gettext-tools/tests/msgcat-17 @@ -0,0 +1,60 @@ +#! /bin/sh + +# Test msgcat with --width option. Check that format strings are not broken. + +tmpfiles="" +trap 'rm -fr $tmpfiles' 1 2 3 15 + +tmpfiles="$tmpfiles mcat-test17.in" +cat <<\EOF > mcat-test17.in +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "write error of a large result on a too small disk%s%s" +msgstr "Fehler beim Schreiben eines großen Ergebnisses auf eine zu kleine Platte%s%smit der jederzeitigen Möglichkeit eines Fehlers in jedem Moment und an jeder Stelle" + +#, c-format +msgid "write error of a big result on a too small disk%s%s" +msgstr "Fehler beim Schreiben eines großen Ergebnisses auf eine zu kleine Platte%s%smit der jederzeitigen Möglichkeit eines Fehlers in jedem Moment und an jeder Stelle" +EOF + +tmpfiles="$tmpfiles mcat-test17.tmp mcat-test17.out" +rm -f mcat-test17.tmp +: ${MSGCAT=msgcat} +${MSGCAT} -o mcat-test17.tmp --width=80 mcat-test17.in +test $? = 0 || { rm -fr $tmpfiles; exit 1; } +tr -d '\r' < mcat-test17.tmp > mcat-test17.out +test $? = 0 || { rm -fr $tmpfiles; exit 1; } + +tmpfiles="$tmpfiles mcat-test17.ok" +cat <<\EOF > mcat-test17.ok +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "write error of a large result on a too small disk%s%s" +msgstr "" +"Fehler beim Schreiben eines großen Ergebnisses auf eine zu kleine Platte%s%" +"smit der jederzeitigen Möglichkeit eines Fehlers in jedem Moment und an jeder " +"Stelle" + +#, c-format +msgid "write error of a big result on a too small disk%s%s" +msgstr "" +"Fehler beim Schreiben eines großen Ergebnisses auf eine zu kleine Platte%s" +"%smit der jederzeitigen Möglichkeit eines Fehlers in jedem Moment und an " +"jeder Stelle" +EOF + +: ${DIFF=diff} +${DIFF} mcat-test17.ok mcat-test17.out +result=$? + +rm -fr $tmpfiles + +exit $result