cal.c 4.6 KB

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