cal.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
cal.c (4204B) | |
--- | |
1 #include <u.h> | |
2 #include <libc.h> | |
3 #include <bio.h> | |
4 | |
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; | |
24 | |
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); | |
32 | |
33 void | |
34 main(int argc, char *argv[]) | |
35 { | |
36 int y, i, j, m; | |
37 | |
38 if(argc > 3) { | |
39 fprint(2, "usage: cal [month] [year]\n"); | |
40 exits("usage"); | |
41 } | |
42 Binit(&bout, 1, OWRITE); | |
43 | |
44 /* | |
45 * no arg, print current month | |
46 */ | |
47 if(argc == 1) { | |
48 m = curmo(); | |
49 y = curyr(); | |
50 goto xshort; | |
51 } | |
52 | |
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 } | |
69 | |
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; | |
78 | |
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 %d\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); | |
93 | |
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, " %d\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); | |
116 } | |
117 Bprint(&bout, "\n\n\n"); | |
118 exits(0); | |
119 | |
120 badarg: | |
121 Bprint(&bout, "cal: bad argument\n"); | |
122 } | |
123 | |
124 struct | |
125 { | |
126 char* word; | |
127 int val; | |
128 } dict[] = | |
129 { | |
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, | |
154 0 | |
155 }; | |
156 | |
157 /* | |
158 * convert to a number. | |
159 * if its a dictionary word, | |
160 * return negative number | |
161 */ | |
162 int | |
163 number(char *str) | |
164 { | |
165 int n, c; | |
166 char *s; | |
167 | |
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'; | |
177 } | |
178 return n; | |
179 } | |
180 | |
181 void | |
182 pstr(char *str, int n) | |
183 { | |
184 int i; | |
185 char *s; | |
186 | |
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); | |
198 } | |
199 | |
200 void | |
201 cal(int m, int y, char *p, int w) | |
202 { | |
203 int d, i; | |
204 char *s; | |
205 | |
206 s = p; | |
207 d = jan1(y); | |
208 mon[2] = 29; | |
209 mon[9] = 30; | |
210 | |
211 switch((jan1(y+1)+7-d)%7) { | |
212 | |
213 /* | |
214 * non-leap year | |
215 */ | |
216 case 1: | |
217 mon[2] = 28; | |
218 break; | |
219 | |
220 /* | |
221 * 1752 | |
222 */ | |
223 default: | |
224 mon[9] = 19; | |
225 break; | |
226 | |
227 /* | |
228 * leap year | |
229 */ | |
230 case 2: | |
231 ; | |
232 } | |
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; | |
241 } | |
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; | |
251 } | |
252 } | |
253 } | |
254 | |
255 /* | |
256 * return day of the week | |
257 * of jan 1 of given year | |
258 */ | |
259 int | |
260 jan1(int yr) | |
261 { | |
262 int y, d; | |
263 | |
264 /* | |
265 * normal gregorian calendar | |
266 * one extra day per four years | |
267 */ | |
268 | |
269 y = yr; | |
270 d = 4+y+(y+3)/4; | |
271 | |
272 /* | |
273 * julian calendar | |
274 * regular gregorian | |
275 * less three days per 400 | |
276 */ | |
277 | |
278 if(y > 1800) { | |
279 d -= (y-1701)/100; | |
280 d += (y-1601)/400; | |
281 } | |
282 | |
283 /* | |
284 * great calendar changeover instant | |
285 */ | |
286 | |
287 if(y > 1752) | |
288 d += 3; | |
289 | |
290 return d%7; | |
291 } | |
292 | |
293 /* | |
294 * system dependent | |
295 * get current month and year | |
296 */ | |
297 int | |
298 curmo(void) | |
299 { | |
300 Tm *tm; | |
301 | |
302 tm = localtime(time(0)); | |
303 return tm->mon+1; | |
304 } | |
305 | |
306 int | |
307 curyr(void) | |
308 { | |
309 Tm *tm; | |
310 | |
311 tm = localtime(time(0)); | |
312 return tm->year+1900; | |
313 } |