cal.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * C A L E N D A R
  3. *
  4. * Usage:
  5. * calend MM If small, it's a month, if large, a year.
  6. * or
  7. * calend YYYY MM year/month
  8. * or
  9. * calend MM YYYY
  10. */
  11. /*)BUILD
  12. */
  13. #include <stdio.h>
  14. #include <sys/time.h>
  15. #ifdef decus
  16. int $$narg = 1; /* Don't prompt */
  17. #endif
  18. #define EOS 0
  19. #define MWIDTH (7*3 + 3) /* Bytes to print a month */
  20. #define WPERMO 6 /* Max. weeks per month */
  21. #define LWIDTH 72 /* Line width */
  22. #define MPERLIN (LWIDTH / MWIDTH) /* Three months per line */
  23. #define WWIDTH (LWIDTH / MPERLIN) /* Bytes in one week */
  24. /* #define BUFSIZ (WPERMO * LWIDTH) */ /* Buffer dimension */
  25. char *weekday = " S M Tu W Th F S";
  26. char *monthname[] = {
  27. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  28. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  29. };
  30. char buffer[BUFSIZ];
  31. main(argc, argv)
  32. int argc;
  33. char *argv[];
  34. {
  35. register int month;
  36. register int year;
  37. register int arg1val;
  38. int arg1len;
  39. int arg2val;
  40. int tvec[2];
  41. struct tm *tm;
  42. time(&tvec[0]);
  43. tm = localtime(&tvec[0]);
  44. year = tm->tm_year + 1900;
  45. month = tm->tm_mon + 1;
  46. if (argc <= 1)
  47. /*
  48. * No arguments mean do last, this, and next month
  49. */
  50. do3months(year, month);
  51. else {
  52. arg1val = atoi(argv[1]);
  53. arg1len = strlen(argv[1]);
  54. if (argc == 2) {
  55. /*
  56. * Only one argument, if small, it's a month. If
  57. * large, it's a year. Note:
  58. * calend 0082 Year '82
  59. * calend 82 Year 1982
  60. */
  61. if (arg1len <= 2 && arg1val <= 12)
  62. do3months(year, arg1val);
  63. else {
  64. if (arg1len <= 2 && arg1val > 0 && arg1val <= 99)
  65. arg1val += 1900;
  66. doyear(arg1val);
  67. }
  68. }
  69. else {
  70. /*
  71. * Two arguments, allow 1980 12 or 12 1980
  72. */
  73. arg2val = atoi(argv[2]);
  74. if (arg1len > 2)
  75. do3months(arg1val, arg2val);
  76. else
  77. do3months(arg2val, arg1val);
  78. }
  79. }
  80. }
  81. doyear(year)
  82. int year;
  83. /*
  84. * Print a calendar for an entire year.
  85. */
  86. {
  87. register int month;
  88. register int windex; /* Week index */
  89. if (year < 1 || year > 9999)
  90. usage("year: %d\n", year);
  91. printf("\n\n\n%35d\n\n", year);
  92. for (month = 1; month <= 12; month += MPERLIN) {
  93. bzero(buffer, sizeof buffer);
  94. printf("%12s%23s%23s\n", monthname[month-1],
  95. monthname[month], monthname[month+1]);
  96. printf("%s %s %s\n", weekday, weekday, weekday);
  97. calendar(year, month+0, &buffer[(MWIDTH-1)*0], LWIDTH);
  98. calendar(year, month+1, &buffer[(MWIDTH-1)*1], LWIDTH);
  99. calendar(year, month+2, &buffer[(MWIDTH-1)*2], LWIDTH);
  100. for (windex = 0; windex < (WPERMO * LWIDTH); windex += LWIDTH)
  101. out(&buffer[windex], LWIDTH);
  102. }
  103. printf("\n\n\n");
  104. }
  105. domonth(year, month)
  106. int year;
  107. int month;
  108. /*
  109. * Do one specific month -- note: no longer used
  110. */
  111. {
  112. register int windex;
  113. if (year < 1 || year > 9999)
  114. usage("Bad year: %d\n", year);
  115. if (month <= 0 || month > 12)
  116. usage("month: %d\n", month);
  117. printf("%9s%5d\n\n%s\n", monthname[month-1], year, weekday);
  118. calendar(year, month, buffer, WWIDTH);
  119. for (windex = 0; windex < (WPERMO * WWIDTH); windex += WWIDTH)
  120. out(&buffer[windex], WWIDTH);
  121. printf("\n\n");
  122. }
  123. do3months(thisyear, thismonth)
  124. int thisyear;
  125. register int thismonth;
  126. /*
  127. * Do last month, this month, and next months. The parameters
  128. * are guaranteed accurate. (and year will not be less than 2 nor
  129. * greater than 9998).
  130. */
  131. {
  132. register int windex; /* Week index */
  133. int lastmonth;
  134. int lastyear;
  135. int nextmonth;
  136. int nextyear;
  137. lastyear = nextyear = thisyear;
  138. if ((lastmonth = thismonth - 1) == 0) {
  139. lastmonth = 12;
  140. lastyear--;
  141. }
  142. if ((nextmonth = thismonth + 1) == 13) {
  143. nextmonth = 1;
  144. nextyear++;
  145. }
  146. printf("%9s%5d%18s%5d%18s%5d\n",
  147. monthname[lastmonth - 1], lastyear,
  148. monthname[thismonth - 1], thisyear,
  149. monthname[nextmonth - 1], nextyear);
  150. printf("%s %s %s\n", weekday, weekday, weekday);
  151. calendar(lastyear, lastmonth, &buffer[(MWIDTH-1)*0], LWIDTH);
  152. calendar(thisyear, thismonth, &buffer[(MWIDTH-1)*1], LWIDTH);
  153. calendar(nextyear, nextmonth, &buffer[(MWIDTH-1)*2], LWIDTH);
  154. for (windex = 0; windex < (WPERMO * LWIDTH); windex += LWIDTH)
  155. out(&buffer[windex], LWIDTH);
  156. printf("\n\n\n");
  157. }
  158. out(text, len)
  159. char *text;
  160. int len;
  161. /*
  162. * Clean up and output this line
  163. */
  164. {
  165. register char *firstp;
  166. register char *lastp;
  167. lastp = &text[len];
  168. for (firstp = text; firstp < lastp; firstp++) {
  169. if (*firstp == EOS)
  170. *firstp = ' ';
  171. }
  172. while (lastp > text && *--lastp == ' ');
  173. lastp[1] = EOS;
  174. printf("%s\n", text);
  175. }
  176. usage(format, args)
  177. char *format;
  178. int args;
  179. /*
  180. * Fatal parameter error
  181. */
  182. {
  183. fprintf(stderr, "Calendar parameter error: ");
  184. #ifdef decus
  185. $$prnt(format, &args, stderr);
  186. #else
  187. _doprnt(format, &args, stderr);
  188. #endif
  189. fprintf(stderr, "Usage: \"calend month\" or \"calend year month\"\n");
  190. fprintf(stderr, "Year and month are integers.\n");
  191. exit(1);
  192. }
  193. /*
  194. * Actually generate a calendar
  195. */
  196. static char monthdays[] = {
  197. 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  198. }; /* Thirty days hath september */
  199. /* Except for 1752 */
  200. calendar(year, month, outbuf, offset)
  201. int year;
  202. int month;
  203. char *outbuf; /* Output goes here */
  204. int offset; /* "Distance" to next month */
  205. /*
  206. * Build the calendar for this year/month
  207. */
  208. {
  209. register char *outp;
  210. register int dow; /* Day of week */
  211. register int day; /* Day in month */
  212. outp = outbuf;
  213. dow = jan1(year);
  214. monthdays[2] = 29; /* Assume leap year */
  215. monthdays[9] = 30; /* Assume no magic */
  216. switch((jan1(year + 1) + 7 - dow) % 7) {
  217. case 2:
  218. /*
  219. * Leap year if jan 1 of next year is two days after
  220. * this year's jan 1
  221. */
  222. break;
  223. case 1:
  224. /*
  225. * Not a leap year if jan 1 of next year is the next day
  226. * after jan 1 of this year.
  227. */
  228. monthdays[2] = 28;
  229. break;
  230. default:
  231. /*
  232. * Magic year of 1752 when September lost 11 days.
  233. */
  234. monthdays[9] = 19;
  235. break;
  236. }
  237. for (day = 1; day < month; day++)
  238. dow += monthdays[day];
  239. dow %= 7; /* Weekday of first of month */
  240. outp += (dow * 3); /* Where to start in calendar */
  241. for (day = 1; day <= monthdays[month]; day++) {
  242. if (day == 3 && monthdays[month] == 19) {
  243. /*
  244. * It's magic (September 3 became September 14)
  245. * And September 1752 really did have 30 days.
  246. */
  247. day += 11;
  248. monthdays[month] += 11;
  249. }
  250. if (day > 9)
  251. *outp = (day / 10) + '0';
  252. outp++;
  253. *outp++ = (day % 10) + '0';
  254. outp++;
  255. if (++dow >= 7) {
  256. /*
  257. * Sunday, rotate to the next line
  258. */
  259. dow = 0;
  260. outp = &outbuf[offset];
  261. outbuf = outp;
  262. }
  263. }
  264. }
  265. jan1(year)
  266. register int year;
  267. /*
  268. * Return day that jan 1 falls on for this year.
  269. */
  270. {
  271. register int day;
  272. /*
  273. * Gregorian calendar: one extra day per four years.
  274. */
  275. day = year + 4 + (year + 3) / 4;
  276. /*
  277. * Julian calendar: Gregorian less three days per 400
  278. */
  279. if (year > 1800) {
  280. day -= ((year - 1701) / 100);
  281. day += ((year - 1601) / 400);
  282. }
  283. /*
  284. * Calendar changeover year (valid in America only).
  285. */
  286. if (year > 1752)
  287. day += 3;
  288. return (day % 7);
  289. }