diff options
author | Ron Yorston <rmy@pobox.com> | 2021-09-21 08:42:58 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-09-21 15:25:37 +0200 |
commit | 56f0e886db0543a27f369d7f95eb9da2fb3d069c (patch) | |
tree | 88d8e966becbb568b78c9448765ab9c5d32e13ed | |
parent | f27a6a94a7fb172a6768bc450dbdec68f15bc78f (diff) | |
download | busybox-w32-56f0e886db0543a27f369d7f95eb9da2fb3d069c.tar.gz busybox-w32-56f0e886db0543a27f369d7f95eb9da2fb3d069c.tar.bz2 busybox-w32-56f0e886db0543a27f369d7f95eb9da2fb3d069c.zip |
cal: implement -m
Some people prefer the week to start on Monday. Add the '-m'
option to support this.
function old new delta
cal_main 926 966 +40
day_array 316 337 +21
packed_usage 34151 34158 +7
.rodata 99224 99225 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 69/0) Total: 69 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | util-linux/cal.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/util-linux/cal.c b/util-linux/cal.c index 006bc817b..6ba6ebf98 100644 --- a/util-linux/cal.c +++ b/util-linux/cal.c | |||
@@ -27,10 +27,11 @@ | |||
27 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */ | 27 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */ |
28 | 28 | ||
29 | //usage:#define cal_trivial_usage | 29 | //usage:#define cal_trivial_usage |
30 | //usage: "[-jy] [[MONTH] YEAR]" | 30 | //usage: "[-jmy] [[MONTH] YEAR]" |
31 | //usage:#define cal_full_usage "\n\n" | 31 | //usage:#define cal_full_usage "\n\n" |
32 | //usage: "Display a calendar\n" | 32 | //usage: "Display a calendar\n" |
33 | //usage: "\n -j Use julian dates" | 33 | //usage: "\n -j Use julian dates" |
34 | //usage: "\n -m Week starts on Monday" | ||
34 | //usage: "\n -y Display the entire year" | 35 | //usage: "\n -y Display the entire year" |
35 | 36 | ||
36 | #include "libbb.h" | 37 | #include "libbb.h" |
@@ -38,6 +39,8 @@ | |||
38 | 39 | ||
39 | /* We often use "unsigned" instead of "int", it's easier to div on most CPUs */ | 40 | /* We often use "unsigned" instead of "int", it's easier to div on most CPUs */ |
40 | 41 | ||
42 | #define SUNDAY 0 | ||
43 | #define MONDAY 1 | ||
41 | #define THURSDAY 4 /* for reformation */ | 44 | #define THURSDAY 4 /* for reformation */ |
42 | #define SATURDAY 6 /* 1 Jan 1 was a Saturday */ | 45 | #define SATURDAY 6 /* 1 Jan 1 was a Saturday */ |
43 | 46 | ||
@@ -81,7 +84,7 @@ static int leap_year(unsigned yr) | |||
81 | ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) | 84 | ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) |
82 | 85 | ||
83 | static void center(char *, unsigned, unsigned); | 86 | static void center(char *, unsigned, unsigned); |
84 | static void day_array(unsigned, unsigned, unsigned *); | 87 | static void day_array(unsigned, unsigned, unsigned, unsigned *); |
85 | static void trim_trailing_spaces_and_print(char *); | 88 | static void trim_trailing_spaces_and_print(char *); |
86 | 89 | ||
87 | static void blank_string(char *buf, size_t buflen); | 90 | static void blank_string(char *buf, size_t buflen); |
@@ -93,12 +96,18 @@ static char *build_row(char *p, unsigned *dp); | |||
93 | #define J_WEEK_LEN (WEEK_LEN + 7) | 96 | #define J_WEEK_LEN (WEEK_LEN + 7) |
94 | #define HEAD_SEP 2 /* spaces between day headings */ | 97 | #define HEAD_SEP 2 /* spaces between day headings */ |
95 | 98 | ||
99 | enum { | ||
100 | OPT_JULIAN = (1 << 0), | ||
101 | OPT_MONDAY = (1 << 1), | ||
102 | OPT_YEAR = (1 << 2), | ||
103 | }; | ||
104 | |||
96 | int cal_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 105 | int cal_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
97 | int cal_main(int argc UNUSED_PARAM, char **argv) | 106 | int cal_main(int argc UNUSED_PARAM, char **argv) |
98 | { | 107 | { |
99 | struct tm zero_tm; | 108 | struct tm zero_tm; |
100 | time_t now; | 109 | time_t now; |
101 | unsigned month, year, flags, i; | 110 | unsigned month, year, flags, i, weekstart; |
102 | char *month_names[12]; | 111 | char *month_names[12]; |
103 | /* normal heading: */ | 112 | /* normal heading: */ |
104 | /* "Su Mo Tu We Th Fr Sa" */ | 113 | /* "Su Mo Tu We Th Fr Sa" */ |
@@ -110,10 +119,11 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
110 | 119 | ||
111 | init_unicode(); | 120 | init_unicode(); |
112 | 121 | ||
113 | flags = getopt32(argv, "jy"); | 122 | flags = getopt32(argv, "jmy"); |
114 | /* This sets julian = flags & 1: */ | 123 | /* This sets julian = flags & OPT_JULIAN: */ |
115 | option_mask32 &= 1; | 124 | option_mask32 &= OPT_JULIAN; |
116 | month = 0; | 125 | month = 0; |
126 | weekstart = (flags & OPT_MONDAY) ? MONDAY : SUNDAY; | ||
117 | argv += optind; | 127 | argv += optind; |
118 | 128 | ||
119 | if (!argv[0]) { | 129 | if (!argv[0]) { |
@@ -122,7 +132,7 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
122 | time(&now); | 132 | time(&now); |
123 | ptm = localtime(&now); | 133 | ptm = localtime(&now); |
124 | year = ptm->tm_year + 1900; | 134 | year = ptm->tm_year + 1900; |
125 | if (!(flags & 2)) { /* no -y */ | 135 | if (!(flags & OPT_YEAR)) { /* no -y */ |
126 | month = ptm->tm_mon + 1; | 136 | month = ptm->tm_mon + 1; |
127 | } | 137 | } |
128 | } else { | 138 | } else { |
@@ -130,7 +140,7 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
130 | if (argv[2]) { | 140 | if (argv[2]) { |
131 | bb_show_usage(); | 141 | bb_show_usage(); |
132 | } | 142 | } |
133 | if (!(flags & 2)) { /* no -y */ | 143 | if (!(flags & OPT_YEAR)) { /* no -y */ |
134 | month = xatou_range(*argv, 1, 12); | 144 | month = xatou_range(*argv, 1, 12); |
135 | } | 145 | } |
136 | argv++; | 146 | argv++; |
@@ -148,7 +158,7 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
148 | month_names[i] = xstrdup(buf); | 158 | month_names[i] = xstrdup(buf); |
149 | 159 | ||
150 | if (i < 7) { | 160 | if (i < 7) { |
151 | zero_tm.tm_wday = i; | 161 | zero_tm.tm_wday = (i + weekstart) % 7; |
152 | /* abbreviated weekday name according to locale */ | 162 | /* abbreviated weekday name according to locale */ |
153 | strftime(buf, sizeof(buf), "%a", &zero_tm); | 163 | strftime(buf, sizeof(buf), "%a", &zero_tm); |
154 | #if ENABLE_UNICODE_SUPPORT | 164 | #if ENABLE_UNICODE_SUPPORT |
@@ -173,7 +183,7 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
173 | unsigned *dp = days; | 183 | unsigned *dp = days; |
174 | char lineout[30]; | 184 | char lineout[30]; |
175 | 185 | ||
176 | day_array(month, year, dp); | 186 | day_array(month, year, weekstart, dp); |
177 | len = sprintf(lineout, "%s %u", month_names[month - 1], year); | 187 | len = sprintf(lineout, "%s %u", month_names[month - 1], year); |
178 | printf("%*s%s\n%s\n", | 188 | printf("%*s%s\n%s\n", |
179 | ((7*julian + WEEK_LEN) - len) / 2, "", | 189 | ((7*julian + WEEK_LEN) - len) / 2, "", |
@@ -197,7 +207,7 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
197 | ); | 207 | ); |
198 | puts("\n"); /* two \n's */ | 208 | puts("\n"); /* two \n's */ |
199 | for (i = 0; i < 12; i++) { | 209 | for (i = 0; i < 12; i++) { |
200 | day_array(i + 1, year, days[i]); | 210 | day_array(i + 1, year, weekstart, days[i]); |
201 | } | 211 | } |
202 | blank_string(lineout, sizeof(lineout)); | 212 | blank_string(lineout, sizeof(lineout)); |
203 | week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN); | 213 | week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN); |
@@ -233,7 +243,8 @@ int cal_main(int argc UNUSED_PARAM, char **argv) | |||
233 | * out end to end. You would have 42 numbers or spaces. This routine | 243 | * out end to end. You would have 42 numbers or spaces. This routine |
234 | * builds that array for any month from Jan. 1 through Dec. 9999. | 244 | * builds that array for any month from Jan. 1 through Dec. 9999. |
235 | */ | 245 | */ |
236 | static void day_array(unsigned month, unsigned year, unsigned *days) | 246 | static void day_array(unsigned month, unsigned year, unsigned weekstart, |
247 | unsigned *days) | ||
237 | { | 248 | { |
238 | unsigned long temp; | 249 | unsigned long temp; |
239 | unsigned i; | 250 | unsigned i; |
@@ -249,7 +260,7 @@ static void day_array(unsigned month, unsigned year, unsigned *days) | |||
249 | size_t oday = 0; | 260 | size_t oday = 0; |
250 | 261 | ||
251 | do { | 262 | do { |
252 | days[oday+2] = sep1752[oday] + j_offset; | 263 | days[oday+2-weekstart] = sep1752[oday] + j_offset; |
253 | } while (++oday < sizeof(sep1752)); | 264 | } while (++oday < sizeof(sep1752)); |
254 | 265 | ||
255 | return; | 266 | return; |
@@ -280,6 +291,7 @@ static void day_array(unsigned month, unsigned year, unsigned *days) | |||
280 | } else { | 291 | } else { |
281 | dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); | 292 | dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); |
282 | } | 293 | } |
294 | dw = (dw - weekstart + 7) % 7; | ||
283 | 295 | ||
284 | if (!julian) { | 296 | if (!julian) { |
285 | day = 1; | 297 | day = 1; |