home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume7 / cal / cal.c < prev   
Encoding:
C/C++ Source or Header  |  1989-08-05  |  5.0 KB  |  257 lines

  1. /* cal.c - print calendar for one month or one year
  2.  *
  3.  * cal [[month] year]
  4.  * 
  5.  * cal (C) 1988 by Gary L. Brant
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <time.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12. #include <sys/types.h>
  13.  
  14. #define    blank(addr, len)    (void) memset(addr, ' ', len)
  15.  
  16. #define DPY    365L    /* days per year */
  17. #define FUDGE1    1    /* needed to make day of week come out right */
  18. #define FUDGE2    6    /* for old style (Julian) calendar */
  19. #define    LINEWID    71    /* width of array line[] */
  20.  
  21. int days[12] = {
  22.     31,  28,  31,  30,    31,  30,  31,  31,  30,  31,  30,  31
  23. };
  24. int mdays[13] = {
  25.      0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  26. };
  27. char *months[12] = {
  28.    "January ", "February ", "March ",     "April ",   "May ",      "June ",
  29.    "July "   , "August " , "September ", "October ", "November ", "December "
  30. };
  31. char monthline[] = "\t ---\t\t\t---\t\t       ---";
  32. char *monthpos[3] = {monthline+2, monthline+8, monthline+20};
  33. char dayline[] = " S  M Tu  W Th  F  S";
  34. char line[7][LINEWID];        /* line buffer */
  35. int multi = 0;
  36.  
  37.  
  38. main(argc, argv)
  39. int argc;
  40. char *argv[];
  41. {
  42.    int i, k, m, y;
  43.    time_t t;
  44.    struct tm *lcl_tim;
  45.  
  46.    t = time((time_t *) 0);
  47.    lcl_tim = localtime(&t);
  48.    y = lcl_tim->tm_year + 1900;
  49.    m = lcl_tim->tm_mon + 1;
  50.    if (argc == 1) {
  51.       fixtab (y);
  52.       printmonth (m, y);
  53.       exit (0);
  54.    }
  55.  
  56.    if ((k = atoi (argv[1])) == 0) {
  57.       m = 0;
  58.       for (i = 0; i < 12; i++)
  59.      if (cmpmonth (argv[1], months[i]) == 0) {
  60.         m = i + 1;
  61.         break;
  62.      }
  63.       if (m == 0) {
  64.      badarg (argv[1]);
  65.       }
  66.    }
  67.  
  68.    if (argc == 2) {
  69.       if (k == 0) {
  70.      fixtab (y);
  71.      printmonth (m, y);
  72.       } else {
  73.      multi = 1;
  74.      fixtab (k);
  75.      fputs("\n\n\n\t\t\t\t", stdout);
  76.      putd(k);        /* put year */
  77.      putchar('\n');
  78.      for (m = 1; m < 13; m++)
  79.         printmonth (m, k);
  80.      puts("\n\n");
  81.       }
  82.       exit (0);
  83.    }
  84.  
  85.    if (k > 0 && k < 13)
  86.       m = k;
  87.    else if (m == 0 || k != 0) {
  88.       badarg (argv[1]);
  89.    }
  90.  
  91.    if (argc == 3) {
  92.       if ((y = atoi (argv[2])) == 0) {
  93.      badarg (argv[2]);
  94.       }
  95.    }
  96.    fixtab (y);
  97.    printmonth (m, y);
  98. }
  99.  
  100.  
  101. /* printmonth () - either prints an entire month at a time or multiplexes
  102.  * a month into a buffer, dumping the buffer after the third call.
  103.  */
  104. printmonth (m, y)
  105. register int m;
  106. int y;
  107. {
  108.    register int first, last;
  109.    register int index, p = 0;
  110.    register char *ll;
  111.    static int q = 0;
  112.    int l;
  113.  
  114.    --m;
  115.    if (multi) {
  116.       q++;
  117.       if (q > 3)
  118.      q = 1;
  119.       p = 23 * (q - 1);        /* character position of line in buffer */
  120.       (void) memcpy(monthpos[q-1], months[m], 3);    /* copy month name */
  121.       if (q == 3) {
  122.      puts(monthline);
  123.      for (index = 0; index < 2; ++index) {
  124.         fputs(dayline, stdout);
  125.         fputs("   ", stdout);
  126.      }
  127.      puts(dayline);
  128.       }
  129.       else
  130.      blank(line[0]+p+12, 11);
  131.    } else {
  132.       q = 1;
  133.       fputs("   ", stdout);
  134.       fputs(months[m], stdout);            /* put month name */
  135.       putd(y);                    /* put year */
  136.       puts(dayline);
  137.    }
  138.  
  139.    l = 1;
  140.    if (p == 0) blank(line[1], 6*LINEWID);
  141.  
  142.    if (y == 1752 && m == 8) {    /* special case Sep. 1752 */
  143.       line[1][p + 7] = '1';
  144.       line[1][p + 10] = '2';
  145.       first = 14;
  146.       last = 16;
  147.       index = 12;
  148.    }
  149.    else {
  150.       int dow;            /* day of week for first day of month */
  151.  
  152.       first = 1;
  153.       dow = weekday (m, y);
  154.       last = 7 - dow;
  155.       index = 3 * dow;
  156.    }
  157.  
  158.    for (; l < 7; ++l) {    /* loop thru month one week per line */
  159.       ll = line[l] + p;
  160.       while (first <= last) {    /* for each day in week encode day of month */
  161.      if (first >= 10)
  162.         ll[index] = '0' + first / 10;
  163.      ll[index+1] = '0' + first % 10;
  164.      index += 3;
  165.      ++first;
  166.       }
  167.       if (!multi || q == 3) {
  168.      index += p - 2;
  169.      if (index < 0) index = 0;
  170.      ll -= p;
  171.      while (index >= 0 && ll[index] == ' ')
  172.         --index;
  173.      ll[index+1] = '\0';
  174.      puts(ll);
  175.       }
  176.       last = (last + 7) > days[m] ? days[m] : last + 7;
  177.       index = 0;
  178.    }
  179.  
  180. }
  181.  
  182.  
  183. /* putd - put year to standard output.
  184.  */
  185. putd (n)
  186. register int n;
  187. {
  188.    char str[5];
  189.    register char *p = str+4;
  190.  
  191.    *p = '\0';
  192.    do {
  193.       --p;
  194.       *p = '0' + n % 10;
  195.       n = n / 10;
  196.    }
  197.    while (n);
  198.    puts(p);
  199. }
  200.  
  201.  
  202. /* fixtab - correct for leapyears.
  203.  */
  204. fixtab (y)
  205. register int y;
  206. {
  207.    register int i;
  208.  
  209.    if ((y % 4) == 0) {
  210.       if (((y % 100) != 0) || ((y % 400) == 0) || (y < 1753)) {
  211.      days[1] = 29;
  212.      for (i = 2; i < 13; i++)
  213.         mdays[i]++;
  214.       }
  215.    }
  216. }
  217.  
  218.  
  219. /* weekday - return day-of-week for first day of month.
  220.  */
  221. weekday (m, y)
  222. register int m, y;
  223. {
  224.    --y;
  225.    if (y > 1752-1 || (y == 1752-1 && m > 8))
  226.       return (mdays[m] + y + y / 4 - y / 100 + y / 400 + FUDGE1) % 7;
  227.    else
  228.       return (mdays[m] + y + y / 4               + FUDGE2) % 7;
  229. }
  230.  
  231.  
  232.  
  233. badarg (string)
  234. char string[];
  235. {
  236.    fputs(string, stderr);
  237.    fputs(" bad argument\n", stderr);
  238.    exit (10);
  239. }
  240.  
  241.  
  242. /* cmpmonth () - compare month argument entered by user with month name.
  243.  * The comparison will be made case insensitive.
  244.  */
  245. cmpmonth (str1, str2)
  246. register char str1[], str2[];
  247. {
  248.    register int j;
  249.  
  250.    if ((j = (toupper(str1[0])-str2[0])) != 0)
  251.       return (j);
  252.    else if ((j = tolower(str1[1])-str2[1]) != 0)
  253.       return (j);
  254.    else
  255.       return (tolower(str1[2])-str2[2]);
  256. }
  257.