[tz] [PATCH 1/2] * zic.c: Prefer <stdarg.h> to allocating memory by hand.
Paul Eggert
eggert at cs.ucla.edu
Mon Sep 9 06:17:22 UTC 2013
Since we assume C89 now, it's safe to use vfprintf.
(verror): New function, with the old implementation of 'error'
but with a va_list API.
(error, warning): Use it.
(associate, gethms): Pass explicit %s to avoid GCC warning about
possibly unsafe formats.
(inzone, outzone, newabbr): Simplify by using the new error or
warning functions, avoiding the need to allocate and free memory.
* private.h (ATTRIBUTE_FORMAT): New macro.
---
private.h | 2 ++
zic.c | 76 +++++++++++++++++++++++++++------------------------------------
2 files changed, 35 insertions(+), 43 deletions(-)
diff --git a/private.h b/private.h
index 8c1cda7..3a19305 100644
--- a/private.h
+++ b/private.h
@@ -204,9 +204,11 @@ typedef unsigned long uintmax_t;
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_PURE /* empty */
+# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if !defined _Noreturn && __STDC_VERSION__ < 201112
diff --git a/zic.c b/zic.c
index 15a1f5f..55afb40 100644
--- a/zic.c
+++ b/zic.c
@@ -8,6 +8,8 @@
#include "locale.h"
#include "tzfile.h"
+#include <stdarg.h>
+
#define ZIC_VERSION '2'
typedef int_fast64_t zic_t;
@@ -389,16 +391,16 @@ eat(const char *const name, const int num)
eats(name, num, NULL, -1);
}
-static void
-error(const char *const string)
+static void ATTRIBUTE_FORMAT((printf, 1, 0))
+verror(const char *const string, va_list args)
{
/*
** Match the format of "cc" to allow sh users to
** zic ... 2>&1 | error -t "*" -v
** on BSD systems.
*/
- (void) fprintf(stderr, _("\"%s\", line %d: %s"),
- filename, linenum, string);
+ fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
+ vfprintf(stderr, string, args);
if (rfilename != NULL)
(void) fprintf(stderr, _(" (rule from \"%s\", line %d)"),
rfilename, rlinenum);
@@ -406,15 +408,23 @@ error(const char *const string)
++errors;
}
-static void
-warning(const char *const string)
+static void ATTRIBUTE_FORMAT((printf, 1, 2))
+error(const char *const string, ...)
{
- char * cp;
+ va_list args;
+ va_start(args, string);
+ verror(string, args);
+ va_end(args);
+}
- cp = ecpyalloc(_("warning: "));
- cp = ecatalloc(cp, string);
- error(cp);
- free(cp);
+static void ATTRIBUTE_FORMAT((printf, 1, 2))
+warning(const char *const string, ...)
+{
+ va_list args;
+ fprintf(stderr, _("warning: "));
+ va_start(args, string);
+ verror(string, args);
+ va_end(args);
--errors;
}
@@ -743,7 +753,7 @@ associate(void)
** a '%s' in the format is a bad thing.
*/
if (strchr(zp->z_format, '%') != 0)
- error(_("%s in ruleless zone"));
+ error("%s", _("%s in ruleless zone"));
}
}
if (errors)
@@ -873,13 +883,13 @@ gethms(const char *string, const char *const errstring, const int signable)
ss = 0;
else if (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"),
&hh, &mm, &ss) != 3) {
- error(errstring);
+ error("%s", errstring);
return 0;
}
if (hh < 0 ||
mm < 0 || mm >= MINSPERHOUR ||
ss < 0 || ss > SECSPERMIN) {
- error(errstring);
+ error("%s", errstring);
return 0;
}
if (ZIC_MAX / SECSPERHOUR < hh) {
@@ -925,40 +935,31 @@ static int
inzone(register char **const fields, const int nfields)
{
register int i;
- static char * buf;
if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
error(_("wrong number of fields on Zone line"));
return FALSE;
}
if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
- buf = erealloc(buf, 132 + strlen(TZDEFAULT));
- (void) sprintf(buf,
+ error(
_("\"Zone %s\" line and -l option are mutually exclusive"),
TZDEFAULT);
- error(buf);
return FALSE;
}
if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
- buf = erealloc(buf, 132 + strlen(TZDEFRULES));
- (void) sprintf(buf,
+ error(
_("\"Zone %s\" line and -p option are mutually exclusive"),
TZDEFRULES);
- error(buf);
return FALSE;
}
for (i = 0; i < nzones; ++i)
if (zones[i].z_name != NULL &&
strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
- buf = erealloc(buf,
- (132 + strlen(fields[ZF_NAME])
- + strlen(zones[i].z_filename)));
- (void) sprintf(buf,
+ error(
_("duplicate zone name %s (file \"%s\", line %d)"),
fields[ZF_NAME],
zones[i].z_filename,
zones[i].z_linenum);
- error(buf);
return FALSE;
}
return inzsub(fields, nfields, FALSE);
@@ -2032,15 +2033,10 @@ outzone(const struct zone * const zpfirst, const int zonecount)
** Generate lots of data if a rule can't cover all future times.
*/
stringzone(envvar, zpfirst, zonecount);
- if (noise && envvar[0] == '\0') {
- register char * wp;
-
-wp = ecpyalloc(_("no POSIX environment variable for zone"));
- wp = ecatalloc(wp, " ");
- wp = ecatalloc(wp, zpfirst->z_name);
- warning(wp);
- free(wp);
- }
+ if (noise && envvar[0] == '\0')
+ warning("%s %s",
+ _("no POSIX environment variable for zone"),
+ zpfirst->z_name);
if (envvar[0] == '\0') {
if (min_year >= ZIC_MIN + YEARSPERREPEAT)
min_year -= YEARSPERREPEAT;
@@ -2622,14 +2618,8 @@ mp = _("time zone abbreviation has too many alphabetics");
}
if (*cp != '\0')
mp = _("time zone abbreviation differs from POSIX standard");
- if (mp != NULL) {
- char *wp = ecpyalloc(mp);
- wp = ecatalloc(wp, " (");
- wp = ecatalloc(wp, string);
- wp = ecatalloc(wp, ")");
- warning(wp);
- free(wp);
- }
+ if (mp != NULL)
+ warning("%s (%s)", mp, string);
}
i = strlen(string) + 1;
if (charcnt + i > TZ_MAX_CHARS) {
--
1.8.1.2
More information about the tz
mailing list