home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / zoneinfo / src / zdump.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-12  |  8.0 KB  |  367 lines

  1. #ifndef lint
  2. #ifndef NOID
  3. static char    elsieid[] = "@(#)zdump.c    7.24";
  4. #endif /* !defined NOID */
  5. #endif /* !defined lint */
  6.  
  7. /*
  8. ** This code has been made independent of the rest of the time
  9. ** conversion package to increase confidence in the verification it provides.
  10. ** You can use this code to help in verifying other implementations.
  11. */
  12.  
  13. #include "stdio.h"    /* for stdout, stderr, perror */
  14. #include "string.h"    /* for strcpy */
  15. #include "sys/types.h"    /* for time_t */
  16. #include "time.h"    /* for struct tm */
  17. #include "stdlib.h"    /* for exit, malloc, atoi */
  18.  
  19. #ifndef MAX_STRING_LENGTH
  20. #define MAX_STRING_LENGTH    1024
  21. #endif /* !defined MAX_STRING_LENGTH */
  22.  
  23. #ifndef TRUE
  24. #define TRUE        1
  25. #endif /* !defined TRUE */
  26.  
  27. #ifndef FALSE
  28. #define FALSE        0
  29. #endif /* !defined FALSE */
  30.  
  31. #ifndef EXIT_SUCCESS
  32. #define EXIT_SUCCESS    0
  33. #endif /* !defined EXIT_SUCCESS */
  34.  
  35. #ifndef EXIT_FAILURE
  36. #define EXIT_FAILURE    1
  37. #endif /* !defined EXIT_FAILURE */
  38.  
  39. #ifndef SECSPERMIN
  40. #define SECSPERMIN    60
  41. #endif /* !defined SECSPERMIN */
  42.  
  43. #ifndef MINSPERHOUR
  44. #define MINSPERHOUR    60
  45. #endif /* !defined MINSPERHOUR */
  46.  
  47. #ifndef SECSPERHOUR
  48. #define SECSPERHOUR    (SECSPERMIN * MINSPERHOUR)
  49. #endif /* !defined SECSPERHOUR */
  50.  
  51. #ifndef HOURSPERDAY
  52. #define HOURSPERDAY    24
  53. #endif /* !defined HOURSPERDAY */
  54.  
  55. #ifndef EPOCH_YEAR
  56. #define EPOCH_YEAR    1970
  57. #endif /* !defined EPOCH_YEAR */
  58.  
  59. #ifndef TM_YEAR_BASE
  60. #define TM_YEAR_BASE    1900
  61. #endif /* !defined TM_YEAR_BASE */
  62.  
  63. #ifndef DAYSPERNYEAR
  64. #define DAYSPERNYEAR    365
  65. #endif /* !defined DAYSPERNYEAR */
  66.  
  67. #ifndef isleap
  68. #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
  69. #endif /* !defined isleap */
  70.  
  71. #if HAVE_GETTEXT - 0
  72. #include "locale.h"    /* for setlocale */
  73. #include "libintl.h"
  74. #endif /* HAVE_GETTEXT - 0 */
  75.  
  76. #ifndef GNUC_or_lint
  77. #ifdef lint
  78. #define GNUC_or_lint
  79. #endif /* defined lint */
  80. #ifndef lint
  81. #ifdef __GNUC__
  82. #define GNUC_or_lint
  83. #endif /* defined __GNUC__ */
  84. #endif /* !defined lint */
  85. #endif /* !defined GNUC_or_lint */
  86.  
  87. #ifndef INITIALIZE
  88. #ifdef GNUC_or_lint
  89. #define INITIALIZE(x)    ((x) = 0)
  90. #endif /* defined GNUC_or_lint */
  91. #ifndef GNUC_or_lint
  92. #define INITIALIZE(x)
  93. #endif /* !defined GNUC_or_lint */
  94. #endif /* !defined INITIALIZE */
  95.  
  96. /*
  97. ** For the benefit of GNU folk...
  98. ** `_(MSGID)' uses the current locale's message library string for MSGID.
  99. ** The default is to use gettext if available, and use MSGID otherwise.
  100. */
  101.  
  102. #ifndef _
  103. #if HAVE_GETTEXT - 0
  104. #define _(msgid) gettext(msgid)
  105. #else /* !(HAVE_GETTEXT - 0) */
  106. #define _(msgid) msgid
  107. #endif /* !(HAVE_GETTEXT - 0) */
  108. #endif /* !defined _ */
  109.  
  110. #ifndef TZ_DOMAIN
  111. #define TZ_DOMAIN "tz"
  112. #endif /* !defined TZ_DOMAIN */
  113.  
  114. extern char **    environ;
  115. extern int    getopt();
  116. extern char *    optarg;
  117. extern int    optind;
  118. extern time_t    time();
  119. extern char *    tzname[2];
  120.  
  121. static char *    abbr();
  122. static long    delta();
  123. static time_t    hunt();
  124. static int    longest;
  125. static char *    progname;
  126. static void    show();
  127.  
  128. int
  129. main(argc, argv)
  130. int    argc;
  131. char *    argv[];
  132. {
  133.     register int        i;
  134.     register int        c;
  135.     register int        vflag;
  136.     register char *        cutoff;
  137.     register int        cutyear;
  138.     register long        cuttime;
  139.     char **            fakeenv;
  140.     time_t            now;
  141.     time_t            t;
  142.     time_t            newt;
  143.     time_t            hibit;
  144.     struct tm        tm;
  145.     struct tm        newtm;
  146.  
  147.     INITIALIZE(cuttime);
  148. #if HAVE_GETTEXT - 0
  149.     (void) setlocale(LC_MESSAGES, "");
  150. #ifdef TZ_DOMAINDIR
  151.     (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
  152. #endif /* defined(TEXTDOMAINDIR) */
  153.     (void) textdomain(TZ_DOMAIN);
  154. #endif /* HAVE_GETTEXT - 0 */
  155.     progname = argv[0];
  156.     vflag = 0;
  157.     cutoff = NULL;
  158.     while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
  159.         if (c == 'v')
  160.             vflag = 1;
  161.         else    cutoff = optarg;
  162.     if (c != EOF ||
  163.         (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
  164.             (void) fprintf(stderr,
  165. _("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"),
  166.                 argv[0], argv[0]);
  167.             (void) exit(EXIT_FAILURE);
  168.     }
  169.     if (cutoff != NULL) {
  170.         int    y;
  171.  
  172.         cutyear = atoi(cutoff);
  173.         cuttime = 0;
  174.         for (y = EPOCH_YEAR; y < cutyear; ++y)
  175.             cuttime += DAYSPERNYEAR + isleap(y);
  176.         cuttime *= SECSPERHOUR * HOURSPERDAY;
  177.     }
  178.     (void) time(&now);
  179.     longest = 0;
  180.     for (i = optind; i < argc; ++i)
  181.         if (strlen(argv[i]) > longest)
  182.             longest = strlen(argv[i]);
  183.     for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
  184.         continue;
  185.     {
  186.         register int    from;
  187.         register int    to;
  188.  
  189.         for (i = 0;  environ[i] != NULL;  ++i)
  190.             continue;
  191.         fakeenv = (char **) malloc((size_t) ((i + 2) *
  192.             sizeof *fakeenv));
  193.         if (fakeenv == NULL ||
  194.             (fakeenv[0] = (char *) malloc((size_t) (longest +
  195.                 4))) == NULL) {
  196.                     (void) perror(progname);
  197.                     (void) exit(EXIT_FAILURE);
  198.         }
  199.         to = 0;
  200.         (void) strcpy(fakeenv[to++], "TZ=");
  201.         for (from = 0; environ[from] != NULL; ++from)
  202.             if (strncmp(environ[from], "TZ=", 3) != 0)
  203.                 fakeenv[to++] = environ[from];
  204.         fakeenv[to] = NULL;
  205.         environ = fakeenv;
  206.     }
  207.     for (i = optind; i < argc; ++i) {
  208.         static char    buf[MAX_STRING_LENGTH];
  209.  
  210.         (void) strcpy(&fakeenv[0][3], argv[i]);
  211.         if (!vflag) {
  212.             show(argv[i], now, FALSE);
  213.             continue;
  214.         }
  215.         /*
  216.         ** Get lowest value of t.
  217.         */
  218.         t = hibit;
  219.         if (t > 0)        /* time_t is unsigned */
  220.             t = 0;
  221.         show(argv[i], t, TRUE);
  222.         t += SECSPERHOUR * HOURSPERDAY;
  223.         show(argv[i], t, TRUE);
  224.         tm = *localtime(&t);
  225.         (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
  226.         for ( ; ; ) {
  227.             if (cutoff != NULL && t >= cuttime)
  228.                 break;
  229.             newt = t + SECSPERHOUR * 12;
  230.             if (cutoff != NULL && newt >= cuttime)
  231.                 break;
  232.             if (newt <= t)
  233.                 break;
  234.             newtm = *localtime(&newt);
  235.             if (delta(&newtm, &tm) != (newt - t) ||
  236.                 newtm.tm_isdst != tm.tm_isdst ||
  237.                 strcmp(abbr(&newtm), buf) != 0) {
  238.                     newt = hunt(argv[i], t, newt);
  239.                     newtm = *localtime(&newt);
  240.                     (void) strncpy(buf, abbr(&newtm),
  241.                         (sizeof buf) - 1);
  242.             }
  243.             t = newt;
  244.             tm = newtm;
  245.         }
  246.         /*
  247.         ** Get highest value of t.
  248.         */
  249.         t = ~((time_t) 0);
  250.         if (t < 0)        /* time_t is signed */
  251.             t &= ~hibit;
  252.         t -= SECSPERHOUR * HOURSPERDAY;
  253.         show(argv[i], t, TRUE);
  254.         t += SECSPERHOUR * HOURSPERDAY;
  255.         show(argv[i], t, TRUE);
  256.     }
  257.     if (fflush(stdout) || ferror(stdout)) {
  258.         (void) fprintf(stderr, _("%s: Error writing standard output "),
  259.             argv[0]);
  260.         (void) perror(_("standard output"));
  261.         (void) exit(EXIT_FAILURE);
  262.     }
  263.     exit(EXIT_SUCCESS);
  264.  
  265.     /* gcc -Wall pacifier */
  266.     for ( ; ; )
  267.         continue;
  268. }
  269.  
  270. static time_t
  271. hunt(name, lot, hit)
  272. char *    name;
  273. time_t    lot;
  274. time_t    hit;
  275. {
  276.     time_t        t;
  277.     struct tm    lotm;
  278.     struct tm    tm;
  279.     static char    loab[MAX_STRING_LENGTH];
  280.  
  281.     lotm = *localtime(&lot);
  282.     (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
  283.     while ((hit - lot) >= 2) {
  284.         t = lot / 2 + hit / 2;
  285.         if (t <= lot)
  286.             ++t;
  287.         else if (t >= hit)
  288.             --t;
  289.         tm = *localtime(&t);
  290.         if (delta(&tm, &lotm) == (t - lot) &&
  291.             tm.tm_isdst == lotm.tm_isdst &&
  292.             strcmp(abbr(&tm), loab) == 0) {
  293.                 lot = t;
  294.                 lotm = tm;
  295.         } else    hit = t;
  296.     }
  297.     show(name, lot, TRUE);
  298.     show(name, hit, TRUE);
  299.     return hit;
  300. }
  301.  
  302. /*
  303. ** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
  304. */
  305.  
  306. static long
  307. delta(newp, oldp)
  308. struct tm *    newp;
  309. struct tm *    oldp;
  310. {
  311.     long    result;
  312.     int    tmy;
  313.  
  314.     if (newp->tm_year < oldp->tm_year)
  315.         return -delta(oldp, newp);
  316.     result = 0;
  317.     for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
  318.         result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
  319.     result += newp->tm_yday - oldp->tm_yday;
  320.     result *= HOURSPERDAY;
  321.     result += newp->tm_hour - oldp->tm_hour;
  322.     result *= MINSPERHOUR;
  323.     result += newp->tm_min - oldp->tm_min;
  324.     result *= SECSPERMIN;
  325.     result += newp->tm_sec - oldp->tm_sec;
  326.     return result;
  327. }
  328.  
  329. extern struct tm *    localtime();
  330.  
  331. static void
  332. show(zone, t, v)
  333. char *    zone;
  334. time_t    t;
  335. int    v;
  336. {
  337.     struct tm *    tmp;
  338.  
  339.     (void) printf("%-*s  ", longest, zone);
  340.     if (v)
  341.         (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
  342.     tmp = localtime(&t);
  343.     (void) printf("%.24s", asctime(tmp));
  344.     if (*abbr(tmp) != '\0')
  345.         (void) printf(" %s", abbr(tmp));
  346.     if (v) {
  347.         (void) printf(" isdst=%d", tmp->tm_isdst);
  348. #ifdef TM_GMTOFF
  349.         (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
  350. #endif /* defined TM_GMTOFF */
  351.     }
  352.     (void) printf("\n");
  353. }
  354.  
  355. static char *
  356. abbr(tmp)
  357. struct tm *    tmp;
  358. {
  359.     register char *    result;
  360.     static char    nada;
  361.  
  362.     if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
  363.         return &nada;
  364.     result = tzname[tmp->tm_isdst];
  365.     return (result == NULL) ? &nada : result;
  366. }
  367.