1 1.4 christos /* $NetBSD: mklocaledb.c,v 1.4 2015/06/16 22:54:10 christos Exp $ */ 2 1.1 tnozaki 3 1.1 tnozaki /*- 4 1.1 tnozaki * Copyright (c)2008 Citrus Project, 5 1.1 tnozaki * All rights reserved. 6 1.1 tnozaki * 7 1.1 tnozaki * Redistribution and use in source and binary forms, with or without 8 1.1 tnozaki * modification, are permitted provided that the following conditions 9 1.1 tnozaki * are met: 10 1.1 tnozaki * 1. Redistributions of source code must retain the above copyright 11 1.1 tnozaki * notice, this list of conditions and the following disclaimer. 12 1.1 tnozaki * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 tnozaki * notice, this list of conditions and the following disclaimer in the 14 1.1 tnozaki * documentation and/or other materials provided with the distribution. 15 1.1 tnozaki * 16 1.1 tnozaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 tnozaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 tnozaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 tnozaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 tnozaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 tnozaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 tnozaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 tnozaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 tnozaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 tnozaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 tnozaki * SUCH DAMAGE. 27 1.1 tnozaki */ 28 1.1 tnozaki 29 1.1 tnozaki /* 30 1.1 tnozaki * XXX TEMPORARY IMPLEMENTATION. 31 1.1 tnozaki * don't waste your time, all we need is localedef(1). 32 1.1 tnozaki */ 33 1.1 tnozaki 34 1.2 dogcow #if HAVE_NBTOOL_CONFIG_H 35 1.2 dogcow #include "nbtool_config.h" 36 1.2 dogcow #endif 37 1.2 dogcow 38 1.1 tnozaki #include <sys/cdefs.h> 39 1.1 tnozaki #if !defined(lint) 40 1.4 christos __RCSID("$NetBSD: mklocaledb.c,v 1.4 2015/06/16 22:54:10 christos Exp $"); 41 1.1 tnozaki #endif /* not lint */ 42 1.1 tnozaki 43 1.1 tnozaki #include <assert.h> 44 1.1 tnozaki #include <err.h> 45 1.1 tnozaki #include <errno.h> 46 1.1 tnozaki #include <limits.h> 47 1.1 tnozaki #include <stdint.h> 48 1.1 tnozaki #include <stdio.h> 49 1.1 tnozaki #include <stdlib.h> 50 1.1 tnozaki #include <string.h> 51 1.1 tnozaki #include <unistd.h> 52 1.1 tnozaki 53 1.1 tnozaki #include "fix_grouping.h" 54 1.1 tnozaki 55 1.1 tnozaki #include "citrus_namespace.h" 56 1.1 tnozaki #include "citrus_bcs.h" 57 1.1 tnozaki #include "citrus_types.h" 58 1.1 tnozaki #include "citrus_region.h" 59 1.1 tnozaki #include "citrus_db_factory.h" 60 1.1 tnozaki #include "citrus_db_hash.h" 61 1.1 tnozaki #include "citrus_db.h" 62 1.1 tnozaki 63 1.1 tnozaki #include "citrus_lc_monetary.h" 64 1.1 tnozaki #include "citrus_lc_numeric.h" 65 1.1 tnozaki #include "citrus_lc_time.h" 66 1.1 tnozaki #include "citrus_lc_messages.h" 67 1.1 tnozaki 68 1.1 tnozaki void mklocaledb(const char *, FILE *, FILE *); 69 1.1 tnozaki 70 1.1 tnozaki /* 71 1.1 tnozaki * TODO: -d debug options's output. 72 1.1 tnozaki */ 73 1.1 tnozaki extern int debug; 74 1.1 tnozaki extern void usage(void); 75 1.1 tnozaki 76 1.1 tnozaki static int 77 1.1 tnozaki save_as_string(struct _db_factory *df, 78 1.1 tnozaki const char *key, const char *value) 79 1.1 tnozaki { 80 1.1 tnozaki return _db_factory_addstr_by_s(df, key, value); 81 1.1 tnozaki } 82 1.1 tnozaki 83 1.1 tnozaki static int 84 1.1 tnozaki save_as_grouping(struct _db_factory *df, 85 1.1 tnozaki const char *key, const char *value) 86 1.1 tnozaki { 87 1.1 tnozaki value = __fix_locale_grouping_str(value); 88 1.1 tnozaki return _db_factory_addstr_by_s(df, key, value); 89 1.1 tnozaki } 90 1.1 tnozaki 91 1.1 tnozaki static int 92 1.1 tnozaki save_as_uint8(struct _db_factory *df, 93 1.1 tnozaki const char *key, const char *head) 94 1.1 tnozaki { 95 1.1 tnozaki char *tail; 96 1.1 tnozaki unsigned long int value; 97 1.1 tnozaki uint8_t u8; 98 1.1 tnozaki 99 1.1 tnozaki value = _bcs_strtoul(head, &tail, 0); 100 1.1 tnozaki if (head == tail || value > 0xFF) 101 1.1 tnozaki return 1; 102 1.1 tnozaki u8 = (uint8_t)(value & 0xFF); 103 1.1 tnozaki return _db_factory_add8_by_s(df, key, u8); 104 1.1 tnozaki } 105 1.1 tnozaki 106 1.1 tnozaki typedef struct { 107 1.1 tnozaki const char *key; 108 1.1 tnozaki int (*save)(struct _db_factory *, 109 1.1 tnozaki const char *, const char *); 110 1.1 tnozaki } token_t; 111 1.1 tnozaki 112 1.1 tnozaki typedef struct { 113 1.1 tnozaki const char *magic, * vers_sym; 114 1.1 tnozaki uint32_t version; 115 1.1 tnozaki const token_t tokens[]; 116 1.1 tnozaki } category_t; 117 1.1 tnozaki 118 1.1 tnozaki static const category_t lc_monetary = { 119 1.1 tnozaki _CITRUS_LC_MONETARY_MAGIC_1, 120 1.1 tnozaki _CITRUS_LC_MONETARY_SYM_VERSION, 121 1.1 tnozaki _CITRUS_LC_MONETARY_VERSION, 122 1.1 tnozaki { 123 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_CURR_SYMBOL, &save_as_string }, 124 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_CURRENCY_SYMBOL, &save_as_string }, 125 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_MON_DECIMAL_POINT, &save_as_string }, 126 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_MON_THOUSANDS_SEP, &save_as_string }, 127 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_MON_GROUPING, &save_as_grouping }, 128 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_POSITIVE_SIGN, &save_as_string }, 129 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_NEGATIVE_SIGN, &save_as_string }, 130 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_FRAC_DIGITS, &save_as_uint8 }, 131 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_FRAC_DIGITS, &save_as_uint8 }, 132 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_P_CS_PRECEDES, &save_as_uint8 }, 133 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_P_SEP_BY_SPACE, &save_as_uint8 }, 134 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_N_CS_PRECEDES, &save_as_uint8 }, 135 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_N_SEP_BY_SPACE, &save_as_uint8 }, 136 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_P_SIGN_POSN, &save_as_uint8 }, 137 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_N_SIGN_POSN, &save_as_uint8 }, 138 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_P_CS_PRECEDES, &save_as_uint8 }, 139 1.3 joerg { _CITRUS_LC_MONETARY_SYM_INT_P_SEP_BY_SPACE, &save_as_uint8 }, 140 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_N_CS_PRECEDES, &save_as_uint8 }, 141 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_N_SEP_BY_SPACE, &save_as_uint8 }, 142 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_P_SIGN_POSN, &save_as_uint8 }, 143 1.1 tnozaki { _CITRUS_LC_MONETARY_SYM_INT_N_SIGN_POSN, &save_as_uint8 }, 144 1.1 tnozaki { NULL }, 145 1.1 tnozaki }, 146 1.1 tnozaki }; 147 1.1 tnozaki 148 1.1 tnozaki static const category_t lc_numeric = { 149 1.1 tnozaki _CITRUS_LC_NUMERIC_MAGIC_1, 150 1.1 tnozaki _CITRUS_LC_NUMERIC_SYM_VERSION, 151 1.1 tnozaki _CITRUS_LC_NUMERIC_VERSION, 152 1.1 tnozaki { 153 1.1 tnozaki { _CITRUS_LC_NUMERIC_SYM_DECIMAL_POINT, &save_as_string }, 154 1.1 tnozaki { _CITRUS_LC_NUMERIC_SYM_THOUSANDS_SEP, &save_as_string }, 155 1.1 tnozaki { _CITRUS_LC_NUMERIC_SYM_GROUPING, &save_as_grouping }, 156 1.1 tnozaki { NULL }, 157 1.1 tnozaki }, 158 1.1 tnozaki }; 159 1.1 tnozaki 160 1.1 tnozaki static const category_t lc_time = { 161 1.1 tnozaki _CITRUS_LC_TIME_MAGIC_1, 162 1.1 tnozaki _CITRUS_LC_TIME_SYM_VERSION, 163 1.1 tnozaki _CITRUS_LC_TIME_VERSION, 164 1.1 tnozaki { 165 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_1, &save_as_string }, 166 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_2, &save_as_string }, 167 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_3, &save_as_string }, 168 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_4, &save_as_string }, 169 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_5, &save_as_string }, 170 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_6, &save_as_string }, 171 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABDAY_7, &save_as_string }, 172 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_1, &save_as_string }, 173 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_2, &save_as_string }, 174 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_3, &save_as_string }, 175 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_4, &save_as_string }, 176 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_5, &save_as_string }, 177 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_6, &save_as_string }, 178 1.1 tnozaki { _CITRUS_LC_TIME_SYM_DAY_7, &save_as_string }, 179 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_1, &save_as_string }, 180 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_2, &save_as_string }, 181 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_3, &save_as_string }, 182 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_4, &save_as_string }, 183 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_5, &save_as_string }, 184 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_6, &save_as_string }, 185 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_7, &save_as_string }, 186 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_8, &save_as_string }, 187 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_9, &save_as_string }, 188 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_10, &save_as_string }, 189 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_11, &save_as_string }, 190 1.1 tnozaki { _CITRUS_LC_TIME_SYM_ABMON_12, &save_as_string }, 191 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_1, &save_as_string }, 192 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_2, &save_as_string }, 193 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_3, &save_as_string }, 194 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_4, &save_as_string }, 195 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_5, &save_as_string }, 196 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_6, &save_as_string }, 197 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_7, &save_as_string }, 198 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_8, &save_as_string }, 199 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_9, &save_as_string }, 200 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_10, &save_as_string }, 201 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_11, &save_as_string }, 202 1.1 tnozaki { _CITRUS_LC_TIME_SYM_MON_12, &save_as_string }, 203 1.1 tnozaki { _CITRUS_LC_TIME_SYM_AM_STR, &save_as_string }, 204 1.1 tnozaki { _CITRUS_LC_TIME_SYM_PM_STR, &save_as_string }, 205 1.1 tnozaki { _CITRUS_LC_TIME_SYM_D_T_FMT, &save_as_string }, 206 1.1 tnozaki { _CITRUS_LC_TIME_SYM_D_FMT, &save_as_string }, 207 1.1 tnozaki { _CITRUS_LC_TIME_SYM_T_FMT, &save_as_string }, 208 1.1 tnozaki { _CITRUS_LC_TIME_SYM_T_FMT_AMPM, &save_as_string }, 209 1.1 tnozaki { NULL }, 210 1.1 tnozaki }, 211 1.1 tnozaki }; 212 1.1 tnozaki 213 1.1 tnozaki static const category_t lc_messages = { 214 1.1 tnozaki _CITRUS_LC_MESSAGES_MAGIC_1, 215 1.1 tnozaki _CITRUS_LC_MESSAGES_SYM_VERSION, 216 1.1 tnozaki _CITRUS_LC_MESSAGES_VERSION, 217 1.1 tnozaki { 218 1.1 tnozaki { _CITRUS_LC_MESSAGES_SYM_YESEXPR, &save_as_string }, 219 1.1 tnozaki { _CITRUS_LC_MESSAGES_SYM_NOEXPR, &save_as_string }, 220 1.1 tnozaki { _CITRUS_LC_MESSAGES_SYM_YESSTR, &save_as_string }, 221 1.1 tnozaki { _CITRUS_LC_MESSAGES_SYM_NOSTR, &save_as_string }, 222 1.1 tnozaki { NULL }, 223 1.1 tnozaki }, 224 1.1 tnozaki }; 225 1.1 tnozaki 226 1.1 tnozaki void 227 1.1 tnozaki mklocaledb(const char *type, FILE *reader, FILE *writer) 228 1.1 tnozaki { 229 1.1 tnozaki static const char delim[3] = { '\0', '\0', '#' }; 230 1.1 tnozaki const category_t *category = NULL; 231 1.1 tnozaki struct _db_factory *df; 232 1.1 tnozaki const token_t *token; 233 1.1 tnozaki char *line; 234 1.1 tnozaki size_t size; 235 1.1 tnozaki void *serialized; 236 1.1 tnozaki struct _region r; 237 1.1 tnozaki 238 1.1 tnozaki _DIAGASSERT(type != NULL); 239 1.1 tnozaki _DIAGASSERT(reader != NULL); 240 1.1 tnozaki _DIAGASSERT(writer != NULL); 241 1.1 tnozaki 242 1.1 tnozaki if (!strcasecmp(type, "MONETARY")) 243 1.1 tnozaki category = &lc_monetary; 244 1.1 tnozaki else if (!strcasecmp(type, "NUMERIC")) 245 1.1 tnozaki category = &lc_numeric; 246 1.1 tnozaki else if (!strcasecmp(type, "TIME")) 247 1.1 tnozaki category = &lc_time; 248 1.1 tnozaki else if (!strcasecmp(type, "MESSAGES")) 249 1.1 tnozaki category = &lc_messages; 250 1.1 tnozaki else { 251 1.1 tnozaki usage(); 252 1.1 tnozaki /*NOTREACHED*/ 253 1.1 tnozaki } 254 1.1 tnozaki if (_db_factory_create(&df, &_db_hash_std, NULL)) 255 1.4 christos errx(EXIT_FAILURE, "can't create db factory"); 256 1.1 tnozaki if (_db_factory_add32_by_s(df, category->vers_sym, category->version)) 257 1.4 christos errx(EXIT_FAILURE, "can't store db"); 258 1.1 tnozaki token = &category->tokens[0]; 259 1.1 tnozaki while (token->key != NULL) { 260 1.1 tnozaki line = fparseln(reader, NULL, 261 1.1 tnozaki NULL, delim, FPARSELN_UNESCALL); 262 1.1 tnozaki if (line == NULL) 263 1.4 christos errx(EXIT_FAILURE, "can't read line"); 264 1.1 tnozaki if ((*token->save)(df, token->key, (const char *)line)) 265 1.4 christos errx(EXIT_FAILURE, "can't store db"); 266 1.1 tnozaki free(line); 267 1.1 tnozaki ++token; 268 1.1 tnozaki } 269 1.1 tnozaki size = _db_factory_calc_size(df); 270 1.1 tnozaki _DIAGASSERT(size > 0); 271 1.1 tnozaki serialized = malloc(size); 272 1.1 tnozaki if (serialized == NULL) 273 1.4 christos errx(EXIT_FAILURE, "can't malloc"); 274 1.1 tnozaki _DIAGASSERT(serialized != NULL); 275 1.1 tnozaki _region_init(&r, serialized, size); 276 1.1 tnozaki if (_db_factory_serialize(df, category->magic, &r)) 277 1.4 christos errx(EXIT_FAILURE, "can't serialize db"); 278 1.1 tnozaki fwrite(serialized, size, 1, writer); 279 1.1 tnozaki _db_factory_free(df); 280 1.1 tnozaki } 281