gen_locale.c 30 KB

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