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 main(int argc, char *argv[]) 27 { 28 int i, fd, ahead; 29 long now; 30 char *line; 31 Tm *tm; 32 Date *d; 33 char buf[1024]; 34 35 ahead = 0; 36 ARGBEGIN{ 37 case 'y': 38 matchyear = 1; 39 break; 40 case 'd': 41 debug = 1; 42 break; 43 case 'p': 44 ahead = atoi(ARGF()); 45 break; 46 default: 47 fprint(2, "usage: calendar [-dy] [-p days] [files ...]\n"); 48 exits("usage"); 49 }ARGEND; 50 51 /* make a list of dates */ 52 now = time(0); 53 tm = localtime(now); 54 dates(tm); 55 now += Secondsperday; 56 tm = localtime(now); 57 dates(tm); 58 if(tm->wday == 6){ 59 now += Secondsperday; 60 tm = localtime(now); 61 dates(tm); 62 } 63 if(tm->wday == 0){ 64 now += Secondsperday; 65 tm = localtime(now); 66 dates(tm); 67 } 68 if(ahead){ 69 now = time(0); 70 now += ahead * Secondsperday; 71 tm = localtime(now); 72 dates(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 "/usr/%s/lib/calendar", getuser()); 79 else 80 strecpy(buf, buf+sizeof 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=Base; 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 char *nth[] = { 118 "first", 119 "seccond", 120 "third", 121 "fourth", 122 "fifth" 123 }; 124 char *days[] = { 125 "sunday", 126 "monday", 127 "tuesday", 128 "wednesday", 129 "thursday", 130 "friday", 131 "saturday" 132 }; 133 134 /* 135 * Generate two Date structures. First has month followed by day; 136 * second has day followed by month. Link them into list after 137 * last, and return the first. 138 */ 139 void 140 dates(Tm *tm) 141 { 142 Date *nd; 143 char mo[128], day[128], buf[128]; 144 145 if(utflen(days[tm->wday]) > 3) 146 snprint(day, sizeof day, "%3.3s(%s)?", 147 days[tm->wday], days[tm->wday]+3); 148 else 149 snprint(day, sizeof day, "%3.3s", days[tm->wday]); 150 151 if(utflen(months[tm->mon]) > 3) 152 snprint(mo, sizeof mo, "%3.3s(%s)?", 153 months[tm->mon], months[tm->mon]+3); 154 else 155 snprint(mo, sizeof mo, "%3.3s", months[tm->mon]); 156 if (matchyear) 157 snprint(buf, sizeof buf, 158 "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))", 159 mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100, tm->year%100); 160 else 161 snprint(buf, sizeof buf, 162 "^[\t ]*((%s( |\t)+)|(%d/))%d( |\t|$)", 163 mo, tm->mon+1, tm->mday); 164 if(debug) 165 print("%s\n", buf); 166 167 nd = emalloc(sizeof(Date)); 168 nd->p = regcomp(buf); 169 nd->next = Base; 170 Base = nd; 171 172 if (matchyear) 173 snprint(buf, sizeof buf, 174 "^[\t ]*%d( |\t)+(%s)( |\t|$)(((%d|%d|%02d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))", 175 tm->mday, mo, tm->year+1900, tm->year%100, tm->year%100); 176 else 177 snprint(buf, sizeof buf, 178 "^[\t ]*%d( |\t)+(%s)( |\t|$)", 179 tm->mday, mo); 180 if(debug) 181 print("%s\n", buf); 182 nd = emalloc(sizeof(Date)); 183 nd->p = regcomp(buf); 184 nd->next = Base; 185 Base = nd; 186 187 snprint(buf, sizeof buf, "^[\t ]*every[ \t]+%s", day); 188 if(debug) 189 print("%s\n", buf); 190 nd = emalloc(sizeof(Date)); 191 nd->p = regcomp(buf); 192 nd->next = Base; 193 Base = nd; 194 195 snprint(buf, sizeof buf, "[\t ]*the[\t ]+%s[\t ]+%s", nth[tm->mday/7], day); 196 if(debug) 197 print("%s\n", buf); 198 nd = emalloc(sizeof(Date)); 199 nd->p = regcomp(buf); 200 nd->next = Base; 201 Base = nd; 202 } 203 204 /* 205 * Copy 'from' to 'to', converting to lower case 206 */ 207 void 208 upper2lower(char *to, char *from, int len) 209 { 210 while(--len>0 && *from!='\0') 211 *to++ = tolower(*from++); 212 *to = 0; 213 } 214 215 /* 216 * Call malloc and check for errors 217 */ 218 void* 219 emalloc(unsigned int n) 220 { 221 void *p; 222 223 p = malloc(n); 224 if(p == 0){ 225 fprint(2, "calendar: malloc failed: %r\n"); 226 exits("malloc"); 227 } 228 return p; 229 } 230