mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
196 lines
3.5 KiB
C
196 lines
3.5 KiB
C
|
#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
|
||
|
};
|
||
|
|
||
|
Biobuf in;
|
||
|
int debug, matchyear;
|
||
|
|
||
|
Date *dates(Date**, Tm*);
|
||
|
void upper2lower(char*, char*, int);
|
||
|
void *alloc(unsigned int);
|
||
|
|
||
|
void
|
||
|
main(int argc, char *argv[])
|
||
|
{
|
||
|
int i, fd, ahead;
|
||
|
long now;
|
||
|
char *line;
|
||
|
Tm *tm;
|
||
|
Date *first, *last, *d;
|
||
|
char buf[1024];
|
||
|
|
||
|
ahead = 0;
|
||
|
ARGBEGIN{
|
||
|
case 'y':
|
||
|
matchyear = 1;
|
||
|
break;
|
||
|
case 'd':
|
||
|
debug = 1;
|
||
|
break;
|
||
|
case 'p':
|
||
|
ahead = atoi(ARGF());
|
||
|
break;
|
||
|
default:
|
||
|
fprint(2, "usage: calendar [-y] [-d] [files ...]\n");
|
||
|
exits("usage");
|
||
|
}ARGEND;
|
||
|
|
||
|
/* make a list of dates */
|
||
|
now = time(0);
|
||
|
tm = localtime(now);
|
||
|
last = nil;
|
||
|
first = dates(&last, tm);
|
||
|
now += Secondsperday;
|
||
|
tm = localtime(now);
|
||
|
dates(&last, tm);
|
||
|
if(tm->wday == 6){
|
||
|
now += Secondsperday;
|
||
|
tm = localtime(now);
|
||
|
dates(&last, tm);
|
||
|
}
|
||
|
if(tm->wday == 0){
|
||
|
now += Secondsperday;
|
||
|
tm = localtime(now);
|
||
|
dates(&last, tm);
|
||
|
}
|
||
|
if(ahead){
|
||
|
now = time(0);
|
||
|
now += ahead * Secondsperday;
|
||
|
tm = localtime(now);
|
||
|
dates(&last, 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
|
||
|
strcpy(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=first; 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"
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* 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.
|
||
|
*/
|
||
|
Date*
|
||
|
dates(Date **last, Tm *tm)
|
||
|
{
|
||
|
Date *first;
|
||
|
Date *nd;
|
||
|
char mo[128], buf[128];
|
||
|
|
||
|
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)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
|
||
|
mo, tm->mon+1, tm->mday, tm->year+1900, 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);
|
||
|
|
||
|
first = alloc(sizeof(Date));
|
||
|
if(*last)
|
||
|
(*last)->next = first;
|
||
|
first->p = regcomp(buf);
|
||
|
|
||
|
if (matchyear)
|
||
|
snprint(buf, sizeof buf,
|
||
|
"(^| |\t)%d( |\t)+(%s)( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
|
||
|
tm->mday, mo, tm->year+1900, tm->year%100);
|
||
|
else
|
||
|
snprint(buf, sizeof buf,
|
||
|
"(^| |\t)%d( |\t)+(%s)( |\t|$)",
|
||
|
tm->mday, mo);
|
||
|
if(debug)
|
||
|
print("%s\n", buf);
|
||
|
nd = alloc(sizeof(Date));
|
||
|
nd->p = regcomp(buf);
|
||
|
nd->next = 0;
|
||
|
first->next = nd;
|
||
|
*last = nd;
|
||
|
|
||
|
return first;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* 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*
|
||
|
alloc(unsigned int n)
|
||
|
{
|
||
|
void *p;
|
||
|
|
||
|
p = malloc(n);
|
||
|
if(p == 0){
|
||
|
fprint(2, "calendar: malloc failed: %r\n");
|
||
|
exits("malloc");
|
||
|
}
|
||
|
return p;
|
||
|
}
|