calendar.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. Biobuf in;
  15. int debug, matchyear;
  16. Date *dates(Date**, Tm*);
  17. void upper2lower(char*, char*, int);
  18. void *alloc(unsigned int);
  19. void
  20. main(int argc, char *argv[])
  21. {
  22. int i, fd, ahead;
  23. long now;
  24. char *line;
  25. Tm *tm;
  26. Date *first, *last, *d;
  27. char buf[1024];
  28. ahead = 0;
  29. ARGBEGIN{
  30. case 'y':
  31. matchyear = 1;
  32. break;
  33. case 'd':
  34. debug = 1;
  35. break;
  36. case 'p':
  37. ahead = atoi(ARGF());
  38. break;
  39. default:
  40. fprint(2, "usage: calendar [-y] [-d] [files ...]\n");
  41. exits("usage");
  42. }ARGEND;
  43. /* make a list of dates */
  44. now = time(0);
  45. tm = localtime(now);
  46. last = nil;
  47. first = dates(&last, tm);
  48. now += Secondsperday;
  49. tm = localtime(now);
  50. dates(&last, tm);
  51. if(tm->wday == 6){
  52. now += Secondsperday;
  53. tm = localtime(now);
  54. dates(&last, tm);
  55. }
  56. if(tm->wday == 0){
  57. now += Secondsperday;
  58. tm = localtime(now);
  59. dates(&last, tm);
  60. }
  61. if(ahead){
  62. now = time(0);
  63. now += ahead * Secondsperday;
  64. tm = localtime(now);
  65. dates(&last, tm);
  66. }
  67. for(i=0; i<argc || (i==0 && argc==0); i++){
  68. if(i==0 && argc==0)
  69. snprint(buf, sizeof(buf),
  70. "/usr/%s/lib/calendar", getuser());
  71. else
  72. strcpy(buf, argv[i]);
  73. fd = open(buf, OREAD);
  74. if(fd<0 || Binit(&in, fd, OREAD)<0){
  75. fprint(2, "calendar: can't open %s: %r\n", buf);
  76. exits("open");
  77. }
  78. /* go through the file */
  79. while(line = Brdline(&in, '\n')){
  80. line[Blinelen(&in) - 1] = 0;
  81. upper2lower(buf, line, sizeof buf);
  82. for(d=first; d; d=d->next)
  83. if(regexec(d->p, buf, 0, 0)){
  84. print("%s\n", line);
  85. break;
  86. }
  87. }
  88. close(fd);
  89. }
  90. exits("");
  91. }
  92. char *months[] =
  93. {
  94. "january",
  95. "february",
  96. "march",
  97. "april",
  98. "may",
  99. "june",
  100. "july",
  101. "august",
  102. "september",
  103. "october",
  104. "november",
  105. "december"
  106. };
  107. /*
  108. * Generate two Date structures. First has month followed by day;
  109. * second has day followed by month. Link them into list after
  110. * last, and return the first.
  111. */
  112. Date*
  113. dates(Date **last, Tm *tm)
  114. {
  115. Date *first;
  116. Date *nd;
  117. char mo[128], buf[128];
  118. if(utflen(months[tm->mon]) > 3)
  119. snprint(mo, sizeof mo, "%3.3s(%s)?",
  120. months[tm->mon], months[tm->mon]+3);
  121. else
  122. snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
  123. if (matchyear)
  124. snprint(buf, sizeof buf,
  125. "(^| |\t)((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
  126. mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100);
  127. else
  128. snprint(buf, sizeof buf,
  129. "(^| |\t)((%s( |\t)+)|(%d/))%d( |\t|$)",
  130. mo, tm->mon+1, tm->mday);
  131. if(debug)
  132. print("%s\n", buf);
  133. first = alloc(sizeof(Date));
  134. if(*last)
  135. (*last)->next = first;
  136. first->p = regcomp(buf);
  137. if (matchyear)
  138. snprint(buf, sizeof buf,
  139. "(^| |\t)%d( |\t)+(%s)( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
  140. tm->mday, mo, tm->year+1900, tm->year%100);
  141. else
  142. snprint(buf, sizeof buf,
  143. "(^| |\t)%d( |\t)+(%s)( |\t|$)",
  144. tm->mday, mo);
  145. if(debug)
  146. print("%s\n", buf);
  147. nd = alloc(sizeof(Date));
  148. nd->p = regcomp(buf);
  149. nd->next = 0;
  150. first->next = nd;
  151. *last = nd;
  152. return first;
  153. }
  154. /*
  155. * Copy 'from' to 'to', converting to lower case
  156. */
  157. void
  158. upper2lower(char *to, char *from, int len)
  159. {
  160. while(--len>0 && *from!='\0')
  161. *to++ = tolower(*from++);
  162. *to = 0;
  163. }
  164. /*
  165. * Call malloc and check for errors
  166. */
  167. void*
  168. alloc(unsigned int n)
  169. {
  170. void *p;
  171. p = malloc(n);
  172. if(p == 0){
  173. fprint(2, "calendar: malloc failed: %r\n");
  174. exits("malloc");
  175. }
  176. return p;
  177. }