localcharset.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277
  1. /* Determine a canonical name for the current locale's character encoding.
  2. Copyright (C) 2000-2006, 2008-2022 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. /* Written by Bruno Haible <bruno@clisp.org>. */
  14. #include <config.h>
  15. /* Specification. */
  16. #include "localcharset.h"
  17. #include <stddef.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET
  22. # define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */
  23. #endif
  24. #if defined _WIN32 && !defined __CYGWIN__
  25. # define WINDOWS_NATIVE
  26. # include <locale.h>
  27. #endif
  28. #if defined __EMX__
  29. /* Assume EMX program runs on OS/2, even if compiled under DOS. */
  30. # ifndef OS2
  31. # define OS2
  32. # endif
  33. #endif
  34. #if !defined WINDOWS_NATIVE
  35. # if HAVE_LANGINFO_CODESET
  36. # include <langinfo.h>
  37. # else
  38. # if 0 /* see comment regarding use of setlocale(), below */
  39. # include <locale.h>
  40. # endif
  41. # endif
  42. # ifdef __CYGWIN__
  43. # define WIN32_LEAN_AND_MEAN
  44. # include <windows.h>
  45. # endif
  46. #elif defined WINDOWS_NATIVE
  47. # define WIN32_LEAN_AND_MEAN
  48. # include <windows.h>
  49. /* For the use of setlocale() below, the Gnulib override in setlocale.c is
  50. not needed; see the platform lists in setlocale_null.m4. */
  51. # undef setlocale
  52. #endif
  53. #if defined OS2
  54. # define INCL_DOS
  55. # include <os2.h>
  56. #endif
  57. /* For MB_CUR_MAX_L */
  58. #if defined DARWIN7
  59. # include <xlocale.h>
  60. #endif
  61. #if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
  62. /* On these platforms, we use a mapping from non-canonical encoding name
  63. to GNU canonical encoding name. */
  64. /* With glibc-2.1 or newer, we don't need any canonicalization,
  65. because glibc has iconv and both glibc and libiconv support all
  66. GNU canonical names directly. */
  67. # if !((defined __GNU_LIBRARY__ && __GLIBC__ >= 2) || defined __UCLIBC__)
  68. struct table_entry
  69. {
  70. const char alias[11+1];
  71. const char canonical[11+1];
  72. };
  73. /* Table of platform-dependent mappings, sorted in ascending order. */
  74. static const struct table_entry alias_table[] =
  75. {
  76. # if defined __FreeBSD__ /* FreeBSD */
  77. /*{ "ARMSCII-8", "ARMSCII-8" },*/
  78. { "Big5", "BIG5" },
  79. { "C", "ASCII" },
  80. /*{ "CP1131", "CP1131" },*/
  81. /*{ "CP1251", "CP1251" },*/
  82. /*{ "CP866", "CP866" },*/
  83. /*{ "GB18030", "GB18030" },*/
  84. /*{ "GB2312", "GB2312" },*/
  85. /*{ "GBK", "GBK" },*/
  86. /*{ "ISCII-DEV", "?" },*/
  87. { "ISO8859-1", "ISO-8859-1" },
  88. { "ISO8859-13", "ISO-8859-13" },
  89. { "ISO8859-15", "ISO-8859-15" },
  90. { "ISO8859-2", "ISO-8859-2" },
  91. { "ISO8859-5", "ISO-8859-5" },
  92. { "ISO8859-7", "ISO-8859-7" },
  93. { "ISO8859-9", "ISO-8859-9" },
  94. /*{ "KOI8-R", "KOI8-R" },*/
  95. /*{ "KOI8-U", "KOI8-U" },*/
  96. { "SJIS", "SHIFT_JIS" },
  97. { "US-ASCII", "ASCII" },
  98. { "eucCN", "GB2312" },
  99. { "eucJP", "EUC-JP" },
  100. { "eucKR", "EUC-KR" }
  101. # define alias_table_defined
  102. # endif
  103. # if defined __NetBSD__ /* NetBSD */
  104. { "646", "ASCII" },
  105. /*{ "ARMSCII-8", "ARMSCII-8" },*/
  106. /*{ "BIG5", "BIG5" },*/
  107. { "Big5-HKSCS", "BIG5-HKSCS" },
  108. /*{ "CP1251", "CP1251" },*/
  109. /*{ "CP866", "CP866" },*/
  110. /*{ "GB18030", "GB18030" },*/
  111. /*{ "GB2312", "GB2312" },*/
  112. { "ISO8859-1", "ISO-8859-1" },
  113. { "ISO8859-13", "ISO-8859-13" },
  114. { "ISO8859-15", "ISO-8859-15" },
  115. { "ISO8859-2", "ISO-8859-2" },
  116. { "ISO8859-4", "ISO-8859-4" },
  117. { "ISO8859-5", "ISO-8859-5" },
  118. { "ISO8859-7", "ISO-8859-7" },
  119. /*{ "KOI8-R", "KOI8-R" },*/
  120. /*{ "KOI8-U", "KOI8-U" },*/
  121. /*{ "PT154", "PT154" },*/
  122. { "SJIS", "SHIFT_JIS" },
  123. { "eucCN", "GB2312" },
  124. { "eucJP", "EUC-JP" },
  125. { "eucKR", "EUC-KR" },
  126. { "eucTW", "EUC-TW" }
  127. # define alias_table_defined
  128. # endif
  129. # if defined __OpenBSD__ /* OpenBSD */
  130. { "646", "ASCII" },
  131. { "ISO8859-1", "ISO-8859-1" },
  132. { "ISO8859-13", "ISO-8859-13" },
  133. { "ISO8859-15", "ISO-8859-15" },
  134. { "ISO8859-2", "ISO-8859-2" },
  135. { "ISO8859-4", "ISO-8859-4" },
  136. { "ISO8859-5", "ISO-8859-5" },
  137. { "ISO8859-7", "ISO-8859-7" },
  138. { "US-ASCII", "ASCII" }
  139. # define alias_table_defined
  140. # endif
  141. # if defined __APPLE__ && defined __MACH__ /* Mac OS X */
  142. /* Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
  143. useless:
  144. - It returns the empty string when LANG is set to a locale of the
  145. form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
  146. LC_CTYPE file.
  147. - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
  148. the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
  149. - The documentation says:
  150. "... all code that calls BSD system routines should ensure
  151. that the const *char parameters of these routines are in UTF-8
  152. encoding. All BSD system functions expect their string
  153. parameters to be in UTF-8 encoding and nothing else."
  154. It also says
  155. "An additional caveat is that string parameters for files,
  156. paths, and other file-system entities must be in canonical
  157. UTF-8. In a canonical UTF-8 Unicode string, all decomposable
  158. characters are decomposed ..."
  159. but this is not true: You can pass non-decomposed UTF-8 strings
  160. to file system functions, and it is the OS which will convert
  161. them to decomposed UTF-8 before accessing the file system.
  162. - The Apple Terminal application displays UTF-8 by default.
  163. - However, other applications are free to use different encodings:
  164. - xterm uses ISO-8859-1 by default.
  165. - TextEdit uses MacRoman by default.
  166. We prefer UTF-8 over decomposed UTF-8-MAC because one should
  167. minimize the use of decomposed Unicode. Unfortunately, through the
  168. Darwin file system, decomposed UTF-8 strings are leaked into user
  169. space nevertheless.
  170. Then there are also the locales with encodings other than US-ASCII
  171. and UTF-8. These locales can be occasionally useful to users (e.g.
  172. when grepping through ISO-8859-1 encoded text files), when all their
  173. file names are in US-ASCII.
  174. */
  175. { "ARMSCII-8", "ARMSCII-8" },
  176. { "Big5", "BIG5" },
  177. { "Big5HKSCS", "BIG5-HKSCS" },
  178. { "CP1131", "CP1131" },
  179. { "CP1251", "CP1251" },
  180. { "CP866", "CP866" },
  181. { "CP949", "CP949" },
  182. { "GB18030", "GB18030" },
  183. { "GB2312", "GB2312" },
  184. { "GBK", "GBK" },
  185. /*{ "ISCII-DEV", "?" },*/
  186. { "ISO8859-1", "ISO-8859-1" },
  187. { "ISO8859-13", "ISO-8859-13" },
  188. { "ISO8859-15", "ISO-8859-15" },
  189. { "ISO8859-2", "ISO-8859-2" },
  190. { "ISO8859-4", "ISO-8859-4" },
  191. { "ISO8859-5", "ISO-8859-5" },
  192. { "ISO8859-7", "ISO-8859-7" },
  193. { "ISO8859-9", "ISO-8859-9" },
  194. { "KOI8-R", "KOI8-R" },
  195. { "KOI8-U", "KOI8-U" },
  196. { "PT154", "PT154" },
  197. { "SJIS", "SHIFT_JIS" },
  198. { "eucCN", "GB2312" },
  199. { "eucJP", "EUC-JP" },
  200. { "eucKR", "EUC-KR" }
  201. # define alias_table_defined
  202. # endif
  203. # if defined _AIX /* AIX */
  204. /*{ "GBK", "GBK" },*/
  205. { "IBM-1046", "CP1046" },
  206. { "IBM-1124", "CP1124" },
  207. { "IBM-1129", "CP1129" },
  208. { "IBM-1252", "CP1252" },
  209. { "IBM-850", "CP850" },
  210. { "IBM-856", "CP856" },
  211. { "IBM-921", "ISO-8859-13" },
  212. { "IBM-922", "CP922" },
  213. { "IBM-932", "CP932" },
  214. { "IBM-943", "CP943" },
  215. { "IBM-eucCN", "GB2312" },
  216. { "IBM-eucJP", "EUC-JP" },
  217. { "IBM-eucKR", "EUC-KR" },
  218. { "IBM-eucTW", "EUC-TW" },
  219. { "ISO8859-1", "ISO-8859-1" },
  220. { "ISO8859-15", "ISO-8859-15" },
  221. { "ISO8859-2", "ISO-8859-2" },
  222. { "ISO8859-5", "ISO-8859-5" },
  223. { "ISO8859-6", "ISO-8859-6" },
  224. { "ISO8859-7", "ISO-8859-7" },
  225. { "ISO8859-8", "ISO-8859-8" },
  226. { "ISO8859-9", "ISO-8859-9" },
  227. { "TIS-620", "TIS-620" },
  228. /*{ "UTF-8", "UTF-8" },*/
  229. { "big5", "BIG5" }
  230. # define alias_table_defined
  231. # endif
  232. # if defined __hpux /* HP-UX */
  233. { "SJIS", "SHIFT_JIS" },
  234. { "arabic8", "HP-ARABIC8" },
  235. { "big5", "BIG5" },
  236. { "cp1251", "CP1251" },
  237. { "eucJP", "EUC-JP" },
  238. { "eucKR", "EUC-KR" },
  239. { "eucTW", "EUC-TW" },
  240. { "gb18030", "GB18030" },
  241. { "greek8", "HP-GREEK8" },
  242. { "hebrew8", "HP-HEBREW8" },
  243. { "hkbig5", "BIG5-HKSCS" },
  244. { "hp15CN", "GB2312" },
  245. { "iso88591", "ISO-8859-1" },
  246. { "iso885913", "ISO-8859-13" },
  247. { "iso885915", "ISO-8859-15" },
  248. { "iso88592", "ISO-8859-2" },
  249. { "iso88594", "ISO-8859-4" },
  250. { "iso88595", "ISO-8859-5" },
  251. { "iso88596", "ISO-8859-6" },
  252. { "iso88597", "ISO-8859-7" },
  253. { "iso88598", "ISO-8859-8" },
  254. { "iso88599", "ISO-8859-9" },
  255. { "kana8", "HP-KANA8" },
  256. { "koi8r", "KOI8-R" },
  257. { "roman8", "HP-ROMAN8" },
  258. { "tis620", "TIS-620" },
  259. { "turkish8", "HP-TURKISH8" },
  260. { "utf8", "UTF-8" }
  261. # define alias_table_defined
  262. # endif
  263. # if defined __sgi /* IRIX */
  264. { "ISO8859-1", "ISO-8859-1" },
  265. { "ISO8859-15", "ISO-8859-15" },
  266. { "ISO8859-2", "ISO-8859-2" },
  267. { "ISO8859-5", "ISO-8859-5" },
  268. { "ISO8859-7", "ISO-8859-7" },
  269. { "ISO8859-9", "ISO-8859-9" },
  270. { "eucCN", "GB2312" },
  271. { "eucJP", "EUC-JP" },
  272. { "eucKR", "EUC-KR" },
  273. { "eucTW", "EUC-TW" }
  274. # define alias_table_defined
  275. # endif
  276. # if defined __osf__ /* OSF/1 */
  277. /*{ "GBK", "GBK" },*/
  278. { "ISO8859-1", "ISO-8859-1" },
  279. { "ISO8859-15", "ISO-8859-15" },
  280. { "ISO8859-2", "ISO-8859-2" },
  281. { "ISO8859-4", "ISO-8859-4" },
  282. { "ISO8859-5", "ISO-8859-5" },
  283. { "ISO8859-7", "ISO-8859-7" },
  284. { "ISO8859-8", "ISO-8859-8" },
  285. { "ISO8859-9", "ISO-8859-9" },
  286. { "KSC5601", "CP949" },
  287. { "SJIS", "SHIFT_JIS" },
  288. { "TACTIS", "TIS-620" },
  289. /*{ "UTF-8", "UTF-8" },*/
  290. { "big5", "BIG5" },
  291. { "cp850", "CP850" },
  292. { "dechanyu", "DEC-HANYU" },
  293. { "dechanzi", "GB2312" },
  294. { "deckanji", "DEC-KANJI" },
  295. { "deckorean", "EUC-KR" },
  296. { "eucJP", "EUC-JP" },
  297. { "eucKR", "EUC-KR" },
  298. { "eucTW", "EUC-TW" },
  299. { "sdeckanji", "EUC-JP" }
  300. # define alias_table_defined
  301. # endif
  302. # if defined __sun /* Solaris */
  303. { "5601", "EUC-KR" },
  304. { "646", "ASCII" },
  305. /*{ "BIG5", "BIG5" },*/
  306. { "Big5-HKSCS", "BIG5-HKSCS" },
  307. { "GB18030", "GB18030" },
  308. /*{ "GBK", "GBK" },*/
  309. { "ISO8859-1", "ISO-8859-1" },
  310. { "ISO8859-11", "TIS-620" },
  311. { "ISO8859-13", "ISO-8859-13" },
  312. { "ISO8859-15", "ISO-8859-15" },
  313. { "ISO8859-2", "ISO-8859-2" },
  314. { "ISO8859-3", "ISO-8859-3" },
  315. { "ISO8859-4", "ISO-8859-4" },
  316. { "ISO8859-5", "ISO-8859-5" },
  317. { "ISO8859-6", "ISO-8859-6" },
  318. { "ISO8859-7", "ISO-8859-7" },
  319. { "ISO8859-8", "ISO-8859-8" },
  320. { "ISO8859-9", "ISO-8859-9" },
  321. { "PCK", "SHIFT_JIS" },
  322. { "TIS620.2533", "TIS-620" },
  323. /*{ "UTF-8", "UTF-8" },*/
  324. { "ansi-1251", "CP1251" },
  325. { "cns11643", "EUC-TW" },
  326. { "eucJP", "EUC-JP" },
  327. { "gb2312", "GB2312" },
  328. { "koi8-r", "KOI8-R" }
  329. # define alias_table_defined
  330. # endif
  331. # if defined __minix /* Minix */
  332. { "646", "ASCII" }
  333. # define alias_table_defined
  334. # endif
  335. # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Windows */
  336. { "CP1361", "JOHAB" },
  337. { "CP20127", "ASCII" },
  338. { "CP20866", "KOI8-R" },
  339. { "CP20936", "GB2312" },
  340. { "CP21866", "KOI8-RU" },
  341. { "CP28591", "ISO-8859-1" },
  342. { "CP28592", "ISO-8859-2" },
  343. { "CP28593", "ISO-8859-3" },
  344. { "CP28594", "ISO-8859-4" },
  345. { "CP28595", "ISO-8859-5" },
  346. { "CP28596", "ISO-8859-6" },
  347. { "CP28597", "ISO-8859-7" },
  348. { "CP28598", "ISO-8859-8" },
  349. { "CP28599", "ISO-8859-9" },
  350. { "CP28605", "ISO-8859-15" },
  351. { "CP38598", "ISO-8859-8" },
  352. { "CP51932", "EUC-JP" },
  353. { "CP51936", "GB2312" },
  354. { "CP51949", "EUC-KR" },
  355. { "CP51950", "EUC-TW" },
  356. { "CP54936", "GB18030" },
  357. { "CP65001", "UTF-8" },
  358. { "CP936", "GBK" }
  359. # define alias_table_defined
  360. # endif
  361. # if defined OS2 /* OS/2 */
  362. /* The list of encodings is taken from "List of OS/2 Codepages"
  363. by Alex Taylor:
  364. <http://altsan.org/os2/toolkits/uls/index.html#codepages>.
  365. See also "__convcp() of kLIBC":
  366. <https://github.com/bitwiseworks/libc/blob/master/src/emx/src/lib/locale/__convcp.c>. */
  367. { "CP1004", "CP1252" },
  368. /*{ "CP1041", "CP943" },*/
  369. /*{ "CP1088", "CP949" },*/
  370. { "CP1089", "ISO-8859-6" },
  371. /*{ "CP1114", "CP950" },*/
  372. /*{ "CP1115", "GB2312" },*/
  373. { "CP1208", "UTF-8" },
  374. /*{ "CP1380", "GB2312" },*/
  375. { "CP1381", "GB2312" },
  376. { "CP1383", "GB2312" },
  377. { "CP1386", "GBK" },
  378. /*{ "CP301", "CP943" },*/
  379. { "CP3372", "EUC-JP" },
  380. { "CP4946", "CP850" },
  381. /*{ "CP5048", "JIS_X0208-1990" },*/
  382. /*{ "CP5049", "JIS_X0212-1990" },*/
  383. /*{ "CP5067", "KS_C_5601-1987" },*/
  384. { "CP813", "ISO-8859-7" },
  385. { "CP819", "ISO-8859-1" },
  386. { "CP878", "KOI8-R" },
  387. /*{ "CP897", "CP943" },*/
  388. { "CP912", "ISO-8859-2" },
  389. { "CP913", "ISO-8859-3" },
  390. { "CP914", "ISO-8859-4" },
  391. { "CP915", "ISO-8859-5" },
  392. { "CP916", "ISO-8859-8" },
  393. { "CP920", "ISO-8859-9" },
  394. { "CP921", "ISO-8859-13" },
  395. { "CP923", "ISO-8859-15" },
  396. /*{ "CP941", "CP943" },*/
  397. /*{ "CP947", "CP950" },*/
  398. /*{ "CP951", "CP949" },*/
  399. /*{ "CP952", "JIS_X0208-1990" },*/
  400. /*{ "CP953", "JIS_X0212-1990" },*/
  401. { "CP954", "EUC-JP" },
  402. { "CP964", "EUC-TW" },
  403. { "CP970", "EUC-KR" },
  404. /*{ "CP971", "KS_C_5601-1987" },*/
  405. { "IBM-1004", "CP1252" },
  406. /*{ "IBM-1006", "?" },*/
  407. /*{ "IBM-1008", "?" },*/
  408. /*{ "IBM-1041", "CP943" },*/
  409. /*{ "IBM-1051", "?" },*/
  410. /*{ "IBM-1088", "CP949" },*/
  411. { "IBM-1089", "ISO-8859-6" },
  412. /*{ "IBM-1098", "?" },*/
  413. /*{ "IBM-1114", "CP950" },*/
  414. /*{ "IBM-1115", "GB2312" },*/
  415. /*{ "IBM-1116", "?" },*/
  416. /*{ "IBM-1117", "?" },*/
  417. /*{ "IBM-1118", "?" },*/
  418. /*{ "IBM-1119", "?" },*/
  419. { "IBM-1124", "CP1124" },
  420. { "IBM-1125", "CP1125" },
  421. { "IBM-1131", "CP1131" },
  422. { "IBM-1208", "UTF-8" },
  423. { "IBM-1250", "CP1250" },
  424. { "IBM-1251", "CP1251" },
  425. { "IBM-1252", "CP1252" },
  426. { "IBM-1253", "CP1253" },
  427. { "IBM-1254", "CP1254" },
  428. { "IBM-1255", "CP1255" },
  429. { "IBM-1256", "CP1256" },
  430. { "IBM-1257", "CP1257" },
  431. /*{ "IBM-1275", "?" },*/
  432. /*{ "IBM-1276", "?" },*/
  433. /*{ "IBM-1277", "?" },*/
  434. /*{ "IBM-1280", "?" },*/
  435. /*{ "IBM-1281", "?" },*/
  436. /*{ "IBM-1282", "?" },*/
  437. /*{ "IBM-1283", "?" },*/
  438. /*{ "IBM-1380", "GB2312" },*/
  439. { "IBM-1381", "GB2312" },
  440. { "IBM-1383", "GB2312" },
  441. { "IBM-1386", "GBK" },
  442. /*{ "IBM-301", "CP943" },*/
  443. { "IBM-3372", "EUC-JP" },
  444. { "IBM-367", "ASCII" },
  445. { "IBM-437", "CP437" },
  446. { "IBM-4946", "CP850" },
  447. /*{ "IBM-5048", "JIS_X0208-1990" },*/
  448. /*{ "IBM-5049", "JIS_X0212-1990" },*/
  449. /*{ "IBM-5067", "KS_C_5601-1987" },*/
  450. { "IBM-813", "ISO-8859-7" },
  451. { "IBM-819", "ISO-8859-1" },
  452. { "IBM-850", "CP850" },
  453. /*{ "IBM-851", "?" },*/
  454. { "IBM-852", "CP852" },
  455. { "IBM-855", "CP855" },
  456. { "IBM-856", "CP856" },
  457. { "IBM-857", "CP857" },
  458. /*{ "IBM-859", "?" },*/
  459. { "IBM-860", "CP860" },
  460. { "IBM-861", "CP861" },
  461. { "IBM-862", "CP862" },
  462. { "IBM-863", "CP863" },
  463. { "IBM-864", "CP864" },
  464. { "IBM-865", "CP865" },
  465. { "IBM-866", "CP866" },
  466. /*{ "IBM-868", "?" },*/
  467. { "IBM-869", "CP869" },
  468. { "IBM-874", "CP874" },
  469. { "IBM-878", "KOI8-R" },
  470. /*{ "IBM-895", "?" },*/
  471. /*{ "IBM-897", "CP943" },*/
  472. /*{ "IBM-907", "?" },*/
  473. /*{ "IBM-909", "?" },*/
  474. { "IBM-912", "ISO-8859-2" },
  475. { "IBM-913", "ISO-8859-3" },
  476. { "IBM-914", "ISO-8859-4" },
  477. { "IBM-915", "ISO-8859-5" },
  478. { "IBM-916", "ISO-8859-8" },
  479. { "IBM-920", "ISO-8859-9" },
  480. { "IBM-921", "ISO-8859-13" },
  481. { "IBM-922", "CP922" },
  482. { "IBM-923", "ISO-8859-15" },
  483. { "IBM-932", "CP932" },
  484. /*{ "IBM-941", "CP943" },*/
  485. /*{ "IBM-942", "?" },*/
  486. { "IBM-943", "CP943" },
  487. /*{ "IBM-947", "CP950" },*/
  488. { "IBM-949", "CP949" },
  489. { "IBM-950", "CP950" },
  490. /*{ "IBM-951", "CP949" },*/
  491. /*{ "IBM-952", "JIS_X0208-1990" },*/
  492. /*{ "IBM-953", "JIS_X0212-1990" },*/
  493. { "IBM-954", "EUC-JP" },
  494. /*{ "IBM-955", "?" },*/
  495. { "IBM-964", "EUC-TW" },
  496. { "IBM-970", "EUC-KR" },
  497. /*{ "IBM-971", "KS_C_5601-1987" },*/
  498. { "IBM-eucCN", "GB2312" },
  499. { "IBM-eucJP", "EUC-JP" },
  500. { "IBM-eucKR", "EUC-KR" },
  501. { "IBM-eucTW", "EUC-TW" },
  502. { "IBM33722", "EUC-JP" },
  503. { "ISO8859-1", "ISO-8859-1" },
  504. { "ISO8859-2", "ISO-8859-2" },
  505. { "ISO8859-3", "ISO-8859-3" },
  506. { "ISO8859-4", "ISO-8859-4" },
  507. { "ISO8859-5", "ISO-8859-5" },
  508. { "ISO8859-6", "ISO-8859-6" },
  509. { "ISO8859-7", "ISO-8859-7" },
  510. { "ISO8859-8", "ISO-8859-8" },
  511. { "ISO8859-9", "ISO-8859-9" },
  512. /*{ "JISX0201-1976", "JISX0201-1976" },*/
  513. /*{ "JISX0208-1978", "?" },*/
  514. /*{ "JISX0208-1983", "JIS_X0208-1983" },*/
  515. /*{ "JISX0208-1990", "JIS_X0208-1990" },*/
  516. /*{ "JISX0212-1990", "JIS_X0212-1990" },*/
  517. /*{ "KSC5601-1987", "KS_C_5601-1987" },*/
  518. { "SJIS-1", "CP943" },
  519. { "SJIS-2", "CP943" },
  520. { "eucJP", "EUC-JP" },
  521. { "eucKR", "EUC-KR" },
  522. { "eucTW-1993", "EUC-TW" }
  523. # define alias_table_defined
  524. # endif
  525. # if defined VMS /* OpenVMS */
  526. /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
  527. "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
  528. section 10.7 "Handling Different Character Sets". */
  529. { "DECHANYU", "DEC-HANYU" },
  530. { "DECHANZI", "GB2312" },
  531. { "DECKANJI", "DEC-KANJI" },
  532. { "DECKOREAN", "EUC-KR" },
  533. { "ISO8859-1", "ISO-8859-1" },
  534. { "ISO8859-2", "ISO-8859-2" },
  535. { "ISO8859-5", "ISO-8859-5" },
  536. { "ISO8859-7", "ISO-8859-7" },
  537. { "ISO8859-8", "ISO-8859-8" },
  538. { "ISO8859-9", "ISO-8859-9" },
  539. { "SDECKANJI", "EUC-JP" },
  540. { "SJIS", "SHIFT_JIS" },
  541. { "eucJP", "EUC-JP" },
  542. { "eucTW", "EUC-TW" }
  543. # define alias_table_defined
  544. # endif
  545. # ifndef alias_table_defined
  546. /* Just a dummy entry, to avoid a C syntax error. */
  547. { "", "" }
  548. # endif
  549. };
  550. # endif
  551. #else
  552. /* On these platforms, we use a mapping from locale name to GNU canonical
  553. encoding name. */
  554. struct table_entry
  555. {
  556. const char locale[17+1];
  557. const char canonical[11+1];
  558. };
  559. /* Table of platform-dependent mappings, sorted in ascending order. */
  560. static const struct table_entry locale_table[] =
  561. {
  562. # if defined __FreeBSD__ /* FreeBSD 4.2 */
  563. { "cs_CZ.ISO_8859-2", "ISO-8859-2" },
  564. { "da_DK.DIS_8859-15", "ISO-8859-15" },
  565. { "da_DK.ISO_8859-1", "ISO-8859-1" },
  566. { "de_AT.DIS_8859-15", "ISO-8859-15" },
  567. { "de_AT.ISO_8859-1", "ISO-8859-1" },
  568. { "de_CH.DIS_8859-15", "ISO-8859-15" },
  569. { "de_CH.ISO_8859-1", "ISO-8859-1" },
  570. { "de_DE.DIS_8859-15", "ISO-8859-15" },
  571. { "de_DE.ISO_8859-1", "ISO-8859-1" },
  572. { "en_AU.DIS_8859-15", "ISO-8859-15" },
  573. { "en_AU.ISO_8859-1", "ISO-8859-1" },
  574. { "en_CA.DIS_8859-15", "ISO-8859-15" },
  575. { "en_CA.ISO_8859-1", "ISO-8859-1" },
  576. { "en_GB.DIS_8859-15", "ISO-8859-15" },
  577. { "en_GB.ISO_8859-1", "ISO-8859-1" },
  578. { "en_US.DIS_8859-15", "ISO-8859-15" },
  579. { "en_US.ISO_8859-1", "ISO-8859-1" },
  580. { "es_ES.DIS_8859-15", "ISO-8859-15" },
  581. { "es_ES.ISO_8859-1", "ISO-8859-1" },
  582. { "fi_FI.DIS_8859-15", "ISO-8859-15" },
  583. { "fi_FI.ISO_8859-1", "ISO-8859-1" },
  584. { "fr_BE.DIS_8859-15", "ISO-8859-15" },
  585. { "fr_BE.ISO_8859-1", "ISO-8859-1" },
  586. { "fr_CA.DIS_8859-15", "ISO-8859-15" },
  587. { "fr_CA.ISO_8859-1", "ISO-8859-1" },
  588. { "fr_CH.DIS_8859-15", "ISO-8859-15" },
  589. { "fr_CH.ISO_8859-1", "ISO-8859-1" },
  590. { "fr_FR.DIS_8859-15", "ISO-8859-15" },
  591. { "fr_FR.ISO_8859-1", "ISO-8859-1" },
  592. { "hr_HR.ISO_8859-2", "ISO-8859-2" },
  593. { "hu_HU.ISO_8859-2", "ISO-8859-2" },
  594. { "is_IS.DIS_8859-15", "ISO-8859-15" },
  595. { "is_IS.ISO_8859-1", "ISO-8859-1" },
  596. { "it_CH.DIS_8859-15", "ISO-8859-15" },
  597. { "it_CH.ISO_8859-1", "ISO-8859-1" },
  598. { "it_IT.DIS_8859-15", "ISO-8859-15" },
  599. { "it_IT.ISO_8859-1", "ISO-8859-1" },
  600. { "ja_JP.EUC", "EUC-JP" },
  601. { "ja_JP.SJIS", "SHIFT_JIS" },
  602. { "ja_JP.Shift_JIS", "SHIFT_JIS" },
  603. { "ko_KR.EUC", "EUC-KR" },
  604. { "la_LN.ASCII", "ASCII" },
  605. { "la_LN.DIS_8859-15", "ISO-8859-15" },
  606. { "la_LN.ISO_8859-1", "ISO-8859-1" },
  607. { "la_LN.ISO_8859-2", "ISO-8859-2" },
  608. { "la_LN.ISO_8859-4", "ISO-8859-4" },
  609. { "lt_LN.ASCII", "ASCII" },
  610. { "lt_LN.DIS_8859-15", "ISO-8859-15" },
  611. { "lt_LN.ISO_8859-1", "ISO-8859-1" },
  612. { "lt_LN.ISO_8859-2", "ISO-8859-2" },
  613. { "lt_LT.ISO_8859-4", "ISO-8859-4" },
  614. { "nl_BE.DIS_8859-15", "ISO-8859-15" },
  615. { "nl_BE.ISO_8859-1", "ISO-8859-1" },
  616. { "nl_NL.DIS_8859-15", "ISO-8859-15" },
  617. { "nl_NL.ISO_8859-1", "ISO-8859-1" },
  618. { "no_NO.DIS_8859-15", "ISO-8859-15" },
  619. { "no_NO.ISO_8859-1", "ISO-8859-1" },
  620. { "pl_PL.ISO_8859-2", "ISO-8859-2" },
  621. { "pt_PT.DIS_8859-15", "ISO-8859-15" },
  622. { "pt_PT.ISO_8859-1", "ISO-8859-1" },
  623. { "ru_RU.CP866", "CP866" },
  624. { "ru_RU.ISO_8859-5", "ISO-8859-5" },
  625. { "ru_RU.KOI8-R", "KOI8-R" },
  626. { "ru_SU.CP866", "CP866" },
  627. { "ru_SU.ISO_8859-5", "ISO-8859-5" },
  628. { "ru_SU.KOI8-R", "KOI8-R" },
  629. { "sl_SI.ISO_8859-2", "ISO-8859-2" },
  630. { "sv_SE.DIS_8859-15", "ISO-8859-15" },
  631. { "sv_SE.ISO_8859-1", "ISO-8859-1" },
  632. { "uk_UA.KOI8-U", "KOI8-U" },
  633. { "zh_CN.EUC", "GB2312" },
  634. { "zh_TW.BIG5", "BIG5" },
  635. { "zh_TW.Big5", "BIG5" }
  636. # define locale_table_defined
  637. # endif
  638. # if defined __DJGPP__ /* DOS / DJGPP 2.03 */
  639. /* The encodings given here may not all be correct.
  640. If you find that the encoding given for your language and
  641. country is not the one your DOS machine actually uses, just
  642. correct it in this file, and send a mail to
  643. Juan Manuel Guerrero <juan.guerrero@gmx.de>
  644. and <bug-gnulib@gnu.org>. */
  645. { "C", "ASCII" },
  646. { "ar", "CP864" },
  647. { "ar_AE", "CP864" },
  648. { "ar_DZ", "CP864" },
  649. { "ar_EG", "CP864" },
  650. { "ar_IQ", "CP864" },
  651. { "ar_IR", "CP864" },
  652. { "ar_JO", "CP864" },
  653. { "ar_KW", "CP864" },
  654. { "ar_MA", "CP864" },
  655. { "ar_OM", "CP864" },
  656. { "ar_QA", "CP864" },
  657. { "ar_SA", "CP864" },
  658. { "ar_SY", "CP864" },
  659. { "be", "CP866" },
  660. { "be_BE", "CP866" },
  661. { "bg", "CP866" }, /* not CP855 ?? */
  662. { "bg_BG", "CP866" }, /* not CP855 ?? */
  663. { "ca", "CP850" },
  664. { "ca_ES", "CP850" },
  665. { "cs", "CP852" },
  666. { "cs_CZ", "CP852" },
  667. { "da", "CP865" }, /* not CP850 ?? */
  668. { "da_DK", "CP865" }, /* not CP850 ?? */
  669. { "de", "CP850" },
  670. { "de_AT", "CP850" },
  671. { "de_CH", "CP850" },
  672. { "de_DE", "CP850" },
  673. { "el", "CP869" },
  674. { "el_GR", "CP869" },
  675. { "en", "CP850" },
  676. { "en_AU", "CP850" }, /* not CP437 ?? */
  677. { "en_CA", "CP850" },
  678. { "en_GB", "CP850" },
  679. { "en_NZ", "CP437" },
  680. { "en_US", "CP437" },
  681. { "en_ZA", "CP850" }, /* not CP437 ?? */
  682. { "eo", "CP850" },
  683. { "eo_EO", "CP850" },
  684. { "es", "CP850" },
  685. { "es_AR", "CP850" },
  686. { "es_BO", "CP850" },
  687. { "es_CL", "CP850" },
  688. { "es_CO", "CP850" },
  689. { "es_CR", "CP850" },
  690. { "es_CU", "CP850" },
  691. { "es_DO", "CP850" },
  692. { "es_EC", "CP850" },
  693. { "es_ES", "CP850" },
  694. { "es_GT", "CP850" },
  695. { "es_HN", "CP850" },
  696. { "es_MX", "CP850" },
  697. { "es_NI", "CP850" },
  698. { "es_PA", "CP850" },
  699. { "es_PE", "CP850" },
  700. { "es_PY", "CP850" },
  701. { "es_SV", "CP850" },
  702. { "es_UY", "CP850" },
  703. { "es_VE", "CP850" },
  704. { "et", "CP850" },
  705. { "et_EE", "CP850" },
  706. { "eu", "CP850" },
  707. { "eu_ES", "CP850" },
  708. { "fi", "CP850" },
  709. { "fi_FI", "CP850" },
  710. { "fr", "CP850" },
  711. { "fr_BE", "CP850" },
  712. { "fr_CA", "CP850" },
  713. { "fr_CH", "CP850" },
  714. { "fr_FR", "CP850" },
  715. { "ga", "CP850" },
  716. { "ga_IE", "CP850" },
  717. { "gd", "CP850" },
  718. { "gd_GB", "CP850" },
  719. { "gl", "CP850" },
  720. { "gl_ES", "CP850" },
  721. { "he", "CP862" },
  722. { "he_IL", "CP862" },
  723. { "hr", "CP852" },
  724. { "hr_HR", "CP852" },
  725. { "hu", "CP852" },
  726. { "hu_HU", "CP852" },
  727. { "id", "CP850" }, /* not CP437 ?? */
  728. { "id_ID", "CP850" }, /* not CP437 ?? */
  729. { "is", "CP861" }, /* not CP850 ?? */
  730. { "is_IS", "CP861" }, /* not CP850 ?? */
  731. { "it", "CP850" },
  732. { "it_CH", "CP850" },
  733. { "it_IT", "CP850" },
  734. { "ja", "CP932" },
  735. { "ja_JP", "CP932" },
  736. { "kr", "CP949" }, /* not CP934 ?? */
  737. { "kr_KR", "CP949" }, /* not CP934 ?? */
  738. { "lt", "CP775" },
  739. { "lt_LT", "CP775" },
  740. { "lv", "CP775" },
  741. { "lv_LV", "CP775" },
  742. { "mk", "CP866" }, /* not CP855 ?? */
  743. { "mk_MK", "CP866" }, /* not CP855 ?? */
  744. { "mt", "CP850" },
  745. { "mt_MT", "CP850" },
  746. { "nb", "CP865" }, /* not CP850 ?? */
  747. { "nb_NO", "CP865" }, /* not CP850 ?? */
  748. { "nl", "CP850" },
  749. { "nl_BE", "CP850" },
  750. { "nl_NL", "CP850" },
  751. { "nn", "CP865" }, /* not CP850 ?? */
  752. { "nn_NO", "CP865" }, /* not CP850 ?? */
  753. { "no", "CP865" }, /* not CP850 ?? */
  754. { "no_NO", "CP865" }, /* not CP850 ?? */
  755. { "pl", "CP852" },
  756. { "pl_PL", "CP852" },
  757. { "pt", "CP850" },
  758. { "pt_BR", "CP850" },
  759. { "pt_PT", "CP850" },
  760. { "ro", "CP852" },
  761. { "ro_RO", "CP852" },
  762. { "ru", "CP866" },
  763. { "ru_RU", "CP866" },
  764. { "sk", "CP852" },
  765. { "sk_SK", "CP852" },
  766. { "sl", "CP852" },
  767. { "sl_SI", "CP852" },
  768. { "sq", "CP852" },
  769. { "sq_AL", "CP852" },
  770. { "sr", "CP852" }, /* CP852 or CP866 or CP855 ?? */
  771. { "sr_CS", "CP852" }, /* CP852 or CP866 or CP855 ?? */
  772. { "sr_YU", "CP852" }, /* CP852 or CP866 or CP855 ?? */
  773. { "sv", "CP850" },
  774. { "sv_SE", "CP850" },
  775. { "th", "CP874" },
  776. { "th_TH", "CP874" },
  777. { "tr", "CP857" },
  778. { "tr_TR", "CP857" },
  779. { "uk", "CP1125" },
  780. { "uk_UA", "CP1125" },
  781. { "zh_CN", "GBK" },
  782. { "zh_TW", "CP950" } /* not CP938 ?? */
  783. # define locale_table_defined
  784. # endif
  785. # ifndef locale_table_defined
  786. /* Just a dummy entry, to avoid a C syntax error. */
  787. { "", "" }
  788. # endif
  789. };
  790. #endif
  791. /* Determine the current locale's character encoding, and canonicalize it
  792. into one of the canonical names listed below.
  793. The result must not be freed; it is statically allocated. The result
  794. becomes invalid when setlocale() is used to change the global locale, or
  795. when the value of one of the environment variables LC_ALL, LC_CTYPE, LANG
  796. is changed; threads in multithreaded programs should not do this.
  797. If the canonical name cannot be determined, the result is a non-canonical
  798. name. */
  799. #ifdef STATIC
  800. STATIC
  801. #endif
  802. const char *
  803. locale_charset (void)
  804. {
  805. const char *codeset;
  806. /* This function must be multithread-safe. To achieve this without using
  807. thread-local storage, we use a simple strcpy or memcpy to fill this static
  808. buffer. Filling it through, for example, strcpy + strcat would not be
  809. guaranteed to leave the buffer's contents intact if another thread is
  810. currently accessing it. If necessary, the contents is first assembled in
  811. a stack-allocated buffer. */
  812. #if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
  813. # if HAVE_LANGINFO_CODESET
  814. /* Most systems support nl_langinfo (CODESET) nowadays. */
  815. codeset = nl_langinfo (CODESET);
  816. # ifdef __CYGWIN__
  817. /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always
  818. returns "US-ASCII". Return the suffix of the locale name from the
  819. environment variables (if present) or the codepage as a number. */
  820. if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
  821. {
  822. const char *locale;
  823. static char resultbuf[2 + 10 + 1];
  824. locale = getenv ("LC_ALL");
  825. if (locale == NULL || locale[0] == '\0')
  826. {
  827. locale = getenv ("LC_CTYPE");
  828. if (locale == NULL || locale[0] == '\0')
  829. locale = getenv ("LANG");
  830. }
  831. if (locale != NULL && locale[0] != '\0')
  832. {
  833. /* If the locale name contains an encoding after the dot, return
  834. it. */
  835. const char *dot = strchr (locale, '.');
  836. if (dot != NULL)
  837. {
  838. const char *modifier;
  839. dot++;
  840. /* Look for the possible @... trailer and remove it, if any. */
  841. modifier = strchr (dot, '@');
  842. if (modifier == NULL)
  843. return dot;
  844. if (modifier - dot < sizeof (resultbuf))
  845. {
  846. /* This way of filling resultbuf is multithread-safe. */
  847. memcpy (resultbuf, dot, modifier - dot);
  848. resultbuf [modifier - dot] = '\0';
  849. return resultbuf;
  850. }
  851. }
  852. }
  853. /* The Windows API has a function returning the locale's codepage as a
  854. number: GetACP(). This encoding is used by Cygwin, unless the user
  855. has set the environment variable CYGWIN=codepage:oem (which very few
  856. people do).
  857. Output directed to console windows needs to be converted (to
  858. GetOEMCP() if the console is using a raster font, or to
  859. GetConsoleOutputCP() if it is using a TrueType font). Cygwin does
  860. this conversion transparently (see winsup/cygwin/fhandler_console.cc),
  861. converting to GetConsoleOutputCP(). This leads to correct results,
  862. except when SetConsoleOutputCP has been called and a raster font is
  863. in use. */
  864. {
  865. char buf[2 + 10 + 1];
  866. sprintf (buf, "CP%u", GetACP ());
  867. strcpy (resultbuf, buf);
  868. codeset = resultbuf;
  869. }
  870. }
  871. # endif
  872. if (codeset == NULL)
  873. /* The canonical name cannot be determined. */
  874. codeset = "";
  875. # elif defined WINDOWS_NATIVE
  876. char buf[2 + 10 + 1];
  877. static char resultbuf[2 + 10 + 1];
  878. /* The Windows API has a function returning the locale's codepage as
  879. a number, but the value doesn't change according to what the
  880. 'setlocale' call specified. So we use it as a last resort, in
  881. case the string returned by 'setlocale' doesn't specify the
  882. codepage. */
  883. char *current_locale = setlocale (LC_CTYPE, NULL);
  884. char *pdot = strrchr (current_locale, '.');
  885. if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf))
  886. sprintf (buf, "CP%s", pdot + 1);
  887. else
  888. {
  889. /* The Windows API has a function returning the locale's codepage as a
  890. number: GetACP().
  891. When the output goes to a console window, it needs to be provided in
  892. GetOEMCP() encoding if the console is using a raster font, or in
  893. GetConsoleOutputCP() encoding if it is using a TrueType font.
  894. But in GUI programs and for output sent to files and pipes, GetACP()
  895. encoding is the best bet. */
  896. sprintf (buf, "CP%u", GetACP ());
  897. }
  898. /* For a locale name such as "French_France.65001", in Windows 10,
  899. setlocale now returns "French_France.utf8" instead. */
  900. if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0)
  901. codeset = "UTF-8";
  902. else
  903. {
  904. strcpy (resultbuf, buf);
  905. codeset = resultbuf;
  906. }
  907. # elif defined OS2
  908. const char *locale;
  909. static char resultbuf[2 + 10 + 1];
  910. ULONG cp[3];
  911. ULONG cplen;
  912. codeset = NULL;
  913. /* Allow user to override the codeset, as set in the operating system,
  914. with standard language environment variables. */
  915. locale = getenv ("LC_ALL");
  916. if (locale == NULL || locale[0] == '\0')
  917. {
  918. locale = getenv ("LC_CTYPE");
  919. if (locale == NULL || locale[0] == '\0')
  920. locale = getenv ("LANG");
  921. }
  922. if (locale != NULL && locale[0] != '\0')
  923. {
  924. /* If the locale name contains an encoding after the dot, return it. */
  925. const char *dot = strchr (locale, '.');
  926. if (dot != NULL)
  927. {
  928. const char *modifier;
  929. dot++;
  930. /* Look for the possible @... trailer and remove it, if any. */
  931. modifier = strchr (dot, '@');
  932. if (modifier == NULL)
  933. return dot;
  934. if (modifier - dot < sizeof (resultbuf))
  935. {
  936. /* This way of filling resultbuf is multithread-safe. */
  937. memcpy (resultbuf, dot, modifier - dot);
  938. resultbuf [modifier - dot] = '\0';
  939. return resultbuf;
  940. }
  941. }
  942. /* For the POSIX locale, don't use the system's codepage. */
  943. if (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0)
  944. codeset = "";
  945. }
  946. if (codeset == NULL)
  947. {
  948. /* OS/2 has a function returning the locale's codepage as a number. */
  949. if (DosQueryCp (sizeof (cp), cp, &cplen))
  950. codeset = "";
  951. else
  952. {
  953. char buf[2 + 10 + 1];
  954. sprintf (buf, "CP%u", cp[0]);
  955. strcpy (resultbuf, buf);
  956. codeset = resultbuf;
  957. }
  958. }
  959. # else
  960. # error "Add code for other platforms here."
  961. # endif
  962. /* Resolve alias. */
  963. {
  964. # ifdef alias_table_defined
  965. /* On some platforms, UTF-8 locales are the most frequently used ones.
  966. Speed up the common case and slow down the less common cases by
  967. testing for this case first. */
  968. # if defined __OpenBSD__ || (defined __APPLE__ && defined __MACH__) || defined __sun || defined __CYGWIN__
  969. if (strcmp (codeset, "UTF-8") == 0)
  970. goto done_table_lookup;
  971. else
  972. # endif
  973. {
  974. const struct table_entry * const table = alias_table;
  975. size_t const table_size =
  976. sizeof (alias_table) / sizeof (struct table_entry);
  977. /* The table is sorted. Perform a binary search. */
  978. size_t hi = table_size;
  979. size_t lo = 0;
  980. while (lo < hi)
  981. {
  982. /* Invariant:
  983. for i < lo, strcmp (table[i].alias, codeset) < 0,
  984. for i >= hi, strcmp (table[i].alias, codeset) > 0. */
  985. size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
  986. int cmp = strcmp (table[mid].alias, codeset);
  987. if (cmp < 0)
  988. lo = mid + 1;
  989. else if (cmp > 0)
  990. hi = mid;
  991. else
  992. {
  993. /* Found an i with
  994. strcmp (table[i].alias, codeset) == 0. */
  995. codeset = table[mid].canonical;
  996. goto done_table_lookup;
  997. }
  998. }
  999. }
  1000. if (0)
  1001. done_table_lookup: ;
  1002. else
  1003. # endif
  1004. {
  1005. /* Did not find it in the table. */
  1006. /* On Mac OS X, all modern locales use the UTF-8 encoding.
  1007. BeOS and Haiku have a single locale, and it has UTF-8 encoding. */
  1008. # if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
  1009. codeset = "UTF-8";
  1010. # else
  1011. /* Don't return an empty string. GNU libc and GNU libiconv interpret
  1012. the empty string as denoting "the locale's character encoding",
  1013. thus GNU libiconv would call this function a second time. */
  1014. if (codeset[0] == '\0')
  1015. codeset = "ASCII";
  1016. # endif
  1017. }
  1018. }
  1019. #else
  1020. /* On old systems which lack it, use setlocale or getenv. */
  1021. const char *locale = NULL;
  1022. /* But most old systems don't have a complete set of locales. Some
  1023. (like DJGPP) have only the C locale. Therefore we don't use setlocale
  1024. here; it would return "C" when it doesn't support the locale name the
  1025. user has set. */
  1026. # if 0
  1027. locale = setlocale (LC_CTYPE, NULL);
  1028. # endif
  1029. if (locale == NULL || locale[0] == '\0')
  1030. {
  1031. locale = getenv ("LC_ALL");
  1032. if (locale == NULL || locale[0] == '\0')
  1033. {
  1034. locale = getenv ("LC_CTYPE");
  1035. if (locale == NULL || locale[0] == '\0')
  1036. locale = getenv ("LANG");
  1037. if (locale == NULL)
  1038. locale = "";
  1039. }
  1040. }
  1041. /* Map locale name to canonical encoding name. */
  1042. {
  1043. # ifdef locale_table_defined
  1044. const struct table_entry * const table = locale_table;
  1045. size_t const table_size =
  1046. sizeof (locale_table) / sizeof (struct table_entry);
  1047. /* The table is sorted. Perform a binary search. */
  1048. size_t hi = table_size;
  1049. size_t lo = 0;
  1050. while (lo < hi)
  1051. {
  1052. /* Invariant:
  1053. for i < lo, strcmp (table[i].locale, locale) < 0,
  1054. for i >= hi, strcmp (table[i].locale, locale) > 0. */
  1055. size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
  1056. int cmp = strcmp (table[mid].locale, locale);
  1057. if (cmp < 0)
  1058. lo = mid + 1;
  1059. else if (cmp > 0)
  1060. hi = mid;
  1061. else
  1062. {
  1063. /* Found an i with
  1064. strcmp (table[i].locale, locale) == 0. */
  1065. codeset = table[mid].canonical;
  1066. goto done_table_lookup;
  1067. }
  1068. }
  1069. if (0)
  1070. done_table_lookup: ;
  1071. else
  1072. # endif
  1073. {
  1074. /* Did not find it in the table. */
  1075. /* On Mac OS X, all modern locales use the UTF-8 encoding.
  1076. BeOS and Haiku have a single locale, and it has UTF-8 encoding. */
  1077. # if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
  1078. codeset = "UTF-8";
  1079. # else
  1080. /* The canonical name cannot be determined. */
  1081. /* Don't return an empty string. GNU libc and GNU libiconv interpret
  1082. the empty string as denoting "the locale's character encoding",
  1083. thus GNU libiconv would call this function a second time. */
  1084. codeset = "ASCII";
  1085. # endif
  1086. }
  1087. }
  1088. #endif
  1089. #ifdef DARWIN7
  1090. /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8"
  1091. (the default codeset) does not work when MB_CUR_MAX is 1. */
  1092. if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1)
  1093. codeset = "ASCII";
  1094. #endif
  1095. return codeset;
  1096. }
  1097. /* A variant of the above, without calls to `setlocale', `nl_langinfo',
  1098. etc. */
  1099. const char *
  1100. environ_locale_charset (void)
  1101. {
  1102. static char buf[2 + 10 + 1];
  1103. const char *codeset, *aliases;
  1104. const char *locale = NULL;
  1105. locale = getenv ("LC_ALL");
  1106. if (locale == NULL || locale[0] == '\0')
  1107. {
  1108. locale = getenv ("LC_CTYPE");
  1109. if (locale == NULL || locale[0] == '\0')
  1110. locale = getenv ("LANG");
  1111. }
  1112. if (locale != NULL && locale[0] != '\0')
  1113. {
  1114. /* If the locale name contains an encoding after the dot, return it. */
  1115. const char *dot = strchr (locale, '.');
  1116. if (dot != NULL)
  1117. {
  1118. const char *modifier;
  1119. dot++;
  1120. /* Look for the possible @... trailer and remove it, if any. */
  1121. modifier = strchr (dot, '@');
  1122. if (modifier == NULL)
  1123. return dot;
  1124. if (modifier - dot < sizeof (buf))
  1125. {
  1126. memcpy (buf, dot, modifier - dot);
  1127. buf [modifier - dot] = '\0';
  1128. return buf;
  1129. }
  1130. }
  1131. else if (strcmp (locale, "C") == 0)
  1132. {
  1133. strcpy (buf, "ASCII");
  1134. return buf;
  1135. }
  1136. else
  1137. codeset = "";
  1138. }
  1139. else
  1140. codeset = "";
  1141. /* Resolve alias. */
  1142. {
  1143. # ifdef alias_table_defined
  1144. /* On some platforms, UTF-8 locales are the most frequently used ones.
  1145. Speed up the common case and slow down the less common cases by
  1146. testing for this case first. */
  1147. # if defined __OpenBSD__ || (defined __APPLE__ && defined __MACH__) || defined __sun || defined __CYGWIN__
  1148. if (strcmp (codeset, "UTF-8") == 0)
  1149. goto done_table_lookup;
  1150. else
  1151. # endif
  1152. {
  1153. const struct table_entry * const table = alias_table;
  1154. size_t const table_size =
  1155. sizeof (alias_table) / sizeof (struct table_entry);
  1156. /* The table is sorted. Perform a binary search. */
  1157. size_t hi = table_size;
  1158. size_t lo = 0;
  1159. while (lo < hi)
  1160. {
  1161. /* Invariant:
  1162. for i < lo, strcmp (table[i].alias, codeset) < 0,
  1163. for i >= hi, strcmp (table[i].alias, codeset) > 0. */
  1164. size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
  1165. int cmp = strcmp (table[mid].alias, codeset);
  1166. if (cmp < 0)
  1167. lo = mid + 1;
  1168. else if (cmp > 0)
  1169. hi = mid;
  1170. else
  1171. {
  1172. /* Found an i with
  1173. strcmp (table[i].alias, codeset) == 0. */
  1174. codeset = table[mid].canonical;
  1175. goto done_table_lookup;
  1176. }
  1177. }
  1178. }
  1179. if (0)
  1180. done_table_lookup: ;
  1181. else
  1182. # endif
  1183. {
  1184. /* Did not find it in the table. */
  1185. /* On Mac OS X, all modern locales use the UTF-8 encoding.
  1186. BeOS and Haiku have a single locale, and it has UTF-8 encoding. */
  1187. # if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
  1188. codeset = "UTF-8";
  1189. # else
  1190. /* Don't return an empty string. GNU libc and GNU libiconv interpret
  1191. the empty string as denoting "the locale's character encoding",
  1192. thus GNU libiconv would call this function a second time. */
  1193. if (codeset[0] == '\0')
  1194. codeset = "ASCII";
  1195. # endif
  1196. }
  1197. }
  1198. /* Don't return an empty string. GNU libc and GNU libiconv interpret
  1199. the empty string as denoting "the locale's character encoding",
  1200. thus GNU libiconv would call this function a second time. */
  1201. if (codeset[0] == '\0')
  1202. /* Default to Latin-1, for backward compatibility with Guile 1.8. */
  1203. codeset = "ISO-8859-1";
  1204. return codeset;
  1205. }