Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Dec 2009 21:17:59 +0000 (UTC)
From:      Edwin Groothuis <edwin@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r200813 - user/edwin/calendar
Message-ID:  <200912212117.nBLLHxTB041085@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: edwin
Date: Mon Dec 21 21:17:59 2009
New Revision: 200813
URL: http://svn.freebsd.org/changeset/base/200813

Log:
  Currently calendar(1) is not able to handle longer periods, mostly
  due to the way Easter and other special days are calculated. This
  will be an attempt to overcome this issue and add proper support
  for non-solar-based events (Easter, Chinese New Year, Jewish calendar,
  moon phases (for the vampires :-))
  
  So far:
  
  - Rewriten the parser to return more detailed reoccuring events
    (ran against calendar.full to catch the fall-out).

Modified:
  user/edwin/calendar/Makefile
  user/edwin/calendar/calendar.c
  user/edwin/calendar/calendar.h
  user/edwin/calendar/day.c
  user/edwin/calendar/io.c

Modified: user/edwin/calendar/Makefile
==============================================================================
--- user/edwin/calendar/Makefile	Mon Dec 21 21:04:41 2009	(r200812)
+++ user/edwin/calendar/Makefile	Mon Dec 21 21:17:59 2009	(r200813)
@@ -1,6 +1,8 @@
 #	@(#)Makefile	8.1 (Berkeley) 6/6/93
 # $FreeBSD$
 
+CFLAGS=	 -pipe  -g -std=gnu99 -fstack-protector   -Wall
+
 PROG=	calendar
 SRCS=   calendar.c io.c day.c ostern.c paskha.c
 INTER=          de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \

Modified: user/edwin/calendar/calendar.c
==============================================================================
--- user/edwin/calendar/calendar.c	Mon Dec 21 21:04:41 2009	(r200812)
+++ user/edwin/calendar/calendar.c	Mon Dec 21 21:17:59 2009	(r200813)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 
 struct passwd	*pw;
 int		doall = 0;
+int		debug = 0;
 time_t		f_time = 0;
 
 int	f_dayAfter = 0;		/* days after current date */
@@ -74,7 +75,7 @@ main(int argc, char *argv[])
 
 	(void)setlocale(LC_ALL, "");
 
