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 } 236