proposed changes to eliminate P macro
Here are proposed changes to eliminate the "P" macro from time zone source (a first step in simplifying the code by assuming C99 compilers). --ado ------- date.c ------- *** /tmp/geta13002 Thu Nov 8 09:23:34 2007 --- /tmp/getb13002 Thu Nov 8 09:23:34 2007 *************** *** 1,6 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)date.c 8.2"; /* ** Modified from the UCB version with the SCCS ID appearing below. */ --- 1,6 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)date.c 8.3"; /* ** Modified from the UCB version with the SCCS ID appearing below. */ *************** *** 75,95 **** static int retval = EXIT_SUCCESS; ! static void checkfinal P((const char *, int, time_t, time_t)); ! static int comptm P((const struct tm *, const struct tm *)); ! static time_t convert P((const char *, int, time_t)); ! static void display P((const char *)); ! static void dogmt P((void)); ! static void errensure P((void)); ! static void iffy P((time_t, time_t, const char *, const char *)); ! int main P((int, char**)); ! static const char * nondigit P((const char *)); ! static void oops P((const char *)); ! static void reset P((time_t, int)); ! static void timeout P((FILE *, const char *, const struct tm *)); ! static void usage P((void)); ! static void wildinput P((const char *, const char *, ! const char *)); int main(argc, argv) --- 75,95 ---- static int retval = EXIT_SUCCESS; ! static void checkfinal(const char *, int, time_t, time_t); ! static int comptm(const struct tm *, const struct tm *); ! static time_t convert(const char *, int, time_t); ! static void display(const char *); ! static void dogmt(void); ! static void errensure(void); ! static void iffy(time_t, time_t, const char *, const char *); ! int main(int, char**); ! static const char * nondigit(const char *); ! static void oops(const char *); ! static void reset(time_t, int); ! static void timeout(FILE *, const char *, const struct tm *); ! static void usage(void); ! static void wildinput(const char *, const char *, ! const char *); int main(argc, argv) *************** *** 499,505 **** } static void ! errensure P((void)) { if (retval == EXIT_SUCCESS) retval = EXIT_FAILURE; --- 499,505 ---- } static void ! errensure(void) { if (retval == EXIT_SUCCESS) retval = EXIT_FAILURE; *************** *** 515,521 **** } static void ! usage P((void)) { (void) fprintf(stderr, _("date: usage is date [-u] [-c] [-n] [-d dst] \ [-t min-west] [-a sss.fff] [[yyyy]mmddhhmm[yyyy][.ss]] [+format]\n")); --- 515,521 ---- } static void ! usage(void) { (void) fprintf(stderr, _("date: usage is date [-u] [-c] [-n] [-d dst] \ [-t min-west] [-a sss.fff] [[yyyy]mmddhhmm[yyyy][.ss]] [+format]\n")); ------- localtime.c ------- *** /tmp/geta13021 Thu Nov 8 09:23:35 2007 --- /tmp/getb13021 Thu Nov 8 09:23:35 2007 *************** *** 5,11 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 8.5"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 5,11 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 8.6"; #endif /* !defined NOID */ #endif /* !defined lint */ *************** *** 136,186 **** ** Prototypes for static functions. */ ! static long detzcode P((const char * codep)); ! static time_t detzcode64 P((const char * codep)); ! static int differ_by_repeat P((time_t t1, time_t t0)); ! static const char * getzname P((const char * strp)); ! static const char * getqzname P((const char * strp, const int delim)); ! static const char * getnum P((const char * strp, int * nump, int min, ! int max)); ! static const char * getsecs P((const char * strp, long * secsp)); ! static const char * getoffset P((const char * strp, long * offsetp)); ! static const char * getrule P((const char * strp, struct rule * rulep)); ! static void gmtload P((struct state * sp)); ! static struct tm * gmtsub P((const time_t * timep, long offset, ! struct tm * tmp)); ! static struct tm * localsub P((const time_t * timep, long offset, ! struct tm * tmp)); ! static int increment_overflow P((int * number, int delta)); ! static int leaps_thru_end_of P((int y)); ! static int long_increment_overflow P((long * number, int delta)); ! static int long_normalize_overflow P((long * tensptr, ! int * unitsptr, int base)); ! static int normalize_overflow P((int * tensptr, int * unitsptr, ! int base)); ! static void settzname P((void)); ! static time_t time1 P((struct tm * tmp, ! struct tm * (*funcp) P((const time_t *, ! long, struct tm *)), ! long offset)); ! static time_t time2 P((struct tm *tmp, ! struct tm * (*funcp) P((const time_t *, ! long, struct tm*)), ! long offset, int * okayp)); ! static time_t time2sub P((struct tm *tmp, ! struct tm * (*funcp) P((const time_t *, ! long, struct tm*)), ! long offset, int * okayp, int do_norm_secs)); ! static struct tm * timesub P((const time_t * timep, long offset, ! const struct state * sp, struct tm * tmp)); ! static int tmcomp P((const struct tm * atmp, ! const struct tm * btmp)); ! static time_t transtime P((time_t janfirst, int year, ! const struct rule * rulep, long offset)); ! static int tzload P((const char * name, struct state * sp, ! int doextend)); ! static int tzparse P((const char * name, struct state * sp, ! int lastditch)); #ifdef ALL_STATE static struct state * lclptr; --- 136,186 ---- ** Prototypes for static functions. */ ! static long detzcode(const char * codep); ! static time_t detzcode64(const char * codep); ! static int differ_by_repeat(time_t t1, time_t t0); ! static const char * getzname(const char * strp); ! static const char * getqzname(const char * strp, const int delim); ! static const char * getnum(const char * strp, int * nump, int min, ! int max); ! static const char * getsecs(const char * strp, long * secsp); ! static const char * getoffset(const char * strp, long * offsetp); ! static const char * getrule(const char * strp, struct rule * rulep); ! static void gmtload(struct state * sp); ! static struct tm * gmtsub(const time_t * timep, long offset, ! struct tm * tmp); ! static struct tm * localsub(const time_t * timep, long offset, ! struct tm * tmp); ! static int increment_overflow(int * number, int delta); ! static int leaps_thru_end_of(int y); ! static int long_increment_overflow(long * number, int delta); ! static int long_normalize_overflow(long * tensptr, ! int * unitsptr, int base); ! static int normalize_overflow(int * tensptr, int * unitsptr, ! int base); ! static void settzname(void); ! static time_t time1(struct tm * tmp, ! struct tm * (*funcp)(const time_t *, ! long, struct tm *), ! long offset); ! static time_t time2(struct tm *tmp, ! struct tm * (*funcp)(const time_t *, ! long, struct tm*), ! long offset, int * okayp); ! static time_t time2sub(struct tm *tmp, ! struct tm * (*funcp)(const time_t *, ! long, struct tm*), ! long offset, int * okayp, int do_norm_secs); ! static struct tm * timesub(const time_t * timep, long offset, ! const struct state * sp, struct tm * tmp); ! static int tmcomp(const struct tm * atmp, ! const struct tm * btmp); ! static time_t transtime(time_t janfirst, int year, ! const struct rule * rulep, long offset); ! static int tzload(const char * name, struct state * sp, ! int doextend); ! static int tzparse(const char * name, struct state * sp, ! int lastditch); #ifdef ALL_STATE static struct state * lclptr; *************** *** 253,259 **** } static void ! settzname P((void)) { register struct state * const sp = lclptr; register int i; --- 253,259 ---- } static void ! settzname(void) { register struct state * const sp = lclptr; register int i; *************** *** 1120,1126 **** static #endif /* !defined STD_INSPIRED */ void ! tzsetwall P((void)) { if (lcl_is_set < 0) return; --- 1120,1126 ---- static #endif /* !defined STD_INSPIRED */ void ! tzsetwall(void) { if (lcl_is_set < 0) return; *************** *** 1141,1147 **** } void ! tzset P((void)) { register const char * name; --- 1141,1147 ---- } void ! tzset(void) { register const char * name; *************** *** 1639,1645 **** static time_t time2sub(tmp, funcp, offset, okayp, do_norm_secs) struct tm * const tmp; ! struct tm * (* const funcp) P((const time_t*, long, struct tm*)); const long offset; int * const okayp; const int do_norm_secs; --- 1639,1645 ---- static time_t time2sub(tmp, funcp, offset, okayp, do_norm_secs) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t*, long, struct tm*); const long offset; int * const okayp; const int do_norm_secs; *************** *** 1827,1833 **** static time_t time2(tmp, funcp, offset, okayp) struct tm * const tmp; ! struct tm * (* const funcp) P((const time_t*, long, struct tm*)); const long offset; int * const okayp; { --- 1827,1833 ---- static time_t time2(tmp, funcp, offset, okayp) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t*, long, struct tm*); const long offset; int * const okayp; { *************** *** 1845,1851 **** static time_t time1(tmp, funcp, offset) struct tm * const tmp; ! struct tm * (* const funcp) P((const time_t *, long, struct tm *)); const long offset; { register time_t t; --- 1845,1851 ---- static time_t time1(tmp, funcp, offset) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t *, long, struct tm *); const long offset; { register time_t t; ------- private.h ------- *** /tmp/geta13040 Thu Nov 8 09:23:35 2007 --- /tmp/getb13040 Thu Nov 8 09:23:35 2007 *************** *** 21,27 **** #ifndef lint #ifndef NOID ! static char privatehid[] = "@(#)private.h 8.3"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 21,27 ---- #ifndef lint #ifndef NOID ! static char privatehid[] = "@(#)private.h 8.4"; #endif /* !defined NOID */ #endif /* !defined lint */ *************** *** 165,178 **** */ /* - ** If your compiler lacks prototypes, "#define P(x) ()". - */ - - #ifndef P - #define P(x) x - #endif /* !defined P */ - - /* ** SunOS 4.1.1 headers lack EXIT_SUCCESS. */ --- 165,170 ---- *************** *** 214,220 **** */ #ifndef remove ! extern int unlink P((const char * filename)); #define remove unlink #endif /* !defined remove */ --- 206,212 ---- */ #ifndef remove ! extern int unlink(const char * filename); #define remove unlink #endif /* !defined remove */ *************** *** 242,255 **** ** Private function declarations. */ ! char * icalloc P((int nelem, int elsize)); ! char * icatalloc P((char * old, const char * new)); ! char * icpyalloc P((const char * string)); ! char * imalloc P((int n)); ! void * irealloc P((void * pointer, int size)); ! void icfree P((char * pointer)); ! void ifree P((char * pointer)); ! const char * scheck P((const char * string, const char * format)); /* ** Finally, some convenience items. --- 234,247 ---- ** Private function declarations. */ ! char * icalloc(int nelem, int elsize); ! char * icatalloc(char * old, const char * new); ! char * icpyalloc(const char * string); ! char * imalloc(int n); ! void * irealloc(void * pointer, int size); ! void icfree(char * pointer); ! void ifree(char * pointer); ! const char * scheck(const char * string, const char * format); /* ** Finally, some convenience items. *************** *** 337,344 **** #if HAVE_INCOMPATIBLE_CTIME_R #undef asctime_r #undef ctime_r ! char *asctime_r P((struct tm const *, char *)); ! char *ctime_r P((time_t const *, char *)); #endif /* HAVE_INCOMPATIBLE_CTIME_R */ #ifndef YEARSPERREPEAT --- 329,336 ---- #if HAVE_INCOMPATIBLE_CTIME_R #undef asctime_r #undef ctime_r ! char *asctime_r(struct tm const *, char *); ! char *ctime_r(time_t const *, char *); #endif /* HAVE_INCOMPATIBLE_CTIME_R */ #ifndef YEARSPERREPEAT ------- strftime.c ------- *** /tmp/geta13059 Thu Nov 8 09:23:35 2007 --- /tmp/getb13059 Thu Nov 8 09:23:35 2007 *************** *** 1,6 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)strftime.c 8.1"; /* ** Based on the UCB version with the ID appearing below. ** This is ANSIish only when "multibyte character == plain character". --- 1,6 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)strftime.c 8.2"; /* ** Based on the UCB version with the ID appearing below. ** This is ANSIish only when "multibyte character == plain character". *************** *** 53,59 **** #ifdef LOCALE_HOME #include "sys/stat.h" static struct lc_time_T localebuf; ! static struct lc_time_T * _loc P((void)); #define Locale _loc() #endif /* defined LOCALE_HOME */ #ifndef LOCALE_HOME --- 53,59 ---- #ifdef LOCALE_HOME #include "sys/stat.h" static struct lc_time_T localebuf; ! static struct lc_time_T * _loc(void); #define Locale _loc() #endif /* defined LOCALE_HOME */ #ifndef LOCALE_HOME *************** *** 106,116 **** "%a %b %e %H:%M:%S %Z %Y" }; ! static char * _add P((const char *, char *, const char *)); ! static char * _conv P((int, const char *, char *, const char *)); ! static char * _fmt P((const char *, const struct tm *, char *, const char *, ! int *)); ! static char * _yconv P((int, int, int, int, char *, const char *)); extern char * tzname[]; --- 106,116 ---- "%a %b %e %H:%M:%S %Z %Y" }; ! static char * _add(const char *, char *, const char *); ! static char * _conv(int, const char *, char *, const char *); ! static char * _fmt(const char *, const struct tm *, char *, const char *, ! int *); ! static char * _yconv(int, int, int, int, char *, const char *); extern char * tzname[]; *************** *** 641,647 **** #ifdef LOCALE_HOME static struct lc_time_T * ! _loc P((void)) { static const char locale_home[] = LOCALE_HOME; static const char lc_time[] = "LC_TIME"; --- 641,647 ---- #ifdef LOCALE_HOME static struct lc_time_T * ! _loc(void) { static const char locale_home[] = LOCALE_HOME; static const char lc_time[] = "LC_TIME"; ------- zdump.c ------- *** /tmp/geta13078 Thu Nov 8 09:23:36 2007 --- /tmp/getb13078 Thu Nov 8 09:23:36 2007 *************** *** 1,4 **** ! static char elsieid[] = "@(#)zdump.c 8.4"; /* ** This code has been made independent of the rest of the time --- 1,4 ---- ! static char elsieid[] = "@(#)zdump.c 8.5"; /* ** This code has been made independent of the rest of the time *************** *** 134,141 **** #endif /* !defined P */ extern char ** environ; ! extern int getopt P((int argc, char * const argv[], ! const char * options)); extern char * optarg; extern int optind; extern char * tzname[2]; --- 134,141 ---- #endif /* !defined P */ extern char ** environ; ! extern int getopt(int argc, char * const argv[], ! const char * options); extern char * optarg; extern int optind; extern char * tzname[2]; *************** *** 146,160 **** static char * progname; static int warned; ! static char * abbr P((struct tm * tmp)); ! static void abbrok P((const char * abbrp, const char * zone)); ! static long delta P((struct tm * newp, struct tm * oldp)); ! static void dumptime P((const struct tm * tmp)); ! static time_t hunt P((char * name, time_t lot, time_t hit)); ! static void setabsolutes P((void)); ! static void show P((char * zone, time_t t, int v)); ! static const char * tformat P((void)); ! static time_t yeartot P((long y)); #ifndef TYPECHECK #define my_localtime localtime --- 146,160 ---- static char * progname; static int warned; ! static char * abbr(struct tm * tmp); ! static void abbrok(const char * abbrp, const char * zone); ! static long delta(struct tm * newp, struct tm * oldp); ! static void dumptime(const struct tm * tmp); ! static time_t hunt(char * name, time_t lot, time_t hit); ! static void setabsolutes(void); ! static void show(char * zone, time_t t, int v); ! static const char * tformat(void); ! static time_t yeartot(long y); #ifndef TYPECHECK #define my_localtime localtime ------- zic.c ------- *** /tmp/geta13097 Thu Nov 8 09:23:36 2007 --- /tmp/getb13097 Thu Nov 8 09:23:36 2007 *************** *** 3,9 **** ** 2006-07-17 by Arthur David Olson. */ ! static char elsieid[] = "@(#)zic.c 8.14"; #include "private.h" #include "locale.h" --- 3,9 ---- ** 2006-07-17 by Arthur David Olson. */ ! static char elsieid[] = "@(#)zic.c 8.15"; #include "private.h" #include "locale.h" *************** *** 99,167 **** zic_t z_untiltime; }; ! extern int getopt P((int argc, char * const argv[], ! const char * options)); ! extern int link P((const char * fromname, const char * toname)); extern char * optarg; extern int optind; ! static void addtt P((zic_t starttime, int type)); ! static int addtype P((long gmtoff, const char * abbr, int isdst, ! int ttisstd, int ttisgmt)); ! static void leapadd P((zic_t t, int positive, int rolling, int count)); ! static void adjleap P((void)); ! static void associate P((void)); ! static int ciequal P((const char * ap, const char * bp)); ! static void convert P((long val, char * buf)); ! static void convert64 P((zic_t val, char * buf)); ! static void dolink P((const char * fromfield, const char * tofield)); ! static void doabbr P((char * abbr, const char * format, ! const char * letters, int isdst, int doquotes)); ! static void eat P((const char * name, int num)); ! static void eats P((const char * name, int num, ! const char * rname, int rnum)); ! static long eitol P((int i)); ! static void error P((const char * message)); ! static char ** getfields P((char * buf)); ! static long gethms P((const char * string, const char * errstrng, ! int signable)); ! static void infile P((const char * filename)); ! static void inleap P((char ** fields, int nfields)); ! static void inlink P((char ** fields, int nfields)); ! static void inrule P((char ** fields, int nfields)); ! static int inzcont P((char ** fields, int nfields)); ! static int inzone P((char ** fields, int nfields)); ! static int inzsub P((char ** fields, int nfields, int iscont)); ! static int is32 P((zic_t x)); ! static int itsabbr P((const char * abbr, const char * word)); ! static int itsdir P((const char * name)); ! static int lowerit P((int c)); ! static char * memcheck P((char * tocheck)); ! static int mkdirs P((char * filename)); ! static void newabbr P((const char * abbr)); ! static long oadd P((long t1, long t2)); ! static void outzone P((const struct zone * zp, int ntzones)); ! static void puttzcode P((long code, FILE * fp)); ! static void puttzcode64 P((zic_t code, FILE * fp)); ! static int rcomp P((const void * leftp, const void * rightp)); ! static zic_t rpytime P((const struct rule * rp, int wantedy)); ! static void rulesub P((struct rule * rp, const char * loyearp, const char * hiyearp, const char * typep, const char * monthp, ! const char * dayp, const char * timep)); ! static int stringoffset P((char * result, long offset)); ! static int stringrule P((char * result, const struct rule * rp, ! long dstoff, long gmtoff)); ! static void stringzone P((char * result, ! const struct zone * zp, int ntzones)); ! static void setboundaries P((void)); ! static zic_t tadd P((zic_t t1, long t2)); ! static void usage P((void)); ! static void writezone P((const char * name, const char * string)); ! static int yearistype P((int year, const char * type)); #if !HAVE_STRERROR ! static char * strerror P((int)); #endif /* !HAVE_STRERROR */ static int charcnt; --- 99,167 ---- zic_t z_untiltime; }; ! extern int getopt(int argc, char * const argv[], ! const char * options); ! extern int link(const char * fromname, const char * toname); extern char * optarg; extern int optind; ! static void addtt(zic_t starttime, int type); ! static int addtype(long gmtoff, const char * abbr, int isdst, ! int ttisstd, int ttisgmt); ! static void leapadd(zic_t t, int positive, int rolling, int count); ! static void adjleap(void); ! static void associate(void); ! static int ciequal(const char * ap, const char * bp); ! static void convert(long val, char * buf); ! static void convert64(zic_t val, char * buf); ! static void dolink(const char * fromfield, const char * tofield); ! static void doabbr(char * abbr, const char * format, ! const char * letters, int isdst, int doquotes); ! static void eat(const char * name, int num); ! static void eats(const char * name, int num, ! const char * rname, int rnum); ! static long eitol(int i); ! static void error(const char * message); ! static char ** getfields(char * buf); ! static long gethms(const char * string, const char * errstrng, ! int signable); ! static void infile(const char * filename); ! static void inleap(char ** fields, int nfields); ! static void inlink(char ** fields, int nfields); ! static void inrule(char ** fields, int nfields); ! static int inzcont(char ** fields, int nfields); ! static int inzone(char ** fields, int nfields); ! static int inzsub(char ** fields, int nfields, int iscont); ! static int is32(zic_t x); ! static int itsabbr(const char * abbr, const char * word); ! static int itsdir(const char * name); ! static int lowerit(int c); ! static char * memcheck(char * tocheck); ! static int mkdirs(char * filename); ! static void newabbr(const char * abbr); ! static long oadd(long t1, long t2); ! static void outzone(const struct zone * zp, int ntzones); ! static void puttzcode(long code, FILE * fp); ! static void puttzcode64(zic_t code, FILE * fp); ! static int rcomp(const void * leftp, const void * rightp); ! static zic_t rpytime(const struct rule * rp, int wantedy); ! static void rulesub(struct rule * rp, const char * loyearp, const char * hiyearp, const char * typep, const char * monthp, ! const char * dayp, const char * timep); ! static int stringoffset(char * result, long offset); ! static int stringrule(char * result, const struct rule * rp, ! long dstoff, long gmtoff); ! static void stringzone(char * result, ! const struct zone * zp, int ntzones); ! static void setboundaries(void); ! static zic_t tadd(zic_t t1, long t2); ! static void usage(void); ! static void writezone(const char * name, const char * string); ! static int yearistype(int year, const char * type); #if !HAVE_STRERROR ! static char * strerror(int); #endif /* !HAVE_STRERROR */ static int charcnt; *************** *** 287,294 **** const int l_value; }; ! static struct lookup const * byword P((const char * string, ! const struct lookup * lp)); static struct lookup const line_codes[] = { { "Rule", LC_RULE }, --- 287,294 ---- const int l_value; }; ! static struct lookup const * byword(const char * string, ! const struct lookup * lp); static struct lookup const line_codes[] = { { "Rule", LC_RULE }, *************** *** 471,477 **** } static void ! usage P((void)) { (void) fprintf(stderr, _("%s: usage is %s \ [ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ --- 471,477 ---- } static void ! usage(void) { (void) fprintf(stderr, _("%s: usage is %s \ [ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ *************** *** 699,705 **** #define TIME_T_BITS_IN_FILE 64 static void ! setboundaries P((void)) { register int i; --- 699,705 ---- #define TIME_T_BITS_IN_FILE 64 static void ! setboundaries(void) { register int i; *************** *** 741,747 **** } static void ! associate P((void)) { register struct zone * zp; register struct rule * rp; --- 741,747 ---- } static void ! associate(void) { register struct zone * zp; register struct rule * rp; *************** *** 2331,2337 **** } static void ! adjleap P((void)) { register int i; register long last = 0; --- 2331,2337 ---- } static void ! adjleap(void) { register int i; register long last = 0;
On Nov 8, 2007 6:26 AM, Arthur David Olson <olsona@elsie.nci.nih.gov> wrote:
Here are proposed changes to eliminate the "P" macro from time zone source (a first step in simplifying the code by assuming C99 compilers).
--ado
I tried to apply this as a patch and run into two problems. 1. The file names are not readily obvious to the patch program; the names it sees are /tmp/geta13002 and /tmp/getb13002 etc, rather than (say) date.c. 2. There should be a 2 characters (eg two blanks, or "! " or "+ ") at the start of each line, but by the time Gmail gets the message, there's a blank missing at the start of lines such as the #ifndef lines at the start of the patch below. I also had some unfortunate line-wrapping, but I'm willing to blame that on the (other) email program I use. 3. I tried manually fixing up the patch file for the line starts, but was not successful.
------- date.c ------- *** /tmp/geta13002 Thu Nov 8 09:23:34 2007 --- /tmp/getb13002 Thu Nov 8 09:23:34 2007 *************** *** 1,6 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)date.c 8.2"; /* ** Modified from the UCB version with the SCCS ID appearing below. */ --- 1,6 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)date.c 8.3"; /* ** Modified from the UCB version with the SCCS ID appearing below. */
Did anyone else run into parallel problems, or is it an artefact of the mix of environments I'm using? -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2007.0914 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."
The patch worked for me, I did "patch < patch.txt" against tzcode2007h and fed it each filename in sequence. Compiled fine as well. The patch did look a bit strange, as to the filename format. -s On 09 Nov 2007, at 20:51, Jonathan Leffler wrote:
On Nov 8, 2007 6:26 AM, Arthur David Olson <olsona@elsie.nci.nih.gov> wrote: Here are proposed changes to eliminate the "P" macro from time zone source (a first step in simplifying the code by assuming C99 compilers).
--ado
I tried to apply this as a patch and run into two problems. The file names are not readily obvious to the patch program; the names it sees are /tmp/geta13002 and /tmp/getb13002 etc, rather than (say) date.c. There should be a 2 characters (eg two blanks, or "! " or "+ ") at the start of each line, but by the time Gmail gets the message, there's a blank missing at the start of lines such as the #ifndef lines at the start of the patch below. I also had some unfortunate line-wrapping, but I'm willing to blame that on the (other) email program I use. I tried manually fixing up the patch file for the line starts, but was not successful.
------- date.c ------- *** /tmp/geta13002 Thu Nov 8 09:23:34 2007 --- /tmp/getb13002 Thu Nov 8 09:23:34 2007 ***************
Resolved... On Nov 9, 2007 9:28 PM, Steven R. Loomis <srl@icu-project.org> wrote:
On 09 Nov 2007, at 20:51, Jonathan Leffler wrote:
On Nov 8, 2007 6:26 AM, Arthur David Olson <olsona@elsie.nci.nih.gov> wrote:
Here are proposed changes to eliminate the "P" macro from time zone source (a first step in simplifying the code by assuming C99 compilers).
I tried to apply this as a patch and run into two problems. 1. The file names are not readily obvious to the patch program; the names it sees are /tmp/geta13002 and /tmp/getb13002 etc, rather than (say) date.c. 2. There should be a 2 characters (eg two blanks, or "! " or "+ ") at the start of each line, but by the time Gmail gets the message, there's a blank missing at the start of lines such as the #ifndef lines at the start of the patch below. I also had some unfortunate line-wrapping, but I'm willing to blame that on the (other) email program I use. 3. I tried manually fixing up the patch file for the line starts, but was not successful.
------- date.c ------- *** /tmp/geta13002 Thu Nov 8 09:23:34 2007 --- /tmp/getb13002 Thu Nov 8 09:23:34 2007 ***************
The patch worked for me, I did "patch < patch.txt" against tzcode2007h and
fed it each filename in sequence. Compiled fine as well.
The patch did look a bit strange, as to the filename format.
Thanks. The problem was at my end - working out how to get an uncorrupted file out of Gmail wasn't as straight-forward as I expected. However, the third time, I used the "show original" option followed by saving that page and the patch worked fine when I supplied the names manually. Steve - thank you for sending the patch to the patch -- I would have used it except for the problems of getting it out of Gmail, too. By the time I'd resolved that, I'd also typed the file names in. -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2007.0914 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."
On Thu, Nov 08, 2007 at 09:26:29AM -0500, Arthur David Olson wrote:
Here are proposed changes to eliminate the "P" macro from time zone source (a first step in simplifying the code by assuming C99 compilers).
A good start. I'm continuing that process with the attached patch: * the main changes, comprising the bulk of this patch, is the addition of prototypes for functions which were _not_ handled by the "P" macro; this includes explicit (void) parameter lists where appropriate * use angle brackets <> instead of double-quotes for system #include-s, for the benefit of any compiler that handles those more efficiently (e.g., support of pre-compiled system headers) * removes some conditionals that were only needed to support pre-C89 compilers (like "cc" on SunOS 4.x and older); this includes: . removal if isascii() definition and calls . removal of private strerror() definition . removal of "%02.2d"-style printf formats (favoring "%.2d" instead) . removal of (void*) casts on function-pointer comparisons . "failsafe" declarations of symbols that C89 dictates must be defined in relevant headers; viz: EXIT_SUCCESS, EXIT_FAILURE, FILENAME_MAX, errno * some small tweaks for type-correctness: . removed a spurious cast from scheck.c . removed a spurious/erroneous cast from zic.c:doabbr() (might have been useful at one time, before function prototypes were used, but now ought to be a (size_t) instead of a (unsigned) if it is going to be an explilcit cast) . made "wp" in zic.c:newabbr() a "const", and added new "xp" variable to handle the case where "wp" was treated as non-const ("wp" is assigned literal string values, so it should be "const") I was going to also remove all "register" delcarations, on the premise that modern compilers do well without the hints, but decided the patch became too unwieldy to review that way (it's already rather large, which is why I decided to attach a gzipped version instead of placing the patch in-line). I did drop "register" delcarations on any lines that I touched for other reasons though. On the meta-level, regarding the goal of this code clean-up project: I'd personally prefer to allow compilers that are C89 compliant (provided that some sort of 64-bit integer is supported) to work with this code, if possible, rather than requiring full C99 support. --Ken Pizzini
I was going to also remove all "register" delcarations, on the premise that modern compilers do well without the hints...
My own use of "register" isn't to provide compilers with hints but rather to avoid unintended calls by reference; everything starts out life as a register variable, and the register only gets dropped if the address of the variable needs to be taken. --ado
On Nov 13, 2007 6:46 AM, Olson, Arthur David (NIH/NCI) [E] < olsona@dc37a.nci.nih.gov> wrote:
I was going to also remove all "register" delcarations, on the premise that modern compilers do well without the hints...
My own use of "register" isn't to provide compilers with hints but rather to avoid unintended calls by reference; everything starts out life as a register variable, and the register only gets dropped if the address of the variable needs to be taken.
Interesting usage - not a technique I'd come across before, but that most certainly does not make it invalid. I won't consider removing the registers any further (not that I am able to make direct changes to your code anyway). -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2007.0914 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."
On Tue, Nov 13, 2007 at 09:46:13AM -0500, Arthur David Olson wrote:
My own use of "register" isn't to provide compilers with hints but rather to avoid unintended calls by reference;
Is it possible to make "unintended calls by reference", without at least a stern warning from the compiler (if not an outright error) in the world of prototyped function calls? Passing a pointer-to-T is quite different from passing a value of type T, after all. --Ken Pizzini
On Nov 13, 2007 2:49 PM, Ken Pizzini <tz_@explicate.org> wrote:
On Tue, Nov 13, 2007 at 09:46:13AM -0500, Arthur David Olson wrote:
My own use of "register" isn't to provide compilers with hints but rather to avoid unintended calls by reference;
Is it possible to make "unintended calls by reference", without at least a stern warning from the compiler (if not an outright error) in the world of prototyped function calls? Passing a pointer-to-T is quite different from passing a value of type T, after all.
To pass by reference, you have to apply the 'address-of' operator to the variable: &variable. The register storage class prevents you applying & to a variable. But you're correct: except in the weird world of the void pointer (and pointer to void pointer, etc), with prototypes in force, you can't pass variable where &variable is correct (or vice versa), so forgetting to apply the & would be an error spotted by the compiler. -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2007.0914 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."
Jonathan Leffler said:
My own use of "register" isn't to provide compilers with hints but rather to avoid unintended calls by reference;
To pass by reference, you have to apply the 'address-of' operator to the variable: &variable. The register storage class prevents you applying & to a variable.
But you're correct: except in the weird world of the void pointer (and pointer to void pointer, etc), with prototypes in force, you can't pass variable where &variable is correct (or vice versa), so forgetting to apply the & would be an error spotted by the compiler.
Actually, there's the area of variable length argument lists. But I think what he meant is that you don't want to set up a pointer to a variable in one place, thus allowing an unrelated bit of code to try to modify the variable somewhere else (or, even, worse, outside the lifetime of that variable). Using "register" means you can't do this until you've thought through the reasons and deleted the qualifier. -- Clive D.W. Feather | Work: <clive@demon.net> | Tel: +44 20 8495 6138 Internet Expert | Home: <clive@davros.org> | Fax: +44 870 051 9937 Demon Internet | WWW: http://www.davros.org | Mobile: +44 7973 377646 THUS plc | |
On Tue, Nov 13, 2007 at 09:46:13AM -0500, Arthur David Olson wrote:
I was going to also remove all "register" delcarations, on the premise that modern compilers do well without the hints...
That is a quote from a message I sent as "tz.", before you added my "tz_" alias (thanks again for that, BTW: it worked just fine for my most recent comment), so obviously _you_ saw my patch, but I still haven't seen my patch posted to the mailing list (neither directly to my inbox, nor on gmane). Should I submit it again? (I'll add back in the "register" annotations that I had dropped if I do resubmit, pending a consensus about whether to keep them or not.) --Ken Pizzini
It looks as if re-sending (modulo register declarations) is best. --ado -----Original Message----- From: Ken Pizzini [mailto:tz_@explicate.org] Sent: Tue 11/13/2007 6:04 PM To: tz@lecserver.nci.nih.gov Subject: Re: proposed changes to eliminate P macro On Tue, Nov 13, 2007 at 09:46:13AM -0500, Arthur David Olson wrote:
I was going to also remove all "register" delcarations, on the premise that modern compilers do well without the hints...
That is a quote from a message I sent as "tz.", before you added my "tz_" alias (thanks again for that, BTW: it worked just fine for my most recent comment), so obviously _you_ saw my patch, but I still haven't seen my patch posted to the mailing list (neither directly to my inbox, nor on gmane). Should I submit it again? (I'll add back in the "register" annotations that I had dropped if I do resubmit, pending a consensus about whether to keep them or not.) --Ken Pizzini
On Thu, Nov 08, 2007 at 09:26:29AM -0500, Arthur David Olson wrote:
Here are proposed changes to eliminate the "P" macro from time zone source (a first step in simplifying the code by assuming C99 compilers).
A good start. I'm continuing that process with the attached patch: * the main changes, comprising the bulk of this patch, is the addition of prototypes for functions which were _not_ handled by the "P" macro; this includes explicit (void) parameter lists where appropriate * use angle brackets <> instead of double-quotes for system #include-s, for the benefit of any compiler that handles those more efficiently (e.g., support of pre-compiled system headers) * removes some conditionals that were only needed to support pre-C89 compilers (like "cc" on SunOS 4.x and older); this includes: . removal if isascii() definition and calls . removal of private strerror() definition . removal of "%02.2d"-style printf formats (favoring "%.2d" instead) . removal of (void*) casts on function-pointer comparisons . removal of "failsafe" declarations of symbols that C89 dictates must be defined in relevant headers; viz: EXIT_SUCCESS, EXIT_FAILURE, FILENAME_MAX, errno * some small tweaks for type-correctness: . removed a spurious cast from scheck.c . removed a spurious/erroneous cast from zic.c:doabbr() (might have been useful at one time, before function prototypes were used, but now ought to be a (size_t) instead of a (unsigned) if it is going to be an explilcit cast) . made "wp" in zic.c:newabbr() a "const", and added new "xp" variable to handle the case where "wp" was treated as non-const ("wp" is assigned literal string values, so it should be "const") Because the patch is rather large, I've decided to attach a gzipped version instead of placing the patch in-line. On the meta-level, regarding the goal of this code clean-up project: I'd personally prefer to allow compilers that are C89 compliant (provided that some sort of 64-bit integer is supported) to work with this code, if possible, rather than requiring full C99 support. --Ken Pizzini
Ken Pizzini <tz_@explicate.org> writes:
I'd personally prefer to allow compilers that are C89 compliant (provided that some sort of 64-bit integer is supported) to work with this code, if possible, rather than requiring full C99 support.
I'll second that. Very few full C99 environments actually exist yet. I just now ran into a bug with Sun's current compiler; it mishandles wider-than-32-bit integers in preprocessor expressions when it is running on 32-bit sparc, because the compiler doesn't support that part of C99 correctly yet. GCC doesn't claim full C99 support yet either.
On Nov 13, 2007 4:43 PM, Paul Eggert <eggert@cs.ucla.edu> wrote:
Ken Pizzini <tz_@explicate.org> writes:
I'd personally prefer to allow compilers that are C89 compliant (provided that some sort of 64-bit integer is supported) to work with this code, if possible, rather than requiring full C99 support.
I'll second that. Very few full C99 environments actually exist yet. I just now ran into a bug with Sun's current compiler; it mishandles wider-than-32-bit integers in preprocessor expressions when it is running on 32-bit sparc, because the compiler doesn't support that part of C99 correctly yet. GCC doesn't claim full C99 support yet either.
If it's relevant, I'll third it. My notes on C99-like support being needed were to justify the change from K&R to C89, not to request C99 support. There are some nice features in C99 - the extra initializer options, for example (though I wish they'd added a Fortran-like "repeat" option). -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2007.0914 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."
I just noticed a bug in my previous patch: my test-run compiling logwtmp.c failed to notice that I botched the strncpy() prototype, because my <utmp.h> file defines the OLD_TIME macro which bypasses the branch of the source code where logwtmp() is defined. Below is a better fix for this: #include the relevant system headers which declare these functions, rather than inserting the prototypes explicitly in the code. I've also cleaned up the function declaration for logwtmp() itself while I was at it. --Ken Pizzini diff -ru tzcode2007-cleancast/logwtmp.c tzcode2007-foo/logwtmp.c --- tzcode2007-cleancast/logwtmp.c 2007-11-13 15:08:32.000000000 -0800 +++ tzcode2007-foo/logwtmp.c 2007-11-13 17:52:54.000000000 -0800 @@ -39,20 +39,20 @@ #ifndef OLD_TIME +#include <string.h> +#include <time.h> #include <sys/file.h> #include <sys/time.h> #include <sys/stat.h> #define WTMPFILE "/usr/adm/wtmp" -logwtmp(line, name, host) - char *line, *name, *host; +void +logwtmp(const char *line, const char *name, const char *host) { struct utmp ut; struct stat buf; int fd; - time_t time(time_t *); - char *strncpy(char *, const char *); if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0) return; diff -ru tzcode2007-cleancast/date.c tzcode2007-foo/date.c --- tzcode2007-cleancast/date.c 2007-11-13 17:26:02.000000000 -0800 +++ tzcode2007-foo/date.c 2007-11-13 17:53:29.000000000 -0800 @@ -440,7 +440,7 @@ #define TSPTYPES #include <protocols/timed.h> -extern int logwtmp(); +extern void logwtmp(const char *line, const char *name, const char *host); #if HAVE_SETTIMEOFDAY == 1 #define settimeofday(t, tz) (settimeofday)(t)
Date: Tue, 13 Nov 2007 16:36:34 -0800 From: Ken Pizzini <tz_@explicate.org> Message-ID: <20071114003634.GA26243@4746044.msa.explicate.org> | * use angle brackets <> instead of double-quotes for system #include-s, | for the benefit of any compiler that handles those more efficiently | (e.g., support of pre-compiled system headers) The change you're doing there should be OK, but the rationale you give makes no sense to me ... all <> ever did in C was to skip the default search of the current directory for the file to include - but if -I. is given, that comes back again - there's no real distinction (in the syntax of the #include) between "system" and other include files. If the compiler wants to support pre-"compiled" include files, it needs some other mechanism to recognise them than the <> vs "" in the .c file. | * removes some conditionals that were only needed to support pre-C89 | compilers (like "cc" on SunOS 4.x and older); this includes: I'm not sure I'd be doing all of those - sure, in most cases they simplify things a little, but (perhaps aside from the isascii() changes) they're not really altering anything that matters. That is, the P() stuff, (and isascii()) are littered everywhere, getting rid of that old cruft makes the code easier to read. On the other hand, having a local strerror() defined in case the system is missing one (as remote a chance as that possibility is) really harms nothing - that declaration is trivially ignored, and affects reading/understanding (and compiling/using) the code in no way at all. That is, don't make changes just for the sake of changing things, even if it is strictly OK to do that, and even if you wouldn't bother to do it the old way if you were writing the code today - there needs to be some positive benefit to the change to justify all the work everyone else is going to need to do looking over the diffs from the last version before integrating the updated code into the many distributions that use it. What I might change however is to make some of the casts a little safer (perhaps only for defective compilers, but still...) Eg: if we have char *cp; and want to use an unsigned char (particularly for args to the isalpha() etc macros), I'd feel safer writing *(unsigned char *)cp rather than the (unsigned char) *cp that now exists. I just don't trust compilers to always evaluate the latter correctly. Or even better, where essentially all uses of *cp in a function want an unsigned char (or would work with unsigned char - and as "char" might be unsigned anyway, that should be just about all of them) I'd just declare it as "unsigned char *cp" and then remove all of the casts on the uses of *cp (instead perhaps adding a cast where cp is initialised, from, and perhaps compared with, a char * pointer that can't as easily be changed. But even that I'd be hesitant about changing, just for the sake of it, if what's there now causes problems for no-one, then leave it alone. kre
On Thu, Nov 15, 2007 at 03:47:27PM +0700, Robert Elz wrote:
| * use angle brackets <> instead of double-quotes for system #include-s, | for the benefit of any compiler that handles those more efficiently | (e.g., support of pre-compiled system headers)
The change you're doing there should be OK, but the rationale you give makes no sense to me ... all <> ever did in C was to skip the default search of the current directory for the file to include - but if -I. is given, that comes back again - there's no real distinction (in the syntax of the #include) between "system" and other include files. If the compiler wants to support pre-"compiled" include files, it needs some other mechanism to recognise them than the <> vs "" in the .c file.
What you describe is the traditional Unix interpretation. And perhaps I'm misremembering and it was C++ only, but I *do* recall that at least one of the two language standard *does* explicitly state that the <> notation for include files allows the language implementation (compiler) to use built-in (even beyond "precompiled") headers for the <> notation. That said, I have never actually worked with a compiler that did this; I just make it a habit to use <> when I want the system headers and "" when I want the application headers, for both the above-stated rationale and just to be clear about my intent.
That is, don't make changes just for the sake of changing things, even if it is strictly OK to do that, and even if you wouldn't bother to do it the old way if you were writing the code today - there needs to be some positive benefit to the change to justify all the work everyone else is going to need to do looking over the diffs from the last version before integrating the updated code into the many distributions that use it.
I understand your point here, but here's my view: even "dead" code has a cost in maintenance and comprehension. Note my follow-up correction for the prototype fix to the logwtmp() code, for example. If 99% of the time the strerror() code is ignored, then it will suffer bit-rot. When scanning the source, one must skip over it. Granted, ignoring the function while reading the code is a low-cost operation, but still, given that it was the standardization process that lead to C *89* that both created function prototypes and mandated the strerror() function (and effectively deprecated the sys_errlist[] array that the locally-defined strerror() function relies on), it seemed worth the one-time cost of eliminating it during this "let's modernize and clean-up the code" project. That said, I'm not adamant that strerror() and isascii() be removed. It is my opinion that they should be removed, but beyond offering the patch and explaining why I think they should go, I really don't care whether they stay in or not. I probably should have split out my proposed changes into a set of more focused patches, rather than bundling them all up at once, to both simplify review and discussion. Sorry about that: I just got a bit carried away during my edit session and swatted at several ancillary gnats that happened to be in my path while I was busy with the primary task of ensuring that all functions used prototype in their declarations and definitions. I *did* back off from including some larger change sets, like the deletion of register annotations (which, based on recent discussion I'll probably not submit), and I am sitting on some clean-ups to castings (not necessarily the same ones you're looking at) until the dust settles on the current round of patches. Oh, and while I'm extemporising on my opinions, I'd like to make an additional comment about the use of "register" in the code: either we should eliminate it altogether, or we need to make a pass through the code to *add* "register" in all the places that it is currently missing. There are many variables that are not declared "register" that could be. My personal preference is to simply remove "register" everywhere, but if we're going to use it to prevent accidental use of "&" on the wrong variable, we should be consistent about it and use it on every variable that it can be applied to. --Ken Pizzini
Robert Elz <kre@munnari.oz.au> writes:
if we have char *cp; and want to use an unsigned char (particularly for args to the isalpha() etc macros), I'd feel safer writing
*(unsigned char *)cp rather than the (unsigned char) *cp that now exists. I just don't trust compilers to always evaluate the latter correctly.
I understand that lack of trust, and it was a deserved lack of trust 20 years ago or maybe even 15. But nowadays we can trust compilers to do the latter version accurately. Conversely, the former version is not portable code according to the C standard: it allows implementations where 'char' has weird representations that don't work well when interpreted as 'unsigned char'. In such implementations, the latter code is reliable (its semantics are defined by the C standard, and work in the usual way) whereas the former is not. As a personal preference, I now avoid all casts in C, as I think their disadvantages now almost always outweigh their advantages. Instead of the above, I'll write code like this: unsigned char uc = *cp; ... uc ... This works on all C compilers nowadays.
participants (9)
-
Arthur David Olson -
Clive D.W. Feather -
Jonathan Leffler -
Ken Pizzini -
Ken Pizzini -
Olson, Arthur David (NIH/NCI) [E] -
Paul Eggert -
Robert Elz -
Steven R. Loomis