Blame src/unicode-parser.c

Packit Service 1d8f1c
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit Service 1d8f1c
/* vim:set et sts=4: */
Packit Service 1d8f1c
/* ibus - The Input Bus
Packit Service 1d8f1c
 * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2018 Red Hat, Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is free software; you can redistribute it and/or
Packit Service 1d8f1c
 * modify it under the terms of the GNU Lesser General Public
Packit Service 1d8f1c
 * License as published by the Free Software Foundation; either
Packit Service 1d8f1c
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is distributed in the hope that it will be useful,
Packit Service 1d8f1c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 1d8f1c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 1d8f1c
 * Lesser General Public License for more details.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * You should have received a copy of the GNU Lesser General Public
Packit Service 1d8f1c
 * License along with this library; if not, write to the Free Software
Packit Service 1d8f1c
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit Service 1d8f1c
 * USA
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
Packit Service 1d8f1c
#ifdef HAVE_CONFIG_H
Packit Service 1d8f1c
#include <config.h>
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <glib.h>
Packit Service 1d8f1c
#include <stdlib.h>
Packit Service 1d8f1c
#include <string.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#ifdef HAVE_LOCALE_H
Packit Service 1d8f1c
#include <locale.h>
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "ibusunicode.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
#define NAMES_LIST_SUBJECT "The Unicode Standard"
Packit Service 1d8f1c
#define BLOCKS_SUBJECT "Blocks-"
Packit Service 1d8f1c
Packit Service 1d8f1c
/* This file has 21 lines about the license at the top of the file. */
Packit Service 1d8f1c
#define LICENSE_LINES 21
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef enum
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    UCD_NAMES_LIST,
Packit Service 1d8f1c
    UCD_BLOCKS
