From owner-svn-src-user@FreeBSD.ORG Mon Dec 21 21:18:00 2009 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 019D0106568B; Mon, 21 Dec 2009 21:18:00 +0000 (UTC) (envelope-from edwin@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E3B588FC1C; Mon, 21 Dec 2009 21:17:59 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nBLLHxVt041091; Mon, 21 Dec 2009 21:17:59 GMT (envelope-from edwin@svn.freebsd.org) Received: (from edwin@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nBLLHxTB041085; Mon, 21 Dec 2009 21:17:59 GMT (envelope-from edwin@svn.freebsd.org) Message-Id: <200912212117.nBLLHxTB041085@svn.freebsd.org> From: Edwin Groothuis Date: Mon, 21 Dec 2009 21:17:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r200813 - user/edwin/calendar X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Dec 2009 21:18:00 -0000 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 #include +#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 ***