Cygwin: signal: Increase chance of handling signal in main thread
[newlib-cygwin.git] / winsup / cygwin / linux-locale-helpers / fetch-lc_time_era-from-linux.c
blob66dc7aa39ab3cee961f134e1c7160832e56a049d
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 #define _GNU_SOURCE
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <dirent.h>
7 #include <time.h>
8 #include <locale.h>
9 #include <langinfo.h>
10 #include <wchar.h>
12 struct lc_era_t {
13 char locale[64];
14 char *date_fmt;
15 char *d_fmt;
16 char *d_t_fmt;
17 char *t_fmt;
18 char *t_fmt_ampm;
19 char *era;
20 char *era_d_fmt;
21 char *era_d_t_fmt;
22 char *era_t_fmt;
23 char *alt_digits;
24 } era[512];
25 int ecnt = 0;
27 char *
28 xfrm_utf (const wchar_t *ws, int slist)
30 static char xfrm[4096];
31 char *p = xfrm;
32 int wconst = 0;
34 while (*ws)
36 if (*ws < 0x80 && (!wconst || !wcschr (L"aAbBcCdDeEfF", *ws)))
38 *p++ = *ws;
39 wconst = 0;
41 else
43 p += sprintf (p, "\\x%04lx", *ws);
44 wconst = 1;
46 ++ws;
47 if (!*ws && slist)
49 ++ws;
50 if (*ws)
51 p += sprintf (p, ";");
54 *p = '\0';
55 return xfrm;
58 char *
59 xfrm_slist (const char *slist)
61 static wchar_t wxfrm[4096], *wp;
62 char *xfrm, *p, *ret;
64 wp = wxfrm;
65 while (*slist)
67 size_t len = mbstowcs (wp, slist, wxfrm + 4096 - wp) + 1;
68 slist += strlen (slist) + 1;
69 wp += len;
71 *wp++ = L'\0';
72 xfrm = xfrm_utf (wxfrm, 1);
73 p = xfrm;
74 while (*p)
75 p += strlen (p) + 1;
76 ++p;
77 ret = (char *) malloc (p - xfrm);
78 memcpy (ret, xfrm, p - xfrm);
79 return ret;
82 void
83 read_locale_era (char *name)
85 char *nl, *nlera, *altd;
86 char locale[64];
87 wchar_t nlbuf[256];
89 strcpy (locale, name);
90 nl = strchr (locale, '@');
91 if (nl)
92 stpcpy (stpcpy (nl, ".utf8"), strchr (name, '@'));
93 else
94 strcat (locale, ".utf8");
95 printf ("%s\n", locale);
96 setlocale (LC_ALL, locale);
98 nlera = nl_langinfo (ERA);
99 altd = nl_langinfo (ALT_DIGITS);
101 if (!*nlera && !*altd)
102 return;
104 strcpy (era[ecnt].locale, name);
105 nl = nl_langinfo (_DATE_FMT);
106 mbstowcs (nlbuf, nl, 256);
107 era[ecnt].date_fmt = strdup (xfrm_utf (nlbuf, 0));
108 nl = nl_langinfo (D_FMT);
109 mbstowcs (nlbuf, nl, 256);
110 era[ecnt].d_fmt = strdup (xfrm_utf (nlbuf, 0));
111 nl = nl_langinfo (D_T_FMT);
112 mbstowcs (nlbuf, nl, 256);
113 era[ecnt].d_t_fmt = strdup (xfrm_utf (nlbuf, 0));
114 nl = nl_langinfo (T_FMT);
115 mbstowcs (nlbuf, nl, 256);
116 era[ecnt].t_fmt = strdup (xfrm_utf (nlbuf, 0));
117 nl = nl_langinfo (T_FMT_AMPM);
118 mbstowcs (nlbuf, nl, 256);
119 era[ecnt].t_fmt_ampm = strdup (xfrm_utf (nlbuf, 0));
121 era[ecnt].era = *nlera ? xfrm_slist (nlera) : "\0";
122 era[ecnt].alt_digits = *altd ? xfrm_slist (altd) : "\0";
124 nl = nl_langinfo (ERA_D_FMT);
125 mbstowcs (nlbuf, nl, 256);
126 era[ecnt].era_d_fmt = strdup (xfrm_utf (nlbuf, 0));
127 nl = nl_langinfo (ERA_D_T_FMT);
128 mbstowcs (nlbuf, nl, 256);
129 era[ecnt].era_d_t_fmt = strdup (xfrm_utf (nlbuf, 0));
130 nl = nl_langinfo (ERA_T_FMT);
131 mbstowcs (nlbuf, nl, 256);
132 era[ecnt].era_t_fmt = strdup (xfrm_utf (nlbuf, 0));
133 /* Serbian locale rename weirdness */
134 if (!strncmp (era[ecnt].locale, "sr_RS", 5))
136 /* Create additional equivalent entries for the old locale sr_SP. */
137 ++ecnt;
138 memcpy (&era[ecnt], &era[ecnt - 1], sizeof era[ecnt]);
139 era[ecnt].locale[3] = 'S';
140 era[ecnt].locale[4] = 'P';
141 /* Create additional equivalent entry for sr_ME@latin missing in Linux. */
142 if (!strcmp (era[ecnt].locale, "sr_SP@latin"))
144 ++ecnt;
145 memcpy (&era[ecnt], &era[ecnt - 1], sizeof era[ecnt]);
146 era[ecnt].locale[3] = 'M';
147 era[ecnt].locale[4] = 'E';
150 ++ecnt;
154 locale_cmp (const void *a, const void *b)
156 struct lc_era_t *la = (struct lc_era_t *) a;
157 struct lc_era_t *lb = (struct lc_era_t *) b;
158 return strcmp (la->locale, lb->locale);
161 void
162 create_list ()
164 FILE *fp = fopen ("lc_era.h", "w");
165 FILE *pp = popen ("rpm -q glibc", "r");
166 char vers[64];
167 int i;
168 struct tm *tm;
169 time_t tim;
170 char tstr[64];
172 fgets (vers, 64, pp);
173 pclose (pp);
174 if (strchr (vers, '\n'))
175 *strchr (vers, '\n') = '\0';
176 tim = time (NULL);
177 tm = gmtime (&tim);
178 strftime (tstr, 64, "%F", tm);
179 fprintf (fp,
180 "/* This struct of LC_TIME ERA data has been generated by fetching locale\n"
181 " data from a Linux system using %s on %s. */\n"
182 "\n"
183 "struct lc_era_t\n"
184 "{\n"
185 " const char *locale;\n"
186 " const wchar_t *date_fmt;\n"
187 " const wchar_t *d_fmt;\n"
188 " const wchar_t *d_t_fmt;\n"
189 " const wchar_t *t_fmt;\n"
190 " const wchar_t *t_fmt_ampm;\n"
191 " const wchar_t *era;\n"
192 " const wchar_t *era_d_fmt;\n"
193 " const wchar_t *era_d_t_fmt;\n"
194 " const wchar_t *era_t_fmt;\n"
195 " const wchar_t *alt_digits;\n"
196 "};\n"
197 "\n"
198 "static struct lc_era_t lc_era[] =\n"
199 "{\n", vers, tstr);
201 qsort (era, ecnt, sizeof (struct lc_era_t), locale_cmp);
202 for (i = 0; i < ecnt; ++i)
203 fprintf (fp, " { \"%s\", L\"%s\", L\"%s\", L\"%s\", L\"%s\", L\"%s\", "
204 "L\"%s\", L\"%s\", L\"%s\", L\"%s\", L\"%s\" },\n",
205 era[i].locale, era[i].date_fmt,
206 era[i].d_fmt, era[i].d_t_fmt,
207 era[i].t_fmt, era[i].t_fmt_ampm,
208 era[i].era, era[i].era_d_fmt,
209 era[i].era_d_t_fmt, era[i].era_t_fmt,
210 era[i].alt_digits);
211 fputs ("};\n", fp);
212 fclose (fp);
216 main ()
218 char name[32], *c;
219 FILE *pp;
221 pp = popen ("locale -a | grep -a '_' | grep -F -v .", "r");
222 if (!pp)
224 perror ("popen failed");
225 return 1;
227 while (fgets (name, 32, pp))
229 c = strchr (name, '\n');
230 if (c)
231 *c = '\0';
232 read_locale_era (name);
234 pclose (pp);
235 create_list ();
236 return 0;