svn commit: r211734 - stable/8/usr.bin/calendar

Edwin Groothuis edwin at FreeBSD.org
Tue Aug 24 07:59:40 UTC 2010


Author: edwin
Date: Tue Aug 24 07:59:39 2010
New Revision: 211734
URL: http://svn.freebsd.org/changeset/base/211734

Log:
  For some reason, the new files which got merged from the head branch
  didn't get automatically added to the repository.
  
  MFC of r205821 r205827 r205828 r205862 r205872 r205937 r206568
  MFC of r208825 r208826 r208827 r208828 r208829 r208943
  
  r205821:
  Long awaited update to the calendar system:
  
  - Repeating events which span multiple years (because of -A, -B or
  just the three days before the end of the year).
  - Support for lunar events (full moon, new moon) and solar events
  (equinox and solstice, chinese new year). Because of this, the
  options -U (UTC offset) and -l (longitude) are available to
  compensate if reality doesn't match the calculated values.
  
  r205828:
  Use local names for calendar.dutch
  
  r205862:
  Fix DST thingies in calendar.australia
  
  r205872:
  Make licenses 3 clause instead of 4 clause
  
  r205937:
  Make the dates in the Tasmanian part of calendar.australia properly
  variable.
  
  r206568:
  Typo in Allerheiligen in calendar.dutch
  
  r208825, r208826, r208827, r208828, r208829, r208943:
  Coverity Prevent related fixes.

Added:
  stable/8/usr.bin/calendar/dates.c   (contents, props changed)
  stable/8/usr.bin/calendar/events.c   (contents, props changed)
  stable/8/usr.bin/calendar/locale.c   (contents, props changed)
  stable/8/usr.bin/calendar/parsedata.c   (contents, props changed)
  stable/8/usr.bin/calendar/pom.c   (contents, props changed)
  stable/8/usr.bin/calendar/sunpos.c   (contents, props changed)

