{
const char *canon_charset;
char *fmtdir;
+ char *fmtdirattr;
const char *s;
bool first_line;
#if HAVE_ICONV
/* 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);
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);
/* 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;
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;
}
}
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)
}
*pp++ = '\\';
*pp++ = c;
- op++;
+ *op++ = brk;
*op++ = UC_BREAK_PROHIBITED;
*ap++ = attr | ATTR_ESCAPE_SEQUENCE;
*ap++ = attr | ATTR_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;
{
*pp++ = '\\';
*pp++ = c;
- op++;
+ *op++ = brk;
*op++ = UC_BREAK_PROHIBITED;
*ap++ = attr | ATTR_ESCAPE_SEQUENCE;
*ap++ = attr | ATTR_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;
*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;
}
}
}
while (*s);
+ if (fmtdirattr != NULL)
+ free (fmtdirattr);
if (fmtdir != NULL)
free (fmtdir);
--- /dev/null
+#! /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