write-properties.c [plain text]
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "write-properties.h"
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "message.h"
#include "msgl-ascii.h"
#include "msgl-iconv.h"
#include "po-charset.h"
#include "utf8-ucs4.h"
#include "write-po.h"
#include "xalloc.h"
static const char *
conv_to_java (const char *string)
{
static const char hexdigit[] = "0123456789abcdef";
size_t length;
char *result;
if (is_ascii_string (string))
return string;
length = 0;
{
const char *str = string;
const char *str_limit = str + strlen (str);
while (str < str_limit)
{
unsigned int uc;
str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
length += (uc <= 0x007f ? 1 : uc < 0x10000 ? 6 : 12);
}
}
result = (char *) xmalloc (length + 1);
{
char *newstr = result;
const char *str = string;
const char *str_limit = str + strlen (str);
while (str < str_limit)
{
unsigned int uc;
str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
if (uc <= 0x007f)
*newstr++ = uc;
else if (uc < 0x10000)
{
sprintf (newstr, "\\u%c%c%c%c",
hexdigit[(uc >> 12) & 0x0f], hexdigit[(uc >> 8) & 0x0f],
hexdigit[(uc >> 4) & 0x0f], hexdigit[uc & 0x0f]);
newstr += 6;
}
else
{
unsigned int uc1 = 0xd800 + ((uc - 0x10000) >> 10);
unsigned int uc2 = 0xdc00 + ((uc - 0x10000) & 0x3ff);
sprintf (newstr, "\\u%c%c%c%c",
hexdigit[(uc1 >> 12) & 0x0f], hexdigit[(uc1 >> 8) & 0x0f],
hexdigit[(uc1 >> 4) & 0x0f], hexdigit[uc1 & 0x0f]);
newstr += 6;
sprintf (newstr, "\\u%c%c%c%c",
hexdigit[(uc2 >> 12) & 0x0f], hexdigit[(uc2 >> 8) & 0x0f],
hexdigit[(uc2 >> 4) & 0x0f], hexdigit[uc2 & 0x0f]);
newstr += 6;
}
}
*newstr = '\0';
}
return result;
}
static void
write_escaped_string (FILE *fp, const char *str, bool in_key)
{
static const char hexdigit[] = "0123456789abcdef";
const char *str_limit = str + strlen (str);
bool first = true;
while (str < str_limit)
{
unsigned int uc;
str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
if (uc == 0x0020 && (first || in_key))
{
putc ('\\', fp);
putc (' ', fp);
}
else if (uc == 0x0009)
{
putc ('\\', fp);
putc ('t', fp);
}
else if (uc == 0x000a)
{
putc ('\\', fp);
putc ('n', fp);
}
else if (uc == 0x000d)
{
putc ('\\', fp);
putc ('r', fp);
}
else if (uc == 0x000c)
{
putc ('\\', fp);
putc ('f', fp);
}
else if (
uc == '\\'
|| uc == '#' || uc == '!'
|| uc == '=' || uc == ':')
{
putc ('\\', fp);
putc (uc, fp);
}
else if (uc >= 0x0020 && uc <= 0x007e)
{
putc (uc, fp);
}
else if (uc < 0x10000)
{
fprintf (fp, "\\u%c%c%c%c",
hexdigit[(uc >> 12) & 0x0f], hexdigit[(uc >> 8) & 0x0f],
hexdigit[(uc >> 4) & 0x0f], hexdigit[uc & 0x0f]);
}
else
{
unsigned int uc1 = 0xd800 + ((uc - 0x10000) >> 10);
unsigned int uc2 = 0xdc00 + ((uc - 0x10000) & 0x3ff);
fprintf (fp, "\\u%c%c%c%c",
hexdigit[(uc1 >> 12) & 0x0f], hexdigit[(uc1 >> 8) & 0x0f],
hexdigit[(uc1 >> 4) & 0x0f], hexdigit[uc1 & 0x0f]);
fprintf (fp, "\\u%c%c%c%c",
hexdigit[(uc2 >> 12) & 0x0f], hexdigit[(uc2 >> 8) & 0x0f],
hexdigit[(uc2 >> 4) & 0x0f], hexdigit[uc2 & 0x0f]);
}
first = false;
}
}
static void
write_message (FILE *fp, const message_ty *mp, size_t page_width, bool debug)
{
message_print_comment (mp, fp);
message_print_comment_dot (mp, fp);
message_print_comment_filepos (mp, fp, false, page_width);
message_print_comment_flags (mp, fp, debug);
if (mp->msgid[0] == '\0'
|| mp->msgstr[0] == '\0'
|| (mp->is_fuzzy && mp->msgid[0] != '\0'))
putc ('!', fp);
write_escaped_string (fp, mp->msgid, true);
putc ('=', fp);
write_escaped_string (fp, mp->msgstr, false);
putc ('\n', fp);
}
static void
write_properties (FILE *fp, message_list_ty *mlp, const char *canon_encoding,
size_t page_width, bool debug)
{
bool blank_line;
size_t j, i;
iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL);
for (j = 0; j < mlp->nitems; ++j)
{
message_ty *mp = mlp->item[j];
if (mp->comment != NULL)
for (i = 0; i < mp->comment->nitems; ++i)
mp->comment->item[i] = conv_to_java (mp->comment->item[i]);
if (mp->comment_dot != NULL)
for (i = 0; i < mp->comment_dot->nitems; ++i)
mp->comment_dot->item[i] = conv_to_java (mp->comment_dot->item[i]);
}
blank_line = false;
for (j = 0; j < mlp->nitems; ++j)
{
const message_ty *mp = mlp->item[j];
if (mp->msgid_plural == NULL && !mp->obsolete)
{
if (blank_line)
putc ('\n', fp);
write_message (fp, mp, page_width, debug);
blank_line = true;
}
}
}
void
msgdomain_list_print_properties (msgdomain_list_ty *mdlp, FILE *fp,
size_t page_width, bool debug)
{
message_list_ty *mlp;
if (mdlp->nitems == 1)
mlp = mdlp->item[0]->messages;
else
mlp = message_list_alloc (false);
write_properties (fp, mlp, mdlp->encoding, page_width, debug);
}