home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / calen < prev    next >
Text File  |  1989-03-25  |  17KB  |  547 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v06i081: another calendar program
  4. Summary: new, improved
  5. Reply-To: awr@genrad.genrad.COM (Andrew W. Rogers)
  6. Organization: 
  7.  
  8. Posting-number: Volume 6, Issue 81
  9. Submitted-by: awr@genrad.COM (Andrew W. Rogers)
  10. Archive-name: calen
  11.  
  12. Here's another calendar program which I think is considerably more
  13. useful than pcal.  For starters, the calendars really do occupy a full
  14. line-printer page; they also include small calendars for the previous
  15. and subsequent months along with a month/year heading in 5x9
  16. dot-matrix characters, printed with overstrikes (on line printers
  17. capable of handling them).  Options are available to select:
  18.  
  19.     1) right- or left- justification of the dates within the boxes
  20.     2) mixed- or upper-case names of months and days
  21.     3) overstrike sequence used to print month/year heading (useful for
  22.        printers which do not support overstrikes, since a single character
  23.        can be specified - try "-o@")
  24.     4) number of blank lines at top of page (useful to center calendar
  25.        vertically when operators are careless about aligning paper)
  26.  
  27. I wrote this in GE Time-Sharing FORTRAN when I was a teenager and have
  28. continued to tweak it through the years; for many years I used it as
  29. my first post-"Hello, world!" program when learning new languages, and
  30. now use it to test the compilers I write.
  31.        
  32. Have fun...
  33. --
  34. Andrew W. Rogers    {decvax,husc6,mit-eddie}!genrad!teddy!awr
  35.             awr@teddy.genrad.com
  36. #! /bin/sh
  37. # This file was wrapped with "dummyshar".  "sh" this file to extract.
  38. # Contents:  calen.c
  39. echo extracting 'calen.c'
  40. if test -f 'calen.c' -a -z "$1"; then echo Not overwriting 'calen.c'; else
  41. sed 's/^X//' << \EOF > 'calen.c'
  42. X/*
  43. X *    Calendar program - one month per page
  44. X *
  45. X *    Originally written in FORTRAN-IV for GE Timesharing, 10/65
  46. X *    Re-coded in C for UNIX, 3/83
  47. X *
  48. X *    Author: AW Rogers
  49. X *
  50. X *    Parameters:
  51. X *
  52. X *        calen yy        generates calendar for year yy
  53. X *
  54. X *        calen mm yy [len]    generates calendar for len months
  55. X *                    (default = 1) starting with mm/yy
  56. X *
  57. X *     Option flags (must precede params):
  58. X *
  59. X *        -l            left-justify dates (default)
  60. X *        -r            right-justify dates
  61. X *        -m            mixed-case output (default)
  62. X *        -u            upper-case output
  63. X *        -o[seq]            use "seq" as overstrike sequence
  64. X *                     for heading (default: HIX)
  65. X *        -bN            add N blank lines after form-feed
  66. X *
  67. X *        Output is to standard output.
  68. X *        
  69. X */
  70. X#include <stdio.h>
  71. X#include <ctype.h>
  72. X
  73. X#define FALSE   0
  74. X#define TRUE    1
  75. X#define JAN     1            /* significant months/years */
  76. X#define FEB    2
  77. X#define DEC    12
  78. X#define MINYR    1753
  79. X#define MAXYR    9999
  80. X#define SOLID    0            /* pseudo-enumeration for line styles */
  81. X#define OPEN    1
  82. X
  83. X#define LEFT    0            /* ... and justification of dates     */
  84. X#define RIGHT    1
  85. X
  86. X#define MIXED    0            /* ... and case of output text          */
  87. X
  88. X#define UPPER    1
  89. X
  90. X#define    OVERSTRIKE    "HIX"        /* overstrike sequence for month/year */
  91. X#define MAX_OVERSTR    3        /* maximum overstrikes permitted */
  92. X
  93. X#define isLeap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))    /* leap year macro */
  94. Xtypedef struct                /* info for a single month */
  95. X    {
  96. X    int     mm;
  97. X    int        yy;
  98. X    char     mmname[10];
  99. X    char    dates[6][7][3];
  100. X    } monthRec;
  101. Xtypedef monthRec *mptr;            /* pointer to above struct */
  102. X
  103. X/* globals corresponding to command-line flags */
  104. X
  105. Xint just = LEFT;            /* default justification of dates */
  106. Xint ocase = MIXED;            /* default case for output */
  107. Xint nblank = 0;                /* default blank lines after FF */
  108. Xchar *seq = OVERSTRIKE;            /* default overstrike sequence */
  109. X
  110. X
  111. X/*
  112. X *    Main - gets and validates parameters, opens output file, executes
  113. X *    loop to fill and print months of calendar, closes output file
  114. X */
  115. Xmain(argc, argv)
  116. X    int argc;
  117. X    char *argv[];
  118. X    {
  119. X    int nmonths;            /* consecutive months to print */
  120. X    int badopt = FALSE;            /* flag set if bad option */
  121. X    int badpar = FALSE;            /* flag set if bad param  */
  122. X    monthRec mRec[3];            /* space for main and small calendars */
  123. X    mptr prev = &mRec[0],         /* pointers to calendars (initially) */
  124. X     curr = &mRec[1],
  125. X     next = &mRec[2],
  126. X     temp;
  127. X
  128. X    /* Get command line flags */
  129. X
  130. X    while (argc > 1 && argv[1][0] == '-')
  131. X        {
  132. X        switch (argv[1][1])
  133. X        {
  134. X        case 'b':
  135. X        sscanf(&argv[1][2], "%d", &nblank);
  136. X        break;
  137. X        case 'l':
  138. X        just = LEFT;
  139. X        break;
  140. X        case 'r':
  141. X        just = RIGHT;
  142. X        break;
  143. X        case 'm':
  144. X        ocase = MIXED;
  145. X        break;
  146. X        case 'u':
  147. X        ocase = UPPER;
  148. X        break;
  149. X        case 'o':
  150. X        if (argv[1][2] != '\0')
  151. X            seq = &argv[1][2];
  152. X        break;
  153. X        default:
  154. X        fprintf(stderr, "Invalid flag: %s\n", argv[1]);
  155. X        badopt = TRUE;
  156. X        break;
  157. X        }
  158. X        argv++;
  159. X    argc--;
  160. X    }
  161. X
  162. X    if (badopt)
  163. X    fprintf(stderr, "Valid flags are -b -l -m -o -r -u\n");
  164. X
  165. X    /* Get and validate parameters */
  166. X    
  167. X    if (argc == 2)        /* only one arg - treat as yy */
  168. X    {
  169. X    sscanf(argv[1], "%d", &curr->yy);
  170. X    curr->mm = JAN;
  171. X    nmonths = 12;
  172. X    }
  173. X    else if (argc >= 3)        /* two or more - treat as mm yy [len] */
  174. X    {
  175. X    sscanf(argv[1], "%d", &curr->mm);
  176. X    sscanf(argv[2], "%d", &curr->yy);
  177. X    if (argc >= 4)
  178. X        sscanf(argv[3], "%d", &nmonths);
  179. X    }
  180. X    else            /* none specified - get interactively */
  181. X    {
  182. X    fprintf(stderr, "Enter calendar specs (month year length): ");
  183. X    scanf("%d %d %d", &curr->mm, &curr->yy, &nmonths);
  184. X    }
  185. X    if (curr->yy > 0 && curr->yy < 100)        /* nn -> 19nn */
  186. X    curr->yy += 1900;
  187. X    if (nmonths < 1)                /* default for month count */
  188. X    nmonths = 1;
  189. X    if (curr->mm < JAN || curr->mm > DEC)    /* validate month/year */
  190. X      {
  191. X      fprintf(stderr, "Month %d not in range %d .. %d\n", curr->mm, JAN, DEC);
  192. X      badpar = TRUE;
  193. X      }
  194. X
  195. X    if (curr->yy < MINYR || curr->yy > MAXYR)
  196. X      {
  197. X      fprintf(stderr, "Year %d not in range %d .. %d\n", curr->yy, MINYR,
  198. X          MAXYR);
  199. X      badpar = TRUE;
  200. X      }
  201. X
  202. X    if (badpar)        /* quit if month or year invalid */
  203. X      exit(1);
  204. X    /* fill in calendars for previous and current month */
  205. X    prev->mm = (curr->mm == JAN) ? DEC : curr->mm - 1;
  206. X    prev->yy = (curr->mm == JAN) ? curr->yy - 1 : curr->yy;
  207. X    fillCalendar(prev);
  208. X    fillCalendar(curr);
  209. X    /*
  210. X     * Main loop: print each month of the calendar (with small calendars for
  211. X     * the preceding and following months in the upper corners).  The current
  212. X     * and next months' calendars can be reused the following month; only
  213. X     * the 'next' calendar need be recalculated each time.
  214. X     */
  215. X    for (; nmonths > 0 && curr->yy <= MAXYR; nmonths--)    /* main loop */
  216. X    {
  217. X    next->mm = (curr->mm == DEC) ? JAN : curr->mm + 1;
  218. X    next->yy = (curr->mm == DEC) ? curr->yy + 1 : curr->yy;
  219. X    fillCalendar(next);            /* fill in following month */
  220. X    printCalendar(prev, curr, next);
  221. X    temp = prev;                /* swap the three months */
  222. X    prev = curr;
  223. X    curr = next;
  224. X    next = temp;
  225. X    }
  226. X    }
  227. X
  228. X/*
  229. X *    Print the calendar for the current month, generating small calendars
  230. X *    for the previous and following months in the upper corners and the
  231. X *    month/year (in large characters) centered at the top.
  232. X */
  233. XprintCalendar(prev, curr, next)
  234. X    mptr prev;            /* Previous month (upper-left corner)  */
  235. X    mptr curr;            /* Current month (main calendar)       */
  236. X    mptr next;            /* Next month (upper-right corner)     */
  237. X    {
  238. X    int nchars, i, j;
  239. X    static char *mc_wkday[] =
  240. X    {
  241. X    " Sunday  ", " Monday  ", " Tuesday ", "Wednesday", "Thursday ",
  242. X    " Friday  ", "Saturday "
  243. X    };
  244. X    static char *uc_wkday[] =
  245. X    {
  246. X    " SUNDAY  ", " MONDAY  ", " TUESDAY ", "WEDNESDAY", "THURSDAY ",
  247. X    " FRIDAY  ", "SATURDAY "
  248. X    };
  249. X
  250. X    char **wkday;                /* pointer to one of above */
  251. X    char *blanks = "                     ";     /* 21 blanks for centering */
  252. X    char *padding;                /* Pointer into 'blanks'   */
  253. X    char monthAndYear[20];            /* Work area            */
  254. X    char *ovr;                    /* overstrike sequence       */
  255. X    nchars = strlen(curr->mmname);        /* set up month/year heading */
  256. X    padding = blanks + (3 * (nchars - 3));    /* and center it           */
  257. X    sprintf(monthAndYear, "%s%5d", curr->mmname, curr->yy);
  258. X    printf("\f\n");            /* print month/year in large chars */
  259. X    for (i = 0; i < nblank; i++)
  260. X    printf("\n");
  261. X
  262. X    for (i = 0; i < 9; i++)        /* surrounded by small calendars   */
  263. X        {
  264. X    for (ovr = seq;            /* overstruck lines first */
  265. X         ovr < seq + MAX_OVERSTR - 1 && *(ovr+1);
  266. X         ovr++) 
  267. X        {
  268. X        printf("%20s%s", " ", padding);
  269. X        printHdr(monthAndYear, i, *ovr);
  270. X        printf("\r");
  271. X        }
  272. X    printSmallCal(prev, i);        /* then small calendars, etc. */
  273. X    printf("%s", padding);
  274. X    printHdr(monthAndYear, i, *ovr);
  275. X    printf(" %s", padding);
  276. X        printSmallCal(next, i);
  277. X        printf("\n");
  278. X        }
  279. X    printf("\n");            /* print the weekday names */
  280. X    print_line(1, SOLID);
  281. X    print_line(1, OPEN);
  282. X    printf("  ");
  283. X    wkday = ocase == UPPER ? uc_wkday : mc_wkday;
  284. X    for (j = 0; j < 7; j++)
  285. X        printf("|%13.9s    ", wkday[j]);
  286. X    printf("|\n");
  287. X    print_line(1, OPEN);
  288. X    
  289. X    for (i = 0; i < 4; i++)        /* print first four rows */
  290. X        {
  291. X        print_line(1, SOLID);
  292. X        print_dates(curr, i, just);
  293. X        print_line(7, OPEN);
  294. X        }
  295. X    print_line(1, SOLID);        /* print bottom row */
  296. X    print_dates(curr, 4, just);
  297. X    print_line(2, OPEN);
  298. X    print_divider(curr->dates[5]);    /* divider for 23/30, 24/31 */
  299. X
  300. X    print_line(3, OPEN);
  301. X    print_dates(curr, 5, !just);    /* print 6th line (30/31) at bottom */
  302. X    print_line(1, SOLID);
  303. X    }
  304. X
  305. X/*
  306. X *    Fill in the month name and date fields of a specified calendar record
  307. X *    (assumes mm, yy fields already filled in)
  308. X */
  309. XfillCalendar(month)
  310. X    mptr month;            /* Pointer to month info record */
  311. X    {
  312. X    typedef struct        /* Local info about months */
  313. X    {
  314. X    char *name[2];        /* Name of month (mixed/upper-case)    */
  315. X    int offset[2];        /* Offset of m/1 from 1/1 (non-leap/leap) */
  316. X    int length[2];        /* Length (non-leap/leap)        */
  317. X    } monthInfo;
  318. X    static monthInfo info[12] = {
  319. X    { {"January",    "JANUARY"},    {0, 0},    {31, 31} },
  320. X    { {"February",    "FEBRUARY"},    {3, 3},    {28, 29} },
  321. X    { {"March",    "MARCH"},    {3, 4},    {31, 31} },
  322. X    { {"April",    "APRIL"},    {6, 0},    {30, 30} },
  323. X    { {"May",    "MAY"},        {1, 2},    {31, 31} },
  324. X    { {"June",    "JUNE"},    {4, 5},    {30, 30} },
  325. X    { {"July",    "JULY"},    {6, 0},    {31, 31} },
  326. X    { {"August",    "AUGUST"},    {2, 3},    {31, 31} },
  327. X    { {"September",    "SEPTEMBER"},    {5, 6},    {30, 30} },
  328. X    { {"October",    "OCTOBER"},    {0, 1},    {31, 31} },
  329. X    { {"November",    "NOVEMBER"},    {3, 4},    {30, 30} },
  330. X    { {"December",    "DECEMBER"},    {5, 6},    {31, 31} }
  331. X    };
  332. X    int i, first, last, date = 0, y = month->yy, m = month->mm-1;
  333. X    int leap = isLeap(y);
  334. X    first = (y + (y-1)/4 - (y-1)/100 + (y-1)/400 + info[m].offset[leap]) % 7;
  335. X    last = first + info[m].length[leap] - 1;
  336. X    for (i = 0; i < 42; i++)            /* fill in the dates */
  337. X    if (i < first || i > last)
  338. X        strcpy(month->dates[i/7][i%7], "  ");
  339. X    else
  340. X        sprintf(month->dates[i/7][i%7], "%2d", ++date);
  341. X    strcpy(month->mmname, info[m].name[ocase]);    /* copy name of month */
  342. X    } 
  343. X
  344. X/*
  345. X *    Print one line of a small calendar (previous and next months in
  346. X *    upper left and right corners of output)
  347. X */
  348. XprintSmallCal(month, line)
  349. X    mptr month;            /* Month info record pointer    */
  350. X    int line;            /* Line to print (see below)    */
  351. X    {
  352. X    int i;
  353. X  
  354. X    switch (line)
  355. X    {
  356. X    case 0:        /* month/year at top */
  357. X        printf("   %-10s%4d   ", month->mmname, month->yy);
  358. X        break;
  359. X    case 1:        /* blank line */
  360. X        printf("%20s", " ");
  361. X        break;
  362. X    case 2:        /* weekdays */
  363. X        printf(ocase == UPPER ? "SU MO TU WE TH FR SA" :
  364. X                    "Su Mo Tu We Th Fr Sa");
  365. X        break;
  366. X    default:    /* line of calendar */
  367. X        for (i = 0; i <= 5; i++)
  368. X            printf("%s ", month->dates[line-3][i]);
  369. X        printf("%s", month->dates[line-3][6]);
  370. X        break;
  371. X    }
  372. X    }
  373. X
  374. X/*
  375. X *    Print n lines in selected style
  376. X */
  377. Xprint_line(n, style)
  378. X    int n;            /* Number of lines to print (> 0)   */
  379. X    int style;            /* SOLID or OPEN             */
  380. X    {
  381. X    int i;
  382. X    char *fmt1 = (style == SOLID) ? "+-----------------" :
  383. X                    "|                 " ;
  384. X    char *fmt2 = (style == SOLID) ? "+\n" : "|\n" ;
  385. X
  386. X    for (; n > 0; n--)
  387. X    {
  388. X    printf("  ");
  389. X    for (i = 0; i < 7; i++)
  390. X        printf(fmt1);
  391. X    printf(fmt2);
  392. X    }
  393. X    }
  394. X
  395. X
  396. X
  397. X/*
  398. X *    Print line of large calendar (open w/left- or right-justified dates)
  399. X */
  400. Xprint_dates(month, line, just)
  401. X    mptr month;            /* Month info record pointer    */
  402. X    int line;            /* Line to print (0-5)        */
  403. X    int just;            /* justification (LEFT / RIGHT)    */
  404. X    {
  405. X    int i;
  406. X    char *fmt = (just == LEFT) ? "| %-16s" : "|%16s " ;
  407. X
  408. X    printf("  ");
  409. X    for (i = 0; i < 7; i++)
  410. X    printf(fmt, month->dates[line][i]);
  411. X    printf("|\n");
  412. X    }
  413. X
  414. X/*
  415. X *    Print divider between 23/30 and 24/31
  416. X */
  417. Xprint_divider(dates)
  418. X    char dates[7][3];
  419. X    {
  420. X    int j;
  421. X
  422. X    printf("  ");
  423. X    for (j = 0; j < 7; j++)
  424. X        if (strcmp(dates[j], "  ") == 0)
  425. X            printf("|                 ");
  426. X        else
  427. X            printf("|_________________");
  428. X    printf("|\n");
  429. X    }
  430. X
  431. X  
  432. X/*
  433. X *    Print LS 6 bits of n (0 = ' '; 1 = selected non-blank)
  434. X */
  435. Xdecode(n, c)
  436. X    int n;                /* Number to print (0-31) */
  437. X    char c;
  438. X    {
  439. X    int msk = 1 << 5;
  440. X    for (; msk; msk /= 2) 
  441. X    printf("%c", (n & msk) ? c : ' ');
  442. X    }
  443. X/*
  444. X *    Print one line of string in large characters
  445. X */
  446. XprintHdr(str, line, c)
  447. X    char *str;                /* string to print            */
  448. X    int line;                /* line to print (0-8; else blanks) */
  449. X    char c;                /* output character to use        */
  450. X    {
  451. X    /* 5x9 dot-matrix representations of A-Z, a-z, 0-9 */
  452. X    static char uppers[26][9] =
  453. X    {
  454. X    {14, 17, 17, 31, 17, 17, 17,  0,  0},    {30, 17, 17, 30, 17, 17, 30,  0,  0},    /* AB */
  455. X    {14, 17, 16, 16, 16, 17, 14,  0,  0},    {30, 17, 17, 17, 17, 17, 30,  0,  0},    /* CD */
  456. X    {31, 16, 16, 30, 16, 16, 31,  0,  0},    {31, 16, 16, 30, 16, 16, 16,  0,  0},    /* EF */
  457. X    {14, 17, 16, 23, 17, 17, 14,  0,  0},    {17, 17, 17, 31, 17, 17, 17,  0,  0},    /* GH */
  458. X    {31,  4,  4,  4,  4,  4, 31,  0,  0},    { 1,  1,  1,  1,  1, 17, 14,  0,  0},    /* IJ */
  459. X    {17, 18, 20, 24, 20, 18, 17,  0,  0},    {16, 16, 16, 16, 16, 16, 31,  0,  0},    /* KL */
  460. X    {17, 27, 21, 21, 17, 17, 17,  0,  0},    {17, 17, 25, 21, 19, 17, 17,  0,  0},    /* MN */
  461. X    {14, 17, 17, 17, 17, 17, 14,  0,  0},    {30, 17, 17, 30, 16, 16, 16,  0,  0},    /* OP */
  462. X    {14, 17, 17, 17, 21, 18, 13,  0,  0},    {30, 17, 17, 30, 20, 18, 17,  0,  0},    /* QR */
  463. X    {14, 17, 16, 14,  1, 17, 14,  0,  0},    {31,  4,  4,  4,  4,  4,  4,  0,  0},    /* ST */
  464. X    {17, 17, 17, 17, 17, 17, 14,  0,  0},    {17, 17, 17, 17, 17, 10,  4,  0,  0},    /* UV */
  465. X    {17, 17, 17, 21, 21, 21, 10,  0,  0},    {17, 17, 10,  4, 10, 17, 17,  0,  0},    /* WX */
  466. X    {17, 17, 17, 14,  4,  4,  4,  0,  0},    {31,  1,  2,  4,  8, 16, 31,  0,  0}    /* YZ */
  467. X    }; 
  468. X    static char lowers[26][9] =
  469. X    {
  470. X    { 0,  0, 14,  1, 15, 17, 15,  0,  0},    {16, 16, 30, 17, 17, 17, 30,  0,  0},    /* ab */
  471. X    { 0,  0, 15, 16, 16, 16, 15,  0,  0},    { 1,  1, 15, 17, 17, 17, 15,  0,  0},    /* cd */
  472. X    { 0,  0, 14, 17, 31, 16, 14,  0,  0},    { 6,  9, 28,  8,  8,  8,  8,  0,  0},    /* ef */
  473. X    { 0,  0, 14, 17, 17, 17, 15,  1, 14},    {16, 16, 30, 17, 17, 17, 17,  0,  0},    /* gh */
  474. X    { 4,  0, 12,  4,  4,  4, 31,  0,  0},    { 1,  0,  3,  1,  1,  1,  1, 17, 14},    /* ij */
  475. X    {16, 16, 17, 18, 28, 18, 17,  0,  0},    {12,  4,  4,  4,  4,  4, 31,  0,  0},    /* kl */
  476. X    { 0,  0, 30, 21, 21, 21, 21,  0,  0},    { 0,  0, 30, 17, 17, 17, 17,  0,  0},    /* mn */
  477. X    { 0,  0, 14, 17, 17, 17, 14,  0,  0},    { 0,  0, 30, 17, 17, 17, 30, 16, 16},    /* op */
  478. X    { 0,  0, 15, 17, 17, 17, 15,  1,  1},    { 0,  0, 30, 17, 16, 16, 16,  0,  0},    /* qr */
  479. X    { 0,  0, 15, 16, 14,  1, 30,  0,  0},    { 8,  8, 30,  8,  8,  9,  6,  0,  0},    /* st */
  480. X    { 0,  0, 17, 17, 17, 17, 14,  0,  0},    { 0,  0, 17, 17, 17, 10,  4,  0,  0},    /* uv */
  481. X    { 0,  0, 17, 21, 21, 21, 10,  0,  0},    { 0,  0, 17, 10,  4, 10, 17,  0,  0},    /* wx */
  482. X    { 0,  0, 17, 17, 17, 17, 15,  1, 14},    { 0,  0, 31,  2,  4,  8, 31,  0,  0}    /* yz */
  483. X    };
  484. X
  485. X    static char digits[10][9] =
  486. X    {
  487. X    {14, 17, 17, 17, 17, 17, 14,  0,  0},    { 2,  6, 10,  2,  2,  2, 31,  0,  0},    /* 01 */
  488. X    {14, 17,  2,  4,  8, 16, 31,  0,  0},    {14, 17,  1, 14,  1, 17, 14,  0,  0},    /* 23 */
  489. X    { 2,  6, 10, 31,  2,  2,  2,  0,  0},    {31, 16, 16, 30,  1, 17, 14,  0,  0},    /* 45 */
  490. X    {14, 17, 16, 30, 17, 17, 14,  0,  0},    {31,  1,  2,  4,  8, 16, 16,  0,  0},    /* 67 */
  491. X    {14, 17, 17, 14, 17, 17, 14,  0,  0},    {14, 17, 17, 15,  1, 17, 14,  0,  0}    /* 89 */
  492. X    };
  493. X    char ch;
  494. X    for ( ; *str; str++)
  495. X    {
  496. X    ch = (line >= 0 && line <= 8) ? *str : ' ';
  497. X    if (isupper(ch))
  498. X        decode(uppers[ch-'A'][line], c);
  499. X    else if (islower(ch))
  500. X        decode(lowers[ch-'a'][line], c);
  501. X    else if (isdigit(ch))
  502. X        decode(digits[ch-'0'][line], c);
  503. X    else
  504. X        decode(0, c);
  505. X    }
  506. X    }
  507. EOF
  508. chars=`wc -c < 'calen.c'`
  509. if test $chars !=    15111; then echo 'calen.c' is $chars characters, should be    15111 characters!; fi
  510. fi
  511. exit 0
  512.