]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/cal.c
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 /* This defines _LINUX_C_LIB_VERSION_MAJOR, dunno about gnulibc. We
38 don't want it to read /usr/i586-unknown-linux/include/_G_config.h
39 so we specify fill path. Were we got /usr/i586-unknown-linux from?
42 #include "/usr/include/_G_config.h"
44 #include <sys/types.h>
55 /* Test changes to deal with gnulibc, Linux libc 5. */
56 /* #if defined(__linux__) && _LINUX_C_LIB_VERSION_MAJOR > 4 */
57 #if _LINUX_C_LIB_VERSION_MAJOR - 0 > 4 || __GNU_LIBRARY__ - 0 >= 5
64 # include <langinfo.h>
66 # include <localeinfo.h>
69 #define THURSDAY 4 /* for reformation */
70 #define SATURDAY 6 /* 1 Jan 1 was a Saturday */
72 #define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */
73 #define NUMBER_MISSING_DAYS 11 /* 11 day correction */
75 #define MAXDAYS 42 /* max slots in a month array */
76 #define SPACE -1 /* used in day array */
78 static int days_in_month
[2][13] = {
79 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
80 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
83 int sep1752
[MAXDAYS
] = {
84 SPACE
, SPACE
, 1, 2, 14, 15, 16,
85 17, 18, 19, 20, 21, 22, 23,
86 24, 25, 26, 27, 28, 29, 30,
87 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
88 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
89 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
90 }, j_sep1752
[MAXDAYS
] = {
91 SPACE
, SPACE
, 245, 246, 258, 259, 260,
92 261, 262, 263, 264, 265, 266, 267,
93 268, 269, 270, 271, 272, 273, 274,
94 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
95 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
96 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
98 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
99 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
100 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
101 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
102 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
103 SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
, SPACE
,
106 char day_headings
[] = " S M Tu W Th F S ";
107 char j_day_headings
[] = " S M Tu W Th F S ";
108 const char *full_month
[12];
110 /* leap year -- account for gregorian reformation in 1752 */
111 #define leap_year(yr) \
112 ((yr) <= 1752 ? !((yr) % 4) : \
113 (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
115 /* number of centuries since 1700, not inclusive */
116 #define centuries_since_1700(yr) \
117 ((yr) > 1700 ? (yr) / 100 - 17 : 0)
119 /* number of centuries since 1700 whose modulo of 400 is 0 */
120 #define quad_centuries_since_1700(yr) \
121 ((yr) > 1600 ? ((yr) - 1600) / 400 : 0)
123 /* number of leap years between year 1 and this year, not inclusive */
124 #define leap_years_since_year_1(yr) \
125 ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
129 void ascii_day
__P((char *, int));
130 void center
__P((const char *, int, int));
131 void day_array
__P((int, int, int *));
132 int day_in_week
__P((int, int, int));
133 int day_in_year
__P((int, int, int));
134 void j_yearly
__P((int));
135 void monthly
__P((int, int));
136 void trim_trailing_spaces
__P((char *));
137 void usage
__P((void));
138 void yearly
__P((int));
139 void headers_init(void);
146 struct tm
*local_time
;
148 int ch
, month
, year
, yflag
;
151 extern char *__progname
;
152 __progname
= argv
[0];
155 setlocale(LC_ALL
,"");
158 while ((ch
= getopt(argc
, argv
, "jy")) != EOF
)
176 if ((month
= atoi(*argv
++)) < 1 || month
> 12)
177 errx(1, "illegal month value: use 1-12");
180 if ((year
= atoi(*argv
)) < 1 || year
> 9999)
181 errx(1, "illegal year value: use 1-9999");
185 local_time
= localtime(&now
);
186 year
= local_time
->tm_year
+ 1900;
188 month
= local_time
->tm_mon
+ 1;
195 monthly(month
, year
);
203 #define DAY_LEN 3 /* 3 spaces per day */
204 #define J_DAY_LEN 4 /* 4 spaces per day */
205 #define WEEK_LEN 21 /* 7 days * 3 characters */
206 #define J_WEEK_LEN 28 /* 7 days * 4 characters */
207 #define HEAD_SEP 2 /* spaces between day headings */
210 void headers_init(void)
214 strcpy(day_headings
,"");
215 strcpy(j_day_headings
,"");
217 for(i
= 0 ; i
< 7 ; i
++ ) {
218 #if defined(__linux__) && (_LINUX_C_LIB_VERSION_MAJOR > 4 || __GNU_LIBRARY__ > 1)
219 strncat(day_headings
,nl_langinfo(ABDAY_1
+i
),2);
220 strcat(j_day_headings
,nl_langinfo(ABDAY_1
+i
));
222 strncat(day_headings
,_time_info
->abbrev_wkday
[i
],2);
223 strcat(j_day_headings
,_time_info
->abbrev_wkday
[i
]);
225 strcat(day_headings
," ");
226 strcat(j_day_headings
," ");
229 for (i
= 0; i
< 12; i
++) {
230 #if defined(__linux__) && (_LINUX_C_LIB_VERSION_MAJOR > 4 || __GNU_LIBRARY__ > 1)
231 full_month
[i
] = nl_langinfo(MON_1
+i
);
233 full_month
[i
] = _time_info
->full_month
[i
];
242 int col
, row
, len
, days
[MAXDAYS
];
243 char *p
, lineout
[30];
245 day_array(month
, year
, days
);
246 len
= sprintf(lineout
, "%s %d", full_month
[month
- 1], year
);
247 (void)printf("%*s%s\n%s\n",
248 ((julian
? J_WEEK_LEN
: WEEK_LEN
) - len
) / 2, "",
249 lineout
, julian
? j_day_headings
: day_headings
);
250 for (row
= 0; row
< 6; row
++) {
251 for (col
= 0, p
= lineout
; col
< 7; col
++,
252 p
+= julian
? J_DAY_LEN
: DAY_LEN
)
253 ascii_day(p
, days
[row
* 7 + col
]);
255 trim_trailing_spaces(lineout
);
256 (void)printf("%s\n", lineout
);
264 int col
, *dp
, i
, month
, row
, which_cal
;
265 int days
[12][MAXDAYS
];
266 char *p
, lineout
[80];
268 (void)sprintf(lineout
, "%d", year
);
269 center(lineout
, J_WEEK_LEN
* 2 + J_HEAD_SEP
, 0);
270 (void)printf("\n\n");
271 for (i
= 0; i
< 12; i
++)
272 day_array(i
+ 1, year
, days
[i
]);
273 (void)memset(lineout
, ' ', sizeof(lineout
) - 1);
274 lineout
[sizeof(lineout
) - 1] = '\0';
275 for (month
= 0; month
< 12; month
+= 2) {
276 center(full_month
[month
], J_WEEK_LEN
, J_HEAD_SEP
);
277 center(full_month
[month
+ 1], J_WEEK_LEN
, 0);
278 (void)printf("\n%s%*s%s\n", j_day_headings
, J_HEAD_SEP
, "",
280 for (row
= 0; row
< 6; row
++) {
281 for (which_cal
= 0; which_cal
< 2; which_cal
++) {
282 p
= lineout
+ which_cal
* (J_WEEK_LEN
+ 2);
283 dp
= &days
[month
+ which_cal
][row
* 7];
284 for (col
= 0; col
< 7; col
++, p
+= J_DAY_LEN
)
288 trim_trailing_spaces(lineout
);
289 (void)printf("%s\n", lineout
);
299 int col
, *dp
, i
, month
, row
, which_cal
;
300 int days
[12][MAXDAYS
];
301 char *p
, lineout
[80];
303 (void)sprintf(lineout
, "%d", year
);
304 center(lineout
, WEEK_LEN
* 3 + HEAD_SEP
* 2, 0);
305 (void)printf("\n\n");
306 for (i
= 0; i
< 12; i
++)
307 day_array(i
+ 1, year
, days
[i
]);
308 (void)memset(lineout
, ' ', sizeof(lineout
) - 1);
309 lineout
[sizeof(lineout
) - 1] = '\0';
310 for (month
= 0; month
< 12; month
+= 3) {
311 center(full_month
[month
], WEEK_LEN
, HEAD_SEP
);
312 center(full_month
[month
+ 1], WEEK_LEN
, HEAD_SEP
);
313 center(full_month
[month
+ 2], WEEK_LEN
, 0);
314 (void)printf("\n%s%*s%s%*s%s\n", day_headings
, HEAD_SEP
,
315 "", day_headings
, HEAD_SEP
, "", day_headings
);
316 for (row
= 0; row
< 6; row
++) {
317 for (which_cal
= 0; which_cal
< 3; which_cal
++) {
318 p
= lineout
+ which_cal
* (WEEK_LEN
+ 2);
319 dp
= &days
[month
+ which_cal
][row
* 7];
320 for (col
= 0; col
< 7; col
++, p
+= DAY_LEN
)
324 trim_trailing_spaces(lineout
);
325 (void)printf("%s\n", lineout
);
333 * Fill in an array of 42 integers with a calendar. Assume for a moment
334 * that you took the (maximum) 6 rows in a calendar and stretched them
335 * out end to end. You would have 42 numbers or spaces. This routine
336 * builds that array for any month from Jan. 1 through Dec. 9999.
339 day_array(month
, year
, days
)
345 if (month
== 9 && year
== 1752) {
347 julian
? j_sep1752
: sep1752
, MAXDAYS
* sizeof(int));
350 memmove(days
, empty
, MAXDAYS
* sizeof(int));
351 dm
= days_in_month
[leap_year(year
)][month
];
352 dw
= day_in_week(1, month
, year
);
353 day
= julian
? day_in_year(1, month
, year
) : 1;
360 * return the 1 based day number within the year
363 day_in_year(day
, month
, year
)
364 int day
, month
, year
;
368 leap
= leap_year(year
);
369 for (i
= 1; i
< month
; i
++)
370 day
+= days_in_month
[leap
][i
];
376 * return the 0 based day number for any date from 1 Jan. 1 to
377 * 31 Dec. 9999. Assumes the Gregorian reformation eliminates
378 * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
382 day_in_week(day
, month
, year
)
383 int day
, month
, year
;
387 temp
= (long)(year
- 1) * 365 + leap_years_since_year_1(year
- 1)
388 + day_in_year(day
, month
, year
);
389 if (temp
< FIRST_MISSING_DAY
)
390 return ((temp
- 1 + SATURDAY
) % 7);
391 if (temp
>= (FIRST_MISSING_DAY
+ NUMBER_MISSING_DAYS
))
392 return (((temp
- 1 + SATURDAY
) - NUMBER_MISSING_DAYS
) % 7);
402 static char *aday
[] = {
404 " 1", " 2", " 3", " 4", " 5", " 6", " 7",
405 " 8", " 9", "10", "11", "12", "13", "14",
406 "15", "16", "17", "18", "19", "20", "21",
407 "22", "23", "24", "25", "26", "27", "28",
412 memset(p
, ' ', julian
? J_DAY_LEN
: DAY_LEN
);
416 if ((val
= day
/ 100)) {
429 *p
++ = day
% 10 + '0';
438 trim_trailing_spaces(s
)
445 while (p
> s
&& isspace(*--p
))
453 center(str
, len
, separate
)
460 (void)printf("%*s%s%*s", len
/ 2, "", str
, len
/ 2 + len
% 2, "");
462 (void)printf("%*s", separate
, "");
469 (void)fprintf(stderr
, "usage: cal [-jy] [[month] year]\n");