bday

changeset 16:79d22407a6be

a lot of refactoring
author markus schnalke <meillo@marmaro.de>
date Mon, 24 Feb 2014 21:11:38 +0100
parents 032af48d590b
children d18a3b2b76bd
files Makefile bday.c
diffstat 2 files changed, 197 insertions(+), 210 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Mon Feb 24 17:46:57 2014 +0100
     1.2 +++ b/Makefile	Mon Feb 24 21:11:38 2014 +0100
     1.3 @@ -1,81 +1,53 @@
     1.4  # bday by meillo@marmaro.de
     1.5  
     1.6  
     1.7 -NAME=bday
     1.8 -VERSION = 0.1
     1.9 -NV=${NAME}-${VERSION}
    1.10 +VERSION = 0.2
    1.11  
    1.12 -DOCS=COPYRIGHT COPYING ChangeLog TODO examples
    1.13 +DOCS=COPYRIGHT COPYING ChangeLog
    1.14  
    1.15  # paths
    1.16 -PREFIX = /usr
    1.17 +PREFIX = /usr/local
    1.18  BINDIR = ${PREFIX}/bin
    1.19  MANDIR = ${PREFIX}/share/man
    1.20  
    1.21 -SRC=bday.c
    1.22 -OBJ=$(SRC:.c=.o)
    1.23 -
    1.24  CFLAGS=-O2 -Wall
    1.25  
    1.26  all: build
    1.27 +build: bday
    1.28  
    1.29 -build: ${NAME}
    1.30 -
    1.31 -${NAME}: $(OBJ)
    1.32 -	$(CC) $(LDFLAGS) $(OBJ) -o $@
    1.33 -
    1.34 -car: clean all
    1.35 +bday: bday.o
    1.36 +	$(CC) $(LDFLAGS) bday.o -o $@
    1.37  
    1.38  dist: build changelog
    1.39 -	@mkdir -p ${NV}
    1.40 -	@cp -rf ${NAME} ${SRC} ${NAME}.1 Makefile ${DOCS} ${NV}
    1.41 -	@tar -czhof ${NV}.tar.gz ${NV}
    1.42 -	@rm -rf ${NV}
    1.43 -
    1.44 -deb: dist
    1.45 -	@mkdir -p Packages
    1.46 -	@cp ${NV}.tar.gz Packages/
    1.47 -	@( \
    1.48 -		cd Packages/ ;\
    1.49 -		tar -xzf ${NV}.tar.gz ;\
    1.50 -		mv ${NV}.tar.gz ${NAME}_${VERSION}.orig.tar.gz ;\
    1.51 -		cd ${NV}/ ;\
    1.52 -		cp -r ../../debian/ . ;\
    1.53 -		debuild -sa ;\
    1.54 -	 )
    1.55 +	@mkdir -p bday-${VERSION}
    1.56 +	@cp bday bday.c bday.1 Makefile ${DOCS} bday-${VERSION}
    1.57 +	@tar -czhf bday-${VERSION}.tar.gz bday-${VERSION}
    1.58 +	@rm -rf bday-${VERSION}
    1.59  
    1.60  changelog:
    1.61  	@echo generating changelog from mercurial log
    1.62  	@hg log -v --style changelog > ChangeLog
    1.63  
    1.64  install:
    1.65 -	@echo installing executable file to ${DESTDIR}${BINDIR}
    1.66 -	@mkdir -p ${DESTDIR}${BINDIR}
    1.67 -	@cp ${NAME} ${DESTDIR}${BINDIR}
    1.68 -	@chmod 755 ${DESTDIR}${BINDIR}/${NAME}
    1.69 -	@echo installing manual page to ${DESTDIR}${MANDIR}/man1
    1.70 -	@mkdir -p ${DESTDIR}${MANDIR}/man1
    1.71 -	@sed 's/VERSION/${VERSION}/g' < ${NAME}.1 > ${DESTDIR}${MANDIR}/man1/${NAME}.1
    1.72 -	@chmod 644 ${DESTDIR}${MANDIR}/man1/${NAME}.1
    1.73 +	@echo installing executable file to ${BINDIR}
    1.74 +	@mkdir -p ${BINDIR}
    1.75 +	@cp bday ${BINDIR}
    1.76 +	@chmod 755 ${BINDIR}/bday
    1.77 +	@echo installing manual page to ${MANDIR}/man1
    1.78 +	@mkdir -p ${MANDIR}/man1
    1.79 +	@sed 's/VERSION/${VERSION}/g' <bday.1 >${MANDIR}/man1/bday.1
    1.80 +	@chmod 644 ${MANDIR}/man1/bday.1
    1.81  
    1.82  uninstall:
    1.83 -	@echo removing executable file from ${DESTDIR}${BINDIR}
    1.84 -	@rm -f ${DESTDIR}${BINDIR}/${NAME}
    1.85 -	@echo removing manual page from ${DESTDIR}${MANDIR}/man1
    1.86 -	@rm -f ${DESTDIR}${MANDIR}/man1/${NAME}.1
    1.87 +	@echo removing executable file from ${BINDIR}
    1.88 +	@rm -f ${BINDIR}/bday
    1.89 +	@echo removing manual page from ${MANDIR}/man1
    1.90 +	@rm -f ${MANDIR}/man1/bday.1
    1.91  
    1.92  
    1.93  clean:
    1.94  	rm -f *.o
    1.95 -
    1.96  realclean: clean
    1.97 -	rm -f ${NAME}
    1.98 -
    1.99 +	rm -f bday
   1.100  distclean: realclean
   1.101 -	@rm -f ${NAME}-*.tar.gz ChangeLog
   1.102 -
   1.103 -debclean: distclean
   1.104 -	@cd Packages/${NV}/ ; debuild clean ;
   1.105 -
   1.106 -
   1.107 -.PHONY: all dist deb changelog clean distclean debclean build install uninstall
   1.108 +	@rm -f bday-*.tar.gz ChangeLog
     2.1 --- a/bday.c	Mon Feb 24 17:46:57 2014 +0100
     2.2 +++ b/bday.c	Mon Feb 24 21:11:38 2014 +0100
     2.3 @@ -26,21 +26,21 @@
     2.4  Input is read through standard input. For example: bday < ~/.birthdays
     2.5  The input (file) has to have the following format:
     2.6  
     2.7 -text=date flags
     2.8 +date flags text
     2.9  
    2.10  where:
    2.11 -	date is yyyy-mm-dd
    2.12 +	date is YYYY-MM-DD
    2.13  	flags is ONE or ZERO of
    2.14 -		bd  for a birthday (default)
    2.15 -		ann for an anniversary
    2.16 -		ev  for an event
    2.17 +		#ann for an anniversary
    2.18 +		#ev  for an event
    2.19  	and zero or more of
    2.20 -		w <n> to set the warn-in-advance time to n days
    2.21 +		#w<n> to set the warn-in-advance time to n days
    2.22  			(don't include the brackets! :)
    2.23 -		to <date>
    2.24 -		for <days>
    2.25 +		#to<date>
    2.26 +		#for<days>
    2.27  			to specify the length of time taken by an
    2.28 -			event, for example a holiday.
    2.29 +			event, for example a holiday
    2.30 +	separated by spaces.
    2.31  
    2.32  Lines preceeded by # are treated as comments.
    2.33  
    2.34 @@ -69,16 +69,8 @@
    2.35  /* ========== Global constants and data types */
    2.36  
    2.37  
    2.38 -/* month lengths etc */
    2.39 -#define isleapyear(y) ((y)%4==0 && ((y)%100 != 0 || (y)%400 == 0))
    2.40 -const unsigned MLENDAT[];
    2.41 -#define mlen(m,y) (MLENDAT[(m)-1] != -1 ? MLENDAT[(m)-1] : (isleapyear((y)) ? 29 : 28))
    2.42 -#define before(a,b) ((a).month < (b).month || ((a).month == (b).month && (a).day < (b).day))
    2.43 -#define ydelta(a,b) ((int) (b).year - (a).year + before((a),(b)))
    2.44 -
    2.45  /* -------- modifier flags */
    2.46  #define F_MTYPE 0x07
    2.47 -#define F_TBIRTHDAY 1
    2.48  #define F_TANNIVERSARY 2
    2.49  #define F_TEVENT 3
    2.50  
    2.51 @@ -88,8 +80,10 @@
    2.52  #define F_FORDAYS 0x16
    2.53  #define F_TODATE 0x24
    2.54  
    2.55 -struct _ftable {char* txt; unsigned flag;};
    2.56 -
    2.57 +struct _ftable {
    2.58 +	char* txt;
    2.59 +	unsigned flag;
    2.60 +};
    2.61  const struct _ftable FTABLE[];
    2.62  
    2.63  struct date {
    2.64 @@ -105,33 +99,29 @@
    2.65  	int warn;
    2.66  };
    2.67  
    2.68 -typedef int (*prnfunc)(const char *);
    2.69 -
    2.70  /* ========== Global Variables */
    2.71  
    2.72  struct event *readlist(void);
    2.73  void gettoday(void);
    2.74  unsigned delta(struct date *);
    2.75  unsigned ddiff(struct date *D1, struct date *D2);
    2.76 -void liststrings(struct event *evl, prnfunc outf);
    2.77 +void liststrings(struct event *evl);
    2.78  char *tdelta(struct date *d);
    2.79  char *ttime(int yr, int mn, int wk, int dy);
    2.80 -int skptok(int j, char *ptr);
    2.81 +char *skptok(char *ptr);
    2.82  int evcmp(const void *e1, const void *e2);
    2.83  
    2.84  
    2.85  struct date today;
    2.86 -int iDWarn = DEF_WARN;
    2.87 +int def_warn = DEF_WARN;
    2.88  
    2.89 -const unsigned MLENDAT[] = {31,-1,31,30,31,30,31,31,30,31,30,31};
    2.90  
    2.91  const struct _ftable FTABLE[] = {
    2.92 -	{"bd", F_TBIRTHDAY},
    2.93 -	{"ann",F_TANNIVERSARY},
    2.94 -	{"ev", F_TEVENT},
    2.95 -	{"w",  F_WTIME_P},
    2.96 -	{"to", F_TODATE},
    2.97 -	{"for", F_FORDAYS},
    2.98 +	{"#ann",F_TANNIVERSARY},
    2.99 +	{"#ev", F_TEVENT},
   2.100 +	{"#w",  F_WTIME_P},
   2.101 +	{"#to", F_TODATE},
   2.102 +	{"#for", F_FORDAYS},
   2.103  	{NULL, 0}
   2.104  };
   2.105  
   2.106 @@ -174,18 +164,60 @@
   2.107  
   2.108  /*
   2.109  like strcat(), but lets the buffer automagically grow :-)
   2.110 -(needs local variable "size" with the buffer size)
   2.111  */
   2.112 -#define append(where, what) do {                            \
   2.113 -	if (strlen(what) > (size - strlen(where))) {          \
   2.114 -		xrealloc(where, size + 128 + strlen(what));   \
   2.115 -		size += 128 + strlen(what);                   \
   2.116 -	}                                                     \
   2.117 -	strcat(where, what);                                  \
   2.118 -} while(0)
   2.119 +int
   2.120 +append(char *where, int size, char *what)
   2.121 +{
   2.122 +	if (strlen(what) > ((size) - strlen(where))) {
   2.123 +		xrealloc(where, (size) + 128 + strlen(what));
   2.124 +		size += 128 + strlen(what);
   2.125 +	}
   2.126 +	strcat(where, what);
   2.127 +	return size;
   2.128 +}
   2.129  
   2.130  /* ========== */
   2.131  
   2.132 +
   2.133 +int
   2.134 +before(struct date a, struct date b)
   2.135 +{
   2.136 +	if (a.month < b.month) {
   2.137 +		return 1;
   2.138 +	} else if (a.month == b.month && a.day < b.day) {
   2.139 +		return 1;
   2.140 +	} else {
   2.141 +		return 0;
   2.142 +	}
   2.143 +}
   2.144 +
   2.145 +int
   2.146 +ydelta(struct date a, struct date b)
   2.147 +{
   2.148 +	return b.year - a.year + before(a, b);
   2.149 +}
   2.150 +
   2.151 +/*
   2.152 +returns the length of the given month
   2.153 +*/
   2.154 +int
   2.155 +mlen(int month, int year)
   2.156 +{
   2.157 +	unsigned mlendat[] = {31,0,31,30,31,30,31,31,30,31,30,31};
   2.158 +
   2.159 +	if (mlendat[month - 1]) {
   2.160 +		return mlendat[month - 1];
   2.161 +	} else {
   2.162 +		if (year%4==0 && (year%100!=0 || year%400==0)) {
   2.163 +			return 29;
   2.164 +		} else {
   2.165 +			return 28;
   2.166 +		}
   2.167 +	}
   2.168 +}
   2.169 +
   2.170 +
   2.171 +
   2.172  /*
   2.173  returns delta(d) in days, weeks, months, etc
   2.174  the returned buffer is malloc()ed, do not forget to free() it
   2.175 @@ -201,10 +233,10 @@
   2.176  	*buf = 0;
   2.177  	switch (delta(d)) {
   2.178  	case 0:
   2.179 -		append(buf, "today");
   2.180 +		size = append(buf, size, "TODAY");
   2.181  		return buf;
   2.182  	case 1:
   2.183 -		append(buf, "tomorrow");
   2.184 +		size = append(buf, size, "Tomorrow");
   2.185  		return buf;
   2.186  	default:
   2.187  		/* like delta(), we ignore the year */
   2.188 @@ -224,9 +256,9 @@
   2.189  		wk = (dy / 7);
   2.190  		dy %= 7;
   2.191  
   2.192 -		append(buf, "in ");
   2.193 +		size = append(buf, size, "In ");
   2.194  		tmp = ttime(yr, mn, wk, dy);
   2.195 -		append(buf, tmp);
   2.196 +		size = append(buf, size, tmp);
   2.197  		free(tmp);
   2.198  
   2.199  		return buf;
   2.200 @@ -237,66 +269,46 @@
   2.201  
   2.202  
   2.203  
   2.204 -/*
   2.205  void
   2.206 -donum(n,txt)
   2.207 +donum(char *buf, int size, int n, char *txt, int *terms)
   2.208  {
   2.209 -	if (n > 0) {
   2.210 -		snprintf(tmp, sizeof(tmp), "%d", n);
   2.211 -		append(buf, tmp);
   2.212 -		append(buf, " " txt);
   2.213 -		if (n != 1)
   2.214 -			append(buf, "s");
   2.215 -		terms--;
   2.216 -		if (orgterms > 1) {
   2.217 -			if (terms == 1)
   2.218 -				append(buf, " and ");
   2.219 -			else if (terms > 1)
   2.220 -				append(buf, ", ");
   2.221 -		}
   2.222 +	char tmp[128];
   2.223 +
   2.224 +	if (n <= 0) {
   2.225 +		return;
   2.226 +	}
   2.227 +	snprintf(tmp, sizeof(tmp), "%d", n);
   2.228 +	size = append(buf, size, tmp);
   2.229 +	size = append(buf, size, " ");
   2.230 +	size = append(buf, size, txt);
   2.231 +	if (n != 1) {
   2.232 +		size = append(buf, size, "s");
   2.233 +	}
   2.234 +	if (--*terms == 1) {
   2.235 +		size = append(buf, size, " and ");
   2.236 +	} else if (*terms > 1) {
   2.237 +		size = append(buf, size, ", ");
   2.238  	}
   2.239  }
   2.240 -*/
   2.241 -
   2.242 -
   2.243 -#define donum(n,txt) do {                       \
   2.244 -	if (n > 0) {                              \
   2.245 -		snprintf(tmp, sizeof(tmp), "%d", n);   \
   2.246 -		append(buf, tmp);                      \
   2.247 -		append(buf, " " txt);                  \
   2.248 -		if (n != 1)                            \
   2.249 -			append(buf, "s");                   \
   2.250 -		terms--;                               \
   2.251 -		if (orgterms > 1) {                    \
   2.252 -			if (terms == 1)                     \
   2.253 -				append(buf, " and ");            \
   2.254 -			else if (terms > 1)                 \
   2.255 -				append(buf, ", ");               \
   2.256 -		}                                      \
   2.257 -	}                                         \
   2.258 -} while(0)
   2.259  
   2.260  
   2.261  /* returns allocated buffer, don't forget to free() */
   2.262  char *
   2.263  ttime(int yr, int mn, int wk, int dy)
   2.264  {
   2.265 -	char *buf = xmalloc(128);
   2.266  	int size = 128;
   2.267 -	int terms, orgterms;
   2.268 -	char tmp[128];
   2.269 +	char *buf = xmalloc(size);
   2.270 +	int terms = (yr!=0) + (mn!=0) + (wk!=0) + (dy!=0);
   2.271  
   2.272 -	*buf = 0; /* Initialize buffer */
   2.273 -	terms = orgterms = (yr!=0) + (mn!=0) + (wk!=0) + (dy!=0);
   2.274 +	*buf = '\0'; /* Initialize buffer */
   2.275  
   2.276 -	donum(yr, "year");
   2.277 -	donum(mn, "month");
   2.278 -	donum(wk, "week");
   2.279 -	donum(dy, "day");
   2.280 +	donum(buf, size, yr, "year", &terms);
   2.281 +	donum(buf, size, mn, "month", &terms);
   2.282 +	donum(buf, size, wk, "week", &terms);
   2.283 +	donum(buf, size, dy, "day", &terms);
   2.284  
   2.285  	return buf;
   2.286  }
   2.287 -#undef donum
   2.288  
   2.289  
   2.290  
   2.291 @@ -308,58 +320,60 @@
   2.292  the string to a function.
   2.293  */
   2.294  void
   2.295 -liststrings(struct event *evl, prnfunc outf)
   2.296 +liststrings(struct event *evl)
   2.297  {
   2.298  	int i,j;
   2.299  	char *buf, *tmp;
   2.300  	int size;
   2.301  
   2.302 -	for (i = 0; evl[i].text != NULL; i++) {
   2.303 -		buf = xmalloc(128);
   2.304 +	for (i=0; evl[i].text; i++) {
   2.305 +		size = 128;
   2.306 +		buf = xmalloc(size);
   2.307  		*buf = '\0';
   2.308 -		size = 128;
   2.309  
   2.310  		if (evl[i].warn == -1 && delta(&(evl[i].date))==0) {
   2.311 -			 append(buf, evl[i].text);
   2.312 +			 size = append(buf, size, evl[i].text);
   2.313  		} else if (evl[i].enddate.day == 0) {
   2.314 +			
   2.315  			if (delta(&(evl[i].date)) <= evl[i].warn) {
   2.316 -				append(buf, evl[i].text);
   2.317 -				append(buf, " ");
   2.318  				tmp = tdelta(&(evl[i].date));
   2.319 -				append(buf, tmp);
   2.320 +				size = append(buf, size, tmp);
   2.321 +				size = append(buf, size, ":  ");
   2.322 +				size = append(buf, size, evl[i].text);
   2.323  				free(tmp);
   2.324  			}
   2.325  		} else {
   2.326  			if (delta(&(evl[i].date)) <= evl[i].warn) {
   2.327 -				append(buf, evl[i].text);
   2.328 -				append(buf, " for ");
   2.329 -				/* +1 because, if the difference between two dates is one day,
   2.330 -				   then the length of an event on those days is two days */
   2.331 +				size = append(buf, size, evl[i].text);
   2.332 +				size = append(buf, size, " for ");
   2.333 +				/* +1 because, if the difference between
   2.334 +				two dates is one day, then the length of
   2.335 +				an event on those days is two days */
   2.336  				j = ddiff(&(evl[i].date),&(evl[i].enddate)) + 1;
   2.337  				tmp = ttime(0, 0, j/7, j%7);
   2.338 -				append(buf, tmp);
   2.339 +				size = append(buf, size, tmp);
   2.340  				free(tmp);
   2.341 -				append(buf, " ");
   2.342 +				size = append(buf, size, " ");
   2.343  				tmp = tdelta(&(evl[i].date));
   2.344 -				append(buf, tmp);
   2.345 +				size = append(buf, size, tmp);
   2.346  			} else if (delta(&(evl[i].enddate)) <= evl[i].warn) {
   2.347 -				append(buf, evl[i].text);
   2.348 -				append(buf, " ");
   2.349 +				size = append(buf, size, evl[i].text);
   2.350 +				size = append(buf, size, " ");
   2.351  				j = delta(&(evl[i].enddate));
   2.352  				if (j) {
   2.353 -					append(buf, "for ");
   2.354 +					size = append(buf, size, "for ");
   2.355  					tmp = ttime(0, 0, j/7, j%7);
   2.356 -					append(buf, tmp);
   2.357 +					size = append(buf, size, tmp);
   2.358  					free(tmp);
   2.359 -					append(buf, " longer");
   2.360 +					size = append(buf, size, " longer");
   2.361  				} else {
   2.362 -					append(buf, "finishes today");
   2.363 +					size = append(buf, size, "finishes today");
   2.364  				}
   2.365  			}
   2.366  		}
   2.367  		if (*buf) {
   2.368 -			append(buf, ".");
   2.369 -			outf(buf);
   2.370 +			size = append(buf, size, ".");
   2.371 +			puts(buf);
   2.372  		}
   2.373  		free(buf);
   2.374  	}
   2.375 @@ -534,7 +548,7 @@
   2.376  	int i, j, k, l, d;
   2.377  	struct event *evl;
   2.378  	char buf[1024], buf2[1024];
   2.379 -	char *ptr;
   2.380 +	char *ptr, *cp;
   2.381  	unsigned flags;
   2.382  
   2.383  	/* initialise */
   2.384 @@ -550,46 +564,48 @@
   2.385  		}
   2.386  
   2.387  		/* parse string in buf */
   2.388 -		ptr = strrchr(buf, '='); /* allow '=' in text */
   2.389 +
   2.390 +		ptr = strchr(buf, ' ');  /* start of text */
   2.391  
   2.392  		/* not a valid line, so ignore it! Cool, huh? */
   2.393  		/* Attention: only recognizes lines without '=' */
   2.394 -		if (ptr == NULL) {
   2.395 -			fprintf(stderr, "WARNING: Invalid line in input:\n%s", buf);
   2.396 +		if (!ptr) {
   2.397 +			fprintf(stderr, "WARNING: Invalid input line:\n\t%s", buf);
   2.398  			i--;
   2.399  			continue;
   2.400  		}
   2.401  
   2.402 -		*(ptr++) = 0;
   2.403 +		*(ptr++) = '\0';
   2.404 +		ptr[strlen(ptr)-1] = '\0';
   2.405  
   2.406 -		j = sscanf(ptr, "%u-%u-%u", &(evl[i].date.year),
   2.407 +		j = sscanf(buf, "%u-%u-%u", &(evl[i].date.year),
   2.408  				&(evl[i].date.month), &(evl[i].date.day));
   2.409 -		/* ... unless it wasn't read, in which case set it to zero */
   2.410 -		if (j==2) {
   2.411 -			evl[i].date.year = 0;
   2.412 +		if (j != 3) {
   2.413 +			fprintf(stderr, "Error: Invalid date:\t%s\n", buf);
   2.414 +			i--;
   2.415 +			continue;
   2.416  		}
   2.417  
   2.418 -
   2.419  		/* parse flags */
   2.420  
   2.421 -		evl[i].warn = iDWarn;
   2.422 +		evl[i].warn = def_warn;
   2.423  		evl[i].enddate.day = 0;
   2.424  		evl[i].enddate.month = 0;
   2.425  		evl[i].enddate.year = 0;
   2.426  
   2.427  		flags = 0;
   2.428  		j = 0;
   2.429 -
   2.430 -		while(j = skptok(j, ptr), ptr[j] != 0) {
   2.431 -			for (k = 0; FTABLE[k].txt != NULL && strncmp(FTABLE[k].txt, ptr + j, strlen(FTABLE[k].txt)); k++) {
   2.432 +		cp = skptok(ptr);
   2.433 +		for (cp=ptr; *cp && *cp=='#'; cp=skptok(cp)) {
   2.434 +			for (k = 0; FTABLE[k].txt && strncmp(FTABLE[k].txt, cp, strlen(FTABLE[k].txt)); k++) {
   2.435  			}
   2.436  
   2.437  			switch (FTABLE[k].flag) {
   2.438 -			case F_WTIME_P: /* w <n> -- sets warning time */
   2.439 -				sscanf(ptr + j, "w %u", &(evl[i].warn));
   2.440 +			case F_WTIME_P: /* #w<n> -- sets warning time */
   2.441 +				sscanf(cp, "#w%u", &(evl[i].warn));
   2.442  				break;
   2.443 -			case F_FORDAYS: /* for <days> -- sets the duration of the event */
   2.444 -				sscanf(ptr + j, "for %u", &d);
   2.445 +			case F_FORDAYS: /* #for<days> -- sets the duration of the event */
   2.446 +				sscanf(cp, "#for%u", &d);
   2.447  				evl[i].enddate=evl[i].date;
   2.448  				for (l = 1; l < d; l++) {
   2.449  					evl[i].enddate.day++;
   2.450 @@ -603,8 +619,8 @@
   2.451  					}
   2.452  				}
   2.453  				break;
   2.454 -			case F_TODATE: /* to <date> -- sets the end date of the event */
   2.455 -				l = sscanf(ptr + j, "to %u-%u-%u", &(evl[i].enddate.year), &(evl[i].enddate.month), &(evl[i].enddate.day));
   2.456 +			case F_TODATE: /* #to<date> -- sets the end date of the event */
   2.457 +				l = sscanf(cp, "#to%u-%u-%u", &(evl[i].enddate.year), &(evl[i].enddate.month), &(evl[i].enddate.day));
   2.458  				if (l == 2) {
   2.459  					evl[i].enddate.year = 0;
   2.460  				}
   2.461 @@ -621,34 +637,32 @@
   2.462  		/* construct event text */
   2.463  
   2.464  		switch(flags & F_MTYPE) {
   2.465 -			case F_TBIRTHDAY:
   2.466  			default: /* assume it's a birthday */
   2.467 -				if (evl[i].date.year != 0) {
   2.468 -					int tmp_age = ydelta(evl[i].date, today);
   2.469 -					if (tmp_age != 1) {
   2.470 -						sprintf(buf2, "%s is %d years old", buf, tmp_age);
   2.471 -					} else {
   2.472 -						sprintf(buf2, "%s is %d year old", buf, tmp_age);
   2.473 -					}
   2.474 -				} else {
   2.475 -					sprintf(buf2, "%s has a birthday", buf);
   2.476 +				if (!evl[i].date.year) {
   2.477 +					sprintf(buf2, "%s has a birthday", cp);
   2.478 +					break;
   2.479  				}
   2.480 +				int tmp_age = ydelta(evl[i].date, today);
   2.481 +				sprintf(buf2, "%s is %d year%s old",
   2.482 +				  cp, tmp_age, (tmp_age>1)?"s":"");
   2.483  				break;
   2.484  			case F_TANNIVERSARY:
   2.485 -				if (evl[i].date.year != 0) {
   2.486 -					sprintf(buf2, "%s %d years ago", buf, ydelta(evl[i].date, today));
   2.487 +				if (evl[i].date.year) {
   2.488 +					sprintf(buf2, "%s %d years ago",
   2.489 +					  cp, ydelta(evl[i].date, today));
   2.490  				} else {
   2.491 -					strcpy(buf2, buf);
   2.492 +					strcpy(buf2, cp);
   2.493  				}
   2.494  				break;
   2.495  			case F_TEVENT:
   2.496 -				/* if a year was specified, and this warning isn't for it, ignore! */
   2.497 -				if ((evl[i].date.year != 0 && ydelta(evl[i].date, today) != 0)
   2.498 -				    && (evl[i].enddate.year == 0 || ydelta(evl[i].enddate, today) != 0)) {
   2.499 +				/* if a year was specified, and this
   2.500 +				   warning isn't for it, ignore! */
   2.501 +				if ((evl[i].date.year && ydelta(evl[i].date, today))
   2.502 +				    && (!evl[i].enddate.year || ydelta(evl[i].enddate, today))) {
   2.503  					i--;
   2.504  					continue;
   2.505  				}
   2.506 -				strcpy(buf2, buf);
   2.507 +				strcpy(buf2, cp);
   2.508  				break;
   2.509  		}
   2.510  		evl[i].text = strdup(buf2);
   2.511 @@ -671,13 +685,16 @@
   2.512  
   2.513  
   2.514  
   2.515 -int
   2.516 -skptok(int j, char *ptr)
   2.517 +char *
   2.518 +skptok(char *ptr)
   2.519  {
   2.520 -	for (; ptr[j] != 0 &&  ptr[j] != ' ' && ptr[j] != '\t' ; j++);
   2.521 -	for (; ptr[j] != 0 && (ptr[j] == ' ' || ptr[j] == '\t'); j++);
   2.522 -
   2.523 -	return j;
   2.524 +	while (*ptr && (*ptr!=' ' && *ptr!='\t')) {
   2.525 +		ptr++;
   2.526 +	}
   2.527 +	while (*ptr && (*ptr==' ' || *ptr=='\t')) {
   2.528 +		ptr++;
   2.529 +	}
   2.530 +	return ptr;
   2.531  }
   2.532  
   2.533  
   2.534 @@ -688,18 +705,16 @@
   2.535  int
   2.536  main(int argc, char *argv[])
   2.537  {
   2.538 -	while (--argc > 0 && (*++argv)[0] == '-') {
   2.539 +	while (--argc > 0 && **++argv == '-') {
   2.540  		if (strcmp(argv[0], "-W") == 0) {
   2.541  			/* TODO: catch if no value given */
   2.542 -			iDWarn = atoi((++argv)[0]);
   2.543 +			def_warn = atoi((++argv)[0]);
   2.544  			argc--;
   2.545  		} else {
   2.546  			fprintf(stderr, "unknown option %s\n", argv[0]);
   2.547  			exit(1);
   2.548  		}
   2.549  	}
   2.550 -
   2.551 -	liststrings(readlist(), puts);
   2.552 -
   2.553 +	liststrings(readlist());
   2.554  	return 0;
   2.555  }