]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cal.c
usb lib: add maxpkt and ntds to Altc struct
[plan9front.git] / sys / src / cmd / cal.c
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 %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);
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, "                                %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);
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 }