Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}