home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume36 / hancal / part01 < prev    next >
Encoding:
Text File  |  1993-03-06  |  61.4 KB  |  2,402 lines

  1. Newsgroups: comp.sources.misc
  2. From: ken@syd.dit.csiro.au (Ken Yap)
  3. Subject: v36i007:  hancal - Chinese calendar generator, Part01/01
  4. Message-ID: <1993Mar8.042433.23822@sparky.imd.sterling.com>
  5. X-Md4-Signature: ed582c2d39ef4453ca4317f4963e8276
  6. Date: Mon, 8 Mar 1993 04:24:33 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ken@syd.dit.csiro.au (Ken Yap)
  10. Posting-number: Volume 36, Issue 7
  11. Archive-name: hancal/part01
  12. Environment: UNIX
  13.  
  14. This program prints a Chinese calendar in a solar calendar.  By this I
  15. mean that the output format is as follows:  The solar month name is
  16. preceeded by the Chinese month for the first day of the month, with a +
  17. suffix if a leap month. The days are the Chinese dates. In this example
  18. below
  19.  
  20.     1/Feb 1993             2/Mar 1993             3/Apr 1993
  21. Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
  22.    10 11 12 13 14 15       9 10 11 12 13 14               10 11 12
  23. 16 17 18 19 20 21 22   15 16 17 18 19 20 21   13 14 15 16 17 18 19
  24. 23 24 25 26 27 28 29   22 23 24 25 26 27 28   20 21 22 23 24 25 26
  25.  1  2  3  4  5  6  7   29 30  1  2  3  4  5   27 28 29 30  1  2  3
  26.  8                      6  7  8  9             4  5  6  7  8  9
  27.  
  28. Monday 1 March 1993 is the 9th day of the 2nd month in the Chinese
  29. calendar.  Usage instructions are in the file cal.man.  Pay attention
  30. to the range limitations of the lunar program.
  31.  
  32. See the README file for further information.
  33. -------------
  34. #! /bin/sh
  35. # This is a shell archive, meaning:
  36. # 1. Remove everything above the #! /bin/sh line.
  37. # 2. Save the resulting text in a file.
  38. # 3. Execute the file with /bin/sh (not csh) to create:
  39. #    Makefile
  40. #    Makefile.lunar
  41. #    README
  42. #    cal.c
  43. #    cal.man
  44. #    hancal.c
  45. #    lunar.1
  46. #    lunar.bitmap
  47. #    lunar.c
  48. #    readme.txt
  49. #    tables.h
  50. # This archive created: Mon Mar  8 10:46:04 1993
  51. export PATH; PATH=/bin:/usr/bin:$PATH
  52. echo shar: "extracting 'Makefile'" '(194 characters)'
  53. if test -f 'Makefile'
  54. then
  55.     echo shar: "will not over-write existing file 'Makefile'"
  56. else
  57. cat << \SHAR_EOF > 'Makefile'
  58. # Makefile of HANCAL
  59.  
  60. CFLAGS= -O
  61.  
  62. hancal:    hancal.o lunar.o
  63.     $(CC) -o $@ hancal.o lunar.o
  64.  
  65. hancal.o:    hancal.c
  66.  
  67. lunar.o:    lunar.c
  68.     $(CC) -Dmain=lmain -Dusage=lusage -c lunar.c
  69.  
  70. clean:
  71.     rm *.o core
  72. SHAR_EOF
  73. if test 194 -ne "`wc -c < 'Makefile'`"
  74. then
  75.     echo shar: "error transmitting 'Makefile'" '(should have been 194 characters)'
  76. fi
  77. fi
  78. echo shar: "extracting 'Makefile.lunar'" '(91 characters)'
  79. if test -f 'Makefile.lunar'
  80. then
  81.     echo shar: "will not over-write existing file 'Makefile.lunar'"
  82. else
  83. cat << \SHAR_EOF > 'Makefile.lunar'
  84. # Makefile of LUNAR
  85.  
  86. CFLAGS= -O
  87.  
  88. lunar:    lunar.o
  89.     cc -o lunar lunar.o
  90.  
  91. clean:
  92.     rm *.o core
  93.  
  94. SHAR_EOF
  95. if test 91 -ne "`wc -c < 'Makefile.lunar'`"
  96. then
  97.     echo shar: "error transmitting 'Makefile.lunar'" '(should have been 91 characters)'
  98. fi
  99. fi
  100. echo shar: "extracting 'README'" '(1711 characters)'
  101. if test -f 'README'
  102. then
  103.     echo shar: "will not over-write existing file 'README'"
  104. else
  105. cat << \SHAR_EOF > 'README'
  106. HANCAL
  107. ======
  108.  
  109. This was a quick one hour hack. Hardly any original programming.
  110.  
  111. What I did was take a public domain reimplementation of Unix cal by
  112. Martin Minow and modify it slightly to call routines from Lunar 2.1, a
  113. Lunar Calendar Conversion Program by Fung F. Lee and Ricky Yeung.
  114. (Their copyright does not allow me to change the file, so I got around
  115. this by redefining the clashing names.  Perhaps they will separate out
  116. the useful conversion routines in a later release, hint hint.)
  117.  
  118. The hybrid program prints a Chinese calendar in a solar calendar.  By
  119. this I mean that the output format is as follows:  The solar month name
  120. is preceeded by the Chinese month for the first day of the month, with
  121. a + suffix if a leap month. The days are the Chinese dates. In this
  122. example below
  123.  
  124.     1/Feb 1993             2/Mar 1993             3/Apr 1993
  125. Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
  126.    10 11 12 13 14 15       9 10 11 12 13 14               10 11 12
  127. 16 17 18 19 20 21 22   15 16 17 18 19 20 21   13 14 15 16 17 18 19
  128. 23 24 25 26 27 28 29   22 23 24 25 26 27 28   20 21 22 23 24 25 26
  129.  1  2  3  4  5  6  7   29 30  1  2  3  4  5   27 28 29 30  1  2  3
  130.  8                      6  7  8  9             4  5  6  7  8  9
  131.  
  132. Monday 1 March 1993 is the 9th day of the 2nd month in the Chinese
  133. calendar.  Usage instructions are in the file cal.man.  Pay attention
  134. to the range limitations of the lunar program.
  135.  
  136. Bugs in the lunar conversion routines should be brought to the
  137. attention of the corresponding authors. For cal,c, If you find a bug,
  138. you've got the source so you fix it yourself.
  139.  
  140. This software has nothing to do with my employers.
  141.  
  142.     Ken Yap
  143.     ken@syd.dit.csiro.au
  144.     6 March 1993
  145. SHAR_EOF
  146. if test 1711 -ne "`wc -c < 'README'`"
  147. then
  148.     echo shar: "error transmitting 'README'" '(should have been 1711 characters)'
  149. fi
  150. fi
  151. echo shar: "extracting 'cal.c'" '(9180 characters)'
  152. if test -f 'cal.c'
  153. then
  154.     echo shar: "will not over-write existing file 'cal.c'"
  155. else
  156. cat << \SHAR_EOF > 'cal.c'
  157. /*
  158.  *             C A L E N D A R
  159.  *
  160.  * Usage:
  161.  *    cal    MM        If small, it's a month, if large, a year.
  162.  * or
  163.  *    cal    YYYY MM        year/month
  164.  * or
  165.  *    cal    MM YYYY    
  166.  */
  167.  
  168. #include <stdio.h>
  169. #include <time.h>
  170. #ifdef    decus
  171. int    $$narg = 1;            /* Don't prompt            */
  172. #endif
  173. #ifdef vms
  174. #include        ssdef
  175. #define    IO_ERROR    SS$_ABORT
  176. #define    IO_SUCCESS    SS$_NORMAL
  177. #endif
  178. #ifndef    IO_ERROR
  179. #define    IO_SUCCESS    0        /* Unix definitions        */
  180. #define    IO_ERROR    1
  181. #endif
  182. #define    EOS    0
  183.  
  184. #define    ENTRY_SIZE    3        /* 3 bytes per value        */
  185. #define DAYS_PER_WEEK    7        /* Sunday, etc.            */
  186. #define    WEEKS_PER_MONTH    6        /* Max. weeks in a month    */
  187. #define    MONTHS_PER_LINE    3        /* Three months across        */
  188. #define    MONTH_SPACE    3        /* Between each month        */
  189.  
  190. /*
  191.  * calendar() stuffs data into layout[],
  192.  * output() copies from layout[] to outline[], (then trims blanks).
  193.  */
  194. char    layout[MONTHS_PER_LINE][WEEKS_PER_MONTH][DAYS_PER_WEEK][ENTRY_SIZE];
  195. char    outline[(MONTHS_PER_LINE * DAYS_PER_WEEK * ENTRY_SIZE)
  196.         + (MONTHS_PER_LINE * MONTH_SPACE)
  197.         + 1];
  198.  
  199. char    *weekday = "Su Mo Tu We Th Fr Sa";
  200. char    *monthname[] = {
  201.     "???",                        /* No month 0    */
  202.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  203.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  204. };
  205.  
  206. main(argc, argv)
  207. int        argc;
  208. char        *argv[];
  209. {
  210.     register int    month;
  211.     register int    year;
  212.  
  213.     register int    arg1val;
  214.     int        arg1len;
  215.     int        arg2val;
  216.     int        tvec[2];
  217.     struct tm    *tm;
  218.  
  219.     time(&tvec[0]);
  220.     tm = localtime(&tvec[0]);
  221.     year = tm->tm_year + 1900;
  222.     month = tm->tm_mon + 1;
  223.     if (argc <= 1) {
  224.         /*
  225.          * No arguments mean do last, this, and next month
  226.          */
  227.         do3months(year, month);
  228.     }
  229.     else {
  230.         arg1val = atoi(argv[1]);
  231.         arg1len = strlen(argv[1]);
  232.         if (argc == 2) {
  233.         /*
  234.          * Only one argument, if small, it's a month.  If
  235.          * large, it's a year.  Note:
  236.          *    calend    0082    Year '82
  237.          *    calend    82    Year 1982
  238.          */
  239.         if (arg1len <= 2 && arg1val <= 12)
  240.             do3months(year, arg1val);
  241.         else {
  242.             if (arg1len <= 2 && arg1val > 0 && arg1val <= 99)
  243.             arg1val += 1900;
  244.             doyear(arg1val);
  245.         }
  246.         }
  247.         else {
  248.         /*
  249.          * Two arguments, allow YYYY MM or MM YYYY (but not
  250.          * MM YY or YY MM).
  251.          */
  252.         arg2val = atoi(argv[2]);
  253.         if (arg1len > 2)
  254.             do3months(arg1val, arg2val);
  255.         else
  256.             do3months(arg2val, arg1val);
  257.         }
  258.     }
  259.     exit(IO_SUCCESS);
  260. }
  261.  
  262. doyear(year)
  263. int        year;
  264. /*
  265.  * Print the calendar for an entire year.
  266.  */
  267. {
  268.     register int    month;
  269.  
  270.     if (year < 1 || year > 9999)
  271.         usage("year", year);
  272.     printf("\n\n\n%35d\n\n", year);
  273.     for (month = 1; month <= 12; month += MONTHS_PER_LINE) {
  274.         printf("\n\n%12s%23s%23s\n",
  275.             monthname[month],
  276.             monthname[month+1],
  277.             monthname[month+2]);
  278.         printf("%s   %s   %s\n", weekday, weekday, weekday);
  279.         calendar(year, month+0, 0);
  280.         calendar(year, month+1, 1);
  281.         calendar(year, month+2, 2);
  282.         output(3);
  283. #if MONTHS_PER_LINE != 3
  284.         << error, the above won't work >>
  285. #endif
  286.     }
  287.     printf("\n\n\n");
  288. }
  289.  
  290. do3months(thisyear, thismonth)
  291. int        thisyear;
  292. register int    thismonth;
  293. /*
  294.  * Do last month, this month, and next month.
  295.  */
  296. {
  297.     int        lastmonth;
  298.     int        lastyear;
  299.     int        nextmonth;
  300.     int        nextyear;
  301.  
  302. /*
  303.  * Range check year and month.  Avoid wraps that would
  304.  * cause embarrassment.
  305.  */
  306.     if (thisyear < 2 || thisyear > 9998)
  307.         usage("year", thisyear);
  308.     if (thismonth <= 0 || thismonth > 12)
  309.         usage("month", thismonth);
  310.  
  311.     lastyear = nextyear = thisyear;
  312.     if ((lastmonth = thismonth - 1) == 0) {
  313.         lastmonth = 12;
  314.         lastyear--;
  315.     }
  316.     if ((nextmonth = thismonth + 1) == 13) {
  317.         nextmonth = 1;
  318.         nextyear++;
  319.     }
  320.     printf("%9s%5d%18s%5d%18s%5d\n",
  321.         monthname[lastmonth], lastyear,
  322.         monthname[thismonth], thisyear,
  323.         monthname[nextmonth], nextyear);
  324.     printf("%s   %s   %s\n", weekday, weekday, weekday);
  325.     calendar(lastyear, lastmonth, 0);
  326.     calendar(thisyear, thismonth, 1);
  327.     calendar(nextyear, nextmonth, 2);
  328.     output(3);
  329. #if MONTHS_PER_LINE != 3
  330.     << error, the above won't work >>
  331. #endif
  332.     printf("\n\n\n");
  333. }
  334.     
  335. output(nmonths)
  336. int        nmonths;        /* Number of months to do    */
  337. /*
  338.  * Clean up and output the text.
  339.  */
  340. {
  341.     register int    week;
  342.     register int    month;
  343.     register char    *outp;
  344.  
  345.     for (week = 0; week < WEEKS_PER_MONTH; week++) {
  346.         outp = outline;
  347.         for (month = 0; month < nmonths; month++) {
  348.         /*
  349.          * The -1 in the following removes
  350.          * the unwanted leading blank from
  351.          * the entry for Sunday.
  352.          */
  353.         sprintf(outp, "%.*s%*s",
  354.             DAYS_PER_WEEK * ENTRY_SIZE - 1,
  355.             &layout[month][week][0][1],
  356.             MONTH_SPACE, "");
  357.         outp += (DAYS_PER_WEEK * ENTRY_SIZE) + MONTH_SPACE - 1;
  358.         }
  359.         while (outp > outline && outp[-1] == ' ')
  360.         outp--;
  361.         *outp = EOS;
  362.         puts(outline);
  363.     }
  364. }
  365.  
  366. calendar(year, month, index)
  367. int        year;
  368. int        month;
  369. int        index;        /* Which of the three months        */
  370. /*
  371.  * Actually build the calendar for this month.
  372.  */
  373. {
  374.     register char    *tp;
  375.     int        week;
  376.     register int    wday;
  377.     register int    today;
  378.  
  379.     setmonth(year, month);
  380.     for (week = 0; week < WEEKS_PER_MONTH; week++) {
  381.         for (wday = 0; wday < DAYS_PER_WEEK; wday++) {
  382.         tp = &layout[index][week][wday][0];
  383.         *tp++ = ' ';
  384.         today = getdate(week, wday);
  385.         if (today <= 0) {
  386.             *tp++ = ' ';
  387.             *tp++ = ' ';
  388.         }
  389.         else if (today < 10) {
  390.             *tp++ = ' ';
  391.             *tp   = (today + '0');
  392.         }
  393.         else {
  394.             *tp++ = (today / 10) + '0';
  395.             *tp   = (today % 10) + '0';
  396.         }
  397.         }
  398.     }
  399. }
  400.  
  401. usage(what, value)
  402. char        *what;
  403. int        value;
  404. /*
  405.  * Fatal parameter error
  406.  */
  407. {
  408.     fprintf(stderr, "Calendar parameter error: bad %s: %d\n",
  409.         what, value);
  410.     fprintf(stderr, "Usage: \"calend month\" or \"calend year month\"\n");
  411.     fprintf(stderr, "Year and month are integers.\n");
  412.     exit(IO_ERROR);
  413. }
  414.  
  415. /*
  416.  * Calendar routines, intended for eventual porting to TeX
  417.  *
  418.  * date(year, month, week, wday)
  419.  *    Returns the date on this week (0 is first, 5 last possible)
  420.  *    and day of the week (Sunday == 0)
  421.  *    Note: January is month 1.
  422.  *
  423.  * setmonth(year, month)
  424.  *    Parameters are as above, sets getdate() for this month.
  425.  *
  426.  * int
  427.  * getdate(week, wday)
  428.  *    Parameters are as above, uses the data set by setmonth()
  429.  */
  430.  
  431. /*
  432.  * This structure is used to pass data between setmonth() and getdate().
  433.  * It needs considerable expansion if the Julian->Gregorian change is
  434.  * to be extended to other countries.
  435.  */
  436.  
  437. static struct {
  438.     int        feb;        /* Days in February for this month    */
  439.     int        sept;        /* Days in September for this month    */
  440.     int        days_in_month;    /* Number of days in this month        */
  441.     int        dow_first;    /* Day of week of the 1st day in month    */
  442. } info;
  443.  
  444. static int day_month[] = {    /* 30 days hath September...        */
  445.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  446. };
  447.  
  448. int
  449. date(year, month, week, wday)
  450. int        year;        /* Calendar date being computed        */
  451. int        month;        /* January == 1                */
  452. int        week;        /* Week in the month 0..5 inclusive    */
  453. int        wday;        /* Weekday, Sunday == 0            */
  454. /*
  455.  * Return the date of the month that fell on this week and weekday.
  456.  * Return zero if it's out of range.
  457.  */
  458. {
  459.     setmonth(year, month);
  460.     return (getdate(week, wday));
  461. }
  462.  
  463. setmonth(year, month)
  464. int        year;            /* Year to compute        */
  465. int        month;            /* Month, January is month 1    */
  466. /*
  467.  * Setup the parameters needed to compute this month
  468.  * (stored in the info structure).
  469.  */
  470. {
  471.     register int        i;
  472.  
  473.     if (month < 1 || month > 12) {    /* Verify caller's parameters    */
  474.         info.days_in_month = 0;    /* Garbage flag            */
  475.         return;
  476.     }
  477.     info.dow_first = Jan1(year);    /* Day of January 1st for now    */
  478.     info.feb = 29;            /* Assume leap year        */
  479.     info.sept = 30;            /* Assume normal year        */
  480.     /*
  481.      * Determine whether it's an ordinary year, a leap year
  482.      * or the magical calendar switch year of 1752.
  483.      */
  484.     switch ((Jan1(year + 1) + 7 - info.dow_first) % 7) {
  485.     case 1:                /* Not a leap year        */
  486.         info.feb = 28;
  487.     case 2:                /* Ordinary leap year        */
  488.         break;
  489.  
  490.     default:            /* The magical moment arrives    */
  491.         info.sept = 19;        /* 19 days hath September    */
  492.         break;
  493.     }
  494.     info.days_in_month =
  495.           (month == 2) ? info.feb
  496.         : (month == 9) ? info.sept
  497.         : day_month[month];
  498.     for (i = 1; i < month; i++) {
  499.         switch (i) {        /* Special months?        */
  500.         case 2:            /* February            */
  501.         info.dow_first += info.feb;
  502.         break;
  503.  
  504.         case 9:
  505.         info.dow_first += info.sept;
  506.         break;
  507.  
  508.         default:
  509.         info.dow_first += day_month[i];
  510.         break;
  511.         }
  512.     }
  513.     info.dow_first %= 7;        /* Now it's Sunday to Saturday    */
  514. }
  515.  
  516. int
  517. getdate(week, wday)
  518. int        week;
  519. int        wday;
  520. {
  521.     register int    today;
  522.  
  523.     /*
  524.      * Get a first guess at today's date and make sure it's in range.
  525.      */
  526.     today = (week * 7) + wday - info.dow_first + 1;
  527.     if (today <= 0 || today > info.days_in_month)
  528.         return (0);
  529.     else if (info.sept == info.days_in_month && info.sept == 19 
  530.          && today >= 3)        /* The magical month?    */
  531.         return (today + 11);    /* If so, some dates changed    */
  532.     else                /* Otherwise,            */
  533.         return (today);        /* Return the date        */
  534. }
  535.  
  536. static int
  537. Jan1(year)
  538. int        year;
  539. /*
  540.  * Return day of the week for Jan 1 of the specified year.
  541.  */
  542. {
  543.     register int    day;
  544.  
  545.     day = year + 4 + ((year + 3) / 4);    /* Julian Calendar    */
  546.     if (year > 1800) {            /* If it's recent, do    */
  547.         day -= ((year - 1701) / 100);    /* Clavian correction    */
  548.         day += ((year - 1601) / 400);    /* Gregorian correction    */
  549.     }
  550.     if (year > 1752)            /* Adjust for Gregorian    */
  551.         day += 3;                /* calendar        */
  552.     return (day % 7);
  553. }
  554.  
  555. SHAR_EOF
  556. if test 9180 -ne "`wc -c < 'cal.c'`"
  557. then
  558.     echo shar: "error transmitting 'cal.c'" '(should have been 9180 characters)'
  559. fi
  560. fi
  561. echo shar: "extracting 'cal.man'" '(1573 characters)'
  562. if test -f 'cal.man'
  563. then
  564.     echo shar: "will not over-write existing file 'cal.man'"
  565. else
  566. cat << \SHAR_EOF > 'cal.man'
  567.  
  568.  
  569.  
  570.  
  571.        CAL(1)        local                CAL(1)
  572.  
  573.  
  574.  
  575.        USAGE
  576.  
  577.             cal [year] [month]
  578.         cal [month] [year]
  579.  
  580.        DESCRIPTION
  581.  
  582.             When invoked without arguments, calend prints a
  583.             calendar for the preceeding, current, and next
  584.             months of the current year.
  585.  
  586.             If a month is given (a value from 1 through 12),
  587.             it prints the three months centered on the requested
  588.             month.  For example,
  589.  
  590.                 calend 12
  591.  
  592.             Prints November and December for this year, and
  593.             January for next year.
  594.  
  595.             If a year is given, it prints a calendar for the
  596.             entire year:
  597.  
  598.                 calend 1985
  599.  
  600.             If both values are given, it prints the three months
  601.             centered on the indicated date:
  602.  
  603.                 calend 1752 9
  604.                 calend 9 1752
  605.  
  606.             Note that a three or four digit number will always be taken as
  607.             a year.  A one or two digit number will be either a month
  608.             or a year in the 20th century:
  609.  
  610.                 calend 78        (equals calend 1978)
  611.                 calend 0078        (early common era)
  612.  
  613.        BUGS
  614.  
  615.             The change from the Julian to Gregorian calendars follows
  616.             usage in England and her colonies.  Options should be provided
  617.             to process the change for other countries (and localities).
  618.             This is, however, a fairly complex task with little payback.
  619.  
  620.             The year didn't always start in January.
  621.  
  622.        REFERENCES
  623.  
  624.             Enclycopaedia Brittanica, 13th edition, Vol. 4, p. 987 et. seq.
  625.  
  626.        AUTHOR
  627.  
  628.             Martin Minow
  629.  
  630.  
  631.                             -1-
  632. SHAR_EOF
  633. if test 1573 -ne "`wc -c < 'cal.man'`"
  634. then
  635.     echo shar: "error transmitting 'cal.man'" '(should have been 1573 characters)'
  636. fi
  637. fi
  638. echo shar: "extracting 'hancal.c'" '(10062 characters)'
  639. if test -f 'hancal.c'
  640. then
  641.     echo shar: "will not over-write existing file 'hancal.c'"
  642. else
  643. cat << \SHAR_EOF > 'hancal.c'
  644. /*
  645.  *             C A L E N D A R
  646.  *
  647.  * Usage:
  648.  *    cal    MM        If small, it's a month, if large, a year.
  649.  * or
  650.  *    cal    YYYY MM        year/month
  651.  * or
  652.  *    cal    MM YYYY    
  653.  */
  654.  
  655. #include <stdio.h>
  656. #include <sys/types.h>
  657. #include <time.h>
  658. #ifdef    decus
  659. int    $$narg = 1;            /* Don't prompt            */
  660. #endif
  661. #ifdef vms
  662. #include        ssdef
  663. #define    IO_ERROR    SS$_ABORT
  664. #define    IO_SUCCESS    SS$_NORMAL
  665. #endif
  666. #ifndef    IO_ERROR
  667. #define    IO_SUCCESS    0        /* Unix definitions        */
  668. #define    IO_ERROR    1
  669. #endif
  670. #define    EOS    0
  671.  
  672. #define    ENTRY_SIZE    3        /* 3 bytes per value        */
  673. #define DAYS_PER_WEEK    7        /* Sunday, etc.            */
  674. #define    WEEKS_PER_MONTH    6        /* Max. weeks in a month    */
  675. #define    MONTHS_PER_LINE    3        /* Three months across        */
  676. #define    MONTH_SPACE    3        /* Between each month        */
  677.  
  678. /*
  679.  * calendar() stuffs data into layout[],
  680.  * output() copies from layout[] to outline[], (then trims blanks).
  681.  */
  682. char    layout[MONTHS_PER_LINE][WEEKS_PER_MONTH][DAYS_PER_WEEK][ENTRY_SIZE];
  683. char    outline[(MONTHS_PER_LINE * DAYS_PER_WEEK * ENTRY_SIZE)
  684.         + (MONTHS_PER_LINE * MONTH_SPACE)
  685.         + 1];
  686.  
  687. char    *weekday = "Su Mo Tu We Th Fr Sa";
  688. char    *monthname[] = {
  689.     "???",                        /* No month 0    */
  690.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  691.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  692. };
  693.  
  694. /*
  695.  * Imports from lunar.c
  696.  */
  697. typedef struct {
  698. int year, month, day, hour, weekday;
  699. int leap;    /* the lunar month is a leap month */
  700. } Date;
  701.  
  702. extern Date solar, lunar;
  703. extern void Solar2Lunar();
  704.  
  705. /* End of imports */
  706.  
  707. /*
  708.  * Interposed to return Chinese month and Solar monthname
  709.  */
  710. char *xmonthname(month, year)
  711. int        month;
  712. int        year;
  713. {
  714.     static char    buffer[13][10];
  715.  
  716.     solar.year = year;
  717.     solar.month = month;
  718.     solar.day = 1;
  719.     solar.hour = 0;
  720.     Solar2Lunar();
  721.     sprintf(buffer[month], "%d%s/%s", lunar.month, lunar.leap ? "+" : "",
  722.         monthname[month]);
  723.     return (buffer[month]);
  724. }
  725.  
  726. main(argc, argv)
  727. int        argc;
  728. char        *argv[];
  729. {
  730.     register int    month;
  731.     register int    year;
  732.  
  733.     register int    arg1val;
  734.     int        arg1len;
  735.     int        arg2val;
  736.     time_t        tval;
  737.     struct tm    *tm;
  738.  
  739.     tval = time(0);
  740.     tm = localtime(&tval);
  741.     year = tm->tm_year + 1900;
  742.     month = tm->tm_mon + 1;
  743.     if (argc <= 1) {
  744.         /*
  745.          * No arguments mean do last, this, and next month
  746.          */
  747.         do3months(year, month);
  748.     }
  749.     else {
  750.         arg1val = atoi(argv[1]);
  751.         arg1len = strlen(argv[1]);
  752.         if (argc == 2) {
  753.         /*
  754.          * Only one argument, if small, it's a month.  If
  755.          * large, it's a year.  Note:
  756.          *    calend    0082    Year '82
  757.          *    calend    82    Year 1982
  758.          */
  759.         if (arg1len <= 2 && arg1val <= 12)
  760.             do3months(year, arg1val);
  761.         else {
  762.             if (arg1len <= 2 && arg1val > 0 && arg1val <= 99)
  763.             arg1val += 1900;
  764.             doyear(arg1val);
  765.         }
  766.         }
  767.         else {
  768.         /*
  769.          * Two arguments, allow YYYY MM or MM YYYY (but not
  770.          * MM YY or YY MM).
  771.          */
  772.         arg2val = atoi(argv[2]);
  773.         if (arg1len > 2)
  774.             do3months(arg1val, arg2val);
  775.         else
  776.             do3months(arg2val, arg1val);
  777.         }
  778.     }
  779.     exit(IO_SUCCESS);
  780. }
  781.  
  782. doyear(year)
  783. int        year;
  784. /*
  785.  * Print the calendar for an entire year.
  786.  */
  787. {
  788.     register int    month;
  789.  
  790.     if (year < 1 || year > 9999)
  791.         usage("year", year);
  792.     printf("\n\n\n%35d\n\n", year);
  793.     for (month = 1; month <= 12; month += MONTHS_PER_LINE) {
  794.         printf("\n\n%12s%23s%23s\n",
  795.             xmonthname(month, year),
  796.             xmonthname(month+1, year),
  797.             xmonthname(month+2, year));
  798.         printf("%s   %s   %s\n", weekday, weekday, weekday);
  799.         calendar(year, month+0, 0);
  800.         calendar(year, month+1, 1);
  801.         calendar(year, month+2, 2);
  802.         output(3);
  803. #if MONTHS_PER_LINE != 3
  804.         << error, the above wont work >>
  805. #endif
  806.     }
  807.     printf("\n\n\n");
  808. }
  809.  
  810. do3months(thisyear, thismonth)
  811. int        thisyear;
  812. register int    thismonth;
  813. /*
  814.  * Do last month, this month, and next month.
  815.  */
  816. {
  817.     int        lastmonth;
  818.     int        lastyear;
  819.     int        nextmonth;
  820.     int        nextyear;
  821.  
  822. /*
  823.  * Range check year and month.  Avoid wraps that would
  824.  * cause embarrassment.
  825.  */
  826.     if (thisyear < 2 || thisyear > 9998)
  827.         usage("year", thisyear);
  828.     if (thismonth <= 0 || thismonth > 12)
  829.         usage("month", thismonth);
  830.  
  831.     lastyear = nextyear = thisyear;
  832.     if ((lastmonth = thismonth - 1) == 0) {
  833.         lastmonth = 12;
  834.         lastyear--;
  835.     }
  836.     if ((nextmonth = thismonth + 1) == 13) {
  837.         nextmonth = 1;
  838.         nextyear++;
  839.     }
  840.     printf("%9s%5d%18s%5d%18s%5d\n",
  841.         xmonthname(lastmonth, lastyear), lastyear,
  842.         xmonthname(thismonth, thisyear), thisyear,
  843.         xmonthname(nextmonth, nextyear), nextyear);
  844.     printf("%s   %s   %s\n", weekday, weekday, weekday);
  845.     calendar(lastyear, lastmonth, 0);
  846.     calendar(thisyear, thismonth, 1);
  847.     calendar(nextyear, nextmonth, 2);
  848.     output(3);
  849. #if MONTHS_PER_LINE != 3
  850.     << error, the above wont work >>
  851. #endif
  852.     printf("\n\n\n");
  853. }
  854.     
  855. output(nmonths)
  856. int        nmonths;        /* Number of months to do    */
  857. /*
  858.  * Clean up and output the text.
  859.  */
  860. {
  861.     register int    week;
  862.     register int    month;
  863.     register char    *outp;
  864.  
  865.     for (week = 0; week < WEEKS_PER_MONTH; week++) {
  866.         outp = outline;
  867.         for (month = 0; month < nmonths; month++) {
  868.         /*
  869.          * The -1 in the following removes
  870.          * the unwanted leading blank from
  871.          * the entry for Sunday.
  872.          */
  873.         sprintf(outp, "%.*s%*s",
  874.             DAYS_PER_WEEK * ENTRY_SIZE - 1,
  875.             &layout[month][week][0][1],
  876.             MONTH_SPACE, "");
  877.         outp += (DAYS_PER_WEEK * ENTRY_SIZE) + MONTH_SPACE - 1;
  878.         }
  879.         while (outp > outline && outp[-1] == ' ')
  880.         outp--;
  881.         *outp = EOS;
  882.         puts(outline);
  883.     }
  884. }
  885.  
  886. calendar(year, month, index)
  887. int        year;
  888. int        month;
  889. int        index;        /* Which of the three months        */
  890. /*
  891.  * Actually build the calendar for this month.
  892.  */
  893. {
  894.     register char    *tp;
  895.     int        week;
  896.     register int    wday;
  897.     register int    today;
  898.  
  899.     setmonth(year, month);
  900.     for (week = 0; week < WEEKS_PER_MONTH; week++) {
  901.         for (wday = 0; wday < DAYS_PER_WEEK; wday++) {
  902.         tp = &layout[index][week][wday][0];
  903.         *tp++ = ' ';
  904.         today = getdate(week, wday);
  905.         if (today <= 0) {
  906.             *tp++ = ' ';
  907.             *tp++ = ' ';
  908.         }
  909.         else if (today < 10) {
  910.             *tp++ = ' ';
  911.             *tp   = (today + '0');
  912.         }
  913.         else {
  914.             *tp++ = (today / 10) + '0';
  915.             *tp   = (today % 10) + '0';
  916.         }
  917.         }
  918.     }
  919. }
  920.  
  921. usage(what, value)
  922. char        *what;
  923. int        value;
  924. /*
  925.  * Fatal parameter error
  926.  */
  927. {
  928.     fprintf(stderr, "Calendar parameter error: bad %s: %d\n",
  929.         what, value);
  930.     fprintf(stderr, "Usage: \"calend month\" or \"calend year month\"\n");
  931.     fprintf(stderr, "Year and month are integers.\n");
  932.     exit(IO_ERROR);
  933. }
  934.  
  935. /*
  936.  * Calendar routines, intended for eventual porting to TeX
  937.  *
  938.  * date(year, month, week, wday)
  939.  *    Returns the date on this week (0 is first, 5 last possible)
  940.  *    and day of the week (Sunday == 0)
  941.  *    Note: January is month 1.
  942.  *
  943.  * setmonth(year, month)
  944.  *    Parameters are as above, sets getdate() for this month.
  945.  *
  946.  * int
  947.  * getdate(week, wday)
  948.  *    Parameters are as above, uses the data set by setmonth()
  949.  */
  950.  
  951. /*
  952.  * This structure is used to pass data between setmonth() and getdate().
  953.  * It needs considerable expansion if the Julian->Gregorian change is
  954.  * to be extended to other countries.
  955.  */
  956.  
  957. static struct {
  958.     int        feb;        /* Days in February for this month    */
  959.     int        sept;        /* Days in September for this month    */
  960.     int        days_in_month;    /* Number of days in this month        */
  961.     int        dow_first;    /* Day of week of the 1st day in month    */
  962. } info;
  963.  
  964. static int day_month[] = {    /* 30 days hath September...        */
  965.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  966. };
  967.  
  968. int
  969. date(year, month, week, wday)
  970. int        year;        /* Calendar date being computed        */
  971. int        month;        /* January == 1                */
  972. int        week;        /* Week in the month 0..5 inclusive    */
  973. int        wday;        /* Weekday, Sunday == 0            */
  974. /*
  975.  * Return the date of the month that fell on this week and weekday.
  976.  * Return zero if it's out of range.
  977.  */
  978. {
  979.     setmonth(year, month);
  980.     return (getdate(week, wday));
  981. }
  982.  
  983. setmonth(year, month)
  984. int        year;            /* Year to compute        */
  985. int        month;            /* Month, January is month 1    */
  986. /*
  987.  * Setup the parameters needed to compute this month
  988.  * (stored in the info structure).
  989.  */
  990. {
  991.     register int        i;
  992.  
  993.     if (month < 1 || month > 12) {    /* Verify caller's parameters    */
  994.         info.days_in_month = 0;    /* Garbage flag            */
  995.         return;
  996.     }
  997. /* mod for lunar.c */
  998.     solar.year = year;
  999.     solar.month = month;
  1000.     solar.hour = 0;
  1001. /* only solar.day left to set in getdate */
  1002.     info.dow_first = Jan1(year);    /* Day of January 1st for now    */
  1003.     info.feb = 29;            /* Assume leap year        */
  1004.     info.sept = 30;            /* Assume normal year        */
  1005.     /*
  1006.      * Determine whether it's an ordinary year, a leap year
  1007.      * or the magical calendar switch year of 1752.
  1008.      */
  1009.     switch ((Jan1(year + 1) + 7 - info.dow_first) % 7) {
  1010.     case 1:                /* Not a leap year        */
  1011.         info.feb = 28;
  1012.     case 2:                /* Ordinary leap year        */
  1013.         break;
  1014.  
  1015.     default:            /* The magical moment arrives    */
  1016.         info.sept = 19;        /* 19 days hath September    */
  1017.         break;
  1018.     }
  1019.     info.days_in_month =
  1020.           (month == 2) ? info.feb
  1021.         : (month == 9) ? info.sept
  1022.         : day_month[month];
  1023.     for (i = 1; i < month; i++) {
  1024.         switch (i) {        /* Special months?        */
  1025.         case 2:            /* February            */
  1026.         info.dow_first += info.feb;
  1027.         break;
  1028.  
  1029.         case 9:
  1030.         info.dow_first += info.sept;
  1031.         break;
  1032.  
  1033.         default:
  1034.         info.dow_first += day_month[i];
  1035.         break;
  1036.         }
  1037.     }
  1038.     info.dow_first %= 7;        /* Now it's Sunday to Saturday    */
  1039. }
  1040.  
  1041. int
  1042. getdate(week, wday)
  1043. int        week;
  1044. int        wday;
  1045. {
  1046.     register int    today;
  1047.  
  1048.     /*
  1049.      * Get a first guess at today's date and make sure it's in range.
  1050.      */
  1051.     today = (week * 7) + wday - info.dow_first + 1;
  1052.     if (today <= 0 || today > info.days_in_month)
  1053.         return (0);
  1054.     else if (info.sept == info.days_in_month && info.sept == 19 
  1055.          && today >= 3)        /* The magical month?    */
  1056. /* mod for lunar.c */
  1057.         return (solar.day = today + 11,
  1058.         Solar2Lunar(),
  1059.         lunar.day);    /* If so, some dates changed    */
  1060.     else                /* Otherwise,            */
  1061.         return (solar.day = today,
  1062.         Solar2Lunar(),
  1063.         lunar.day);        /* Return the date        */
  1064. }
  1065.  
  1066. static int
  1067. Jan1(year)
  1068. int        year;
  1069. /*
  1070.  * Return day of the week for Jan 1 of the specified year.
  1071.  */
  1072. {
  1073.     register int    day;
  1074.  
  1075.     day = year + 4 + ((year + 3) / 4);    /* Julian Calendar    */
  1076.     if (year > 1800) {            /* If it's recent, do    */
  1077.         day -= ((year - 1701) / 100);    /* Clavian correction    */
  1078.         day += ((year - 1601) / 400);    /* Gregorian correction    */
  1079.     }
  1080.     if (year > 1752)            /* Adjust for Gregorian    */
  1081.         day += 3;                /* calendar        */
  1082.     return (day % 7);
  1083. }
  1084.  
  1085. SHAR_EOF
  1086. if test 10062 -ne "`wc -c < 'hancal.c'`"
  1087. then
  1088.     echo shar: "error transmitting 'hancal.c'" '(should have been 10062 characters)'
  1089. fi
  1090. fi
  1091. echo shar: "extracting 'lunar.1'" '(2938 characters)'
  1092. if test -f 'lunar.1'
  1093. then
  1094.     echo shar: "will not over-write existing file 'lunar.1'"
  1095. else
  1096. cat << \SHAR_EOF > 'lunar.1'
  1097. .TH lunar 1 "23 July 1992"
  1098. .SH NAME
  1099. lunar (version 2.1) \- a calendar conversion utility
  1100. .SH SYNTAX
  1101. .B lunar
  1102. [
  1103. .B\-h
  1104. ] [
  1105. .B\-b
  1106. ] [
  1107. .B\-i
  1108. ] [
  1109. .B\-l
  1110. ]
  1111. .I year month day
  1112. [
  1113. .I hour
  1114. ]
  1115. .SH DESCRIPTION
  1116. The
  1117. .PN lunar
  1118. program performs date conversion between the Gregorian Solar Calendar (SC)
  1119. and the Chinese Lunar Calendar (LC).
  1120. Given a date in either calendar, the program also
  1121. outputs the corresponding "shengxiao" (animal of the year)
  1122. and "ganzhi" characters.
  1123. The date range currently covered is from about 1900 A.D. to 2049 A.D.
  1124. .PP
  1125. For the sake of convenience, we choose the convention such that the solar 
  1126. and lunar year numbers of the first day of a lunar year are the same.
  1127. For example, SC 1991.2.15 is LC 1991.1.1,
  1128. while SC 1991.2.14 is LC 1990.12.30.
  1129. Moreover, we choose the convention such that the solar and lunar hour numbers
  1130. (in 24-hour clock) of a date are the same, although a lunar day starts
  1131. at 23:00 of a solar day. This means that SC 1991.2.15.23 is LC 1991.1.2.23,
  1132. while SC 1991.2.16.0 is LC 1991.1.2.0,
  1133. and SC 1991.2.16.1 is LC 1991.1.2.1.
  1134. .PP
  1135. The standard time of the Lunar Calendar is
  1136. Beijing (Hong Kong) Standard Time, not GMT.
  1137. Be sure to adjust appropriately for other time zones
  1138. and "Day-light Saving Time".
  1139. .PP
  1140. In the Lunar Calendar,
  1141. a normal year has 12 months, and a leap year (run-nian) has 13 months,
  1142. where the extra month is called a "leap month" (run-yue).
  1143. For example, the leap month that follows immediately the 6-th lunar month
  1144. is called the 6-th leap month.
  1145. A (leap) month is either a short or long one, which has 29 or 30 days
  1146. respectively.
  1147. .PP
  1148. There are 10 gan's and 12 zhi's.
  1149. The ganzhi labeling of the year, month, day and hour of a date
  1150. is a member of the Cartesian product GxGxGxG, where G = {1,2,...,60}.
  1151. For example, "jia-zi" is 1, "yi-chou" is 2, and so on.
  1152. The ganzhi of the j-th leap month is the same as that of the j-th month.
  1153.  
  1154. The possible options are
  1155. .IP b
  1156. output ganzhi in special "bitmap" characters.
  1157. .IP h
  1158. output hanzi or Chinese characters encoded in (highest-bit-set) GB code.
  1159. .IP i
  1160. convert a lunar date to solar date.
  1161. The default is to convert a solar date to a lunar date.
  1162. .IP l
  1163. indicate the month is a lunar leap month.
  1164. This option is meaningful only when the "-i" option is used.
  1165. .SH COPYRIGHT
  1166. Copyright (C) 1988, 1989, 1991, 1992    Fung F. Lee and Ricky Yeung 
  1167. .sp
  1168. All rights reserved.
  1169. Permission to copy and distribute verbatim copies of the source code
  1170. and accompanied documents for non-commercial purposes is granted,
  1171. but changing them is not allowed.
  1172. There is absolutely no warranty for this program.
  1173. .SH AUTHORS
  1174. Fung F. Lee and Ricky Yeung
  1175. .SH ACKNOWLEDGEMENT
  1176. The special "bitmap" file "lunar.bitmap" was contributed by Weimin Liu.
  1177.  
  1178. Special thanks to Hwei Chen Ti who extended the tables from 2001 to 2049.
  1179. .SH BUGS
  1180. Bug reports and comments should be sent to Ricky.Yeung@Eng.Sun.Com or
  1181. lee@umunhum.stanford.edu.
  1182. .SH DISCLAIMER
  1183. This software has no connection with our employers.
  1184.  
  1185. SHAR_EOF
  1186. if test 2938 -ne "`wc -c < 'lunar.1'`"
  1187. then
  1188.     echo shar: "error transmitting 'lunar.1'" '(should have been 2938 characters)'
  1189. fi
  1190. fi
  1191. echo shar: "extracting 'lunar.bitmap'" '(1731 characters)'
  1192. if test -f 'lunar.bitmap'
  1193. then
  1194.     echo shar: "will not over-write existing file 'lunar.bitmap'"
  1195. else
  1196. cat << \SHAR_EOF > 'lunar.bitmap'
  1197.  /_______
  1198. /    |
  1199.  .___|___
  1200.  |   |  
  1201. _|___|____
  1202.      |
  1203.      |
  1204.   |-----|
  1205.   |     |
  1206.   |-----|
  1207.   |_____|
  1208.   |     |
  1209.   |     |
  1210.  /    \_|
  1211.   ._____.
  1212.   |     |
  1213.   |     |
  1214.   |_____|
  1215.   |     |
  1216.   |     |
  1217.   |_____|
  1218.        |
  1219. |-|  --|--
  1220. |_| ---`---     
  1221. | | ____|__
  1222. |-|  \  |
  1223.         |
  1224.       \_|
  1225.  |---:---|
  1226.  |   |   |
  1227.  |---|---|
  1228.  |   |   |
  1229.  |---|---|
  1230.      |
  1231.      |
  1232.  ______.
  1233.       /
  1234.      /
  1235.     /
  1236.    /
  1237.   /      |
  1238.  |______/
  1239.  _________
  1240.      |
  1241.  |---|---|
  1242.  |   ^   |
  1243.  |  / \  |
  1244.  |       |
  1245.  |     \_|
  1246.  _________
  1247.      |
  1248.      |
  1249.      |
  1250.      |
  1251.      |
  1252.    \_|
  1253.      |   \
  1254.  |---+----
  1255.  |   |   .
  1256.  |    \ /
  1257.  |     X
  1258.  |    / \
  1259. /        \_
  1260. ________.
  1261.         |
  1262.         |
  1263. --------|
  1264. |
  1265. |
  1266. |________|
  1267.  .____\____
  1268.  | ___|__.
  1269.  |  __|__|_
  1270.  | ___|__|
  1271.  |    ^  
  1272.  |   / \
  1273. /   /   \_
  1274.  ____\____
  1275.    \   /
  1276.   -------
  1277.      |
  1278.  ----+----
  1279.      |
  1280.      |
  1281.   ____.-'
  1282.      |
  1283.      |    
  1284.  ----+---'
  1285.      |
  1286.      |
  1287.   -------
  1288.   ___ ___
  1289.     / \  
  1290.  \_/___\/
  1291.   /__|__\
  1292. _/   ^   \_
  1293.     / \
  1294.   _/   \_
  1295.   ._____.
  1296.        /
  1297.       /
  1298.  ____|___.
  1299.      |
  1300.      |
  1301.    \_|
  1302.   ______.
  1303.     |   |
  1304.     |   |
  1305.   __|___|
  1306.     |   |
  1307.     |   |
  1308.  __/___/__
  1309. .____\____.
  1310. | _______ '
  1311.   .__|__.
  1312.   |__|__|
  1313.   |__|__|
  1314.    .   .
  1315.  _/     \_
  1316. ._-' ____.
  1317. |  |  |  |
  1318. |  |  |  |
  1319. | .|  |  |
  1320. |/ |  |\_|
  1321.   /   |
  1322.  /    |
  1323.  ._______.
  1324.  |_______
  1325.  |________ 
  1326.  | | \  .
  1327.  | |  \/
  1328.  | |   \
  1329. /  |/   \_
  1330. _______.
  1331. |      |
  1332. |      |
  1333. |------'
  1334. |
  1335. |
  1336. |_______|.
  1337.   /______
  1338.  /   |
  1339.      |
  1340.  ----+----
  1341.      |
  1342.      |
  1343.      |
  1344.   ___|___
  1345.      |
  1346. -----+----'
  1347.    / |\
  1348.   /  | \
  1349.  /   |  \_
  1350.    \_|
  1351.  .___|___.
  1352.  |   |   |
  1353.  |___|___|
  1354.  |   |   |
  1355.  |___|___|
  1356.      |
  1357.      |
  1358. ----------
  1359.  ._|__|_.
  1360.  | |  | |
  1361.  | |  | |
  1362.  |/    \|
  1363.  | ____ |
  1364.  |______|
  1365.      |   \
  1366.  |---+----
  1367.  |   |   .
  1368.  |__  \ /
  1369.  |     X
  1370.  |    / \
  1371. /        \_
  1372. _____\_____
  1373.    /  /
  1374.   /__/  /
  1375.     /  /
  1376.    /  /
  1377.   '  / \
  1378.   __/   \__
  1379. SHAR_EOF
  1380. if test 1731 -ne "`wc -c < 'lunar.bitmap'`"
  1381. then
  1382.     echo shar: "error transmitting 'lunar.bitmap'" '(should have been 1731 characters)'
  1383. fi
  1384. fi
  1385. echo shar: "extracting 'lunar.c'" '(18447 characters)'
  1386. if test -f 'lunar.c'
  1387. then
  1388.     echo shar: "will not over-write existing file 'lunar.c'"
  1389. else
  1390. cat << \SHAR_EOF > 'lunar.c'
  1391. char version[] = "Lunar Version 2.1 (July 23, 1992)";
  1392.  
  1393. /*----------------------------------------------------------------------------
  1394.  
  1395.  
  1396.           Lunar 2.1: A Calendar Conversion Program
  1397.                 for
  1398.     Gregorian Solar Calendar and Chinese Lunar Calendar
  1399.     ---------------------------------------------------
  1400.  
  1401.     By Fung F. Lee and Ricky Yeung
  1402.  
  1403.     Copyright (C) 1988,1989,1991,1992  Fung F. Lee and Ricky Yeung
  1404.  
  1405.     All rights reserved.
  1406.     Permission to copy and distribute verbatim copies of this
  1407.     document for non-commercial purposes is granted, but changing
  1408.     it is not allowed.
  1409.     There is absolutely no warranty for this program.
  1410.  
  1411.     Please send your comments and suggestions to the authors:
  1412.     Fung F. Lee    lee@umunhum.stanford.edu
  1413.     Ricky Yeung    Ricky.Yeung@Eng.Sun.Com
  1414.     
  1415.     The special "bitmap" file "lunar.bitmap" was contributed
  1416.     by Weimin Liu (weimin@alpha.ece.jhu.edu).
  1417.  
  1418.     Special thanks to Hwei Chen Ti (chetihc@nuscc.nus.sg or
  1419.     CHETIHC@NUSVM.Bitnet) who extended the tables from 2001 to 2049. 
  1420.  
  1421. ----------------------------------------------------------------------------*/
  1422.  
  1423. /*
  1424. This document contains Highest-bit-set GuoBiao (HGB) code, as adopted by
  1425. CCDOS on IBM PC compatibles, ChineseTalk 6.0 (GB version) on Macintosh,
  1426. and cxterm on UNIX and X window.  Hence, one may need to transfer this 
  1427. document as a **binary** file.
  1428.  
  1429. References:
  1430. 1. "Zhong1guo2 yin1yang2 ri4yue4 dui4zhao4 wan4nian2li4" by Lin2 Qi3yuan2.
  1431.    !6VP9zRuQtHUTB6TUUMrDj@z!7#.AV
  1432. 2. "Ming4li3 ge2xin1 zi3ping2 cui4yan2" by Xu2 Le4wu2.
  1433.    !6C|@m8oPBWSF=4bQT!7#.Pl
  1434. 3. Da1zhong4 wan4nian2li4.
  1435.    !64sVZMrDj@z!7
  1436. */ 
  1437.  
  1438.  
  1439. #include <stdio.h>
  1440. #include <string.h>
  1441.  
  1442. /* "Bitmap" constants */
  1443. #define    BMRow    7    /* number of rows for each bitmap */
  1444. #define    BMCol    11    /* number of columns for each bitmap */
  1445. #define    NBM    26    /* number of bitmaps */
  1446. #define NianBM  0
  1447. #define YueBM   1
  1448. #define RiBM    2
  1449. #define ShiBM   3
  1450. #define    GanBM    4
  1451. #define    ZhiBM    14
  1452.  
  1453. typedef struct {
  1454. int year, month, day, hour, weekday;
  1455. int leap;    /* the lunar month is a leap month */
  1456. } Date;
  1457.  
  1458. typedef char byte;
  1459.  
  1460. #include "tables.h"
  1461.  
  1462. static int daysInSolarMonth[13] = {
  1463.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  1464.  
  1465. static int moon[2] = {29,30}; /* a short (long) lunar month has 29 (30) days */
  1466.  
  1467. static    char    *Gan[] = {
  1468.     "Jia3",    "Yi3",     "Bing3", "Ding1", "Wu4",
  1469.     "Ji3",    "Geng1", "Xin1",  "Ren2",  "Gui3"
  1470. };
  1471.  
  1472. static    char    *Zhi[] = {
  1473.     "Zi3",    "Chou3", "Yin2",  "Mao3",  "Chen2", "Si4",
  1474.     "Wu3",    "Wei4",     "Shen1", "You3",  "Xu1",   "Hai4"
  1475. };
  1476.  
  1477. static    char   *ShengXiao[] = {
  1478.     "Mouse", "Ox", "Tiger", "Rabbit", "Dragon", "Snake",
  1479.     "Horse", "Goat", "Monkey", "Rooster", "Dog", "Pig"
  1480. };
  1481.  
  1482. static char *weekday[] = {
  1483.     "Sunday", "Monday", "Tuesday", "Wednesday",
  1484.     "Thursday", "Friday", "Saturday"
  1485. };
  1486.  
  1487. static    char    *GanGB[] = {
  1488.     "<W", "RR", "1{", "6!", "Nl",
  1489.     "<:", "8}", "PA", "HI", "9o"
  1490. };
  1491.  
  1492. static    char    *ZhiGB[] = {
  1493.     "WS", "3s", "Rz", "C.", "3=", "KH",
  1494.     "Ng", "N4", "Ij", "SO", "Pg", ":%"
  1495. };
  1496.  
  1497. static    char   *ShengXiaoGB[] = {
  1498.     "Js", "E#", ";"", "MC", "Az", "I_",
  1499.     "Bm", "Qr", ":o", "<&", "97", "Vm"
  1500. };
  1501.  
  1502. static char *weekdayGB[] = {
  1503.     "HU", "R;", "6~", "H}",
  1504.     "KD", "Ne", "Ay"
  1505. };
  1506.  
  1507.  
  1508. Date solar, lunar, gan, zhi, gan2, zhi2, lunar2;
  1509.  
  1510. int ymonth[Nyear];    /* number of lunar months in the years */
  1511. int yday[Nyear];    /* number of lunar days in the years */
  1512. int mday[Nmonth+1];    /* number of days in the months of the lunar year */
  1513. int jieAlert;        /* if there is uncertainty in JieQi calculation */
  1514.  
  1515. int    showHZ = 0;            /* output in hanzi */
  1516. int    showBM = 0;            /* output in bitmap */
  1517. char    BMfile[] = "lunar.bitmap";    /* bit map file */
  1518. char    GZBM[NBM][BMRow][BMCol];    /* the bitmap array */
  1519. char    *progname;
  1520.  
  1521. void    Solar2Lunar(), Lunar2Solar();
  1522. long    Solar2Day(), Solar2Day1(), Lunar2Day();
  1523. void    Day2Lunar(), Day2Solar();
  1524. int     make_yday(), make_mday(), GZcycle();
  1525. void    CalGZ();
  1526. int    JieDate(), JieDate();
  1527. void    readBM(), display3();
  1528. void    Report(), ReportE(), ReportBM(), ReportGB();
  1529. void    usage(), Error();
  1530.  
  1531.  
  1532. void main(argc, argv)
  1533. int argc;
  1534. char *argv[];
  1535. {
  1536.     int year, month, day, hour, i, k, option, inverse=0, leap=0;
  1537.     int dateInfo[4];
  1538.     
  1539.     progname = "lunar";
  1540.     printf("%s\n\n", version);
  1541.  
  1542.     for (k=1; k<argc && argv[k][0]=='-'; k++)
  1543.     {
  1544.     option = argv[k][1];
  1545.     switch(option)
  1546.     {
  1547.         case 'i': inverse = 1; break;
  1548.         case 'l': if (inverse) leap=1; else usage(); break;
  1549.         case 'h': showHZ = 1; break;
  1550.         case 'b': showBM = 1; break;
  1551.         default:  usage(); break;
  1552.     }
  1553.     }
  1554.     if (showBM) readBM();
  1555.     if (!((argc - k >= 3) && (argc - k <= 4))) usage();
  1556.     dateInfo[3] = 0;
  1557.     for (i=0; k<argc && i<4; k++, i++)
  1558.     {
  1559.     if (sscanf(argv[k], "%d", &dateInfo[i]) != 1)
  1560.         usage();
  1561.     }
  1562.     year = dateInfo[0];
  1563.     month = dateInfo[1];
  1564.     day = dateInfo[2];
  1565.     hour = dateInfo[3];
  1566.     if (!(year>=Cyear && year<Cyear+Nyear))
  1567.     Error("Year out of range.");
  1568.     if (!(month>=1 && month<=12))
  1569.     Error("Month out of range.");
  1570.     if (!(day>=1 && day<=31) || (inverse && day>30))
  1571.     Error("Day out of range.");
  1572.     if (!(hour>=0 && hour<=23))
  1573.     Error("Hour out of range.");
  1574.  
  1575.     if (!inverse && year==SolarFirstDate.year &&
  1576.     CmpDate(month, day, SolarFirstDate.month, SolarFirstDate.day)<0)
  1577.     Error("Date out of range.");
  1578.  
  1579.     if (inverse)
  1580.     {
  1581.     lunar.year = year;
  1582.     lunar.month = month;
  1583.     lunar.day = day;
  1584.     lunar.hour = hour;
  1585.     lunar.leap = leap;
  1586.     Lunar2Solar();
  1587.     }
  1588.     else
  1589.     {
  1590.     solar.year = year;
  1591.     solar.month = month;
  1592.     solar.day = day;
  1593.     solar.hour = hour;
  1594.     Solar2Lunar();
  1595.     }
  1596.     Report();
  1597. }
  1598.  
  1599. void usage()
  1600. {
  1601.     printf("Usage:\n\n");
  1602.     printf("Solar->Lunar:\t%s [-h] [-b] year month day [hour]\n", progname);
  1603.     printf("\t\t(in Solar Calendar, 24 hour clock)\n\n");
  1604.     printf("Lunar->Solar:\t%s [-h] [-b] -i [-l] year month day [hour]\n",
  1605.        progname);
  1606.     printf("\t\t(in Lunar Calendar, 24 hour clock)\n");
  1607.     printf("\t\t-l means the month is a leap month (\"run4 yue4\")\n\n");
  1608.     printf("\t\t-h means output in hanzi (GB)\n");
  1609.     printf("\t\t-b means output in \"bitmap\"\n\n");
  1610.     printf("Date range: about %d years from the Solar Date %d.%d.%d\n", Nyear,
  1611.        SolarFirstDate.year, SolarFirstDate.month, SolarFirstDate.day);
  1612.     exit(1);
  1613. }
  1614.  
  1615.  
  1616. void Solar2Lunar()
  1617. {
  1618.  
  1619.     long offset;
  1620.     Date *d;
  1621.  
  1622.     offset = Solar2Day(&solar);
  1623.     solar.weekday = (offset + SolarFirstDate.weekday) % 7;
  1624.     
  1625.     /* A lunar day begins at 11 p.m. */
  1626.     if (solar.hour == 23)
  1627.     offset++;
  1628.  
  1629.     Day2Lunar(offset, &lunar);
  1630.     lunar.hour = solar.hour;
  1631.     CalGZ(offset, &lunar, &gan, &zhi);
  1632.  
  1633.     jieAlert = JieDate(&solar, &lunar2);
  1634.     lunar2.day = lunar.day;
  1635.     lunar2.hour = lunar.hour;
  1636.     CalGZ(offset, &lunar2, &gan2, &zhi2);
  1637. }
  1638.  
  1639.  
  1640. void Lunar2Solar()
  1641. {
  1642.     long offset;
  1643.     int adj;
  1644.     Date *d;
  1645.  
  1646.     /* A solar day begins at 12 a.m. */
  1647.     adj = (lunar.hour == 23)? -1 : 0;
  1648.     offset = Lunar2Day(&lunar);
  1649.     solar.weekday = (offset+ adj + SolarFirstDate.weekday) % 7;
  1650.     Day2Solar(offset + adj, &solar);
  1651.     solar.hour = lunar.hour;
  1652.     CalGZ(offset, &lunar, &gan, &zhi);
  1653.  
  1654.     jieAlert = JieDate(&solar, &lunar2);
  1655.     lunar2.day = lunar.day;
  1656.     lunar2.hour = lunar.hour;
  1657.     CalGZ(offset, &lunar2, &gan2, &zhi2);
  1658. }
  1659.  
  1660.  
  1661. #define    LeapYear(y)    (((y)%4==0) && ((y)%100!=0) || ((y)%400==0))
  1662. #define BYEAR        1201
  1663. /* BYEAR % 4 == 1  and BYEAR % 400 == 1 for easy calculation of leap years */
  1664. /* assert(BYEAR <= SolarFirstDate.year) */
  1665.  
  1666. long Solar2Day(d)
  1667. Date *d;
  1668. {
  1669.     return (Solar2Day1(d) - Solar2Day1(&SolarFirstDate));
  1670. }
  1671.  
  1672.  
  1673. /* Compute the number of days from the Solar date BYEAR.1.1 */
  1674. long Solar2Day1(d)
  1675. Date *d;
  1676. {
  1677.     long offset, delta;
  1678.     int i;
  1679.  
  1680.     delta = d->year - BYEAR;
  1681.     if (delta<0) Error("Internal error: pick a larger constant for BYEAR.");
  1682.     offset = delta * 365 + delta / 4 - delta / 100 + delta / 400;
  1683.     for (i=1; i< d->month; i++)
  1684.         offset += daysInSolarMonth[i];
  1685.     if ((d->month > 2) && LeapYear(d->year))
  1686.     offset++;
  1687.     offset += d->day - 1;
  1688.  
  1689.     if ((d->month == 2) && LeapYear(d->year))
  1690.     {
  1691.     if (d->day > 29) Error("Day out of range.");
  1692.     }
  1693.     else if (d->day > daysInSolarMonth[d->month]) Error("Day out of range.");
  1694.     return offset;
  1695. }
  1696.  
  1697.  
  1698. /* Compute offset days of a lunar date from the beginning of the table */
  1699. long Lunar2Day(d)
  1700. Date *d;
  1701. {
  1702.     long offset = 0;
  1703.     int year, i, m, nYear, leapMonth;
  1704.  
  1705.     nYear = make_yday();
  1706.     year = d->year - LunarFirstDate.year;
  1707.     for (i=0; i<year; i++)
  1708.     offset += yday[i];
  1709.  
  1710.     leapMonth = make_mday(year);
  1711.     if ((d->leap) && (leapMonth!=d->month))
  1712.     {
  1713.     printf("%d is not a leap month in year %d.\n", d->month, d->year);
  1714.     exit(1);
  1715.     }
  1716.     for (m=1; m<d->month; m++)
  1717.     offset += mday[m];
  1718.     if (leapMonth && 
  1719.     ((d->month>leapMonth) || (d->leap && (d->month==leapMonth))))
  1720.     offset += mday[m++];
  1721.     offset += d->day - 1;
  1722.  
  1723.     if (d->day > mday[m]) Error("Day out of range.");
  1724.  
  1725.     return offset;
  1726. }
  1727.  
  1728.  
  1729. void Day2Lunar(offset, d)
  1730. long offset;
  1731. Date *d;
  1732.  
  1733. {
  1734.     int i, m, nYear, leapMonth;
  1735.     
  1736.     nYear = make_yday();
  1737.     for (i=0; i<nYear && offset > 0; i++)
  1738.     offset -= yday[i];
  1739.     if (offset<0)
  1740.     offset += yday[--i];
  1741.     if (i==Nyear) Error("Year out of range.");
  1742.     d->year = i + LunarFirstDate.year;
  1743.  
  1744.     leapMonth = make_mday(i);
  1745.     for (m=1; m<=Nmonth && offset>0; m++)
  1746.     offset -= mday[m];
  1747.     if (offset<0)
  1748.     offset += mday[--m];
  1749.  
  1750.     d->leap = 0;    /* don't know leap or not yet */
  1751.  
  1752.     if (leapMonth>0)    /* has leap month */
  1753.     {
  1754.     /* if preceeding month number is the leap month,
  1755.        this month is the actual extra leap month */
  1756.     d->leap = (leapMonth == (m - 1));
  1757.  
  1758.     /* month > leapMonth is off by 1, so adjust it */
  1759.     if (m > leapMonth) --m;
  1760.     }
  1761.  
  1762.     d->month = m;
  1763.     d->day = offset + 1;
  1764. }
  1765.  
  1766.  
  1767. void Day2Solar(offset, d)
  1768. long offset;
  1769. Date *d;
  1770. {
  1771.     int    i, m, days;
  1772.  
  1773.     /* offset is the number of days from SolarFirstDate */
  1774.     offset -= Solar2Day(&LunarFirstDate);  /* the argument is negative */
  1775.     /* offset is now the number of days from SolarFirstDate.year.1.1 */
  1776.  
  1777.     for (i=SolarFirstDate.year;
  1778.          (i<SolarFirstDate.year+Nyear) && (offset > 0);     i++) 
  1779.     offset -= 365 + LeapYear(i);
  1780.     if (offset<0)
  1781.     {
  1782.     --i;     /* LeapYear is a macro */
  1783.     offset += 365 + LeapYear(i);
  1784.     }
  1785.     if (i==(SolarFirstDate.year + Nyear)) Error("Year out of range.");
  1786.     d->year = i;
  1787.     
  1788.     /* assert(offset<(365+LeapYear(i))); */
  1789.     for (m=1; m<=12; m++)
  1790.     {
  1791.     days = daysInSolarMonth[m];
  1792.     if ((m==2) && LeapYear(i))    /* leap February */
  1793.         days++;
  1794.     if (offset<days)
  1795.     {
  1796.         d->month = m;
  1797.         d->day = offset + 1;
  1798.         return;
  1799.     }
  1800.     offset -= days;
  1801.     }
  1802. }
  1803.  
  1804.  
  1805. int GZcycle(g, z)
  1806. int g, z;
  1807. {
  1808.     int gz;
  1809.  
  1810.     for (gz = z; gz % 10 != g && gz < 60; gz += 12) ;
  1811.     if (gz >= 60) printf("internal error\n");
  1812.     return gz+1;
  1813. }
  1814.          
  1815.  
  1816. void CalGZ(offset, d, g, z)
  1817. long offset;
  1818. Date *d, *g, *z;
  1819. {
  1820.     int    year, month;
  1821.         
  1822.     year = d->year - LunarFirstDate.year;
  1823.     month = year * 12 + d->month - 1;   /* leap months do not count */
  1824.  
  1825.     g->year = (GanFirstDate.year + year) % 10;
  1826.     z->year = (ZhiFirstDate.year + year) % 12;
  1827.     g->month = (GanFirstDate.month + month) % 10;
  1828.     z->month = (ZhiFirstDate.month + month) % 12;
  1829.     g->day = (GanFirstDate.day + offset) % 10;
  1830.     z->day = (ZhiFirstDate.day + offset) % 12;
  1831.     z->hour = ((d->hour + 1) / 2) % 12;
  1832.     g->hour = (g->day * 12 + z->hour) % 10;
  1833. }
  1834.  
  1835.  
  1836. void Error(s)
  1837. char    *s;
  1838. {
  1839.     printf("%s\n",s);
  1840.     exit(1);
  1841. }
  1842.  
  1843.  
  1844. /* Compare two dates and return <,=,> 0 if the 1st is <,=,> the 2nd */
  1845. int CmpDate(month1, day1, month2, day2)
  1846. int month1, day1, month2, day2;
  1847. {
  1848.     if (month1!=month2) return(month1-month2);
  1849.     if (day1!=day2) return(day1-day2);
  1850.     return(0);
  1851. }
  1852.  
  1853.  
  1854. /*
  1855.    Given a solar date, find the "lunar" date for the purpose of
  1856.    calculating the "4-columns" by taking jie into consideration.
  1857. */
  1858. int JieDate(ds, dl)
  1859. Date *ds, *dl;
  1860. {
  1861.     int m, flag;
  1862.  
  1863.     if (ds->month==1)
  1864.     {
  1865.     flag = CmpDate(ds->month, ds->day,
  1866.                1, fest[ds->year - SolarFirstDate.year - 1][11]);
  1867.     if (flag<0) dl->month = 11;
  1868.     else if (flag>0) dl->month = 12;
  1869.     dl->year = ds->year - 1;
  1870.     return(flag==0);
  1871.     }
  1872.     for (m=2; m<=12; m++)
  1873.     {
  1874.     flag = CmpDate(ds->month, ds->day,
  1875.                m, fest[ds->year - SolarFirstDate.year][m-2]);
  1876.     if (flag==0) m++;
  1877.     if (flag<=0) break;
  1878.     }
  1879.     dl->month = (m-2) % 12;
  1880.     dl->year = ds->year;
  1881.     if ((dl->month)==0)
  1882.     {
  1883.     dl->year = ds->year - 1;
  1884.     dl->month = 12;
  1885.     }
  1886.     return(flag==0);
  1887. }
  1888.  
  1889.  
  1890. /* Compute the number of days in each lunar year in the table */
  1891. int make_yday()
  1892. {
  1893.     int year, i, leap;
  1894.     long code;
  1895.     
  1896.     for (year = 0; year < Nyear; year++)
  1897.     {
  1898.     code = yearInfo[year];
  1899.     leap = code & 0xf;
  1900.     yday[year] = 0;
  1901.     if (leap != 0)
  1902.     {
  1903.         i = (code >> 16) & 0x1;
  1904.         yday[year] += moon[i];
  1905.     }
  1906.     code >>= 4;
  1907.     for (i = 0; i < Nmonth-1; i++)
  1908.     {
  1909.         yday[year] += moon[code&0x1];
  1910.         code >>= 1;
  1911.     }
  1912.     ymonth[year] = 12;
  1913.     if (leap != 0) ymonth[year]++;
  1914.     }
  1915.     return Nyear;
  1916. }
  1917.  
  1918.  
  1919. /* Compute the days of each month in the given lunar year */
  1920. int make_mday(year)
  1921. int year;
  1922. {
  1923.     int i, leapMonth;
  1924.     long code;
  1925.     
  1926.     code = yearInfo[year];
  1927.     leapMonth = code & 0xf;
  1928.     /* leapMonth == 0 means no leap month */
  1929.     code >>= 4;
  1930.     if (leapMonth == 0)
  1931.     {
  1932.     mday[Nmonth] = 0;
  1933.     for (i = Nmonth-1; i >= 1; i--)
  1934.     {
  1935.         mday[i] = moon[code&0x1];
  1936.         code >>= 1;
  1937.     }
  1938.     }
  1939.     else
  1940.     {
  1941.     /* 
  1942.       There is a leap month (run4 yue4) L in this year.
  1943.       mday[1] contains the number of days in the 1-st month;
  1944.       mday[L] contains the number of days in the L-th month;
  1945.       mday[L+1] contains the number of days in the L-th leap month;
  1946.       mday[L+2] contains the number of days in the L+1 month, etc.
  1947.  
  1948.       cf. yearInfo[]: info about the leap month is encoded differently.
  1949.     */
  1950.     i = (yearInfo[year] >> 16) & 0x1;
  1951.     mday[leapMonth+1] = moon[i];
  1952.     for (i = Nmonth; i >= 1; i--)
  1953.     {
  1954.         if (i == leapMonth+1) i--;
  1955.         mday[i] = moon[code&0x1];
  1956.         code >>= 1;
  1957.     }
  1958.     }
  1959.     return leapMonth;
  1960. }
  1961.  
  1962.  
  1963. void Report()
  1964. {
  1965.     if (showHZ)
  1966.     ReportGB();
  1967.     else if (showBM)
  1968.     ReportBM();
  1969.     else
  1970.     ReportE();
  1971. }
  1972.  
  1973.  
  1974. void ReportGB()
  1975. {
  1976.     printf("%s%d%s%2d%s%2d%s%2d%s%s%s\n", "Qt@z#:!!",
  1977.        solar.year, "Dj", solar.month, "TB", solar.day,
  1978.        "HU", solar.hour, "J1!!",
  1979.        "PGFZ", weekdayGB[solar.weekday]); 
  1980.     printf("%s%d%s%s%2d%s%2d%s%s%s%s%s\n", "Ru@z#:!!",
  1981.        lunar.year, "Dj", (lunar.leap? "Hr":""),
  1982.        lunar.month, "TB", lunar.day, "HU", 
  1983.        ZhiGB[zhi.hour], "J1!!",
  1984.        "IzP$Jt", ShengXiaoGB[zhi.year]);
  1985.     printf("%s%s%s%s%s%s%s%s%s%s%s%s%s\n", "8IV'#:!!",
  1986.        GanGB[gan.year], ZhiGB[zhi.year], "Dj!!",
  1987.        GanGB[gan.month], ZhiGB[zhi.month], "TB!!",
  1988.        GanGB[gan.day], ZhiGB[zhi.day], "HU!!",
  1989.        GanGB[gan.hour], ZhiGB[zhi.hour], "J1!!");
  1990.     printf("%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
  1991.        "SCKDVyIqKcMFKcV.J13=0KWV#:!!",
  1992.        GanGB[gan2.year], ZhiGB[zhi2.year], "Dj!!",
  1993.        GanGB[gan2.month], ZhiGB[zhi2.month], "TB!!",
  1994.        GanGB[gan2.day], ZhiGB[zhi2.day], "HU!!",
  1995.        GanGB[gan2.hour], ZhiGB[zhi2.hour], "J1!!");
  1996.     if (jieAlert)
  1997.     {
  1998.     printf("* %s, %s\n", "JGHUN*=Z",
  1999.            "TBVy?ID\R*P^8D");
  2000.     if (lunar2.month==1)
  2001.         printf("* %s\n", "DjVyR`?ID\R*P^8D");
  2002.     printf("* %s\n", "Gk2iSP=ZFxJ1<dV.MrDj@z");
  2003.     }
  2004. }
  2005.  
  2006.  
  2007. void ReportE()
  2008. {
  2009.     printf("Solar : %d.%d.%d.%d\t%s\n", solar.year, solar.month, solar.day,
  2010.        solar.hour, weekday[solar.weekday]);
  2011.     printf("Lunar : %d.%d%s.%d.%d\tShengXiao: %s\n",
  2012.        lunar.year, lunar.month, (lunar.leap?"Leap":""), lunar.day,
  2013.        lunar.hour, ShengXiao[zhi.year] );
  2014.     printf("GanZhi: %s-%s.%s-%s.%s-%s.%s-%s\n",
  2015.        Gan[gan.year], Zhi[zhi.year], Gan[gan.month], Zhi[zhi.month],
  2016.        Gan[gan.day], Zhi[zhi.day], Gan[gan.hour], Zhi[zhi.hour]);
  2017.     printf("        (GanZhi Order)\t%d-%d.%d-%d.%d-%d.%d-%d\n",
  2018.        gan.year+1, zhi.year+1, gan.month+1, zhi.month+1,
  2019.        gan.day+1, zhi.day+1, gan.hour+1, zhi.hour+1);
  2020.     printf("        (JiaZi Cycle)\t%d.%d.%d.%d\n\n",
  2021.        GZcycle(gan.year, zhi.year), GZcycle(gan.month, zhi.month),
  2022.        GZcycle(gan.day, zhi.day), GZcycle(gan.hour, zhi.hour));
  2023.     printf("BaZi (8-characters) according to 'Four Column Calculation':\n");
  2024.     printf("        %s-%s.%s-%s.%s-%s.%s-%s\n",
  2025.        Gan[gan2.year], Zhi[zhi2.year], Gan[gan2.month], Zhi[zhi2.month],
  2026.        Gan[gan2.day], Zhi[zhi2.day], Gan[gan2.hour], Zhi[zhi2.hour]);
  2027.     printf("        (GanZhi Order)\t%d-%d.%d-%d.%d-%d.%d-%d\n",
  2028.        gan2.year+1, zhi2.year+1, gan2.month+1, zhi2.month+1,
  2029.        gan2.day+1, zhi2.day+1, gan2.hour+1, zhi2.hour+1);
  2030.     printf("        (JiaZi Cycle)\t%d.%d.%d.%d\n\n",
  2031.        GZcycle(gan2.year, zhi2.year), GZcycle(gan2.month, zhi2.month),
  2032.        GZcycle(gan2.day, zhi2.day), GZcycle(gan2.hour, zhi2.hour));
  2033.     if (jieAlert)
  2034.     {
  2035.     printf("* The month column may need adjustment because the date falls on a jie.\n");
  2036.     if (lunar2.month==1)
  2037.         printf("* The day column may need adjustment, too.\n");
  2038.     printf("* Please consult a detailed conversion table.\n");
  2039.     }
  2040. }
  2041.  
  2042.  
  2043. void ReportBM()
  2044. {
  2045.     printf("Solar : %d.%d.%d.%d\t%s\n", solar.year, solar.month, solar.day,
  2046.        solar.hour, weekday[solar.weekday]);
  2047.     printf("Lunar : %d.%d%s.%d.%d\tShengXiao: %s\n",
  2048.        lunar.year, lunar.month, (lunar.leap?"Leap":""), lunar.day,
  2049.        lunar.hour, ShengXiao[zhi.year] );
  2050.     printf("GanZhi: \n\n");
  2051.     display3(gan.year+GanBM, zhi.year+ZhiBM, NianBM);
  2052.     display3(gan.month+GanBM, zhi.month+ZhiBM, YueBM);
  2053.     display3(gan.day+GanBM, zhi.day+ZhiBM, RiBM);
  2054.     display3(gan.hour+GanBM, zhi.hour+ZhiBM, ShiBM);
  2055.     printf("\nBaZi  : \n\n");
  2056.     display3(gan2.year+GanBM, zhi2.year+ZhiBM, NianBM);
  2057.     display3(gan2.month+GanBM, zhi2.month+ZhiBM, YueBM);
  2058.     display3(gan2.day+GanBM, zhi2.day+ZhiBM, RiBM);
  2059.     display3(gan2.hour+GanBM, zhi2.hour+ZhiBM, ShiBM);
  2060.     if (jieAlert)
  2061.     {
  2062.     printf("* The month column may need adjustment because the date falls on a jie.\n");
  2063.     if (lunar2.month==1)
  2064.         printf("* The day column may need adjustment, too.\n");
  2065.     printf("* Please consult a detailed conversion table.\n");
  2066.     }
  2067. }
  2068.  
  2069.  
  2070. void readBM()
  2071. {
  2072.     int    i, j, k, m, c;
  2073.     FILE *fp;
  2074.  
  2075.     if ((fp=fopen(BMfile,"r"))==NULL)
  2076.     {
  2077.     printf("Bitmap file '%s' not found.\n",BMfile);
  2078.     exit(1);
  2079.     }
  2080.     for (i=0; i<NBM; i++)
  2081.       for (j=0; j<BMRow; j++)
  2082.       {
  2083.       k = 0;
  2084.       for (;;)
  2085.       {
  2086.           c = getc(fp);
  2087.           if ((c==EOF) || (c=='\n')) break;
  2088.           GZBM[i][j][k++] = c;
  2089.       }
  2090.       for (m=k; m<BMCol; m++) GZBM[i][j][m] = ' ';
  2091.       }
  2092.     fclose(fp);
  2093. }
  2094.  
  2095.  
  2096. /* Display three ganzhi characters in a row */
  2097. void display3(i, j, k)
  2098. int i,j,k;
  2099. {
  2100.     int    r,c;
  2101.  
  2102.     for (r=0; r<BMRow; r++)
  2103.     {
  2104.     for (c=0; c<BMCol; c++) putchar(GZBM[i][r][c]);
  2105.     printf("  ");
  2106.     for (c=0; c<BMCol; c++) putchar(GZBM[j][r][c]);
  2107.     printf("    ");
  2108.     for (c=0; c<BMCol; c++) putchar(GZBM[k][r][c]);
  2109.     putchar('\n');
  2110.     }
  2111.     putchar('\n');
  2112. }
  2113.  
  2114.  
  2115. SHAR_EOF
  2116. if test 18447 -ne "`wc -c < 'lunar.c'`"
  2117. then
  2118.     echo shar: "error transmitting 'lunar.c'" '(should have been 18447 characters)'
  2119. fi
  2120. fi
  2121. echo shar: "extracting 'readme.txt'" '(357 characters)'
  2122. if test -f 'readme.txt'
  2123. then
  2124.     echo shar: "will not over-write existing file 'readme.txt'"
  2125. else
  2126. cat << \SHAR_EOF > 'readme.txt'
  2127. This is a public-domain reimplementation of the Unix "cal" calendar program.
  2128. The inner-loop -- that puts a date into the calendar -- was designed
  2129. for eventual rewriting in LaTeX (but I haven't gotten that working yet).
  2130.  
  2131. If you aren't interested in Julian/Gregorian hacks, the code can
  2132. be considerably simplified.
  2133.  
  2134. Happy New Year.
  2135.  
  2136. Martin Minow
  2137. decvax!minow
  2138. SHAR_EOF
  2139. if test 357 -ne "`wc -c < 'readme.txt'`"
  2140. then
  2141.     echo shar: "error transmitting 'readme.txt'" '(should have been 357 characters)'
  2142. fi
  2143. fi
  2144. echo shar: "extracting 'tables.h'" '(11140 characters)'
  2145. if test -f 'tables.h'
  2146. then
  2147.     echo shar: "will not over-write existing file 'tables.h'"
  2148. else
  2149. cat << \SHAR_EOF > 'tables.h'
  2150. /* 
  2151.  * tables.h: contains tables and parameters for lunar.c
  2152.  */
  2153. #define Cyear    1900    /* Note that LC1900.1.1 is SC1900.1.31 */
  2154. #define Nyear    150    /* number of years covered by the table */
  2155. #define Nmonth  13    /* maximum number of months in a lunar year */
  2156.  
  2157. static Date SolarFirstDate = {
  2158.     /* Wednesday, 12 a.m., 31 January, 1900 */
  2159.     1900, 1, 31, 0, 3, 0
  2160.     };
  2161.  
  2162. static Date LunarFirstDate = {
  2163.     /* Wednesday, 12 a.m., First day, First month, 1900 */
  2164.     1900, 1, 1, 0, 3, 0
  2165.     };
  2166.  
  2167. static Date GanFirstDate = {
  2168.     /* geng1-nian2 wu4-yue4 jia3-ri4 jia3-shi2 */
  2169.        6,          4,       0,       0,           3, 0
  2170.     };
  2171.  
  2172. static Date ZhiFirstDate = {
  2173.     /* zi3-nian2 yin2-yue4 chen2-ri4 zi3-shi2 */
  2174.        0,        2,        4,        0,           3, 0
  2175.     };
  2176.  
  2177. static long yearInfo[Nyear] = {
  2178.     /* encoding:
  2179.         b bbbbbbbbbbbb bbbb
  2180.        bit#        1 111111000000 0000
  2181.             6 543210987654 3210
  2182.             . ............ ....
  2183.        month#      000000000111
  2184.             M 123456789012   L
  2185.                 
  2186.     b_j = 1 for long month, b_j = 0 for short month
  2187.     L is the leap month of the year if 1<=L<=12; NO leap month if L = 0.
  2188.     The leap month (if exists) is long one iff M = 1.
  2189.     */
  2190.                         0x04bd8,    /* 1900 */
  2191.     0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950,    /* 1905 */
  2192.     0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0,    /* 1910 */
  2193.     0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,    /* 1915 */
  2194.     0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970,    /* 1920 */
  2195.     0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54,    /* 1925 */
  2196.     0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,    /* 1930 */
  2197.     0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60,    /* 1935 */
  2198.     0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0,    /* 1940 */
  2199.     0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0,    /* 1945 */
  2200.     0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0,    /* 1950 */
  2201.     0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573,    /* 1955 */
  2202.     0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6,    /* 1960 */
  2203.     0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,    /* 1965 */
  2204.     0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0,    /* 1970 */
  2205.     0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250,    /* 1975 */
  2206.     0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0,    /* 1980 */
  2207.     0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50,    /* 1985 */
  2208.     0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5,    /* 1990 */
  2209.     0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58,    /* 1995 */
  2210.     0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,    /* 2000 */
  2211.     0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0,    /* 2005 */
  2212.     0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950,    /* 2010 */
  2213.     0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0,    /* 2015 */
  2214.     0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954,    /* 2020 */
  2215.     0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6,    /* 2025 */
  2216.     0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0,    /* 2030 */
  2217.     0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,    /* 2035 */
  2218.     0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0,    /* 2040 */
  2219.     0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0,    /* 2045 */
  2220.     0x0aa50, 0x1b255, 0x06d20, 0x0ada0            /* 2049 */
  2221. };
  2222.  
  2223. /*
  2224.   In "4-column" calculation, a "mingli" (fortune-telling) calculation,
  2225.   the beginning of a month is not the first day of the month as in
  2226.   the Lunar Calendar; it is instead governed by "jie2" (festival).
  2227.   Interestingly, in the Solar calendar, a jie always comes around certain
  2228.   day. For example, the jie "li4chun1" (beginning of spring) always comes
  2229.   near Feburary 4 of the Solar Calendar. 
  2230.  
  2231.   Meaning of array fest:
  2232.   Each element, fest[i][j] stores the jie day (in term of the following Solar
  2233.   month) of the lunar i-th year, j-th month.
  2234.   For example, in 1992, fest[92][0] is 4, that means the jie "li4chun1"
  2235.   (beginning of spring) is on Feb. 4, 1992; fest[92][11] is 5, that means
  2236.   the jie of the 12th lunar month is on Jan. 5, 1993.
  2237. */
  2238.  
  2239. static byte fest[Nyear][12] = {
  2240. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1900 */
  2241. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1901 */
  2242. {5, 6, 6, 6, 7, 8, 8, 8, 9, 8, 8, 6},    /* 1902 */
  2243. {5, 7, 6, 7, 7, 8, 9, 9, 9, 8, 8, 7},    /* 1903 */
  2244. {5, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1904 */
  2245. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1905 */
  2246. {5, 6, 6, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1906 */
  2247. {5, 7, 6, 7, 7, 8, 9, 9, 9, 8, 8, 7},    /* 1907 */
  2248. {5, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1908 */
  2249. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1909 */
  2250. {5, 6, 6, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1910 */
  2251. {5, 7, 6, 7, 7, 8, 9, 9, 9, 8, 8, 7},    /* 1911 */
  2252. {5, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1912 */
  2253. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1913 */
  2254. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1914 */
  2255. {5, 6, 6, 6, 7, 8, 8, 9, 9, 8, 8, 6},    /* 1915 */
  2256. {5, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1916 */
  2257. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 7, 6},    /* 1917 */
  2258. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1918 */
  2259. {5, 6, 6, 6, 7, 8, 8, 9, 9, 8, 8, 6},    /* 1919 */
  2260. {5, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1920 */
  2261. {4, 6, 5, 6, 6, 8, 8, 8, 9, 9, 7, 6},    /* 1921 */
  2262. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1922 */
  2263. {5, 6, 6, 6, 7, 8, 8, 9, 9, 8, 8, 6},    /* 1923 */
  2264. {5, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1924 */
  2265. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 7, 6},    /* 1925 */
  2266. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1926 */
  2267. {5, 6, 6, 6, 7, 8, 8, 8, 9, 8, 8, 6},    /* 1927 */
  2268. {5, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1928 */
  2269. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1929 */
  2270. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1930 */
  2271. {5, 6, 6, 6, 7, 8, 8, 8, 9, 8, 8, 6},    /* 1931 */
  2272. {5, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1932 */
  2273. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1933 */
  2274. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1934 */
  2275. {5, 6, 6, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1935 */
  2276. {5, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1936 */
  2277. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1937 */
  2278. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1938 */
  2279. {5, 6, 6, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1939 */
  2280. {5, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1940 */
  2281. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1941 */
  2282. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1942 */
  2283. {5, 6, 6, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1943 */
  2284. {5, 6, 5, 5, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1944 */
  2285. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1945 */
  2286. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1946 */
  2287. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1947 */
  2288. {5, 5, 5, 5, 6, 7, 7, 8, 8, 7, 7, 5},    /* 1948 */
  2289. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1949 */
  2290. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1950 */
  2291. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1951 */
  2292. {5, 5, 5, 5, 6, 7, 7, 8, 8, 7, 7, 5},    /* 1952 */
  2293. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1953 */
  2294. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 7, 6},    /* 1954 */
  2295. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1955 */
  2296. {5, 5, 5, 5, 6, 7, 7, 8, 8, 7, 7, 5},    /* 1956 */
  2297. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1957 */
  2298. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1958 */
  2299. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1959 */
  2300. {5, 5, 5, 5, 6, 7, 7, 7, 8, 7, 7, 5},    /* 1960 */
  2301. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1961 */
  2302. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1962 */
  2303. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1963 */
  2304. {5, 5, 5, 5, 6, 7, 7, 7, 8, 7, 7, 5},    /* 1964 */
  2305. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1965 */
  2306. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1966 */
  2307. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1967 */
  2308. {5, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1968 */
  2309. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1969 */
  2310. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1970 */
  2311. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1971 */
  2312. {5, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1972 */
  2313. {4, 6, 5, 5, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1973 */
  2314. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1974 */
  2315. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1975 */
  2316. {5, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1976 */
  2317. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 1977 */
  2318. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1978 */
  2319. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1979 */
  2320. {5, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1980 */
  2321. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 1981 */
  2322. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1982 */
  2323. {4, 6, 5, 6, 6, 8, 8, 8, 9, 8, 8, 6},    /* 1983 */
  2324. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1984 */
  2325. {5, 5, 5, 5, 5, 8, 7, 7, 8, 7, 7, 5},    /* 1985 */
  2326. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1986 */
  2327. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1987 */
  2328. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1988 */
  2329. {5, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1989 */
  2330. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 1990 */
  2331. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1991 */
  2332. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1992 */
  2333. {5, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1993 */
  2334. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1994 */
  2335. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1995 */
  2336. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1996 */
  2337. {5, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 1997 */
  2338. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 1998 */
  2339. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 1999 */
  2340. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2000 */
  2341. {4, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2001 */
  2342. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 2002 */
  2343. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 2003 */
  2344. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2004 */
  2345. {4, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2005 */
  2346. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2006 */
  2347. {4, 6, 5, 6, 6, 7, 8, 8, 9, 8, 7, 6},    /* 2007 */
  2348. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2008 */
  2349. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2009 */
  2350. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2010 */
  2351. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 2011 */
  2352. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2012 */
  2353. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2013 */
  2354. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2014 */
  2355. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 2015 */
  2356. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2016 */
  2357. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2017 */
  2358. {4, 5, 5, 5, 6, 7, 7, 8, 8, 7, 7, 5},    /* 2018 */
  2359. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 2019 */
  2360. {4, 5, 4, 5, 5, 6, 7, 7, 8, 7, 7, 5},    /* 2020 */
  2361. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2021 */
  2362. {4, 5, 5, 5, 6, 7, 7, 7, 8, 7, 7, 5},    /* 2022 */
  2363. {4, 6, 5, 6, 6, 7, 8, 8, 8, 8, 7, 6},    /* 2023 */
  2364. {4, 5, 4, 5, 5, 6, 7, 7, 8, 7, 6, 5},    /* 2024 */
  2365. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2025 */
  2366. {4, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2026 */
  2367. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 2027 */
  2368. {4, 5, 4, 5, 5, 6, 7, 7, 8, 7, 6, 5},    /* 2028 */
  2369. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2029 */
  2370. {4, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2030 */
  2371. {4, 6, 5, 6, 6, 7, 8, 8, 8, 7, 7, 6},    /* 2031 */
  2372. {4, 5, 4, 5, 5, 6, 7, 7, 8, 7, 6, 5},    /* 2032 */
  2373. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2033 */
  2374. {4, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2034 */
  2375. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2035 */
  2376. {4, 5, 4, 5, 5, 6, 7, 7, 8, 7, 6, 5},    /* 2036 */
  2377. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2037 */
  2378. {4, 5, 5, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2038 */
  2379. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2039 */
  2380. {4, 5, 4, 5, 5, 6, 7, 7, 8, 7, 6, 5},    /* 2040 */
  2381. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2041 */
  2382. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2042 */
  2383. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2043 */
  2384. {4, 5, 4, 5, 5, 6, 7, 7, 7, 7, 6, 5},    /* 2044 */
  2385. {3, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2045 */
  2386. {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5},    /* 2046 */
  2387. {4, 6, 5, 5, 6, 7, 7, 8, 8, 7, 7, 6},    /* 2047 */
  2388. {4, 5, 4, 5, 5, 6, 7, 7, 7, 7, 6, 5},    /* 2048 */
  2389. {3, 5, 4, 5, 5, 6, 7, 7, 8, 7, 7, 5}    /* 2049 */
  2390. };
  2391.  
  2392. SHAR_EOF
  2393. if test 11140 -ne "`wc -c < 'tables.h'`"
  2394. then
  2395.     echo shar: "error transmitting 'tables.h'" '(should have been 11140 characters)'
  2396. fi
  2397. fi
  2398. exit 0
  2399. #    End of shell archive
  2400.  
  2401. exit 0 # Just in case...
  2402.