Home | History | Annotate | Line # | Download | only in cal
cal.c revision 1.17
      1  1.17    atatat /*	$NetBSD: cal.c,v 1.17 2003/07/24 01:19:45 atatat Exp $	*/
      2   1.6     glass 
      3   1.1       cgd /*
      4   1.6     glass  * Copyright (c) 1989, 1993, 1994
      5   1.6     glass  *	The Regents of the University of California.  All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * This code is derived from software contributed to Berkeley by
      8   1.1       cgd  * Kim Letkeman.
      9   1.1       cgd  *
     10   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     11   1.1       cgd  * modification, are permitted provided that the following conditions
     12   1.1       cgd  * are met:
     13   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     14   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     15   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     17   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     18   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     19   1.1       cgd  *    must display the following acknowledgement:
     20   1.1       cgd  *	This product includes software developed by the University of
     21   1.1       cgd  *	California, Berkeley and its contributors.
     22   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     23   1.1       cgd  *    may be used to endorse or promote products derived from this software
     24   1.1       cgd  *    without specific prior written permission.
     25   1.1       cgd  *
     26   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36   1.1       cgd  * SUCH DAMAGE.
     37   1.1       cgd  */
     38   1.1       cgd 
     39   1.7     lukem #include <sys/cdefs.h>
     40   1.1       cgd #ifndef lint
     41   1.7     lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
     42   1.7     lukem 	The Regents of the University of California.  All rights reserved.\n");
     43   1.1       cgd #endif /* not lint */
     44   1.1       cgd 
     45   1.1       cgd #ifndef lint
     46   1.6     glass #if 0
     47   1.6     glass static char sccsid[] = "@(#)cal.c	8.4 (Berkeley) 4/2/94";
     48   1.6     glass #else
     49  1.17    atatat __RCSID("$NetBSD: cal.c,v 1.17 2003/07/24 01:19:45 atatat Exp $");
     50   1.6     glass #endif
     51   1.1       cgd #endif /* not lint */
     52   1.1       cgd 
     53   1.1       cgd #include <sys/types.h>
     54   1.6     glass 
     55   1.6     glass #include <ctype.h>
     56   1.6     glass #include <err.h>
     57  1.14      yamt #include <errno.h>
     58  1.14      yamt #include <limits.h>
     59   1.1       cgd #include <stdio.h>
     60   1.6     glass #include <stdlib.h>
     61   1.4       cgd #include <string.h>
     62  1.15    atatat #include <termcap.h>
     63   1.6     glass #include <time.h>
     64   1.8  christos #include <tzfile.h>
     65   1.6     glass #include <unistd.h>
     66   1.1       cgd 
     67   1.1       cgd #define	SATURDAY 		6		/* 1 Jan 1 was a Saturday */
     68   1.1       cgd 
     69  1.17    atatat #define	FIRST_MISSING_DAY 	reform->first_missing_day
     70  1.17    atatat #define	NUMBER_MISSING_DAYS 	reform->missing_days
     71   1.1       cgd 
     72   1.1       cgd #define	MAXDAYS			42		/* max slots in a month array */
     73   1.1       cgd #define	SPACE			-1		/* used in day array */
     74   1.1       cgd 
     75   1.1       cgd static int days_in_month[2][13] = {
     76   1.1       cgd 	{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     77   1.1       cgd 	{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     78   1.1       cgd };
     79   1.1       cgd 
     80  1.17    atatat int empty[MAXDAYS] = {
     81   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     82   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     83   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     84   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     85   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     86   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     87   1.1       cgd };
     88  1.17    atatat int shift_days[2][4][MAXDAYS + 1];
     89   1.1       cgd 
     90   1.1       cgd char *month_names[12] = {
     91   1.1       cgd 	"January", "February", "March", "April", "May", "June",
     92   1.1       cgd 	"July", "August", "September", "October", "November", "December",
     93   1.1       cgd };
     94   1.1       cgd 
     95   1.1       cgd char *day_headings = " S  M Tu  W Th  F  S";
     96   1.1       cgd char *j_day_headings = "  S   M  Tu   W  Th   F   S";
     97   1.1       cgd 
     98  1.17    atatat /* leap years according to the julian calendar */
     99  1.17    atatat #define j_leap_year(y, m, d) \
    100  1.17    atatat 	(((m) > 2) && \
    101  1.17    atatat 	 !((y) % 4))
    102  1.17    atatat 
    103  1.17    atatat /* leap years according to the gregorian calendar */
    104  1.17    atatat #define g_leap_year(y, m, d) \
    105  1.17    atatat 	(((m) > 2) && \
    106  1.17    atatat 	 ((!((y) % 4) && ((y) % 100)) || \
    107  1.17    atatat 	  !((y) % 400)))
    108  1.17    atatat 
    109  1.17    atatat /* leap year -- account for gregorian reformation at some point */
    110   1.1       cgd #define	leap_year(yr) \
    111  1.17    atatat 	((yr) <= reform->year ? j_leap_year((yr), 3, 1) : \
    112  1.17    atatat 	g_leap_year((yr), 3, 1))
    113   1.1       cgd 
    114  1.17    atatat /* number of julian leap days that have passed by a given date */
    115  1.17    atatat #define j_leap_days(y, m, d) \
    116  1.17    atatat 	((((y) - 1) / 4) + j_leap_year(y, m, d))
    117  1.17    atatat 
    118  1.17    atatat /* number of gregorian leap days that have passed by a given date */
    119  1.17    atatat #define g_leap_days(y, m, d) \
    120  1.17    atatat 	((((y) - 1) / 4) - (((y) - 1) / 100) + (((y) - 1) / 400) + \
    121  1.17    atatat 	g_leap_year(y, m, d))
    122  1.17    atatat 
    123  1.17    atatat /*
    124  1.17    atatat  * Subtracting the gregorian leap day count (for a given date) from
    125  1.17    atatat  * the julian leap day count (for the same date) describes the number
    126  1.17    atatat  * of days from the date before the shift to the next date that
    127  1.17    atatat  * appears in the calendar.  Since we want to know the number of
    128  1.17    atatat  * *missing* days, not the number of days that the shift spans, we
    129  1.17    atatat  * subtract 2.
    130  1.17    atatat  *
    131  1.17    atatat  * Alternately...
    132  1.17    atatat  *
    133  1.17    atatat  * There's a reason they call the Dark ages the Dark Ages.  Part of it
    134  1.17    atatat  * is that we don't have that many records of that period of time.
    135  1.17    atatat  * One of the reasons for this is that a lot of the Dark Ages never
    136  1.17    atatat  * actually took place.  At some point in the first millenium A.D., a
    137  1.17    atatat  * ruler of some power decided that he wanted the number of the year
    138  1.17    atatat  * to be different than what it was, so he changed it to coincide
    139  1.17    atatat  * nicely with some event (a birthday or anniversary, perhaps a
    140  1.17    atatat  * wedding, or maybe a centennial for a largish city).  One of the
    141  1.17    atatat  * side effects of this upon the Gregorian reform is that two Julian
    142  1.17    atatat  * leap years (leap days celebrated during centennial years that are
    143  1.17    atatat  * not quatro-centennial years) were skipped.
    144  1.17    atatat  */
    145  1.17    atatat #define GREGORIAN_MAGIC 2
    146  1.17    atatat 
    147  1.17    atatat /* number of centuries since the reform, not inclusive */
    148  1.17    atatat #define	centuries_since_reform(yr) \
    149  1.17    atatat 	((yr) > reform->year ? ((yr) / 100) - (reform->year / 100) : 0)
    150  1.17    atatat 
    151  1.17    atatat /* number of centuries since the reform whose modulo of 400 is 0 */
    152  1.17    atatat #define	quad_centuries_since_reform(yr) \
    153  1.17    atatat 	((yr) > reform->year ? ((yr) / 400) - (reform->year / 400) : 0)
    154   1.1       cgd 
    155   1.1       cgd /* number of leap years between year 1 and this year, not inclusive */
    156   1.1       cgd #define	leap_years_since_year_1(yr) \
    157  1.17    atatat 	((yr) / 4 - centuries_since_reform(yr) + quad_centuries_since_reform(yr))
    158  1.17    atatat 
    159  1.17    atatat struct reform {
    160  1.17    atatat 	const char *country;
    161  1.17    atatat 	int ambiguity, year, month, date;
    162  1.17    atatat 	long first_missing_day;
    163  1.17    atatat 	int missing_days;
    164  1.17    atatat 	/*
    165  1.17    atatat 	 * That's 2 for standard/julian display, 4 for months possibly
    166  1.17    atatat 	 * affected by the Gregorian shift, and MAXDAYS + 1 for the
    167  1.17    atatat 	 * days that get displayed, plus a crib slot.
    168  1.17    atatat 	 */
    169  1.17    atatat } *reform, reforms[] = {
    170  1.17    atatat 	{ "DEFAULT",		0, 1752,  9,  3 },
    171  1.17    atatat 	{ "Italy",		1, 1582, 10,  5 },
    172  1.17    atatat 	{ "Spain",		1, 1582, 10,  5 },
    173  1.17    atatat 	{ "Portugal",		1, 1582, 10,  5 },
    174  1.17    atatat 	{ "Poland",		1, 1582, 10,  5 },
    175  1.17    atatat 	{ "France",		2, 1582, 12, 10 },
    176  1.17    atatat 	{ "Luxembourg",		2, 1582, 12, 22 },
    177  1.17    atatat 	{ "Netherlands",	2, 1582, 12, 22 },
    178  1.17    atatat 	{ "Bavaria",		0, 1583, 10,  6 },
    179  1.17    atatat 	{ "Austria",		2, 1584,  1,  7 },
    180  1.17    atatat 	{ "Switzerland",	2, 1584,  1, 12 },
    181  1.17    atatat 	{ "Hungary",		0, 1587, 10, 22 },
    182  1.17    atatat 	{ "Germany",		0, 1700,  2, 19 },
    183  1.17    atatat 	{ "Norway",		0, 1700,  2, 19 },
    184  1.17    atatat 	{ "Denmark",		0, 1700,  2, 19 },
    185  1.17    atatat 	{ "Great Britain",	0, 1752,  9,  3 },
    186  1.17    atatat 	{ "England",		0, 1752,  9,  3 },
    187  1.17    atatat 	{ "America",		0, 1752,  9,  3 },
    188  1.17    atatat 	{ "Sweden",		0, 1753,  2, 18 },
    189  1.17    atatat 	{ "Finland",		0, 1753,  2, 18 },
    190  1.17    atatat 	{ "Japan",		0, 1872, 12, 20 },
    191  1.17    atatat 	{ "China",		0, 1911, 11,  7 },
    192  1.17    atatat 	{ "Bulgaria",		0, 1916,  4,  1 },
    193  1.17    atatat 	{ "U.S.S.R.",		0, 1918,  2,  1 },
    194  1.17    atatat 	{ "Serbia",		0, 1919,  1, 19 },
    195  1.17    atatat 	{ "Romania",		0, 1919,  1, 19 },
    196  1.17    atatat 	{ "Greece",		0, 1924,  3, 10 },
    197  1.17    atatat 	{ "Turkey",		0, 1925, 12, 19 },
    198  1.17    atatat 	{ "Egypt",		0, 1928,  9, 18 },
    199  1.17    atatat 	{ NULL,			0,    0,  0,  0 },
    200  1.17    atatat };
    201   1.1       cgd 
    202   1.1       cgd int julian;
    203  1.17    atatat int dow;
    204  1.15    atatat int hilite;
    205  1.15    atatat char *md, *me;
    206   1.1       cgd 
    207  1.15    atatat void	init_hilite(void);
    208  1.14      yamt int	getnum(const char *);
    209  1.17    atatat void	gregorian_reform(const char *);
    210  1.17    atatat void	reform_day_array(int, int, int *, int *, int *,int *,int *,int *);
    211  1.15    atatat int	ascii_day(char *, int);
    212  1.12     perry void	center(char *, int, int);
    213  1.12     perry void	day_array(int, int, int *);
    214  1.12     perry int	day_in_week(int, int, int);
    215  1.12     perry int	day_in_year(int, int, int);
    216  1.14      yamt void	monthrange(int, int, int, int, int);
    217  1.12     perry int	main(int, char **);
    218  1.12     perry void	trim_trailing_spaces(char *);
    219  1.12     perry void	usage(void);
    220   1.6     glass 
    221   1.6     glass int
    222  1.12     perry main(int argc, char **argv)
    223   1.1       cgd {
    224   1.1       cgd 	struct tm *local_time;
    225   1.6     glass 	time_t now;
    226  1.14      yamt 	int ch, month, year, yflag;
    227  1.17    atatat 	int before, after, use_reform;
    228  1.14      yamt 	int yearly = 0;
    229  1.17    atatat 	char *when;
    230   1.1       cgd 
    231  1.14      yamt 	before = after = 0;
    232  1.17    atatat 	use_reform = yflag = year = 0;
    233  1.17    atatat 	when = NULL;
    234  1.17    atatat 	while ((ch = getopt(argc, argv, "A:B:d:hjR:ry3")) != -1) {
    235  1.12     perry 		switch (ch) {
    236  1.14      yamt 		case 'A':
    237  1.14      yamt 			after = getnum(optarg);
    238  1.14      yamt 			break;
    239  1.14      yamt 		case 'B':
    240  1.14      yamt 			before = getnum(optarg);
    241  1.14      yamt 			break;
    242  1.17    atatat 		case 'd':
    243  1.17    atatat 			dow = getnum(optarg);
    244  1.17    atatat 			if (dow < 0 || dow > 6)
    245  1.17    atatat 				errx(1, "illegal day of week value: use 0-6");
    246  1.17    atatat 			break;
    247  1.15    atatat 		case 'h':
    248  1.15    atatat 			init_hilite();
    249  1.15    atatat 			break;
    250   1.1       cgd 		case 'j':
    251   1.1       cgd 			julian = 1;
    252   1.1       cgd 			break;
    253  1.17    atatat 		case 'R':
    254  1.17    atatat 			when = optarg;
    255  1.17    atatat 			break;
    256  1.17    atatat 		case 'r':
    257  1.17    atatat 			use_reform = 1;
    258  1.17    atatat 			break;
    259   1.1       cgd 		case 'y':
    260   1.1       cgd 			yflag = 1;
    261   1.1       cgd 			break;
    262  1.13     perry 		case '3':
    263  1.14      yamt 			before = after = 1;
    264  1.13     perry 			break;
    265   1.1       cgd 		case '?':
    266   1.1       cgd 		default:
    267   1.1       cgd 			usage();
    268  1.12     perry 			/* NOTREACHED */
    269   1.1       cgd 		}
    270  1.12     perry 	}
    271  1.13     perry 
    272   1.1       cgd 	argc -= optind;
    273   1.1       cgd 	argv += optind;
    274   1.1       cgd 
    275  1.17    atatat 	if (when != NULL)
    276  1.17    atatat 		gregorian_reform(when);
    277  1.17    atatat 	if (reform == NULL)
    278  1.17    atatat 		gregorian_reform("DEFAULT");
    279  1.17    atatat 
    280   1.1       cgd 	month = 0;
    281  1.12     perry 	switch (argc) {
    282   1.1       cgd 	case 2:
    283   1.6     glass 		if ((month = atoi(*argv++)) < 1 || month > 12)
    284   1.6     glass 			errx(1, "illegal month value: use 1-12");
    285   1.1       cgd 		/* FALLTHROUGH */
    286   1.1       cgd 	case 1:
    287   1.6     glass 		if ((year = atoi(*argv)) < 1 || year > 9999)
    288   1.6     glass 			errx(1, "illegal year value: use 1-9999");
    289   1.1       cgd 		break;
    290   1.1       cgd 	case 0:
    291   1.1       cgd 		(void)time(&now);
    292   1.1       cgd 		local_time = localtime(&now);
    293  1.17    atatat 		if (use_reform)
    294  1.17    atatat 			year = reform->year;
    295  1.17    atatat 		else
    296  1.17    atatat 			year = local_time->tm_year + TM_YEAR_BASE;
    297  1.17    atatat 		if (!yflag) {
    298  1.17    atatat 			if (use_reform)
    299  1.17    atatat 				month = reform->month;
    300  1.17    atatat 			else
    301  1.17    atatat 				month = local_time->tm_mon + 1;
    302  1.17    atatat 		}
    303   1.1       cgd 		break;
    304   1.1       cgd 	default:
    305   1.1       cgd 		usage();
    306   1.1       cgd 	}
    307   1.1       cgd 
    308  1.14      yamt 	if (!month) {
    309  1.14      yamt 		/* yearly */
    310  1.14      yamt 		month = 1;
    311  1.14      yamt 		before = 0;
    312  1.14      yamt 		after = 11;
    313  1.14      yamt 		yearly = 1;
    314  1.14      yamt 	}
    315  1.14      yamt 
    316  1.14      yamt 	monthrange(month, year, before, after, yearly);
    317  1.13     perry 
    318   1.1       cgd 	exit(0);
    319   1.1       cgd }
    320   1.1       cgd 
    321   1.1       cgd #define	DAY_LEN		3		/* 3 spaces per day */
    322   1.1       cgd #define	J_DAY_LEN	4		/* 4 spaces per day */
    323   1.1       cgd #define	WEEK_LEN	20		/* 7 * 3 - one space at the end */
    324   1.1       cgd #define	J_WEEK_LEN	27		/* 7 * 4 - one space at the end */
    325   1.1       cgd #define	HEAD_SEP	2		/* spaces between day headings */
    326   1.1       cgd #define	J_HEAD_SEP	2
    327  1.14      yamt #define	MONTH_PER_ROW	3		/* how many monthes in a row */
    328  1.14      yamt #define	J_MONTH_PER_ROW	2
    329   1.1       cgd 
    330   1.6     glass void
    331  1.14      yamt monthrange(int month, int year, int before, int after, int yearly)
    332   1.1       cgd {
    333  1.14      yamt 	int startmonth, startyear;
    334  1.14      yamt 	int endmonth, endyear;
    335  1.14      yamt 	int i, row;
    336  1.14      yamt 	int days[3][MAXDAYS];
    337  1.15    atatat 	char lineout[256];
    338  1.14      yamt 	int inayear;
    339  1.14      yamt 	int newyear;
    340  1.14      yamt 	int day_len, week_len, head_sep;
    341  1.14      yamt 	int month_per_row;
    342  1.15    atatat 	int skip, r_off, w_off;
    343  1.14      yamt 
    344  1.14      yamt 	if (julian) {
    345  1.14      yamt 		day_len = J_DAY_LEN;
    346  1.14      yamt 		week_len = J_WEEK_LEN;
    347  1.14      yamt 		head_sep = J_HEAD_SEP;
    348  1.14      yamt 		month_per_row = J_MONTH_PER_ROW;
    349  1.14      yamt 	}
    350  1.14      yamt 	else {
    351  1.14      yamt 		day_len = DAY_LEN;
    352  1.14      yamt 		week_len = WEEK_LEN;
    353  1.14      yamt 		head_sep = HEAD_SEP;
    354  1.14      yamt 		month_per_row = MONTH_PER_ROW;
    355  1.14      yamt 	}
    356  1.14      yamt 
    357  1.14      yamt 	month--;
    358  1.14      yamt 
    359  1.14      yamt 	startyear = year - (before + 12 - 1 - month) / 12;
    360  1.14      yamt 	startmonth = 12 - 1 - ((before + 12 - 1 - month) % 12);
    361  1.14      yamt 	endyear = year + (month + after) / 12;
    362  1.14      yamt 	endmonth = (month + after) % 12;
    363   1.1       cgd 
    364  1.14      yamt 	if (startyear < 0 || endyear > 9999) {
    365  1.14      yamt 		errx(1, "year should be in 1-9999\n");
    366   1.1       cgd 	}
    367   1.1       cgd 
    368  1.14      yamt 	year = startyear;
    369  1.14      yamt 	month = startmonth;
    370  1.14      yamt 	inayear = newyear = (year != endyear || yearly);
    371  1.14      yamt 	if (inayear) {
    372  1.14      yamt 		skip = month % month_per_row;
    373  1.14      yamt 		month -= skip;
    374  1.14      yamt 	}
    375  1.14      yamt 	else {
    376  1.14      yamt 		skip = 0;
    377  1.14      yamt 	}
    378  1.14      yamt 
    379  1.14      yamt 	do {
    380  1.14      yamt 		if (newyear) {
    381  1.14      yamt 			(void)snprintf(lineout, sizeof(lineout), "%d", year);
    382  1.14      yamt 			center(lineout, week_len * month_per_row +
    383  1.14      yamt 			    head_sep * (month_per_row - 1), 0);
    384  1.14      yamt 			(void)printf("\n\n");
    385  1.14      yamt 			newyear = 0;
    386  1.14      yamt 		}
    387  1.14      yamt 
    388  1.14      yamt 		for (i = 0; i < skip; i++)
    389  1.14      yamt 			center("", week_len, head_sep);
    390  1.14      yamt 
    391  1.14      yamt 		for (; i < month_per_row; i++) {
    392  1.14      yamt 			int sep;
    393  1.14      yamt 
    394  1.14      yamt 			if (year == endyear && month + i > endmonth)
    395  1.14      yamt 				break;
    396  1.14      yamt 
    397  1.14      yamt 			sep = (i == month_per_row - 1) ? 0 : head_sep;
    398  1.14      yamt 			day_array(month + i + 1, year, days[i]);
    399  1.14      yamt 			if (inayear) {
    400  1.14      yamt 				center(month_names[month + i], week_len, sep);
    401  1.14      yamt 			}
    402  1.14      yamt 			else {
    403  1.14      yamt 				snprintf(lineout, sizeof(lineout), "%s %d",
    404  1.14      yamt 				    month_names[month + i], year);
    405  1.14      yamt 				center(lineout, week_len, sep);
    406   1.1       cgd 			}
    407   1.1       cgd 		}
    408  1.14      yamt 		printf("\n");
    409  1.14      yamt 
    410  1.14      yamt 		for (i = 0; i < skip; i++)
    411  1.14      yamt 			center("", week_len, head_sep);
    412  1.14      yamt 
    413  1.14      yamt 		for (; i < month_per_row; i++) {
    414  1.14      yamt 			int sep;
    415  1.14      yamt 
    416  1.14      yamt 			if (year == endyear && month + i > endmonth)
    417  1.14      yamt 				break;
    418  1.14      yamt 
    419  1.14      yamt 			sep = (i == month_per_row - 1) ? 0 : head_sep;
    420  1.17    atatat 			if (dow) {
    421  1.17    atatat 				printf("%s ", (julian) ?
    422  1.17    atatat 				    j_day_headings + 4 * dow :
    423  1.17    atatat 				    day_headings + 3 * dow);
    424  1.17    atatat 				printf("%.*s", dow * (julian ? 4 : 3) - 1,
    425  1.17    atatat 				       (julian) ? j_day_headings : day_headings);
    426  1.17    atatat 			} else
    427  1.17    atatat 				printf("%s", (julian) ? j_day_headings : day_headings);
    428  1.17    atatat 			printf("%*s", sep, "");
    429  1.14      yamt 		}
    430  1.14      yamt 		printf("\n");
    431   1.1       cgd 
    432   1.1       cgd 		for (row = 0; row < 6; row++) {
    433  1.14      yamt 			char *p;
    434  1.16      yamt 
    435  1.16      yamt 			memset(lineout, ' ', sizeof(lineout));
    436  1.14      yamt 			for (i = 0; i < skip; i++) {
    437  1.16      yamt 				/* nothing */
    438  1.14      yamt 			}
    439  1.15    atatat 			w_off = 0;
    440  1.14      yamt 			for (; i < month_per_row; i++) {
    441  1.14      yamt 				int col, *dp;
    442  1.14      yamt 
    443  1.14      yamt 				if (year == endyear && month + i > endmonth)
    444  1.14      yamt 					break;
    445  1.14      yamt 
    446  1.15    atatat 				p = lineout + i * (week_len + 2) + w_off;
    447  1.14      yamt 				dp = &days[i][row * 7];
    448  1.15    atatat 				for (col = 0; col < 7;
    449  1.15    atatat 				     col++, p += day_len + r_off) {
    450  1.15    atatat 					r_off = ascii_day(p, *dp++);
    451  1.15    atatat 					w_off += r_off;
    452  1.15    atatat 				}
    453   1.1       cgd 			}
    454   1.3       cgd 			*p = '\0';
    455   1.1       cgd 			trim_trailing_spaces(lineout);
    456   1.1       cgd 			(void)printf("%s\n", lineout);
    457   1.1       cgd 		}
    458  1.13     perry 
    459  1.14      yamt 		skip = 0;
    460  1.14      yamt 		month += month_per_row;
    461  1.14      yamt 		if (month >= 12) {
    462  1.14      yamt 			month -= 12;
    463  1.14      yamt 			year++;
    464  1.14      yamt 			newyear = 1;
    465  1.13     perry 		}
    466  1.14      yamt 	} while (year < endyear || (year == endyear && month <= endmonth));
    467  1.13     perry }
    468  1.13     perry 
    469   1.1       cgd /*
    470   1.1       cgd  * day_array --
    471   1.1       cgd  *	Fill in an array of 42 integers with a calendar.  Assume for a moment
    472   1.1       cgd  *	that you took the (maximum) 6 rows in a calendar and stretched them
    473   1.1       cgd  *	out end to end.  You would have 42 numbers or spaces.  This routine
    474   1.1       cgd  *	builds that array for any month from Jan. 1 through Dec. 9999.
    475   1.1       cgd  */
    476   1.6     glass void
    477  1.12     perry day_array(int month, int year, int *days)
    478   1.1       cgd {
    479   1.6     glass 	int day, dw, dm;
    480  1.15    atatat 	time_t t;
    481  1.15    atatat 	struct tm *tm;
    482  1.15    atatat 
    483  1.15    atatat 	t = time(NULL);
    484  1.15    atatat 	tm = localtime(&t);
    485  1.15    atatat 	tm->tm_year += TM_YEAR_BASE;
    486  1.15    atatat 	tm->tm_mon++;
    487  1.15    atatat 	tm->tm_yday++; /* jan 1 is 1 for us, not 0 */
    488   1.1       cgd 
    489  1.17    atatat 	for (dm = month + year * 12, dw = 0; dw < 4; dw++) {
    490  1.17    atatat 		if (dm == shift_days[julian][dw][MAXDAYS]) {
    491  1.17    atatat 			memmove(days, shift_days[julian][dw],
    492  1.17    atatat 				MAXDAYS * sizeof(int));
    493  1.17    atatat 			return;
    494  1.17    atatat 		}
    495   1.1       cgd 	}
    496  1.17    atatat 
    497   1.6     glass 	memmove(days, empty, MAXDAYS * sizeof(int));
    498   1.1       cgd 	dm = days_in_month[leap_year(year)][month];
    499   1.1       cgd 	dw = day_in_week(1, month, year);
    500   1.1       cgd 	day = julian ? day_in_year(1, month, year) : 1;
    501  1.15    atatat 	while (dm--) {
    502  1.15    atatat 		if (hilite && year == tm->tm_year &&
    503  1.15    atatat 		    (julian ? (day == tm->tm_yday) :
    504  1.15    atatat 		     (month == tm->tm_mon && day == tm->tm_mday)))
    505  1.17    atatat 			days[dw++] = SPACE - day++;
    506  1.15    atatat 		else
    507  1.15    atatat 			days[dw++] = day++;
    508  1.15    atatat 	}
    509   1.1       cgd }
    510   1.1       cgd 
    511   1.1       cgd /*
    512   1.1       cgd  * day_in_year --
    513   1.1       cgd  *	return the 1 based day number within the year
    514   1.1       cgd  */
    515   1.6     glass int
    516  1.12     perry day_in_year(int day, int month, int year)
    517   1.1       cgd {
    518   1.6     glass 	int i, leap;
    519   1.1       cgd 
    520   1.1       cgd 	leap = leap_year(year);
    521   1.1       cgd 	for (i = 1; i < month; i++)
    522   1.1       cgd 		day += days_in_month[leap][i];
    523   1.6     glass 	return (day);
    524   1.1       cgd }
    525   1.1       cgd 
    526   1.1       cgd /*
    527   1.1       cgd  * day_in_week
    528   1.1       cgd  *	return the 0 based day number for any date from 1 Jan. 1 to
    529  1.17    atatat  *	31 Dec. 9999.  Returns the day of the week of the first
    530  1.17    atatat  *	missing day for any given Gregorian shift.
    531   1.1       cgd  */
    532   1.6     glass int
    533  1.12     perry day_in_week(int day, int month, int year)
    534   1.1       cgd {
    535   1.1       cgd 	long temp;
    536   1.1       cgd 
    537   1.1       cgd 	temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
    538   1.1       cgd 	    + day_in_year(day, month, year);
    539   1.1       cgd 	if (temp < FIRST_MISSING_DAY)
    540  1.17    atatat 		return ((temp - dow + 6 + SATURDAY) % 7);
    541   1.1       cgd 	if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS))
    542  1.17    atatat 		return (((temp - dow + 6 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
    543  1.17    atatat 	return ((FIRST_MISSING_DAY - dow + 6 + SATURDAY) % 7);
    544   1.1       cgd }
    545   1.1       cgd 
    546  1.15    atatat int
    547  1.12     perry ascii_day(char *p, int day)
    548   1.1       cgd {
    549  1.15    atatat 	int display, val, rc;
    550  1.15    atatat 	char *b;
    551   1.1       cgd 	static char *aday[] = {
    552   1.1       cgd 		"",
    553   1.1       cgd 		" 1", " 2", " 3", " 4", " 5", " 6", " 7",
    554   1.1       cgd 		" 8", " 9", "10", "11", "12", "13", "14",
    555   1.1       cgd 		"15", "16", "17", "18", "19", "20", "21",
    556   1.1       cgd 		"22", "23", "24", "25", "26", "27", "28",
    557   1.1       cgd 		"29", "30", "31",
    558   1.1       cgd 	};
    559   1.1       cgd 
    560   1.1       cgd 	if (day == SPACE) {
    561   1.1       cgd 		memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
    562  1.15    atatat 		return (0);
    563   1.1       cgd 	}
    564  1.17    atatat 	if (day < SPACE) {
    565  1.15    atatat 		b = p;
    566  1.17    atatat 		day = SPACE - day;
    567  1.15    atatat 	} else
    568  1.15    atatat 		b = NULL;
    569   1.1       cgd 	if (julian) {
    570   1.7     lukem 		if ((val = day / 100) != 0) {
    571   1.1       cgd 			day %= 100;
    572   1.1       cgd 			*p++ = val + '0';
    573   1.1       cgd 			display = 1;
    574   1.1       cgd 		} else {
    575   1.1       cgd 			*p++ = ' ';
    576   1.1       cgd 			display = 0;
    577   1.1       cgd 		}
    578   1.1       cgd 		val = day / 10;
    579   1.1       cgd 		if (val || display)
    580   1.1       cgd 			*p++ = val + '0';
    581   1.1       cgd 		else
    582   1.1       cgd 			*p++ = ' ';
    583   1.1       cgd 		*p++ = day % 10 + '0';
    584   1.1       cgd 	} else {
    585   1.1       cgd 		*p++ = aday[day][0];
    586   1.1       cgd 		*p++ = aday[day][1];
    587   1.1       cgd 	}
    588  1.15    atatat 
    589  1.15    atatat 	rc = 0;
    590  1.15    atatat 	if (b != NULL) {
    591  1.15    atatat 		char *t, h[64];
    592  1.15    atatat 		int l;
    593  1.15    atatat 
    594  1.15    atatat 		l = p - b;
    595  1.15    atatat 		memcpy(h, b, l);
    596  1.15    atatat 		p = b;
    597  1.15    atatat 
    598  1.15    atatat 		if (md != NULL) {
    599  1.15    atatat 			for (t = md; *t; rc++)
    600  1.15    atatat 				*p++ = *t++;
    601  1.15    atatat 			memcpy(p, h, l);
    602  1.15    atatat 			p += l;
    603  1.15    atatat 			for (t = me; *t; rc++)
    604  1.15    atatat 				*p++ = *t++;
    605  1.15    atatat 		} else {
    606  1.15    atatat 			for (t = &h[0]; l--; t++) {
    607  1.15    atatat 				*p++ = *t;
    608  1.15    atatat 				rc++;
    609  1.15    atatat 				*p++ = '\b';
    610  1.15    atatat 				rc++;
    611  1.15    atatat 				*p++ = *t;
    612  1.15    atatat 			}
    613  1.15    atatat 		}
    614  1.15    atatat 	}
    615  1.15    atatat 
    616   1.1       cgd 	*p = ' ';
    617  1.15    atatat 	return (rc);
    618   1.1       cgd }
    619   1.1       cgd 
    620   1.6     glass void
    621  1.12     perry trim_trailing_spaces(char *s)
    622   1.1       cgd {
    623   1.6     glass 	char *p;
    624   1.1       cgd 
    625   1.6     glass 	for (p = s; *p; ++p)
    626   1.6     glass 		continue;
    627  1.11  christos 	while (p > s && isspace((unsigned char)*--p))
    628   1.6     glass 		continue;
    629   1.1       cgd 	if (p > s)
    630   1.1       cgd 		++p;
    631   1.1       cgd 	*p = '\0';
    632   1.1       cgd }
    633   1.1       cgd 
    634   1.6     glass void
    635  1.12     perry center(char *str, int len, int separate)
    636   1.1       cgd {
    637   1.6     glass 
    638   1.1       cgd 	len -= strlen(str);
    639   1.1       cgd 	(void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
    640   1.1       cgd 	if (separate)
    641   1.1       cgd 		(void)printf("%*s", separate, "");
    642   1.1       cgd }
    643   1.1       cgd 
    644  1.17    atatat /*
    645  1.17    atatat  * gregorian_reform --
    646  1.17    atatat  *	Given a description of date on which the Gregorian Reform was
    647  1.17    atatat  *	applied.  The argument can be any of the "country" names
    648  1.17    atatat  *	listed in the reforms array (case insensitive) or a date of
    649  1.17    atatat  *	the form YYYY/MM/DD.  The date and month can be omitted if
    650  1.17    atatat  *	doing so would not select more than one different built-in
    651  1.17    atatat  *	reform point.
    652  1.17    atatat  */
    653  1.17    atatat void
    654  1.17    atatat gregorian_reform(const char *p)
    655  1.17    atatat {
    656  1.17    atatat 	int year, month, date;
    657  1.17    atatat 	int i, days, diw, diy;
    658  1.17    atatat 	char c;
    659  1.17    atatat 
    660  1.17    atatat 	i = sscanf(p, "%d%*[/,-]%d%*[/,-]%d%c", &year, &month, &date, &c);
    661  1.17    atatat 	switch (i) {
    662  1.17    atatat 	case 4:
    663  1.17    atatat 		/*
    664  1.17    atatat 		 * If the character was sscanf()ed, then there's more
    665  1.17    atatat 		 * stuff than we need.
    666  1.17    atatat 		 */
    667  1.17    atatat 		errx(1, "date specifier %s invalid", p);
    668  1.17    atatat 	case 0:
    669  1.17    atatat 		/*
    670  1.17    atatat 		 * Not a form we can sscanf(), so void these, and we
    671  1.17    atatat 		 * can try matching "country" names later.
    672  1.17    atatat 		 */
    673  1.17    atatat 		year = month = date = -1;
    674  1.17    atatat 		break;
    675  1.17    atatat 	case 1:
    676  1.17    atatat 		month = 0;
    677  1.17    atatat 		/*FALLTHROUGH*/
    678  1.17    atatat 	case 2:
    679  1.17    atatat 		date = 0;
    680  1.17    atatat 		/*FALLTHROUGH*/
    681  1.17    atatat 	    case 3:
    682  1.17    atatat 		/*
    683  1.17    atatat 		 * At last, some sanity checking on the values we were
    684  1.17    atatat 		 * given.
    685  1.17    atatat 		 */
    686  1.17    atatat 		if (year < 1 || year > 9999)
    687  1.17    atatat 			errx(1, "%d: illegal year value: use 1-9999", year);
    688  1.17    atatat 		if (i > 1 && (month < 1 || month > 12))
    689  1.17    atatat 			errx(1, "%d: illegal month value: use 1-12", month);
    690  1.17    atatat 		if ((i == 3 && date < 1) || date < 0 ||
    691  1.17    atatat 		    date > days_in_month[1][month])
    692  1.17    atatat 			/*
    693  1.17    atatat 			 * What about someone specifying a leap day in
    694  1.17    atatat 			 * a non-leap year?  Well...that's a tricky
    695  1.17    atatat 			 * one.  We can't yet *say* whether the year
    696  1.17    atatat 			 * in question is a leap year.  What if the
    697  1.17    atatat 			 * date given was, for example, 1700/2/29?  is
    698  1.17    atatat 			 * that a valid leap day?
    699  1.17    atatat 			 *
    700  1.17    atatat 			 * So...we punt, and hope that saying 29 in
    701  1.17    atatat 			 * the case of February isn't too bad an idea.
    702  1.17    atatat 			 */
    703  1.17    atatat 			errx(1, "%d: illegal date value: use 1-%d", date,
    704  1.17    atatat 			     days_in_month[1][month]);
    705  1.17    atatat 		break;
    706  1.17    atatat 	}
    707  1.17    atatat 
    708  1.17    atatat 	/*
    709  1.17    atatat 	 * A complete date was specified, so use the other pope.
    710  1.17    atatat 	 */
    711  1.17    atatat 	if (date > 0) {
    712  1.17    atatat 		static struct reform Goestheveezl;
    713  1.17    atatat 
    714  1.17    atatat 		reform = &Goestheveezl;
    715  1.17    atatat 		reform->country = "Bompzidaize";
    716  1.17    atatat 		reform->year = year;
    717  1.17    atatat 		reform->month = month;
    718  1.17    atatat 		reform->date = date;
    719  1.17    atatat 	}
    720  1.17    atatat 
    721  1.17    atatat 	/*
    722  1.17    atatat 	 * No date information was specified, so let's try to match on
    723  1.17    atatat 	 * country name.
    724  1.17    atatat 	 */
    725  1.17    atatat 	else if (year == -1) {
    726  1.17    atatat 		for (reform = &reforms[0]; reform->year; reform++) {
    727  1.17    atatat 			if (strcasecmp(p, reform->country) == 0)
    728  1.17    atatat 				break;
    729  1.17    atatat 		}
    730  1.17    atatat 	}
    731  1.17    atatat 
    732  1.17    atatat 	/*
    733  1.17    atatat 	 * We have *some* date information, but not a complete date.
    734  1.17    atatat 	 * Let's see if we have enough to pick a single entry from the
    735  1.17    atatat 	 * list that's not ambiguous.
    736  1.17    atatat 	 */
    737  1.17    atatat 	else {
    738  1.17    atatat 		for (reform = &reforms[0]; reform->year; reform++) {
    739  1.17    atatat 			if ((year == 0 || year == reform->year) &&
    740  1.17    atatat 			    (month == 0 || month == reform->month) &&
    741  1.17    atatat 			    (date == 0 || month == reform->date))
    742  1.17    atatat 				break;
    743  1.17    atatat 		}
    744  1.17    atatat 
    745  1.17    atatat 		if (i <= reform->ambiguity)
    746  1.17    atatat 			errx(1, "%s: ambiguous short reform date specification", p);
    747  1.17    atatat 	}
    748  1.17    atatat 
    749  1.17    atatat 	/*
    750  1.17    atatat 	 * Oops...we reached the end of the list.
    751  1.17    atatat 	 */
    752  1.17    atatat 	if (reform->year == 0)
    753  1.17    atatat 		errx(1, "reform name %s invalid", p);
    754  1.17    atatat 
    755  1.17    atatat 	/*
    756  1.17    atatat 	 *
    757  1.17    atatat 	 */
    758  1.17    atatat 	reform->missing_days =
    759  1.17    atatat 		j_leap_days(reform->year, reform->month, reform->date) -
    760  1.17    atatat 		g_leap_days(reform->year, reform->month, reform->date) -
    761  1.17    atatat 		GREGORIAN_MAGIC;
    762  1.17    atatat 
    763  1.17    atatat 	reform->first_missing_day =
    764  1.17    atatat 		(reform->year - 1) * 365 +
    765  1.17    atatat 		day_in_year(reform->date, reform->month, reform->year) +
    766  1.17    atatat 		date +
    767  1.17    atatat 		j_leap_days(reform->year, reform->month, reform->date);
    768  1.17    atatat 
    769  1.17    atatat 	/*
    770  1.17    atatat 	 * Once we know the day of the week of the first missing day,
    771  1.17    atatat 	 * skip back to the first of the month's day of the week.
    772  1.17    atatat 	 */
    773  1.17    atatat 	diw = day_in_week(reform->date, reform->month, reform->year);
    774  1.17    atatat 	diw = (diw + 8 - (reform->date % 7)) % 7;
    775  1.17    atatat 	diy = day_in_year(1, reform->month, reform->year);
    776  1.17    atatat 
    777  1.17    atatat 	/*
    778  1.17    atatat 	 * We might need all four of these (if you switch from Julian
    779  1.17    atatat 	 * to Gregorian at some point after 9900, you get a gap of 73
    780  1.17    atatat 	 * days, and that can affect four months), and it doesn't hurt
    781  1.17    atatat 	 * all that much to precompute them, so there.
    782  1.17    atatat 	 */
    783  1.17    atatat 	date = 1;
    784  1.17    atatat 	days = 0;
    785  1.17    atatat 	for (i = 0; i < 4; i++)
    786  1.17    atatat 		reform_day_array(reform->month + i, reform->year,
    787  1.17    atatat 				 &days, &date, &diw, &diy,
    788  1.17    atatat 				 shift_days[0][i],
    789  1.17    atatat 				 shift_days[1][i]);
    790  1.17    atatat }
    791  1.17    atatat 
    792  1.17    atatat /*
    793  1.17    atatat  * reform_day_array --
    794  1.17    atatat  *	Pre-calculates the given month's calendar (in both "standard"
    795  1.17    atatat  *	and "julian day" representations) with respect for days
    796  1.17    atatat  *	skipped during a reform period.
    797  1.17    atatat  */
    798  1.17    atatat void
    799  1.17    atatat reform_day_array(int month, int year, int *done, int *date, int *diw, int *diy,
    800  1.17    atatat 	int *scal, int *jcal)
    801  1.17    atatat {
    802  1.17    atatat 	int mdays;
    803  1.17    atatat 
    804  1.17    atatat 	/*
    805  1.17    atatat 	 * If the reform was in the month of october or later, then
    806  1.17    atatat 	 * the month number from the caller could "overflow".
    807  1.17    atatat 	 */
    808  1.17    atatat 	if (month > 12) {
    809  1.17    atatat 		month -= 12;
    810  1.17    atatat 		year++;
    811  1.17    atatat 	}
    812  1.17    atatat 
    813  1.17    atatat 	/*
    814  1.17    atatat 	 * Erase months, and set crib number.  The crib number is used
    815  1.17    atatat 	 * later to determine if the month to be displayed is here or
    816  1.17    atatat 	 * should be built on the fly with the generic routine
    817  1.17    atatat 	 */
    818  1.17    atatat 	memmove(scal, empty, MAXDAYS * sizeof(int));
    819  1.17    atatat 	scal[MAXDAYS] = month + year * 12;
    820  1.17    atatat 	memmove(jcal, empty, MAXDAYS * sizeof(int));
    821  1.17    atatat 	jcal[MAXDAYS] = month + year * 12;
    822  1.17    atatat 
    823  1.17    atatat 	/*
    824  1.17    atatat 	 * It doesn't matter what the actual month is when figuring
    825  1.17    atatat 	 * out if this is a leap year or not, just so long as February
    826  1.17    atatat 	 * gets the right number of days in it.
    827  1.17    atatat 	 */
    828  1.17    atatat 	mdays = days_in_month[g_leap_year(year, 3, 1)][month];
    829  1.17    atatat 
    830  1.17    atatat 	/*
    831  1.17    atatat 	 * Bounce back to the first "row" in the day array, and fill
    832  1.17    atatat 	 * in any days that actually occur.
    833  1.17    atatat 	 */
    834  1.17    atatat 	for (*diw %= 7; (*date - *done) <= mdays; (*date)++, (*diy)++) {
    835  1.17    atatat 		/*
    836  1.17    atatat 		 * "date" doesn't get reset by the caller across calls
    837  1.17    atatat 		 * to this routine, so we can actually tell that we're
    838  1.17    atatat 		 * looking at April the 41st.  Much easier than trying
    839  1.17    atatat 		 * to calculate the absolute julian day for a given
    840  1.17    atatat 		 * date and then checking that.
    841  1.17    atatat 		 */
    842  1.17    atatat 		if (*date < reform->date ||
    843  1.17    atatat 		    *date >= reform->date + reform->missing_days) {
    844  1.17    atatat 			scal[*diw] = *date - *done;
    845  1.17    atatat 			jcal[*diw] = *diy;
    846  1.17    atatat 			(*diw)++;
    847  1.17    atatat 		}
    848  1.17    atatat 	}
    849  1.17    atatat 	*done += mdays;
    850  1.17    atatat }
    851  1.17    atatat 
    852  1.14      yamt int
    853  1.14      yamt getnum(const char *p)
    854  1.14      yamt {
    855  1.14      yamt 	long result;
    856  1.14      yamt 	char *ep;
    857  1.14      yamt 
    858  1.14      yamt 	errno = 0;
    859  1.14      yamt 	result = strtoul(p, &ep, 10);
    860  1.14      yamt 	if (p[0] == '\0' || *ep != '\0')
    861  1.14      yamt 		goto error;
    862  1.14      yamt 	if (errno == ERANGE && result == ULONG_MAX)
    863  1.14      yamt 		goto error;
    864  1.14      yamt 	if (result > INT_MAX)
    865  1.14      yamt 		goto error;
    866  1.14      yamt 
    867  1.14      yamt 	return (int)result;
    868  1.14      yamt 
    869  1.14      yamt error:
    870  1.14      yamt 	errx(1, "bad number: %s", p);
    871  1.14      yamt 	/*NOTREACHED*/
    872  1.14      yamt }
    873  1.14      yamt 
    874   1.6     glass void
    875  1.15    atatat init_hilite(void)
    876  1.15    atatat {
    877  1.15    atatat 	static char control[128];
    878  1.15    atatat 	char cap[1024];
    879  1.15    atatat 	char *tc;
    880  1.15    atatat 
    881  1.15    atatat 	hilite++;
    882  1.15    atatat 
    883  1.15    atatat 	if (!isatty(fileno(stdout)))
    884  1.15    atatat 		return;
    885  1.15    atatat 
    886  1.15    atatat 	tc = getenv("TERM");
    887  1.15    atatat 	if (tc == NULL)
    888  1.15    atatat 		tc = "dumb";
    889  1.15    atatat 	if (tgetent(&cap[0], tc) != 1)
    890  1.15    atatat 		return;
    891  1.15    atatat 
    892  1.15    atatat 	tc = &control[0];
    893  1.15    atatat 	if ((md = tgetstr(hilite > 1 ? "mr" : "md", &tc)))
    894  1.15    atatat 		*tc++ = '\0';
    895  1.15    atatat 	if ((me = tgetstr("me", &tc)))
    896  1.15    atatat 		*tc++ = '\0';
    897  1.15    atatat 	if (me == NULL || md == NULL)
    898  1.15    atatat 		md = me = NULL;
    899  1.15    atatat }
    900  1.15    atatat 
    901  1.15    atatat void
    902  1.12     perry usage(void)
    903   1.1       cgd {
    904   1.6     glass 
    905  1.14      yamt 	(void)fprintf(stderr,
    906  1.17    atatat 	    "usage: cal [-hjry3] [-d day-of-week] [-B before] [-A after] "
    907  1.17    atatat 	    "[-R reform-spec]\n           [[month] year]\n");
    908   1.1       cgd 	exit(1);
    909   1.1       cgd }
    910