gen_locale.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <limits.h>
  7. #include <assert.h>
  8. #include <locale.h>
  9. #include <langinfo.h>
  10. #include <nl_types.h>
  11. #include <stdint.h>
  12. #define __CTYPE_HAS_8_BIT_LOCALES
  13. #include "c8tables.h"
  14. #define CATEGORIES 6
  15. /* must agree with ordering of gen_mmap! */
  16. static const unsigned char *lc_names[] = {
  17. "LC_CTYPE",
  18. "LC_NUMERIC",
  19. "LC_MONETARY",
  20. "LC_TIME",
  21. "LC_COLLATE",
  22. "LC_MESSAGES",
  23. #if CATEGORIES == 12
  24. "LC_PAPER",
  25. "LC_NAME",
  26. "LC_ADDRESS",
  27. "LC_TELEPHONE",
  28. "LC_MEASUREMENT",
  29. "LC_IDENTIFICATION",
  30. #elif CATEGORIES != 6
  31. #error unsupported CATEGORIES value!
  32. #endif
  33. };
  34. typedef struct {
  35. char *glibc_name;
  36. char name[5];
  37. char dot_cs; /* 0 if no codeset specified */
  38. char cs;
  39. unsigned char idx_name;
  40. unsigned char lc_time_row;
  41. unsigned char lc_numeric_row;
  42. unsigned char lc_monetary_row;
  43. unsigned char lc_messages_row;
  44. #if CATEGORIES != 6
  45. #error unsupported CATEGORIES value
  46. #endif
  47. } locale_entry;
  48. static void read_at_mappings(void);
  49. static void read_enable_disable(void);
  50. static void read_locale_list(void);
  51. static int find_codeset_num(const char *cs);
  52. static int find_at_string_num(const char *as);
  53. static int le_cmp(const void *, const void *);
  54. static void dump_table8(const char *name, const char *tbl, int len);
  55. static void dump_table8c(const char *name, const char *tbl, int len);
  56. static void dump_table16(const char *name, const int *tbl, int len);
  57. static void do_lc_time(void);
  58. static void do_lc_numeric(void);
  59. static void do_lc_monetary(void);
  60. static void do_lc_messages(void);
  61. static FILE *fp;
  62. static FILE *ofp;
  63. static char line_buf[80];
  64. static char at_mappings[256];
  65. static char at_mapto[256];
  66. static char at_strings[1024];
  67. static char *at_strings_end;
  68. static locale_entry locales[700];
  69. static char glibc_locale_names[60000];
  70. static int num_locales;
  71. static int default_utf8;
  72. static int default_8bit;
  73. static int total_size;
  74. static int null_count;
  75. static void do_locale_names(void)
  76. {
  77. /* "C" locale name is handled specially by the setlocale code. */
  78. int uniq = 0;
  79. int i;
  80. if (num_locales <= 1) {
  81. /* printf("error - only C locale?\n"); */
  82. /* exit(EXIT_FAILURE); */
  83. fprintf(ofp, "static const unsigned char __locales[%d];\n", (3 + CATEGORIES));
  84. fprintf(ofp, "static const unsigned char __locale_names5[5];\n");
  85. } else {
  86. fprintf(ofp, "#define CATEGORIES\t\t\t%d\n", CATEGORIES);
  87. fprintf(ofp, "#define WIDTH_LOCALES\t\t\t%d\n", 3+CATEGORIES);
  88. fprintf(ofp, "#define NUM_LOCALES\t\t\t%d\n", num_locales);
  89. fprintf(ofp, "static const unsigned char __locales[%d] = {\n",
  90. (num_locales) * (3 + CATEGORIES));
  91. for (i=0 ; i < num_locales ; i++) {
  92. if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) {
  93. locales[i].idx_name = uniq;
  94. ++uniq;
  95. } else {
  96. locales[i].idx_name = uniq - 1;
  97. }
  98. fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].idx_name));
  99. fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].dot_cs));
  100. fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].cs));
  101. /* lc_ctype would store translit flags and turkish up/low flag. */
  102. fprintf(ofp, "%#4x, ", 0); /* place holder for lc_ctype */
  103. fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_numeric_row));
  104. fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_monetary_row));
  105. fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_time_row));
  106. fprintf(ofp, "%#4x, ", 0); /* place holder for lc_collate */
  107. fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_messages_row));
  108. fprintf(ofp, "\t/* %s */\n", locales[i].glibc_name);
  109. }
  110. fprintf(ofp, "};\n\n");
  111. fprintf(ofp, "#define NUM_LOCALE_NAMES\t\t%d\n", uniq );
  112. fprintf(ofp, "static const unsigned char __locale_names5[%d] = \n\t", uniq * 5);
  113. uniq = 0;
  114. for (i=1 ; i < num_locales ; i++) {
  115. if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) {
  116. fprintf(ofp, "\"%5.5s\" ", locales[i].name);
  117. ++uniq;
  118. if ((uniq % 8) == 0) {
  119. fprintf(ofp, "\n\t");
  120. }
  121. }
  122. }
  123. fprintf(ofp,";\n\n");
  124. if (at_strings_end > at_strings) {
  125. int i, j;
  126. char *p;
  127. i = 0;
  128. p = at_strings;
  129. while (*p) {
  130. ++i;
  131. p += 1 + (unsigned char) *p;
  132. }
  133. /* len, char, string\0 */
  134. fprintf(ofp, "#define LOCALE_AT_MODIFIERS_LENGTH\t\t%d\n",
  135. i + (at_strings_end - at_strings));
  136. fprintf(ofp, "static const unsigned char __locale_at_modifiers[%d] = {",
  137. i + (at_strings_end - at_strings));
  138. i = 0;
  139. p = at_strings;
  140. while (*p) {
  141. fprintf(ofp, "\n\t%4d, '%c',",
  142. (unsigned char) *p, /* len of string\0 */
  143. at_mapto[i]);
  144. for (j=1 ; j < ((unsigned char) *p) ; j++) {
  145. fprintf(ofp, " '%c',", p[j]);
  146. }
  147. fprintf(ofp, " 0,");
  148. ++i;
  149. p += 1 + (unsigned char) *p;
  150. }
  151. fprintf(ofp, "\n};\n\n");
  152. }
  153. {
  154. int pos[CATEGORIES];
  155. pos[0] = CATEGORIES;
  156. for (i=0 ; i < CATEGORIES ; i++) {
  157. fprintf(ofp, "#define __%s\t\t%d\n", lc_names[i], i);
  158. if (i + 1 < CATEGORIES) {
  159. pos[i+1] = 1 + strlen(lc_names[i]) + pos[i];
  160. }
  161. }
  162. if (pos[CATEGORIES-1] > 255) {
  163. printf("error - lc_names is too big (%d)\n", pos[CATEGORIES-1]);
  164. exit(EXIT_FAILURE);
  165. }
  166. fprintf(ofp, "#define __LC_ALL\t\t%d\n\n", i);
  167. fprintf(ofp, "#define lc_names_LEN\t\t%d\n",
  168. pos[CATEGORIES-1] + strlen(lc_names[CATEGORIES-1]) + 1);
  169. total_size += pos[CATEGORIES-1] + strlen(lc_names[CATEGORIES-1]) + 1;
  170. fprintf(ofp, "static unsigned const char lc_names[%d] =\n",
  171. pos[CATEGORIES-1] + strlen(lc_names[CATEGORIES-1]) + 1);
  172. fprintf(ofp, "\t\"");
  173. for (i=0 ; i < CATEGORIES ; i++) {
  174. fprintf(ofp, "\\x%02x", (unsigned char) pos[i]);
  175. }
  176. fprintf(ofp, "\"");
  177. for (i=0 ; i < CATEGORIES ; i++) {
  178. fprintf(ofp, "\n\t\"%s\\0\"", lc_names[i]);
  179. }
  180. fprintf(ofp, ";\n\n");
  181. }
  182. printf("locale data = %d name data = %d for %d uniq\n",
  183. num_locales * (3 + CATEGORIES), uniq * 5, uniq);
  184. total_size += num_locales * (3 + CATEGORIES) + uniq * 5;
  185. }
  186. }
  187. int main(int argc, char **argv)
  188. {
  189. if ((argc != 2) || (!(fp = fopen(*++argv, "r")))) {
  190. printf("error: missing filename or file!\n");
  191. return EXIT_FAILURE;
  192. }
  193. at_strings_end = at_strings;
  194. read_at_mappings();
  195. read_enable_disable();
  196. read_locale_list();
  197. fclose(fp);
  198. /* handle C locale specially */
  199. qsort(locales+1, num_locales-1, sizeof(locale_entry), le_cmp);
  200. #if 0
  201. for (i=0 ; i < num_locales ; i++) {
  202. printf("locale: %5.5s %2d %2d %s\n",
  203. locales[i].name,
  204. locales[i].cs,
  205. locales[i].dot_cs,
  206. locales[i].glibc_name
  207. );
  208. }
  209. #endif
  210. if (!(ofp = fopen("locale_tables.h", "w"))) {
  211. printf("error: can not open locale_tables.h for writing!\n");
  212. return EXIT_FAILURE;
  213. }
  214. do_lc_time();
  215. do_lc_numeric();
  216. do_lc_monetary();
  217. do_lc_messages();
  218. do_locale_names();
  219. fclose(ofp);
  220. printf("total data size = %d\n", total_size);
  221. printf("null count = %d\n", null_count);
  222. return EXIT_SUCCESS;
  223. }
  224. static char *idx[10000];
  225. static char buf[100000];
  226. static char *last;
  227. static int uniq;
  228. static int addstring(const char *s)
  229. {
  230. int j;
  231. size_t l;
  232. if (!s) {
  233. ++null_count;
  234. return 0;
  235. }
  236. for (j=0 ; j < uniq ; j++) {
  237. if (!strcmp(s, idx[j])) {
  238. return idx[j] - buf;
  239. }
  240. }
  241. if (uniq >= sizeof(idx)) {
  242. printf("too many uniq strings!\n");
  243. exit(EXIT_FAILURE);
  244. }
  245. l = strlen(s) + 1;
  246. if (last + l >= buf + sizeof(buf)) {
  247. printf("need to increase size of buf!\n");
  248. exit(EXIT_FAILURE);
  249. }
  250. idx[uniq] = last;
  251. ++uniq;
  252. strcpy(last, s);
  253. last += l;
  254. return idx[uniq - 1] - buf;
  255. }
  256. static int buf16[50*256];
  257. static int lc_time_item[50][256];
  258. static int lc_time_count[50];
  259. static unsigned char lc_time_uniq_50[700][50];
  260. static int lc_time_uniq;
  261. #define DO_NL_S(X) lc_time_S(X, k++)
  262. static void lc_time_S(int X, int k)
  263. {
  264. int j, m;
  265. j = addstring(nl_langinfo(X));
  266. for (m=0 ; m < lc_time_count[k] ; m++) {
  267. if (lc_time_item[k][m] == j) {
  268. break;
  269. }
  270. }
  271. if (m == lc_time_count[k]) { /* new for this nl_item */
  272. if (m > 255) {
  273. printf("too many nl_item %d entries in lc_time\n", k);
  274. exit(EXIT_FAILURE);
  275. }
  276. lc_time_item[k][m] = j;
  277. ++lc_time_count[k];
  278. }
  279. /* printf("\\x%02x", m); */
  280. lc_time_uniq_50[lc_time_uniq][k] = m;
  281. }
  282. static void do_lc_time(void)
  283. {
  284. int i, k, m;
  285. last = buf+1;
  286. uniq = 1;
  287. *buf = 0;
  288. *idx = buf;
  289. /* printf("processing lc_time..."); */
  290. for (i=0 ; i < num_locales ; i++) {
  291. k = 0;
  292. /* printf(" %d", i); fflush(stdout); */
  293. if (!setlocale(LC_ALL, locales[i].glibc_name)) {
  294. printf("setlocale(LC_ALL,%s) failed!\n",
  295. locales[i].glibc_name);
  296. }
  297. DO_NL_S(ABDAY_1);
  298. DO_NL_S(ABDAY_2);
  299. DO_NL_S(ABDAY_3);
  300. DO_NL_S(ABDAY_4);
  301. DO_NL_S(ABDAY_5);
  302. DO_NL_S(ABDAY_6);
  303. DO_NL_S(ABDAY_7);
  304. DO_NL_S(DAY_1);
  305. DO_NL_S(DAY_2);
  306. DO_NL_S(DAY_3);
  307. DO_NL_S(DAY_4);
  308. DO_NL_S(DAY_5);
  309. DO_NL_S(DAY_6);
  310. DO_NL_S(DAY_7);
  311. DO_NL_S(ABMON_1);
  312. DO_NL_S(ABMON_2);
  313. DO_NL_S(ABMON_3);
  314. DO_NL_S(ABMON_4);
  315. DO_NL_S(ABMON_5);
  316. DO_NL_S(ABMON_6);
  317. DO_NL_S(ABMON_7);
  318. DO_NL_S(ABMON_8);
  319. DO_NL_S(ABMON_9);
  320. DO_NL_S(ABMON_10);
  321. DO_NL_S(ABMON_11);
  322. DO_NL_S(ABMON_12);
  323. DO_NL_S(MON_1);
  324. DO_NL_S(MON_2);
  325. DO_NL_S(MON_3);
  326. DO_NL_S(MON_4);
  327. DO_NL_S(MON_5);
  328. DO_NL_S(MON_6);
  329. DO_NL_S(MON_7);
  330. DO_NL_S(MON_8);
  331. DO_NL_S(MON_9);
  332. DO_NL_S(MON_10);
  333. DO_NL_S(MON_11);
  334. DO_NL_S(MON_12);
  335. DO_NL_S(AM_STR);
  336. DO_NL_S(PM_STR);
  337. DO_NL_S(D_T_FMT);
  338. DO_NL_S(D_FMT);
  339. DO_NL_S(T_FMT);
  340. DO_NL_S(T_FMT_AMPM);
  341. DO_NL_S(ERA);
  342. DO_NL_S(ERA_YEAR); /* non SuSv3 */
  343. DO_NL_S(ERA_D_FMT);
  344. DO_NL_S(ALT_DIGITS);
  345. DO_NL_S(ERA_D_T_FMT);
  346. DO_NL_S(ERA_T_FMT);
  347. if (k > 50) {
  348. printf("error -- lc_time nl_item count > 50!\n");
  349. exit(EXIT_FAILURE);
  350. }
  351. {
  352. int r;
  353. for (r=0 ; r < lc_time_uniq ; r++) {
  354. if (!memcmp(lc_time_uniq_50[lc_time_uniq],
  355. lc_time_uniq_50[r], 50)) {
  356. break;
  357. }
  358. }
  359. if (r == lc_time_uniq) { /* new locale row */
  360. ++lc_time_uniq;
  361. if (lc_time_uniq > 255) {
  362. printf("too many unique lc_time rows!\n");
  363. exit(EXIT_FAILURE);
  364. }
  365. }
  366. locales[i].lc_time_row = r;
  367. }
  368. /* printf("\n"); */
  369. }
  370. /* printf(" done\n"); */
  371. m = k = 0;
  372. for (i=0 ; i < 50 ; i++) {
  373. k += lc_time_count[i];
  374. if (m < lc_time_count[i]) {
  375. m = lc_time_count[i];
  376. }
  377. }
  378. printf("buf-size=%d uniq=%d item_offsets=%d max=%d rows=%d\n",
  379. (int)(last - buf), uniq, k, m, lc_time_uniq);
  380. /* printf("total = %d * 50 + 2 * (50 + %d) + %d = %d\n", */
  381. /* num_locales, k, (int)(last - buf), */
  382. /* num_locales*50 + 2*(50 + k) + (int)(last - buf)); */
  383. printf("total = %d + %d * 50 + 2 * (50 + %d) + %d = %d\n",
  384. num_locales, lc_time_uniq, k, (int)(last - buf),
  385. i = num_locales + lc_time_uniq*50 + 2*(50 + k) + (int)(last - buf));
  386. total_size += i;
  387. dump_table8c("__lc_time_data", buf, (int)(last - buf));
  388. for (i=0 ; i < lc_time_uniq ; i++) {
  389. m = locales[i].lc_time_row;
  390. for (k=0 ; k < 50 ; k++) {
  391. buf[50*i + k] = (char)((unsigned char) lc_time_uniq_50[i][k]);
  392. }
  393. }
  394. dump_table8("__lc_time_rows", buf, lc_time_uniq * 50);
  395. buf16[0] =0;
  396. for (i=0 ; i < 50 - 1 ; i++) {
  397. buf16[i+1] = buf16[i] + lc_time_count[i];
  398. }
  399. dump_table16("__lc_time_item_offsets", buf16, 50);
  400. m = 0;
  401. for (k=0 ; k < 50 ; k++) {
  402. for (i=0 ; i < lc_time_count[k] ; i++) {
  403. buf16[m] = lc_time_item[k][i];
  404. ++m;
  405. }
  406. }
  407. dump_table16("__lc_time_item_idx", buf16, m);
  408. }
  409. static void dump_table8(const char *name, const char *tbl, int len)
  410. {
  411. int i;
  412. fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len);
  413. fprintf(ofp, "static const unsigned char %s[%d] = {", name, len);
  414. for (i=0 ; i < len ; i++) {
  415. if ((i % 12) == 0) {
  416. fprintf(ofp, "\n\t");
  417. }
  418. fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i]));
  419. }
  420. fprintf(ofp, "\n};\n\n");
  421. }
  422. #define __C_isdigit(c) \
  423. ((sizeof(c) == sizeof(char)) \
  424. ? (((unsigned char)((c) - '0')) < 10) \
  425. : (((unsigned int)((c) - '0')) < 10))
  426. #define __C_isalpha(c) \
  427. ((sizeof(c) == sizeof(char)) \
  428. ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \
  429. : (((unsigned int)(((c) | 0x20) - 'a')) < 26))
  430. #define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c))
  431. static void dump_table8c(const char *name, const char *tbl, int len)
  432. {
  433. int i;
  434. fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len);
  435. fprintf(ofp, "static const unsigned char %s[%d] = {", name, len);
  436. for (i=0 ; i < len ; i++) {
  437. if ((i % 12) == 0) {
  438. fprintf(ofp, "\n\t");
  439. }
  440. if (__C_isalnum(tbl[i]) || (tbl[i] == ' ')) {
  441. fprintf(ofp, " '%c', ", (int)((unsigned char) tbl[i]));
  442. } else {
  443. fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i]));
  444. }
  445. }
  446. fprintf(ofp, "\n};\n\n");
  447. }
  448. static void dump_table16(const char *name, const int *tbl, int len)
  449. {
  450. int i;
  451. fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len);
  452. fprintf(ofp, "static const uint16_t %s[%d] = {", name, len);
  453. for (i=0 ; i < len ; i++) {
  454. if ((i % 8) == 0) {
  455. fprintf(ofp, "\n\t");
  456. }
  457. if (tbl[i] != (uint16_t) tbl[i]) {
  458. printf("error - falls outside uint16 range!\n");
  459. exit(EXIT_FAILURE);
  460. }
  461. fprintf(ofp, "%#6x, ", tbl[i]);
  462. }
  463. fprintf(ofp, "\n};\n\n");
  464. }
  465. #undef DO_NL_S
  466. static int lc_numeric_item[3][256];
  467. static int lc_numeric_count[3];
  468. static unsigned char lc_numeric_uniq_3[700][3];
  469. static int lc_numeric_uniq;
  470. #define DO_NL_S(X) lc_numeric_S(X, k++)
  471. static void lc_numeric_S(int X, int k)
  472. {
  473. int j, m;
  474. char buf[256];
  475. char *e;
  476. char *s;
  477. char c;
  478. s = nl_langinfo(X);
  479. if (X == GROUPING) {
  480. if (s) {
  481. if ((*s == CHAR_MAX) || (*s == -1)) { /* stupid glibc... :-( */
  482. s = "";
  483. }
  484. e = s;
  485. c = 0;
  486. while (*e) { /* find end of string */
  487. if (*e == CHAR_MAX) {
  488. c = CHAR_MAX;
  489. ++e;
  490. break;
  491. }
  492. ++e;
  493. }
  494. if ((e - s) > sizeof(buf)) {
  495. printf("grouping specifier too long\n");
  496. exit(EXIT_FAILURE);
  497. }
  498. strncpy(buf, s, (e-s));
  499. e = buf + (e-s);
  500. *e = 0; /* Make sure we're null-terminated. */
  501. if (c != CHAR_MAX) { /* remove duplicate repeats */
  502. while (e > buf) {
  503. --e;
  504. if (*e != e[-1]) {
  505. break;
  506. }
  507. }
  508. *++e = 0;
  509. }
  510. s = buf;
  511. }
  512. }
  513. j = addstring(s);
  514. for (m=0 ; m < lc_numeric_count[k] ; m++) {
  515. if (lc_numeric_item[k][m] == j) {
  516. break;
  517. }
  518. }
  519. if (m == lc_numeric_count[k]) { /* new for this nl_item */
  520. if (m > 255) {
  521. printf("too many nl_item %d entries in lc_numeric\n", k);
  522. exit(EXIT_FAILURE);
  523. }
  524. lc_numeric_item[k][m] = j;
  525. ++lc_numeric_count[k];
  526. }
  527. /* printf("\\x%02x", m); */
  528. lc_numeric_uniq_3[lc_numeric_uniq][k] = m;
  529. }
  530. static void do_lc_numeric(void)
  531. {
  532. int i, k, m;
  533. last = buf+1;
  534. uniq = 1;
  535. *buf = 0;
  536. *idx = buf;
  537. for (i=0 ; i < num_locales ; i++) {
  538. k = 0;
  539. if (!setlocale(LC_ALL, locales[i].glibc_name)) {
  540. printf("setlocale(LC_ALL,%s) failed!\n",
  541. locales[i].glibc_name);
  542. }
  543. DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */
  544. DO_NL_S(THOUSEP); /* THOUSANDS_SEP */
  545. DO_NL_S(GROUPING);
  546. if (k > 3) {
  547. printf("error -- lc_numeric nl_item count > 3!\n");
  548. exit(EXIT_FAILURE);
  549. }
  550. {
  551. int r;
  552. for (r=0 ; r < lc_numeric_uniq ; r++) {
  553. if (!memcmp(lc_numeric_uniq_3[lc_numeric_uniq],
  554. lc_numeric_uniq_3[r], 3)) {
  555. break;
  556. }
  557. }
  558. if (r == lc_numeric_uniq) { /* new locale row */
  559. ++lc_numeric_uniq;
  560. if (lc_numeric_uniq > 255) {
  561. printf("too many unique lc_numeric rows!\n");
  562. exit(EXIT_FAILURE);
  563. }
  564. }
  565. locales[i].lc_numeric_row = r;
  566. }
  567. }
  568. printf("buf-size=%d uniq=%d rows=%d\n",
  569. (int)(last - buf), uniq, lc_numeric_uniq);
  570. printf("total = %d + %d * 3 + %d = %d\n",
  571. num_locales, lc_numeric_uniq, (int)(last - buf),
  572. i = num_locales + lc_numeric_uniq*3 + (int)(last - buf));
  573. total_size += i;
  574. /* printf("buf-size=%d uniq=%d\n", (int)(last - buf), uniq); */
  575. dump_table8c("__lc_numeric_data", buf, (int)(last - buf));
  576. for (i=0 ; i < lc_numeric_uniq ; i++) {
  577. m = locales[i].lc_numeric_row;
  578. for (k=0 ; k < 3 ; k++) {
  579. buf[3*i + k] = (char)((unsigned char) lc_numeric_uniq_3[i][k]);
  580. }
  581. }
  582. dump_table8("__lc_numeric_rows", buf, lc_numeric_uniq * 3);
  583. buf16[0] =0;
  584. for (i=0 ; i < 3 - 1 ; i++) {
  585. buf16[i+1] = buf16[i] + lc_numeric_count[i];
  586. }
  587. dump_table16("__lc_numeric_item_offsets", buf16, 3);
  588. m = 0;
  589. for (k=0 ; k < 3 ; k++) {
  590. for (i=0 ; i < lc_numeric_count[k] ; i++) {
  591. buf16[m] = lc_numeric_item[k][i];
  592. ++m;
  593. }
  594. }
  595. dump_table16("__lc_numeric_item_idx", buf16, m);
  596. }
  597. #undef DO_NL_S
  598. /* #define NUM_NL_MONETARY 7 */
  599. #define NUM_NL_MONETARY (7+14+1)
  600. static int lc_monetary_item[NUM_NL_MONETARY][256];
  601. static int lc_monetary_count[NUM_NL_MONETARY];
  602. static unsigned char lc_monetary_uniq_X[700][NUM_NL_MONETARY];
  603. static int lc_monetary_uniq;
  604. #define DO_NL_S(X) lc_monetary_S(X, k++)
  605. /* #define DO_NL_C(X) printf("%#02x", (int)(unsigned char)(*nl_langinfo(X))); */
  606. #define DO_NL_C(X) lc_monetary_C(X, k++)
  607. static void lc_monetary_C(int X, int k)
  608. {
  609. int j, m;
  610. char c_buf[2];
  611. #warning fix the char entries for monetary... target signedness of char may be different!
  612. c_buf[1] = 0;
  613. c_buf[0] = *nl_langinfo(X);
  614. j = addstring(c_buf);
  615. for (m=0 ; m < lc_monetary_count[k] ; m++) {
  616. if (lc_monetary_item[k][m] == j) {
  617. break;
  618. }
  619. }
  620. if (m == lc_monetary_count[k]) { /* new for this nl_item */
  621. if (m > 255) {
  622. printf("too many nl_item %d entries in lc_monetary\n", k);
  623. exit(EXIT_FAILURE);
  624. }
  625. lc_monetary_item[k][m] = j;
  626. ++lc_monetary_count[k];
  627. }
  628. /* printf("\\x%02x", m); */
  629. lc_monetary_uniq_X[lc_monetary_uniq][k] = m;
  630. }
  631. static void lc_monetary_S(int X, int k)
  632. {
  633. int j, m;
  634. char buf[256];
  635. char *e;
  636. char *s;
  637. char c;
  638. s = nl_langinfo(X);
  639. if (X == MON_GROUPING) {
  640. if (s) {
  641. if ((*s == CHAR_MAX) || (*s == -1)) { /* stupid glibc... :-( */
  642. s = "";
  643. }
  644. e = s;
  645. c = 0;
  646. while (*e) { /* find end of string */
  647. if (*e == CHAR_MAX) {
  648. c = CHAR_MAX;
  649. ++e;
  650. break;
  651. }
  652. ++e;
  653. }
  654. if ((e - s) > sizeof(buf)) {
  655. printf("mon_grouping specifier too long\n");
  656. exit(EXIT_FAILURE);
  657. }
  658. strncpy(buf, s, (e-s));
  659. e = buf + (e-s);
  660. *e = 0; /* Make sure we're null-terminated. */
  661. if (c != CHAR_MAX) { /* remove duplicate repeats */
  662. while (e > buf) {
  663. --e;
  664. if (*e != e[-1]) {
  665. break;
  666. }
  667. }
  668. *++e = 0;
  669. }
  670. s = buf;
  671. }
  672. }
  673. j = addstring(s);
  674. for (m=0 ; m < lc_monetary_count[k] ; m++) {
  675. if (lc_monetary_item[k][m] == j) {
  676. break;
  677. }
  678. }
  679. if (m == lc_monetary_count[k]) { /* new for this nl_item */
  680. if (m > 255) {
  681. printf("too many nl_item %d entries in lc_monetary\n", k);
  682. exit(EXIT_FAILURE);
  683. }
  684. lc_monetary_item[k][m] = j;
  685. ++lc_monetary_count[k];
  686. }
  687. /* printf("\\x%02x", m); */
  688. lc_monetary_uniq_X[lc_monetary_uniq][k] = m;
  689. }
  690. static void do_lc_monetary(void)
  691. {
  692. int i, k, m;
  693. last = buf+1;
  694. uniq = 1;
  695. *buf = 0;
  696. *idx = buf;
  697. for (i=0 ; i < num_locales ; i++) {
  698. k = 0;
  699. if (!setlocale(LC_ALL, locales[i].glibc_name)) {
  700. printf("setlocale(LC_ALL,%s) failed!\n",
  701. locales[i].glibc_name);
  702. }
  703. /* non SUSv3 */
  704. DO_NL_S(INT_CURR_SYMBOL);
  705. DO_NL_S(CURRENCY_SYMBOL);
  706. DO_NL_S(MON_DECIMAL_POINT);
  707. DO_NL_S(MON_THOUSANDS_SEP);
  708. DO_NL_S(MON_GROUPING);
  709. DO_NL_S(POSITIVE_SIGN);
  710. DO_NL_S(NEGATIVE_SIGN);
  711. DO_NL_C(INT_FRAC_DIGITS);
  712. DO_NL_C(FRAC_DIGITS);
  713. DO_NL_C(P_CS_PRECEDES);
  714. DO_NL_C(P_SEP_BY_SPACE);
  715. DO_NL_C(N_CS_PRECEDES);
  716. DO_NL_C(N_SEP_BY_SPACE);
  717. DO_NL_C(P_SIGN_POSN);
  718. DO_NL_C(N_SIGN_POSN);
  719. DO_NL_C(INT_P_CS_PRECEDES);
  720. DO_NL_C(INT_P_SEP_BY_SPACE);
  721. DO_NL_C(INT_N_CS_PRECEDES);
  722. DO_NL_C(INT_N_SEP_BY_SPACE);
  723. DO_NL_C(INT_P_SIGN_POSN);
  724. DO_NL_C(INT_N_SIGN_POSN);
  725. DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */
  726. /* printf("\n"); */
  727. if (k > NUM_NL_MONETARY) {
  728. printf("error -- lc_monetary nl_item count > %d!\n", NUM_NL_MONETARY);
  729. exit(EXIT_FAILURE);
  730. }
  731. {
  732. int r;
  733. for (r=0 ; r < lc_monetary_uniq ; r++) {
  734. if (!memcmp(lc_monetary_uniq_X[lc_monetary_uniq],
  735. lc_monetary_uniq_X[r], NUM_NL_MONETARY)) {
  736. break;
  737. }
  738. }
  739. if (r == lc_monetary_uniq) { /* new locale row */
  740. ++lc_monetary_uniq;
  741. if (lc_monetary_uniq > 255) {
  742. printf("too many unique lc_monetary rows!\n");
  743. exit(EXIT_FAILURE);
  744. }
  745. }
  746. locales[i].lc_monetary_row = r;
  747. }
  748. }
  749. printf("buf-size=%d uniq=%d rows=%d\n",
  750. (int)(last - buf), uniq, lc_monetary_uniq);
  751. printf("total = %d + %d * %d + %d = %d\n",
  752. num_locales, lc_monetary_uniq, NUM_NL_MONETARY, (int)(last - buf),
  753. i = num_locales + lc_monetary_uniq*NUM_NL_MONETARY + (int)(last - buf));
  754. total_size += i;
  755. dump_table8c("__lc_monetary_data", buf, (int)(last - buf));
  756. for (i=0 ; i < lc_monetary_uniq ; i++) {
  757. m = locales[i].lc_monetary_row;
  758. for (k=0 ; k < NUM_NL_MONETARY ; k++) {
  759. buf[NUM_NL_MONETARY*i + k] = (char)((unsigned char) lc_monetary_uniq_X[i][k]);
  760. }
  761. }
  762. dump_table8("__lc_monetary_rows", buf, lc_monetary_uniq * NUM_NL_MONETARY);
  763. buf16[0] =0;
  764. for (i=0 ; i < NUM_NL_MONETARY - 1 ; i++) {
  765. buf16[i+1] = buf16[i] + lc_monetary_count[i];
  766. }
  767. dump_table16("__lc_monetary_item_offsets", buf16, NUM_NL_MONETARY);
  768. m = 0;
  769. for (k=0 ; k < NUM_NL_MONETARY ; k++) {
  770. for (i=0 ; i < lc_monetary_count[k] ; i++) {
  771. buf16[m] = lc_monetary_item[k][i];
  772. ++m;
  773. }
  774. }
  775. dump_table16("__lc_monetary_item_idx", buf16, m);
  776. }
  777. #undef DO_NL_S
  778. static int lc_messages_item[2][256];
  779. static int lc_messages_count[2];
  780. static unsigned char lc_messages_uniq_2[700][2];
  781. static int lc_messages_uniq;
  782. #define DO_NL_S(X) lc_messages_S(X, k++)
  783. static void lc_messages_S(int X, int k)
  784. {
  785. int j, m;
  786. j = addstring(nl_langinfo(X));
  787. for (m=0 ; m < lc_messages_count[k] ; m++) {
  788. if (lc_messages_item[k][m] == j) {
  789. break;
  790. }
  791. }
  792. if (m == lc_messages_count[k]) { /* new for this nl_item */
  793. if (m > 255) {
  794. printf("too many nl_item %d entries in lc_messages\n", k);
  795. exit(EXIT_FAILURE);
  796. }
  797. lc_messages_item[k][m] = j;
  798. ++lc_messages_count[k];
  799. }
  800. /* printf("\\x%02x", m); */
  801. lc_messages_uniq_2[lc_messages_uniq][k] = m;
  802. }
  803. static void do_lc_messages(void)
  804. {
  805. int i, k, m;
  806. last = buf+1;
  807. uniq = 1;
  808. *buf = 0;
  809. *idx = buf;
  810. for (i=0 ; i < num_locales ; i++) {
  811. k = 0;
  812. if (!setlocale(LC_ALL, locales[i].glibc_name)) {
  813. printf("setlocale(LC_ALL,%s) failed!\n",
  814. locales[i].glibc_name);
  815. }
  816. DO_NL_S(YESEXPR);
  817. DO_NL_S(NOEXPR);
  818. if (k > 2) {
  819. printf("error -- lc_messages nl_item count > 2!\n");
  820. exit(EXIT_FAILURE);
  821. }
  822. {
  823. int r;
  824. for (r=0 ; r < lc_messages_uniq ; r++) {
  825. if (!memcmp(lc_messages_uniq_2[lc_messages_uniq],
  826. lc_messages_uniq_2[r], 2)) {
  827. break;
  828. }
  829. }
  830. if (r == lc_messages_uniq) { /* new locale row */
  831. ++lc_messages_uniq;
  832. if (lc_messages_uniq > 255) {
  833. printf("too many unique lc_messages rows!\n");
  834. exit(EXIT_FAILURE);
  835. }
  836. }
  837. locales[i].lc_messages_row = r;
  838. }
  839. }
  840. printf("buf-size=%d uniq=%d rows=%d\n",
  841. (int)(last - buf), uniq, lc_messages_uniq);
  842. printf("total = %d + %d * 2 + %d = %d\n",
  843. num_locales, lc_messages_uniq, (int)(last - buf),
  844. i = num_locales + lc_messages_uniq*2 + (int)(last - buf));
  845. total_size += i;
  846. /* printf("buf-size=%d uniq=%d\n", (int)(last - buf), uniq); */
  847. dump_table8c("__lc_messages_data", buf, (int)(last - buf));
  848. for (i=0 ; i < lc_messages_uniq ; i++) {
  849. m = locales[i].lc_messages_row;
  850. for (k=0 ; k < 2 ; k++) {
  851. buf[2*i + k] = (char)((unsigned char) lc_messages_uniq_2[i][k]);
  852. }
  853. }
  854. dump_table8("__lc_messages_rows", buf, lc_messages_uniq * 2);
  855. buf16[0] =0;
  856. for (i=0 ; i < 2 - 1 ; i++) {
  857. buf16[i+1] = buf16[i] + lc_messages_count[i];
  858. }
  859. dump_table16("__lc_messages_item_offsets", buf16, 2);
  860. m = 0;
  861. for (k=0 ; k < 2 ; k++) {
  862. for (i=0 ; i < lc_messages_count[k] ; i++) {
  863. buf16[m] = lc_messages_item[k][i];
  864. ++m;
  865. }
  866. }
  867. dump_table16("__lc_messages_item_idx", buf16, m);
  868. }
  869. static void read_at_mappings(void)
  870. {
  871. char *p;
  872. char *m;
  873. int mc = 0;
  874. do {
  875. if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) {
  876. if (!fgets(line_buf, sizeof(line_buf), fp)) {
  877. if (ferror(fp)) {
  878. printf("error reading file\n");
  879. exit(EXIT_FAILURE);
  880. }
  881. return; /* EOF */
  882. }
  883. if ((*line_buf == '#') && (line_buf[1] == '-')) {
  884. break;
  885. }
  886. continue;
  887. }
  888. if (*p == '@') {
  889. if (p[1] == 0) {
  890. printf("error: missing @modifier name\n");
  891. exit(EXIT_FAILURE);
  892. }
  893. m = p; /* save the modifier name */
  894. if (!(p = strtok(NULL, " \t\n")) || p[1] || (((unsigned char) *p) > 0x7f)) {
  895. printf("error: missing or illegal @modifier mapping char\n");
  896. exit(EXIT_FAILURE);
  897. }
  898. if (at_mappings[(int)((unsigned char) *p)]) {
  899. printf("error: reused @modifier mapping char\n");
  900. exit(EXIT_FAILURE);
  901. }
  902. at_mappings[(int)((unsigned char) *p)] = 1;
  903. at_mapto[mc] = *p;
  904. ++mc;
  905. *at_strings_end = (char)( (unsigned char) (strlen(m)) );
  906. strcpy(++at_strings_end, m+1);
  907. at_strings_end += (unsigned char) at_strings_end[-1];
  908. printf("@mapping: \"%s\" to '%c'\n", m, *p);
  909. if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
  910. printf("ignoring trailing text: %s...\n", p);
  911. }
  912. *line_buf = 0;
  913. continue;
  914. }
  915. break;
  916. } while (1);
  917. #if 0
  918. {
  919. p = at_strings;
  920. if (!*p) {
  921. printf("no @ strings\n");
  922. return;
  923. }
  924. do {
  925. printf("%s\n", p+1);
  926. p += 1 + (unsigned char) *p;
  927. } while (*p);
  928. }
  929. #endif
  930. }
  931. static void read_enable_disable(void)
  932. {
  933. char *p;
  934. do {
  935. if (!(p = strtok(line_buf, " =\t\n")) || (*p == '#')) {
  936. if (!fgets(line_buf, sizeof(line_buf), fp)) {
  937. if (ferror(fp)) {
  938. printf("error reading file\n");
  939. exit(EXIT_FAILURE);
  940. }
  941. return; /* EOF */
  942. }
  943. if ((*line_buf == '#') && (line_buf[1] == '-')) {
  944. break;
  945. }
  946. continue;
  947. }
  948. if (!strcmp(p, "UTF-8")) {
  949. if (!(p = strtok(NULL, " =\t\n"))
  950. || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) {
  951. printf("error: missing or illegal UTF-8 setting\n");
  952. exit(EXIT_FAILURE);
  953. }
  954. default_utf8 = (toupper(*p) == 'Y');
  955. printf("UTF-8 locales are %sabled\n", "dis\0en"+ (default_utf8 << 2));
  956. } else if (!strcmp(p, "8-BIT")) {
  957. if (!(p = strtok(NULL, " =\t\n"))
  958. || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) {
  959. printf("error: missing or illegal 8-BIT setting\n");
  960. exit(EXIT_FAILURE);
  961. }
  962. default_8bit = (toupper(*p) == 'Y');
  963. printf("8-BIT locales are %sabled\n", "dis\0en" + (default_8bit << 2));
  964. } else {
  965. break;
  966. }
  967. if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
  968. printf("ignoring trailing text: %s...\n", p);
  969. }
  970. *line_buf = 0;
  971. continue;
  972. } while (1);
  973. }
  974. #ifdef CODESET_LIST
  975. static int find_codeset_num(const char *cs)
  976. {
  977. int r = 2;
  978. char *s = CODESET_LIST;
  979. /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */
  980. if (strcmp(cs, "UTF-8") != 0) {
  981. ++r;
  982. while (*s && strcmp(CODESET_LIST+ ((unsigned char) *s), cs)) {
  983. /* printf("tried %s\n", CODESET_LIST + ((unsigned char) *s)); */
  984. ++r;
  985. ++s;
  986. }
  987. if (!*s) {
  988. printf("error: unsupported codeset %s\n", cs);
  989. exit(EXIT_FAILURE);
  990. }
  991. }
  992. return r;
  993. }
  994. #else
  995. static int find_codeset_num(const char *cs)
  996. {
  997. int r = 2;
  998. /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */
  999. if (strcmp(cs, "UTF-8") != 0) {
  1000. printf("error: unsupported codeset %s\n", cs);
  1001. exit(EXIT_FAILURE);
  1002. }
  1003. return r;
  1004. }
  1005. #endif
  1006. static int find_at_string_num(const char *as)
  1007. {
  1008. int i = 0;
  1009. char *p = at_strings;
  1010. while (*p) {
  1011. if (!strcmp(p+1, as)) {
  1012. return i;
  1013. }
  1014. ++i;
  1015. p += 1 + (unsigned char) *p;
  1016. }
  1017. printf("error: unmapped @string %s\n", as);
  1018. exit(EXIT_FAILURE);
  1019. }
  1020. static void read_locale_list(void)
  1021. {
  1022. char *p;
  1023. char *s;
  1024. char *ln; /* locale name */
  1025. char *ls; /* locale name ll_CC */
  1026. char *as; /* at string */
  1027. char *ds; /* dot string */
  1028. char *cs; /* codeset */
  1029. int i;
  1030. typedef struct {
  1031. char *glibc_name;
  1032. char name[5];
  1033. char dot_cs; /* 0 if no codeset specified */
  1034. char cs;
  1035. } locale_entry;
  1036. /* First the C locale. */
  1037. locales[0].glibc_name = locales[0].name;
  1038. strncpy(locales[0].name,"C",5);
  1039. locales[0].dot_cs = 0;
  1040. locales[0].cs = 1; /* 7-bit encoding */
  1041. ++num_locales;
  1042. do {
  1043. if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) {
  1044. if (!fgets(line_buf, sizeof(line_buf), fp)) {
  1045. if (ferror(fp)) {
  1046. printf("error reading file\n");
  1047. exit(EXIT_FAILURE);
  1048. }
  1049. return; /* EOF */
  1050. }
  1051. if ((*line_buf == '#') && (line_buf[1] == '-')) {
  1052. break;
  1053. }
  1054. continue;
  1055. }
  1056. s = glibc_locale_names;
  1057. for (i=0 ; i < num_locales ; i++) {
  1058. if (!strcmp(s+1, p)) {
  1059. break;
  1060. }
  1061. s += 1 + ((unsigned char) *s);
  1062. }
  1063. if (i < num_locales) {
  1064. printf("ignoring dulplicate locale name: %s", p);
  1065. *line_buf = 0;
  1066. continue;
  1067. }
  1068. /* New locale, but don't increment num until codeset verified! */
  1069. *s = (char)((unsigned char) (strlen(p) + 1));
  1070. strcpy(s+1, p);
  1071. locales[num_locales].glibc_name = s+1;
  1072. ln = p; /* save locale name */
  1073. if (!(p = strtok(NULL, " \t\n"))) {
  1074. printf("error: missing codeset for locale %s\n", ln);
  1075. exit(EXIT_FAILURE);
  1076. }
  1077. cs = p;
  1078. i = find_codeset_num(p);
  1079. if ((i == 2) && !default_utf8) {
  1080. printf("ignoring UTF-8 locale %s\n", ln);
  1081. *line_buf = 0;
  1082. continue;
  1083. } else if ((i > 2) && !default_8bit) {
  1084. printf("ignoring 8-bit codeset locale %s\n", ln);
  1085. *line_buf = 0;
  1086. continue;
  1087. }
  1088. locales[num_locales].cs = (char)((unsigned char) i);
  1089. if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
  1090. printf("ignoring trailing text: %s...\n", p);
  1091. }
  1092. /* Now go back to locale string for .codeset and @modifier */
  1093. as = strtok(ln, "@");
  1094. if (as) {
  1095. as = strtok(NULL, "@");
  1096. }
  1097. ds = strtok(ln, ".");
  1098. if (ds) {
  1099. ds = strtok(NULL, ".");
  1100. }
  1101. ls = ln;
  1102. if ((strlen(ls) != 5) || (ls[2] != '_')) {
  1103. printf("error: illegal locale name %s\n", ls);
  1104. exit(EXIT_FAILURE);
  1105. }
  1106. i = 0; /* value for unspecified codeset */
  1107. if (ds) {
  1108. i = find_codeset_num(ds);
  1109. if ((i == 2) && !default_utf8) {
  1110. printf("ignoring UTF-8 locale %s\n", ln);
  1111. *line_buf = 0;
  1112. continue;
  1113. } else if ((i > 2) && !default_8bit) {
  1114. printf("ignoring 8-bit codeset locale %s\n", ln);
  1115. *line_buf = 0;
  1116. continue;
  1117. }
  1118. }
  1119. locales[num_locales].dot_cs = (char)((unsigned char) i);
  1120. if (as) {
  1121. i = find_at_string_num(as);
  1122. ls[2] = at_mapto[i];
  1123. }
  1124. memcpy(locales[num_locales].name, ls, 5);
  1125. /* printf("locale: %5.5s %2d %2d %s\n", */
  1126. /* locales[num_locales].name, */
  1127. /* locales[num_locales].cs, */
  1128. /* locales[num_locales].dot_cs, */
  1129. /* locales[num_locales].glibc_name */
  1130. /* ); */
  1131. ++num_locales;
  1132. *line_buf = 0;
  1133. } while (1);
  1134. }
  1135. static int le_cmp(const void *a, const void *b)
  1136. {
  1137. const locale_entry *p;
  1138. const locale_entry *q;
  1139. int r;
  1140. p = (const locale_entry *) a;
  1141. q = (const locale_entry *) b;
  1142. if (!(r = p->name[0] - q->name[0])
  1143. && !(r = p->name[1] - q->name[1])
  1144. && !(r = p->name[3] - q->name[3])
  1145. && !(r = p->name[4] - q->name[4])
  1146. && !(r = p->name[2] - q->name[2])
  1147. && !(r = -(p->cs - q->cs))
  1148. ) {
  1149. r = -(p->dot_cs - q->dot_cs);
  1150. /* Reverse the ordering of the codesets so UTF-8 comes last.
  1151. * Work-around (hopefully) for glibc bug affecting at least
  1152. * the euro currency symbol. */
  1153. }
  1154. return r;
  1155. }