1
0
mirror of https://frontier.innolan.net/rainlance/amiga-tz.git synced 2026-05-07 07:58:06 +00:00

Add optional meta-information to version-3 format.

* Makefile (ZFLAGS): Add a comment about how to enable meta-info.
* tzfile.5: Describe meta-information.
* zic.8: Document new options -n and -o, which cause zic to
generate meta-info.
* zic.c: Include <stddef.h>, for ptrdiff_t.
(genoption, genoptions, genname): New static vars.
(usage): Summarize new options.
(addgenoption, writevalue): New function.
(main, writezone): Add support for new options.
This commit is contained in:
Paul Eggert
2013-09-09 17:16:37 -07:00
parent 8ee0fbebc6
commit d7680ffd3d
4 changed files with 101 additions and 2 deletions

View File

@@ -250,6 +250,9 @@ LDFLAGS= $(LFLAGS)
zic= ./zic
ZIC= $(zic) $(ZFLAGS)
# Uncomment this to put name and version info into zic output files.
#ZFLAGS= -n -o version='$(VERSION)'
# The name of a Posix-compliant `awk' on your system.
AWK= awk

View File

@@ -154,6 +154,19 @@ First, the hours part of its transition times may be signed and range from
from 0 through 24. Second, DST is in effect all year if it starts
January 1 at 00:00 and ends December 31 at 24:00 plus the difference
between daylight saving and standard time.
.PP
Also, for version-3-format time zone files, the version-2 header and
data are optionally followed by a section containing auxiliary
meta-information that is not needed to process time stamps. This
section, if present, consists of the four magic bytes "=TZ\en"
followed by zero or more newline-terminated byte strings, each
containing a name-value pair separated by "=". Names consist of ASCII
letters, digits and underscores, and start with a letter; duplicate
names are not allowed. Two common names are "name", the Zone name for
the data, and "version", the version number. Values consist of any
bytes except NUL, newline, and backslash; however, newline and
backslash can represented via the two-byte strings "\en" and "\e\e"
respectively.
.SH SEE ALSO
newctime(3), newtzset(3)
.\" This file is in the public domain, so clarified as of

14
zic.8
View File

@@ -15,6 +15,11 @@ zic \- time zone compiler
.B \-l
.I localtime
] [
.B \-n
] [
.B \-o
.IB name = value
] [
.B \-p
.I posixrules
] [
@@ -62,6 +67,15 @@ will act as if the input contained a link line of the form
.ti +.5i
Link \fItimezone\fP localtime
.TP
.B "\-n"
Store each zone's name into its generated file, as meta-information
with the name "name" and value the zone's name.
.TP
.BI "\-o " name = value
Store the given name-value pair into the generated file, as
meta-information. This option can be repeated, once for each distinct
name.
.TP
.BI "\-p " timezone
Use the given time zone's rules when handling POSIX-format
time zone environment variables.

73
zic.c
View File

@@ -9,6 +9,7 @@
#include "tzfile.h"
#include <stdarg.h>
#include <stddef.h>
#define ZIC_VERSION '3'
@@ -140,6 +141,9 @@ static int yearistype(int year, const char * type);
static int charcnt;
static int errors;
static const char * filename;
static const char ** genoption;
static int genoptions;
static int genname;
static int leapcnt;
static int leapseen;
static zic_t leapminyear;
@@ -432,7 +436,8 @@ static _Noreturn void
usage(FILE *stream, int status)
{
(void) fprintf(stream, _("%s: usage is %s \
[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
[ --version ] [ --help ] [ -v ] [ -l localtime ]\\\n\
\t[ -n ] [ -o name=value ]... [ -p posixrules ] \\\n\
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
\n\
Report bugs to %s.\n"),
@@ -446,6 +451,31 @@ static const char * directory;
static const char * leapsec;
static const char * yitcommand;
static int
addgenoption(char const *option)
{
register char const *o = option;
register ptrdiff_t namelen;
register int i;
if (! (isascii (*o) && isalpha(*o)))
return 0;
while (*++o != '=')
if (! (isascii (*o) && (isalnum(*o) || *o == '_')))
return 0;
namelen = o - option;
if (INT_MAX < namelen)
return 0; /* fprintf won't work. */
if (namelen == sizeof "name" - 1
&& memcmp(option, "name", namelen) == 0)
return 0;
for (i = 0; i < genoptions; i++)
if (strncmp(genoption[i], option, namelen + 1) == 0)
return 0;
genoption = erealloc(genoption, (genoptions + 1) * sizeof *genoption);
genoption[genoptions++] = option;
return 1;
}
int
main(int argc, char **argv)
{
@@ -476,7 +506,7 @@ main(int argc, char **argv)
} else if (strcmp(argv[i], "--help") == 0) {
usage(stdout, EXIT_SUCCESS);
}
while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
while ((c = getopt(argc, argv, "d:l:p:L:no:vsy:")) != EOF && c != -1)
switch (c) {
default:
usage(stderr, EXIT_FAILURE);
@@ -500,6 +530,17 @@ _("%s: More than one -l option specified\n"),
exit(EXIT_FAILURE);
}
break;
case 'n':
genname = TRUE;
break;
case 'o':
if (!addgenoption(optarg)) {
fprintf(stderr,
_("%s: %s: invalid -o option\n"),
progname, optarg);
exit(EXIT_FAILURE);
}
break;
case 'p':
if (psxrules == NULL)
psxrules = optarg;
@@ -1385,6 +1426,22 @@ is32(const zic_t x)
return INT32_MIN <= x && x <= INT32_MAX;
}
static void
writevalue(FILE *fp, char const *v)
{
fputc('=', fp);
for (; *v; v++)
if (*v == '\n')
fprintf(fp, "\\n");
else if (*v == '\\')
fprintf(fp, "\\\\");
else
fputc(*v, fp);
fputc('\n', fp);
}
static void
writezone(const char *const name, const char *const string)
{
@@ -1708,6 +1765,18 @@ writezone(const char *const name, const char *const string)
(void) putc(ttisgmts[i], fp);
}
(void) fprintf(fp, "\n%s\n", string);
if (genname || genoptions)
fprintf(fp, "=TZ\n");
if (genname) {
fprintf(fp, "name");
writevalue(fp, name);
}
for (i = 0; i < genoptions; i++) {
register char const *v = genoption[i];
register int namelen = strchr(v, '=') - v;
fprintf(fp, "%.*s", namelen, v);
writevalue(fp, v + namelen + 1);
}
if (ferror(fp) || fclose(fp)) {
(void) fprintf(stderr, _("%s: Error writing %s\n"),
progname, fullname);