calendar.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. #include <regexp.h>
  13. #include <ctype.h>
  14. typedef struct Date Date;
  15. struct Date {
  16. Reprog *p; /* an RE to match this date */
  17. Date *next; /* pointer to next in list */
  18. };
  19. enum{
  20. Secondsperday = 24*60*60
  21. };
  22. Date *Base = nil;
  23. Biobuf in;
  24. int debug, matchyear;
  25. void dates(Tm*);
  26. void upper2lower(char*, char*, int);
  27. void *emalloc(unsigned int);
  28. void
  29. usage(void)
  30. {
  31. fprint(2, "usage: calendar [-dy] [-p days] [files ...]\n");
  32. exits("usage");
  33. }
  34. void
  35. main(int argc, char *argv[])
  36. {
  37. int i, fd, ahead;
  38. int32_t now;
  39. char *line;
  40. Tm *tm;
  41. Date *d;
  42. char buf[1024];
  43. ahead = 0;
  44. ARGBEGIN{
  45. case 'y':
  46. matchyear = 1;
  47. break;
  48. case 'd':
  49. debug = 1;
  50. break;
  51. case 'p':
  52. ahead = atoi(EARGF(usage()));
  53. break;
  54. default:
  55. usage();
  56. }ARGEND;
  57. /* make a list of dates */
  58. now = time(0);
  59. tm = localtime(now);
  60. dates(tm);
  61. now += Secondsperday;
  62. tm = localtime(now);
  63. dates(tm);
  64. if(tm->wday == 6){
  65. now += Secondsperday;
  66. tm = localtime(now);
  67. dates(tm);
  68. }
  69. if(tm->wday == 0){
  70. now += Secondsperday;
  71. tm = localtime(now);
  72. dates(tm);
  73. }
  74. if(ahead){
  75. now = time(0);
  76. now += ahead * Secondsperday;
  77. tm = localtime(now);
  78. dates(tm);
  79. }
  80. for(i=0; i<argc || (i==0 && argc==0); i++){
  81. if(i==0 && argc==0)
  82. snprint(buf, sizeof buf,
  83. "/usr/%s/lib/calendar", getuser());
  84. else
  85. strecpy(buf, buf+sizeof buf, argv[i]);
  86. fd = open(buf, OREAD);
  87. if(fd<0 || Binit(&in, fd, OREAD)<0){
  88. fprint(2, "calendar: can't open %s: %r\n", buf);
  89. exits("open");
  90. }
  91. /* go through the file */
  92. while((line = Brdline(&in, '\n')) != nil){
  93. line[Blinelen(&in) - 1] = 0;
  94. upper2lower(buf, line, sizeof buf);
  95. for(d=Base; d; d=d->next)
  96. if(regexec(d->p, buf, 0, 0)){
  97. print("%s\n", line);
  98. break;
  99. }
  100. }
  101. close(fd);
  102. }
  103. exits("");
  104. }
  105. char *months[] =
  106. {
  107. "january",
  108. "february",
  109. "march",
  110. "april",
  111. "may",
  112. "june",
  113. "july",
  114. "august",
  115. "september",
  116. "october",
  117. "november",
  118. "december"
  119. };
  120. char *nth[] = {
  121. "first",
  122. "second",
  123. "third",
  124. "fourth",
  125. "fifth"
  126. };
  127. char *days[] = {
  128. "sunday",
  129. "monday",
  130. "tuesday",
  131. "wednesday",
  132. "thursday",
  133. "friday",
  134. "saturday"
  135. };
  136. /*
  137. * Generate two Date structures. First has month followed by day;
  138. * second has day followed by month. Link them into list after
  139. * last, and return the first.
  140. */
  141. void
  142. dates(Tm *tm)
  143. {
  144. Date *nd;
  145. char mo[128], day[128], buf[128];
  146. if(utflen(days[tm->wday]) > 3)
  147. snprint(day, sizeof day, "%3.3s(%s)?",
  148. days[tm->wday], days[tm->wday]+3);
  149. else
  150. snprint(day, sizeof day, "%3.3s", days[tm->wday]);
  151. if(utflen(months[tm->mon]) > 3)
  152. snprint(mo, sizeof mo, "%3.3s(%s)?",
  153. months[tm->mon], months[tm->mon]+3);
  154. else
  155. snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
  156. if (matchyear)
  157. snprint(buf, sizeof buf,
  158. "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
  159. mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100, tm->year%100);
  160. else
  161. snprint(buf, sizeof buf,
  162. "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)",
  163. mo, tm->mon+1, tm->mday);
  164. if(debug)
  165. print("%s\n", buf);
  166. nd = emalloc(sizeof(Date));
  167. nd->p = regcomp(buf);
  168. nd->next = Base;
  169. Base = nd;
  170. if (matchyear)
  171. snprint(buf, sizeof buf,
  172. "^[\t ]*%d( |\t)+(%s)( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
  173. tm->mday, mo, tm->year+1900, tm->year%100, tm->year%100);
  174. else
  175. snprint(buf, sizeof buf,
  176. "^[\t ]*%d( |\t)+(%s)( |\t|$)",
  177. tm->mday, mo);
  178. if(debug)
  179. print("%s\n", buf);
  180. nd = emalloc(sizeof(Date));
  181. nd->p = regcomp(buf);
  182. nd->next = Base;
  183. Base = nd;
  184. snprint(buf, sizeof buf, "^[\t ]*every[ \t]+%s", day);
  185. if(debug)
  186. print("%s\n", buf);
  187. nd = emalloc(sizeof(Date));
  188. nd->p = regcomp(buf);
  189. nd->next = Base;
  190. Base = nd;
  191. snprint(buf, sizeof buf, "[\t ]*the[\t ]+%s[\t ]+%s", nth[(tm->mday-1)/7], day);
  192. if(debug)
  193. print("%s\n", buf);
  194. nd = emalloc(sizeof(Date));
  195. nd->p = regcomp(buf);
  196. nd->next = Base;
  197. Base = nd;
  198. }
  199. /*
  200. * Copy 'from' to 'to', converting to lower case
  201. */
  202. void
  203. upper2lower(char *to, char *from, int len)
  204. {
  205. while(--len>0 && *from!='\0')
  206. *to++ = tolower(*from++);
  207. *to = 0;
  208. }
  209. /*
  210. * Call malloc and check for errors
  211. */
  212. void*
  213. emalloc(unsigned int n)
  214. {
  215. void *p;
  216. p = malloc(n);
  217. if(p == 0){
  218. fprint(2, "calendar: malloc failed: %r\n");
  219. exits("malloc");
  220. }
  221. return p;
  222. }