-	while ((ch = getopt(argc, argv, "-A:aB:F:f:t:W:")) != -1)
+	while ((ch = getopt(argc, argv, "-A:aB:dF:f:t:W:")) != -1)
 		switch (ch) {
 		case '-':		/* backward contemptible */
 		case 'a':
@@ -95,8 +96,8 @@ main(int argc, char *argv[])
 
 		case 'W': /* we don't need no steenking Fridays */
 			Friday = -1;
-
 			/* FALLTHROUGH */
+
 		case 'A': /* days after current date */
 			f_dayAfter = atoi(optarg);
 			break;
@@ -109,6 +110,10 @@ main(int argc, char *argv[])
 			Friday = atoi(optarg);
 			break;
 
+		case 'd':
+			debug = 1;
+			break;
+
 		case '?':
 		default:
 			usage();
@@ -124,7 +129,7 @@ main(int argc, char *argv[])
 	if (f_time <= 0)
 		(void)time(&f_time);
 
-	settime(f_time);
+	settimes(f_time, f_dayBefore, f_dayAfter);
 
 	if (doall)
 		while ((pw = getpwent()) != NULL) {

Modified: user/edwin/calendar/calendar.h
==============================================================================
--- user/edwin/calendar/calendar.h	Mon Dec 21 21:04:41 2009	(r200812)
+++ user/edwin/calendar/calendar.h	Mon Dec 21 21:17:59 2009	(r200813)
@@ -36,38 +36,59 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 
+#define	SECSPERDAY	24 * 60 * 60
+
 extern struct passwd *pw;
 extern int doall;
 extern struct iovec header[];
-extern struct tm *tp;
+extern struct tm tp1, tp2;
+extern time_t t1, t2;
 extern const char *calendarFile;
 extern int *cumdays;
 extern int yrdays;
-extern struct fixs neaster, npaskha;
+extern struct fixs neaster, npaskha, ncny;
 
 void	cal(void);
 void	closecal(FILE *);
+int	checkdayofweek(char *, int *len, int *offset, char **dow);
+char *	getdayofweekname(int);
+int	checkmonth(char *, int *len, int *offset, char **month);
+char *	getmonthname(int);
 int	getday(char *);
 int	getdayvar(char *);
-int	getfield(char *, char **, int *);
+int	getfield(char *, int *);
 int	getmonth(char *);
 int	geteaster(char *, int);
 int	getpaskha(char *, int);
 int	easter(int);
-int	isnow(char *, int *, int *, int *);
+int	parsedaymonth(char *, int *, int *, int *);
 FILE	*opencal(void);
-void	settime(time_t);
+void	settimes(time_t,int, int);
 time_t	Mktime(char *);
 void	setnnames(void);
 
 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
 
-/* some flags */
-#define	F_ISMONTH	0x01	/* month (January ...) */
-#define	F_ISDAY		0x02	/* day of week (Sun, Mon, ...) */
-#define	F_ISDAYVAR	0x04	/* variables day of week, like SundayLast */
-#define	F_EASTER	0x08	/* Easter or easter depending days */
+/* Flags to determine the returned values by determinestyle() */
+#define	F_NONE			0x000
+#define	F_MONTH			0x001
+#define	F_DAYOFWEEK		0x002
+#define	F_DAYOFMONTH		0x004
+#define	F_MODIFIERINDEX		0x008
+#define	F_MODIFIEROFFSET	0x010
+#define	F_SPECIALDAY		0x020
+#define	F_ALLMONTH		0x040
+#define	F_ALLDAY		0x080
+#define	F_VARIABLE		0x100
+#define	F_EASTER		0x200
+#define	F_CNY			0x400
+#define	F_PASKHA		0x800
+
+#define	STRING_EASTER	"Easter"
+#define	STRING_PASKHA	"Paskha"
+#define	STRING_CNY	"ChineseNewYear"
 
+extern int	debug;		/* show parsing of the input */
 extern int	f_dayAfter;	/* days after current date */
 extern int	f_dayBefore;	/* days before current date */
 extern int	Friday;		/* day before weekend */

Modified: user/edwin/calendar/day.c
==============================================================================
--- user/edwin/calendar/day.c	Mon Dec 21 21:04:41 2009	(r200812)
+++ user/edwin/calendar/day.c	Mon Dec 21 21:17:59 2009	(r200813)
@@ -46,7 +46,8 @@ __FBSDID("$FreeBSD$");
 
 #include "calendar.h"
 
-struct tm		*tp;
+struct tm		tp1, tp2;
+time_t			time1, time2;
 static const struct tm	tm0;
 int			*cumdays, yrdays;
 char			dayname[10];
@@ -58,13 +59,23 @@ int	daytab[][14] = {
 	{0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
 };
 
+static char const *fdays[] = {
+	"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+	"Saturday", NULL,
+};
+
 static char const *days[] = {
-	"sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL,
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL,
+};
+
+static const char *fmonths[] = {
+	"January", "February", "March", "April", "May", "June", "Juli",
+	"August", "September", "October", "November", "December", NULL,
 };
 
 static const char *months[] = {
-	"jan", "feb", "mar", "apr", "may", "jun",
-	"jul", "aug", "sep", "oct", "nov", "dec", NULL,
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL,
 };
 
 static struct fixs fndays[8];		/* full national days names */
@@ -73,6 +84,9 @@ static struct fixs ndays[8];		/* short n
 static struct fixs fnmonths[13];	/* full national months names */
 static struct fixs nmonths[13];		/* short national month names */
 
+static char *showflags(int flags);
+static int isonlydigits(char *s, int star);
+
 
 void
 setnnames(void)
@@ -137,12 +151,13 @@ setnnames(void)
 }
 
 void
-settime(time_t now)
+settimes(time_t now, int before, int after)
 {
 	char *oldl, *lbufp;
+	struct tm tp;
 
-	tp = localtime(&now);
-	if (isleap(tp->tm_year + 1900)) {
+	localtime_r(&now, &tp);
+	if (isleap(tp.tm_year + 1900)) {
 		yrdays = 366;
 		cumdays = daytab[1];
 	} else {
@@ -151,7 +166,13 @@ settime(time_t now)
 	}
 	/* Friday displays Monday's events */
 	if (f_dayAfter == 0 && f_dayBefore == 0 && Friday != -1)
-		f_dayAfter = tp->tm_wday == Friday ? 3 : 1;
+		f_dayAfter = tp.tm_wday == Friday ? 3 : 1;
+
+	time1 = now - SECSPERDAY * f_dayBefore;
+	localtime_r(&time1, &tp1);
+	time2 = now + SECSPERDAY * f_dayAfter;
+	localtime_r(&time2, &tp2);
+
 	header[5].iov_base = dayname;
 
 	oldl = NULL;
@@ -159,7 +180,7 @@ settime(time_t now)
 	if (lbufp != NULL && (oldl = strdup(lbufp)) == NULL)
 		errx(1, "cannot allocate memory");
 	(void)setlocale(LC_TIME, "C");
-	header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
+	header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", &tp);
 	(void)setlocale(LC_TIME, (oldl != NULL ? oldl : ""));
 	if (oldl != NULL)
 		free(oldl);
@@ -175,15 +196,15 @@ Mktime(char *dp)
 {
 	time_t t;
 	int d, m, y;
-	struct tm tm;
+	struct tm tm, tp;
 
 	(void)time(&t);
-	tp = localtime(&t);
+	localtime_r(&t, &tp);
 
 	tm = tm0;
-	tm.tm_mday = tp->tm_mday;
-	tm.tm_mon = tp->tm_mon;
-	tm.tm_year = tp->tm_year;
+	tm.tm_mday = tp.tm_mday;
+	tm.tm_mon = tp.tm_mon;
+	tm.tm_year = tp.tm_year;
 
 	switch (sscanf(dp, "%d.%d.%d", &d, &m, &y)) {
 	case 3:
@@ -206,6 +227,231 @@ Mktime(char *dp)
 }
 
 /*
+ * Expected styles:
+ *
+ * Date			::=	Month . ' ' . DayOfMonth |
+ *				Month . ' ' . DayOfWeek . ModifierIndex |
+ *				Month . '/' . DayOfMonth |
+ *				Month . '/' . DayOfWeek . ModifierIndex |
+ *				DayOfMonth . ' ' . Month |
+ *				DayOfMonth . '/' . Month |
+ *				DayOfWeek . ModifierIndex . ' ' .Month |
+ *				DayOfWeek . ModifierIndex . '/' .Month |
+ *				DayOfWeek . ModifierIndex |
+ *				SpecialDay . ModifierOffset
+ *
+ * Month		::=	MonthName | MonthNumber | '*'
+ * MonthNumber		::=	'0' ... '9' | '00' ... '09' | '10' ... '12'
+ * MonthName		::=	MonthNameShort | MonthNameLong
+ * MonthNameLong	::=	'January' ... 'December'
+ * MonthNameShort	::=	'Jan' ... 'Dec' | 'Jan.' ... 'Dec.'
+ *
+ * DayOfWeek		::=	DayOfWeekShort | DayOfWeekLong
+ * DayOfWeekShort	::=	'Mon' .. 'Sun'
+ * DayOfWeekLong	::=	'Monday' .. 'Sunday'
+ * DayOfMonth		::=	'0' ... '9' | '00' ... '09' | '10' ... '29' |
+ *				'30' ... '31' | '*'
+ *
+ * ModifierOffset	::=	'' | '+' . ModifierNumber | '-' . ModifierNumber
+ * ModifierNumber	::=	'0' ... '9' | '00' ... '99' | '000' ... '299' |
+ *				'300' ... '359' | '360' ... '365'
+ * ModifierIndex	::=	'Second' | 'Third' | 'Fourth' | 'Fifth' |
+ *				'First' | 'Last'
+ * 
+ * SpecialDay		::=	'Easter' | 'Pashka' | 'ChineseNewYear'
+ *
+ */
+int
+determinestyle(char *date, int *flags,
+    char *month, int *imonth, char *dayofmonth, int *idayofmonth,
+    char *dayofweek, int *idayofweek, char *modifieroffset,
+    char *modifierindex, char *specialday)
+{
+	char *p, *dow, *pmonth, *p1, *p2;
+	char pold;
+	int len, offset;
+
+	*flags = F_NONE;
+	*month = '\0';
+	*imonth = 0;
+	*dayofmonth = '\0';
+	*idayofmonth = 0;
+	*dayofweek = '\0';
+	*idayofweek = 0;
+	*modifieroffset = '\0';
+	*modifierindex = '\0';
+	*specialday = '\0';
+
+#define CHECKSPECIAL(s1, s2, lens2, type)				\
+	if (s2 != NULL && strncmp(s1, s2, lens2) == 0) {		\
+		*flags |= F_SPECIALDAY;					\
+		*flags |= type;						\
+		*flags |= F_VARIABLE;					\
+		if (strlen(s1) == lens2) {				\
+			strcpy(specialday, s1);				\
+			return (1);					\
+		}							\
+		strncpy(specialday, s1, lens2);				\
+		specialday[lens2] = '\0';				\
+		strcpy(modifieroffset, s1 + lens2);			\
+		*flags |= F_MODIFIEROFFSET;				\
+		return (1);						\
+	}
+
+	if ((p = strchr(date, ' ')) == NULL) {
+		if ((p = strchr(date, '/')) == NULL) {
+			CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY),
+			    F_CNY);
+			CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY);
+			CHECKSPECIAL(date, STRING_PASKHA,
+			    strlen(STRING_PASKHA), F_PASKHA);
+			CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA);
+			CHECKSPECIAL(date, STRING_EASTER,
+			    strlen(STRING_EASTER), F_EASTER);
+			CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER);
+			if (checkdayofweek(date, &len, &offset, &dow) != 0) {
+				*flags |= F_DAYOFWEEK;
+				*flags |= F_VARIABLE;
+				*idayofweek = offset;
+				if (strlen(date) == len) {
+					strcpy(dayofweek, date);
+					return (1);
+				}
+				strncpy(dayofweek, date, len);
+				dayofweek[len] = '\0';
+				strcpy(modifierindex, date + len);
+				*flags |= F_MODIFIERINDEX;
+				return (1);
+			}
+			if (isonlydigits(date, 1)) {
+				/* Assume month number only */
+				*flags |= F_MONTH;
+				*imonth = (int)strtol(date, (char **)NULL, 10);
+				strcpy(month, getmonthname(*imonth));
+				return(1);
+			}
+			return (0);
+		}
+	}
+
+	/*
+	 * After this, leave by goto-ing to "allfine" or "fail" to restore the
+	 * original data in `date'.
+	 */
+	pold = *p;
+	*p = 0;
+	p1 = date;
+	p2 = p + 1;
+	/* Now p2 points to the next field and p1 to the first field */
+
+	/* Check if there is a month-string in the date */
+	if ((checkmonth(p1, &len, &offset, &pmonth) != 0)
+	 || (checkmonth(p2, &len, &offset, &pmonth) != 0 && (p2 = p1))) {
+		/* p2 is the non-month part */
+		*flags |= F_MONTH;
+		*imonth = offset;
+
+		strcpy(month, getmonthname(offset));
+		if (isonlydigits(p2, 1)) {
+			strcpy(dayofmonth, p2);
+			*idayofmonth = (int)strtol(p2, (char **)NULL, 10);
+			*flags |= F_DAYOFMONTH;
+			goto allfine;
+		}
+		if (strcmp(p2, "*") == 0) {
+			*flags |= F_ALLDAY;
+			goto allfine;
+		}
+
+		if (checkdayofweek(p2, &len, &offset, &dow) != 0) {
+			*flags |= F_DAYOFWEEK;
+			*flags |= F_VARIABLE;
+			*idayofweek = offset;
+			strcpy(dayofweek, getdayofweekname(offset));
+			if (strlen(p2) == len)
+				goto allfine;
+			strcpy(modifierindex, p2 + len);
+			*flags |= F_MODIFIERINDEX;
+			goto allfine;
+		}
+
+		goto fail;
+	}
+
+	/* Check if there is an every-day or every-month in the string */
+	if ((strcmp(p1, "*") == 0 && isonlydigits(p2, 1))
+	 || (strcmp(p2, "*") == 0 && isonlydigits(p1, 1) && (p2 = p1))) {
+		int d;
+
+		*flags |= F_ALLMONTH;
+		*flags |= F_DAYOFMONTH;
+		d = (int)strtol(p2, (char **)NULL, 10);
+		*idayofmonth = d;
+		sprintf(dayofmonth, "%d", d);
+		goto allfine;
+	}
+
+	/* Month as a number, then a weekday */
+	if (isonlydigits(p1, 1)
+	 && checkdayofweek(p2, &len, &offset, &dow) != 0) {
+		int d;
+
+		*flags |= F_MONTH;
+		*flags |= F_DAYOFWEEK;
+		*flags |= F_VARIABLE;
+
+		*idayofweek = offset;
+		d = (int)strtol(p1, (char **)NULL, 10);
+		*imonth = d;
+		strcpy(month, getmonthname(d));
+
+		strcpy(dayofweek, getdayofweekname(offset));
+		if (strlen(p2) == len)
+			goto allfine;
+		strcpy(modifierindex, p2 + len);
+		*flags |= F_MODIFIERINDEX;
+		goto allfine;
+	}
+
+	/* If both the month and date are specified as numbers */
+	if (isonlydigits(p1, 1) && isonlydigits(p2, 0)) {
+		/* Now who wants to be this ambigious? :-( */
+		int m, d;
+
+		if (strchr(p2, '*') != NULL)
+			*flags |= F_VARIABLE;
+
+		m = (int)strtol(p1, (char **)NULL, 10);
+		d = (int)strtol(p2, (char **)NULL, 10);
+
+		*flags |= F_MONTH;
+		*flags |= F_DAYOFMONTH;
+
+		if (m > 12) {
+			*imonth = d;
+			*idayofmonth = m;
+			strcpy(month, getmonthname(d));
+			sprintf(dayofmonth, "%d", m);
+		} else {
+			*imonth = m;
+			*idayofmonth = d;
+			strcpy(month, getmonthname(m));
+			sprintf(dayofmonth, "%d", d);
+		}
+		goto allfine;
+	}
+
+	/* FALLTHROUGH */
+fail:
+	*p = pold;
+	return (0);
+allfine:
+	*p = pold;
+	return (1);
+	
+}
+
+/*
  * Possible date formats include any combination of:
  *	3-charmonth			(January, Jan, Jan)
  *	3-charweekday			(Friday, Monday, mon.)
@@ -216,9 +462,11 @@ Mktime(char *dp)
  * along with the matched line.
  */
 int
