use bufio; use errors; use io; use os; use strings; def locale_conf_path = "/etc/locale.conf"; // Returns the locale to use for character classification and case conversion. // The memory is statically allocated and must not be free'd. It may be // overwritten later, so use [[dup]] to extend its lifetime. export fn get_ctype() locale = get_locale("LC_CTYPE"); // Returns the locale to use for collation order. // The memory is statically allocated and must not be free'd. It may be // overwritten later, so use [[dup]] to extend its lifetime. export fn get_collate() locale = get_locale("LC_COLLATE"); // Returns the locale to use for monetary formatting. // The memory is statically allocated and must not be free'd. It may be // overwritten later, so use [[dup]] to extend its lifetime. export fn get_monetary() locale = get_locale("LC_MONETARY"); // Returns the locale to use for numeric, non-monetary formatting. // The memory is statically allocated and must not be free'd. It may be // overwritten later, so use [[dup]] to extend its lifetime. export fn get_numeric() locale = get_locale("LC_NUMERIC"); // Returns the locale to use for date and time formats. // The memory is statically allocated and must not be free'd. It may be // overwritten later, so use [[dup]] to extend its lifetime. export fn get_time() locale = get_locale("LC_TIME"); // Returns the locale to use for formats of informative and diagnostic messages // and interactive responses. // The memory is statically allocated and must not be free'd. It may be // overwritten later, so use [[dup]] to extend its lifetime. export fn get_messages() locale = get_locale("LC_MESSAGES"); fn get_locale(var: str) locale = match (get_locale_no_fallback(var)) { case let local: locale => yield local; case => yield match (get_locale_no_fallback("LC_LANG")) { case let local: locale => yield local; case => yield c; }; }; fn get_locale_no_fallback(var: str) (locale | errors::invalid) = match (get_env_locale(var)) { case let local: locale => yield local; case => yield (get_locale_conf_entry(var)); }; fn get_env_locale(var: str) (locale | errors::invalid) = match (os::getenv(var)) { case let env: str => return parse(env); case => return errors::invalid; }; let locale_conf: []str = []; @fini fn locale_conf() void = strings::freeall(locale_conf); fn get_locale_conf_entry(var: str) (locale | errors::invalid) = { get_locale_conf(); for (let entry .. locale_conf) { let (key, value) = strings::cut(entry, "="); if (key == var) return parse(value); }; return errors::invalid; }; fn get_locale_conf() []str = { if (len(locale_conf) != 0) return locale_conf; let file = match (os::open(locale_conf_path)) { case let file: io::file => yield file; case => return locale_conf; }; defer io::close(file)!; // when the hell does closing a file fail???? let scanner = bufio::newscanner(file); defer bufio::finish(&scanner); for (true) { match (bufio::scan_line(&scanner)) { case let line: const str => append(locale_conf, line); case => return locale_conf; }; }; };