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 }