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 }