diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/calendar.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/calendar.c')
-rwxr-xr-x | sys/src/cmd/calendar.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/sys/src/cmd/calendar.c b/sys/src/cmd/calendar.c new file mode 100755 index 000000000..37e32668a --- /dev/null +++ b/sys/src/cmd/calendar.c @@ -0,0 +1,235 @@ +#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; +} |