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