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 void34 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 month46 */47 if(argc == 1) {48 m = curmo();49 y = curyr();50 goto xshort;51 }53 /*54 * one arg55 * if looks like a month, print month56 * else print year57 */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 year72 */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 month81 */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 year96 */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);120 badarg:121 Bprint(&bout, "cal: bad argument\n");122 }124 struct125 {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 0155 };157 /*158 * convert to a number.159 * if its a dictionary word,160 * return negative number161 */162 int163 number(char *str)164 {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';177 }178 return n;179 }181 void182 pstr(char *str, int n)183 {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);198 }200 void201 cal(int m, int y, char *p, int w)202 {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 year215 */216 case 1:217 mon[2] = 28;218 break;220 /*221 * 1752222 */223 default:224 mon[9] = 19;225 break;227 /*228 * leap year229 */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 }255 /*256 * return day of the week257 * of jan 1 of given year258 */259 int260 jan1(int yr)261 {262 int y, d;264 /*265 * normal gregorian calendar266 * one extra day per four years267 */269 y = yr;270 d = 4+y+(y+3)/4;272 /*273 * julian calendar274 * regular gregorian275 * less three days per 400276 */278 if(y > 1800) {279 d -= (y-1701)/100;280 d += (y-1601)/400;281 }283 /*284 * great calendar changeover instant285 */287 if(y > 1752)288 d += 3;290 return d%7;291 }293 /*294 * system dependent295 * get current month and year296 */297 int298 curmo(void)299 {300 Tm *tm;302 tm = localtime(time(0));303 return tm->mon+1;304 }306 int307 curyr(void)308 {309 Tm *tm;311 tm = localtime(time(0));312 return tm->year+1900;313 }