Ruby 4.1.0dev (2026-09-26 revision 57213d44ce7b1a31fc9648e9cd5eb0c4507f4a49)
localeinit.c (57213d44ce7b1a31fc9648e9cd5eb0c4507f4a49)
1/**********************************************************************
2
3 localeinit.c -
4
5 $Author$
6 created at: Thu Jul 11 22:09:57 JST 2013
7
8 Copyright (C) 2013 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "ruby/encoding.h"
13#include "internal.h"
14#include "encindex.h"
15#ifdef __CYGWIN__
16#include <windows.h>
17#endif
18#ifdef HAVE_LANGINFO_H
19#include <langinfo.h>
20#endif
21
22#if defined _WIN32 || defined __CYGWIN__
23#define SIZEOF_CP_NAME ((sizeof(UINT) * 8 / 3) + 4)
24#define CP_FORMAT(buf, codepage) snprintf(buf, sizeof(buf), "CP%u", (codepage))
25
26extern UINT ruby_w32_codepage[2];
27#endif
28
29#ifndef NO_LOCALE_CHARMAP
30# if defined _WIN32 || defined __CYGWIN__ || defined HAVE_LANGINFO_H
31# define NO_LOCALE_CHARMAP 0
32# else
33# define NO_LOCALE_CHARMAP 1
34# endif
35#endif
36
37#if !NO_LOCALE_CHARMAP
38static VALUE
39locale_charmap(VALUE (*conv)(const char *))
40{
41 const char *codeset = 0;
42#if defined _WIN32 || defined __CYGWIN__
43 char cp[SIZEOF_CP_NAME];
44# ifdef __CYGWIN__
45 const char *nl_langinfo_codeset(void);
46 codeset = nl_langinfo_codeset();
47# endif
48 if (!codeset) {
49 UINT codepage = ruby_w32_codepage[0];
50 if (!codepage) codepage = GetConsoleCP();
51 if (!codepage) codepage = GetACP();
52 CP_FORMAT(cp, codepage);
53 codeset = cp;
54 }
55#elif defined HAVE_LANGINFO_H
56 codeset = nl_langinfo(CODESET);
57 ASSUME(codeset);
58#else
59# error locale_charmap() is not implemented
60#endif
61 return (*conv)(codeset);
62}
63#endif
64
65/*
66 * call-seq:
67 * Encoding.locale_charmap -> string
68 *
69 * Returns the locale charmap name.
70 *
71 * Debian GNU/Linux
72 * LANG=C
73 * Encoding.locale_charmap #=> "ANSI_X3.4-1968"
74 * LANG=ja_JP.EUC-JP
75 * Encoding.locale_charmap #=> "EUC-JP"
76 *
77 * SunOS 5
78 * LANG=C
79 * Encoding.locale_charmap #=> "646"
80 * LANG=ja
81 * Encoding.locale_charmap #=> "eucJP"
82 *
83 * The result is highly platform dependent.
84 * So Encoding.find(Encoding.locale_charmap) may cause an error.
85 * If you need some encoding object even for unknown locale,
86 * Encoding.find("locale") can be used.
87 *
88 */
91{
92#if NO_LOCALE_CHARMAP
93 return rb_usascii_str_new_cstr("US-ASCII");
94#else
95 return locale_charmap(rb_usascii_str_new_cstr);
96#endif
97}
98
99#if !NO_LOCALE_CHARMAP
100static VALUE
101enc_find_index(const char *name)
102{
103 return (VALUE)rb_enc_find_index(name);
104}
105#endif
106
107int
108rb_locale_charmap_index(void)
109{
110#if NO_LOCALE_CHARMAP
111 return ENCINDEX_US_ASCII;
112#else
113 return (int)locale_charmap(enc_find_index);
114#endif
115}
116
117int
118Init_enc_set_filesystem_encoding(void)
119{
120 int idx;
121#if NO_LOCALE_CHARMAP
122 idx = ENCINDEX_US_ASCII;
123#elif defined _WIN32
124 char cp[SIZEOF_CP_NAME];
125 const UINT codepage = ruby_w32_codepage[1];
126 if (!codepage) return ENCINDEX_UTF_8;
127 /* for debugging */
128 CP_FORMAT(cp, codepage);
129 idx = rb_enc_find_index(cp);
130 if (idx < 0) idx = ENCINDEX_ASCII_8BIT;
131#elif defined __CYGWIN__
132 idx = ENCINDEX_UTF_8;
133#else
134 idx = rb_enc_to_index(rb_default_external_encoding());
135#endif
136 return idx;
137}
#define ASSUME
Old name of RBIMPL_ASSUME.
Definition assume.h:27
Encoding relates APIs.
VALUE rb_locale_charmap(VALUE klass)
Returns a platform-depended "charmap" of the current locale.
Definition localeinit.c:90
#define rb_usascii_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "US ASCII" encoding.
Definition string.h:1568
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40