plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

calendar.c (3575B)


      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 Biobuf in;
     18 int debug, matchyear;
     19 
     20 Date *dates(Date**, Tm*);
     21 void upper2lower(char*, char*, int);
     22 void *alloc(unsigned int);
     23 
     24 void
     25 main(int argc, char *argv[])
     26 {
     27 	int i, fd, ahead;
     28 	long now;
     29 	char *line;
     30 	Tm *tm;
     31 	Date *first, *last, *d;
     32 	char buf[1024];
     33 
     34 	ahead = 0;
     35 	ARGBEGIN{
     36 	case 'y':
     37 		matchyear = 1;
     38 		break;
     39 	case 'd':
     40 		debug = 1;
     41 		break;
     42 	case 'p':
     43 		ahead = atoi(ARGF());
     44 		break;
     45 	default:
     46 		fprint(2, "usage: calendar [-y] [-d] [files ...]\n");
     47 		exits("usage");
     48 	}ARGEND;
     49 
     50 	/* make a list of dates */
     51 	now = time(0);
     52 	tm = localtime(now);
     53 	last = nil;
     54 	first = dates(&last, tm);
     55 	now += Secondsperday;
     56 	tm = localtime(now);
     57 	dates(&last, tm);
     58 	if(tm->wday == 6){
     59 		now += Secondsperday;
     60 		tm = localtime(now);
     61 		dates(&last, tm);
     62 	}
     63 	if(tm->wday == 0){
     64 		now += Secondsperday;
     65 		tm = localtime(now);
     66 		dates(&last, tm);
     67 	}
     68 	if(ahead){
     69 		now = time(0);
     70 		now += ahead * Secondsperday;
     71 		tm = localtime(now);
     72 		dates(&last, tm);
     73 	}
     74 
     75 	for(i=0; i<argc || (i==0 && argc==0); i++){
     76 		if(i==0 && argc==0)
     77 			snprint(buf, sizeof(buf),
     78 				"%s/lib/calendar", getenv("HOME"));
     79 		else
     80 			strcpy(buf, argv[i]);
     81 		fd = open(buf, OREAD);
     82 		if(fd<0 || Binit(&in, fd, OREAD)<0){
     83 			fprint(2, "calendar: can't open %s: %r\n", buf);
     84 			exits("open");
     85 		}
     86 
     87 		/* go through the file */
     88 		while(line = Brdline(&in, '\n')){
     89 			line[Blinelen(&in) - 1] = 0;
     90 			upper2lower(buf, line, sizeof buf);
     91 			for(d=first; d; d=d->next)
     92 				if(regexec(d->p, buf, 0, 0)){
     93 					print("%s\n", line);
     94 					break;
     95 				}
     96 		}
     97 		close(fd);
     98 	}
     99 	exits("");
    100 }
    101 
    102 char *months[] =
    103 {
    104 	"january",
    105 	"february",
    106 	"march",
    107 	"april",
    108 	"may",
    109 	"june",
    110 	"july",
    111 	"august",
    112 	"september",
    113 	"october",
    114 	"november",
    115 	"december"
    116 };
    117 
    118 /*
    119  * Generate two Date structures.  First has month followed by day;
    120  * second has day followed by month.  Link them into list after
    121  * last, and return the first.
    122  */
    123 Date*
    124 dates(Date **last, Tm *tm)
    125 {
    126 	Date *first;
    127 	Date *nd;
    128 	char mo[128], buf[128];
    129 
    130 	if(utflen(months[tm->mon]) > 3)
    131 		snprint(mo, sizeof mo, "%3.3s(%s)?",
    132 			months[tm->mon], months[tm->mon]+3);
    133 	else
    134 		snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
    135 	if (matchyear)
    136 		snprint(buf, sizeof buf,
    137 			"(^| |\t)((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
    138 			mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100);
    139 	else
    140 		snprint(buf, sizeof buf,
    141 			"(^| |\t)((%s( |\t)+)|(%d/))%d( |\t|$)",
    142 			mo, tm->mon+1, tm->mday);
    143 	if(debug)
    144 		print("%s\n", buf);
    145 
    146 	first = alloc(sizeof(Date));
    147 	if(*last)
    148 		(*last)->next = first;
    149 	first->p = regcomp(buf);
    150 
    151 	if (matchyear)
    152 		snprint(buf, sizeof buf,
    153 			"(^| |\t)%d( |\t)+(%s)( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
    154 			tm->mday, mo, tm->year+1900, tm->year%100);
    155 	else
    156 		snprint(buf, sizeof buf,
    157 			"(^| |\t)%d( |\t)+(%s)( |\t|$)",
    158 			tm->mday, mo);
    159 	if(debug)
    160 		print("%s\n", buf);
    161 	nd = alloc(sizeof(Date));
    162 	nd->p = regcomp(buf);
    163 	nd->next = 0;
    164 	first->next = nd;
    165 	*last = nd;
    166 
    167 	return first;
    168 }
    169 
    170 /*
    171  * Copy 'from' to 'to', converting to lower case
    172  */
    173 void
    174 upper2lower(char *to, char *from, int len)
    175 {
    176 	while(--len>0 && *from!='\0')
    177 		*to++ = tolower((uchar)*from++);
    178 	*to = 0;
    179 }
    180 
    181 /*
    182  * Call malloc and check for errors
    183  */
    184 void*
    185 alloc(unsigned int n)
    186 {
    187 	void *p;
    188 
    189 	p = malloc(n);
    190 	if(p == 0){
    191 		fprint(2, "calendar: malloc failed: %r\n");
    192 		exits("malloc");
    193 	}
    194 	return p;
    195 }