The branch main has been updated by yuripv:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=cfd0217aa9a929ac625db90828a56dfe4dc1dbd2

commit cfd0217aa9a929ac625db90828a56dfe4dc1dbd2
Author:     Yuri Pankov <[email protected]>
AuthorDate: 2023-04-27 17:31:48 +0000
Commit:     Yuri Pankov <[email protected]>
CommitDate: 2023-04-27 17:31:48 +0000

    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
---
 usr.sbin/tzsetup/baseline  |  24 ++--
 usr.sbin/tzsetup/tzsetup.c | 310 +++++++++++++++++++++++----------------------
 2 files changed, 169 insertions(+), 165 deletions(-)

diff --git a/usr.sbin/tzsetup/baseline b/usr.sbin/tzsetup/baseline
index 79a7f2a869b6..de9b5f638d09 100644
--- a/usr.sbin/tzsetup/baseline
+++ b/usr.sbin/tzsetup/baseline
@@ -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
diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c
index b4d906d90b7e..a20c0730c48e 100644
--- a/usr.sbin/tzsetup/tzsetup.c
+++ b/usr.sbin/tzsetup/tzsetup.c
@@ -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);
+}
+
+static void
+add_zone_to_country(int lineno, struct country *cp, const char *descr,
+    const char *file, struct continent *cont)
+{
+       struct zone     *zp;
 
-               zp = malloc(sizeof(*zp));
-               if (zp == NULL)
-                       errx(1, "malloc(%zu)", sizeof(*zp));
+       zp = malloc(sizeof(*zp));
+       if (zp == NULL)
+               errx(1, "malloc(%zu)", sizeof(*zp));
 
-               if (cp->nzones == 0)
-                       TAILQ_INIT(&cp->zones);
+       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);
-
-               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);
+               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;
+
+                       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, ",");
+                               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->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", ++cp->continent->nitems);
+                       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)

Reply via email to