calendar.c 4.2 KB

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