[BACK]Return to locale.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / locale

Annotation of src/usr.bin/locale/locale.c, Revision 1.3.2.1

1.3.2.1 ! he          1: /*     $NetBSD: locale.c,v 1.3 2004/01/05 23:23:35 jmmv Exp $  */
1.1       tshiozak    2:
                      3: /*-
                      4:  * Copyright (c) 2002, 2003 Alexey Zelkin <phantom@FreeBSD.org>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  *
                     28:  * FreeBSD: src/usr.bin/locale/locale.c,v 1.10 2003/06/26 11:05:56 phantom Exp
                     29:  */
                     30:
                     31: #include <sys/cdefs.h>
                     32: #if defined(LIBC_SCCS) && !defined(lint)
1.3.2.1 ! he         33: __RCSID("$NetBSD: locale.c,v 1.3 2004/01/05 23:23:35 jmmv Exp $");
1.1       tshiozak   34: #endif /* LIBC_SCCS and not lint */
                     35:
                     36: /*
                     37:  * XXX: implement missing era_* (LC_TIME) keywords (require libc &
                     38:  *     nl_langinfo(3) extensions)
                     39:  *
                     40:  * XXX: correctly handle reserved 'charmap' keyword and '-m' option (require
                     41:  *      localedef(1) implementation).  Currently it's handled via
                     42:  *     nl_langinfo(CODESET).
                     43:  */
                     44:
                     45: #include <sys/types.h>
                     46: #include <dirent.h>
                     47: #include <err.h>
                     48: #include <locale.h>
                     49: #include <langinfo.h>
                     50: #include <paths.h>
                     51: #include <stdio.h>
                     52: #include <stdlib.h>
                     53: #include <string.h>
                     54: #include <stringlist.h>
                     55: #include <unistd.h>
                     56:
                     57: /* Local prototypes */
                     58: void   init_locales_list(void);
                     59: void   list_charmaps(void);
                     60: void   list_locales(void);
                     61: const char *lookup_localecat(int);
                     62: char   *kwval_lconv(int);
                     63: int    kwval_lookup(char *, char **, int *, int *);
                     64: void   showdetails(char *);
                     65: void   showkeywordslist(void);
                     66: void   showlocale(void);
                     67: void   usage(void);
                     68:
                     69: /* Global variables */
                     70: static StringList *locales = NULL;
                     71: extern char *_PathLocale;
                     72:
                     73: int    all_locales = 0;
                     74: int    all_charmaps = 0;
                     75: int    prt_categories = 0;
                     76: int    prt_keywords = 0;
                     77: int    more_params = 0;
                     78:
                     79: struct _lcinfo {
                     80:        const char      *name;
                     81:        int             id;
                     82: } lcinfo [] = {
                     83:        { "LC_CTYPE",           LC_CTYPE },
                     84:        { "LC_COLLATE",         LC_COLLATE },
                     85:        { "LC_TIME",            LC_TIME },
                     86:        { "LC_NUMERIC",         LC_NUMERIC },
                     87:        { "LC_MONETARY",        LC_MONETARY },
                     88:        { "LC_MESSAGES",        LC_MESSAGES }
                     89: };
                     90: #define NLCINFO (sizeof(lcinfo)/sizeof(lcinfo[0]))
                     91:
                     92: /* ids for values not referenced by nl_langinfo() */
                     93: #define        KW_ZERO                 10000
                     94: #define        KW_GROUPING             (KW_ZERO+1)
                     95: #define KW_INT_CURR_SYMBOL     (KW_ZERO+2)
                     96: #define KW_CURRENCY_SYMBOL     (KW_ZERO+3)
                     97: #define KW_MON_DECIMAL_POINT   (KW_ZERO+4)
                     98: #define KW_MON_THOUSANDS_SEP   (KW_ZERO+5)
                     99: #define KW_MON_GROUPING        (KW_ZERO+6)
                    100: #define KW_POSITIVE_SIGN       (KW_ZERO+7)
                    101: #define KW_NEGATIVE_SIGN       (KW_ZERO+8)
                    102: #define KW_INT_FRAC_DIGITS     (KW_ZERO+9)
                    103: #define KW_FRAC_DIGITS                 (KW_ZERO+10)
                    104: #define KW_P_CS_PRECEDES       (KW_ZERO+11)
                    105: #define KW_P_SEP_BY_SPACE      (KW_ZERO+12)
                    106: #define KW_N_CS_PRECEDES       (KW_ZERO+13)
                    107: #define KW_N_SEP_BY_SPACE      (KW_ZERO+14)
                    108: #define KW_P_SIGN_POSN                 (KW_ZERO+15)
                    109: #define KW_N_SIGN_POSN                 (KW_ZERO+16)
                    110: #define KW_INT_P_CS_PRECEDES   (KW_ZERO+17)
                    111: #define KW_INT_P_SEP_BY_SPACE  (KW_ZERO+18)
                    112: #define KW_INT_N_CS_PRECEDES   (KW_ZERO+19)
                    113: #define KW_INT_N_SEP_BY_SPACE  (KW_ZERO+20)
                    114: #define KW_INT_P_SIGN_POSN     (KW_ZERO+21)
                    115: #define KW_INT_N_SIGN_POSN     (KW_ZERO+22)
                    116:
                    117: struct _kwinfo {
                    118:        const char      *name;
                    119:        int             isstr;          /* true - string, false - number */
                    120:        int             catid;          /* LC_* */
                    121:        int             value_ref;
                    122:        const char      *comment;
                    123: } kwinfo [] = {
                    124:        { "charmap",            1, LC_CTYPE,    CODESET, "" },  /* hack */
                    125:
                    126:        { "decimal_point",      1, LC_NUMERIC,  RADIXCHAR, "" },
                    127:        { "thousands_sep",      1, LC_NUMERIC,  THOUSEP, "" },
                    128:        { "grouping",           1, LC_NUMERIC,  KW_GROUPING, "" },
                    129:        { "radixchar",          1, LC_NUMERIC,  RADIXCHAR,
                    130:          "Same as decimal_point (BSD only)" },                 /* compat */
                    131:        { "thousep",            1, LC_NUMERIC,  THOUSEP,
                    132:          "Same as thousands_sep (BSD only)" },                 /* compat */
                    133:
                    134:        { "int_curr_symbol",    1, LC_MONETARY, KW_INT_CURR_SYMBOL, "" },
                    135:        { "currency_symbol",    1, LC_MONETARY, KW_CURRENCY_SYMBOL, "" },
                    136:        { "mon_decimal_point",  1, LC_MONETARY, KW_MON_DECIMAL_POINT, "" },
                    137:        { "mon_thousands_sep",  1, LC_MONETARY, KW_MON_THOUSANDS_SEP, "" },
                    138:        { "mon_grouping",       1, LC_MONETARY, KW_MON_GROUPING, "" },
                    139:        { "positive_sign",      1, LC_MONETARY, KW_POSITIVE_SIGN, "" },
                    140:        { "negative_sign",      1, LC_MONETARY, KW_NEGATIVE_SIGN, "" },
                    141:
                    142:        { "int_frac_digits",    0, LC_MONETARY, KW_INT_FRAC_DIGITS, "" },
                    143:        { "frac_digits",        0, LC_MONETARY, KW_FRAC_DIGITS, "" },
                    144:        { "p_cs_precedes",      0, LC_MONETARY, KW_P_CS_PRECEDES, "" },
                    145:        { "p_sep_by_space",     0, LC_MONETARY, KW_P_SEP_BY_SPACE, "" },
                    146:        { "n_cs_precedes",      0, LC_MONETARY, KW_N_CS_PRECEDES, "" },
                    147:        { "n_sep_by_space",     0, LC_MONETARY, KW_N_SEP_BY_SPACE, "" },
                    148:        { "p_sign_posn",        0, LC_MONETARY, KW_P_SIGN_POSN, "" },
                    149:        { "n_sign_posn",        0, LC_MONETARY, KW_N_SIGN_POSN, "" },
                    150:        { "int_p_cs_precedes",  0, LC_MONETARY, KW_INT_P_CS_PRECEDES, "" },
                    151:        { "int_p_sep_by_space", 0, LC_MONETARY, KW_INT_P_SEP_BY_SPACE, "" },
                    152:        { "int_n_cs_precedes",  0, LC_MONETARY, KW_INT_N_CS_PRECEDES, "" },
                    153:        { "int_n_sep_by_space", 0, LC_MONETARY, KW_INT_N_SEP_BY_SPACE, "" },
                    154:        { "int_p_sign_posn",    0, LC_MONETARY, KW_INT_P_SIGN_POSN, "" },
                    155:        { "int_n_sign_posn",    0, LC_MONETARY, KW_INT_N_SIGN_POSN, "" },
                    156:
                    157:        { "d_t_fmt",            1, LC_TIME,     D_T_FMT, "" },
                    158:        { "d_fmt",              1, LC_TIME,     D_FMT, "" },
                    159:        { "t_fmt",              1, LC_TIME,     T_FMT, "" },
                    160:        { "am_str",             1, LC_TIME,     AM_STR, "" },
                    161:        { "pm_str",             1, LC_TIME,     PM_STR, "" },
                    162:        { "t_fmt_ampm",         1, LC_TIME,     T_FMT_AMPM, "" },
                    163:        { "day_1",              1, LC_TIME,     DAY_1, "" },
                    164:        { "day_2",              1, LC_TIME,     DAY_2, "" },
                    165:        { "day_3",              1, LC_TIME,     DAY_3, "" },
                    166:        { "day_4",              1, LC_TIME,     DAY_4, "" },
                    167:        { "day_5",              1, LC_TIME,     DAY_5, "" },
                    168:        { "day_6",              1, LC_TIME,     DAY_6, "" },
                    169:        { "day_7",              1, LC_TIME,     DAY_7, "" },
                    170:        { "abday_1",            1, LC_TIME,     ABDAY_1, "" },
                    171:        { "abday_2",            1, LC_TIME,     ABDAY_2, "" },
                    172:        { "abday_3",            1, LC_TIME,     ABDAY_3, "" },
                    173:        { "abday_4",            1, LC_TIME,     ABDAY_4, "" },
                    174:        { "abday_5",            1, LC_TIME,     ABDAY_5, "" },
                    175:        { "abday_6",            1, LC_TIME,     ABDAY_6, "" },
                    176:        { "abday_7",            1, LC_TIME,     ABDAY_7, "" },
                    177:        { "mon_1",              1, LC_TIME,     MON_1, "" },
                    178:        { "mon_2",              1, LC_TIME,     MON_2, "" },
                    179:        { "mon_3",              1, LC_TIME,     MON_3, "" },
                    180:        { "mon_4",              1, LC_TIME,     MON_4, "" },
                    181:        { "mon_5",              1, LC_TIME,     MON_5, "" },
                    182:        { "mon_6",              1, LC_TIME,     MON_6, "" },
                    183:        { "mon_7",              1, LC_TIME,     MON_7, "" },
                    184:        { "mon_8",              1, LC_TIME,     MON_8, "" },
                    185:        { "mon_9",              1, LC_TIME,     MON_9, "" },
                    186:        { "mon_10",             1, LC_TIME,     MON_10, "" },
                    187:        { "mon_11",             1, LC_TIME,     MON_11, "" },
                    188:        { "mon_12",             1, LC_TIME,     MON_12, "" },
                    189:        { "abmon_1",            1, LC_TIME,     ABMON_1, "" },
                    190:        { "abmon_2",            1, LC_TIME,     ABMON_2, "" },
                    191:        { "abmon_3",            1, LC_TIME,     ABMON_3, "" },
                    192:        { "abmon_4",            1, LC_TIME,     ABMON_4, "" },
                    193:        { "abmon_5",            1, LC_TIME,     ABMON_5, "" },
                    194:        { "abmon_6",            1, LC_TIME,     ABMON_6, "" },
                    195:        { "abmon_7",            1, LC_TIME,     ABMON_7, "" },
                    196:        { "abmon_8",            1, LC_TIME,     ABMON_8, "" },
                    197:        { "abmon_9",            1, LC_TIME,     ABMON_9, "" },
                    198:        { "abmon_10",           1, LC_TIME,     ABMON_10, "" },
                    199:        { "abmon_11",           1, LC_TIME,     ABMON_11, "" },
                    200:        { "abmon_12",           1, LC_TIME,     ABMON_12, "" },
                    201:        { "era",                1, LC_TIME,     ERA, "(unavailable)" },
                    202:        { "era_d_fmt",          1, LC_TIME,     ERA_D_FMT, "(unavailable)" },
                    203:        { "era_d_t_fmt",        1, LC_TIME,     ERA_D_T_FMT, "(unavailable)" },
                    204:        { "era_t_fmt",          1, LC_TIME,     ERA_T_FMT, "(unavailable)" },
                    205:        { "alt_digits",         1, LC_TIME,     ALT_DIGITS, "" },
                    206:
                    207:        { "yesexpr",            1, LC_MESSAGES, YESEXPR, "" },
                    208:        { "noexpr",             1, LC_MESSAGES, NOEXPR, "" },
                    209:        { "yesstr",             1, LC_MESSAGES, YESSTR,
                    210:          "(POSIX legacy)" },                                   /* compat */
                    211:        { "nostr",              1, LC_MESSAGES, NOSTR,
                    212:          "(POSIX legacy)" }                                    /* compat */
                    213:
                    214: };
                    215: #define NKWINFO (sizeof(kwinfo)/sizeof(kwinfo[0]))
                    216:
                    217: int
                    218: main(int argc, char *argv[])
                    219: {
1.2       agc       220:        int     ch;
1.1       tshiozak  221:        int     tmp;
                    222:
                    223:        while ((ch = getopt(argc, argv, "ackm")) != -1) {
                    224:                switch (ch) {
                    225:                case 'a':
                    226:                        all_locales = 1;
                    227:                        break;
                    228:                case 'c':
                    229:                        prt_categories = 1;
                    230:                        break;
                    231:                case 'k':
                    232:                        prt_keywords = 1;
                    233:                        break;
                    234:                case 'm':
                    235:                        all_charmaps = 1;
                    236:                        break;
                    237:                default:
                    238:                        usage();
                    239:                }
                    240:        }
                    241:        argc -= optind;
                    242:        argv += optind;
                    243:
                    244:        /* validate arguments */
                    245:        if (all_locales && all_charmaps)
                    246:                usage();
                    247:        if ((all_locales || all_charmaps) && argc > 0)
                    248:                usage();
                    249:        if ((all_locales || all_charmaps) && (prt_categories || prt_keywords))
                    250:                usage();
                    251:        if ((prt_categories || prt_keywords) && argc <= 0)
                    252:                usage();
                    253:
                    254:        /* process '-a' */
                    255:        if (all_locales) {
                    256:                list_locales();
                    257:                exit(0);
                    258:        }
                    259:
                    260:        /* process '-m' */
                    261:        if (all_charmaps) {
                    262:                list_charmaps();
                    263:                exit(0);
                    264:        }
                    265:
                    266:        /* check for special case '-k list' */
                    267:        tmp = 0;
                    268:        if (prt_keywords && argc > 0)
                    269:                while (tmp < argc)
                    270:                        if (strcasecmp(argv[tmp++], "list") == 0) {
                    271:                                showkeywordslist();
                    272:                                exit(0);
                    273:                        }
                    274:
                    275:        /* process '-c' and/or '-k' */
                    276:        if (prt_categories || prt_keywords || argc > 0) {
                    277:                setlocale(LC_ALL, "");
                    278:                while (argc > 0) {
                    279:                        showdetails(*argv);
                    280:                        argv++;
                    281:                        argc--;
                    282:                }
                    283:                exit(0);
                    284:        }
                    285:
                    286:        /* no arguments, show current locale state */
                    287:        showlocale();
                    288:
                    289:        return (0);
                    290: }
                    291:
                    292: void
                    293: usage(void)
                    294: {
1.3       jmmv      295:        printf("usage: locale [ -a | -m ]\n"
1.1       tshiozak  296:                "       locale [ -ck ] name ...\n");
                    297:        exit(1);
                    298: }
                    299:
                    300: /*
                    301:  * Output information about all available locales
                    302:  *
                    303:  * XXX actually output of this function does not guarantee that locale
                    304:  *     is really available to application, since it can be broken or
                    305:  *     inconsistent thus setlocale() will fail.  Maybe add '-V' function to
                    306:  *     also validate these locales?
                    307:  */
                    308: void
                    309: list_locales(void)
                    310: {
                    311:        size_t i;
                    312:
                    313:        init_locales_list();
                    314:        for (i = 0; i < locales->sl_cur; i++) {
                    315:                printf("%s\n", locales->sl_str[i]);
                    316:        }
                    317: }
                    318:
                    319: /*
                    320:  * qsort() helper function
                    321:  */
                    322: static int
                    323: scmp(const void *s1, const void *s2)
                    324: {
                    325:        return strcmp(*(const char **)s1, *(const char **)s2);
                    326: }
                    327:
                    328: /*
                    329:  * Output information about all available charmaps
                    330:  *
                    331:  * XXX this function is doing a task in hackish way, i.e. by scaning
                    332:  *     list of locales, spliting their codeset part and building list of
                    333:  *     them.
                    334:  */
                    335: void
                    336: list_charmaps(void)
                    337: {
                    338:        size_t i;
                    339:        char *s, *cs;
                    340:        StringList *charmaps;
                    341:
                    342:        /* initialize StringList */
                    343:        charmaps = sl_init();
                    344:        if (charmaps == NULL)
                    345:                err(1, "could not allocate memory");
                    346:
                    347:        /* fetch locales list */
                    348:        init_locales_list();
                    349:
                    350:        /* split codesets and build their list */
                    351:        for (i = 0; i < locales->sl_cur; i++) {
                    352:                s = locales->sl_str[i];
                    353:                if ((cs = strchr(s, '.')) != NULL) {
                    354:                        cs++;
                    355:                        if (sl_find(charmaps, cs) == NULL)
                    356:                                sl_add(charmaps, cs);
                    357:                }
                    358:        }
                    359:
                    360:        /* add US-ASCII, if not yet added */
                    361:        if (sl_find(charmaps, "US-ASCII") == NULL)
                    362:                sl_add(charmaps, "US-ASCII");
                    363:
                    364:        /* sort the list */
                    365:        qsort(charmaps->sl_str, charmaps->sl_cur, sizeof(char *), scmp);
                    366:
                    367:        /* print results */
                    368:        for (i = 0; i < charmaps->sl_cur; i++) {
                    369:                printf("%s\n", charmaps->sl_str[i]);
                    370:        }
                    371: }
                    372:
                    373: /*
                    374:  * Retrieve sorted list of system locales (or user locales, if PATH_LOCALE
                    375:  * environment variable is set)
                    376:  */
                    377: void
                    378: init_locales_list(void)
                    379: {
                    380:        DIR *dirp;
                    381:        struct dirent *dp;
                    382:
                    383:        /* why call this function twice ? */
                    384:        if (locales != NULL)
                    385:                return;
                    386:
                    387:        /* initialize StringList */
                    388:        locales = sl_init();
                    389:        if (locales == NULL)
                    390:                err(1, "could not allocate memory");
                    391:
                    392:        /* get actual locales directory name */
                    393:        setlocale(LC_CTYPE, "C");
                    394:        if (_PathLocale == NULL)
                    395:                errx(1, "unable to find locales storage");
                    396:
                    397:        /* open locales directory */
                    398:        dirp = opendir(_PathLocale);
                    399:        if (dirp == NULL)
                    400:                err(1, "could not open directory '%s'", _PathLocale);
                    401:
                    402:        /* scan directory and store its contents except "." and ".." */
                    403:        while ((dp = readdir(dirp)) != NULL) {
                    404:                if (*(dp->d_name) == '.')
                    405:                        continue;               /* exclude "." and ".." */
                    406:                sl_add(locales, strdup(dp->d_name));
                    407:        }
                    408:        closedir(dirp);
                    409:
                    410:         /* make sure that 'POSIX' and 'C' locales are present in the list.
                    411:         * POSIX 1003.1-2001 requires presence of 'POSIX' name only here, but
                    412:          * we also list 'C' for constistency
                    413:          */
                    414:        if (sl_find(locales, "POSIX") == NULL)
                    415:                sl_add(locales, "POSIX");
                    416:
                    417:        if (sl_find(locales, "C") == NULL)
                    418:                sl_add(locales, "C");
                    419:
                    420:        /* make output nicer, sort the list */
                    421:        qsort(locales->sl_str, locales->sl_cur, sizeof(char *), scmp);
                    422: }
                    423:
                    424: /*
                    425:  * Show current locale status, depending on environment variables
                    426:  */
                    427: void
                    428: showlocale(void)
                    429: {
                    430:        size_t  i;
                    431:        const char *lang, *vval, *eval;
                    432:
                    433:        setlocale(LC_ALL, "");
                    434:
                    435:        lang = getenv("LANG");
                    436:        if (lang == NULL) {
                    437:                lang = "";
                    438:        }
1.3.2.1 ! he        439:        printf("LANG=\"%s\"\n", lang);
1.1       tshiozak  440:        /* XXX: if LANG is null, then set it to "C" to get implied values? */
                    441:
                    442:        for (i = 0; i < NLCINFO; i++) {
                    443:                vval = setlocale(lcinfo[i].id, NULL);
                    444:                eval = getenv(lcinfo[i].name);
                    445:                if (eval != NULL && !strcmp(eval, vval)
                    446:                                && strcmp(lang, vval)) {
                    447:                        /*
                    448:                         * Appropriate environment variable set, its value
                    449:                         * is valid and not overriden by LC_ALL
                    450:                         *
                    451:                         * XXX: possible side effect: if both LANG and
                    452:                         * overriden environment variable are set into same
                    453:                         * value, then it'll be assumed as 'implied'
                    454:                         */
1.3.2.1 ! he        455:                        printf("%s=\"%s\"\n", lcinfo[i].name, vval);
1.1       tshiozak  456:                } else {
                    457:                        printf("%s=\"%s\"\n", lcinfo[i].name, vval);
                    458:                }
                    459:        }
                    460:
                    461:        vval = getenv("LC_ALL");
                    462:        if (vval == NULL) {
                    463:                vval = "";
                    464:        }
1.3.2.1 ! he        465:        printf("LC_ALL=\"%s\"\n", vval);
1.1       tshiozak  466: }
                    467:
                    468: /*
                    469:  * keyword value lookup helper (via localeconv())
                    470:  */
                    471: char *
                    472: kwval_lconv(int id)
                    473: {
                    474:        struct lconv *lc;
                    475:        char *rval;
                    476:
                    477:        rval = NULL;
                    478:        lc = localeconv();
                    479:        switch (id) {
                    480:                case KW_GROUPING:
                    481:                        rval = lc->grouping;
                    482:                        break;
                    483:                case KW_INT_CURR_SYMBOL:
                    484:                        rval = lc->int_curr_symbol;
                    485:                        break;
                    486:                case KW_CURRENCY_SYMBOL:
                    487:                        rval = lc->currency_symbol;
                    488:                        break;
                    489:                case KW_MON_DECIMAL_POINT:
                    490:                        rval = lc->mon_decimal_point;
                    491:                        break;
                    492:                case KW_MON_THOUSANDS_SEP:
                    493:                        rval = lc->mon_thousands_sep;
                    494:                        break;
                    495:                case KW_MON_GROUPING:
                    496:                        rval = lc->mon_grouping;
                    497:                        break;
                    498:                case KW_POSITIVE_SIGN:
                    499:                        rval = lc->positive_sign;
                    500:                        break;
                    501:                case KW_NEGATIVE_SIGN:
                    502:                        rval = lc->negative_sign;
                    503:                        break;
                    504:                case KW_INT_FRAC_DIGITS:
                    505:                        rval = &(lc->int_frac_digits);
                    506:                        break;
                    507:                case KW_FRAC_DIGITS:
                    508:                        rval = &(lc->frac_digits);
                    509:                        break;
                    510:                case KW_P_CS_PRECEDES:
                    511:                        rval = &(lc->p_cs_precedes);
                    512:                        break;
                    513:                case KW_P_SEP_BY_SPACE:
                    514:                        rval = &(lc->p_sep_by_space);
                    515:                        break;
                    516:                case KW_N_CS_PRECEDES:
                    517:                        rval = &(lc->n_cs_precedes);
                    518:                        break;
                    519:                case KW_N_SEP_BY_SPACE:
                    520:                        rval = &(lc->n_sep_by_space);
                    521:                        break;
                    522:                case KW_P_SIGN_POSN:
                    523:                        rval = &(lc->p_sign_posn);
                    524:                        break;
                    525:                case KW_N_SIGN_POSN:
                    526:                        rval = &(lc->n_sign_posn);
                    527:                        break;
                    528:                case KW_INT_P_CS_PRECEDES:
                    529:                        rval = &(lc->int_p_cs_precedes);
                    530:                        break;
                    531:                case KW_INT_P_SEP_BY_SPACE:
                    532:                        rval = &(lc->int_p_sep_by_space);
                    533:                        break;
                    534:                case KW_INT_N_CS_PRECEDES:
                    535:                        rval = &(lc->int_n_cs_precedes);
                    536:                        break;
                    537:                case KW_INT_N_SEP_BY_SPACE:
                    538:                        rval = &(lc->int_n_sep_by_space);
                    539:                        break;
                    540:                case KW_INT_P_SIGN_POSN:
                    541:                        rval = &(lc->int_p_sign_posn);
                    542:                        break;
                    543:                case KW_INT_N_SIGN_POSN:
                    544:                        rval = &(lc->int_n_sign_posn);
                    545:                        break;
                    546:                default:
                    547:                        break;
                    548:        }
                    549:        return (rval);
                    550: }
                    551:
                    552: /*
                    553:  * keyword value and properties lookup
                    554:  */
                    555: int
                    556: kwval_lookup(char *kwname, char **kwval, int *cat, int *isstr)
                    557: {
                    558:        int     rval;
                    559:        size_t  i;
                    560:
                    561:        rval = 0;
                    562:        for (i = 0; i < NKWINFO; i++) {
                    563:                if (strcasecmp(kwname, kwinfo[i].name) == 0) {
                    564:                        rval = 1;
                    565:                        *cat = kwinfo[i].catid;
                    566:                        *isstr = kwinfo[i].isstr;
                    567:                        if (kwinfo[i].value_ref < KW_ZERO) {
                    568:                                *kwval = nl_langinfo(kwinfo[i].value_ref);
                    569:                        } else {
                    570:                                *kwval = kwval_lconv(kwinfo[i].value_ref);
                    571:                        }
                    572:                        break;
                    573:                }
                    574:        }
                    575:
                    576:        return (rval);
                    577: }
                    578:
                    579: /*
                    580:  * Show details about requested keyword according to '-k' and/or '-c'
                    581:  * command line options specified.
                    582:  */
                    583: void
                    584: showdetails(char *kw)
                    585: {
                    586:        int     isstr, cat, tmpval;
                    587:        char    *kwval;
                    588:
                    589:        if (kwval_lookup(kw, &kwval, &cat, &isstr) == 0) {
                    590:                /*
                    591:                 * invalid keyword specified.
                    592:                 * XXX: any actions?
                    593:                 */
                    594:                return;
                    595:        }
                    596:
                    597:        if (prt_categories) {
                    598:                printf("%s\n", lookup_localecat(cat));
                    599:        }
                    600:
                    601:        if (prt_keywords) {
                    602:                if (isstr) {
                    603:                        printf("%s=\"%s\"\n", kw, kwval);
                    604:                } else {
                    605:                        tmpval = (char) *kwval;
                    606:                        printf("%s=%d\n", kw, tmpval);
                    607:                }
                    608:        }
                    609:
                    610:        if (!prt_categories && !prt_keywords) {
                    611:                if (isstr) {
                    612:                        printf("%s\n", kwval);
                    613:                } else {
                    614:                        tmpval = (char) *kwval;
                    615:                        printf("%d\n", tmpval);
                    616:                }
                    617:        }
                    618: }
                    619:
                    620: /*
                    621:  * Convert locale category id into string
                    622:  */
                    623: const char *
                    624: lookup_localecat(int cat)
                    625: {
                    626:        size_t  i;
                    627:
                    628:        for (i = 0; i < NLCINFO; i++)
                    629:                if (lcinfo[i].id == cat) {
                    630:                        return (lcinfo[i].name);
                    631:                }
                    632:        return ("UNKNOWN");
                    633: }
                    634:
                    635: /*
                    636:  * Show list of keywords
                    637:  */
                    638: void
                    639: showkeywordslist(void)
                    640: {
                    641:        size_t  i;
                    642:
                    643: #define FMT "%-20s %-12s %-7s %-20s\n"
                    644:
                    645:        printf("List of available keywords\n\n");
                    646:        printf(FMT, "Keyword", "Category", "Type", "Comment");
                    647:        printf("-------------------- ------------ ------- --------------------\n");
                    648:        for (i = 0; i < NKWINFO; i++) {
                    649:                printf(FMT,
                    650:                        kwinfo[i].name,
                    651:                        lookup_localecat(kwinfo[i].catid),
                    652:                        (kwinfo[i].isstr == 0) ? "number" : "string",
                    653:                        kwinfo[i].comment);
                    654:        }
                    655: }

CVSweb <webmaster@jp.NetBSD.org>