cal.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. char dayw[] =
  5. {
  6. " S M Tu W Th F S"
  7. };
  8. char *smon[] =
  9. {
  10. "January", "February", "March", "April",
  11. "May", "June", "July", "August",
  12. "September", "October", "November", "December",
  13. };
  14. char mon[] =
  15. {
  16. 0,
  17. 31, 29, 31, 30,
  18. 31, 30, 31, 31,
  19. 30, 31, 30, 31,
  20. };
  21. char string[432];
  22. Biobuf bout;
  23. void main(int argc, char *argv[]);
  24. int number(char *str);
  25. void pstr(char *str, int n);
  26. void cal(int m, int y, char *p, int w);
  27. int jan1(int yr);
  28. int curmo(void);
  29. int curyr(void);
  30. void
  31. main(int argc, char *argv[])
  32. {
  33. int y, i, j, m;
  34. if(argc > 3) {
  35. fprint(2, "usage: cal [month] [year]\n");
  36. exits("usage");
  37. }
  38. Binit(&bout, 1, OWRITE);
  39. /*
  40. * no arg, print current month
  41. */
  42. if(argc == 1) {
  43. m = curmo();
  44. y = curyr();
  45. goto xshort;
  46. }
  47. /*
  48. * one arg
  49. * if looks like a month, print month
  50. * else print year
  51. */
  52. if(argc == 2) {
  53. y = number(argv[1]);
  54. if(y < 0)
  55. y = -y;
  56. if(y >= 1 && y <= 12) {
  57. m = y;
  58. y = curyr();
  59. goto xshort;
  60. }
  61. goto xlong;
  62. }
  63. /*
  64. * two arg, month and year
  65. */
  66. m = number(argv[1]);
  67. if(m < 0)
  68. m = -m;
  69. y = number(argv[2]);
  70. goto xshort;
  71. /*
  72. * print out just month
  73. */
  74. xshort:
  75. if(m < 1 || m > 12)
  76. goto badarg;
  77. if(y < 1 || y > 9999)
  78. goto badarg;
  79. Bprint(&bout, " %s %ud\n", smon[m-1], y);
  80. Bprint(&bout, "%s\n", dayw);
  81. cal(m, y, string, 24);
  82. for(i=0; i<6*24; i+=24)
  83. pstr(string+i, 24);
  84. exits(0);
  85. /*
  86. * print out complete year
  87. */
  88. xlong:
  89. y = number(argv[1]);
  90. if(y<1 || y>9999)
  91. goto badarg;
  92. Bprint(&bout, "\n\n\n");
  93. Bprint(&bout, " %ud\n", y);
  94. Bprint(&bout, "\n");
  95. for(i=0; i<12; i+=3) {
  96. for(j=0; j<6*72; j++)
  97. string[j] = '\0';
  98. Bprint(&bout, " %.3s", smon[i]);
  99. Bprint(&bout, " %.3s", smon[i+1]);
  100. Bprint(&bout, " %.3s\n", smon[i+2]);
  101. Bprint(&bout, "%s %s %s\n", dayw, dayw, dayw);
  102. cal(i+1, y, string, 72);
  103. cal(i+2, y, string+23, 72);
  104. cal(i+3, y, string+46, 72);
  105. for(j=0; j<6*72; j+=72)
  106. pstr(string+j, 72);
  107. }
  108. Bprint(&bout, "\n\n\n");
  109. exits(0);
  110. badarg:
  111. Bprint(&bout, "cal: bad argument\n");
  112. }
  113. struct
  114. {
  115. char* word;
  116. int val;
  117. } dict[] =
  118. {
  119. "jan", 1,
  120. "january", 1,
  121. "feb", 2,
  122. "february", 2,
  123. "mar", 3,
  124. "march", 3,
  125. "apr", 4,
  126. "april", 4,
  127. "may", 5,
  128. "jun", 6,
  129. "june", 6,
  130. "jul", 7,
  131. "july", 7,
  132. "aug", 8,
  133. "august", 8,
  134. "sep", 9,
  135. "sept", 9,
  136. "september", 9,
  137. "oct", 10,
  138. "october", 10,
  139. "nov", 11,
  140. "november", 11,
  141. "dec", 12,
  142. "december", 12,
  143. 0
  144. };
  145. /*
  146. * convert to a number.
  147. * if its a dictionary word,
  148. * return negative number
  149. */
  150. int
  151. number(char *str)
  152. {
  153. int n, c;
  154. char *s;
  155. for(n=0; s=dict[n].word; n++)
  156. if(strcmp(s, str) == 0)
  157. return -dict[n].val;
  158. n = 0;
  159. s = str;
  160. while(c = *s++) {
  161. if(c<'0' || c>'9')
  162. return 0;
  163. n = n*10 + c-'0';
  164. }
  165. return n;
  166. }
  167. void
  168. pstr(char *str, int n)
  169. {
  170. int i;
  171. char *s;
  172. s = str;
  173. i = n;
  174. while(i--)
  175. if(*s++ == '\0')
  176. s[-1] = ' ';
  177. i = n+1;
  178. while(i--)
  179. if(*--s != ' ')
  180. break;
  181. s[1] = '\0';
  182. Bprint(&bout, "%s\n", str);
  183. }
  184. void
  185. cal(int m, int y, char *p, int w)
  186. {
  187. int d, i;
  188. char *s;
  189. s = p;
  190. d = jan1(y);
  191. mon[2] = 29;
  192. mon[9] = 30;
  193. switch((jan1(y+1)+7-d)%7) {
  194. /*
  195. * non-leap year
  196. */
  197. case 1:
  198. mon[2] = 28;
  199. break;
  200. /*
  201. * 1752
  202. */
  203. default:
  204. mon[9] = 19;
  205. break;
  206. /*
  207. * leap year
  208. */
  209. case 2:
  210. ;
  211. }
  212. for(i=1; i<m; i++)
  213. d += mon[i];
  214. d %= 7;
  215. s += 3*d;
  216. for(i=1; i<=mon[m]; i++) {
  217. if(i==3 && mon[m]==19) {
  218. i += 11;
  219. mon[m] += 11;
  220. }
  221. if(i > 9)
  222. *s = i/10+'0';
  223. s++;
  224. *s++ = i%10+'0';
  225. s++;
  226. if(++d == 7) {
  227. d = 0;
  228. s = p+w;
  229. p = s;
  230. }
  231. }
  232. }
  233. /*
  234. * return day of the week
  235. * of jan 1 of given year
  236. */
  237. int
  238. jan1(int yr)
  239. {
  240. int y, d;
  241. /*
  242. * normal gregorian calendar
  243. * one extra day per four years
  244. */
  245. y = yr;
  246. d = 4+y+(y+3)/4;
  247. /*
  248. * julian calendar
  249. * regular gregorian
  250. * less three days per 400
  251. */
  252. if(y > 1800) {
  253. d -= (y-1701)/100;
  254. d += (y-1601)/400;
  255. }
  256. /*
  257. * great calendar changeover instant
  258. */
  259. if(y > 1752)
  260. d += 3;
  261. return d%7;
  262. }
  263. /*
  264. * system dependent
  265. * get current month and year
  266. */
  267. int
  268. curmo(void)
  269. {
  270. Tm *tm;
  271. tm = localtime(time(0));
  272. return tm->mon+1;
  273. }
  274. int
  275. curyr(void)
  276. {
  277. Tm *tm;
  278. tm = localtime(time(0));
  279. return tm->year+1900;
  280. }