123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <regexp.h>
- #include <ctype.h>
- typedef struct Date Date;
- struct Date {
- Reprog *p; /* an RE to match this date */
- Date *next; /* pointer to next in list */
- };
- enum{
- Secondsperday = 24*60*60
- };
- Date *Base = nil;
- Biobuf in;
- int debug, matchyear;
- void dates(Tm*);
- void upper2lower(char*, char*, int);
- void *emalloc(unsigned int);
- void
- usage(void)
- {
- fprint(2, "usage: calendar [-dy] [-p days] [files ...]\n");
- exits("usage");
- }
- void
- main(int argc, char *argv[])
- {
- int i, fd, ahead;
- long now;
- char *line;
- Tm *tm;
- Date *d;
- char buf[1024];
- ahead = 0;
- ARGBEGIN{
- case 'y':
- matchyear = 1;
- break;
- case 'd':
- debug = 1;
- break;
- case 'p':
- ahead = atoi(EARGF(usage()));
- break;
- default:
- usage();
- }ARGEND;
- /* make a list of dates */
- now = time(0);
- tm = localtime(now);
- dates(tm);
- now += Secondsperday;
- tm = localtime(now);
- dates(tm);
- if(tm->wday == 6){
- now += Secondsperday;
- tm = localtime(now);
- dates(tm);
- }
- if(tm->wday == 0){
- now += Secondsperday;
- tm = localtime(now);
- dates(tm);
- }
- if(ahead){
- now = time(0);
- now += ahead * Secondsperday;
- tm = localtime(now);
- dates(tm);
- }
- for(i=0; i<argc || (i==0 && argc==0); i++){
- if(i==0 && argc==0)
- snprint(buf, sizeof buf,
- "/usr/%s/lib/calendar", getuser());
- else
- strecpy(buf, buf+sizeof buf, argv[i]);
- fd = open(buf, OREAD);
- if(fd<0 || Binit(&in, fd, OREAD)<0){
- fprint(2, "calendar: can't open %s: %r\n", buf);
- exits("open");
- }
- /* go through the file */
- while(line = Brdline(&in, '\n')){
- line[Blinelen(&in) - 1] = 0;
- upper2lower(buf, line, sizeof buf);
- for(d=Base; d; d=d->next)
- if(regexec(d->p, buf, 0, 0)){
- print("%s\n", line);
- break;
- }
- }
- close(fd);
- }
- exits("");
- }
- char *months[] =
- {
- "january",
- "february",
- "march",
- "april",
- "may",
- "june",
- "july",
- "august",
- "september",
- "october",
- "november",
- "december"
- };
- char *nth[] = {
- "first",
- "second",
- "third",
- "fourth",
- "fifth"
- };
- char *days[] = {
- "sunday",
- "monday",
- "tuesday",
- "wednesday",
- "thursday",
- "friday",
- "saturday"
- };
- /*
- * Generate two Date structures. First has month followed by day;
- * second has day followed by month. Link them into list after
- * last, and return the first.
- */
- void
- dates(Tm *tm)
- {
- Date *nd;
- char mo[128], day[128], buf[128];
- if(utflen(days[tm->wday]) > 3)
- snprint(day, sizeof day, "%3.3s(%s)?",
- days[tm->wday], days[tm->wday]+3);
- else
- snprint(day, sizeof day, "%3.3s", days[tm->wday]);
- if(utflen(months[tm->mon]) > 3)
- snprint(mo, sizeof mo, "%3.3s(%s)?",
- months[tm->mon], months[tm->mon]+3);
- else
- snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
- if (matchyear)
- snprint(buf, sizeof buf,
- "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
- mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100, tm->year%100);
- else
- snprint(buf, sizeof buf,
- "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)",
- mo, tm->mon+1, tm->mday);
- if(debug)
- print("%s\n", buf);
- nd = emalloc(sizeof(Date));
- nd->p = regcomp(buf);
- nd->next = Base;
- Base = nd;
- if (matchyear)
- snprint(buf, sizeof buf,
- "^[\t ]*%d( |\t)+(%s)( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
- tm->mday, mo, tm->year+1900, tm->year%100, tm->year%100);
- else
- snprint(buf, sizeof buf,
- "^[\t ]*%d( |\t)+(%s)( |\t|$)",
- tm->mday, mo);
- if(debug)
- print("%s\n", buf);
- nd = emalloc(sizeof(Date));
- nd->p = regcomp(buf);
- nd->next = Base;
- Base = nd;
- snprint(buf, sizeof buf, "^[\t ]*every[ \t]+%s", day);
- if(debug)
- print("%s\n", buf);
- nd = emalloc(sizeof(Date));
- nd->p = regcomp(buf);
- nd->next = Base;
- Base = nd;
- snprint(buf, sizeof buf, "[\t ]*the[\t ]+%s[\t ]+%s", nth[(tm->mday-1)/7], day);
- if(debug)
- print("%s\n", buf);
- nd = emalloc(sizeof(Date));
- nd->p = regcomp(buf);
- nd->next = Base;
- Base = nd;
- }
- /*
- * Copy 'from' to 'to', converting to lower case
- */
- void
- upper2lower(char *to, char *from, int len)
- {
- while(--len>0 && *from!='\0')
- *to++ = tolower(*from++);
- *to = 0;
- }
- /*
- * Call malloc and check for errors
- */
- void*
- emalloc(unsigned int n)
- {
- void *p;
- p = malloc(n);
- if(p == 0){
- fprint(2, "calendar: malloc failed: %r\n");
- exits("malloc");
- }
- return p;
- }
|