1*b5d75fbcSdogcow /* $NetBSD: mklocaledb.c,v 1.2 2009/01/05 02:55:34 dogcow Exp $ */ 252ed7b03Stnozaki 352ed7b03Stnozaki /*- 452ed7b03Stnozaki * Copyright (c)2008 Citrus Project, 552ed7b03Stnozaki * All rights reserved. 652ed7b03Stnozaki * 752ed7b03Stnozaki * Redistribution and use in source and binary forms, with or without 852ed7b03Stnozaki * modification, are permitted provided that the following conditions 952ed7b03Stnozaki * are met: 1052ed7b03Stnozaki * 1. Redistributions of source code must retain the above copyright 1152ed7b03Stnozaki * notice, this list of conditions and the following disclaimer. 1252ed7b03Stnozaki * 2. Redistributions in binary form must reproduce the above copyright 1352ed7b03Stnozaki * notice, this list of conditions and the following disclaimer in the 1452ed7b03Stnozaki * documentation and/or other materials provided with the distribution. 1552ed7b03Stnozaki * 1652ed7b03Stnozaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1752ed7b03Stnozaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1852ed7b03Stnozaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1952ed7b03Stnozaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2052ed7b03Stnozaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2152ed7b03Stnozaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2252ed7b03Stnozaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2352ed7b03Stnozaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2452ed7b03Stnozaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2552ed7b03Stnozaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2652ed7b03Stnozaki * SUCH DAMAGE. 2752ed7b03Stnozaki */ 2852ed7b03Stnozaki 2952ed7b03Stnozaki /* 3052ed7b03Stnozaki * XXX TEMPORARY IMPLEMENTATION. 3152ed7b03Stnozaki * don't waste your time, all we need is localedef(1). 3252ed7b03Stnozaki */ 3352ed7b03Stnozaki 3452ed7b03Stnozaki #if HAVE_NBTOOL_CONFIG_H 3552ed7b03Stnozaki #include "nbtool_config.h" 3652ed7b03Stnozaki #endif 3752ed7b03Stnozaki 38*b5d75fbcSdogcow #include <sys/cdefs.h> 39*b5d75fbcSdogcow #if !defined(lint) 40*b5d75fbcSdogcow __RCSID("$NetBSD: mklocaledb.c,v 1.2 2009/01/05 02:55:34 dogcow Exp $"); 41*b5d75fbcSdogcow #endif /* not lint */ 42*b5d75fbcSdogcow 4352ed7b03Stnozaki #include <assert.h> 4452ed7b03Stnozaki #include <err.h> 4552ed7b03Stnozaki #include <errno.h> 4652ed7b03Stnozaki #include <limits.h> 4752ed7b03Stnozaki #include <stdint.h> 4852ed7b03Stnozaki #include <stdio.h> 4952ed7b03Stnozaki #include <stdlib.h> 5052ed7b03Stnozaki #include <string.h> 5152ed7b03Stnozaki #include <unistd.h> 5252ed7b03Stnozaki 5352ed7b03Stnozaki #include "fix_grouping.h" 5452ed7b03Stnozaki 5552ed7b03Stnozaki #include "citrus_namespace.h" 5652ed7b03Stnozaki #include "citrus_bcs.h" 5752ed7b03Stnozaki #include "citrus_types.h" 5852ed7b03Stnozaki #include "citrus_region.h" 5952ed7b03Stnozaki #include "citrus_db_factory.h" 6052ed7b03Stnozaki #include "citrus_db_hash.h" 6152ed7b03Stnozaki #include "citrus_db.h" 6252ed7b03Stnozaki 6352ed7b03Stnozaki #include "citrus_lc_monetary.h" 6452ed7b03Stnozaki #include "citrus_lc_numeric.h" 6552ed7b03Stnozaki #include "citrus_lc_time.h" 6652ed7b03Stnozaki #include "citrus_lc_messages.h" 6752ed7b03Stnozaki 6852ed7b03Stnozaki void mklocaledb(const char *, FILE *, FILE *); 6952ed7b03Stnozaki 7052ed7b03Stnozaki /* 7152ed7b03Stnozaki * TODO: -d debug options's output. 7252ed7b03Stnozaki */ 7352ed7b03Stnozaki extern int debug; 7452ed7b03Stnozaki extern void usage(void); 7552ed7b03Stnozaki 7652ed7b03Stnozaki static int 7752ed7b03Stnozaki save_as_string(struct _db_factory *df, 7852ed7b03Stnozaki const char *key, const char *value) 7952ed7b03Stnozaki { 8052ed7b03Stnozaki return _db_factory_addstr_by_s(df, key, value); 8152ed7b03Stnozaki } 8252ed7b03Stnozaki 8352ed7b03Stnozaki static int 8452ed7b03Stnozaki save_as_grouping(struct _db_factory *df, 8552ed7b03Stnozaki const char *key, const char *value) 8652ed7b03Stnozaki { 8752ed7b03Stnozaki value = __fix_locale_grouping_str(value); 8852ed7b03Stnozaki return _db_factory_addstr_by_s(df, key, value); 8952ed7b03Stnozaki } 9052ed7b03Stnozaki 9152ed7b03Stnozaki static int 9252ed7b03Stnozaki save_as_uint8(struct _db_factory *df, 9352ed7b03Stnozaki const char *key, const char *head) 9452ed7b03Stnozaki { 9552ed7b03Stnozaki char *tail; 9652ed7b03Stnozaki unsigned long int value; 9752ed7b03Stnozaki uint8_t u8; 9852ed7b03Stnozaki 9952ed7b03Stnozaki value = _bcs_strtoul(head, &tail, 0); 10052ed7b03Stnozaki if (head == tail || value > 0xFF) 10152ed7b03Stnozaki return 1; 10252ed7b03Stnozaki u8 = (uint8_t)(value & 0xFF); 10352ed7b03Stnozaki return _db_factory_add8_by_s(df, key, u8); 10452ed7b03Stnozaki } 10552ed7b03Stnozaki 10652ed7b03Stnozaki typedef struct { 10752ed7b03Stnozaki const char *key; 10852ed7b03Stnozaki int (*save)(struct _db_factory *, 10952ed7b03Stnozaki const char *, const char *); 11052ed7b03Stnozaki } token_t; 11152ed7b03Stnozaki 11252ed7b03Stnozaki typedef struct { 11352ed7b03Stnozaki const char *magic, * vers_sym; 11452ed7b03Stnozaki uint32_t version; 11552ed7b03Stnozaki const token_t tokens[]; 11652ed7b03Stnozaki } category_t; 11752ed7b03Stnozaki 11852ed7b03Stnozaki static const category_t lc_monetary = { 11952ed7b03Stnozaki _CITRUS_LC_MONETARY_MAGIC_1, 12052ed7b03Stnozaki _CITRUS_LC_MONETARY_SYM_VERSION, 12152ed7b03Stnozaki _CITRUS_LC_MONETARY_VERSION, 12252ed7b03Stnozaki { 12352ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_CURR_SYMBOL, &save_as_string }, 12452ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_CURRENCY_SYMBOL, &save_as_string }, 12552ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_MON_DECIMAL_POINT, &save_as_string }, 12652ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_MON_THOUSANDS_SEP, &save_as_string }, 12752ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_MON_GROUPING, &save_as_grouping }, 12852ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_POSITIVE_SIGN, &save_as_string }, 12952ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_NEGATIVE_SIGN, &save_as_string }, 13052ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_FRAC_DIGITS, &save_as_uint8 }, 13152ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_FRAC_DIGITS, &save_as_uint8 }, 13252ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_P_CS_PRECEDES, &save_as_uint8 }, 13352ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_P_SEP_BY_SPACE, &save_as_uint8 }, 13452ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_N_CS_PRECEDES, &save_as_uint8 }, 13552ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_N_SEP_BY_SPACE, &save_as_uint8 }, 13652ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_P_SIGN_POSN, &save_as_uint8 }, 13752ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_N_SIGN_POSN, &save_as_uint8 }, 13852ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_P_CS_PRECEDES, &save_as_uint8 }, 13952ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_N_CS_PRECEDES, &save_as_uint8 }, 14052ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_P_SEP_BY_SPACE, &save_as_uint8 }, 14152ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_N_SEP_BY_SPACE, &save_as_uint8 }, 14252ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_P_SIGN_POSN, &save_as_uint8 }, 14352ed7b03Stnozaki { _CITRUS_LC_MONETARY_SYM_INT_N_SIGN_POSN, &save_as_uint8 }, 14452ed7b03Stnozaki { NULL }, 14552ed7b03Stnozaki }, 14652ed7b03Stnozaki }; 14752ed7b03Stnozaki 14852ed7b03Stnozaki static const category_t lc_numeric = { 14952ed7b03Stnozaki _CITRUS_LC_NUMERIC_MAGIC_1, 15052ed7b03Stnozaki _CITRUS_LC_NUMERIC_SYM_VERSION, 15152ed7b03Stnozaki _CITRUS_LC_NUMERIC_VERSION, 15252ed7b03Stnozaki { 15352ed7b03Stnozaki { _CITRUS_LC_NUMERIC_SYM_DECIMAL_POINT, &save_as_string }, 15452ed7b03Stnozaki { _CITRUS_LC_NUMERIC_SYM_THOUSANDS_SEP, &save_as_string }, 15552ed7b03Stnozaki { _CITRUS_LC_NUMERIC_SYM_GROUPING, &save_as_grouping }, 15652ed7b03Stnozaki { NULL }, 15752ed7b03Stnozaki }, 15852ed7b03Stnozaki }; 15952ed7b03Stnozaki 16052ed7b03Stnozaki static const category_t lc_time = { 16152ed7b03Stnozaki _CITRUS_LC_TIME_MAGIC_1, 16252ed7b03Stnozaki _CITRUS_LC_TIME_SYM_VERSION, 16352ed7b03Stnozaki _CITRUS_LC_TIME_VERSION, 16452ed7b03Stnozaki { 16552ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_1, &save_as_string }, 16652ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_2, &save_as_string }, 16752ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_3, &save_as_string }, 16852ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_4, &save_as_string }, 16952ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_5, &save_as_string }, 17052ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_6, &save_as_string }, 17152ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABDAY_7, &save_as_string }, 17252ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_1, &save_as_string }, 17352ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_2, &save_as_string }, 17452ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_3, &save_as_string }, 17552ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_4, &save_as_string }, 17652ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_5, &save_as_string }, 17752ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_6, &save_as_string }, 17852ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_DAY_7, &save_as_string }, 17952ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_1, &save_as_string }, 18052ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_2, &save_as_string }, 18152ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_3, &save_as_string }, 18252ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_4, &save_as_string }, 18352ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_5, &save_as_string }, 18452ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_6, &save_as_string }, 18552ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_7, &save_as_string }, 18652ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_8, &save_as_string }, 18752ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_9, &save_as_string }, 18852ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_10, &save_as_string }, 18952ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_11, &save_as_string }, 19052ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_ABMON_12, &save_as_string }, 19152ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_1, &save_as_string }, 19252ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_2, &save_as_string }, 19352ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_3, &save_as_string }, 19452ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_4, &save_as_string }, 19552ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_5, &save_as_string }, 19652ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_6, &save_as_string }, 19752ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_7, &save_as_string }, 19852ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_8, &save_as_string }, 19952ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_9, &save_as_string }, 20052ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_10, &save_as_string }, 20152ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_11, &save_as_string }, 20252ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_MON_12, &save_as_string }, 20352ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_AM_STR, &save_as_string }, 20452ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_PM_STR, &save_as_string }, 20552ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_D_T_FMT, &save_as_string }, 20652ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_D_FMT, &save_as_string }, 20752ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_T_FMT, &save_as_string }, 20852ed7b03Stnozaki { _CITRUS_LC_TIME_SYM_T_FMT_AMPM, &save_as_string }, 20952ed7b03Stnozaki { NULL }, 21052ed7b03Stnozaki }, 21152ed7b03Stnozaki }; 21252ed7b03Stnozaki 21352ed7b03Stnozaki static const category_t lc_messages = { 21452ed7b03Stnozaki _CITRUS_LC_MESSAGES_MAGIC_1, 21552ed7b03Stnozaki _CITRUS_LC_MESSAGES_SYM_VERSION, 21652ed7b03Stnozaki _CITRUS_LC_MESSAGES_VERSION, 21752ed7b03Stnozaki { 21852ed7b03Stnozaki { _CITRUS_LC_MESSAGES_SYM_YESEXPR, &save_as_string }, 21952ed7b03Stnozaki { _CITRUS_LC_MESSAGES_SYM_NOEXPR, &save_as_string }, 22052ed7b03Stnozaki { _CITRUS_LC_MESSAGES_SYM_YESSTR, &save_as_string }, 22152ed7b03Stnozaki { _CITRUS_LC_MESSAGES_SYM_NOSTR, &save_as_string }, 22252ed7b03Stnozaki { NULL }, 22352ed7b03Stnozaki }, 22452ed7b03Stnozaki }; 22552ed7b03Stnozaki 22652ed7b03Stnozaki void 22752ed7b03Stnozaki mklocaledb(const char *type, FILE *reader, FILE *writer) 22852ed7b03Stnozaki { 22952ed7b03Stnozaki static const char delim[3] = { '\0', '\0', '#' }; 23052ed7b03Stnozaki const category_t *category = NULL; 23152ed7b03Stnozaki struct _db_factory *df; 23252ed7b03Stnozaki const token_t *token; 23352ed7b03Stnozaki char *line; 23452ed7b03Stnozaki size_t size; 23552ed7b03Stnozaki void *serialized; 23652ed7b03Stnozaki struct _region r; 23752ed7b03Stnozaki 23852ed7b03Stnozaki _DIAGASSERT(type != NULL); 23952ed7b03Stnozaki _DIAGASSERT(reader != NULL); 24052ed7b03Stnozaki _DIAGASSERT(writer != NULL); 24152ed7b03Stnozaki 24252ed7b03Stnozaki if (!strcasecmp(type, "MONETARY")) 24352ed7b03Stnozaki category = &lc_monetary; 24452ed7b03Stnozaki else if (!strcasecmp(type, "NUMERIC")) 24552ed7b03Stnozaki category = &lc_numeric; 24652ed7b03Stnozaki else if (!strcasecmp(type, "TIME")) 24752ed7b03Stnozaki category = &lc_time; 24852ed7b03Stnozaki else if (!strcasecmp(type, "MESSAGES")) 24952ed7b03Stnozaki category = &lc_messages; 25052ed7b03Stnozaki else { 25152ed7b03Stnozaki usage(); 25252ed7b03Stnozaki /*NOTREACHED*/ 25352ed7b03Stnozaki } 25452ed7b03Stnozaki if (_db_factory_create(&df, &_db_hash_std, NULL)) 25552ed7b03Stnozaki errx(1, "can't create db factory.\n"); 25652ed7b03Stnozaki if (_db_factory_add32_by_s(df, category->vers_sym, category->version)) 25752ed7b03Stnozaki errx(1, "can't store db.\n"); 25852ed7b03Stnozaki token = &category->tokens[0]; 25952ed7b03Stnozaki while (token->key != NULL) { 26052ed7b03Stnozaki line = fparseln(reader, NULL, 26152ed7b03Stnozaki NULL, delim, FPARSELN_UNESCALL); 26252ed7b03Stnozaki if (line == NULL) 26352ed7b03Stnozaki errx(1, "can't read line.\n"); 26452ed7b03Stnozaki if ((*token->save)(df, token->key, (const char *)line)) 26552ed7b03Stnozaki errx(1, "can't store db.\n"); 26652ed7b03Stnozaki free(line); 26752ed7b03Stnozaki ++token; 26852ed7b03Stnozaki } 26952ed7b03Stnozaki size = _db_factory_calc_size(df); 27052ed7b03Stnozaki _DIAGASSERT(size > 0); 27152ed7b03Stnozaki serialized = malloc(size); 27252ed7b03Stnozaki if (serialized == NULL) 27352ed7b03Stnozaki errx(1, "can't malloc.\n"); 27452ed7b03Stnozaki _DIAGASSERT(serialized != NULL); 27552ed7b03Stnozaki _region_init(&r, serialized, size); 27652ed7b03Stnozaki if (_db_factory_serialize(df, category->magic, &r)) 27752ed7b03Stnozaki errx(1, "can't serialize db.\n"); 27852ed7b03Stnozaki fwrite(serialized, size, 1, writer); 27952ed7b03Stnozaki _db_factory_free(df); 28052ed7b03Stnozaki } 281