[tz] [PROPOSED 6/7] Refactor zic to record input line order
Paul Eggert
eggert at cs.ucla.edu
Thu Oct 20 19:44:05 UTC 2022
Keep track of which file came before which other file internally,
so we always know which input line came first. This doesn’t
affect behavior now, but later changes will need this.
* zic.c (struct rule): Replace r_filename with r_filenum.
All uses changed.
(struct zone): Replace z_filename with z_filenum. All uses changed.
(filenum, rfilenum): New static vars, replacing filename and rfilename.
(main_argv): New static var, for translating filenums to names.
(leapsec): Move decl earlier.
(struct link): Replace l_filename with l_filenum. All uses changed.
(LEAPSEC_FILENUM, COMMAND_LINE_FILENUM): New constants.
(filename): New static function.
(eats, eat, verror, inzone):
Take file numbers as args instead of file names. All uses changed.
Expand file numbers into their names before outputting them.
(main): Initialize main_argv early.
(infile): Also take file number as arg. All uses changed.
No need to fiddle with name, as filename does that for us now.
---
zic.c | 125 +++++++++++++++++++++++++++++++++-------------------------
1 file changed, 71 insertions(+), 54 deletions(-)
diff --git a/zic.c b/zic.c
index f280b31..59fd4e4 100644
--- a/zic.c
+++ b/zic.c
@@ -72,7 +72,7 @@ static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
typedef intmax_t lineno;
struct rule {
- const char * r_filename;
+ int r_filenum;
lineno r_linenum;
const char * r_name;
@@ -108,7 +108,7 @@ enum {
};
struct zone {
- const char * z_filename;
+ int z_filenum;
lineno z_linenum;
const char * z_name;
@@ -158,7 +158,7 @@ static int getfields(char *, char **, int);
static zic_t gethms(const char * string, const char * errstring);
static zic_t getsave(char *, bool *);
static void inexpires(char **, int);
-static void infile(const char * filename);
+static void infile(int, char const *);
static void inleap(char ** fields, int nfields);
static void inlink(char ** fields, int nfields);
static void inrule(char ** fields, int nfields);
@@ -194,7 +194,7 @@ enum { WORK_AROUND_QTBUG_53071 = true };
static int charcnt;
static bool errors;
static bool warnings;
-static const char * filename;
+static int filenum;
static int leapcnt;
static bool leapseen;
static zic_t leapminyear;
@@ -205,9 +205,11 @@ static int max_format_len;
static zic_t max_year;
static zic_t min_year;
static bool noise;
-static const char * rfilename;
+static int rfilenum;
static lineno rlinenum;
static const char * progname;
+static char const * leapsec;
+static char *const * main_argv;
static ptrdiff_t timecnt;
static ptrdiff_t timecnt_alloc;
static int typecnt;
@@ -328,7 +330,7 @@ static ptrdiff_t nzones; /* number of zones */
static ptrdiff_t nzones_alloc;
struct link {
- const char * l_filename;
+ int l_filenum;
lineno l_linenum;
const char * l_target;
const char * l_linkname;
@@ -522,19 +524,36 @@ growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
** Error handling.
*/
+/* In most of the code, an input file name is represented by its index
+ into the main argument vector, except that LEAPSEC_FILENUM stands
+ for leapsec and COMMAND_LINE_FILENUM stands for the command line. */
+enum { LEAPSEC_FILENUM = -2, COMMAND_LINE_FILENUM = -1 };
+
+/* Return the name of the Ith input file, for diagnostics. */
+static char const *
+filename(int i)
+{
+ if (i == COMMAND_LINE_FILENUM)
+ return _("command line");
+ else {
+ char const *fname = i == LEAPSEC_FILENUM ? leapsec : main_argv[i];
+ return strcmp(fname, "-") == 0 ? _("standard input") : fname;
+ }
+}
+
static void
-eats(char const *name, lineno num, char const *rname, lineno rnum)
+eats(int fnum, lineno num, int rfnum, lineno rnum)
{
- filename = name;
+ filenum = fnum;
linenum = num;
- rfilename = rname;
+ rfilenum = rfnum;
rlinenum = rnum;
}
static void
-eat(char const *name, lineno num)
+eat(int fnum, lineno num)
{
- eats(name, num, NULL, -1);
+ eats(fnum, num, 0, -1);
}
static void ATTRIBUTE_FORMAT((printf, 1, 0))
@@ -545,12 +564,13 @@ verror(const char *const string, va_list args)
** zic ... 2>&1 | error -t "*" -v
** on BSD systems.
*/
- if (filename)
- fprintf(stderr, _("\"%s\", line %"PRIdMAX": "), filename, linenum);
+ if (filenum)
+ fprintf(stderr, _("\"%s\", line %"PRIdMAX": "),
+ filename(filenum), linenum);
vfprintf(stderr, string, args);
- if (rfilename != NULL)
+ if (rfilenum)
fprintf(stderr, _(" (rule from \"%s\", line %"PRIdMAX")"),
- rfilename, rlinenum);
+ filename(rfilenum), rlinenum);
fprintf(stderr, "\n");
}
@@ -757,7 +777,6 @@ redundant_time_option(char *opt)
static const char * psxrules;
static const char * lcltime;
static const char * directory;
-static const char * leapsec;
static const char * tzdefault;
/* -1 if the TZif output file should be slim, 0 if default, 1 if the
@@ -792,6 +811,7 @@ main(int argc, char **argv)
# endif /* defined TEXTDOMAINDIR */
textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */
+ main_argv = argv;
progname = argv[0];
if (TYPE_BIT(zic_t) < 64) {
fprintf(stderr, "%s: %s\n", progname,
@@ -926,12 +946,12 @@ _("%s: invalid time range: %s\n"),
tzdefault = TZDEFAULT;
if (optind < argc && leapsec != NULL) {
- infile(leapsec);
+ infile(LEAPSEC_FILENUM, leapsec);
adjleap();
}
for (k = optind; k < argc; k++)
- infile(argv[k]);
+ infile(k, argv[k]);
if (errors)
return EXIT_FAILURE;
associate();
@@ -949,7 +969,7 @@ _("%s: invalid time range: %s\n"),
** Make links.
*/
for (i = 0; i < nlinks; ++i) {
- eat(links[i].l_filename, links[i].l_linenum);
+ eat(links[i].l_filenum, links[i].l_linenum);
dolink(links[i].l_target, links[i].l_linkname, false);
if (noise)
for (j = 0; j < nlinks; ++j)
@@ -961,11 +981,11 @@ _("%s: invalid time range: %s\n"),
}
}
if (lcltime != NULL) {
- eat(_("command line"), 1);
+ eat(COMMAND_LINE_FILENUM, 1);
dolink(lcltime, tzdefault, true);
}
if (psxrules != NULL) {
- eat(_("command line"), 1);
+ eat(COMMAND_LINE_FILENUM, 1);
dolink(psxrules, TZDEFRULES, true);
}
if (warnings && (ferror(stderr) || fclose(stderr) != 0))
@@ -1378,22 +1398,20 @@ associate(void)
if (strcmp(rules[i].r_name,
rules[i + 1].r_name) != 0)
continue;
- if (strcmp(rules[i].r_filename,
- rules[i + 1].r_filename) == 0)
+ if (rules[i].r_filenum == rules[i + 1].r_filenum)
continue;
- eat(rules[i].r_filename, rules[i].r_linenum);
+ eat(rules[i].r_filenum, rules[i].r_linenum);
warning(_("same rule name in multiple files"));
- eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
+ eat(rules[i + 1].r_filenum, rules[i + 1].r_linenum);
warning(_("same rule name in multiple files"));
for (j = i + 2; j < nrules; ++j) {
if (strcmp(rules[i].r_name,
rules[j].r_name) != 0)
break;
- if (strcmp(rules[i].r_filename,
- rules[j].r_filename) == 0)
+ if (rules[i].r_filenum == rules[j].r_filenum)
continue;
- if (strcmp(rules[i + 1].r_filename,
- rules[j].r_filename) == 0)
+ if (rules[i + 1].r_filenum
+ == rules[j].r_filenum)
continue;
break;
}
@@ -1424,7 +1442,7 @@ associate(void)
/*
** Maybe we have a local standard time offset.
*/
- eat(zp->z_filename, zp->z_linenum);
+ eat(zp->z_filenum, zp->z_linenum);
zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
/*
** Note, though, that if there's no rule,
@@ -1473,7 +1491,7 @@ inputline(FILE *fp, char *buf, ptrdiff_t bufsize)
}
static void
-infile(const char *name)
+infile(int fnum, char const *name)
{
register FILE * fp;
register const struct lookup * lp;
@@ -1481,7 +1499,6 @@ infile(const char *name)
register lineno num;
if (strcmp(name, "-") == 0) {
- name = _("standard input");
fp = stdin;
} else if ((fp = fopen(name, "r")) == NULL) {
const char *e = strerror(errno);
@@ -1496,7 +1513,7 @@ infile(const char *name)
char buf[_POSIX2_LINE_MAX];
int nfields;
char *fields[MAX_FIELDS];
- eat(name, num);
+ eat(fnum, num);
linelen = inputline(fp, buf, sizeof buf);
if (linelen < 0)
break;
@@ -1508,7 +1525,7 @@ infile(const char *name)
wantcont = inzcont(fields, nfields);
} else {
struct lookup const *line_codes
- = name == leapsec ? leap_line_codes : zi_line_codes;
+ = fnum < 0 ? leap_line_codes : zi_line_codes;
lp = byword(fields[0], line_codes);
if (lp == NULL)
error(_("input line of unknown type"));
@@ -1536,7 +1553,7 @@ infile(const char *name)
}
}
}
- close_file(fp, NULL, filename, NULL);
+ close_file(fp, NULL, filename(fnum), NULL);
if (wantcont)
error(_("expected continuation line not found"));
}
@@ -1639,7 +1656,7 @@ inrule(char **fields, int nfields)
error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
return;
}
- r.r_filename = filename;
+ r.r_filenum = filenum;
r.r_linenum = linenum;
r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
if (!rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR],
@@ -1680,9 +1697,9 @@ _("\"Zone %s\" line and -p option are mutually exclusive"),
strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
error(_("duplicate zone name %s"
" (file \"%s\", line %"PRIdMAX")"),
- fields[ZF_NAME],
- zones[i].z_filename,
- zones[i].z_linenum);
+ fields[ZF_NAME],
+ filename(zones[i].z_filenum),
+ zones[i].z_linenum);
return false;
}
return inzsub(fields, nfields, false);
@@ -1729,7 +1746,7 @@ inzsub(char **fields, int nfields, bool iscont)
i_untilday = ZF_TILDAY;
i_untiltime = ZF_TILTIME;
}
- z.z_filename = filename;
+ z.z_filenum = filenum;
z.z_linenum = linenum;
z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
if ((cp = strchr(fields[i_format], '%')) != 0) {
@@ -1745,7 +1762,7 @@ inzsub(char **fields, int nfields, bool iscont)
max_format_len = format_len;
hasuntil = nfields > i_untilyear;
if (hasuntil) {
- z.z_untilrule.r_filename = filename;
+ z.z_untilrule.r_filenum = filenum;
z.z_untilrule.r_linenum = linenum;
if (!rulesub(
&z.z_untilrule,
@@ -1914,7 +1931,7 @@ inlink(char **fields, int nfields)
}
if (! namecheck(fields[LF_LINKNAME]))
return;
- l.l_filename = filename;
+ l.l_filenum = filenum;
l.l_linenum = linenum;
l.l_target = ecpyalloc(fields[LF_TARGET]);
l.l_linkname = ecpyalloc(fields[LF_LINKNAME]);
@@ -3052,7 +3069,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
INITIALIZE(prevktime);
if (useuntil && zp->z_untiltime <= min_time)
continue;
- eat(zp->z_filename, zp->z_linenum);
+ eat(zp->z_filenum, zp->z_linenum);
*startbuf = '\0';
if (zp->z_nrules == 0) {
int type;
@@ -3080,8 +3097,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
zic_t one = 1;
zic_t y2038_boundary = one << 31;
struct rule *rp = &zp->z_rules[j];
- eats(zp->z_filename, zp->z_linenum,
- rp->r_filename, rp->r_linenum);
+ eats(zp->z_filenum, zp->z_linenum,
+ rp->r_filenum, rp->r_linenum);
rp->r_todo = year >= rp->r_loyear &&
year <= rp->r_hiyear;
if (rp->r_todo) {
@@ -3122,8 +3139,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
struct rule *r = &zp->z_rules[j];
if (!r->r_todo)
continue;
- eats(zp->z_filename, zp->z_linenum,
- r->r_filename, r->r_linenum);
+ eats(zp->z_filenum, zp->z_linenum,
+ r->r_filenum, r->r_linenum);
offset = r->r_todisut ? 0 : stdoff;
if (!r->r_todisstd)
offset = oadd(offset, save);
@@ -3138,12 +3155,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
} else if (jtime == ktime) {
char const *dup_rules_msg =
_("two rules for same instant");
- eats(zp->z_filename, zp->z_linenum,
- r->r_filename, r->r_linenum);
+ eats(zp->z_filenum, zp->z_linenum,
+ r->r_filenum, r->r_linenum);
warning("%s", dup_rules_msg);
r = &zp->z_rules[k];
- eats(zp->z_filename, zp->z_linenum,
- r->r_filename, r->r_linenum);
+ eats(zp->z_filenum, zp->z_linenum,
+ r->r_filenum, r->r_linenum);
error("%s", dup_rules_msg);
}
}
@@ -3185,8 +3202,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
false);
}
}
- eats(zp->z_filename, zp->z_linenum,
- rp->r_filename, rp->r_linenum);
+ eats(zp->z_filenum, zp->z_linenum,
+ rp->r_filenum, rp->r_linenum);
doabbr(ab, zp, rp->r_abbrvar,
rp->r_isdst, rp->r_save, false);
offset = oadd(zp->z_stdoff, rp->r_save);
@@ -3215,7 +3232,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
if (*startbuf == '\0' && zp->z_format)
doabbr(startbuf, zp, disable_percent_s,
isdst, save, false);
- eat(zp->z_filename, zp->z_linenum);
+ eat(zp->z_filenum, zp->z_linenum);
if (*startbuf == '\0')
error(_("can't determine time zone abbreviation to use just after until time"));
else {
--
2.37.3
More information about the tz
mailing list