Add way to query the system locales
This commit is contained in:
		
							parent
							
								
									27b7252580
								
							
						
					
					
						commit
						409aab92ff
					
				
							
								
								
									
										96
									
								
								locale/+linux.ha
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								locale/+linux.ha
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | ||||
| 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 [[locale_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 [[locale_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 [[locale_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 [[locale_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 [[locale_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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_messages() locale = get_locale("LC_MESSAGES"); | ||||
| 
 | ||||
| // Returns the locale to use for linguistic translations. | ||||
| // The memory is statically allocated and must not be free'd. It may be | ||||
| // overwritten later, so use [[locale_dup]] to extend its lifetime. | ||||
| export fn get_lang() locale = get_locale("LC_LANG"); | ||||
| 
 | ||||
| // TODO | ||||
| fn get_language() []locale; | ||||
| 
 | ||||
| fn get_locale(var: str) locale = | ||||
| 	match (get_env_locale(var)) { | ||||
| 	case let local: locale => yield local; | ||||
| 	case => | ||||
| 		yield match (get_locale_conf_entry(var)) { | ||||
| 		case let local: locale => yield local; | ||||
| 		case => | ||||
| 			yield c; | ||||
| 		}; | ||||
| 	}; | ||||
| 
 | ||||
| fn get_env_locale(var: str) (locale | errors::invalid) = | ||||
| 	match (os::getenv(var)) { | ||||
| 	case let env: str => return parse_locale(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_locale(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; | ||||
| 		}; | ||||
| 	}; | ||||
| }; | ||||
							
								
								
									
										40
									
								
								locale/-linux.ha
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								locale/-linux.ha
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| use errors; | ||||
| 
 | ||||
| // 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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_ctype() locale = c; | ||||
| 
 | ||||
| // 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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_collate() locale = c; | ||||
| 
 | ||||
| // 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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_monetary() locale = c; | ||||
| 
 | ||||
| // 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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_numeric() locale = c; | ||||
| 
 | ||||
| // 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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_time() locale = c; | ||||
| 
 | ||||
| // 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 [[locale_dup]] to extend its lifetime. | ||||
| export fn get_messages() locale = c; | ||||
| 
 | ||||
| // Returns the locale to use for linguistic translations. | ||||
| // The memory is statically allocated and must not be free'd. It may be | ||||
| // overwritten later, so use [[locale_dup]] to extend its lifetime. | ||||
| export fn get_lang() locale = c; | ||||
| 
 | ||||
| // TODO | ||||
| export fn get_language() []locale; | ||||
| @ -10,13 +10,20 @@ export type locale = struct { | ||||
| 	modifier: str, | ||||
| }; | ||||
| 
 | ||||
| // The default locale. Stands for computer, the C language, etc. | ||||
| export def c = locale { | ||||
| 	lang = "C", | ||||
| 	... | ||||
| }; | ||||
| 
 | ||||
| // Parses a [[locale]] name of the form: | ||||
| //  | ||||
| //   lang_COUNTRY.ENCODING@MODIFIER | ||||
| //  | ||||
| // Where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. The function | ||||
| // returns a [[locale]], or [[errors::invalid]] if the input cannot be parsed. | ||||
| // All memory is borrowed from the input. | ||||
| // All memory is borrowed from the input, so [[locale_finish]] should not be | ||||
| // used to free it. | ||||
| export fn parse_locale(in: str) (locale | errors::invalid) = { | ||||
| 	let (in, modifier) = strings::rcut(in, "@"); | ||||
| 	if (strings::compare(in, "") == 0) return void: errors::invalid; | ||||
| @ -55,7 +62,23 @@ export fn format_locale(local: locale) str = { | ||||
| 
 | ||||
| // Checks if two [[locale]]s are equal. | ||||
| export fn locale_equal(a: locale, b: locale) bool = | ||||
| 	strings::compare(a.lang,     b.lang    ) == 0 && | ||||
| 	strings::compare(a.country,  b.country ) == 0 && | ||||
| 	strings::compare(a.encoding, b.encoding) == 0 && | ||||
| 	strings::compare(a.modifier, b.modifier) == 0; | ||||
| 	a.lang     == b.lang     && | ||||
| 	a.country  == b.country  && | ||||
| 	a.encoding == b.encoding && | ||||
| 	a.modifier == b.modifier; | ||||
| 
 | ||||
| // Duplicates a [[locale]] structure. Use [[locale_finish]] to get rid of it. | ||||
| export fn locale_dup(local: locale) locale = locale { | ||||
| 	lang     = strings::dup(local.lang), | ||||
| 	country  = strings::dup(local.country), | ||||
| 	encoding = strings::dup(local.encoding), | ||||
| 	modifier = strings::dup(local.modifier), | ||||
| }; | ||||
| 
 | ||||
| // Frees memory associated with a [[locale]] structure. | ||||
| export fn locale_finish(local: locale) void = { | ||||
| 	free(local.lang); | ||||
| 	free(local.country); | ||||
| 	free(local.encoding); | ||||
| 	free(local.modifier); | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user