calendar.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. main(int argc, char *argv[])
  22. {
  23. int i, fd, ahead;
  24. long now;
  25. char *line;
  26. Tm *tm;
  27. Date *d;
  28. char buf[1024];
  29. ahead = 0;
  30. ARGBEGIN{
  31. case 'y':
  32. matchyear = 1;
  33. break;
  34. case 'd':
  35. debug = 1;
  36. break;
  37. case 'p':
  38. ahead = atoi(ARGF());
  39. break;
  40. default:
  41. fprint(2, "usage: calendar [-dy] [-p days] [files ...]\n");
  42. exits("usage");
  43. }ARGEND;
  44. /* make a list of dates */
  45. now = time(0);
  46. tm = localtime(now);
  47. dates(tm);
  48. now += Secondsperday;
  49. tm = localtime(now);
  50. dates(tm);
  51. if(tm->wday == 6){
  52. now += Secondsperday;
  53. tm = localtime(now);
  54. dates(tm);
  55. }
  56. if(tm->wday == 0){
  57. now += Secondsperday;
  58. tm = localtime(now);
  59. dates(tm);
  60. }
  61. if(ahead){
  62. now = time(0);
  63. now += ahead * Secondsperday;
  64. tm = localtime(now);
  65. dates(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. strecpy(buf, buf+sizeof 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=Base; 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. char *nth[] = {
  108. "first",
  109. "seccond",
  110. "third",
  111. "fourth",
  112. "fifth"
  113. };
  114. char *days[] = {
  115. "sunday",
  116. "monday",
  117. "tuesday",
  118. "wednesday",
  119. "thursday",
  120. "friday",
  121. "saturday"
  122. };
  123. /*
  124. * Generate two Date structures. First has month followed by day;
  125. * second has day followed by month. Link them into list after
  126. * last, and return the first.
  127. */
  128. void
  129. dates(Tm *tm)
  130. {
  131. Date *nd;
  132. char mo[128], day[128], buf[128];
  133. if(utflen(days[tm->wday]) > 3)
  134. snprint(day, sizeof day, "%3.3s(%s)?",
  135. days[tm->wday], days[tm->wday]+3);
  136. else
  137. snprint(day, sizeof day, "%3.3s", days[tm->wday]);
  138. if(utflen(months[tm->mon]) > 3)
  139. snprint(mo, sizeof mo, "%3.3s(%s)?",
  140. months[tm->mon], months[tm->mon]+3);
  141. else
  142. snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
  143. if (matchyear)
  144. snprint(buf, sizeof buf,
  145. "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
  146. mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100, tm->year%100);
  147. else
  148. snprint(buf, sizeof buf,
  149. "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)",
  150. mo, tm->mon+1, tm->mday);
  151. if(debug)
  152. print("%s\n", buf);
  153. nd = emalloc(sizeof(Date));
  154. nd->p = regcomp(buf);
  155. nd->next = Base;
  156. Base = nd;
  157. if (matchyear)
  158. snprint(buf, sizeof buf,
  159. "^[\t ]*%d( |\t)+(%s)( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
  160. tm->mday, mo, tm->year+1900, tm->year%100, tm->year%100);
  161. else
  162. snprint(buf, sizeof buf,
  163. "^[\t ]*%d( |\t)+(%s)( |\t|$)",
  164. tm->mday, mo);
  165. if(debug)
  166. print("%s\n", buf);
  167. nd = emalloc(sizeof(Date));
  168. nd->p = regcomp(buf);
  169. nd->next = Base;
  170. Base = nd;
  171. snprint(buf, sizeof buf, "^[\t ]*every[ \t]+%s", day);
  172. if(debug)
  173. print("%s\n", buf);
  174. nd = emalloc(sizeof(Date));
  175. nd->p = regcomp(buf);
  176. nd->next = Base;
  177. Base = nd;
  178. snprint(buf, sizeof buf, "[\t ]*the[\t ]+%s[\t ]+%s", nth[tm->mday/7], day);
  179. if(debug)
  180. print("%s\n", buf);
  181. nd = emalloc(sizeof(Date));
  182. nd->p = regcomp(buf);
  183. nd->next = Base;
  184. Base = nd;
  185. }
  186. /*
  187. * Copy 'from' to 'to', converting to lower case
  188. */
  189. void
  190. upper2lower(char *to, char *from, int len)
  191. {
  192. while(--len>0 && *from!='\0')
  193. *to++ = tolower(*from++);
  194. *to = 0;
  195. }
  196. /*
  197. * Call malloc and check for errors
  198. */
  199. void*
  200. emalloc(unsigned int n)
  201. {
  202. void *p;
  203. p = malloc(n);
  204. if(p == 0){
  205. fprint(2, "calendar: malloc failed: %r\n");
  206. exits("malloc");
  207. }
  208. return p;
  209. }