tzsetup: adopt zone1970.tab changes

- assumption that single-zone countries do not have description
  is no longer correct; do not try to optimize this case as it's
  only going to make the code more confusing and we now have menus
  with a single zone selection because of this
- remove the single-country continent short cut, it also only serves
  to confuse users as we now have such a continent
- instead add a single-zone contry short cut (see above), now all
  single-zone countries fall here
- use the #@ continent overrides that zone1970.tab introduces (this is
  visible at least fixing Iceland being currently listed under Africa)
- add Arctic Ocean "continent" coming only from the overrides at the
  moment
- update baseline with the changes

Reviewed by:	bapt, philip
Differential Revision:	https://reviews.freebsd.org/D39606
This commit is contained in:
Yuri Pankov 2023-04-27 19:31:48 +02:00
parent ec45f952a2
commit cfd0217aa9
2 changed files with 167 additions and 163 deletions

View file

@ -19,10 +19,10 @@ AQ:Antarctica
Antarctica:Antarctica/Palmer
Antarctica:Antarctica/Rothera
Antarctica:Antarctica/Troll
Asia:Asia/Urumqi
Pacific:Pacific/Auckland
Pacific:Pacific/Port_Moresby
Asia:Asia/Riyadh
Antarctica:Asia/Urumqi
Antarctica:Pacific/Auckland
Antarctica:Pacific/Port_Moresby
Antarctica:Asia/Riyadh
AG:Antigua and Barbuda
America:America/Puerto_Rico
AR:Argentina
@ -159,13 +159,13 @@ CN:China
Asia:Asia/Shanghai
Asia:Asia/Urumqi
CX:Christmas Island
Asia:Asia/Bangkok
Indian:Asia/Bangkok
CC:Cocos (Keeling) Islands
Asia:Asia/Yangon
Indian:Asia/Yangon
CO:Colombia
America:America/Bogota
KM:Comoros
Africa:Africa/Nairobi
Indian:Africa/Nairobi
CG:Congo
Africa:Africa/Lagos
CD:Congo, Democratic Republic of the
@ -280,7 +280,7 @@ HK:Hong Kong
HU:Hungary
Europe:Europe/Budapest
IS:Iceland
Africa:Africa/Abidjan
Atlantic:Africa/Abidjan
IN:India
Asia:Asia/Kolkata
ID:Indonesia
@ -353,7 +353,7 @@ MO:Macao
MK:Macedonia (the former Yugoslav Republic of)
Europe:Europe/Belgrade
MG:Madagascar
Africa:Africa/Nairobi
Indian:Africa/Nairobi
MW:Malawi
Africa:Africa/Maputo
MY:Malaysia
@ -375,7 +375,7 @@ MR:Mauritania
MU:Mauritius
Indian:Indian/Mauritius
YT:Mayotte
Africa:Africa/Nairobi
Indian:Africa/Nairobi
MX:Mexico
America:America/Mexico_City
America:America/Cancun
@ -507,7 +507,7 @@ RE:Réunion
BL:Saint Barthélemy
America:America/Puerto_Rico
SH:Saint Helena Ascension and Tristan da Cunha
Africa:Africa/Abidjan
Atlantic:Africa/Abidjan
KN:Saint Kitts and Nevis
America:America/Puerto_Rico
LC:Saint Lucia
@ -563,7 +563,7 @@ SD:Sudan
SR:Suriname
America:America/Paramaribo
SJ:Svalbard and Jan Mayen
Europe:Europe/Berlin
Arctic:Europe/Berlin
SE:Sweden
Europe:Europe/Berlin
CH:Switzerland

View file