-isnow(char *endp, int *monthp, int *dayp, int *varp)
+parsedaymonth(char *date, int *monthp, int *dayp, int *flags)
 {
-	int day, flags, month = 0, v1, v2;
+	char month[100], dayofmonth[100], dayofweek[100], modifieroffset[100];
+	char modifierindex[100], specialday[100];
+	int idayofweek, imonth, idayofmonth;
 
 	/*
 	 * CONVENTION
@@ -226,15 +474,46 @@ isnow(char *endp, int *monthp, int *dayp
 	 * Month:     1-12
 	 * Monthname: Jan .. Dec
 	 * Day:       1-31
-	 * Weekday:   Mon-Sun
+	 * Weekday:   Mon .. Sun
 	 *
 	 */
 
-	flags = 0;
+	*flags = 0;
 
-	/* read first field */
-	/* didn't recognize anything, skip it */
-	if (!(v1 = getfield(endp, &endp, &flags)))
+	if (debug)
+		printf("-------\ndate: |%s|\n", date);
+	if (determinestyle(date, flags, month, &imonth, dayofmonth,
+	    &idayofmonth, dayofweek, &idayofweek, modifieroffset,
+	    modifierindex, specialday) == 0) {
+		if (debug)
+			printf("Failed!\n");
+		return (0);
+	}
+
+	if (debug) {
+		printf("flags: %x - %s\n", *flags, showflags(*flags));
+		if (modifieroffset[0] != '\0')
+			printf("modifieroffset: |%s|\n", modifieroffset);
+		if (modifierindex[0] != '\0')
+			printf("modifierindex: |%s|\n", modifierindex);
+		if (month[0] != '\0')
+			printf("month: |%s| (%d)\n", month, imonth);
+		if (dayofmonth[0] != '\0')
+			printf("dayofmonth: |%s| (%d)\n", dayofmonth,
+			    idayofmonth);
+		if (dayofweek[0] != '\0')
+			printf("dayofweek: |%s| (%d)\n", dayofweek, idayofweek);
+		if (specialday[0] != '\0')
+			printf("specialday: |%s|\n", specialday);
+	}
+
+	if ((*flags & !F_VARIABLE) == (F_MONTH | F_DAYOFMONTH)) {
+	}
+
+	return (0);
+
+#ifdef NOTDEF
+	if (!(v1 = getfield(date, &flags)))
 		return (0);
 
 	/* Easter or Easter depending days */
@@ -254,7 +533,7 @@ isnow(char *endp, int *monthp, int *dayp
 		/* {Day,Weekday} {Month,Monthname} ... */
 		/* if no recognizable month, assume just a day alone
 		 * in other words, find month or use current month */
-		if (!(month = getfield(endp, &endp, &flags)))
+		if (!(month = getfield(endp, &flags)))
 			month = tp->tm_mon + 1;
 	}
 
@@ -264,13 +543,13 @@ isnow(char *endp, int *monthp, int *dayp
 
 		/* Monthname {day,weekday} */
 		/* if no recognizable day, assume the first day in month */
-		if (!(day = getfield(endp, &endp, &flags)))
+		if (!(day = getfield(endp, &flags)))
 			day = 1;
 	}
 
 	/* Hm ... */
 	else {
-		v2 = getfield(endp, &endp, &flags);
+		v2 = getfield(endp, &flags);
 
 		/*
 		 * {Day} {Monthname} ...
@@ -399,45 +678,145 @@ isnow(char *endp, int *monthp, int *dayp
 		if (day >= before)
 			return (1);
 	}
-
+#endif
 	return (0);
 }
 
 
+static char *
+showflags(int flags)
+{
+	static char s[1000];
+	s[0] = '\0';
+
+	if ((flags & F_MONTH) != 0)
+		strcat(s, "month ");
+	if ((flags & F_DAYOFWEEK) != 0)
+		strcat(s, "dayofweek ");
+	if ((flags & F_DAYOFMONTH) != 0)
+		strcat(s, "dayofmonth ");
+	if ((flags & F_MODIFIERINDEX) != 0)
+		strcat(s, "modifierindex ");
+	if ((flags & F_MODIFIEROFFSET) != 0)
+		strcat(s, "modifieroffset ");
+	if ((flags & F_SPECIALDAY) != 0)
+		strcat(s, "specialday ");
+	if ((flags & F_ALLMONTH) != 0)
+		strcat(s, "allmonth ");
+	if ((flags & F_ALLDAY) != 0)
+		strcat(s, "allday ");
+	if ((flags & F_VARIABLE) != 0)
+		strcat(s, "variable ");
+	if ((flags & F_CNY) != 0)
+		strcat(s, "chinesenewyear ");
+	if ((flags & F_PASKHA) != 0)
+		strcat(s, "paskha ");
+	if ((flags & F_EASTER) != 0)
+		strcat(s, "easter ");
+
+	return s;
+}
+
+char *
+getmonthname(int i)
+{
+	if (nmonths[i - 1].len != 0 && nmonths[i - 1].name != NULL)
+		return (nmonths[i - 1].name);
+	return ((char *)months[i - 1]);
+}
+
 int
-getmonth(char *s)
+checkmonth(char *s, int *len, int *offset, char **month)
 {
-	const char **p;
 	struct fixs *n;
+	int i;
 
-	for (n = fnmonths; n->name; ++n)
-		if (!strncasecmp(s, n->name, n->len))
-			return ((n - fnmonths) + 1);
-	for (n = nmonths; n->name; ++n)
-		if (!strncasecmp(s, n->name, n->len))
-			return ((n - nmonths) + 1);
-	for (p = months; *p; ++p)
-		if (!strncasecmp(s, *p, 3))
-			return ((p - months) + 1);
+	for (i = 0; fnmonths[i].name != NULL; i++) {
+		n = fnmonths + i;
+		if (strncasecmp(s, n->name, n->len) == 0) {
+			*len = n->len;
+			*month = n->name;
+			*offset = i + 1;
+			return (1);
+		}
+	}
+	for (i = 0; nmonths[i].name != NULL; i++) {
+		n = nmonths + i;
+		if (strncasecmp(s, n->name, n->len) == 0) {
+			*len = n->len;
+			*month = n->name;
+			*offset = i + 1;
+			return (1);
+		}
+	}
+	for (i = 0; fmonths[i] != NULL; i++) {
+		*len = strlen(fmonths[i]);
+		if (strncasecmp(s, fmonths[i], *len) == 0) {
+			*month = (char *)fmonths[i];
+			*offset = i + 1;
+			return (1);
+		}
+	}
+	for (i = 0; months[i] != NULL; i++) {
+		if (strncasecmp(s, months[i], 3) == 0) {
+			*len = 3;
+			*month = (char *)months[i];
+			*offset = i + 1;
+			return (1);
+		}
+	}
 	return (0);
 }
 
 
+char *
+getdayofweekname(int i)
+{
+	if (ndays[i].len != 0 && ndays[i].name != NULL)
+		return (ndays[i].name);
+	return ((char *)days[i]);
+}
+
 int
-getday(char *s)
+checkdayofweek(char *s, int *len, int *offset, char **dow)
 {
-	const char **p;
 	struct fixs *n;
+	int i;
 
-	for (n = fndays; n->name; ++n)
-		if (!strncasecmp(s, n->name, n->len))
-			return ((n - fndays) + 1);
-	for (n = ndays; n->name; ++n)
-		if (!strncasecmp(s, n->name, n->len))
-			return ((n - ndays) + 1);
-	for (p = days; *p; ++p)
-		if (!strncasecmp(s, *p, 3))
-			return ((p - days) + 1);
+	for (i = 0; fndays[i].name != NULL; i++) {
+		n = fndays + i;
+		if (strncasecmp(s, n->name, n->len) == 0) {
+			*len = n->len;
+			*dow = n->name;
+			*offset = i;
+			return (1);
+		}
+	}
+	for (i = 0; ndays[i].name != NULL; i++) {
+		n = ndays + i;
+		if (strncasecmp(s, n->name, n->len) == 0) {
+			*len = n->len;
+			*dow = n->name;
+			*offset = i;
+			return (1);
+		}
+	}
+	for (i = 0; fdays[i] != NULL; i++) {
+		*len = strlen(fdays[i]);
+		if (strncasecmp(s, fdays[i], *len) == 0) {
+			*dow = (char *)fdays[i];
+			*offset = i;
+			return (1);
+		}
+	}
+	for (i = 0; days[i] != NULL; i++) {
+		if (strncasecmp(s, days[i], 3) == 0) {
+			*len = 3;
+			*dow = (char *)days[i];
+			*offset = i;
+			return (1);
+		}
+	}
 	return (0);
 }
 
@@ -483,3 +862,18 @@ getdayvar(char *s)
 	/* no offset detected */
 	return (0);
 }
+
+
+static int
+isonlydigits(char *s, int nostar)
+{
+	int i;
+	for (i = 0; s[i] != '\0'; i++) {
+		if (nostar == 0 && s[i] == '*' && s[i + 1] == '\0')
+			return 1;
+		if (!isdigit(s[i]))
+			return (0);
+	}
+	return (1);
+}
+

Modified: user/edwin/calendar/io.c
==============================================================================
--- user/edwin/calendar/io.c	Mon Dec 21 21:04:41 2009	(r200812)
+++ user/edwin/calendar/io.c	Mon Dec 21 21:17:59 2009	(r200813)
@@ -90,7 +90,7 @@ const char *calendarNoMail = "nomail";	/
 
 char	path[MAXPATHLEN];
 
-struct fixs neaster, npaskha;
+struct fixs neaster, npaskha, ncny;
 
 struct iovec header[] = {
 	{"From: ", 6},
@@ -102,26 +102,37 @@ struct iovec header[] = {
 	{"'s Calendar\nPrecedence: bulk\n\n", 30},
 };
 
+#define MAXCOUNT	55
 void
 cal(void)
 {
-	int printing;
-	char *p;
+	char *pp, p;
 	FILE *fp;
 	int ch, l;
-	int month;
-	int day;
-	int var;
+	int count, i;
+	int month[MAXCOUNT];
+	int day[MAXCOUNT];
+	int flags;
 	static int d_first = -1;
 	char buf[2048 + 1];
-	struct event *events = NULL;
+	struct event *events[MAXCOUNT];
+	struct event *eventshead = NULL;
+	struct tm tm;
+	char dbuf[80];
+
+	/* Unused */
+	tm.tm_sec = 0;
+	tm.tm_min = 0;
+	tm.tm_hour = 0;
+	tm.tm_wday = 0;
 
 	if ((fp = opencal()) == NULL)
 		return;
-	for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) {
-		if ((p = strchr(buf, '\n')) != NULL)
-			*p = '\0';
+	while (fgets(buf, sizeof(buf), stdin) != NULL) {
+		if ((pp = strchr(buf, '\n')) != NULL)
+			*pp = '\0';
 		else
+			/* Flush this line */
 			while ((ch = getchar()) != '\n' && ch != EOF);
 		for (l = strlen(buf);
 		     l > 0 && isspace((unsigned char)buf[l - 1]);
@@ -130,6 +141,8 @@ cal(void)
 		buf[l] = '\0';
 		if (buf[0] == '\0')
 			continue;
+
+		/* Parse special definitions: LANG, Easter and Paskha */
 		if (strncmp(buf, "LANG=", 5) == 0) {
 			(void)setlocale(LC_ALL, buf + 5);
 			d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
@@ -152,38 +165,54 @@ cal(void)
 			npaskha.len = strlen(buf + 7);
 			continue;
 		}
-		if (buf[0] != '\t') {
-			printing = isnow(buf, &month, &day, &var) ? 1 : 0;
-			if ((p = strchr(buf, '\t')) == NULL)
-				continue;
-			if (p > buf && p[-1] == '*')
-				var = 1;
-			if (printing) {
-				struct tm tm;
-				char dbuf[80];
-
-				if (d_first < 0)
-					d_first =
-					    (*nl_langinfo(D_MD_ORDER) == 'd');
-				tm.tm_sec = 0;	/* unused */
-				tm.tm_min = 0;	/* unused */
-				tm.tm_hour = 0;	/* unused */
-				tm.tm_wday = 0;	/* unused */
-				tm.tm_mon = month - 1;
-				tm.tm_mday = day;
-				tm.tm_year = tp->tm_year; /* unused */
-				(void)strftime(dbuf, sizeof(dbuf),
-				    d_first ? "%e %b" : "%b %e", &tm);
-				events = event_add(events, month, day, dbuf,
-				    var, p);
-			}
-		} else {
-			if (printing)
-				event_continue(events, buf);
+
+		/*
+		 * If the line starts with a tab, the data has to be
+		 * added to the previous line
+		 */
+		if (buf[0] == '\t') {
+			for (i = 0; i < count; i++)
+				event_continue(events[i], buf);
+			continue;
+		}
+
+		/* Get rid of leading spaces (non-standard) */
+		while (isspace(buf[0]))
+			memcpy(buf, buf + 1, strlen(buf) - 1);
+
+		/* No tab in the line, then not a valid line */
+		if ((pp = strchr(buf, '\t')) == NULL)
+			continue;
+
+		/* Trim spaces in front of the tab */
+		while (isspace(pp[-1]))
+			pp--;
+		p = *pp;
+		*pp = '\0';
+		if ((count = parsedaymonth(buf, month, day, &flags)) == 0)
+			continue;
+		*pp = p;
+		/* Find the last tab */
+		while (pp[1] == '\t')
+			pp++;
+
+		if (d_first < 0)
+			d_first =
+			    (*nl_langinfo(D_MD_ORDER) == 'd');
+
+		for (i = 0; i < count; i++) {
+			tm.tm_mon = month[i] - 1;
+			tm.tm_mday = day[i];
+			tm.tm_year = tp1.tm_year; /* unused */
+			(void)strftime(dbuf, sizeof(dbuf),
+			    d_first ? "%e %b" : "%b %e", &tm);
+			eventshead = event_add(eventshead, month[i], day[i],
+			    dbuf, (flags &= F_VARIABLE != 0) ? 1 : 0, pp);
+			events[i] = eventshead;
 		}
 	}
 
-	event_print_all(fp, events);
+	event_print_all(fp, eventshead);
 	closecal(fp);
 }
 
@@ -263,7 +292,7 @@ event_print_all(FILE *fp, struct event *
 	 */
 	for (daycounter = 0; daycounter <= f_dayAfter + f_dayBefore;
 	    daycounter++) {
-		day = tp->tm_yday - f_dayBefore + daycounter;
+		day = tp1.tm_yday - f_dayBefore + daycounter;
 		if (day < 0)
 			day += yrdays;
 		if (day >= yrdays)
@@ -303,74 +332,77 @@ event_print_all(FILE *fp, struct event *
 	}
 }
 
-int
-getfield(char *p, char **endp, int *flags)
-{
-	int val, var;
-	char *start, savech;
-
-	for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p)
-               && *p != '*'; ++p)
-	       ;
-	if (*p == '*') {			/* `*' is current month */
-		*flags |= F_ISMONTH;
-		*endp = p + 1;
-		return (tp->tm_mon + 1);
-	}
-	if (isdigit((unsigned char)*p)) {
-		val = strtol(p, &p, 10);	/* if 0, it's failure */
-		for (; !isdigit((unsigned char)*p)
-                       && !isalpha((unsigned char)*p) && *p != '*'; ++p);
-		*endp = p;
-		return (val);
-	}
-	for (start = p; isalpha((unsigned char)*++p););
-
-	/* Sunday-1 */
-	if (*p == '+' || *p == '-')
-		for(; isdigit((unsigned char)*++p);)
-			;
-
-	savech = *p;
-	*p = '\0';
-
-	/* Month */
-	if ((val = getmonth(start)) != 0)
-		*flags |= F_ISMONTH;
-
-	/* Day */
-	else if ((val = getday(start)) != 0) {
-		*flags |= F_ISDAY;
-
-		/* variable weekday */
-		if ((var = getdayvar(start)) != 0) {
-			if (var <= 5 && var >= -4)
-				val += var * 10;
-#ifdef DEBUG
-			printf("var: %d\n", var);
+#ifdef NOTDEF
+//int
+//getfield(char *p, int *flags)
+//{
+//	int val, var;
+//	char *start, savech;
+//
+//	if (*p == '\0')
+//		return(0);
+//
+//	/* Find the first digit, alpha or * */
+//	for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p)
+//               && *p != '*'; ++p)
+//	       ;
+//	if (*p == '*') {			/* `*' is current month */
+//		*flags |= F_ISMONTH;
+//		return (tp->tm_mon + 1);
+//	}
+//	if (isdigit((unsigned char)*p)) {
+//		val = strtol(p, &p, 10);	/* if 0, it's failure */
+//		for (; !isdigit((unsigned char)*p)
+//                       && !isalpha((unsigned char)*p) && *p != '*'; ++p);
+//		return (val);
+//	}
+//	for (start = p; isalpha((unsigned char)*++p););
+//
+//	/* Sunday-1 */
+//	if (*p == '+' || *p == '-')
+//		for(; isdigit((unsigned char)*++p);)
+//			;
+//
+//	savech = *p;
+//	*p = '\0';
+//
+//	/* Month */
+//	if ((val = getmonth(start)) != 0)
+//		*flags |= F_ISMONTH;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912212117.nBLLHxTB041085>