summaryrefslogtreecommitdiffstats
path: root/misc-utils
diff options
context:
space:
mode:
authorSami Kerola2013-11-10 19:23:35 +0100
committerKarel Zak2013-12-06 10:58:54 +0100
commitffc563579853d7d6c316d63d090b4a1845d65b83 (patch)
tree85b2a2bb163dba459e2e69c50eecfaf298a1e5ca /misc-utils
parenttests: cal: take account week numbers when determing month lenght (diff)
downloadkernel-qcow2-util-linux-ffc563579853d7d6c316d63d090b4a1845d65b83.tar.gz
kernel-qcow2-util-linux-ffc563579853d7d6c316d63d090b4a1845d65b83.tar.xz
kernel-qcow2-util-linux-ffc563579853d7d6c316d63d090b4a1845d65b83.zip
cal: make user request to be part of read-only control struct
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'misc-utils')
-rw-r--r--misc-utils/cal.c138
1 files changed, 73 insertions, 65 deletions
diff --git a/misc-utils/cal.c b/misc-utils/cal.c
index bc53d4f8a..185b7a91b 100644
--- a/misc-utils/cal.c
+++ b/misc-utils/cal.c
@@ -230,15 +230,22 @@ enum {
/* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */
static char day_headings[(WEEK_LEN + 1) * 6 + 1];
+struct cal_request {
+ int day;
+ int month;
+ long year;
+ int week;
+};
+
struct cal_control {
const char *full_month[MONTHS_IN_YEAR]; /* month names */
int colormode; /* day and week number highlight */
int num_months; /* number of months horizontally in print out */
int weekstart; /* day the week starts, often Sun or Mon */
int weektype; /* WEEK_TYPE_{NONE,ISO,US} */
- int weeknum; /* requested --week=<number> */
size_t day_width; /* day width in characters in printout */
size_t week_width; /* 7 * day_width + possible week num */
+ struct cal_request req; /* the times user is interested */
unsigned int julian:1, /* julian output */
yflag:1; /* print whole year */
};
@@ -248,17 +255,17 @@ static int leap_year(long year);
static void headers_init(struct cal_control *ctl);
static int do_monthly(int day, int month, long year, struct fmt_st *out, int header_hint,
const struct cal_control *ctl);
-static void monthly(int day, int month, long year, const struct cal_control *ctl);
+static void monthly(const struct cal_control *ctl);
static int two_header_lines(int month, long year, const struct cal_control *ctl);
-static void monthly3(int day, int month, long year, const struct cal_control *ctl);
+static void monthly3(const struct cal_control *ctl);
static char *append_weeknum(char *p, int *dp, int month, long year, int cal, int row,
const struct cal_control *ctl);
-static void yearly(int day, long year, const struct cal_control *ctl);
+static void yearly(const struct cal_control *ctl);
static void day_array(int day, int month, long year, int *days, const struct cal_control *ctl);
static int day_in_year(int day, int month, long year);
static int day_in_week(int day, int month, long year);
static int week_number(int day, int month, long year, const struct cal_control *ctl);
-static int week_to_day(long year, const struct cal_control *ctl);
+static int week_to_day(const struct cal_control *ctl);
static char *ascii_day(char *p, int day, const struct cal_control *ctl);
static char *ascii_weeknum(char *p, int weeknum, const struct cal_control *ctl);
static int center_str(const char *src, char *dest, size_t dest_size, size_t width);
@@ -269,14 +276,15 @@ int main(int argc, char **argv)
{
struct tm *local_time;
time_t now;
- int ch, day = 0, month = 0;
- long year;
+ int ch;
static struct cal_control ctl = {
.weekstart = SUNDAY,
.num_months = NUM_MONTHS,
.colormode = UL_COLORMODE_AUTO,
.weektype = WEEK_NUM_DISABLED,
- .day_width = DAY_LEN
+ .day_width = DAY_LEN,
+ .req.day = 0,
+ .req.month = 0
};
enum {
@@ -372,9 +380,9 @@ int main(int argc, char **argv)
break;
case 'w':
if (optarg) {
- ctl.weeknum = strtos32_or_err(optarg,
+ ctl.req.week = strtos32_or_err(optarg,
_("invalid week argument"));
- if (ctl.weeknum < 1 || 53 < ctl.weeknum)
+ if (ctl.req.week < 1 || 53 < ctl.req.week)
errx(EXIT_FAILURE,_("illegal week value: use 1-53"));
}
ctl.weektype = WEEK_NUM_US; /* default per weekstart */
@@ -397,7 +405,7 @@ int main(int argc, char **argv)
argv += optind;
if (ctl.weektype) {
- ctl.weektype = ctl.weeknum & WEEK_NUM_MASK;
+ ctl.weektype = ctl.req.week & WEEK_NUM_MASK;
ctl.weektype |= (ctl.weekstart == MONDAY ? WEEK_NUM_ISO : WEEK_NUM_US);
ctl.week_width = (ctl.day_width * DAYS_IN_WEEK) + WNUM_LEN;
} else
@@ -408,70 +416,70 @@ int main(int argc, char **argv)
switch(argc) {
case 3:
- day = strtos32_or_err(*argv++, _("illegal day value"));
- if (day < 1 || DAYS_IN_MONTH < day)
+ ctl.req.day = strtos32_or_err(*argv++, _("illegal day value"));
+ if (ctl.req.day < 1 || DAYS_IN_MONTH < ctl.req.day)
errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), DAYS_IN_MONTH);
/* FALLTHROUGH */
case 2:
- month = strtos32_or_err(*argv++, _("illegal month value: use 1-12"));
- if (month < 1 || MONTHS_IN_YEAR < month)
+ ctl.req.month = strtos32_or_err(*argv++, _("illegal month value: use 1-12"));
+ if (ctl.req.month < 1 || MONTHS_IN_YEAR < ctl.req.month)
errx(EXIT_FAILURE, _("illegal month value: use 1-12"));
/* FALLTHROUGH */
case 1:
- year = strtol_or_err(*argv++, _("illegal year value"));
- if (year < SMALLEST_YEAR)
+ ctl.req.year = strtol_or_err(*argv++, _("illegal year value"));
+ if (ctl.req.year < SMALLEST_YEAR)
errx(EXIT_FAILURE, _("illegal year value: use positive integer"));
- if (day) {
- int dm = days_in_month[leap_year(year)][month];
- if (day > dm)
+ if (ctl.req.day) {
+ int dm = days_in_month[leap_year(ctl.req.year)][ctl.req.month];
+ if (ctl.req.day > dm)
errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), dm);
- day = day_in_year(day, month, year);
- } else if ((long) (local_time->tm_year + 1900) == year) {
- day = local_time->tm_yday + 1;
+ ctl.req.day = day_in_year(ctl.req.day, ctl.req.month, ctl.req.year);
+ } else if ((long) (local_time->tm_year + 1900) == ctl.req.year) {
+ ctl.req.day = local_time->tm_yday + 1;
}
- if (!month && !ctl.weeknum)
+ if (!ctl.req.month && !ctl.req.week)
ctl.yflag = 1;
break;
case 0:
- day = local_time->tm_yday + 1;
- year = local_time->tm_year + 1900;
- month = local_time->tm_mon + 1;
+ ctl.req.day = local_time->tm_yday + 1;
+ ctl.req.year = local_time->tm_year + 1900;
+ ctl.req.month = local_time->tm_mon + 1;
break;
default:
usage(stderr);
}
- if (0 < ctl.weeknum) {
- int yday = week_to_day(year, &ctl);
- int leap = leap_year(year);
+ if (0 < ctl.req.week) {
+ int yday = week_to_day(&ctl);
+ int leap = leap_year(ctl.req.year);
+ int m = 1;
if (yday < 1)
errx(EXIT_FAILURE, _("illegal week value: year %ld "
"doesn't have week %d"),
- year, ctl.weeknum);
- month = 1;
- while (month <= 12 && yday > days_in_month[leap][month])
- yday -= days_in_month[leap][month++];
- if (month > 12) {
+ ctl.req.year, ctl.req.week);
+ while (m <= 12 && yday > days_in_month[leap][m])
+ yday -= days_in_month[leap][m++];
+ if (m > 12) {
/* In some years (e.g. 2010 in ISO mode) it's possible
* to have a remnant of week 53 starting the year yet
* the year in question ends during 52, in this case
* we're assuming that early remnant is being referred
* to if 53 is given as argument. */
- if (ctl.weeknum == week_number(31, 12, year - 1, &ctl))
- month = 1;
- else
+ if (ctl.req.week != week_number(31, 12, ctl.req.year - 1, &ctl))
errx(EXIT_FAILURE,
_("illegal week value: year %ld "
"doesn't have week %d"),
- year, ctl.weeknum);
+ ctl.req.year, ctl.req.week);
}
+ if (!ctl.req.month)
+ ctl.req.month = 12 < m ? 1 : m;
}
headers_init(&ctl);
if (!colors_init(ctl.colormode)) {
- day = 0;
+ ctl.req.day = 0;
ctl.weektype &= ~WEEK_NUM_MASK;
}
@@ -480,11 +488,11 @@ int main(int argc, char **argv)
ctl.num_months = MONTH_COLS - 1;
else
ctl.num_months = MONTH_COLS;
- yearly(day, year, &ctl);
+ yearly(&ctl);
} else if (ctl.num_months == 1)
- monthly(day, month, year, &ctl);
+ monthly(&ctl);
else if (ctl.num_months == 3)
- monthly3(day, month, year, &ctl);
+ monthly3(&ctl);
return EXIT_SUCCESS;
}
@@ -583,12 +591,12 @@ static int do_monthly(int day, int month, long year, struct fmt_st *out,
return pos;
}
-static void monthly(int day, int month, long year, const struct cal_control *ctl)
+static void monthly(const struct cal_control *ctl)
{
int i, rows;
struct fmt_st out;
- rows = do_monthly(day, month, year, &out, -1, ctl);
+ rows = do_monthly(ctl->req.day, ctl->req.month, ctl->req.year, &out, -1, ctl);
for (i = 0; i < rows; i++) {
my_putstring(out.s[i]);
my_putstring("\n");
@@ -607,7 +615,7 @@ static int two_header_lines(int month, long year, const struct cal_control *ctl)
return 0;
}
-static void monthly3(int day, int month, long year, const struct cal_control *ctl)
+static void monthly3(const struct cal_control *ctl)
{
char lineout[FMT_ST_CHARS];
int i;
@@ -621,30 +629,30 @@ static void monthly3(int day, int month, long year, const struct cal_control *ct
memset(&out_prev, 0, sizeof(struct fmt_st));
memset(&out_curm, 0, sizeof(struct fmt_st));
memset(&out_next, 0, sizeof(struct fmt_st));
- if (month == 1) {
+ if (ctl->req.month == 1) {
prev_month = MONTHS_IN_YEAR;
- prev_year = year - 1;
+ prev_year = ctl->req.year - 1;
} else {
- prev_month = month - 1;
- prev_year = year;
+ prev_month = ctl->req.month - 1;
+ prev_year = ctl->req.year;
}
- if (month == MONTHS_IN_YEAR) {
+ if (ctl->req.month == MONTHS_IN_YEAR) {
next_month = 1;
- next_year = year + 1;
+ next_year = ctl->req.year + 1;
} else {
- next_month = month + 1;
- next_year = year;
+ next_month = ctl->req.month + 1;
+ next_year = ctl->req.year;
}
two_lines = two_header_lines(prev_month, prev_year, ctl);
- two_lines += two_header_lines(month, year, ctl);
+ two_lines += two_header_lines(ctl->req.month, ctl->req.year, ctl);
two_lines += two_header_lines(next_month, next_year, ctl);
if (0 < two_lines)
rows = FMT_ST_LINES;
else
rows = FMT_ST_LINES - 1;
- do_monthly(day, prev_month, prev_year, &out_prev, two_lines, ctl);
- do_monthly(day, month, year, &out_curm, two_lines, ctl);
- do_monthly(day, next_month, next_year, &out_next, two_lines, ctl);
+ do_monthly(ctl->req.day, prev_month, prev_year, &out_prev, two_lines, ctl);
+ do_monthly(ctl->req.day, ctl->req.month, ctl->req.year, &out_curm, two_lines, ctl);
+ do_monthly(ctl->req.day, next_month, next_year, &out_next, two_lines, ctl);
for (i = 0; i < (two_lines ? 3 : 2); i++) {
snprintf(lineout, sizeof(lineout),
@@ -690,7 +698,7 @@ static char *append_weeknum(char *p, int *dp,
return p;
}
-static void yearly(int day, long year, const struct cal_control *ctl)
+static void yearly(const struct cal_control *ctl)
{
int col, i, month, row, which_cal;
int days[MONTHS_IN_YEAR][MAXDAYS];
@@ -701,7 +709,7 @@ static void yearly(int day, long year, const struct cal_control *ctl)
weeknumlen + sizeof(day_headings) + 2 +
weeknumlen + sizeof(day_headings) + 1 ];
- snprintf(lineout, sizeof(lineout), "%ld", year);
+ snprintf(lineout, sizeof(lineout), "%ld", ctl->req.year);
/* 2013-04-28: The -1 near HEAD_SEP makes year header to be aligned
* exactly how it has been aligned for long time, but it is
@@ -710,7 +718,7 @@ static void yearly(int day, long year, const struct cal_control *ctl)
my_putstring("\n\n");
for (i = 0; i < MONTHS_IN_YEAR; i++)
- day_array(day, i + 1, year, days[i], ctl);
+ day_array(ctl->req.day, i + 1, ctl->req.year, days[i], ctl);
for (month = 0; month < MONTHS_IN_YEAR; month += ctl->num_months) {
center(ctl->full_month[month], ctl->week_width - 1, HEAD_SEP + 1);
@@ -740,7 +748,7 @@ static void yearly(int day, long year, const struct cal_control *ctl)
if (ctl->weektype)
p = append_weeknum(p, days[month + which_cal],
- month, year, which_cal,
+ month, ctl->req.year, which_cal,
row, ctl);
for (col = 0; col < DAYS_IN_WEEK; col++)
@@ -894,12 +902,12 @@ static int week_number(int day, int month, long year, const struct cal_control *
* for ISO-8601 modes. For North American numbering this
* always returns a Sunday.
*/
-static int week_to_day(long year, const struct cal_control *ctl)
+static int week_to_day(const struct cal_control *ctl)
{
int yday, wday;
- wday = day_in_week(1, 1, year);
- yday = ctl->weeknum * 7 - wday;
+ wday = day_in_week(1, 1, ctl->req.year);
+ yday = ctl->req.week * 7 - wday;
if (ctl->weektype & WEEK_NUM_ISO)
yday -= (wday >= FRIDAY ? -2 : 5);