[tz] [PROPOSED 5/5] Fix bug in zic’s abbreviation algorithm

Paul Eggert eggert at cs.ucla.edu
Wed May 24 05:19:24 UTC 2017


For example, when the context is weekdays, the old, buggy code
rejected both "Sa" and "Su" as ambiguous abbreviations.
* NEWS: Document this.
* zic.c (ciprefix): New function.
(byword): Use it to fix bug in abbreviation determination.
Warn if an unambiguous abbreviation is not portable to
pre-2017c zic.
---
 NEWS  |  7 +++++++
 zic.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 1af7b69..d22d561 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,13 @@ Unreleased, experimental changes
     in civil timekeeping.  (Thanks to Robert Elz and Bradley White for
     noticing glitches in the code that uncovered this problem.)
 
+    zic now allows unambiguous abbreviations like "Sa" and "Su" for
+    weekdays; formerly it rejected them due to a bug.  Conversely, zic
+    no longer considers non-prefixes to be abbreviations; for example,
+    it no longer accepts "lF" as an abbreviation for "lastFriday".
+    Also, zic warns about the undocumented usage with a "last-"
+    prefix, e.g., "last-Fri".
+
     'make BACKWARD=' now suppresses backward-compatibility names
     like 'US/Pacific' that are defined in the 'backward' and
     'pacificnew' files.
diff --git a/zic.c b/zic.c
index f57d346..c2737e1 100644
--- a/zic.c
+++ b/zic.c
@@ -2901,6 +2901,19 @@ itsabbr(register const char *abbr, register const char *word)
 	return true;
 }
 
+/* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case.  */
+
+static bool
+ciprefix(char const *abbr, char const *word)
+{
+  do
+    if (!*abbr)
+      return true;
+  while (lowerit(*abbr++) == lowerit(*word++));
+
+  return false;
+}
+
 static const struct lookup *
 byword(const char *word, const struct lookup *table)
 {
@@ -2909,6 +2922,20 @@ byword(const char *word, const struct lookup *table)
 
 	if (word == NULL || table == NULL)
 		return NULL;
+
+	/* If TABLE is LASTS and the word starts with "last" followed
+	   by a non-'-', skip the "last" and look in WDAY_NAMES instead.
+	   Warn about any usage of the undocumented prefix "last-".  */
+	if (table == lasts && ciprefix("last", word) && word[4]) {
+	  if (word[4] == '-')
+	    warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
+		    word, word + 5);
+	  else {
+	    word += 4;
+	    table = wday_names;
+	  }
+	}
+
 	/*
 	** Look for exact match.
 	*/
@@ -2920,11 +2947,25 @@ byword(const char *word, const struct lookup *table)
 	*/
 	foundlp = NULL;
 	for (lp = table; lp->l_word != NULL; ++lp)
-		if (itsabbr(word, lp->l_word)) {
+		if (ciprefix(word, lp->l_word)) {
 			if (foundlp == NULL)
 				foundlp = lp;
 			else	return NULL;	/* multiple inexact matches */
 		}
+
+	/* Warn about any backward-compatibility issue with pre-2017c zic.  */
+	if (foundlp) {
+	  bool pre_2017c_match = false;
+	  for (lp = table; lp->l_word; lp++)
+	    if (itsabbr(word, lp->l_word)) {
+	      if (pre_2017c_match) {
+		warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
+		break;
+	      }
+	      pre_2017c_match = true;
+	    }
+	}
+
 	return foundlp;
 }
 
-- 
2.9.4



More information about the tz mailing list