1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate * locale -- get current locale information
29*7c478bd9Sstevel@tonic-gate *
30*7c478bd9Sstevel@tonic-gate * Copyright 1991, 1993 by Mortice Kern Systems Inc. All rights reserved.
31*7c478bd9Sstevel@tonic-gate *
32*7c478bd9Sstevel@tonic-gate */
33*7c478bd9Sstevel@tonic-gate
34*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
35*7c478bd9Sstevel@tonic-gate
36*7c478bd9Sstevel@tonic-gate /*
37*7c478bd9Sstevel@tonic-gate * locale: get locale-specific information
38*7c478bd9Sstevel@tonic-gate * usage: locale [-a|-m]
39*7c478bd9Sstevel@tonic-gate * locale [-ck] name ...
40*7c478bd9Sstevel@tonic-gate */
41*7c478bd9Sstevel@tonic-gate
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate * New members added in the struct lconv by IEEE Std 1003.1-2001
44*7c478bd9Sstevel@tonic-gate * are always activated in the locale object.
45*7c478bd9Sstevel@tonic-gate * See <iso/locale_iso.h>.
46*7c478bd9Sstevel@tonic-gate */
47*7c478bd9Sstevel@tonic-gate #define _LCONV_C99
48*7c478bd9Sstevel@tonic-gate
49*7c478bd9Sstevel@tonic-gate #include <stdio.h>
50*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
51*7c478bd9Sstevel@tonic-gate #include <limits.h>
52*7c478bd9Sstevel@tonic-gate #include <string.h>
53*7c478bd9Sstevel@tonic-gate #include <dirent.h>
54*7c478bd9Sstevel@tonic-gate #include <ctype.h>
55*7c478bd9Sstevel@tonic-gate #include <stddef.h>
56*7c478bd9Sstevel@tonic-gate #include <nl_types.h>
57*7c478bd9Sstevel@tonic-gate #include <langinfo.h>
58*7c478bd9Sstevel@tonic-gate #include <locale.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate #define LC_LOCDEF 999 /* Random number! */
63*7c478bd9Sstevel@tonic-gate
64*7c478bd9Sstevel@tonic-gate #define LOCALE_DIR "/usr/lib/locale/"
65*7c478bd9Sstevel@tonic-gate #define CHARMAP_DIR "/usr/lib/localedef/src/"
66*7c478bd9Sstevel@tonic-gate #define CHARMAP_NAME "charmap.src"
67*7c478bd9Sstevel@tonic-gate
68*7c478bd9Sstevel@tonic-gate #define GET_LOCALE 0
69*7c478bd9Sstevel@tonic-gate #define GET_CHARMAP 1
70*7c478bd9Sstevel@tonic-gate #define CSSIZE 128
71*7c478bd9Sstevel@tonic-gate
72*7c478bd9Sstevel@tonic-gate #ifndef isblank
73*7c478bd9Sstevel@tonic-gate #define isblank(c) ((__ctype + 1)[c] & _B)
74*7c478bd9Sstevel@tonic-gate #endif
75*7c478bd9Sstevel@tonic-gate
76*7c478bd9Sstevel@tonic-gate enum types {
77*7c478bd9Sstevel@tonic-gate TYPE_STR, /* char * */
78*7c478bd9Sstevel@tonic-gate TYPE_GROUP, /* char *, for mon_grouping, and grouping */
79*7c478bd9Sstevel@tonic-gate TYPE_INT, /* int */
80*7c478bd9Sstevel@tonic-gate TYPE_CHR, /* char, printed as signed integer */
81*7c478bd9Sstevel@tonic-gate TYPE_PCHR, /* char, printed as printable character */
82*7c478bd9Sstevel@tonic-gate TYPE_CTP, /* ctype entry */
83*7c478bd9Sstevel@tonic-gate TYPE_CNVL, /* convert to lower */
84*7c478bd9Sstevel@tonic-gate TYPE_CNVU, /* convert to upper */
85*7c478bd9Sstevel@tonic-gate TYPE_COLLEL /* print the multi-character collating elements */
86*7c478bd9Sstevel@tonic-gate };
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gate static int print_locale_info(char *keyword, int cflag, int kflag);
89*7c478bd9Sstevel@tonic-gate static int print_category(int category, int cflag, int kflag);
90*7c478bd9Sstevel@tonic-gate static int print_keyword(char *name, int cflag, int kflag);
91*7c478bd9Sstevel@tonic-gate static void usage(void);
92*7c478bd9Sstevel@tonic-gate static void print_all_info(int);
93*7c478bd9Sstevel@tonic-gate static void print_cur_locale(void);
94*7c478bd9Sstevel@tonic-gate static void outstr(char *s);
95*7c478bd9Sstevel@tonic-gate static void outchar(int);
96*7c478bd9Sstevel@tonic-gate static void prt_ctp(char *);
97*7c478bd9Sstevel@tonic-gate static void prt_cnv(char *);
98*7c478bd9Sstevel@tonic-gate static void prt_collel(char *);
99*7c478bd9Sstevel@tonic-gate static char get_escapechar(void);
100*7c478bd9Sstevel@tonic-gate static char get_commentchar(void);
101*7c478bd9Sstevel@tonic-gate
102*7c478bd9Sstevel@tonic-gate static char *save_loc;
103*7c478bd9Sstevel@tonic-gate
104*7c478bd9Sstevel@tonic-gate /*
105*7c478bd9Sstevel@tonic-gate * yes/no is not in the localeconv structure for xpg style.
106*7c478bd9Sstevel@tonic-gate * We dummy up a new structure for purposes of the code below.
107*7c478bd9Sstevel@tonic-gate * If YESEXPR is available per XPG4, we use it.
108*7c478bd9Sstevel@tonic-gate * Otherwise, use YESSTR, the old method with less functionality from XPG3.
109*7c478bd9Sstevel@tonic-gate */
110*7c478bd9Sstevel@tonic-gate struct yesno {
111*7c478bd9Sstevel@tonic-gate char *yes_expr;
112*7c478bd9Sstevel@tonic-gate char *no_expr;
113*7c478bd9Sstevel@tonic-gate char *yes_str;
114*7c478bd9Sstevel@tonic-gate char *no_str;
115*7c478bd9Sstevel@tonic-gate };
116*7c478bd9Sstevel@tonic-gate
117*7c478bd9Sstevel@tonic-gate struct dtconv {
118*7c478bd9Sstevel@tonic-gate char *date_time_format;
119*7c478bd9Sstevel@tonic-gate char *date_format;
120*7c478bd9Sstevel@tonic-gate char *time_format;
121*7c478bd9Sstevel@tonic-gate char *time_format_ampm;
122*7c478bd9Sstevel@tonic-gate char *am_string;
123*7c478bd9Sstevel@tonic-gate char *pm_string;
124*7c478bd9Sstevel@tonic-gate char *abbrev_day_names[7];
125*7c478bd9Sstevel@tonic-gate char *day_names[7];
126*7c478bd9Sstevel@tonic-gate char *abbrev_month_names[12];
127*7c478bd9Sstevel@tonic-gate char *month_names[12];
128*7c478bd9Sstevel@tonic-gate char *era;
129*7c478bd9Sstevel@tonic-gate char *era_d_fmt;
130*7c478bd9Sstevel@tonic-gate char *era_d_t_fmt;
131*7c478bd9Sstevel@tonic-gate char *era_t_fmt;
132*7c478bd9Sstevel@tonic-gate char *alt_digits;
133*7c478bd9Sstevel@tonic-gate };
134*7c478bd9Sstevel@tonic-gate
135*7c478bd9Sstevel@tonic-gate struct localedef {
136*7c478bd9Sstevel@tonic-gate char *charmap;
137*7c478bd9Sstevel@tonic-gate char *code_set_name;
138*7c478bd9Sstevel@tonic-gate char escape_char;
139*7c478bd9Sstevel@tonic-gate char comment_char;
140*7c478bd9Sstevel@tonic-gate int mb_cur_max;
141*7c478bd9Sstevel@tonic-gate int mb_cur_min;
142*7c478bd9Sstevel@tonic-gate };
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate static struct yesno *
getyesno(void)145*7c478bd9Sstevel@tonic-gate getyesno(void)
146*7c478bd9Sstevel@tonic-gate {
147*7c478bd9Sstevel@tonic-gate static struct yesno yn;
148*7c478bd9Sstevel@tonic-gate static int loaded = 0;
149*7c478bd9Sstevel@tonic-gate
150*7c478bd9Sstevel@tonic-gate if (loaded) {
151*7c478bd9Sstevel@tonic-gate return (&yn);
152*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
153*7c478bd9Sstevel@tonic-gate }
154*7c478bd9Sstevel@tonic-gate
155*7c478bd9Sstevel@tonic-gate yn.yes_expr = strdup(nl_langinfo(YESEXPR));
156*7c478bd9Sstevel@tonic-gate yn.no_expr = strdup(nl_langinfo(NOEXPR));
157*7c478bd9Sstevel@tonic-gate yn.yes_str = strdup(nl_langinfo(YESSTR));
158*7c478bd9Sstevel@tonic-gate yn.no_str = strdup(nl_langinfo(NOSTR));
159*7c478bd9Sstevel@tonic-gate
160*7c478bd9Sstevel@tonic-gate loaded = 1;
161*7c478bd9Sstevel@tonic-gate return (&yn);
162*7c478bd9Sstevel@tonic-gate }
163*7c478bd9Sstevel@tonic-gate
164*7c478bd9Sstevel@tonic-gate static struct dtconv *
localedtconv(void)165*7c478bd9Sstevel@tonic-gate localedtconv(void)
166*7c478bd9Sstevel@tonic-gate {
167*7c478bd9Sstevel@tonic-gate static struct dtconv _dtconv;
168*7c478bd9Sstevel@tonic-gate static int loaded = 0;
169*7c478bd9Sstevel@tonic-gate
170*7c478bd9Sstevel@tonic-gate if (loaded) {
171*7c478bd9Sstevel@tonic-gate return (&_dtconv);
172*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
173*7c478bd9Sstevel@tonic-gate }
174*7c478bd9Sstevel@tonic-gate
175*7c478bd9Sstevel@tonic-gate _dtconv.date_time_format = strdup(nl_langinfo(D_T_FMT));
176*7c478bd9Sstevel@tonic-gate _dtconv.date_format = strdup(nl_langinfo(D_FMT));
177*7c478bd9Sstevel@tonic-gate _dtconv.time_format = strdup(nl_langinfo(T_FMT));
178*7c478bd9Sstevel@tonic-gate _dtconv.time_format_ampm = strdup(nl_langinfo(T_FMT_AMPM));
179*7c478bd9Sstevel@tonic-gate _dtconv.am_string = strdup(nl_langinfo(AM_STR));
180*7c478bd9Sstevel@tonic-gate _dtconv.pm_string = strdup(nl_langinfo(PM_STR));
181*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[0] = strdup(nl_langinfo(ABDAY_1));
182*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[1] = strdup(nl_langinfo(ABDAY_2));
183*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[2] = strdup(nl_langinfo(ABDAY_3));
184*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[3] = strdup(nl_langinfo(ABDAY_4));
185*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[4] = strdup(nl_langinfo(ABDAY_5));
186*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[5] = strdup(nl_langinfo(ABDAY_6));
187*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[6] = strdup(nl_langinfo(ABDAY_7));
188*7c478bd9Sstevel@tonic-gate _dtconv.day_names[0] = strdup(nl_langinfo(DAY_1));
189*7c478bd9Sstevel@tonic-gate _dtconv.day_names[1] = strdup(nl_langinfo(DAY_2));
190*7c478bd9Sstevel@tonic-gate _dtconv.day_names[2] = strdup(nl_langinfo(DAY_3));
191*7c478bd9Sstevel@tonic-gate _dtconv.day_names[3] = strdup(nl_langinfo(DAY_4));
192*7c478bd9Sstevel@tonic-gate _dtconv.day_names[4] = strdup(nl_langinfo(DAY_5));
193*7c478bd9Sstevel@tonic-gate _dtconv.day_names[5] = strdup(nl_langinfo(DAY_6));
194*7c478bd9Sstevel@tonic-gate _dtconv.day_names[6] = strdup(nl_langinfo(DAY_7));
195*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[0] = strdup(nl_langinfo(ABMON_1));
196*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[1] = strdup(nl_langinfo(ABMON_2));
197*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[2] = strdup(nl_langinfo(ABMON_3));
198*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[3] = strdup(nl_langinfo(ABMON_4));
199*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[4] = strdup(nl_langinfo(ABMON_5));
200*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[5] = strdup(nl_langinfo(ABMON_6));
201*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[6] = strdup(nl_langinfo(ABMON_7));
202*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[7] = strdup(nl_langinfo(ABMON_8));
203*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[8] = strdup(nl_langinfo(ABMON_9));
204*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[9] = strdup(nl_langinfo(ABMON_10));
205*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[10] = strdup(nl_langinfo(ABMON_11));
206*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[11] = strdup(nl_langinfo(ABMON_12));
207*7c478bd9Sstevel@tonic-gate _dtconv.month_names[0] = strdup(nl_langinfo(MON_1));
208*7c478bd9Sstevel@tonic-gate _dtconv.month_names[1] = strdup(nl_langinfo(MON_2));
209*7c478bd9Sstevel@tonic-gate _dtconv.month_names[2] = strdup(nl_langinfo(MON_3));
210*7c478bd9Sstevel@tonic-gate _dtconv.month_names[3] = strdup(nl_langinfo(MON_4));
211*7c478bd9Sstevel@tonic-gate _dtconv.month_names[4] = strdup(nl_langinfo(MON_5));
212*7c478bd9Sstevel@tonic-gate _dtconv.month_names[5] = strdup(nl_langinfo(MON_6));
213*7c478bd9Sstevel@tonic-gate _dtconv.month_names[6] = strdup(nl_langinfo(MON_7));
214*7c478bd9Sstevel@tonic-gate _dtconv.month_names[7] = strdup(nl_langinfo(MON_8));
215*7c478bd9Sstevel@tonic-gate _dtconv.month_names[8] = strdup(nl_langinfo(MON_9));
216*7c478bd9Sstevel@tonic-gate _dtconv.month_names[9] = strdup(nl_langinfo(MON_10));
217*7c478bd9Sstevel@tonic-gate _dtconv.month_names[10] = strdup(nl_langinfo(MON_11));
218*7c478bd9Sstevel@tonic-gate _dtconv.month_names[11] = strdup(nl_langinfo(MON_12));
219*7c478bd9Sstevel@tonic-gate _dtconv.era = strdup(nl_langinfo(ERA));
220*7c478bd9Sstevel@tonic-gate _dtconv.era_d_fmt = strdup(nl_langinfo(ERA_D_FMT));
221*7c478bd9Sstevel@tonic-gate _dtconv.era_d_t_fmt = strdup(nl_langinfo(ERA_D_T_FMT));
222*7c478bd9Sstevel@tonic-gate _dtconv.era_t_fmt = strdup(nl_langinfo(ERA_T_FMT));
223*7c478bd9Sstevel@tonic-gate _dtconv.alt_digits = strdup(nl_langinfo(ALT_DIGITS));
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate loaded = 1;
226*7c478bd9Sstevel@tonic-gate return (&_dtconv);
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate
229*7c478bd9Sstevel@tonic-gate static struct localedef *
localeldconv(void)230*7c478bd9Sstevel@tonic-gate localeldconv(void)
231*7c478bd9Sstevel@tonic-gate {
232*7c478bd9Sstevel@tonic-gate static struct localedef _locdef;
233*7c478bd9Sstevel@tonic-gate static int loaded = 0;
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate if (loaded) {
236*7c478bd9Sstevel@tonic-gate return (&_locdef);
237*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
238*7c478bd9Sstevel@tonic-gate }
239*7c478bd9Sstevel@tonic-gate
240*7c478bd9Sstevel@tonic-gate _locdef.charmap = strdup(nl_langinfo(CODESET));
241*7c478bd9Sstevel@tonic-gate _locdef.code_set_name = strdup(nl_langinfo(CODESET));
242*7c478bd9Sstevel@tonic-gate _locdef.mb_cur_max = MB_CUR_MAX;
243*7c478bd9Sstevel@tonic-gate _locdef.mb_cur_min = 1;
244*7c478bd9Sstevel@tonic-gate _locdef.escape_char = get_escapechar();
245*7c478bd9Sstevel@tonic-gate _locdef.comment_char = get_commentchar();
246*7c478bd9Sstevel@tonic-gate
247*7c478bd9Sstevel@tonic-gate loaded = 1;
248*7c478bd9Sstevel@tonic-gate return (&_locdef);
249*7c478bd9Sstevel@tonic-gate }
250*7c478bd9Sstevel@tonic-gate
251*7c478bd9Sstevel@tonic-gate /*
252*7c478bd9Sstevel@tonic-gate * The locale_name array also defines a canonical ordering for the categories.
253*7c478bd9Sstevel@tonic-gate * The function tocanon() translates the LC_* manifests to their canonical
254*7c478bd9Sstevel@tonic-gate * values.
255*7c478bd9Sstevel@tonic-gate */
256*7c478bd9Sstevel@tonic-gate static struct locale_name {
257*7c478bd9Sstevel@tonic-gate char *name;
258*7c478bd9Sstevel@tonic-gate int category;
259*7c478bd9Sstevel@tonic-gate } locale_name[] = {
260*7c478bd9Sstevel@tonic-gate {"LC_CTYPE", LC_CTYPE},
261*7c478bd9Sstevel@tonic-gate {"LC_NUMERIC", LC_NUMERIC},
262*7c478bd9Sstevel@tonic-gate {"LC_TIME", LC_TIME},
263*7c478bd9Sstevel@tonic-gate {"LC_COLLATE", LC_COLLATE},
264*7c478bd9Sstevel@tonic-gate {"LC_MONETARY", LC_MONETARY},
265*7c478bd9Sstevel@tonic-gate {"LC_MESSAGES", LC_MESSAGES},
266*7c478bd9Sstevel@tonic-gate {"LC_ALL", LC_ALL},
267*7c478bd9Sstevel@tonic-gate NULL
268*7c478bd9Sstevel@tonic-gate };
269*7c478bd9Sstevel@tonic-gate
270*7c478bd9Sstevel@tonic-gate /*
271*7c478bd9Sstevel@tonic-gate * The structure key contains all keywords string name,
272*7c478bd9Sstevel@tonic-gate * symbolic name, category, and type (STR INT ...)
273*7c478bd9Sstevel@tonic-gate * the type will decide the way the value of the item be printed out
274*7c478bd9Sstevel@tonic-gate */
275*7c478bd9Sstevel@tonic-gate static struct key {
276*7c478bd9Sstevel@tonic-gate char *name;
277*7c478bd9Sstevel@tonic-gate void *(*structure)(void);
278*7c478bd9Sstevel@tonic-gate int offset;
279*7c478bd9Sstevel@tonic-gate int count;
280*7c478bd9Sstevel@tonic-gate int category;
281*7c478bd9Sstevel@tonic-gate enum types type;
282*7c478bd9Sstevel@tonic-gate } key[] = {
283*7c478bd9Sstevel@tonic-gate
284*7c478bd9Sstevel@tonic-gate #define SPECIAL 0, 0, 0,
285*7c478bd9Sstevel@tonic-gate {"lower", SPECIAL LC_CTYPE, TYPE_CTP},
286*7c478bd9Sstevel@tonic-gate {"upper", SPECIAL LC_CTYPE, TYPE_CTP},
287*7c478bd9Sstevel@tonic-gate {"alpha", SPECIAL LC_CTYPE, TYPE_CTP},
288*7c478bd9Sstevel@tonic-gate {"digit", SPECIAL LC_CTYPE, TYPE_CTP},
289*7c478bd9Sstevel@tonic-gate {"space", SPECIAL LC_CTYPE, TYPE_CTP},
290*7c478bd9Sstevel@tonic-gate {"cntrl", SPECIAL LC_CTYPE, TYPE_CTP},
291*7c478bd9Sstevel@tonic-gate {"punct", SPECIAL LC_CTYPE, TYPE_CTP},
292*7c478bd9Sstevel@tonic-gate {"graph", SPECIAL LC_CTYPE, TYPE_CTP},
293*7c478bd9Sstevel@tonic-gate {"print", SPECIAL LC_CTYPE, TYPE_CTP},
294*7c478bd9Sstevel@tonic-gate {"xdigit", SPECIAL LC_CTYPE, TYPE_CTP},
295*7c478bd9Sstevel@tonic-gate {"blank", SPECIAL LC_CTYPE, TYPE_CTP},
296*7c478bd9Sstevel@tonic-gate
297*7c478bd9Sstevel@tonic-gate {"tolower", SPECIAL LC_CTYPE, TYPE_CNVL},
298*7c478bd9Sstevel@tonic-gate {"toupper", SPECIAL LC_CTYPE, TYPE_CNVU},
299*7c478bd9Sstevel@tonic-gate
300*7c478bd9Sstevel@tonic-gate {"collating-element", 0, 0, 0, LC_COLLATE, TYPE_COLLEL},
301*7c478bd9Sstevel@tonic-gate {"character-collation", 0, 1, 0, LC_COLLATE, TYPE_COLLEL},
302*7c478bd9Sstevel@tonic-gate
303*7c478bd9Sstevel@tonic-gate #define dt(member, count) \
304*7c478bd9Sstevel@tonic-gate (void *(*)(void))localedtconv, \
305*7c478bd9Sstevel@tonic-gate offsetof(struct dtconv, member), \
306*7c478bd9Sstevel@tonic-gate count, \
307*7c478bd9Sstevel@tonic-gate LC_TIME, \
308*7c478bd9Sstevel@tonic-gate TYPE_STR
309*7c478bd9Sstevel@tonic-gate {"d_t_fmt", dt(date_time_format, 1)},
310*7c478bd9Sstevel@tonic-gate {"d_fmt", dt(date_format, 1)},
311*7c478bd9Sstevel@tonic-gate {"t_fmt", dt(time_format, 1)},
312*7c478bd9Sstevel@tonic-gate {"t_fmt_ampm", dt(time_format_ampm, 1)},
313*7c478bd9Sstevel@tonic-gate {"am_pm", dt(am_string, 2)},
314*7c478bd9Sstevel@tonic-gate {"day", dt(day_names, 7)},
315*7c478bd9Sstevel@tonic-gate {"abday", dt(abbrev_day_names, 7)},
316*7c478bd9Sstevel@tonic-gate {"mon", dt(month_names, 12)},
317*7c478bd9Sstevel@tonic-gate {"abmon", dt(abbrev_month_names, 12)},
318*7c478bd9Sstevel@tonic-gate {"era", dt(era, 1)},
319*7c478bd9Sstevel@tonic-gate {"era_d_fmt", dt(era_d_fmt, 1)},
320*7c478bd9Sstevel@tonic-gate {"era_d_t_fmt", dt(era_d_t_fmt, 1)},
321*7c478bd9Sstevel@tonic-gate {"era_t_fmt", dt(era_t_fmt, 1)},
322*7c478bd9Sstevel@tonic-gate {"alt_digits", dt(alt_digits, 1)},
323*7c478bd9Sstevel@tonic-gate
324*7c478bd9Sstevel@tonic-gate #undef dt
325*7c478bd9Sstevel@tonic-gate
326*7c478bd9Sstevel@tonic-gate #define lc(member, locale, type) \
327*7c478bd9Sstevel@tonic-gate (void *(*)(void))localeconv, \
328*7c478bd9Sstevel@tonic-gate offsetof(struct lconv, member), \
329*7c478bd9Sstevel@tonic-gate 1, \
330*7c478bd9Sstevel@tonic-gate locale, \
331*7c478bd9Sstevel@tonic-gate type
332*7c478bd9Sstevel@tonic-gate {"decimal_point", lc(decimal_point, LC_NUMERIC, TYPE_STR) },
333*7c478bd9Sstevel@tonic-gate {"thousands_sep", lc(thousands_sep, LC_NUMERIC, TYPE_STR) },
334*7c478bd9Sstevel@tonic-gate {"grouping", lc(grouping, LC_NUMERIC, TYPE_GROUP)},
335*7c478bd9Sstevel@tonic-gate {"int_curr_symbol", lc(int_curr_symbol, LC_MONETARY, TYPE_STR)},
336*7c478bd9Sstevel@tonic-gate {"currency_symbol", lc(currency_symbol, LC_MONETARY, TYPE_STR)},
337*7c478bd9Sstevel@tonic-gate {"mon_decimal_point", lc(mon_decimal_point, LC_MONETARY, TYPE_STR)},
338*7c478bd9Sstevel@tonic-gate {"mon_thousands_sep", lc(mon_thousands_sep, LC_MONETARY, TYPE_STR)},
339*7c478bd9Sstevel@tonic-gate {"mon_grouping", lc(mon_grouping, LC_MONETARY, TYPE_GROUP)},
340*7c478bd9Sstevel@tonic-gate {"positive_sign", lc(positive_sign, LC_MONETARY, TYPE_STR)},
341*7c478bd9Sstevel@tonic-gate {"negative_sign", lc(negative_sign, LC_MONETARY, TYPE_STR)},
342*7c478bd9Sstevel@tonic-gate
343*7c478bd9Sstevel@tonic-gate {"int_frac_digits", lc(int_frac_digits, LC_MONETARY, TYPE_CHR)},
344*7c478bd9Sstevel@tonic-gate {"frac_digits", lc(frac_digits, LC_MONETARY, TYPE_CHR)},
345*7c478bd9Sstevel@tonic-gate {"p_cs_precedes", lc(p_cs_precedes, LC_MONETARY, TYPE_CHR)},
346*7c478bd9Sstevel@tonic-gate {"p_sep_by_space", lc(p_sep_by_space, LC_MONETARY, TYPE_CHR)},
347*7c478bd9Sstevel@tonic-gate {"n_cs_precedes", lc(n_cs_precedes, LC_MONETARY, TYPE_CHR)},
348*7c478bd9Sstevel@tonic-gate {"n_sep_by_space", lc(n_sep_by_space, LC_MONETARY, TYPE_CHR)},
349*7c478bd9Sstevel@tonic-gate {"p_sign_posn", lc(p_sign_posn, LC_MONETARY, TYPE_CHR)},
350*7c478bd9Sstevel@tonic-gate {"n_sign_posn", lc(n_sign_posn, LC_MONETARY, TYPE_CHR)},
351*7c478bd9Sstevel@tonic-gate {"int_p_cs_precedes", lc(int_p_cs_precedes, LC_MONETARY, TYPE_CHR)},
352*7c478bd9Sstevel@tonic-gate {"int_p_sep_by_space", lc(int_p_sep_by_space, LC_MONETARY, TYPE_CHR)},
353*7c478bd9Sstevel@tonic-gate {"int_n_cs_precedes", lc(int_n_cs_precedes, LC_MONETARY, TYPE_CHR)},
354*7c478bd9Sstevel@tonic-gate {"int_n_sep_by_space", lc(int_n_sep_by_space, LC_MONETARY, TYPE_CHR)},
355*7c478bd9Sstevel@tonic-gate {"int_p_sign_posn", lc(int_p_sign_posn, LC_MONETARY, TYPE_CHR)},
356*7c478bd9Sstevel@tonic-gate {"int_n_sign_posn", lc(int_n_sign_posn, LC_MONETARY, TYPE_CHR)},
357*7c478bd9Sstevel@tonic-gate
358*7c478bd9Sstevel@tonic-gate #undef lc
359*7c478bd9Sstevel@tonic-gate #define lc(member) \
360*7c478bd9Sstevel@tonic-gate (void *(*)(void))getyesno, \
361*7c478bd9Sstevel@tonic-gate offsetof(struct yesno, member), \
362*7c478bd9Sstevel@tonic-gate 1, \
363*7c478bd9Sstevel@tonic-gate LC_MESSAGES, \
364*7c478bd9Sstevel@tonic-gate TYPE_STR
365*7c478bd9Sstevel@tonic-gate {"yesexpr", lc(yes_expr)},
366*7c478bd9Sstevel@tonic-gate {"noexpr", lc(no_expr)},
367*7c478bd9Sstevel@tonic-gate {"yesstr", lc(yes_str)},
368*7c478bd9Sstevel@tonic-gate {"nostr", lc(no_str)},
369*7c478bd9Sstevel@tonic-gate #undef lc
370*7c478bd9Sstevel@tonic-gate
371*7c478bd9Sstevel@tonic-gate /*
372*7c478bd9Sstevel@tonic-gate * Following keywords have no official method of obtaining them
373*7c478bd9Sstevel@tonic-gate */
374*7c478bd9Sstevel@tonic-gate #define ld(member, locale, type) \
375*7c478bd9Sstevel@tonic-gate (void *(*)(void))localeldconv, \
376*7c478bd9Sstevel@tonic-gate offsetof(struct localedef, member), \
377*7c478bd9Sstevel@tonic-gate 1, \
378*7c478bd9Sstevel@tonic-gate locale, \
379*7c478bd9Sstevel@tonic-gate type
380*7c478bd9Sstevel@tonic-gate {"charmap", ld(charmap, LC_LOCDEF, TYPE_STR)},
381*7c478bd9Sstevel@tonic-gate {"code_set_name", ld(code_set_name, LC_LOCDEF, TYPE_STR)},
382*7c478bd9Sstevel@tonic-gate {"escape_char", ld(escape_char, LC_LOCDEF, TYPE_PCHR)},
383*7c478bd9Sstevel@tonic-gate {"comment_char", ld(comment_char, LC_LOCDEF, TYPE_PCHR)},
384*7c478bd9Sstevel@tonic-gate {"mb_cur_max", ld(mb_cur_max, LC_LOCDEF, TYPE_INT)},
385*7c478bd9Sstevel@tonic-gate {"mb_cur_min", ld(mb_cur_min, LC_LOCDEF, TYPE_INT)},
386*7c478bd9Sstevel@tonic-gate #undef ld
387*7c478bd9Sstevel@tonic-gate
388*7c478bd9Sstevel@tonic-gate {NULL, NULL, 0, 0}
389*7c478bd9Sstevel@tonic-gate };
390*7c478bd9Sstevel@tonic-gate
391*7c478bd9Sstevel@tonic-gate static char escapec;
392*7c478bd9Sstevel@tonic-gate
393*7c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)394*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate int c;
397*7c478bd9Sstevel@tonic-gate int retval = 0;
398*7c478bd9Sstevel@tonic-gate int cflag, kflag, aflag, mflag;
399*7c478bd9Sstevel@tonic-gate
400*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
401*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
402*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
403*7c478bd9Sstevel@tonic-gate #endif
404*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
405*7c478bd9Sstevel@tonic-gate
406*7c478bd9Sstevel@tonic-gate cflag = kflag = aflag = mflag = 0;
407*7c478bd9Sstevel@tonic-gate
408*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "amck")) != EOF) {
409*7c478bd9Sstevel@tonic-gate switch (c) {
410*7c478bd9Sstevel@tonic-gate case 'a':
411*7c478bd9Sstevel@tonic-gate aflag = 1;
412*7c478bd9Sstevel@tonic-gate break;
413*7c478bd9Sstevel@tonic-gate case 'm':
414*7c478bd9Sstevel@tonic-gate mflag = 1;
415*7c478bd9Sstevel@tonic-gate break;
416*7c478bd9Sstevel@tonic-gate case 'c':
417*7c478bd9Sstevel@tonic-gate cflag = 1;
418*7c478bd9Sstevel@tonic-gate break;
419*7c478bd9Sstevel@tonic-gate case 'k':
420*7c478bd9Sstevel@tonic-gate kflag = 1;
421*7c478bd9Sstevel@tonic-gate break;
422*7c478bd9Sstevel@tonic-gate default:
423*7c478bd9Sstevel@tonic-gate usage();
424*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
425*7c478bd9Sstevel@tonic-gate break;
426*7c478bd9Sstevel@tonic-gate }
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate
429*7c478bd9Sstevel@tonic-gate /* -a OR -m OR (-c and/or -k) */
430*7c478bd9Sstevel@tonic-gate if ((aflag && mflag) || ((aflag || mflag) && (cflag || kflag))) {
431*7c478bd9Sstevel@tonic-gate usage();
432*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate
435*7c478bd9Sstevel@tonic-gate escapec = get_escapechar();
436*7c478bd9Sstevel@tonic-gate
437*7c478bd9Sstevel@tonic-gate if (aflag) {
438*7c478bd9Sstevel@tonic-gate print_all_info(GET_LOCALE);
439*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
440*7c478bd9Sstevel@tonic-gate }
441*7c478bd9Sstevel@tonic-gate
442*7c478bd9Sstevel@tonic-gate if (mflag) {
443*7c478bd9Sstevel@tonic-gate print_all_info(GET_CHARMAP);
444*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
445*7c478bd9Sstevel@tonic-gate }
446*7c478bd9Sstevel@tonic-gate
447*7c478bd9Sstevel@tonic-gate if (optind == argc && !cflag && !kflag) {
448*7c478bd9Sstevel@tonic-gate print_cur_locale();
449*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
450*7c478bd9Sstevel@tonic-gate }
451*7c478bd9Sstevel@tonic-gate if (optind == argc) {
452*7c478bd9Sstevel@tonic-gate usage();
453*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate
456*7c478bd9Sstevel@tonic-gate for (; optind < argc; optind++) {
457*7c478bd9Sstevel@tonic-gate retval += print_locale_info(argv[optind], cflag, kflag);
458*7c478bd9Sstevel@tonic-gate }
459*7c478bd9Sstevel@tonic-gate return (retval);
460*7c478bd9Sstevel@tonic-gate }
461*7c478bd9Sstevel@tonic-gate
462*7c478bd9Sstevel@tonic-gate /*
463*7c478bd9Sstevel@tonic-gate * No options or operands.
464*7c478bd9Sstevel@tonic-gate * Print out the current locale names from the environment, or implied.
465*7c478bd9Sstevel@tonic-gate * Variables directly set in the environment are printed as-is, those
466*7c478bd9Sstevel@tonic-gate * implied are printed in quotes.
467*7c478bd9Sstevel@tonic-gate * The strings are printed ``appropriately quoted for possible later re-entry
468*7c478bd9Sstevel@tonic-gate * to the shell''. We use the routine outstr to do this -- however we
469*7c478bd9Sstevel@tonic-gate * want the shell escape character, the backslash, not the locale escape
470*7c478bd9Sstevel@tonic-gate * character, so we quietly save and restore the locale escape character.
471*7c478bd9Sstevel@tonic-gate */
472*7c478bd9Sstevel@tonic-gate static void
print_cur_locale(void)473*7c478bd9Sstevel@tonic-gate print_cur_locale(void)
474*7c478bd9Sstevel@tonic-gate {
475*7c478bd9Sstevel@tonic-gate char *lc_allp;
476*7c478bd9Sstevel@tonic-gate char *env, *eff;
477*7c478bd9Sstevel@tonic-gate int i;
478*7c478bd9Sstevel@tonic-gate
479*7c478bd9Sstevel@tonic-gate if ((env = getenv("LANG")) != NULL) {
480*7c478bd9Sstevel@tonic-gate (void) printf("LANG=%s\n", env);
481*7c478bd9Sstevel@tonic-gate } else {
482*7c478bd9Sstevel@tonic-gate (void) printf("LANG=\n");
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate
485*7c478bd9Sstevel@tonic-gate lc_allp = getenv("LC_ALL");
486*7c478bd9Sstevel@tonic-gate
487*7c478bd9Sstevel@tonic-gate for (i = 0; i < LC_ALL; i++) {
488*7c478bd9Sstevel@tonic-gate (void) printf("%s=", locale_name[i].name);
489*7c478bd9Sstevel@tonic-gate eff = setlocale(i, NULL);
490*7c478bd9Sstevel@tonic-gate if (eff == NULL) {
491*7c478bd9Sstevel@tonic-gate eff = "";
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate env = getenv(locale_name[i].name);
494*7c478bd9Sstevel@tonic-gate
495*7c478bd9Sstevel@tonic-gate if (env == NULL) {
496*7c478bd9Sstevel@tonic-gate (void) putchar('"');
497*7c478bd9Sstevel@tonic-gate outstr(eff);
498*7c478bd9Sstevel@tonic-gate (void) putchar('"');
499*7c478bd9Sstevel@tonic-gate } else {
500*7c478bd9Sstevel@tonic-gate if (strcmp(env, eff) != 0) {
501*7c478bd9Sstevel@tonic-gate (void) putchar('"');
502*7c478bd9Sstevel@tonic-gate outstr(eff);
503*7c478bd9Sstevel@tonic-gate (void) putchar('"');
504*7c478bd9Sstevel@tonic-gate } else {
505*7c478bd9Sstevel@tonic-gate outstr(eff);
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate }
508*7c478bd9Sstevel@tonic-gate (void) putchar('\n');
509*7c478bd9Sstevel@tonic-gate }
510*7c478bd9Sstevel@tonic-gate
511*7c478bd9Sstevel@tonic-gate (void) printf("LC_ALL=");
512*7c478bd9Sstevel@tonic-gate if (lc_allp != NULL) {
513*7c478bd9Sstevel@tonic-gate outstr(lc_allp);
514*7c478bd9Sstevel@tonic-gate }
515*7c478bd9Sstevel@tonic-gate (void) putchar('\n');
516*7c478bd9Sstevel@tonic-gate exit(0);
517*7c478bd9Sstevel@tonic-gate }
518*7c478bd9Sstevel@tonic-gate
519*7c478bd9Sstevel@tonic-gate static int num_of_loc = 0;
520*7c478bd9Sstevel@tonic-gate static int num_of_entries = 0;
521*7c478bd9Sstevel@tonic-gate static char **entries = NULL;
522*7c478bd9Sstevel@tonic-gate
523*7c478bd9Sstevel@tonic-gate static void
add_loc_entry(char * loc)524*7c478bd9Sstevel@tonic-gate add_loc_entry(char *loc)
525*7c478bd9Sstevel@tonic-gate {
526*7c478bd9Sstevel@tonic-gate #define _INC_NUM 10
527*7c478bd9Sstevel@tonic-gate char *s;
528*7c478bd9Sstevel@tonic-gate
529*7c478bd9Sstevel@tonic-gate if (num_of_loc >= num_of_entries) {
530*7c478bd9Sstevel@tonic-gate char **tmp;
531*7c478bd9Sstevel@tonic-gate num_of_entries += _INC_NUM;
532*7c478bd9Sstevel@tonic-gate tmp = realloc(entries, sizeof (char *) * num_of_entries);
533*7c478bd9Sstevel@tonic-gate if (tmp == NULL) {
534*7c478bd9Sstevel@tonic-gate /* restoring original locale */
535*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, save_loc);
536*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
537*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer"));
538*7c478bd9Sstevel@tonic-gate exit(1);
539*7c478bd9Sstevel@tonic-gate }
540*7c478bd9Sstevel@tonic-gate entries = tmp;
541*7c478bd9Sstevel@tonic-gate }
542*7c478bd9Sstevel@tonic-gate s = strdup(loc);
543*7c478bd9Sstevel@tonic-gate if (s == NULL) {
544*7c478bd9Sstevel@tonic-gate /* restoring original locale */
545*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, save_loc);
546*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
547*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer"));
548*7c478bd9Sstevel@tonic-gate exit(1);
549*7c478bd9Sstevel@tonic-gate }
550*7c478bd9Sstevel@tonic-gate entries[num_of_loc] = s;
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate num_of_loc++;
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate
555*7c478bd9Sstevel@tonic-gate static int
loccmp(const char ** str1,const char ** str2)556*7c478bd9Sstevel@tonic-gate loccmp(const char **str1, const char **str2)
557*7c478bd9Sstevel@tonic-gate {
558*7c478bd9Sstevel@tonic-gate return (strcmp(*str1, *str2));
559*7c478bd9Sstevel@tonic-gate }
560*7c478bd9Sstevel@tonic-gate
561*7c478bd9Sstevel@tonic-gate static void
show_loc_entry(void)562*7c478bd9Sstevel@tonic-gate show_loc_entry(void)
563*7c478bd9Sstevel@tonic-gate {
564*7c478bd9Sstevel@tonic-gate int i;
565*7c478bd9Sstevel@tonic-gate
566*7c478bd9Sstevel@tonic-gate qsort(entries, num_of_loc, sizeof (char *),
567*7c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))loccmp);
568*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_of_loc; i++) {
569*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", entries[i]);
570*7c478bd9Sstevel@tonic-gate }
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate
573*7c478bd9Sstevel@tonic-gate static void
check_loc(char * loc)574*7c478bd9Sstevel@tonic-gate check_loc(char *loc)
575*7c478bd9Sstevel@tonic-gate {
576*7c478bd9Sstevel@tonic-gate int cat;
577*7c478bd9Sstevel@tonic-gate
578*7c478bd9Sstevel@tonic-gate /* first, try LC_ALL */
579*7c478bd9Sstevel@tonic-gate if (setlocale(LC_ALL, loc) != NULL) {
580*7c478bd9Sstevel@tonic-gate /* succeeded */
581*7c478bd9Sstevel@tonic-gate add_loc_entry(loc);
582*7c478bd9Sstevel@tonic-gate return;
583*7c478bd9Sstevel@tonic-gate }
584*7c478bd9Sstevel@tonic-gate
585*7c478bd9Sstevel@tonic-gate /*
586*7c478bd9Sstevel@tonic-gate * LC_ALL failed.
587*7c478bd9Sstevel@tonic-gate * try each category.
588*7c478bd9Sstevel@tonic-gate */
589*7c478bd9Sstevel@tonic-gate for (cat = 0; cat <= _LastCategory; cat++) {
590*7c478bd9Sstevel@tonic-gate if (setlocale(cat, loc) != NULL) {
591*7c478bd9Sstevel@tonic-gate /* succeeded */
592*7c478bd9Sstevel@tonic-gate add_loc_entry(loc);
593*7c478bd9Sstevel@tonic-gate return;
594*7c478bd9Sstevel@tonic-gate }
595*7c478bd9Sstevel@tonic-gate }
596*7c478bd9Sstevel@tonic-gate
597*7c478bd9Sstevel@tonic-gate /* loc is not a valid locale */
598*7c478bd9Sstevel@tonic-gate }
599*7c478bd9Sstevel@tonic-gate
600*7c478bd9Sstevel@tonic-gate /*
601*7c478bd9Sstevel@tonic-gate * print_all_info(): Print out all the locales and
602*7c478bd9Sstevel@tonic-gate * charmaps supported by the system
603*7c478bd9Sstevel@tonic-gate */
604*7c478bd9Sstevel@tonic-gate static void
print_all_info(int flag)605*7c478bd9Sstevel@tonic-gate print_all_info(int flag)
606*7c478bd9Sstevel@tonic-gate {
607*7c478bd9Sstevel@tonic-gate struct dirent *direntp;
608*7c478bd9Sstevel@tonic-gate DIR *dirp;
609*7c478bd9Sstevel@tonic-gate char *filename; /* filename[PATH_MAX] */
610*7c478bd9Sstevel@tonic-gate char *p;
611*7c478bd9Sstevel@tonic-gate
612*7c478bd9Sstevel@tonic-gate if ((filename = malloc(PATH_MAX)) == NULL) {
613*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
614*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer"));
615*7c478bd9Sstevel@tonic-gate exit(1);
616*7c478bd9Sstevel@tonic-gate }
617*7c478bd9Sstevel@tonic-gate
618*7c478bd9Sstevel@tonic-gate (void) memset(filename, 0, PATH_MAX);
619*7c478bd9Sstevel@tonic-gate
620*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) {
621*7c478bd9Sstevel@tonic-gate /* save the current locale */
622*7c478bd9Sstevel@tonic-gate save_loc = setlocale(LC_ALL, NULL);
623*7c478bd9Sstevel@tonic-gate
624*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, LOCALE_DIR);
625*7c478bd9Sstevel@tonic-gate add_loc_entry("POSIX");
626*7c478bd9Sstevel@tonic-gate } else { /* CHARMAP */
627*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, CHARMAP_DIR);
628*7c478bd9Sstevel@tonic-gate }
629*7c478bd9Sstevel@tonic-gate
630*7c478bd9Sstevel@tonic-gate if ((dirp = opendir(filename)) == NULL) {
631*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE)
632*7c478bd9Sstevel@tonic-gate exit(0);
633*7c478bd9Sstevel@tonic-gate else { /* CHARMAP */
634*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
635*7c478bd9Sstevel@tonic-gate "locale: charmap information not available.\n"));
636*7c478bd9Sstevel@tonic-gate exit(2);
637*7c478bd9Sstevel@tonic-gate }
638*7c478bd9Sstevel@tonic-gate }
639*7c478bd9Sstevel@tonic-gate
640*7c478bd9Sstevel@tonic-gate p = filename + strlen(filename);
641*7c478bd9Sstevel@tonic-gate while ((direntp = readdir(dirp)) != NULL) {
642*7c478bd9Sstevel@tonic-gate struct stat stbuf;
643*7c478bd9Sstevel@tonic-gate
644*7c478bd9Sstevel@tonic-gate (void) strcpy(p, direntp->d_name);
645*7c478bd9Sstevel@tonic-gate if (stat(filename, &stbuf) < 0) {
646*7c478bd9Sstevel@tonic-gate continue;
647*7c478bd9Sstevel@tonic-gate }
648*7c478bd9Sstevel@tonic-gate
649*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) {
650*7c478bd9Sstevel@tonic-gate if (S_ISDIR(stbuf.st_mode) &&
651*7c478bd9Sstevel@tonic-gate (direntp->d_name[0] != '.') &&
652*7c478bd9Sstevel@tonic-gate /* "POSIX" has already been printed out */
653*7c478bd9Sstevel@tonic-gate strcmp(direntp->d_name, "POSIX") != 0) {
654*7c478bd9Sstevel@tonic-gate check_loc(direntp->d_name);
655*7c478bd9Sstevel@tonic-gate }
656*7c478bd9Sstevel@tonic-gate } else { /* CHARMAP */
657*7c478bd9Sstevel@tonic-gate if (S_ISDIR(stbuf.st_mode) &&
658*7c478bd9Sstevel@tonic-gate direntp->d_name[0] != '.') {
659*7c478bd9Sstevel@tonic-gate struct dirent *direntc;
660*7c478bd9Sstevel@tonic-gate DIR *dirc;
661*7c478bd9Sstevel@tonic-gate char *charmap;
662*7c478bd9Sstevel@tonic-gate char *c;
663*7c478bd9Sstevel@tonic-gate
664*7c478bd9Sstevel@tonic-gate if ((charmap = malloc(PATH_MAX)) == NULL) {
665*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
666*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer"));
667*7c478bd9Sstevel@tonic-gate exit(1);
668*7c478bd9Sstevel@tonic-gate }
669*7c478bd9Sstevel@tonic-gate
670*7c478bd9Sstevel@tonic-gate (void) memset(charmap, 0, PATH_MAX);
671*7c478bd9Sstevel@tonic-gate
672*7c478bd9Sstevel@tonic-gate (void) strcpy(charmap, filename);
673*7c478bd9Sstevel@tonic-gate
674*7c478bd9Sstevel@tonic-gate if ((dirc = opendir(charmap)) == NULL) {
675*7c478bd9Sstevel@tonic-gate exit(0);
676*7c478bd9Sstevel@tonic-gate }
677*7c478bd9Sstevel@tonic-gate
678*7c478bd9Sstevel@tonic-gate c = charmap + strlen(charmap);
679*7c478bd9Sstevel@tonic-gate *c++ = '/';
680*7c478bd9Sstevel@tonic-gate while ((direntc = readdir(dirc)) != NULL) {
681*7c478bd9Sstevel@tonic-gate struct stat stbuf;
682*7c478bd9Sstevel@tonic-gate
683*7c478bd9Sstevel@tonic-gate (void) strcpy(c, direntc->d_name);
684*7c478bd9Sstevel@tonic-gate if (stat(charmap, &stbuf) < 0) {
685*7c478bd9Sstevel@tonic-gate continue;
686*7c478bd9Sstevel@tonic-gate }
687*7c478bd9Sstevel@tonic-gate
688*7c478bd9Sstevel@tonic-gate if (S_ISREG(stbuf.st_mode) &&
689*7c478bd9Sstevel@tonic-gate (strcmp(direntc->d_name,
690*7c478bd9Sstevel@tonic-gate CHARMAP_NAME) == 0) &&
691*7c478bd9Sstevel@tonic-gate (direntc->d_name[0] != '.')) {
692*7c478bd9Sstevel@tonic-gate (void) printf("%s/%s\n",
693*7c478bd9Sstevel@tonic-gate p, direntc->d_name);
694*7c478bd9Sstevel@tonic-gate }
695*7c478bd9Sstevel@tonic-gate }
696*7c478bd9Sstevel@tonic-gate (void) closedir(dirc);
697*7c478bd9Sstevel@tonic-gate free(charmap);
698*7c478bd9Sstevel@tonic-gate }
699*7c478bd9Sstevel@tonic-gate }
700*7c478bd9Sstevel@tonic-gate }
701*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) {
702*7c478bd9Sstevel@tonic-gate /* restore the saved loc */
703*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, save_loc);
704*7c478bd9Sstevel@tonic-gate show_loc_entry();
705*7c478bd9Sstevel@tonic-gate }
706*7c478bd9Sstevel@tonic-gate (void) closedir(dirp);
707*7c478bd9Sstevel@tonic-gate free(filename);
708*7c478bd9Sstevel@tonic-gate exit(0);
709*7c478bd9Sstevel@tonic-gate }
710*7c478bd9Sstevel@tonic-gate
711*7c478bd9Sstevel@tonic-gate /*
712*7c478bd9Sstevel@tonic-gate * Print out the keyword value or category info.
713*7c478bd9Sstevel@tonic-gate * Call print_category() to print the entire locale category, if the name
714*7c478bd9Sstevel@tonic-gate * given is recognized as a category.
715*7c478bd9Sstevel@tonic-gate * Otherwise, assume that it is a keyword, and call print_keyword().
716*7c478bd9Sstevel@tonic-gate */
717*7c478bd9Sstevel@tonic-gate static int
print_locale_info(char * name,int cflag,int kflag)718*7c478bd9Sstevel@tonic-gate print_locale_info(char *name, int cflag, int kflag)
719*7c478bd9Sstevel@tonic-gate {
720*7c478bd9Sstevel@tonic-gate int i;
721*7c478bd9Sstevel@tonic-gate
722*7c478bd9Sstevel@tonic-gate for (i = 0; locale_name[i].name != NULL; i++) {
723*7c478bd9Sstevel@tonic-gate if (strcmp(locale_name[i].name, name) == 0) {
724*7c478bd9Sstevel@tonic-gate /*
725*7c478bd9Sstevel@tonic-gate * name is a category name
726*7c478bd9Sstevel@tonic-gate * print out all keywords in this category
727*7c478bd9Sstevel@tonic-gate */
728*7c478bd9Sstevel@tonic-gate return (print_category(locale_name[i].category,
729*7c478bd9Sstevel@tonic-gate cflag, kflag));
730*7c478bd9Sstevel@tonic-gate }
731*7c478bd9Sstevel@tonic-gate }
732*7c478bd9Sstevel@tonic-gate
733*7c478bd9Sstevel@tonic-gate /* The name is a keyword name */
734*7c478bd9Sstevel@tonic-gate return (print_keyword(name, cflag, kflag));
735*7c478bd9Sstevel@tonic-gate }
736*7c478bd9Sstevel@tonic-gate
737*7c478bd9Sstevel@tonic-gate /*
738*7c478bd9Sstevel@tonic-gate * Print out the value of the keyword
739*7c478bd9Sstevel@tonic-gate */
740*7c478bd9Sstevel@tonic-gate static int
print_keyword(char * name,int cflag,int kflag)741*7c478bd9Sstevel@tonic-gate print_keyword(char *name, int cflag, int kflag)
742*7c478bd9Sstevel@tonic-gate {
743*7c478bd9Sstevel@tonic-gate int i, j;
744*7c478bd9Sstevel@tonic-gate int first_flag = 1;
745*7c478bd9Sstevel@tonic-gate int found = 0;
746*7c478bd9Sstevel@tonic-gate
747*7c478bd9Sstevel@tonic-gate for (i = 0; key[i].name != NULL; i++) {
748*7c478bd9Sstevel@tonic-gate if (strcmp(key[i].name, name) != 0) {
749*7c478bd9Sstevel@tonic-gate continue;
750*7c478bd9Sstevel@tonic-gate }
751*7c478bd9Sstevel@tonic-gate
752*7c478bd9Sstevel@tonic-gate found = 1;
753*7c478bd9Sstevel@tonic-gate if (first_flag && cflag && key[i].category != LC_LOCDEF) {
754*7c478bd9Sstevel@tonic-gate /* print out this category's name */
755*7c478bd9Sstevel@tonic-gate (void) printf("%s\n",
756*7c478bd9Sstevel@tonic-gate locale_name[key[i].category].name);
757*7c478bd9Sstevel@tonic-gate }
758*7c478bd9Sstevel@tonic-gate if (kflag) {
759*7c478bd9Sstevel@tonic-gate (void) printf("%s=", name);
760*7c478bd9Sstevel@tonic-gate }
761*7c478bd9Sstevel@tonic-gate switch (key[i].type) {
762*7c478bd9Sstevel@tonic-gate
763*7c478bd9Sstevel@tonic-gate /*
764*7c478bd9Sstevel@tonic-gate * The grouping fields are a set of bytes, each of which
765*7c478bd9Sstevel@tonic-gate * is the numeric value of the next group size, terminated
766*7c478bd9Sstevel@tonic-gate * by a \0, or by CHAR_MAX
767*7c478bd9Sstevel@tonic-gate */
768*7c478bd9Sstevel@tonic-gate case TYPE_GROUP:
769*7c478bd9Sstevel@tonic-gate {
770*7c478bd9Sstevel@tonic-gate void *s;
771*7c478bd9Sstevel@tonic-gate char *q;
772*7c478bd9Sstevel@tonic-gate int first = 1;
773*7c478bd9Sstevel@tonic-gate
774*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)();
775*7c478bd9Sstevel@tonic-gate /* LINTED */
776*7c478bd9Sstevel@tonic-gate q = *(char **)((char *)s + key[i].offset);
777*7c478bd9Sstevel@tonic-gate if (*q == '\0') {
778*7c478bd9Sstevel@tonic-gate (void) printf("-1");
779*7c478bd9Sstevel@tonic-gate break;
780*7c478bd9Sstevel@tonic-gate }
781*7c478bd9Sstevel@tonic-gate while (*q != '\0' && *q != CHAR_MAX) {
782*7c478bd9Sstevel@tonic-gate if (!first) {
783*7c478bd9Sstevel@tonic-gate (void) putchar(';');
784*7c478bd9Sstevel@tonic-gate }
785*7c478bd9Sstevel@tonic-gate first = 0;
786*7c478bd9Sstevel@tonic-gate (void) printf("%u",
787*7c478bd9Sstevel@tonic-gate *(unsigned char *)q++);
788*7c478bd9Sstevel@tonic-gate }
789*7c478bd9Sstevel@tonic-gate /* CHAR_MAX: no further grouping performed. */
790*7c478bd9Sstevel@tonic-gate if (!first) {
791*7c478bd9Sstevel@tonic-gate (void) putchar(';');
792*7c478bd9Sstevel@tonic-gate }
793*7c478bd9Sstevel@tonic-gate if (*q == CHAR_MAX) {
794*7c478bd9Sstevel@tonic-gate (void) printf("-1");
795*7c478bd9Sstevel@tonic-gate } else {
796*7c478bd9Sstevel@tonic-gate (void) putchar('0');
797*7c478bd9Sstevel@tonic-gate }
798*7c478bd9Sstevel@tonic-gate }
799*7c478bd9Sstevel@tonic-gate break;
800*7c478bd9Sstevel@tonic-gate
801*7c478bd9Sstevel@tonic-gate /*
802*7c478bd9Sstevel@tonic-gate * Entries like decimal_point states ``the decimal-point
803*7c478bd9Sstevel@tonic-gate * character...'' not string. However, it is a char *.
804*7c478bd9Sstevel@tonic-gate * This assumes single, narrow, character.
805*7c478bd9Sstevel@tonic-gate * Should it permit multibyte characters?
806*7c478bd9Sstevel@tonic-gate * Should it permit a whole string, in that case?
807*7c478bd9Sstevel@tonic-gate */
808*7c478bd9Sstevel@tonic-gate case TYPE_STR:
809*7c478bd9Sstevel@tonic-gate {
810*7c478bd9Sstevel@tonic-gate void *s;
811*7c478bd9Sstevel@tonic-gate char **q;
812*7c478bd9Sstevel@tonic-gate
813*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)();
814*7c478bd9Sstevel@tonic-gate /* LINTED */
815*7c478bd9Sstevel@tonic-gate q = (char **)((char *)s + key[i].offset);
816*7c478bd9Sstevel@tonic-gate for (j = 0; j < key[i].count; j++) {
817*7c478bd9Sstevel@tonic-gate if (j != 0) {
818*7c478bd9Sstevel@tonic-gate (void) printf(";");
819*7c478bd9Sstevel@tonic-gate }
820*7c478bd9Sstevel@tonic-gate if (kflag) {
821*7c478bd9Sstevel@tonic-gate (void) printf("\"");
822*7c478bd9Sstevel@tonic-gate outstr(q[j]);
823*7c478bd9Sstevel@tonic-gate (void) printf("\"");
824*7c478bd9Sstevel@tonic-gate } else {
825*7c478bd9Sstevel@tonic-gate (void) printf("%s", q[j]);
826*7c478bd9Sstevel@tonic-gate }
827*7c478bd9Sstevel@tonic-gate }
828*7c478bd9Sstevel@tonic-gate }
829*7c478bd9Sstevel@tonic-gate break;
830*7c478bd9Sstevel@tonic-gate
831*7c478bd9Sstevel@tonic-gate case TYPE_INT:
832*7c478bd9Sstevel@tonic-gate {
833*7c478bd9Sstevel@tonic-gate void *s;
834*7c478bd9Sstevel@tonic-gate int *q;
835*7c478bd9Sstevel@tonic-gate
836*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)();
837*7c478bd9Sstevel@tonic-gate /* LINTED */
838*7c478bd9Sstevel@tonic-gate q = (int *)((char *)s + key[i].offset);
839*7c478bd9Sstevel@tonic-gate (void) printf("%d", *q);
840*7c478bd9Sstevel@tonic-gate }
841*7c478bd9Sstevel@tonic-gate break;
842*7c478bd9Sstevel@tonic-gate
843*7c478bd9Sstevel@tonic-gate /*
844*7c478bd9Sstevel@tonic-gate * TYPE_CHR: Single byte integer.
845*7c478bd9Sstevel@tonic-gate */
846*7c478bd9Sstevel@tonic-gate case TYPE_CHR:
847*7c478bd9Sstevel@tonic-gate {
848*7c478bd9Sstevel@tonic-gate void *s;
849*7c478bd9Sstevel@tonic-gate char *q;
850*7c478bd9Sstevel@tonic-gate
851*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)();
852*7c478bd9Sstevel@tonic-gate q = (char *)((char *)s + key[i].offset);
853*7c478bd9Sstevel@tonic-gate if (*q == CHAR_MAX) {
854*7c478bd9Sstevel@tonic-gate (void) printf("-1");
855*7c478bd9Sstevel@tonic-gate } else {
856*7c478bd9Sstevel@tonic-gate (void) printf("%u",
857*7c478bd9Sstevel@tonic-gate *(unsigned char *)q);
858*7c478bd9Sstevel@tonic-gate }
859*7c478bd9Sstevel@tonic-gate }
860*7c478bd9Sstevel@tonic-gate break;
861*7c478bd9Sstevel@tonic-gate
862*7c478bd9Sstevel@tonic-gate /*
863*7c478bd9Sstevel@tonic-gate * TYPE_PCHR: Single byte, printed as a character if printable
864*7c478bd9Sstevel@tonic-gate */
865*7c478bd9Sstevel@tonic-gate case TYPE_PCHR:
866*7c478bd9Sstevel@tonic-gate {
867*7c478bd9Sstevel@tonic-gate void *s;
868*7c478bd9Sstevel@tonic-gate char *q;
869*7c478bd9Sstevel@tonic-gate
870*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)();
871*7c478bd9Sstevel@tonic-gate q = (char *)((char *)s + key[i].offset);
872*7c478bd9Sstevel@tonic-gate if (isprint(*(unsigned char *)q)) {
873*7c478bd9Sstevel@tonic-gate if (kflag) {
874*7c478bd9Sstevel@tonic-gate (void) printf("\"");
875*7c478bd9Sstevel@tonic-gate if ((*q == '\\') ||
876*7c478bd9Sstevel@tonic-gate (*q == ';') ||
877*7c478bd9Sstevel@tonic-gate (*q == '"')) {
878*7c478bd9Sstevel@tonic-gate (void) putchar(escapec);
879*7c478bd9Sstevel@tonic-gate (void) printf("%c",
880*7c478bd9Sstevel@tonic-gate *(unsigned char *)q);
881*7c478bd9Sstevel@tonic-gate } else {
882*7c478bd9Sstevel@tonic-gate (void) printf("%c",
883*7c478bd9Sstevel@tonic-gate *(unsigned char *)q);
884*7c478bd9Sstevel@tonic-gate }
885*7c478bd9Sstevel@tonic-gate (void) printf("\"");
886*7c478bd9Sstevel@tonic-gate } else {
887*7c478bd9Sstevel@tonic-gate (void) printf("%c",
888*7c478bd9Sstevel@tonic-gate *(unsigned char *)q);
889*7c478bd9Sstevel@tonic-gate }
890*7c478bd9Sstevel@tonic-gate } else if (*q == (char)-1) {
891*7c478bd9Sstevel@tonic-gate /* In case no signed chars */
892*7c478bd9Sstevel@tonic-gate (void) printf("-1");
893*7c478bd9Sstevel@tonic-gate } else {
894*7c478bd9Sstevel@tonic-gate (void) printf("%u",
895*7c478bd9Sstevel@tonic-gate *(unsigned char *)q);
896*7c478bd9Sstevel@tonic-gate }
897*7c478bd9Sstevel@tonic-gate }
898*7c478bd9Sstevel@tonic-gate break;
899*7c478bd9Sstevel@tonic-gate
900*7c478bd9Sstevel@tonic-gate case TYPE_CTP:
901*7c478bd9Sstevel@tonic-gate {
902*7c478bd9Sstevel@tonic-gate prt_ctp(key[i].name);
903*7c478bd9Sstevel@tonic-gate }
904*7c478bd9Sstevel@tonic-gate break;
905*7c478bd9Sstevel@tonic-gate
906*7c478bd9Sstevel@tonic-gate case TYPE_CNVU:
907*7c478bd9Sstevel@tonic-gate {
908*7c478bd9Sstevel@tonic-gate prt_cnv(key[i].name);
909*7c478bd9Sstevel@tonic-gate }
910*7c478bd9Sstevel@tonic-gate break;
911*7c478bd9Sstevel@tonic-gate
912*7c478bd9Sstevel@tonic-gate case TYPE_CNVL:
913*7c478bd9Sstevel@tonic-gate {
914*7c478bd9Sstevel@tonic-gate prt_cnv(key[i].name);
915*7c478bd9Sstevel@tonic-gate }
916*7c478bd9Sstevel@tonic-gate break;
917*7c478bd9Sstevel@tonic-gate
918*7c478bd9Sstevel@tonic-gate case TYPE_COLLEL:
919*7c478bd9Sstevel@tonic-gate {
920*7c478bd9Sstevel@tonic-gate prt_collel(key[i].name);
921*7c478bd9Sstevel@tonic-gate }
922*7c478bd9Sstevel@tonic-gate break;
923*7c478bd9Sstevel@tonic-gate }
924*7c478bd9Sstevel@tonic-gate }
925*7c478bd9Sstevel@tonic-gate if (found) {
926*7c478bd9Sstevel@tonic-gate (void) printf("\n");
927*7c478bd9Sstevel@tonic-gate return (0);
928*7c478bd9Sstevel@tonic-gate } else {
929*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
930*7c478bd9Sstevel@tonic-gate gettext("Unknown keyword name '%s'.\n"), name);
931*7c478bd9Sstevel@tonic-gate return (1);
932*7c478bd9Sstevel@tonic-gate }
933*7c478bd9Sstevel@tonic-gate }
934*7c478bd9Sstevel@tonic-gate
935*7c478bd9Sstevel@tonic-gate /*
936*7c478bd9Sstevel@tonic-gate * Strings being outputed have to use an unambiguous format -- escape
937*7c478bd9Sstevel@tonic-gate * any potentially bad output characters.
938*7c478bd9Sstevel@tonic-gate * The standard says that any control character shall be preceeded by
939*7c478bd9Sstevel@tonic-gate * the escape character. But it doesn't say that you can format that
940*7c478bd9Sstevel@tonic-gate * character at all.
941*7c478bd9Sstevel@tonic-gate * Question: If the multibyte character contains a quoting character,
942*7c478bd9Sstevel@tonic-gate * should that *byte* be escaped?
943*7c478bd9Sstevel@tonic-gate */
944*7c478bd9Sstevel@tonic-gate static void
outstr(char * s)945*7c478bd9Sstevel@tonic-gate outstr(char *s)
946*7c478bd9Sstevel@tonic-gate {
947*7c478bd9Sstevel@tonic-gate wchar_t ws;
948*7c478bd9Sstevel@tonic-gate int c;
949*7c478bd9Sstevel@tonic-gate size_t mbcurmax = MB_CUR_MAX;
950*7c478bd9Sstevel@tonic-gate
951*7c478bd9Sstevel@tonic-gate while (*s != '\0') {
952*7c478bd9Sstevel@tonic-gate c = mbtowc(&ws, s, mbcurmax);
953*7c478bd9Sstevel@tonic-gate if (c < 0) {
954*7c478bd9Sstevel@tonic-gate s++;
955*7c478bd9Sstevel@tonic-gate } else if (c == 1) {
956*7c478bd9Sstevel@tonic-gate outchar(*s++);
957*7c478bd9Sstevel@tonic-gate } else {
958*7c478bd9Sstevel@tonic-gate for (; c > 0; c--) {
959*7c478bd9Sstevel@tonic-gate (void) putchar(*s++);
960*7c478bd9Sstevel@tonic-gate }
961*7c478bd9Sstevel@tonic-gate }
962*7c478bd9Sstevel@tonic-gate }
963*7c478bd9Sstevel@tonic-gate }
964*7c478bd9Sstevel@tonic-gate
965*7c478bd9Sstevel@tonic-gate static void
outchar(int c)966*7c478bd9Sstevel@tonic-gate outchar(int c)
967*7c478bd9Sstevel@tonic-gate {
968*7c478bd9Sstevel@tonic-gate unsigned char uc;
969*7c478bd9Sstevel@tonic-gate
970*7c478bd9Sstevel@tonic-gate uc = (unsigned char) c;
971*7c478bd9Sstevel@tonic-gate
972*7c478bd9Sstevel@tonic-gate if ((uc == '\\') || (uc == ';') || (uc == '"')) {
973*7c478bd9Sstevel@tonic-gate (void) putchar(escapec);
974*7c478bd9Sstevel@tonic-gate (void) putchar(uc);
975*7c478bd9Sstevel@tonic-gate } else if (iscntrl(uc)) {
976*7c478bd9Sstevel@tonic-gate (void) printf("%cx%02x", escapec, uc);
977*7c478bd9Sstevel@tonic-gate } else {
978*7c478bd9Sstevel@tonic-gate (void) putchar(uc);
979*7c478bd9Sstevel@tonic-gate }
980*7c478bd9Sstevel@tonic-gate }
981*7c478bd9Sstevel@tonic-gate
982*7c478bd9Sstevel@tonic-gate /*
983*7c478bd9Sstevel@tonic-gate * print_category(): Print out all the keyword's value
984*7c478bd9Sstevel@tonic-gate * in the given category
985*7c478bd9Sstevel@tonic-gate */
986*7c478bd9Sstevel@tonic-gate static int
print_category(int category,int cflag,int kflag)987*7c478bd9Sstevel@tonic-gate print_category(int category, int cflag, int kflag)
988*7c478bd9Sstevel@tonic-gate {
989*7c478bd9Sstevel@tonic-gate int i;
990*7c478bd9Sstevel@tonic-gate int retval = 0;
991*7c478bd9Sstevel@tonic-gate
992*7c478bd9Sstevel@tonic-gate if (category == LC_ALL) {
993*7c478bd9Sstevel@tonic-gate retval += print_category(LC_CTYPE, cflag, kflag);
994*7c478bd9Sstevel@tonic-gate retval += print_category(LC_NUMERIC, cflag, kflag);
995*7c478bd9Sstevel@tonic-gate retval += print_category(LC_TIME, cflag, kflag);
996*7c478bd9Sstevel@tonic-gate retval += print_category(LC_COLLATE, cflag, kflag);
997*7c478bd9Sstevel@tonic-gate retval += print_category(LC_MONETARY, cflag, kflag);
998*7c478bd9Sstevel@tonic-gate retval += print_category(LC_MESSAGES, cflag, kflag);
999*7c478bd9Sstevel@tonic-gate } else {
1000*7c478bd9Sstevel@tonic-gate if (cflag) {
1001*7c478bd9Sstevel@tonic-gate (void) printf("%s\n",
1002*7c478bd9Sstevel@tonic-gate locale_name[category].name);
1003*7c478bd9Sstevel@tonic-gate }
1004*7c478bd9Sstevel@tonic-gate
1005*7c478bd9Sstevel@tonic-gate for (i = 0; key[i].name != NULL; i++) {
1006*7c478bd9Sstevel@tonic-gate if (key[i].category == category) {
1007*7c478bd9Sstevel@tonic-gate retval += print_keyword(key[i].name, 0, kflag);
1008*7c478bd9Sstevel@tonic-gate }
1009*7c478bd9Sstevel@tonic-gate }
1010*7c478bd9Sstevel@tonic-gate }
1011*7c478bd9Sstevel@tonic-gate return (retval);
1012*7c478bd9Sstevel@tonic-gate }
1013*7c478bd9Sstevel@tonic-gate
1014*7c478bd9Sstevel@tonic-gate /*
1015*7c478bd9Sstevel@tonic-gate * usage message for locale
1016*7c478bd9Sstevel@tonic-gate */
1017*7c478bd9Sstevel@tonic-gate static void
usage(void)1018*7c478bd9Sstevel@tonic-gate usage(void)
1019*7c478bd9Sstevel@tonic-gate {
1020*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
1021*7c478bd9Sstevel@tonic-gate "Usage: locale [-a|-m]\n"
1022*7c478bd9Sstevel@tonic-gate " locale [-ck] name ...\n"));
1023*7c478bd9Sstevel@tonic-gate exit(2);
1024*7c478bd9Sstevel@tonic-gate }
1025*7c478bd9Sstevel@tonic-gate
1026*7c478bd9Sstevel@tonic-gate static void
prt_ctp(char * name)1027*7c478bd9Sstevel@tonic-gate prt_ctp(char *name)
1028*7c478bd9Sstevel@tonic-gate {
1029*7c478bd9Sstevel@tonic-gate int idx, i, mem;
1030*7c478bd9Sstevel@tonic-gate int first = 1;
1031*7c478bd9Sstevel@tonic-gate
1032*7c478bd9Sstevel@tonic-gate static const char *reg_names[] = {
1033*7c478bd9Sstevel@tonic-gate "upper", "lower", "alpha", "digit", "space", "cntrl",
1034*7c478bd9Sstevel@tonic-gate "punct", "graph", "print", "xdigit", "blank", NULL
1035*7c478bd9Sstevel@tonic-gate };
1036*7c478bd9Sstevel@tonic-gate for (idx = 0; reg_names[idx] != NULL; idx++) {
1037*7c478bd9Sstevel@tonic-gate if (strcmp(name, reg_names[idx]) == 0) {
1038*7c478bd9Sstevel@tonic-gate break;
1039*7c478bd9Sstevel@tonic-gate }
1040*7c478bd9Sstevel@tonic-gate }
1041*7c478bd9Sstevel@tonic-gate if (reg_names[idx] == NULL) {
1042*7c478bd9Sstevel@tonic-gate return;
1043*7c478bd9Sstevel@tonic-gate }
1044*7c478bd9Sstevel@tonic-gate
1045*7c478bd9Sstevel@tonic-gate for (i = 0; i < CSSIZE; i++) {
1046*7c478bd9Sstevel@tonic-gate mem = 0;
1047*7c478bd9Sstevel@tonic-gate switch (idx) {
1048*7c478bd9Sstevel@tonic-gate case 0:
1049*7c478bd9Sstevel@tonic-gate mem = isupper(i);
1050*7c478bd9Sstevel@tonic-gate break;
1051*7c478bd9Sstevel@tonic-gate case 1:
1052*7c478bd9Sstevel@tonic-gate mem = islower(i);
1053*7c478bd9Sstevel@tonic-gate break;
1054*7c478bd9Sstevel@tonic-gate case 2:
1055*7c478bd9Sstevel@tonic-gate mem = isalpha(i);
1056*7c478bd9Sstevel@tonic-gate break;
1057*7c478bd9Sstevel@tonic-gate case 3:
1058*7c478bd9Sstevel@tonic-gate mem = isdigit(i);
1059*7c478bd9Sstevel@tonic-gate break;
1060*7c478bd9Sstevel@tonic-gate case 4:
1061*7c478bd9Sstevel@tonic-gate mem = isspace(i);
1062*7c478bd9Sstevel@tonic-gate break;
1063*7c478bd9Sstevel@tonic-gate case 5:
1064*7c478bd9Sstevel@tonic-gate mem = iscntrl(i);
1065*7c478bd9Sstevel@tonic-gate break;
1066*7c478bd9Sstevel@tonic-gate case 6:
1067*7c478bd9Sstevel@tonic-gate mem = ispunct(i);
1068*7c478bd9Sstevel@tonic-gate break;
1069*7c478bd9Sstevel@tonic-gate case 7:
1070*7c478bd9Sstevel@tonic-gate mem = isgraph(i);
1071*7c478bd9Sstevel@tonic-gate break;
1072*7c478bd9Sstevel@tonic-gate case 8:
1073*7c478bd9Sstevel@tonic-gate mem = isprint(i);
1074*7c478bd9Sstevel@tonic-gate break;
1075*7c478bd9Sstevel@tonic-gate case 9:
1076*7c478bd9Sstevel@tonic-gate mem = isxdigit(i);
1077*7c478bd9Sstevel@tonic-gate break;
1078*7c478bd9Sstevel@tonic-gate case 10:
1079*7c478bd9Sstevel@tonic-gate mem = isblank(i);
1080*7c478bd9Sstevel@tonic-gate break;
1081*7c478bd9Sstevel@tonic-gate }
1082*7c478bd9Sstevel@tonic-gate if (mem) {
1083*7c478bd9Sstevel@tonic-gate if (!first) {
1084*7c478bd9Sstevel@tonic-gate (void) putchar(';');
1085*7c478bd9Sstevel@tonic-gate }
1086*7c478bd9Sstevel@tonic-gate first = 0;
1087*7c478bd9Sstevel@tonic-gate (void) printf("\"");
1088*7c478bd9Sstevel@tonic-gate outchar(i);
1089*7c478bd9Sstevel@tonic-gate (void) printf("\"");
1090*7c478bd9Sstevel@tonic-gate }
1091*7c478bd9Sstevel@tonic-gate }
1092*7c478bd9Sstevel@tonic-gate }
1093*7c478bd9Sstevel@tonic-gate
1094*7c478bd9Sstevel@tonic-gate static void
prt_cnv(char * name)1095*7c478bd9Sstevel@tonic-gate prt_cnv(char *name)
1096*7c478bd9Sstevel@tonic-gate {
1097*7c478bd9Sstevel@tonic-gate int idx, i, q;
1098*7c478bd9Sstevel@tonic-gate int first = 1;
1099*7c478bd9Sstevel@tonic-gate
1100*7c478bd9Sstevel@tonic-gate static const char *reg_names[] = {
1101*7c478bd9Sstevel@tonic-gate "toupper", "tolower", NULL
1102*7c478bd9Sstevel@tonic-gate };
1103*7c478bd9Sstevel@tonic-gate for (idx = 0; reg_names[idx] != NULL; idx++) {
1104*7c478bd9Sstevel@tonic-gate if (strcmp(name, reg_names[idx]) == 0) {
1105*7c478bd9Sstevel@tonic-gate break;
1106*7c478bd9Sstevel@tonic-gate }
1107*7c478bd9Sstevel@tonic-gate }
1108*7c478bd9Sstevel@tonic-gate if (reg_names[idx] == NULL) {
1109*7c478bd9Sstevel@tonic-gate return;
1110*7c478bd9Sstevel@tonic-gate }
1111*7c478bd9Sstevel@tonic-gate
1112*7c478bd9Sstevel@tonic-gate for (i = 0; i < CSSIZE; i++) {
1113*7c478bd9Sstevel@tonic-gate switch (idx) {
1114*7c478bd9Sstevel@tonic-gate case 0:
1115*7c478bd9Sstevel@tonic-gate q = toupper(i);
1116*7c478bd9Sstevel@tonic-gate if (q == i) {
1117*7c478bd9Sstevel@tonic-gate continue;
1118*7c478bd9Sstevel@tonic-gate }
1119*7c478bd9Sstevel@tonic-gate if (!first) {
1120*7c478bd9Sstevel@tonic-gate (void) putchar(';');
1121*7c478bd9Sstevel@tonic-gate }
1122*7c478bd9Sstevel@tonic-gate first = 0;
1123*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
1124*7c478bd9Sstevel@tonic-gate (void) printf("\"<'");
1125*7c478bd9Sstevel@tonic-gate /* END CSTYLED */
1126*7c478bd9Sstevel@tonic-gate outchar(i);
1127*7c478bd9Sstevel@tonic-gate (void) printf("','");
1128*7c478bd9Sstevel@tonic-gate outchar(q);
1129*7c478bd9Sstevel@tonic-gate (void) printf("'>\"");
1130*7c478bd9Sstevel@tonic-gate break;
1131*7c478bd9Sstevel@tonic-gate case 1:
1132*7c478bd9Sstevel@tonic-gate q = tolower(i);
1133*7c478bd9Sstevel@tonic-gate if (q == i) {
1134*7c478bd9Sstevel@tonic-gate continue;
1135*7c478bd9Sstevel@tonic-gate }
1136*7c478bd9Sstevel@tonic-gate if (!first) {
1137*7c478bd9Sstevel@tonic-gate (void) putchar(';');
1138*7c478bd9Sstevel@tonic-gate }
1139*7c478bd9Sstevel@tonic-gate first = 0;
1140*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
1141*7c478bd9Sstevel@tonic-gate (void) printf("\"<'");
1142*7c478bd9Sstevel@tonic-gate /* END CSTYLED */
1143*7c478bd9Sstevel@tonic-gate outchar(i);
1144*7c478bd9Sstevel@tonic-gate (void) printf("','");
1145*7c478bd9Sstevel@tonic-gate outchar(q);
1146*7c478bd9Sstevel@tonic-gate (void) printf("'>\"");
1147*7c478bd9Sstevel@tonic-gate break;
1148*7c478bd9Sstevel@tonic-gate }
1149*7c478bd9Sstevel@tonic-gate }
1150*7c478bd9Sstevel@tonic-gate }
1151*7c478bd9Sstevel@tonic-gate
1152*7c478bd9Sstevel@tonic-gate /*
1153*7c478bd9Sstevel@tonic-gate * prt_collel(): Stub for the collate class which does nothing.
1154*7c478bd9Sstevel@tonic-gate */
1155*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1156*7c478bd9Sstevel@tonic-gate static void
prt_collel(char * name)1157*7c478bd9Sstevel@tonic-gate prt_collel(char *name)
1158*7c478bd9Sstevel@tonic-gate {
1159*7c478bd9Sstevel@tonic-gate }
1160*7c478bd9Sstevel@tonic-gate
1161*7c478bd9Sstevel@tonic-gate static char
get_escapechar(void)1162*7c478bd9Sstevel@tonic-gate get_escapechar(void)
1163*7c478bd9Sstevel@tonic-gate {
1164*7c478bd9Sstevel@tonic-gate return ('\\');
1165*7c478bd9Sstevel@tonic-gate }
1166*7c478bd9Sstevel@tonic-gate
1167*7c478bd9Sstevel@tonic-gate static char
get_commentchar(void)1168*7c478bd9Sstevel@tonic-gate get_commentchar(void)
1169*7c478bd9Sstevel@tonic-gate {
1170*7c478bd9Sstevel@tonic-gate return ('#');
1171*7c478bd9Sstevel@tonic-gate }
1172