1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include <regexp.h>
5219b2ee8SDavid du Colombier #include <ctype.h>
6219b2ee8SDavid du Colombier
7219b2ee8SDavid du Colombier typedef struct Date Date;
8219b2ee8SDavid du Colombier struct Date {
97dd7cddfSDavid du Colombier Reprog *p; /* an RE to match this date */
107dd7cddfSDavid du Colombier Date *next; /* pointer to next in list */
117dd7cddfSDavid du Colombier };
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier enum{
147dd7cddfSDavid du Colombier Secondsperday = 24*60*60
15219b2ee8SDavid du Colombier };
16219b2ee8SDavid du Colombier
17f48db99cSDavid du Colombier Date *Base = nil;
18219b2ee8SDavid du Colombier Biobuf in;
1980ee5cbfSDavid du Colombier int debug, matchyear;
20219b2ee8SDavid du Colombier
21f48db99cSDavid du Colombier void dates(Tm*);
22219b2ee8SDavid du Colombier void upper2lower(char*, char*, int);
23f48db99cSDavid du Colombier void *emalloc(unsigned int);
24219b2ee8SDavid du Colombier
25219b2ee8SDavid du Colombier void
usage(void)26de8abbc9SDavid du Colombier usage(void)
27de8abbc9SDavid du Colombier {
28de8abbc9SDavid du Colombier fprint(2, "usage: calendar [-dy] [-p days] [files ...]\n");
29de8abbc9SDavid du Colombier exits("usage");
30de8abbc9SDavid du Colombier }
31de8abbc9SDavid du Colombier
32de8abbc9SDavid du Colombier void
main(int argc,char * argv[])33219b2ee8SDavid du Colombier main(int argc, char *argv[])
34219b2ee8SDavid du Colombier {
353ff48bf5SDavid du Colombier int i, fd, ahead;
36219b2ee8SDavid du Colombier long now;
37219b2ee8SDavid du Colombier char *line;
38219b2ee8SDavid du Colombier Tm *tm;
39f48db99cSDavid du Colombier Date *d;
40219b2ee8SDavid du Colombier char buf[1024];
41219b2ee8SDavid du Colombier
423ff48bf5SDavid du Colombier ahead = 0;
43219b2ee8SDavid du Colombier ARGBEGIN{
4480ee5cbfSDavid du Colombier case 'y':
4580ee5cbfSDavid du Colombier matchyear = 1;
4680ee5cbfSDavid du Colombier break;
47219b2ee8SDavid du Colombier case 'd':
48219b2ee8SDavid du Colombier debug = 1;
49219b2ee8SDavid du Colombier break;
503ff48bf5SDavid du Colombier case 'p':
51de8abbc9SDavid du Colombier ahead = atoi(EARGF(usage()));
523ff48bf5SDavid du Colombier break;
537dd7cddfSDavid du Colombier default:
54de8abbc9SDavid du Colombier usage();
55219b2ee8SDavid du Colombier }ARGEND;
56219b2ee8SDavid du Colombier
57219b2ee8SDavid du Colombier /* make a list of dates */
58219b2ee8SDavid du Colombier now = time(0);
59219b2ee8SDavid du Colombier tm = localtime(now);
60f48db99cSDavid du Colombier dates(tm);
617dd7cddfSDavid du Colombier now += Secondsperday;
627dd7cddfSDavid du Colombier tm = localtime(now);
63f48db99cSDavid du Colombier dates(tm);
64219b2ee8SDavid du Colombier if(tm->wday == 6){
657dd7cddfSDavid du Colombier now += Secondsperday;
667dd7cddfSDavid du Colombier tm = localtime(now);
67f48db99cSDavid du Colombier dates(tm);
68219b2ee8SDavid du Colombier }
69219b2ee8SDavid du Colombier if(tm->wday == 0){
707dd7cddfSDavid du Colombier now += Secondsperday;
717dd7cddfSDavid du Colombier tm = localtime(now);
72f48db99cSDavid du Colombier dates(tm);
73219b2ee8SDavid du Colombier }
743ff48bf5SDavid du Colombier if(ahead){
753ff48bf5SDavid du Colombier now = time(0);
763ff48bf5SDavid du Colombier now += ahead * Secondsperday;
773ff48bf5SDavid du Colombier tm = localtime(now);
78f48db99cSDavid du Colombier dates(tm);
793ff48bf5SDavid du Colombier }
80219b2ee8SDavid du Colombier
817dd7cddfSDavid du Colombier for(i=0; i<argc || (i==0 && argc==0); i++){
827dd7cddfSDavid du Colombier if(i==0 && argc==0)
834d44ba9bSDavid du Colombier snprint(buf, sizeof buf,
847dd7cddfSDavid du Colombier "/usr/%s/lib/calendar", getuser());
857dd7cddfSDavid du Colombier else
864d44ba9bSDavid du Colombier strecpy(buf, buf+sizeof buf, argv[i]);
877dd7cddfSDavid du Colombier fd = open(buf, OREAD);
887dd7cddfSDavid du Colombier if(fd<0 || Binit(&in, fd, OREAD)<0){
897dd7cddfSDavid du Colombier fprint(2, "calendar: can't open %s: %r\n", buf);
907dd7cddfSDavid du Colombier exits("open");
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
93219b2ee8SDavid du Colombier /* go through the file */
94219b2ee8SDavid du Colombier while(line = Brdline(&in, '\n')){
95219b2ee8SDavid du Colombier line[Blinelen(&in) - 1] = 0;
967dd7cddfSDavid du Colombier upper2lower(buf, line, sizeof buf);
97f48db99cSDavid du Colombier for(d=Base; d; d=d->next)
98219b2ee8SDavid du Colombier if(regexec(d->p, buf, 0, 0)){
99219b2ee8SDavid du Colombier print("%s\n", line);
100219b2ee8SDavid du Colombier break;
101219b2ee8SDavid du Colombier }
102219b2ee8SDavid du Colombier }
1037dd7cddfSDavid du Colombier close(fd);
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier exits("");
106219b2ee8SDavid du Colombier }
107219b2ee8SDavid du Colombier
108219b2ee8SDavid du Colombier char *months[] =
109219b2ee8SDavid du Colombier {
110219b2ee8SDavid du Colombier "january",
111219b2ee8SDavid du Colombier "february",
112219b2ee8SDavid du Colombier "march",
113219b2ee8SDavid du Colombier "april",
114219b2ee8SDavid du Colombier "may",
115219b2ee8SDavid du Colombier "june",
116219b2ee8SDavid du Colombier "july",
117219b2ee8SDavid du Colombier "august",
118219b2ee8SDavid du Colombier "september",
119219b2ee8SDavid du Colombier "october",
120219b2ee8SDavid du Colombier "november",
121219b2ee8SDavid du Colombier "december"
122219b2ee8SDavid du Colombier };
123f48db99cSDavid du Colombier char *nth[] = {
124f48db99cSDavid du Colombier "first",
125*7386956aSDavid du Colombier "second",
126f48db99cSDavid du Colombier "third",
127f48db99cSDavid du Colombier "fourth",
128f48db99cSDavid du Colombier "fifth"
129f48db99cSDavid du Colombier };
130f48db99cSDavid du Colombier char *days[] = {
131f48db99cSDavid du Colombier "sunday",
132f48db99cSDavid du Colombier "monday",
133f48db99cSDavid du Colombier "tuesday",
134f48db99cSDavid du Colombier "wednesday",
135f48db99cSDavid du Colombier "thursday",
136f48db99cSDavid du Colombier "friday",
137f48db99cSDavid du Colombier "saturday"
138f48db99cSDavid du Colombier };
139219b2ee8SDavid du Colombier
1407dd7cddfSDavid du Colombier /*
1417dd7cddfSDavid du Colombier * Generate two Date structures. First has month followed by day;
1427dd7cddfSDavid du Colombier * second has day followed by month. Link them into list after
1437dd7cddfSDavid du Colombier * last, and return the first.
1447dd7cddfSDavid du Colombier */
145f48db99cSDavid du Colombier void
dates(Tm * tm)146f48db99cSDavid du Colombier dates(Tm *tm)
147219b2ee8SDavid du Colombier {
148219b2ee8SDavid du Colombier Date *nd;
149f48db99cSDavid du Colombier char mo[128], day[128], buf[128];
150f48db99cSDavid du Colombier
151f48db99cSDavid du Colombier if(utflen(days[tm->wday]) > 3)
152f48db99cSDavid du Colombier snprint(day, sizeof day, "%3.3s(%s)?",
153f48db99cSDavid du Colombier days[tm->wday], days[tm->wday]+3);
154f48db99cSDavid du Colombier else
155f48db99cSDavid du Colombier snprint(day, sizeof day, "%3.3s", days[tm->wday]);
156219b2ee8SDavid du Colombier
15759cc4ca5SDavid du Colombier if(utflen(months[tm->mon]) > 3)
15859cc4ca5SDavid du Colombier snprint(mo, sizeof mo, "%3.3s(%s)?",
159219b2ee8SDavid du Colombier months[tm->mon], months[tm->mon]+3);
160219b2ee8SDavid du Colombier else
16159cc4ca5SDavid du Colombier snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
16280ee5cbfSDavid du Colombier if (matchyear)
16380ee5cbfSDavid du Colombier snprint(buf, sizeof buf,
164f48db99cSDavid du Colombier "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
165f48db99cSDavid du Colombier mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100, tm->year%100);
16680ee5cbfSDavid du Colombier else
1677dd7cddfSDavid du Colombier snprint(buf, sizeof buf,
168f48db99cSDavid du Colombier "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)",
1697dd7cddfSDavid du Colombier mo, tm->mon+1, tm->mday);
170219b2ee8SDavid du Colombier if(debug)
171219b2ee8SDavid du Colombier print("%s\n", buf);
1727dd7cddfSDavid du Colombier
173f48db99cSDavid du Colombier nd = emalloc(sizeof(Date));
174f48db99cSDavid du Colombier nd->p = regcomp(buf);
175f48db99cSDavid du Colombier nd->next = Base;
176f48db99cSDavid du Colombier Base = nd;
177219b2ee8SDavid du Colombier
17880ee5cbfSDavid du Colombier if (matchyear)
17980ee5cbfSDavid du Colombier snprint(buf, sizeof buf,
180f48db99cSDavid du Colombier "^[\t ]*%d( |\t)+(%s)( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
181f48db99cSDavid du Colombier tm->mday, mo, tm->year+1900, tm->year%100, tm->year%100);
18280ee5cbfSDavid du Colombier else
1837dd7cddfSDavid du Colombier snprint(buf, sizeof buf,
184f48db99cSDavid du Colombier "^[\t ]*%d( |\t)+(%s)( |\t|$)",
185219b2ee8SDavid du Colombier tm->mday, mo);
186219b2ee8SDavid du Colombier if(debug)
187219b2ee8SDavid du Colombier print("%s\n", buf);
188f48db99cSDavid du Colombier nd = emalloc(sizeof(Date));
189219b2ee8SDavid du Colombier nd->p = regcomp(buf);
190f48db99cSDavid du Colombier nd->next = Base;
191f48db99cSDavid du Colombier Base = nd;
192219b2ee8SDavid du Colombier
193f48db99cSDavid du Colombier snprint(buf, sizeof buf, "^[\t ]*every[ \t]+%s", day);
194f48db99cSDavid du Colombier if(debug)
195f48db99cSDavid du Colombier print("%s\n", buf);
196f48db99cSDavid du Colombier nd = emalloc(sizeof(Date));
197f48db99cSDavid du Colombier nd->p = regcomp(buf);
198f48db99cSDavid du Colombier nd->next = Base;
199f48db99cSDavid du Colombier Base = nd;
200f48db99cSDavid du Colombier
201*7386956aSDavid du Colombier snprint(buf, sizeof buf, "[\t ]*the[\t ]+%s[\t ]+%s", nth[(tm->mday-1)/7], day);
202f48db99cSDavid du Colombier if(debug)
203f48db99cSDavid du Colombier print("%s\n", buf);
204f48db99cSDavid du Colombier nd = emalloc(sizeof(Date));
205f48db99cSDavid du Colombier nd->p = regcomp(buf);
206f48db99cSDavid du Colombier nd->next = Base;
207f48db99cSDavid du Colombier Base = nd;
208219b2ee8SDavid du Colombier }
209219b2ee8SDavid du Colombier
2107dd7cddfSDavid du Colombier /*
2117dd7cddfSDavid du Colombier * Copy 'from' to 'to', converting to lower case
2127dd7cddfSDavid du Colombier */
213219b2ee8SDavid du Colombier void
upper2lower(char * to,char * from,int len)2147dd7cddfSDavid du Colombier upper2lower(char *to, char *from, int len)
215219b2ee8SDavid du Colombier {
2167dd7cddfSDavid du Colombier while(--len>0 && *from!='\0')
2177dd7cddfSDavid du Colombier *to++ = tolower(*from++);
218219b2ee8SDavid du Colombier *to = 0;
219219b2ee8SDavid du Colombier }
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier /*
2227dd7cddfSDavid du Colombier * Call malloc and check for errors
2237dd7cddfSDavid du Colombier */
2247dd7cddfSDavid du Colombier void*
emalloc(unsigned int n)225f48db99cSDavid du Colombier emalloc(unsigned int n)
2267dd7cddfSDavid du Colombier {
2277dd7cddfSDavid du Colombier void *p;
2287dd7cddfSDavid du Colombier
2297dd7cddfSDavid du Colombier p = malloc(n);
2307dd7cddfSDavid du Colombier if(p == 0){
2317dd7cddfSDavid du Colombier fprint(2, "calendar: malloc failed: %r\n");
2327dd7cddfSDavid du Colombier exits("malloc");
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier return p;
2357dd7cddfSDavid du Colombier }
236