Audit cal(1)

1) Update manpage with the num-syntax.
2) Use size_t for years and derivatives.
3) Use putchar instead of printf wherever possible.
4) Update usage().
5) Style changes.
This commit is contained in:
FRIGN 2015-03-08 21:28:32 +01:00
parent f140403fca
commit 76ad86b2a3
3 changed files with 64 additions and 63 deletions

2
README
View File

@ -10,7 +10,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
UTILITY POSIX 2008 COMPLIANT MISSING OPTIONS UTILITY POSIX 2008 COMPLIANT MISSING OPTIONS
------- -------------------- --------------- ------- -------------------- ---------------
=*| basename yes none =*| basename yes none
=* cal yes none =*| cal yes none
=*| cat yes none =*| cat yes none
=* chgrp yes none =* chgrp yes none
=*| chmod yes none =*| chmod yes none

64
cal.1
View File

@ -1,4 +1,4 @@
.Dd January 18, 2015 .Dd March 8, 2015
.Dt CAL 1 .Dt CAL 1
.Os sbase .Os sbase
.Sh NAME .Sh NAME
@ -6,53 +6,55 @@
.Nd show calendar .Nd show calendar
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl 1 | Fl 3 | Fl y | Fl n Ar nmonths .Op Fl 1 | Fl 3 | Fl y | Fl n Ar num
.Op Fl s | Fl m | Fl f Ar firstday .Op Fl s | Fl m | Fl f Ar num
.Op Fl c Ar columns .Op Fl c Ar num
.Oo Oo Ar month Oc Ar year Oc .Oo Oo Ar month Oc Ar year Oc
.Sh DESCRIPTION .Sh DESCRIPTION
Print .Nm
.Ar nmonths writes a calendar of
calendars side by side beginning with
.Ar month .Ar month
and and
.Ar year . .Ar year
Each row of calendars contains at most or the current month to stdout.
.Ar columns
calendars. The date formatting is obtained using
.Xr localtime 3 .
.Pp
If If
.Ar year .Ar year
is given without is given without
.Ar month , .Ar month ,
print the whole year, unless overridden by other options. .Nm
writes a 3-column calendar of the whole
year to stdout.
The date formatting is according to
.Xr localtime 3 .
.Pp .Pp
The Julian calendar is used until Sep 2, 1752. The Gregorian calendar is used The Julian calendar is used until Sep 2, 1752. The Gregorian calendar is used
starting the next day on Sep 14, 1752. starting the next day on Sep 14, 1752.
.Sh OPTIONS .Sh OPTIONS
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl 1 .It Fl 1
Output current month. This is the default. Print current month. This is the default.
.It Fl 3 .It Fl 3
Output previous, current and next month. Print previous, current and next month.
.It Fl c Ar columns .It Fl c Ar num
Set number of calendars in a row. The default is 3. Print
.It Fl f Ar firstday .Ar num
Output calendars in a row. The default is 3.
.Ar firstday .It Fl f Ar num
Set
.Ar num
(0 is Sunday, 6 is Saturday) as first day of week. (0 is Sunday, 6 is Saturday) as first day of week.
.It Fl m .It Fl m
Output Monday as first day of week. Set Monday as first day of week.
.It Fl n Ar nmonths .It Fl n Ar num
Output in total Output
.Ar nmonths .Ar num
starting from the current month. months starting from and including the current month.
.It Fl s .It Fl s
Output Sunday as first day of week. Set Sunday as first day of week.
.It Fl y Ar year .It Fl y
Output an entire Print the entire
.Ar year . .Ar year
or current year.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr localtime 3 .Xr localtime 3
@ -64,5 +66,5 @@ utility is compliant with the
specification. specification.
.Pp .Pp
The flags The flags
.Op Fl 13ynsmfc .Op Fl 13cfmnsy
are an extension to that specification. are an extension to that specification.

61
cal.c
View File

