]>
git.cameronkatri.com Git - apple_cmds.git/blob - adv_cmds/locale/locale.cc
12 #include <sys/types.h>
15 #define LAST(array) array + (sizeof(array) / sizeof(*array))
17 #define LC_SPECIAL (LC_COLLATE+LC_CTYPE+LC_MESSAGES+LC_MONETARY+LC_NUMERIC+LC_TIME)
25 template<typename T
> string
tostr(T val
) {
31 string
quote(string s
) {
37 virtual string
get_category() const { return category
; }
38 virtual string
get_keyword() const { return kword
; }
39 virtual string
get_value(bool show_quotes
) const {
40 return (show_quotes
&& t
== V_STR
) ? quote(value
) : value
; }
42 virtual ~keyword() { }
44 keyword(int category_
, string kword
, string value
, vtype t
)
45 : kword(kword
), value(value
), t(t
) {
48 category
= "LC_COLLATE";
51 category
= "LC_CTYPE";
54 category
= "LC_MESSAGES";
57 category
= "LC_MONETARY";
60 category
= "LC_NUMERIC";
66 category
= "LC_SPECIAL";
71 lc
<< "LC_" << category_
;
78 string category
, kword
, value
;
83 bool operator()(const keyword
*a
, const keyword
*b
) const {
84 return a
->get_category() < b
->get_category();
88 class li_keyword
: public keyword
{
90 li_keyword(int category
, string kword
, int itemnum
, vtype t
= V_STR
)
91 : keyword(category
, kword
, nl_langinfo(itemnum
), t
) { }
94 class lia_keyword
: public keyword
{
96 vector
<string
> values
;
98 virtual string
get_value(bool show_quotes
) const {
100 vector
<string
>::const_iterator
s(values
.begin()), e(values
.end()), i(s
);
106 if (show_quotes
&& t
== V_STR
) {
116 lia_keyword(int category
, string kword
, int *s
, int *e
, vtype t
= V_STR
)
117 : keyword(category
, kword
, "", t
) {
119 values
.push_back(nl_langinfo(*s
));
124 class lc_keyword
: public keyword
{
126 lc_keyword(int category
, string kword
, string value
, vtype t
= V_STR
)
127 : keyword(category
, kword
, value
, t
) { }
130 void usage(char *argv0
) {
131 clog
<< "usage: " << argv0
<< "[-a|-m]\n or: "
132 << argv0
<< " [-cCk] name..." << endl
;
135 void list_all_valid_locales() {
136 string
locale_dir("/usr/share/locale");
137 bool found_C
= false, found_POSIX
= false;
138 DIR *d
= opendir(locale_dir
.c_str());
140 static string expected
[] = { "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES",
141 "LC_NUMERIC", "LC_TIME" };
143 for(de
= readdir(d
); de
; de
= readdir(d
)) {
144 string
lname(de
->d_name
, de
->d_namlen
);
145 string
ldir(locale_dir
+ "/" + lname
);
147 DIR *ld
= opendir(ldir
.c_str());
150 for(lde
= readdir(ld
); lde
; lde
= readdir(ld
)) {
151 string
fname(lde
->d_name
, lde
->d_namlen
);
152 if (LAST(expected
) != find(expected
, LAST(expected
), fname
)) {
158 if (cnt
== LAST(expected
) - expected
) {
159 cout
<< lname
<< endl
;
163 if (lname
== "POSIX") {
174 cout
<< "POSIX" << endl
;
178 void show_all_unique_codesets() {
179 string
locale_dir("/usr/share/locale");
180 DIR *d
= opendir(locale_dir
.c_str());
182 static string expected
[] = { "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES",
183 "LC_NUMERIC", "LC_TIME" };
184 set
<string
> codesets
;
185 for(de
= readdir(d
); de
; de
= readdir(d
)) {
186 string
lname(de
->d_name
, de
->d_namlen
);
187 string
ldir(locale_dir
+ "/" + lname
);
189 DIR *ld
= opendir(ldir
.c_str());
192 for(lde
= readdir(ld
); lde
; lde
= readdir(ld
)) {
193 string
fname(lde
->d_name
, lde
->d_namlen
);
194 if (LAST(expected
) != find(expected
, LAST(expected
), fname
)) {
200 if (cnt
== LAST(expected
) - expected
) {
201 locale_t xloc
= newlocale(LC_ALL_MASK
, lname
.c_str(), NULL
);
203 char *cs
= nl_langinfo_l(CODESET
, xloc
);
204 if (cs
&& *cs
&& (codesets
.find(cs
) == codesets
.end())) {
216 typedef map
<string
, keyword
*> keywords_t
;
219 typedef map
<string
, vector
<keyword
*> > catorgies_t
;
220 catorgies_t catoriges
;
222 void add_kw(keyword
*k
) {
223 keywords
.insert(make_pair(k
->get_keyword(), k
));
224 catorgies_t::iterator c
= catoriges
.find(k
->get_category());
225 if (c
!= catoriges
.end()) {
226 c
->second
.push_back(k
);
230 catoriges
.insert(make_pair(k
->get_category(), v
));
234 string
grouping(char *g
) {
239 ss
<< static_cast<int>(*g
);
241 ss
<< ";" << static_cast<int>(*g
);
247 void init_keywords() {
248 struct lconv
*lc
= localeconv();
250 add_kw(new lc_keyword(LC_NUMERIC
, "decimal_point", lc
->decimal_point
));
251 add_kw(new lc_keyword(LC_NUMERIC
, "thousands_sep", lc
->thousands_sep
));
252 add_kw(new lc_keyword(LC_NUMERIC
, "grouping", grouping(lc
->grouping
)));
253 add_kw(new lc_keyword(LC_MONETARY
, "int_curr_symbol", lc
->int_curr_symbol
));
254 add_kw(new lc_keyword(LC_MONETARY
, "currency_symbol", lc
->currency_symbol
));
255 add_kw(new lc_keyword(LC_MONETARY
, "mon_decimal_point", lc
->mon_decimal_point
));
256 add_kw(new lc_keyword(LC_MONETARY
, "mon_thousands_sep", lc
->mon_thousands_sep
));
257 add_kw(new lc_keyword(LC_MONETARY
, "mon_grouping", grouping(lc
->mon_grouping
)));
258 add_kw(new lc_keyword(LC_MONETARY
, "positive_sign", lc
->positive_sign
));
259 add_kw(new lc_keyword(LC_MONETARY
, "negative_sign", lc
->negative_sign
));
260 add_kw(new lc_keyword(LC_MONETARY
, "int_frac_digits", tostr((int)lc
->int_frac_digits
), V_NUM
));
261 add_kw(new lc_keyword(LC_MONETARY
, "frac_digits", tostr((int)lc
->frac_digits
), V_NUM
));
262 add_kw(new lc_keyword(LC_MONETARY
, "p_cs_precedes", tostr((int)lc
->p_cs_precedes
), V_NUM
));
263 add_kw(new lc_keyword(LC_MONETARY
, "p_sep_by_space", tostr((int)lc
->p_sep_by_space
), V_NUM
));
264 add_kw(new lc_keyword(LC_MONETARY
, "n_cs_precedes", tostr((int)lc
->n_cs_precedes
), V_NUM
));
265 add_kw(new lc_keyword(LC_MONETARY
, "n_sep_by_space", tostr((int)lc
->n_sep_by_space
), V_NUM
));
266 add_kw(new lc_keyword(LC_MONETARY
, "p_sign_posn", tostr((int)lc
->p_sign_posn
), V_NUM
));
267 add_kw(new lc_keyword(LC_MONETARY
, "n_sign_posn", tostr((int)lc
->n_sign_posn
), V_NUM
));
268 add_kw(new lc_keyword(LC_MONETARY
, "int_p_cs_precedes", tostr((int)lc
->int_p_cs_precedes
), V_NUM
));
269 add_kw(new lc_keyword(LC_MONETARY
, "int_n_cs_precedes", tostr((int)lc
->int_n_cs_precedes
), V_NUM
));
270 add_kw(new lc_keyword(LC_MONETARY
, "int_p_sep_by_space", tostr((int)lc
->int_p_sep_by_space
), V_NUM
));
271 add_kw(new lc_keyword(LC_MONETARY
, "int_n_sep_by_space", tostr((int)lc
->int_n_sep_by_space
), V_NUM
));
272 add_kw(new lc_keyword(LC_MONETARY
, "int_p_sign_posn", tostr((int)lc
->int_p_sign_posn
), V_NUM
));
273 add_kw(new lc_keyword(LC_MONETARY
, "int_n_sign_posn", tostr((int)lc
->int_n_sign_posn
), V_NUM
));
276 int abdays
[] = {ABDAY_1
, ABDAY_2
, ABDAY_3
, ABDAY_4
, ABDAY_5
, ABDAY_6
, ABDAY_7
};
277 add_kw(new lia_keyword(LC_TIME
, "ab_day", abdays
, LAST(abdays
)));
278 add_kw(new lia_keyword(LC_TIME
, "abday", abdays
, LAST(abdays
)));
280 int days
[] = {DAY_1
, DAY_2
, DAY_3
, DAY_4
, DAY_5
, DAY_6
, DAY_7
};
281 add_kw(new lia_keyword(LC_TIME
, "day", days
, LAST(days
)));
283 int abmons
[] = {ABMON_1
, ABMON_2
, ABMON_3
, ABMON_4
, ABMON_5
, ABMON_6
, ABMON_7
, ABMON_8
, ABMON_9
, ABMON_10
, ABMON_11
, ABMON_12
};
284 add_kw(new lia_keyword(LC_TIME
, "abmon", abmons
, LAST(abmons
)));
286 int mons
[] = {MON_1
, MON_2
, MON_3
, MON_4
, MON_5
, MON_6
, MON_7
, MON_8
, MON_9
, MON_10
, MON_11
, MON_12
};
287 add_kw(new lia_keyword(LC_TIME
, "mon", mons
, LAST(mons
)));
289 int am_pms
[] = {AM_STR
, PM_STR
};
290 add_kw(new lia_keyword(LC_TIME
, "am_pm", am_pms
, LAST(am_pms
)));
292 add_kw(new li_keyword(LC_TIME
, "t_fmt_ampm", T_FMT_AMPM
));
293 add_kw(new li_keyword(LC_TIME
, "era", ERA
));
294 add_kw(new li_keyword(LC_TIME
, "era_d_fmt", ERA_D_FMT
));
295 add_kw(new li_keyword(LC_TIME
, "era_t_fmt", ERA_T_FMT
));
296 add_kw(new li_keyword(LC_TIME
, "era_d_t_fmt", ERA_D_T_FMT
));
297 add_kw(new li_keyword(LC_TIME
, "alt_digits", ALT_DIGITS
));
299 add_kw(new li_keyword(LC_TIME
, "d_t_fmt", D_T_FMT
));
300 add_kw(new li_keyword(LC_TIME
, "d_fmt", D_FMT
));
301 add_kw(new li_keyword(LC_TIME
, "t_fmt", T_FMT
));
303 add_kw(new li_keyword(LC_MESSAGES
, "yesexpr", YESEXPR
));
304 add_kw(new li_keyword(LC_MESSAGES
, "noexpr", NOEXPR
));
305 add_kw(new li_keyword(LC_MESSAGES
, "yesstr", YESSTR
));
306 add_kw(new li_keyword(LC_MESSAGES
, "nostr", NOSTR
));
308 add_kw(new li_keyword(LC_CTYPE
, "charmap", CODESET
));
309 add_kw(new lc_keyword(LC_SPECIAL
, "categories", "LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME"));
311 // add_kw: CRNCYSTR D_MD_ORDER CODESET RADIXCHAR THOUSEP
314 void show_keyword(string
&last_cat
, bool sw_categories
, bool sw_keywords
,
316 if (sw_categories
&& last_cat
!= k
->get_category()) {
317 last_cat
= k
->get_category();
318 cout
<< last_cat
<< endl
;
321 cout
<< k
->get_keyword() << "=";
323 cout
<< k
->get_value(sw_keywords
) << endl
;
326 int main(int argc
, char *argv
[]) {
328 bool sw_all_locales
= false, sw_categories
= false, sw_keywords
= false,
331 while(-1 != (sw
= getopt(argc
, argv
, "ackm"))) {
334 sw_all_locales
= true;
337 sw_categories
= true;
351 if ((sw_all_locales
&& sw_charmaps
)
352 || ((sw_all_locales
|| sw_charmaps
) && (sw_keywords
|| sw_categories
))
358 setlocale(LC_ALL
, "");
360 if (!(sw_all_locales
|| sw_categories
|| sw_keywords
|| sw_charmaps
)
362 char *lang
= getenv("LANG");
363 cout
<< "LANG=" << quote(lang
? lang
: "") << endl
;
364 cout
<< "LC_COLLATE=" << quote(setlocale(LC_COLLATE
, NULL
)) << endl
;
365 cout
<< "LC_CTYPE=" << quote(setlocale(LC_CTYPE
, NULL
)) << endl
;
366 cout
<< "LC_MESSAGES=" << quote(setlocale(LC_MESSAGES
, NULL
)) << endl
;
367 cout
<< "LC_MONETARY=" << quote(setlocale(LC_MONETARY
, NULL
)) << endl
;
368 cout
<< "LC_NUMERIC=" << quote(setlocale(LC_NUMERIC
, NULL
)) << endl
;
369 cout
<< "LC_TIME=" << quote(setlocale(LC_TIME
, NULL
)) << endl
;
370 if (getenv("LC_ALL")) {
371 cout
<< "LC_ALL=" << quote(setlocale(LC_ALL
, NULL
)) << endl
;
373 cout
<< "LC_ALL=" << endl
;
379 if (sw_all_locales
) {
380 list_all_valid_locales();
385 show_all_unique_codesets();
392 for(int i
= optind
; i
< argc
; ++i
) {
393 keywords_t::iterator ki
= keywords
.find(argv
[i
]);
394 if (ki
!= keywords
.end()) {
395 show_keyword(last_cat
, sw_categories
, sw_keywords
, ki
->second
);
397 catorgies_t::iterator ci
= catoriges
.find(argv
[i
]);
398 if (ci
!= catoriges
.end()) {
399 vector
<keyword
*>::iterator
vi(ci
->second
.begin()),
400 ve(ci
->second
.end());
401 for(; vi
!= ve
; ++vi
) {
402 show_keyword(last_cat
, sw_categories
, sw_keywords
, *vi
);
404 } else if (argv
[i
] == string("LC_ALL")) {
405 ki
= keywords
.begin();
406 keywords_t::iterator ke
= keywords
.end();
407 for(; ki
!= ke
; ++ki
) {
408 show_keyword(last_cat
, sw_categories
, sw_keywords
, ki
->second
);
411 if (argv
[i
] == string("LC_CTYPE")
412 || argv
[i
] == string("LC_COLLATE")) {
413 // It would be nice to print a warning,
414 // but we aren't allowed (locale.ex test#14)
416 cout
<< argv
[i
] << endl
;
419 clog
<< "unknown keyword "