Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
5 char dayw[] =
6 {
7 " S M Tu W Th F S"
8 };
9 char *smon[] =
10 {
11 "January", "February", "March", "April",
12 "May", "June", "July", "August",
13 "September", "October", "November", "December",
14 };
15 char mon[] =
16 {
17 0,
18 31, 29, 31, 30,
19 31, 30, 31, 31,
20 30, 31, 30, 31,
21 };
22 char string[432];
23 Biobuf bout;
25 void main(int argc, char *argv[]);
26 int number(char *str);
27 void pstr(char *str, int n);
28 void cal(int m, int y, char *p, int w);
29 int jan1(int yr);
30 int curmo(void);
31 int curyr(void);
33 void
34 main(int argc, char *argv[])
35 {
36 int y, i, j, m;
38 if(argc > 3) {
39 fprint(2, "usage: cal [month] [year]\n");
40 exits("usage");
41 }
42 Binit(&bout, 1, OWRITE);
44 /*
45 * no arg, print current month
46 */
47 if(argc == 1) {
48 m = curmo();
49 y = curyr();
50 goto xshort;
51 }
53 /*
54 * one arg
55 * if looks like a month, print month
56 * else print year
57 */
58 if(argc == 2) {
59 y = number(argv[1]);
60 if(y < 0)
61 y = -y;
62 if(y >= 1 && y <= 12) {
63 m = y;
64 y = curyr();
65 goto xshort;
66 }
67 goto xlong;
68 }
70 /*
71 * two arg, month and year
72 */
73 m = number(argv[1]);
74 if(m < 0)
75 m = -m;
76 y = number(argv[2]);
77 goto xshort;
79 /*
80 * print out just month
81 */
82 xshort:
83 if(m < 1 || m > 12)
84 goto badarg;
85 if(y < 1 || y > 9999)
86 goto badarg;
87 Bprint(&bout, " %s %ud\n", smon[m-1], y);
88 Bprint(&bout, "%s\n", dayw);
89 cal(m, y, string, 24);
90 for(i=0; i<6*24; i+=24)
91 pstr(string+i, 24);
92 exits(0);
94 /*
95 * print out complete year
96 */
97 xlong:
98 y = number(argv[1]);
99 if(y<1 || y>9999)
100 goto badarg;
101 Bprint(&bout, "\n\n\n");
102 Bprint(&bout, " %ud\n", y);
103 Bprint(&bout, "\n");
104 for(i=0; i<12; i+=3) {
105 for(j=0; j<6*72; j++)
106 string[j] = '\0';
107 Bprint(&bout, " %.3s", smon[i]);
108 Bprint(&bout, " %.3s", smon[i+1]);
109 Bprint(&bout, " %.3s\n", smon[i+2]);
110 Bprint(&bout, "%s %s %s\n", dayw, dayw, dayw);
111 cal(i+1, y, string, 72);
112 cal(i+2, y, string+23, 72);
113 cal(i+3, y, string+46, 72);
114 for(j=0; j<6*72; j+=72)
115 pstr(string+j, 72);
117 Bprint(&bout, "\n\n\n");
118 exits(0);
120 badarg:
121 Bprint(&bout, "cal: bad argument\n");
124 struct
126 char* word;
127 int val;
128 } dict[] =
130 "jan", 1,
131 "january", 1,
132 "feb", 2,
133 "february", 2,
134 "mar", 3,
135 "march", 3,
136 "apr", 4,
137 "april", 4,
138 "may", 5,
139 "jun", 6,
140 "june", 6,
141 "jul", 7,
142 "july", 7,
143 "aug", 8,
144 "august", 8,
145 "sep", 9,
146 "sept", 9,
147 "september", 9,
148 "oct", 10,
149 "october", 10,
150 "nov", 11,
151 "november", 11,
152 "dec", 12,
153 "december", 12,
155 };
157 /*
158 * convert to a number.
159 * if its a dictionary word,
160 * return negative number
161 */
162 int
163 number(char *str)
165 int n, c;
166 char *s;
168 for(n=0; s=dict[n].word; n++)
169 if(strcmp(s, str) == 0)
170 return -dict[n].val;
171 n = 0;
172 s = str;
173 while(c = *s++) {
174 if(c<'0' || c>'9')
175 return 0;
176 n = n*10 + c-'0';
178 return n;
181 void
182 pstr(char *str, int n)
184 int i;
185 char *s;
187 s = str;
188 i = n;
189 while(i--)
190 if(*s++ == '\0')
191 s[-1] = ' ';
192 i = n+1;
193 while(i--)
194 if(*--s != ' ')
195 break;
196 s[1] = '\0';
197 Bprint(&bout, "%s\n", str);
200 void
201 cal(int m, int y, char *p, int w)
203 int d, i;
204 char *s;
206 s = p;
207 d = jan1(y);
208 mon[2] = 29;
209 mon[9] = 30;
211 switch((jan1(y+1)+7-d)%7) {
213 /*
214 * non-leap year
215 */
216 case 1:
217 mon[2] = 28;
218 break;
220 /*
221 * 1752
222 */
223 default:
224 mon[9] = 19;
225 break;
227 /*
228 * leap year
229 */
230 case 2:
233 for(i=1; i<m; i++)
234 d += mon[i];
235 d %= 7;
236 s += 3*d;
237 for(i=1; i<=mon[m]; i++) {
238 if(i==3 && mon[m]==19) {
239 i += 11;
240 mon[m] += 11;
242 if(i > 9)
243 *s = i/10+'0';
244 s++;
245 *s++ = i%10+'0';
246 s++;
247 if(++d == 7) {
248 d = 0;
249 s = p+w;
250 p = s;
255 /*
256 * return day of the week
257 * of jan 1 of given year
258 */
259 int
260 jan1(int yr)
262 int y, d;
264 /*
265 * normal gregorian calendar
266 * one extra day per four years
267 */
269 y = yr;
270 d = 4+y+(y+3)/4;
272 /*
273 * julian calendar
274 * regular gregorian
275 * less three days per 400
276 */
278 if(y > 1800) {
279 d -= (y-1701)/100;
280 d += (y-1601)/400;
283 /*
284 * great calendar changeover instant
285 */
287 if(y > 1752)
288 d += 3;
290 return d%7;
293 /*
294 * system dependent
295 * get current month and year
296 */
297 int
298 curmo(void)
300 Tm *tm;
302 tm = localtime(time(0));
303 return tm->mon+1;
306 int
307 curyr(void)
309 Tm *tm;
311 tm = localtime(time(0));
312 return tm->year+1900;