Mercurial > bday
comparison bday.c @ 8:19c1ad697022
beautifing :-)
author | meillo@marmaro.de |
---|---|
date | Tue, 18 Dec 2007 14:56:05 +0100 |
parents | b6f4c7fba64a |
children | 4f48b4f86e3d |
comparison
equal
deleted
inserted
replaced
7:b6f4c7fba64a | 8:19c1ad697022 |
---|---|
1 /* | 1 /* |
2 birthday | 2 bday |
3 | 3 |
4 Birthday/Anniversary display on login | 4 Birthday/Anniversary reminder |
5 | 5 |
6 (c) 1996 AS Mortimer | 6 (c) 1996 AS Mortimer |
7 | 7 (c) 2007 markus schnalke <meillo@marmaro.de> |
8 This program is free software; you can redistribute it and/or | 8 |
9 modify it under the terms of the GNU General Public License as | 9 This program is free software; you can redistribute it and/or |
10 published by the Free Software Foundation; either version 2 of the | 10 modify it under the terms of the GNU General Public License as |
11 License, or (at your option) any later version. You may also | 11 published by the Free Software Foundation; either version 2 of the |
12 distribute it under the Artistic License, as comes with Perl. | 12 License, or (at your option) any later version. |
13 | 13 |
14 This program is distributed in the hope that it will be useful, | 14 This program is distributed in the hope that it will be useful, |
15 but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | 17 |
18 You should have received a copy of the GNU General Public License | 18 You should have received a copy of the GNU General Public License |
19 along with this program; if not, write to the Free Software | 19 along with this program; if not, write to the Free Software |
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | 21 |
22 You should also have recieved a copy of the Artistic license with | 22 =============================================================================== |
23 this program. | 23 |
24 | 24 Input is read through standard input. For example: bday < ~/.birthdays |
25 | 25 The input (file) has to have the following format: |
26 We're getting there. At the moment, the file used by default is ~/.birthdays | 26 |
27 under UNIX, or C:\PERSONAL\BDAYS.LST under DOS, but this can be overridden on | 27 text=date flags |
28 the command line. The file has the following format: | 28 |
29 | 29 where: |
30 name/event/whatever=date flags | 30 date is yyyy-mm-dd |
31 where: | 31 flags is ONE or ZERO of |
32 date is dd/mm, dd/mm/yy (assumes 20th century!) or dd/mm/yyyy | 32 bd for a birthday (default) |
33 flags is ONE or ZERO of | 33 ann for an anniversary |
34 o bd for a birthday (default) | 34 ev for an event |
35 o ann for an anniversary | 35 and zero or more of |
36 o ev for an event | 36 w <n> to set the warn-in-advance time to n days (don't include the |
37 and zero or more of | 37 brackets! :) |
38 o w <n> to set the warn-in-advance time to n days (don't include the | 38 to <date> |
39 brackets! :) | 39 for <days> |
40 o to <date> | 40 to specify the length of time taken by an event, for example a holiday. |
41 o for <days> | 41 |
42 to specify the length of time taken by an event, for example a | 42 Lines preceeded by # are treated as comments. |
43 holiday. | 43 |
44 | 44 Note: If you deviate from this format, I cannot guarantee anything about |
45 Comment lines are preceeded by #. | 45 it's behaviour. In most cases, it will just quietly ignore the error, |
46 | 46 which probably isn't ideal behaviour. Oh, well. |
47 Note: If you deviate from this format, I cannot guarantee anything about | 47 |
48 it's behaviour. In most cases, it will just quietly ignore the error, | 48 =============================================================================== |
49 which probably isn't ideal behaviour. Oh, well. | |
50 | |
51 2003/05/20: Automatic reallocation of output buffer in listsrings() by | |
52 Sebastian Schmidt <yath@yath.eu.org>. | |
53 | |
54 */ | 49 */ |
50 | |
51 | |
52 /* standard time to warn in advance, when no explicit w flag is given. */ | |
53 #define DEF_WARN 14 | |
55 | 54 |
56 | 55 |
57 #include <stdarg.h> | 56 #include <stdarg.h> |
58 #include <stdio.h> | 57 #include <stdio.h> |
59 #include <stdlib.h> | 58 #include <stdlib.h> |
62 #include <time.h> | 61 #include <time.h> |
63 #include <unistd.h> | 62 #include <unistd.h> |
64 | 63 |
65 | 64 |
66 | 65 |
67 /* standard time to warn in advance, when no explicit w flag is given. */ | |
68 #define DEF_WARN 14 | |
69 | |
70 /* ========== Global constants and data types */ | 66 /* ========== Global constants and data types */ |
71 | 67 |
72 | 68 |
73 /* month lengths etc */ | 69 /* month lengths etc */ |
74 | |
75 #define isleapyear(y) ((y)%4==0 && ((y)%100 != 0 || (y)%400 == 0)) | 70 #define isleapyear(y) ((y)%4==0 && ((y)%100 != 0 || (y)%400 == 0)) |
76 const unsigned MLENDAT[]; | 71 const unsigned MLENDAT[]; |
77 #define mlen(m,y) (MLENDAT[(m)-1] != -1 ? MLENDAT[(m)-1] : (isleapyear((y)) ? 29 : 28)) | 72 #define mlen(m,y) (MLENDAT[(m)-1] != -1 ? MLENDAT[(m)-1] : (isleapyear((y)) ? 29 : 28)) |
78 #define before(a,b) ((a).month < (b).month || ((a).month == (b).month && (a).day < (b).day)) | 73 #define before(a,b) ((a).month < (b).month || ((a).month == (b).month && (a).day < (b).day)) |
79 #define ydelta(a,b) ((int) (b).year - (a).year + before((a),(b))) | 74 #define ydelta(a,b) ((int) (b).year - (a).year + before((a),(b))) |
80 | 75 |
81 /* -------- modifier flags */ | 76 /* -------- modifier flags */ |
82 | |
83 #define F_MTYPE 0x07 | 77 #define F_MTYPE 0x07 |
84 #define F_TBIRTHDAY 1 | 78 #define F_TBIRTHDAY 1 |
85 #define F_TANNIVERSARY 2 | 79 #define F_TANNIVERSARY 2 |
86 #define F_TEVENT 3 | 80 #define F_TEVENT 3 |
87 | 81 |
89 #define F_MIMMEDIATE 0x24 | 83 #define F_MIMMEDIATE 0x24 |
90 #define F_WTIME_P 0x08 | 84 #define F_WTIME_P 0x08 |
91 #define F_FORDAYS 0x16 | 85 #define F_FORDAYS 0x16 |
92 #define F_TODATE 0x24 | 86 #define F_TODATE 0x24 |
93 | 87 |
94 struct _ftable {char *txt; unsigned flag;}; | 88 struct _ftable {char* txt; unsigned flag;}; |
95 | 89 |
96 const struct _ftable FTABLE[]; | 90 const struct _ftable FTABLE[]; |
97 | 91 |
98 struct date { | 92 struct date { |
99 unsigned day; | 93 unsigned day; |
100 unsigned month; | 94 unsigned month; |
101 unsigned year; | 95 unsigned year; |
102 }; | 96 }; |
103 | 97 |
104 struct event { | 98 struct event { |
105 char *text; | 99 char* text; |
106 struct date date; | 100 struct date date; |
107 struct date enddate; | 101 struct date enddate; |
108 int warn; | 102 int warn; |
109 }; | 103 }; |
110 | 104 |
112 | 106 |
113 /* ========== Global Variables */ | 107 /* ========== Global Variables */ |
114 | 108 |
115 struct event* readlist(void); | 109 struct event* readlist(void); |
116 void gettoday(void); | 110 void gettoday(void); |
117 unsigned delta(struct date *); | 111 unsigned delta(struct date*); |
118 unsigned ddiff(struct date *D1, struct date *D2); | 112 unsigned ddiff(struct date* D1, struct date* D2); |
119 void liststrings(struct event* evl, prnfunc outf); | 113 void liststrings(struct event* evl, prnfunc outf); |
120 char *tdelta(struct date *d); | 114 char* tdelta(struct date* d); |
121 char *ttime(int yr, int mn, int wk, int dy); | 115 char* ttime(int yr, int mn, int wk, int dy); |
122 | 116 int skptok(int j, char* ptr); |
123 int skptok(int j, char *ptr); | 117 int evcmp(const void* e1, const void* e2); |
124 int evcmp(const void *e1, const void *e2); | |
125 | 118 |
126 | 119 |
127 struct date today; | 120 struct date today; |
128 int iDWarn = DEF_WARN; | 121 int iDWarn = DEF_WARN; |
129 | 122 |
157 exit(1); | 150 exit(1); |
158 } | 151 } |
159 return value; | 152 return value; |
160 } | 153 } |
161 | 154 |
162 | |
163 void* xrealloc (void* ptr, size_t size) { | 155 void* xrealloc (void* ptr, size_t size) { |
164 register void* value = realloc (ptr, size); | 156 register void* value = realloc (ptr, size); |
165 if (value == 0) { | 157 if (value == 0) { |
166 fprintf(stderr, "virtual memory exhausted\n"); | 158 fprintf(stderr, "virtual memory exhausted\n"); |
167 exit(1); | 159 exit(1); |
168 } | 160 } |
169 return value; | 161 return value; |
170 } | 162 } |
171 | 163 |
164 | |
172 /* ========== */ | 165 /* ========== */ |
173 | |
174 | 166 |
175 | 167 |
176 /* like strcat(), but lets the buffer automagically grow :-) | 168 /* like strcat(), but lets the buffer automagically grow :-) |
177 * (needs local variable "size" with the buffer size) */ | 169 * (needs local variable "size" with the buffer size) */ |
178 #define append(where, what) do { \ | 170 #define append(where, what) do { \ |
185 | 177 |
186 /* ========== */ | 178 /* ========== */ |
187 | 179 |
188 /* returns delta(d) in days, weeks, months, etc | 180 /* returns delta(d) in days, weeks, months, etc |
189 * the returned buffer is malloc()ed, do not forget to free() it */ | 181 * the returned buffer is malloc()ed, do not forget to free() it */ |
190 char *tdelta(struct date *d) { | 182 char* tdelta(struct date* d) { |
191 int dy, wk, mn, yr; | 183 int dy, wk, mn, yr; |
192 char *tmp; | 184 char* tmp; |
193 char *buf = xmalloc(128); | 185 char* buf = xmalloc(128); |
194 int size = 128; | 186 int size = 128; |
195 *buf = 0; | 187 *buf = 0; |
196 | 188 |
197 switch (delta(d)) { | 189 switch (delta(d)) { |
198 case 0: | 190 case 0: |
201 case 1: | 193 case 1: |
202 append(buf, "tomorrow"); | 194 append(buf, "tomorrow"); |
203 return buf; | 195 return buf; |
204 default: | 196 default: |
205 /* like delta(), we ignore the year */ | 197 /* like delta(), we ignore the year */ |
206 yr=-before(*d,today); | 198 yr = -before(*d, today); |
207 mn=d->month - today.month; | 199 mn = d->month - today.month; |
208 dy=d->day - today.day; | 200 dy = d->day - today.day; |
209 | 201 |
210 if (dy < 0) { | 202 if (dy < 0) { |
211 dy += mlen(today.month, today.year); | 203 dy += mlen(today.month, today.year); |
212 mn--; | 204 mn--; |
213 } | 205 } |
359 | 351 |
360 | 352 |
361 | 353 |
362 /* sort the events by the time before the next time they come up, putting those | 354 /* sort the events by the time before the next time they come up, putting those |
363 where the start has passed but we are still in the time-period first */ | 355 where the start has passed but we are still in the time-period first */ |
364 int evcmp(const void *p1, const void *p2) { | 356 int evcmp(const void* p1, const void* p2) { |
365 struct event *e1=(struct event *)p1; | 357 struct event* e1=(struct event*) p1; |
366 struct event *e2=(struct event *)p2; | 358 struct event* e2=(struct event*) p2; |
367 unsigned d1,d2; | 359 unsigned d1, d2; |
368 | 360 |
369 /* if the delta for the enddate is less than that for the start date, then we | 361 /* if the delta for the enddate is less than that for the start date, then we |
370 have passed the start date but not yet the end date, and so we should | 362 have passed the start date but not yet the end date, and so we should |
371 display the enddate; otherwise, we should display the start date */ | 363 display the enddate; otherwise, we should display the start date */ |
372 | 364 |
377 d2=delta(&(e2->date)); | 369 d2=delta(&(e2->date)); |
378 if (e2->enddate.day && delta(&(e2->enddate)) < d2) | 370 if (e2->enddate.day && delta(&(e2->enddate)) < d2) |
379 d2=delta(&(e2->enddate)); | 371 d2=delta(&(e2->enddate)); |
380 | 372 |
381 if (d1 < d2) return -1; | 373 if (d1 < d2) return -1; |
382 if (d1 > d2) return 1; | 374 if (d1 > d2) return 1; |
383 | 375 |
384 return strcmp(e1->text, e2->text); | 376 return strcmp(e1->text, e2->text); |
385 } | 377 } |
386 | 378 |
387 | 379 |
389 | 381 |
390 | 382 |
391 | 383 |
392 /* difference in days between two dates */ | 384 /* difference in days between two dates */ |
393 /* it is assumed that D1 < D2, and so the result is always positive */ | 385 /* it is assumed that D1 < D2, and so the result is always positive */ |
394 unsigned ddiff(struct date *D1, struct date *D2) { | 386 unsigned ddiff(struct date* D1, struct date* D2) { |
395 struct date d1,d2; | 387 struct date d1, d2; |
396 int dd,m; | 388 int dd, m; |
397 | 389 |
398 /* make working copies */ | 390 /* make working copies */ |
399 d1=*D1; | 391 d1 = *D1; |
400 d2=*D2; | 392 d2 = *D2; |
401 | 393 |
402 /* sort out zero years */ | 394 /* sort out zero years */ |
403 if (d1.year == 0 || d2.year==0) { | 395 if (d1.year == 0 || d2.year==0) { |
404 if (d1.year != d2.year) { | 396 if (d1.year != d2.year) { |
405 if (d1.year == 0) { | 397 if (d1.year == 0) { |
406 if (before(d1,d2)) | 398 if (before(d1,d2)) |
407 d1.year=d2.year; | 399 d1.year = d2.year; |
408 else | 400 else |
409 d1.year=d2.year-1; | 401 d1.year = d2.year - 1; |
410 } else { | 402 } else { |
411 if (before(d1,d2)) | 403 if (before(d1, d2)) |
412 d2.year=d1.year; | 404 d2.year = d1.year; |
413 else | 405 else |
414 d2.year=d1.year+1; | 406 d2.year = d1.year + 1; |
415 } | 407 } |
416 } else { /* both years zero */ | 408 } else { /* both years zero */ |
417 if (before(d1,d2)) | 409 if (before(d1, d2)) |
418 d1.year=d2.year=today.year; | 410 d1.year = d2.year = today.year; |
419 else { | 411 else { |
420 d1.year=today.year; | 412 d1.year = today.year; |
421 d2.year=d1.year+1; | 413 d2.year = d1.year + 1; |
422 } | 414 } |
423 } | 415 } |
424 } | 416 } |
425 | 417 |
426 /* now we can actually do the comparison ... */ | 418 /* now we can actually do the comparison ... */ |
427 dd=0; | 419 dd = 0; |
428 | 420 |
429 /* to start with, we work in months */ | 421 /* to start with, we work in months */ |
430 for (m=d1.month; m < d2.month + (d2.year-d1.year)*12; m++) | 422 for (m=d1.month; m < d2.month + (d2.year-d1.year)*12; m++) |
431 dd += mlen(((m-1)%12)+1, d1.year + m/12); | 423 dd += mlen(((m-1)%12)+1, d1.year + m/12); |
432 | 424 |
458 d.year = 1; | 450 d.year = 1; |
459 } else { | 451 } else { |
460 d.year = 0; | 452 d.year = 0; |
461 } | 453 } |
462 | 454 |
463 for (mn = today.month, dt=0; mn < d.month + 12*d.year; mn++) | 455 for (mn = today.month, dt=0; mn < d.month + 12*d.year; mn++) { |
464 dt += mlen(((mn-1)%12) + 1,today.year + mn/12); | 456 dt += mlen(((mn-1)%12) + 1,today.year + mn/12); |
457 } | |
465 | 458 |
466 dt -= today.day; | 459 dt -= today.day; |
467 dt += d.day; | 460 dt += d.day; |
468 | 461 |
469 return dt; | 462 return dt; |