@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <limits.h> #include <limits.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
@ -11,7 +12,7 @@ enum caltype { JULIAN, GREGORIAN };
enum { TRANS_YEAR = 1752, TRANS_MONTH = SEP, TRANS_DAY = 2 }; enum { TRANS_YEAR = 1752, TRANS_MONTH = SEP, TRANS_DAY = 2 };
static int static int
isleap(int year, enum caltype cal) isleap(size_t year, enum caltype cal)
{ {
if (cal == GREGORIAN) { if (cal == GREGORIAN) {
if (year % 400 == 0) if (year % 400 == 0)
@ -26,23 +27,23 @@ isleap(int year, enum caltype cal)
} }
static int static int
monthlength(int year, int month, enum caltype cal) monthlength(size_t year, int month, enum caltype cal)
{ {
int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
return (month == FEB && isleap(year,cal)) ? 29 : mdays[month]; return (month == FEB && isleap(year, cal)) ? 29 : mdays[month];
} }
/* From http://www.tondering.dk/claus/cal/chrweek.php#calcdow */ /* From http://www.tondering.dk/claus/cal/chrweek.php#calcdow */
static int static int
dayofweek(int year, int month, int dom, enum caltype cal) dayofweek(size_t year, int month, int dom, enum caltype cal)
{ {
int m, y, a; size_t y;
int m, a;
month += 1; /* in this formula, 1 <= month <= 12 */ a = (13 - month) / 12;
a = (14 - month) / 12;
y = year - a; y = year - a;
m = month + 12 * a - 2; m = month + 12 * a - 1;
if (cal == GREGORIAN) if (cal == GREGORIAN)
return (dom + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12) % 7; return (dom + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12) % 7;
@ -51,22 +52,19 @@ dayofweek(int year, int month, int dom, enum caltype cal)
} }
static void static void
printgrid(int year, int month, int fday, int line) printgrid(size_t year, int month, int fday, int line)
{ {
enum caltype cal; enum caltype cal;
int trans; /* are we in the transition from Julian to Gregorian? */ int offset, dom, d = 0, trans; /* are we in the transition from Julian to Gregorian? */
int offset, dom, d = 0;
if (year < TRANS_YEAR || (year == TRANS_YEAR && month <= TRANS_MONTH)) cal = (year < TRANS_YEAR || (year == TRANS_YEAR && month <= TRANS_MONTH)) ? JULIAN : GREGORIAN;
cal = JULIAN;
else
cal = GREGORIAN;
trans = (year == TRANS_YEAR && month == TRANS_MONTH); trans = (year == TRANS_YEAR && month == TRANS_MONTH);
offset = dayofweek(year, month, 1, cal) - fday; offset = dayofweek(year, month, 1, cal) - fday;
if (offset < 0) if (offset < 0)
offset += 7; offset += 7;
if (line == 1) { if (line == 1) {
for ( ; d < offset; ++d) for (; d < offset; ++d)
printf(" "); printf(" ");
dom = 1; dom = 1;
} else { } else {
@ -74,23 +72,24 @@ printgrid(int year, int month, int fday, int line)
if (trans && !(line == 2 && fday == 3)) if (trans && !(line == 2 && fday == 3))
dom += 11; dom += 11;
} }
for ( ; d < 7 && dom <= monthlength(year, month, cal); ++d, ++dom) { for (; d < 7 && dom <= monthlength(year, month, cal); ++d, ++dom) {
printf("%2d ", dom); printf("%2d ", dom);
if (trans && dom==TRANS_DAY) if (trans && dom == TRANS_DAY)
dom += 11; dom += 11;
} }
for ( ; d < 7; ++d) for (; d < 7; ++d)
printf(" "); printf(" ");
} }
static void static void
drawcal(int year, int month, int ncols, int nmons, int fday) drawcal(size_t year, int month, size_t ncols, size_t nmons, int fday)
{ {
char *smon[] = {" January", " February", " March", " April", char *smon[] = {" January", " February", " March", " April",
" May", " June", " July", " August", " May", " June", " July", " August",
"September", " October", " November", " December" }; "September", " October", " November", " December" };
char *days[] = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", }; char *days[] = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", };
int m, n, col, cur_year, cur_month, line, dow; size_t m, n, col, cur_year, cur_month, dow;
int line;
for (m = 0; m < nmons; ) { for (m = 0; m < nmons; ) {
n = m; n = m;
@ -101,16 +100,16 @@ drawcal(int year, int month, int ncols, int nmons, int fday)
cur_month -= 12; cur_month -= 12;
cur_year += 1; cur_year += 1;
} }
printf(" %s %d ", smon[cur_month], cur_year); printf(" %s %zu ", smon[cur_month], cur_year);
printf(" "); printf(" ");
} }
printf("\n"); putchar('\n');
for (col = 0, m = n; m < nmons && col < ncols; ++col, ++m) { for (col = 0, m = n; m < nmons && col < ncols; ++col, ++m) {
for (dow = fday; dow < (fday + 7); ++dow) for (dow = fday; dow < (fday + 7); ++dow)
printf("%s ", days[dow % 7]); printf("%s ", days[dow % 7]);
printf(" "); printf(" ");
} }
printf("\n"); putchar('\n');
for (line = 1; line <= 6; ++line) { for (line = 1; line <= 6; ++line) {
for (col = 0, m = n; m < nmons && col < ncols; ++col, ++m) { for (col = 0, m = n; m < nmons && col < ncols; ++col, ++m) {
cur_year = year + m / 12; cur_year = year + m / 12;
@ -122,7 +121,7 @@ drawcal(int year, int month, int ncols, int nmons, int fday)
printgrid(cur_year, cur_month, fday, line); printgrid(cur_year, cur_month, fday, line);
printf(" "); printf(" ");
} }
printf("\n"); putchar('\n');
} }
} }
} }
@ -130,16 +129,17 @@ drawcal(int year, int month, int ncols, int nmons, int fday)
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-1 | -3 | -y | -n nmonths] " eprintf("usage: %s [-1 | -3 | -y | -n num] "
"[-s | -m | -f firstday] [-c columns] [[month] year]\n", argv0); "[-s | -m | -f num] [-c num] [[month] year]\n", argv0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct tm *ltime; struct tm *ltime;
int year, ncols, nmons, month, fday;
time_t now; time_t now;
size_t year, ncols, nmons;
int fday, month;
now = time(NULL); now = time(NULL);
ltime = localtime(&now); ltime = localtime(&now);
@ -156,14 +156,13 @@ main(int argc, char *argv[])
break; break;
case '3': case '3':
nmons = 3; nmons = 3;
month -= 1; if (--month == 0) {
if (month == 0) {
month = 12; month = 12;
year--; year--;
} }
break; break;
case 'c': case 'c':
ncols = estrtonum(EARGF(usage()), 0, INT_MAX); ncols = estrtonum(EARGF(usage()), 0, MIN(SIZE_MAX, LLONG_MAX));
break; break;
case 'f': case 'f':
fday = estrtonum(EARGF(usage()), 0, 6); fday = estrtonum(EARGF(usage()), 0, 6);