@ -157,8 +157,7 @@ static int usedialog = 1;
static int confirm_zone(const char *filename);
static int continent_country_menu(dialogMenuItem *);
static int set_zone_multi(dialogMenuItem *);
static int set_zone_whole_country(dialogMenuItem *);
static int set_zone(dialogMenuItem *);
static int set_zone_menu(dialogMenuItem *);
static int set_zone_utc(void);
@ -167,7 +166,7 @@ struct continent {
int nitems;
};
static struct continent africa, america, antarctica, asia, atlantic;
static struct continent africa, america, antarctica, arctic, asia, atlantic;
static struct continent australia, europe, indian, pacific, utc;
static struct continent_names {
@ -177,6 +176,7 @@ static struct continent_names {
{ "Africa", &africa },
{ "America", &america },
{ "Antarctica", &antarctica },
{ "Arctic", &arctic },
{ "Asia", &asia },
{ "Atlantic", &atlantic },
{ "Australia", &australia },
@ -187,26 +187,27 @@ static struct continent_names {
};
static struct continent_items {
char prompt[2];
char prompt[3];
char title[30];
} continent_items[] = {
{ "1", "Africa" },
{ "2", "America -- North and South" },
{ "3", "Antarctica" },
{ "4", "Asia" },
{ "5", "Atlantic Ocean" },
{ "6", "Australia" },
{ "7", "Europe" },
{ "8", "Indian Ocean" },
{ "9", "Pacific Ocean" },
{ "0", "UTC" }
{ "4", "Arctic Ocean" },
{ "5", "Asia" },
{ "6", "Atlantic Ocean" },
{ "7", "Australia" },
{ "8", "Europe" },
{ "9", "Indian Ocean" },
{ "10", "Pacific Ocean" },
{ "11", "UTC" }
};
#define NCONTINENTS \
(int)((sizeof(continent_items)) / (sizeof(continent_items[0])))
static dialogMenuItem continents[NCONTINENTS];
#define OCEANP(x) ((x) == 4 || (x) == 7 || (x) == 8)
#define OCEANP(x) ((x) == 3 || (x) == 5 || (x) == 8 || (x) == 9)
static int
continent_country_menu(dialogMenuItem *continent)
@ -219,10 +220,6 @@ continent_country_menu(dialogMenuItem *continent)
if (strcmp(continent->title, "UTC") == 0)
return (set_zone_utc());
/* Short cut -- if there's only one country, don't post a menu. */
if (contp->nitems == 1)
return (contp->menu[0].fire(&contp->menu[0]));
/* It's amazing how much good grammar really matters... */
if (!isocean) {
snprintf(title, sizeof(title), "Countries in %s",
@ -239,14 +236,30 @@ continent_country_menu(dialogMenuItem *continent)
}
static struct continent *
find_continent(const char *name)
find_continent(int lineno, const char *name)
{
char *cname, *cp;
int i;
/*
* Both normal (the ones in zone filename, e.g. Europe/Andorra) and
* override (e.g. Atlantic/) entries should contain '/'.
*/
cp = strdup(name);
if (cp == NULL)
err(1, "strdup");
cname = strsep(&cp, "/");
if (cp == NULL)
errx(1, "%s:%d: invalid entry `%s'", path_zonetab, lineno,
cname);
for (i = 0; i < NCONTINENTS; i++)
if (strcmp(name, continent_names[i].name) == 0)
if (strcmp(cname, continent_names[i].name) == 0) {
free(cname);
return (continent_names[i].continent);
return (0);
}
errx(1, "%s:%d: continent `%s' unknown", path_zonetab, lineno, cname);
}
static const char *
@ -264,10 +277,9 @@ struct country {
char *name;
char *tlc;
int nzones;
char *filename; /* use iff nzones < 0 */
struct continent *continent; /* use iff nzones < 0 */
TAILQ_HEAD(, zone) zones; /* use iff nzones > 0 */
dialogMenuItem *submenu; /* use iff nzones > 0 */
struct continent *override; /* continent override */
TAILQ_HEAD(, zone) zones;
dialogMenuItem *submenu;
};
struct zone {
@ -346,56 +358,50 @@ read_iso3166_table(void)
fclose(fp);
}
static void
add_zone_to_country(int lineno, const char *tlc, const char *descr,
const char *file, struct continent *cont)
static struct country *
find_country(int lineno, const char *tlc)
{
struct zone *zp;
struct country *cp;
if (tlc[0] < 'A' || tlc[0] > 'Z' || tlc[1] < 'A' || tlc[1] > 'Z')
if (strlen(tlc) != 2 ||
tlc[0] < 'A' || tlc[0] > 'Z' || tlc[1] < 'A' || tlc[1] > 'Z')
errx(1, "%s:%d: country code `%s' invalid", path_zonetab,
lineno, tlc);
cp = &countries[CODE2INT(tlc)];
if (cp->name == 0)
if (cp->name == NULL)
errx(1, "%s:%d: country code `%s' unknown", path_zonetab,
lineno, tlc);
if (descr) {
if (cp->nzones < 0)
errx(1, "%s:%d: conflicting zone definition",
path_zonetab, lineno);
return (cp);
}
zp = malloc(sizeof(*zp));
if (zp == NULL)
errx(1, "malloc(%zu)", sizeof(*zp));
static void
add_zone_to_country(int lineno, struct country *cp, const char *descr,
const char *file, struct continent *cont)
{
struct zone *zp;
if (cp->nzones == 0)
TAILQ_INIT(&cp->zones);
zp = malloc(sizeof(*zp));
if (zp == NULL)
errx(1, "malloc(%zu)", sizeof(*zp));
if (cp->nzones == 0)
TAILQ_INIT(&cp->zones);
if (descr != NULL) {
zp->descr = strdup(descr);
if (zp->descr == NULL)
errx(1, "malloc failed");
zp->filename = strdup(file);
if (zp->filename == NULL)
errx(1, "malloc failed");
zp->continent = cont;
TAILQ_INSERT_TAIL(&cp->zones, zp, link);
cp->nzones++;
} else {
if (cp->nzones > 0)
errx(1, "%s:%d: zone must have description",
path_zonetab, lineno);
if (cp->nzones < 0)
errx(1, "%s:%d: zone multiply defined",
path_zonetab, lineno);
cp->nzones = -1;
cp->filename = strdup(file);
if (cp->filename == NULL)
errx(1, "malloc failed");
cp->continent = cont;
zp->descr = NULL;
}
zp->filename = strdup(file);
if (zp->filename == NULL)
errx(1, "malloc failed");
zp->continent = cp->override != NULL ? cp->override : cont;
TAILQ_INSERT_TAIL(&cp->zones, zp, link);
cp->nzones++;
}
/*
@ -432,54 +438,79 @@ sort_countries(void)
static void
read_zones(void)
{
char contbuf[16];
FILE *fp;
struct continent *cont;
size_t len, contlen;
char *line, *country_list, *tlc, *file, *descr, *p;
struct country *cp;
size_t len;
char *line, *country_list, *tlc, *file, *descr;
int lineno;
bool pass1;
fp = fopen(path_zonetab, "r");
if (!fp)
err(1, "%s", path_zonetab);
lineno = 0;
pass1 = true;
again:
lineno = 0;
while ((line = fgetln(fp, &len)) != NULL) {
lineno++;
if (line[len - 1] != '\n')
errx(1, "%s:%d: invalid format", path_zonetab, lineno);
line[len - 1] = '\0';
if (line[0] == '#')
continue;
country_list = strsep(&line, "\t");
/* coord = */ strsep(&line, "\t"); /* Unused */
file = strsep(&line, "\t");
/* get continent portion from continent/country */
p = strchr(file, '/');
if (p == NULL)
errx(1, "%s:%d: invalid zone name `%s'", path_zonetab,
lineno, file);
contlen = p - file + 1; /* trailing nul */
if (contlen > sizeof(contbuf))
errx(1, "%s:%d: continent name in zone name `%s' too long",
path_zonetab, lineno, file);
strlcpy(contbuf, file, contlen);
cont = find_continent(contbuf);
if (!cont)
errx(1, "%s:%d: invalid region `%s'", path_zonetab,
lineno, contbuf);
if (pass1) {
/*
* First pass: collect overrides, only looking for
* single continent ones for the moment.
*
* zone1970.tab introduced continent overrides in the
* following format:
*
* #@TLC[,TLC...]<tab>CONTINENT/[,CONTINENT/...]
*/
if (strncmp(line, "#@", strlen("#@")) != 0)
continue;
line += 2;
country_list = strsep(&line, "\t");
/* Skip multi-continent overrides */
if (strchr(line, ',') != NULL)
continue;
cont = find_continent(lineno, line);
/* Parse and store overrides */
while (country_list != NULL) {
tlc = strsep(&country_list, ",");
cp = find_country(lineno, tlc);
cp->override = cont;
}
} else {
/* Second pass: parse actual data */
if (line[0] == '#')
continue;
descr = (line != NULL && *line != '\0') ? line : NULL;
country_list = strsep(&line, "\t");
/* coord = */ strsep(&line, "\t"); /* Unused */
file = strsep(&line, "\t");
cont = find_continent(lineno, file);
descr = (line != NULL && *line != '\0') ? line : NULL;
while (country_list != NULL) {
tlc = strsep(&country_list, ",");
if (strlen(tlc) != 2)
errx(1, "%s:%d: invalid country code `%s'",
path_zonetab, lineno, tlc);
add_zone_to_country(lineno, tlc, descr, file, cont);
while (country_list != NULL) {
tlc = strsep(&country_list, ",");
cp = find_country(lineno, tlc);
add_zone_to_country(lineno, cp, descr, file,
cont);
}
}
}
if (pass1) {
pass1 = false;
errno = 0;
rewind(fp);
if (errno != 0)
err(1, "failed to rewind %s", path_zonetab);
goto again;
}
fclose(fp);
}
@ -492,14 +523,9 @@ dump_zonetab(void)
for (cp = countries; cp->name != NULL; cp++) {
printf("%s:%s\n", cp->tlc, cp->name);
if (cp->nzones < 0) {
cont = find_continent_name(cp->continent);
printf(" %s:%s\n", cont, cp->filename);
} else {
TAILQ_FOREACH(zp, &cp->zones, link) {
cont = find_continent_name(zp->continent);
printf(" %s:%s\n", cont, zp->filename);
}
TAILQ_FOREACH(zp, &cp->zones, link) {
cont = find_continent_name(zp->continent);
printf(" %s:%s\n", cont, zp->filename);
}
}
}
@ -522,18 +548,14 @@ make_menus(void)
for (cp = countries; cp->name; cp++) {
if (cp->nzones == 0)
continue;
if (cp->nzones < 0) {
cp->continent->nitems++;
} else {
TAILQ_FOREACH(zp, &cp->zones, link) {
cont = zp->continent;
for (zp2 = TAILQ_FIRST(&cp->zones);
zp2->continent != cont;
zp2 = TAILQ_NEXT(zp2, link))
;
if (zp2 == zp)
zp->continent->nitems++;
}
TAILQ_FOREACH(zp, &cp->zones, link) {
cont = zp->continent;
for (zp2 = TAILQ_FIRST(&cp->zones);
zp2->continent != cont;
zp2 = TAILQ_NEXT(zp2, link))
;
if (zp2 == zp)
zp->continent->nitems++;
}
}
@ -564,41 +586,32 @@ make_menus(void)
for (cp = countries; cp->name; cp++) {
if (cp->nzones == 0)
continue;
if (cp->nzones < 0) {
dmi = &cp->continent->menu[cp->continent->nitems];
cp->submenu = malloc(cp->nzones * sizeof(*dmi));
if (cp->submenu == 0)
errx(1, "malloc for submenu");
cp->nzones = 0;
TAILQ_FOREACH(zp, &cp->zones, link) {
cont = zp->continent;
dmi = &cp->submenu[cp->nzones];
memset(dmi, 0, sizeof(*dmi));
asprintf(&dmi->prompt, "%d", ++cp->continent->nitems);
asprintf(&dmi->prompt, "%d", ++cp->nzones);
dmi->title = zp->descr;
dmi->fire = set_zone;
dmi->data = zp;
for (zp2 = TAILQ_FIRST(&cp->zones);
zp2->continent != cont;
zp2 = TAILQ_NEXT(zp2, link))
;
if (zp2 != zp)
continue;
dmi = &cont->menu[cont->nitems];
memset(dmi, 0, sizeof(*dmi));
asprintf(&dmi->prompt, "%d", ++cont->nitems);
dmi->title = cp->name;
dmi->fire = set_zone_whole_country;
dmi->fire = set_zone_menu;
dmi->data = cp;
} else {
cp->submenu = malloc(cp->nzones * sizeof(*dmi));
if (cp->submenu == 0)
errx(1, "malloc for submenu");
cp->nzones = 0;
TAILQ_FOREACH(zp, &cp->zones, link) {
cont = zp->continent;
dmi = &cp->submenu[cp->nzones];
memset(dmi, 0, sizeof(*dmi));
asprintf(&dmi->prompt, "%d", ++cp->nzones);
dmi->title = zp->descr;
dmi->fire = set_zone_multi;
dmi->data = zp;
for (zp2 = TAILQ_FIRST(&cp->zones);
zp2->continent != cont;
zp2 = TAILQ_NEXT(zp2, link))
;
if (zp2 != zp)
continue;
dmi = &cont->menu[cont->nitems];
memset(dmi, 0, sizeof(*dmi));
asprintf(&dmi->prompt, "%d", ++cont->nitems);
dmi->title = cp->name;
dmi->fire = set_zone_menu;
dmi->data = cp;
}
}
}
}
@ -610,6 +623,10 @@ set_zone_menu(dialogMenuItem *dmi)
struct country *cp = dmi->data;
int rv;
/* Short cut -- if there's only one zone, don't post a menu. */
if (cp->nzones == 1)
return (cp->submenu[0].fire(&cp->submenu[0]));
snprintf(title, sizeof(title), "%s Time Zones", cp->name);
snprintf(prompt, sizeof(prompt),
"Select a zone which observes the same time as your locality.");
@ -646,7 +663,7 @@ confirm_zone(const char *filename)
}
static int
set_zone_multi(dialogMenuItem *dmi)
set_zone(dialogMenuItem *dmi)
{
struct zone *zp = dmi->data;
int rv;
@ -658,19 +675,6 @@ set_zone_multi(dialogMenuItem *dmi)
return (rv);
}
static int
set_zone_whole_country(dialogMenuItem *dmi)
{
struct country *cp = dmi->data;
int rv;
if (!confirm_zone(cp->filename))
return (DITEM_FAILURE | DITEM_RECREATE);
rv = install_zoneinfo(cp->filename);
return (rv);
}
#endif
static void message_zoneinfo_file(const char *title, char *prompt)