- add -A and -B option.

- change -3 to a synonym of "-A1 -B1".
  (to make compatible other implementations)
- eliminate duplicated codes.
- fix crashes for -3.
This commit is contained in:
yamt 2002-10-25 20:06:56 +00:00
parent 9d459e65ae
commit c81873c76e
2 changed files with 182 additions and 148 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: cal.1,v 1.11 2002/06/23 00:22:56 wiz Exp $
.\" $NetBSD: cal.1,v 1.12 2002/10/25 20:06:56 yamt Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -36,7 +36,7 @@
.\"
.\" @(#)cal.1 8.2 (Berkeley) 4/28/95
.\"
.Dd April 28, 1995
.Dd October 25, 2002
.Dt CAL 1
.Os
.Sh NAME
@ -45,6 +45,8 @@
.Sh SYNOPSIS
.Nm
.Op Fl jy3
.Op Fl A after
.Op Fl B before
.Op Oo Ar month Oc Ar \ year
.Sh DESCRIPTION
.Nm
@ -53,15 +55,20 @@ If arguments are not specified,
the current month is displayed.
The options are as follows:
.Bl -tag -width Ds
.It Fl A Ar after
Display
.Ar after
monthes after the specified month.
.It Fl B Ar before
Display
.Ar before
monthes before the specified month.
.It Fl j
Display julian dates (days one-based, numbered from January 1).
.It Fl y
Display a calendar for the current year.
.It Fl 3
Display a three month calendar, starting with the current month or the
specified year and month. If a year is specified but no month is
specified January is assumed. This option is not compatible with
.Fl j .
Same as -A1 -B1.
.El
.Pp
A single parameter specifies the year (1 - 9999) to be displayed;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cal.c,v 1.13 2002/06/22 21:14:18 perry Exp $ */
/* $NetBSD: cal.c,v 1.14 2002/10/25 20:06:56 yamt Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
@ -46,7 +46,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
#if 0
static char sccsid[] = "@(#)cal.c 8.4 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: cal.c,v 1.13 2002/06/22 21:14:18 perry Exp $");
__RCSID("$NetBSD: cal.c,v 1.14 2002/10/25 20:06:56 yamt Exp $");
#endif
#endif /* not lint */
@ -54,6 +54,8 @@ __RCSID("$NetBSD: cal.c,v 1.13 2002/06/22 21:14:18 perry Exp $");
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -125,30 +127,36 @@ char *j_day_headings = " S M Tu W Th F S";
int julian;
int getnum(const char *);
void ascii_day(char *, int);
void center(char *, int, int);
void day_array(int, int, int *);
int day_in_week(int, int, int);
int day_in_year(int, int, int);
void j_yearly(int);
void month3(int, int);
void monthly(int, int);
void monthrange(int, int, int, int, int);
int main(int, char **);
void trim_trailing_spaces(char *);
void usage(void);
void yearly(int);
int
main(int argc, char **argv)
{
struct tm *local_time;
time_t now;
int ch, month, year, yflag, threeflag;
int ch, month, year, yflag;
int before, after;
int yearly = 0;
before = after = 0;
yflag = year = 0;
threeflag = 0;
while ((ch = getopt(argc, argv, "jy3")) != -1) {
while ((ch = getopt(argc, argv, "A:B:jy3")) != -1) {
switch (ch) {
case 'A':
after = getnum(optarg);
break;
case 'B':
before = getnum(optarg);
break;
case 'j':
julian = 1;
break;
@ -156,7 +164,7 @@ main(int argc, char **argv)
yflag = 1;
break;
case '3':
threeflag = 1;
before = after = 1;
break;
case '?':
default:
@ -165,10 +173,6 @@ main(int argc, char **argv)
}
}
if (threeflag && julian) {
usage();
}
argc -= optind;
argv += optind;
@ -193,14 +197,15 @@ main(int argc, char **argv)
usage();
}
if (threeflag)
month3(month ? month : 1 , year);
else if (month)
monthly(month, year);
else if (julian)
j_yearly(year);
else
yearly(year);
if (!month) {
/* yearly */
month = 1;
before = 0;
after = 11;
yearly = 1;
}
monthrange(month, year, before, after, yearly);
exit(0);
}
@ -211,136 +216,135 @@ main(int argc, char **argv)
#define J_WEEK_LEN 27 /* 7 * 4 - one space at the end */
#define HEAD_SEP 2 /* spaces between day headings */
#define J_HEAD_SEP 2
#define MONTH_PER_ROW 3 /* how many monthes in a row */
#define J_MONTH_PER_ROW 2
void
monthly(int month, int year)
monthrange(int month, int year, int before, int after, int yearly)
{
int col, row, len, days[MAXDAYS];
char *p, lineout[30];
int startmonth, startyear;
int endmonth, endyear;
int i, row;
int days[3][MAXDAYS];
char lineout[80];
int inayear;
int newyear;
int day_len, week_len, head_sep;
int month_per_row;
int skip;
day_array(month, year, days);
len = snprintf(lineout, sizeof(lineout), "%s %d",
month_names[month - 1], year);
(void)printf("%*s%s\n%s\n",
((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "",
lineout, julian ? j_day_headings : day_headings);
for (row = 0; row < 6; row++) {
for (col = 0, p = lineout; col < 7; col++,
p += julian ? J_DAY_LEN : DAY_LEN)
ascii_day(p, days[row * 7 + col]);
*p = '\0';
trim_trailing_spaces(lineout);
(void)printf("%s\n", lineout);
if (julian) {
day_len = J_DAY_LEN;
week_len = J_WEEK_LEN;
head_sep = J_HEAD_SEP;
month_per_row = J_MONTH_PER_ROW;
}
else {
day_len = DAY_LEN;
week_len = WEEK_LEN;
head_sep = HEAD_SEP;
month_per_row = MONTH_PER_ROW;
}
void
j_yearly(int year)
{
int col, *dp, i, month, row, which_cal;
int days[12][MAXDAYS];
char *p, lineout[80];
(void)snprintf(lineout, sizeof(lineout), "%d", year);
center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
(void)printf("\n\n");
for (i = 0; i < 12; i++)
day_array(i + 1, year, days[i]);
(void)memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 2) {
center(month_names[month], J_WEEK_LEN, J_HEAD_SEP);
center(month_names[month + 1], J_WEEK_LEN, 0);
(void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
j_day_headings);
for (row = 0; row < 6; row++) {
for (which_cal = 0; which_cal < 2; which_cal++) {
p = lineout + which_cal * (J_WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
for (col = 0; col < 7; col++, p += J_DAY_LEN)
ascii_day(p, *dp++);
}
*p = '\0';
trim_trailing_spaces(lineout);
(void)printf("%s\n", lineout);
}
}
(void)printf("\n");
}
void
yearly(int year)
{
int col, *dp, i, month, row, which_cal;
int days[12][MAXDAYS];
char *p, lineout[80];
(void)snprintf(lineout, sizeof(lineout), "%d", year);
center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0);
(void)printf("\n\n");
for (i = 0; i < 12; i++)
day_array(i + 1, year, days[i]);
(void)memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 3) {
center(month_names[month], WEEK_LEN, HEAD_SEP);
center(month_names[month + 1], WEEK_LEN, HEAD_SEP);
center(month_names[month + 2], WEEK_LEN, 0);
(void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
"", day_headings, HEAD_SEP, "", day_headings);
for (row = 0; row < 6; row++) {
for (which_cal = 0; which_cal < 3; which_cal++) {
p = lineout + which_cal * (WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
for (col = 0; col < 7; col++, p += DAY_LEN)
ascii_day(p, *dp++);
}
*p = '\0';
trim_trailing_spaces(lineout);
(void)printf("%s\n", lineout);
}
}
(void)printf("\n");
}
void
month3(int month, int year)
{
int col, *dp, i, row, which_cal;
int days[12][MAXDAYS];
char *p, lineout[80];
for (i = 0; i < 12; i++)
day_array(i + 1, year, days[i]);
month--;
snprintf(lineout, sizeof(lineout), "%s %d",
month_names[month], year);
center(lineout, WEEK_LEN, HEAD_SEP);
snprintf(lineout, sizeof(lineout), "%s %d",
month_names[month+1], year);
center(lineout, WEEK_LEN, HEAD_SEP);
snprintf(lineout, sizeof(lineout), "%s %d",
month_names[month+2], year);
center(lineout, WEEK_LEN, 0);
startyear = year - (before + 12 - 1 - month) / 12;
startmonth = 12 - 1 - ((before + 12 - 1 - month) % 12);
endyear = year + (month + after) / 12;
endmonth = (month + after) % 12;
(void)memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
if (startyear < 0 || endyear > 9999) {
errx(1, "year should be in 1-9999\n");
}
(void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
"", day_headings, HEAD_SEP, "", day_headings);
year = startyear;
month = startmonth;
inayear = newyear = (year != endyear || yearly);
if (inayear) {
skip = month % month_per_row;
month -= skip;
}
else {
skip = 0;
}
do {
if (newyear) {
(void)snprintf(lineout, sizeof(lineout), "%d", year);
center(lineout, week_len * month_per_row +
head_sep * (month_per_row - 1), 0);
(void)printf("\n\n");
newyear = 0;
}
for (i = 0; i < skip; i++)
center("", week_len, head_sep);
for (; i < month_per_row; i++) {
int sep;
if (year == endyear && month + i > endmonth)
break;
sep = (i == month_per_row - 1) ? 0 : head_sep;
day_array(month + i + 1, year, days[i]);
if (inayear) {
center(month_names[month + i], week_len, sep);
}
else {
snprintf(lineout, sizeof(lineout), "%s %d",
month_names[month + i], year);
center(lineout, week_len, sep);
}
}
printf("\n");
for (i = 0; i < skip; i++)
center("", week_len, head_sep);
for (; i < month_per_row; i++) {
int sep;
if (year == endyear && month + i > endmonth)
break;
sep = (i == month_per_row - 1) ? 0 : head_sep;
printf("%s%*s",
(julian) ? j_day_headings : day_headings, sep, "");
}
printf("\n");
memset(lineout, ' ', sizeof(lineout));
for (row = 0; row < 6; row++) {
for (which_cal = 0; which_cal < 3; which_cal++) {
p = lineout + which_cal * (WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
for (col = 0; col < 7; col++, p += DAY_LEN)
char *p;
for (i = 0; i < skip; i++) {
p = lineout + i * (week_len + 2);
memset(p, ' ', week_len);
}
for (; i < month_per_row; i++) {
int col, *dp;
if (year == endyear && month + i > endmonth)
break;
p = lineout + i * (week_len + 2);
dp = &days[i][row * 7];
for (col = 0; col < 7; col++, p += day_len)
ascii_day(p, *dp++);
}
*p = '\0';
trim_trailing_spaces(lineout);
(void)printf("%s\n", lineout);
}
skip = 0;
month += month_per_row;
if (month >= 12) {
month -= 12;
year++;
newyear = 1;
}
} while (year < endyear || (year == endyear && month <= endmonth));
}
/*
@ -467,10 +471,33 @@ center(char *str, int len, int separate)
(void)printf("%*s", separate, "");
}
int
getnum(const char *p)
{
long result;
char *ep;
errno = 0;
result = strtoul(p, &ep, 10);
if (p[0] == '\0' || *ep != '\0')
goto error;
if (errno == ERANGE && result == ULONG_MAX)
goto error;
if (result > INT_MAX)
goto error;
return (int)result;
error:
errx(1, "bad number: %s", p);
/*NOTREACHED*/
}
void
usage(void)
{
(void)fprintf(stderr, "usage: cal [-jy3] [[month] year]\n");
(void)fprintf(stderr,
"usage: cal [-jy3] [-B before] [-A after] [[month] year]\n");
exit(1);
}