Added: stable/8/usr.bin/calendar/dates.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.bin/calendar/dates.c	Tue Aug 24 07:59:39 2010	(r211734)
@@ -0,0 +1,452 @@
+/*-
+ * Copyright (c) 1992-2009 Edwin Groothuis <edwin at FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <time.h>
+
+#include "calendar.h"
+
+struct cal_year {
+	int year;	/* 19xx, 20xx, 21xx */
+	int easter;	/* Julian day */
+	int paskha;	/* Julian day */
+	int cny;	/* Julian day */
+	int firstdayofweek; /* 0 .. 6 */
+	struct cal_month *months;
+	struct cal_year	*nextyear;
+} cal_year;
+
+struct cal_month {
+	int month;			/* 01 .. 12 */
+	int firstdayjulian;		/* 000 .. 366 */
+	int firstdayofweek;		/* 0 .. 6 */
+	struct cal_year *year;		/* points back */
+	struct cal_day *days;
+	struct cal_month *nextmonth;
+} cal_month;
+
+struct cal_day {
+	int dayofmonth;			/* 01 .. 31 */
+	int julianday;			/* 000 .. 366 */
+	int dayofweek;			/* 0 .. 6 */
+	struct cal_day *nextday;
+	struct cal_month *month;	/* points back */
+	struct cal_year	*year;		/* points back */
+	struct event *events;
+} cal_day;
+
+int debug_remember = 0;
+struct cal_year	*hyear = NULL;
+
+/* 1-based month, 0-based days, cumulative */
+int *cumdays;
+int	cumdaytab[][14] = {
+	{0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
+	{0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+};
+/* 1-based month, individual */
+int *mondays;
+int	mondaytab[][14] = {
+	{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30},
+	{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30},
+};
+
+static struct cal_day *	find_day(int yy, int mm, int dd);
+
+static void
+createdate(int y, int m, int d)
+{
+	struct cal_year *py, *pyp;
+	struct cal_month *pm, *pmp;
+	struct cal_day *pd, *pdp;
+	int *cumday;
+
+	pyp = NULL;
+	py = hyear;
+	while (py != NULL) {
+		if (py->year == y + 1900)
+			break;
+		pyp = py;
+		py = py->nextyear;
+	}
+
+	if (py == NULL) {
+		struct tm td;
+		time_t t;
+		py = (struct cal_year *)calloc(1, sizeof(struct cal_year));
+		py->year = y + 1900;
+		py->easter = easter(y);
+		py->paskha = paskha(y);
+
+		td = tm0;
+		td.tm_year = y;
+		td.tm_mday = 1;
+		t = mktime(&td);
+		localtime_r(&t, &td);
+		py->firstdayofweek = td.tm_wday;
+
+		if (pyp != NULL)
+			pyp->nextyear = py;
+	}
+	if (pyp == NULL) {
+		/* The very very very first one */
+		hyear = py;
+	}
+
+	pmp = NULL;
+	pm = py->months;
+	while (pm != NULL) {
+		if (pm->month == m)
+			break;
+		pmp = pm;
+		pm = pm->nextmonth;
+	}
+
+	if (pm == NULL) {
+		pm = (struct cal_month *)calloc(1, sizeof(struct cal_month));
+		pm->year = py;
+		pm->month = m;
+		cumday = cumdaytab[isleap(y)];
+		pm->firstdayjulian = cumday[m] + 2;
+		pm->firstdayofweek =
+		    (py->firstdayofweek + pm->firstdayjulian -1) % 7;
+		if (pmp != NULL)
+			pmp->nextmonth = pm;
+	}
+	if (pmp == NULL)
+		py->months = pm;
+
+	pdp = NULL;
+	pd = pm->days;
+	while (pd != NULL) {
+		pdp = pd;
+		pd = pd->nextday;
+	}
+
+	if (pd == NULL) {	/* Always true */
+		pd = (struct cal_day *)calloc(1, sizeof(struct cal_day));
+		pd->month = pm;
+		pd->year = py;
+		pd->dayofmonth = d;
+		pd->julianday = pm->firstdayjulian + d - 1;
+		pd->dayofweek = (pm->firstdayofweek + d - 1) % 7;
+		if (pdp != NULL)
+			pdp->nextday = pd;
+	}
+	if (pdp == NULL)
+		pm->days = pd;
+}
+
+void
+generatedates(struct tm *tp1, struct tm *tp2)
+{
+	int y1, m1, d1;
+	int y2, m2, d2;
+	int y, m, d;
+
+	y1 = tp1->tm_year;
+	m1 = tp1->tm_mon + 1;
+	d1 = tp1->tm_mday;
+	y2 = tp2->tm_year;
+	m2 = tp2->tm_mon + 1;
+	d2 = tp2->tm_mday;
+
+	if (y1 == y2) {
+		if (m1 == m2) {
+			/* Same year, same month. Easy! */
+			for (d = d1; d <= d2; d++)
+				createdate(y1, m1, d);
+			return;
+		}
+		/*
+		 * Same year, different month.
+		 * - Take the leftover days from m1
+		 * - Take all days from <m1 .. m2>
+		 * - Take the first days from m2
+		 */
+		mondays = mondaytab[isleap(y1)];
+		for (d = d1; d <= mondays[m1]; d++)
+			createdate(y1, m1, d);
+		for (m = m1 + 1; m < m2; m++)
+			for (d = 1; d <= mondays[m]; d++)
+				createdate(y1, m, d);
+		for (d = 1; d <= d2; d++)
+			createdate(y1, m2, d);
+		return;
+	}
+	/*
+	 * Different year, different month.
+	 * - Take the leftover days from y1-m1
+	 * - Take all days from y1-<m1 .. 12]
+	 * - Take all days from <y1 .. y2>
+	 * - Take all days from y2-[1 .. m2>
+	 * - Take the first days of y2-m2
+	 */
+	mondays = mondaytab[isleap(y1)];
+	for (d = d1; d <= mondays[m1]; d++)
+		createdate(y1, m1, d);
+	for (m = m1 + 1; m <= 12; m++)
+		for (d = 1; d <= mondays[m]; d++)
+			createdate(y1, m, d);
+	for (y = y1 + 1; y < y2; y++) {
+		mondays = mondaytab[isleap(y)];
+		for (m = 1; m <= 12; m++)
+			for (d = 1; d <= mondays[m]; d++)
+				createdate(y, m, d);
+	}
+	mondays = mondaytab[isleap(y2)];
+	for (m = 1; m < m2; m++)
+		for (d = 1; d <= mondays[m]; d++)
+			createdate(y2, m, d);
+	for (d = 1; d <= d2; d++)
+		createdate(y2, m2, d);
+}
+
+void
+dumpdates(void)
+{
+	struct cal_year *y;
+	struct cal_month *m;
+	struct cal_day *d;
+
+	y = hyear;
+	while (y != NULL) {
+		printf("%-5d (wday:%d)\n", y->year, y->firstdayofweek);
+		m = y->months;
+		while (m != NULL) {
+			printf("-- %-5d (julian:%d, dow:%d)\n", m->month,
+			    m->firstdayjulian, m->firstdayofweek);
+			d = m->days;
+			while (d != NULL) {
+				printf("  -- %-5d (julian:%d, dow:%d)\n",
+				    d->dayofmonth, d->julianday, d->dayofweek);
+				d = d->nextday;
+			}
+			m = m->nextmonth;
+		}
+		y = y->nextyear;
+	}
+}
+
+int
+remember_ymd(int yy, int mm, int dd)
+{
+	struct cal_year *y;
+	struct cal_month *m;
+	struct cal_day *d;
+
+	if (debug_remember)
+		printf("remember_ymd: %d - %d - %d\n", yy, mm, dd);
+
+	y = hyear;
+	while (y != NULL) {
+		if (y->year != yy) {
+			y = y->nextyear;
+			continue;
+		}
+		m = y->months;
+		while (m != NULL) {
+			if (m->month != mm) {
+				m = m->nextmonth;
+				continue;
+			}
+			d = m->days;
+			while (d != NULL) {
+				if (d->dayofmonth == dd)
+					return (1);
+				d = d->nextday;
+				continue;
+			}
+			return (0);
+		}
+		return (0);
+	}
+	return (0);
+}
+
+int
+remember_yd(int yy, int dd, int *rm, int *rd)
+{
+	struct cal_year *y;
+	struct cal_month *m;
+	struct cal_day *d;
+
+	if (debug_remember)
+		printf("remember_yd: %d - %d\n", yy, dd);
+
+	y = hyear;
+	while (y != NULL) {
+		if (y->year != yy) {
+			y = y->nextyear;
+			continue;
+		}
+		m = y->months;
+		while (m != NULL) {
+			d = m->days;
+			while (d != NULL) {
+				if (d->julianday == dd) {
+					*rm = m->month;
+					*rd = d->dayofmonth;
+					return (1);
+				}
+				d = d->nextday;
+			}
+			m = m->nextmonth;
+		}
+		return (0);
+	}
+	return (0);
+}
+
+int
+first_dayofweek_of_year(int yy)
+{
+	struct cal_year *y;
+
+	y = hyear;
+	while (y != NULL) {
+		if (y->year == yy)
+			return (y->firstdayofweek);
+		y = y->nextyear;
+	}
+
+	/* Should not happen */
+	return (-1);
+}
+
+int
+first_dayofweek_of_month(int yy, int mm)
+{
+	struct cal_year *y;
+	struct cal_month *m;
+
+	y = hyear;
+	while (y != NULL) {
+		if (y->year != yy) {
+			y = y->nextyear;
+			continue;
+		}
+		m = y->months;
+		while (m != NULL) {
+			if (m->month == mm)
+				return (m->firstdayofweek);
+			m = m->nextmonth;
+		}
+		/* Should not happen */
+		return (-1);
+	}
+
+	/* Should not happen */
+	return (-1);
+}
+
+int
+walkthrough_dates(struct event **e)
+{
+	static struct cal_year *y = NULL;
+	static struct cal_month *m = NULL;
+	static struct cal_day *d = NULL;
+
+	if (y == NULL) {
+		y = hyear;
+		m = y->months;
+		d = m->days;
+		*e = d->events;
+		return (1);
+	};
+	if (d->nextday != NULL) {
+		d = d->nextday;
+		*e = d->events;
+		return (1);
+	}
+	if (m->nextmonth != NULL) {
+		m = m->nextmonth;
+		d = m->days;
+		*e = d->events;
+		return (1);
+	}
+	if (y->nextyear != NULL) {
+		y = y->nextyear;
+		m = y->months;
+		d = m->days;
+		*e = d->events;
+		return (1);
+	}
+
+	return (0);
+}
+
+static struct cal_day *
+find_day(int yy, int mm, int dd)
+{
+	struct cal_year *y;
+	struct cal_month *m;
+	struct cal_day *d;
+
+	if (debug_remember)
+		printf("remember_ymd: %d - %d - %d\n", yy, mm, dd);
+
+	y = hyear;
+	while (y != NULL) {
+		if (y->year != yy) {
+			y = y->nextyear;
+			continue;
+		}
+		m = y->months;
+		while (m != NULL) {
+			if (m->month != mm) {
+				m = m->nextmonth;
+				continue;
+			}
+			d = m->days;
+			while (d != NULL) {
+				if (d->dayofmonth == dd)
+					return (d);
+				d = d->nextday;
+				continue;
+			}
+			return (NULL);
+		}
+		return (NULL);
+	}
+	return (NULL);
+}
+
+void
+addtodate(struct event *e, int year, int month, int day)
+{
+	struct cal_day *d;
+
+	d = find_day(year, month, day);
+	e->next = d->events;
+	d->events = e;
+}

Added: stable/8/usr.bin/calendar/events.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.bin/calendar/events.c	Tue Aug 24 07:59:39 2010	(r211734)
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1992-2009 Edwin Groothuis <edwin at FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/time.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pathnames.h"
+#include "calendar.h"
+
+struct event *
+event_add(int year, int month, int day, char *date, int var, char *txt,
+    char *extra)
+{
+	struct event *e;
+
+	/*
+	 * Creating a new event:
+	 * - Create a new event
+	 * - Copy the machine readable day and month
+	 * - Copy the human readable and language specific date
+	 * - Copy the text of the event
+	 */
+	e = (struct event *)calloc(1, sizeof(struct event));
+	if (e == NULL)
+		errx(1, "event_add: cannot allocate memory");
+	e->month = month;
+	e->day = day;
+	e->var = var;
+	e->date = strdup(date);
+	if (e->date == NULL)
+		errx(1, "event_add: cannot allocate memory");
+	e->text = strdup(txt);
+	if (e->text == NULL)
+		errx(1, "event_add: cannot allocate memory");
+	e->extra = NULL;
+	if (extra != NULL && extra[0] != '\0')
+		e->extra = strdup(extra);
+	addtodate(e, year, month, day);
+	return (e);
+}
+
+void
+event_continue(struct event *e, char *txt)
+{
+	char *text;
+
+	/*
+	 * Adding text to the event:
+	 * - Save a copy of the old text (unknown length, so strdup())
+	 * - Allocate enough space for old text + \n + new text + 0
+	 * - Store the old text + \n + new text
+	 * - Destroy the saved copy.
+	 */
+	text = strdup(e->text);
+	if (text == NULL)
+		errx(1, "event_continue: cannot allocate memory");
+
+	free(e->text);
+	e->text = (char *)malloc(strlen(text) + strlen(txt) + 3);
+	if (e->text == NULL)
+		errx(1, "event_continue: cannot allocate memory");
+	strcpy(e->text, text);
+	strcat(e->text, "\n");
+	strcat(e->text, txt);
+	free(text);
+
+	return;
+}
+
+void
+event_print_all(FILE *fp)
+{
+	struct event *e;
+
+	while (walkthrough_dates(&e) != 0) {
+#ifdef DEBUG
+		fprintf(stderr, "event_print_allmonth: %d, day: %d\n",
+		    month, day);
+#endif
+
+		/*
+		 * Go through all events and print the text of the matching
+		 * dates
+		 */
+		while (e != NULL) {
+			(void)fprintf(fp, "%s%c%s%s%s%s\n", e->date,
+			    e->var ? '*' : ' ', e->text,
+			    e->extra != NULL ? " (" : "",
+			    e->extra != NULL ? e->extra : "",
+			    e->extra != NULL ? ")" : ""
+			);
+
+			e = e->next;
+		}
+	}
+}

Added: stable/8/usr.bin/calendar/locale.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.bin/calendar/locale.c	Tue Aug 24 07:59:39 2010	(r211734)
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "calendar.h"
+
+const char *fdays[] = {
+	"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+	"Saturday", NULL,
+};
+
+const char *days[] = {
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL,
+};
+
+const char *fmonths[] = {
+	"January", "February", "March", "April", "May", "June", "Juli",
+	"August", "September", "October", "November", "December", NULL,
+};
+
+const char *months[] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL,
+};
+
+const char *sequences[] = {
+	"First", "Second", "Third", "Fourth", "Fifth", "Last"
+};
+
+struct fixs fndays[8];		/* full national days names */
+struct fixs ndays[8];		/* short national days names */
+struct fixs fnmonths[13];	/* full national months names */
+struct fixs nmonths[13];	/* short national month names */
+struct fixs nsequences[10];	/* national sequence names */
+
+
+void
+setnnames(void)
+{
+	char buf[80];
+	int i, l;
+	struct tm tm;
+
+	memset(&tm, 0, sizeof(struct tm));
+	for (i = 0; i < 7; i++) {
+		tm.tm_wday = i;
+		strftime(buf, sizeof(buf), "%a", &tm);
+		for (l = strlen(buf);
+		     l > 0 && isspace((unsigned char)buf[l - 1]);
+		     l--)
+			;
+		buf[l] = '\0';
+		if (ndays[i].name != NULL)
+			free(ndays[i].name);
+		if ((ndays[i].name = strdup(buf)) == NULL)
+			errx(1, "cannot allocate memory");
+		ndays[i].len = strlen(buf);
+
+		strftime(buf, sizeof(buf), "%A", &tm);
+		for (l = strlen(buf);
+		     l > 0 && isspace((unsigned char)buf[l - 1]);
+		     l--)
+			;
+		buf[l] = '\0';
+		if (fndays[i].name != NULL)
+			free(fndays[i].name);
+		if ((fndays[i].name = strdup(buf)) == NULL)
+			errx(1, "cannot allocate memory");
+		fndays[i].len = strlen(buf);
+	}
+
+	memset(&tm, 0, sizeof(struct tm));
+	for (i = 0; i < 12; i++) {
+		tm.tm_mon = i;
+		strftime(buf, sizeof(buf), "%b", &tm);
+		for (l = strlen(buf);
+		     l > 0 && isspace((unsigned char)buf[l - 1]);
+		     l--)
+			;
+		buf[l] = '\0';
+		if (nmonths[i].name != NULL)
+			free(nmonths[i].name);
+		if ((nmonths[i].name = strdup(buf)) == NULL)
+			errx(1, "cannot allocate memory");
+		nmonths[i].len = strlen(buf);
+
+		strftime(buf, sizeof(buf), "%B", &tm);
+		for (l = strlen(buf);
+		     l > 0 && isspace((unsigned char)buf[l - 1]);
+		     l--)
+			;
+		buf[l] = '\0';
+		if (fnmonths[i].name != NULL)
+			free(fnmonths[i].name);
+		if ((fnmonths[i].name = strdup(buf)) == NULL)
+			errx(1, "cannot allocate memory");
+		fnmonths[i].len = strlen(buf);
+	}
+}
+
+void
+setnsequences(char *seq)
+{
+	int i;
+	char *p;
+
+	p = seq;
+	for (i = 0; i < 5; i++) {
+		nsequences[i].name = p;
+		if ((p = strchr(p, ' ')) == NULL) {
+			/* Oh oh there is something wrong. Erase! Erase! */
+			for (i = 0; i < 5; i++) {
+				nsequences[i].name = NULL;
+				nsequences[i].len = 0;
+			}
+			return;
+		}
+		*p = '\0';
+		p++;
+	}
+	nsequences[i].name = p;
+
+	for (i = 0; i < 5; i++) {
+		nsequences[i].name = strdup(nsequences[i].name);
+		nsequences[i].len = nsequences[i + 1].name - nsequences[i].name;
+	}
+	nsequences[i].name = strdup(nsequences[i].name);
+	nsequences[i].len = strlen(nsequences[i].name);
+
+	return;
+}

Added: stable/8/usr.bin/calendar/parsedata.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.bin/calendar/parsedata.c	Tue Aug 24 07:59:39 2010	(r211734)
@@ -0,0 +1,1009 @@
+/*-
+ * Copyright (c) 1992-2009 Edwin Groothuis <edwin at FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+
+#include "calendar.h"
+
+static char *showflags(int flags);
+static int isonlydigits(char *s, int nostar);
+static const char *getmonthname(int i);
+static int checkmonth(char *s, size_t *len, size_t *offset, const char **month);
+static const char *getdayofweekname(int i);
+static int checkdayofweek(char *s, size_t *len, size_t *offset, const char **dow);
+static int indextooffset(char *s);
+static int parseoffset(char *s);
+static char *floattoday(int year, double f);
+static char *floattotime(double f);
+
+/*
+ * 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'
+ *
+ */
+static 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, *p1, *p2;
+	const char *dow, *pmonth;
+	char pold;
+	size_t 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_NEWMOON,
+			    strlen(STRING_NEWMOON), F_NEWMOON);
+			CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len,
+			    F_NEWMOON);
+			CHECKSPECIAL(date, STRING_FULLMOON,
+			    strlen(STRING_FULLMOON), F_FULLMOON);
+			CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len,
+			    F_FULLMOON);
+			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);
+			CHECKSPECIAL(date, STRING_MAREQUINOX,
+			    strlen(STRING_MAREQUINOX), F_MAREQUINOX);
+			CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len,
+			    F_SEPEQUINOX);
+			CHECKSPECIAL(date, STRING_SEPEQUINOX,
+			    strlen(STRING_SEPEQUINOX), F_SEPEQUINOX);
+			CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len,
+			    F_SEPEQUINOX);
+			CHECKSPECIAL(date, STRING_JUNSOLSTICE,
+			    strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE);
+			CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len,
+			    F_JUNSOLSTICE);
+			CHECKSPECIAL(date, STRING_DECSOLSTICE,
+			    strlen(STRING_DECSOLSTICE), F_DECSOLSTICE);
+			CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len,
+			    F_DECSOLSTICE);
+			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;

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


More information about the svn-src-stable-8 mailing list