| 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 } |