Packit Service 1d8f1c
} UCDType;
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _UnicodeData UnicodeData;
Packit Service 1d8f1c
typedef struct _UnicodeDataIndex UnicodeDataIndex;
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _UnicodeData{
Packit Service 1d8f1c
    gunichar code;
Packit Service 1d8f1c
    gchar   *name;
Packit Service 1d8f1c
    gchar   *alias;
Packit Service 1d8f1c
    gunichar start;
Packit Service 1d8f1c
    gunichar end;
Packit Service 1d8f1c
    GSList  *list;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _UnicodeDataIndex {
Packit Service 1d8f1c
    gchar *index;
Packit Service 1d8f1c
    UnicodeData *data_list;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
static gchar *unicode_version;
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
unicode_data_new_object (UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (data != NULL);
Packit Service 1d8f1c
    if (!data->name) {
Packit Service 1d8f1c
        g_warning ("No name in U+%04X", data->code);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    IBusUnicodeData *unicode =
Packit Service 1d8f1c
            ibus_unicode_data_new ("code",
Packit Service 1d8f1c
                                   data->code,
Packit Service 1d8f1c
                                   "name",
Packit Service 1d8f1c
                                   data->name ? g_strdup (data->name)
Packit Service 1d8f1c
                                           : g_strdup (""),
Packit Service 1d8f1c
                                   "alias",
Packit Service 1d8f1c
                                   data->alias ? g_strdup (data->alias)
Packit Service 1d8f1c
                                           : g_strdup (""),
Packit Service 1d8f1c
                                   NULL);
Packit Service 1d8f1c
    data->list = g_slist_append (data->list, unicode);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
unicode_block_new_object (UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (data != NULL);
Packit Service 1d8f1c
    if (!data->name) {
Packit Service 1d8f1c
        g_warning ("No name in U+%04X", data->start);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    IBusUnicodeBlock *block =
Packit Service 1d8f1c
            ibus_unicode_block_new ("start",
Packit Service 1d8f1c
                                    data->start,
Packit Service 1d8f1c
                                    "end",
Packit Service 1d8f1c
                                    data->end,
Packit Service 1d8f1c
                                    "name",
Packit Service 1d8f1c
                                    data->name ? g_strdup (data->name)
Packit Service 1d8f1c
                                           : g_strdup (""),
Packit Service 1d8f1c
                                   NULL);
Packit Service 1d8f1c
    data->list = g_slist_append (data->list, block);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
unicode_data_reset (UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (data != NULL);
Packit Service 1d8f1c
    data->code = 0;
Packit Service 1d8f1c
    g_clear_pointer (&data->name, g_free);
Packit Service 1d8f1c
    g_clear_pointer (&data->alias, g_free);
Packit Service 1d8f1c
    data->start = 0;
Packit Service 1d8f1c
    data->end = 0;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_names_list_parse_comment (const gchar *line)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    static gboolean has_version = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (has_version)
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    if (strlen (line) > 4 && strncmp (line, "@@@", 3) == 0) {
Packit Service 1d8f1c
        gchar **elements = g_strsplit (line, "\t", -1);
Packit Service 1d8f1c
        if (strncmp (elements[1], NAMES_LIST_SUBJECT,
Packit Service 1d8f1c
            strlen (NAMES_LIST_SUBJECT)) == 0) {
Packit Service 1d8f1c
            unicode_version =
Packit Service 1d8f1c
                    g_strdup (elements[1] + strlen (NAMES_LIST_SUBJECT) + 1);
Packit Service 1d8f1c
            has_version = TRUE;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        g_strfreev (elements);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_names_list_parse_alias (const gchar *line,
Packit Service 1d8f1c
                            UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (line != NULL, FALSE);
Packit Service 1d8f1c
    g_return_val_if_fail (data != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (*line == '\0')
Packit Service 1d8f1c
        return FALSE;
Packit Service 1d8f1c
    data->alias = g_strdup (line);
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_names_list_parse_indent_line (const gchar *line,
Packit Service 1d8f1c
                                  UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (line != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    switch (*line) {
Packit Service 1d8f1c
    case '\0':
Packit Service 1d8f1c
        return FALSE;
Packit Service 1d8f1c
    case '=':
Packit Service 1d8f1c
        line++;
Packit Service 1d8f1c
        while (*line == ' ') line++;
Packit Service 1d8f1c
        return ucd_names_list_parse_alias (line, data);
Packit Service 1d8f1c
    default:;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_names_list_parse_line (const gchar *line,
Packit Service 1d8f1c
                           UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (line != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    switch (*line) {
Packit Service 1d8f1c
    case '\0':
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    case ';':
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    case '@':
Packit Service 1d8f1c
        return ucd_names_list_parse_comment (line);
Packit Service 1d8f1c
    case '\t':
Packit Service 1d8f1c
        return ucd_names_list_parse_indent_line (line + 1, data);
Packit Service 1d8f1c
    default:;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (g_ascii_isxdigit (*line)) {
Packit Service 1d8f1c
        gchar **elements = g_strsplit (line, "\t", -1);
Packit Service 1d8f1c
        gunichar code;
Packit Service 1d8f1c
        gchar *name;
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (g_strv_length (elements) < 2) {
Packit Service 1d8f1c
            g_strfreev (elements);
Packit Service 1d8f1c
            return FALSE;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        code = g_ascii_strtoull (elements[0], NULL, 16);
Packit Service 1d8f1c
        name = g_strdup (elements[1]);
Packit Service 1d8f1c
        if (data->name) {
Packit Service 1d8f1c
            unicode_data_new_object (data);
Packit Service 1d8f1c
            unicode_data_reset (data);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        data->code = code;
Packit Service 1d8f1c
        data->name = name;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_blocks_parse_comment (const gchar *line)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    static gboolean has_version = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_val_if_fail (line != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (has_version)
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    while (*line == ' ') line++;
Packit Service 1d8f1c
    if (strlen (line) > strlen (BLOCKS_SUBJECT) &&
Packit Service 1d8f1c
        strncmp (line, BLOCKS_SUBJECT, strlen (BLOCKS_SUBJECT)) == 0) {
Packit Service 1d8f1c
            unicode_version = g_strdup (line + strlen (BLOCKS_SUBJECT) + 1);
Packit Service 1d8f1c
            has_version = TRUE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_blocks_parse_line (const gchar *line,
Packit Service 1d8f1c
                       UnicodeData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (line != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    switch (*line) {
Packit Service 1d8f1c
    case '\0':
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    case '#':
Packit Service 1d8f1c
        return ucd_blocks_parse_comment (line + 1);
Packit Service 1d8f1c
    default:;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (g_ascii_isxdigit (*line)) {
Packit Service 1d8f1c
        gchar *endptr = NULL;
Packit Service 1d8f1c
        gunichar start = g_ascii_strtoull (line, &endptr, 16);
Packit Service 1d8f1c
        gunichar end;
Packit Service 1d8f1c
        gchar *name = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (endptr == NULL || *endptr == '\0')
Packit Service 1d8f1c
            return FALSE;
Packit Service 1d8f1c
        while (*endptr == '.') endptr++;
Packit Service 1d8f1c
        line = endptr;
Packit Service 1d8f1c
        endptr = NULL;
Packit Service 1d8f1c
        end = g_ascii_strtoull (line, &endptr, 16);
Packit Service 1d8f1c
        if (endptr == NULL || *endptr == '\0')
Packit Service 1d8f1c
            return FALSE;
Packit Service 1d8f1c
        while (*endptr == ';') endptr++;
Packit Service 1d8f1c
        while (*endptr == ' ') endptr++;
Packit Service 1d8f1c
        if (*endptr == '\0')
Packit Service 1d8f1c
            return FALSE;
Packit Service 1d8f1c
        name = g_strdup (endptr);
Packit Service 1d8f1c
        if (data->name) {
Packit Service 1d8f1c
            unicode_block_new_object (data);
Packit Service 1d8f1c
            unicode_data_reset (data);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        data->start = start;
Packit Service 1d8f1c
        data->end = end;
Packit Service 1d8f1c
        data->name = name;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ucd_parse_file (const gchar *filename,
Packit Service 1d8f1c
                GSList     **list,
Packit Service 1d8f1c
                UCDType      type)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    UnicodeData data = { 0, };
Packit Service 1d8f1c
    gchar *content = NULL;
Packit Service 1d8f1c
    gsize length = 0;
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    gchar *head, *end, *line;
Packit Service 1d8f1c
    int n = 1;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_val_if_fail (filename != NULL, FALSE);
Packit Service 1d8f1c
    g_return_val_if_fail (list != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_file_get_contents (filename, &content, &length, &error)) {
Packit Service 1d8f1c
        g_warning ("Failed to load %s: %s",
Packit Service 1d8f1c
                   filename, error ? error->message : "");
Packit Service 1d8f1c
        goto failed_to_parse_ucd_names_list;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    head = end = content;
Packit Service 1d8f1c
    while (*end == '\n' && end - content < length) {
Packit Service 1d8f1c
        end++;
Packit Service 1d8f1c
        n++;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    head = end;
Packit Service 1d8f1c
    while (end - content < length) {
Packit Service 1d8f1c
        while (*end != '\n' && end - content < length)
Packit Service 1d8f1c
            end++;
Packit Service 1d8f1c
        if (end - content >= length)
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        line = g_strndup (head, end - head);
Packit Service 1d8f1c
        switch (type) {
Packit Service 1d8f1c
        case UCD_NAMES_LIST:
Packit Service 1d8f1c
            if (!ucd_names_list_parse_line (line, &data)) {
Packit Service 1d8f1c
                g_warning ("parse error #%d in %s version %s: %s",
Packit Service 1d8f1c
                           n, filename,
Packit Service 1d8f1c
                           unicode_version ? unicode_version : "(null)",
Packit Service 1d8f1c
                           line);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case UCD_BLOCKS:
Packit Service 1d8f1c
            if (!ucd_blocks_parse_line (line, &data)) {
Packit Service 1d8f1c
                g_warning ("parse error #%d in %s version %s: %s",
Packit Service 1d8f1c
                           n, filename,
Packit Service 1d8f1c
                           unicode_version ? unicode_version : "(null)",
Packit Service 1d8f1c
                           line);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        default:
Packit Service 1d8f1c
            g_abort ();
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        while (*end == '\n' && end - content < length) {
Packit Service 1d8f1c
            end++;
Packit Service 1d8f1c
            n++;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        g_free (line);
Packit Service 1d8f1c
        head = end;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (data.name != NULL) {
Packit Service 1d8f1c
        switch (type) {
Packit Service 1d8f1c
        case UCD_NAMES_LIST:
Packit Service 1d8f1c
            unicode_data_new_object (&data);
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case UCD_BLOCKS:
Packit Service 1d8f1c
            unicode_block_new_object (&data);
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        default:;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        unicode_data_reset (&data);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_free (content);
Packit Service 1d8f1c
    *list = data.list;
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
Packit Service 1d8f1c
failed_to_parse_ucd_names_list:
Packit Service 1d8f1c
    if (error)
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    g_clear_pointer (&content, g_free);
Packit Service 1d8f1c
    *list = data.list;
Packit Service 1d8f1c
    return FALSE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
block_list_dump (IBusUnicodeBlock *block,
Packit Service 1d8f1c
                 GString          *buff)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (buff != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_string_append (buff, "    /* TRANSLATORS: You might refer the "         \
Packit Service 1d8f1c
                           "translations from gucharmap with\n"               \
Packit Service 1d8f1c
                           "                    the following command:\n"     \
Packit Service 1d8f1c
                           "       msgmerge -C gucharmap.po ibus.po "         \
Packit Service 1d8f1c
                           "ibus.pot */\n");
Packit Service 1d8f1c
    gchar *line = g_strdup_printf ("    N_(\"%s\"),\n",
Packit Service 1d8f1c
                                   ibus_unicode_block_get_name (block));
Packit Service 1d8f1c
    g_string_append (buff, line);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ucd_block_translatable_save (const gchar *filename,
Packit Service 1d8f1c
                             GSList      *blocks_list)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gchar *content = NULL;
Packit Service 1d8f1c
    gsize length = 0;
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    gchar *p;
Packit Service 1d8f1c
    GString *buff = NULL;
Packit Service 1d8f1c
    int i;
Packit Service 1d8f1c
    GSList *list = blocks_list;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (filename != NULL);
Packit Service 1d8f1c
    g_return_if_fail (list != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_file_get_contents (__FILE__, &content, &length, &error)) {
Packit Service 1d8f1c
        g_warning ("Failed to load %s: %s", __FILE__, error->message);
Packit Service 1d8f1c
        g_clear_pointer (&error, g_error_free);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    buff = g_string_new (NULL);
Packit Service 1d8f1c
    p = content;
Packit Service 1d8f1c
    for (i = 0; i < LICENSE_LINES; i++, p++) {
Packit Service 1d8f1c
        if ((p = strchr (p, '\n')) == NULL)
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (p != NULL) {
Packit Service 1d8f1c
        g_string_append (buff, g_strndup (content, p - content));
Packit Service 1d8f1c
        g_string_append_c (buff, '\n');
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_clear_pointer (&content, g_free);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup_printf ("/* This file is generated by %s. */", __FILE__));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("include <glib/gi18n.h>\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("#ifndef __IBUS_UNICODE_GEN_H_\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("#define __IBUS_UNICODE_GEN_H_\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("const static char *unicode_blocks[] = {\n"));
Packit Service 1d8f1c
    g_slist_foreach (list, (GFunc)block_list_dump, buff);
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("};\n"));
Packit Service 1d8f1c
    g_string_append (buff, g_strdup ("#endif\n"));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_file_set_contents (filename, buff->str, -1, &error)) {
Packit Service 1d8f1c
        g_warning ("Failed to save emoji category file %s: %s", filename, error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_string_free (buff, TRUE);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
int
Packit Service 1d8f1c
main (int argc, char *argv[])
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gchar *prgname;
Packit Service 1d8f1c
    gchar *input_names_list = NULL;
Packit Service 1d8f1c
    gchar *input_blocks = NULL;
Packit Service 1d8f1c
    gchar *output_names_list = NULL;
Packit Service 1d8f1c
    gchar *output_blocks = NULL;
Packit Service 1d8f1c
    gchar *output_blocks_trans = NULL;
Packit Service 1d8f1c
    GOptionEntry     entries[] = {
Packit Service 1d8f1c
        { "input-names-list", 'n', 0, G_OPTION_ARG_STRING, &input_names_list,
Packit Service 1d8f1c
          "Parse NamesList.txt FILE in unicode.org ",
Packit Service 1d8f1c
          "FILE"
Packit Service 1d8f1c
        },
Packit Service 1d8f1c
        { "input-blocks", 'b', 0, G_OPTION_ARG_STRING, &input_blocks,
Packit Service 1d8f1c
          "Parse Blocks.txt FILE in unicode.org ",
Packit Service 1d8f1c
          "FILE"
Packit Service 1d8f1c
        },
Packit Service 1d8f1c
        { "output-names-list", 'o', 0, G_OPTION_ARG_STRING, &output_names_list,
Packit Service 1d8f1c
          "Save the Unicode data as FILE",
Packit Service 1d8f1c
          "FILE"
Packit Service 1d8f1c
        },
Packit Service 1d8f1c
        { "output-blocks", 'B', 0, G_OPTION_ARG_STRING, &output_blocks,
Packit Service 1d8f1c
          "Save the Unicode block list as FILE",
Packit Service 1d8f1c
          "FILE"
Packit Service 1d8f1c
        },
Packit Service 1d8f1c
        { "output-blocks-trans", 'C', 0, G_OPTION_ARG_STRING,
Packit Service 1d8f1c
          &output_blocks_trans,
Packit Service 1d8f1c
          "Save the translatable Unicode blocks as FILE",
Packit Service 1d8f1c
          "FILE"
Packit Service 1d8f1c
        },
Packit Service 1d8f1c
        { NULL }
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
    GOptionContext *context;
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GSList *names_list = NULL;
Packit Service 1d8f1c
    GSList *blocks_list = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
#ifdef HAVE_LOCALE_H
Packit Service 1d8f1c
    /* To output emoji warnings. */
Packit Service 1d8f1c
    setlocale (LC_ALL, "");
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
Packit Service 1d8f1c
    prgname = g_path_get_basename (argv[0]);
Packit Service 1d8f1c
    g_set_prgname (prgname);
Packit Service 1d8f1c
    g_free (prgname);
Packit Service 1d8f1c
Packit Service 1d8f1c
    context = g_option_context_new (NULL);
Packit Service 1d8f1c
    g_option_context_add_main_entries (context, entries, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (argc < 3) {
Packit Service 1d8f1c
        g_print ("%s", g_option_context_get_help (context, TRUE, NULL));
Packit Service 1d8f1c
        g_option_context_free (context);
Packit Service 1d8f1c
        return -1;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_option_context_parse (context, &argc, &argv, &error)) {
Packit Service 1d8f1c
        g_warning ("Failed options: %s", error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        return -1;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_option_context_free (context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (input_names_list) {
Packit Service 1d8f1c
        ucd_parse_file (input_names_list, &names_list, UCD_NAMES_LIST);
Packit Service 1d8f1c
        g_free (input_names_list);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (output_names_list && names_list)
Packit Service 1d8f1c
        ibus_unicode_data_save (output_names_list, names_list);
Packit Service 1d8f1c
    g_free (output_names_list);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (input_blocks) {
Packit Service 1d8f1c
        ucd_parse_file (input_blocks, &blocks_list, UCD_BLOCKS);
Packit Service 1d8f1c
        g_free (input_blocks);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (output_blocks && blocks_list)
Packit Service 1d8f1c
        ibus_unicode_block_save (output_blocks, blocks_list);
Packit Service 1d8f1c
    if (output_blocks_trans && blocks_list)
Packit Service 1d8f1c
        ucd_block_translatable_save (output_blocks_trans, blocks_list);
Packit Service 1d8f1c
    g_free (output_blocks);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (unicode_version);
Packit Service 1d8f1c
    return 0;
Packit Service 1d8f1c
}