]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/calendar.c
cpu: make -p work with explicit service in dialstring (same as import)
[plan9front.git] / sys / src / cmd / calendar.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <regexp.h>
5 #include <ctype.h>
6
7 typedef struct Date     Date;
8 struct Date {
9         Reprog *p;      /* an RE to match this date */
10         Date *next;     /* pointer to next in list */
11 };
12
13 enum{
14         Secondsperday = 24*60*60
15 };
16
17 Date *Base = nil;
18 Biobuf in;
19 int debug, matchyear;
20
21 void dates(Tm*);
22 void upper2lower(char*, char*, int);
23 void *emalloc(unsigned int);
24
25 void
26 usage(void)
27 {
28         fprint(2, "usage: calendar [-dy] [-p days] [files ...]\n");
29         exits("usage");
30 }
31
32 void
33 main(int argc, char *argv[])
34 {
35         int i, fd, ahead;
36         long now;
37         char *line;
38         Tm *tm;
39         Date *d;
40         char buf[1024];
41
42         ahead = 0;
43         ARGBEGIN{
44         case 'y':
45                 matchyear = 1;
46                 break;
47         case 'd':
48                 debug = 1;
49                 break;
50         case 'p':
51                 ahead = atoi(EARGF(usage()));
52                 break;
53         default:
54                 usage();
55         }ARGEND;
56
57         /* make a list of dates */
58         now = time(0);
59         tm = localtime(now);
60         dates(tm);
61         now += Secondsperday;
62         tm = localtime(now);
63         dates(tm);
64         if(tm->wday == 6){
65                 now += Secondsperday;
66                 tm = localtime(now);
67                 dates(tm);
68         }
69         if(tm->wday == 0){
70                 now += Secondsperday;
71                 tm = localtime(now);
72                 dates(tm);
73         }
74         if(ahead){
75                 now = time(0);
76                 now += ahead * Secondsperday;
77                 tm = localtime(now);
78                 dates(tm);
79         }
80
81         for(i=0; i<argc || (i==0 && argc==0); i++){
82                 if(i==0 && argc==0)
83                         snprint(buf, sizeof buf,
84                                 "/usr/%s/lib/calendar", getuser());
85                 else
86                         strecpy(buf, buf+sizeof buf, argv[i]);
87                 fd = open(buf, OREAD);
88                 if(fd<0 || Binit(&in, fd, OREAD)<0){
89                         fprint(2, "calendar: can't open %s: %r\n", buf);
90                         exits("open");
91                 }
92
93                 /* go through the file */
94                 while(line = Brdline(&in, '\n')){
95                         line[Blinelen(&in) - 1] = 0;
96                         upper2lower(buf, line, sizeof buf);
97                         for(d=Base; d; d=d->next)
98                                 if(regexec(d->p, buf, 0, 0)){
99                                         print("%s\n", line);
100                                         break;
101                                 }
102                 }
103                 close(fd);
104         }
105         exits("");
106 }
107
108 char *months[] = 
109 {
110         "january",
111         "february",
112         "march",
113         "april",
114         "may",
115         "june",
116         "july",
117         "august",
118         "september",
119         "october",
120         "november",
121         "december"
122 };
123 char *nth[] = {
124         "first", 
125         "second",
126         "third",
127         "fourth",
128         "fifth"
129 };
130 char *days[] = {
131         "sunday",
132         "monday",
133         "tuesday",
134         "wednesday",
135         "thursday",
136         "friday",
137         "saturday"
138 };
139
140 /*
141  * Generate two Date structures.  First has month followed by day;
142  * second has day followed by month.  Link them into list after
143  * last, and return the first.
144  */
145 void
146 dates(Tm *tm)
147 {
148         Date *nd;
149         char mo[128], day[128], buf[128];
150
151         if(utflen(days[tm->wday]) > 3)
152                 snprint(day, sizeof day, "%3.3s(%s)?",
153                         days[tm->wday], days[tm->wday]+3);
154         else
155                 snprint(day, sizeof day, "%3.3s", days[tm->wday]);
156
157         if(utflen(months[tm->mon]) > 3)
158                 snprint(mo, sizeof mo, "%3.3s(%s)?",
159                         months[tm->mon], months[tm->mon]+3);
160         else
161                 snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
162         if (matchyear)
163                 snprint(buf, sizeof buf,
164                         "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
165                         mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100, tm->year%100);
166         else
167                 snprint(buf, sizeof buf,
168                         "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)",
169                         mo, tm->mon+1, tm->mday);
170         if(debug)
171                 print("%s\n", buf);
172
173         nd = emalloc(sizeof(Date));
174         nd->p = regcomp(buf);
175         nd->next = Base;        
176         Base = nd;
177
178         if (matchyear)
179                 snprint(buf, sizeof buf,
180                         "^[\t ]*%d( |\t)+(%s)( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
181                         tm->mday, mo, tm->year+1900, tm->year%100, tm->year%100);
182         else
183                 snprint(buf, sizeof buf,
184                         "^[\t ]*%d( |\t)+(%s)( |\t|$)",
185                         tm->mday, mo);
186         if(debug)
187                 print("%s\n", buf);
188         nd = emalloc(sizeof(Date));
189         nd->p = regcomp(buf);   
190         nd->next = Base;        
191         Base = nd;
192
193         snprint(buf, sizeof buf, "^[\t ]*every[ \t]+%s", day);
194         if(debug)
195                 print("%s\n", buf);
196         nd = emalloc(sizeof(Date));
197         nd->p = regcomp(buf);   
198         nd->next = Base;        
199         Base = nd;
200
201         snprint(buf, sizeof buf, "[\t ]*the[\t ]+%s[\t ]+%s", nth[(tm->mday-1)/7], day);
202         if(debug)
203                 print("%s\n", buf);
204         nd = emalloc(sizeof(Date));
205         nd->p = regcomp(buf);   
206         nd->next = Base;        
207         Base = nd;
208 }
209
210 /*
211  * Copy 'from' to 'to', converting to lower case
212  */
213 void
214 upper2lower(char *to, char *from, int len)
215 {
216         while(--len>0 && *from!='\0')
217                 *to++ = tolower(*from++);
218         *to = 0;
219 }
220
221 /*
222  * Call malloc and check for errors
223  */
224 void*
225 emalloc(unsigned int n)
226 {
227         void *p;
228
229         p = malloc(n);
230         if(p == 0){
231                 fprint(2, "calendar: malloc failed: %r\n");
232                 exits("malloc");
233         }
234         return p;
235 }