Author: edwin
Date: Mon Mar 29 06:49:20 2010
New Revision: 205821
URL: http://svn.freebsd.org/changeset/base/205821

Log:
  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.
  
  MFC after:    1 month

Added:
  head/usr.bin/calendar/dates.c   (contents, props changed)
  head/usr.bin/calendar/events.c   (contents, props changed)
  head/usr.bin/calendar/locale.c   (contents, props changed)
  head/usr.bin/calendar/parsedata.c   (contents, props changed)
  head/usr.bin/calendar/pom.c   (contents, props changed)
  head/usr.bin/calendar/sunpos.c   (contents, props changed)
Modified:
  head/usr.bin/calendar/Makefile
  head/usr.bin/calendar/calendar.1
  head/usr.bin/calendar/calendar.c
  head/usr.bin/calendar/calendar.h
  head/usr.bin/calendar/day.c
  head/usr.bin/calendar/io.c
  head/usr.bin/calendar/ostern.c
  head/usr.bin/calendar/paskha.c
  head/usr.bin/calendar/pathnames.h

Modified: head/usr.bin/calendar/Makefile
==============================================================================
--- head/usr.bin/calendar/Makefile      Mon Mar 29 06:31:58 2010        
(r205820)
+++ head/usr.bin/calendar/Makefile      Mon Mar 29 06:49:20 2010        
(r205821)
@@ -2,7 +2,9 @@
 # $FreeBSD$
 
 PROG=  calendar
-SRCS=   calendar.c io.c day.c ostern.c paskha.c
+SRCS=  calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
+       ostern.c paskha.c pom.c sunpos.c
+LDADD= -lm
 INTER=          de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \
                hr_HR.ISO8859-2 hu_HU.ISO8859-2 ru_RU.KOI8-R uk_UA.KOI8-U
 DE_LINKS=       de_DE.ISO8859-15

Modified: head/usr.bin/calendar/calendar.1
==============================================================================
--- head/usr.bin/calendar/calendar.1    Mon Mar 29 06:31:58 2010        
(r205820)
+++ head/usr.bin/calendar/calendar.1    Mon Mar 29 06:49:20 2010        
(r205821)
@@ -54,6 +54,8 @@
 .Ek
 .Oc
 .Op Fl W Ar num
+.Op Fl U Ar UTC-offset
+.Op Fl l Ar longitude
 .Sh DESCRIPTION
 The
 .Nm
@@ -93,6 +95,12 @@ as the default calendar file.
 .Sm on
 .Xc
 For test purposes only: set date directly to argument values.
+.It Fl l Ar longitude , Fl U Ar UTC-offset
+Only one is needed:
+Perform lunar and solar calculations from this longitude or from
+this UTC offset.
+If neither is specified, the calculations will be based on the
+difference between UTC time and localtime.
 .It Fl W Ar num
 Print lines from today and the next
 .Ar num
@@ -103,12 +111,36 @@ Ignore weekends when calculating the num
 To handle calendars in your national code table you can specify
 .Dq LANG=<locale_name>
 in the calendar file as early as possible.
-To handle national Easter
-names in the calendars
-.Dq Easter=<national_name>
-(for Catholic Easter) or
-.Dq Paskha=<national_name>
-(for Orthodox Easter) can be used.
+.Pp
+To handle the local name of sequences, you can specify them as:
+.Dq SEQUENCE=<first> <second> <third> <fourth> <fifth> <last>
+in the calendar file as early as possible.
+.Pp
+The names of the following special days are recognized:
+.Bl -tag -width 123456789012345 -compact
+.It Easter
+Catholic Easter.
+.It Paskha
+Orthodox Easter.
+.It NewMoon
+The lunar New Moon.
+.It FullMoon
+The lunar Full Moon.
+.It MarEquinox
+The solar equinox in March.
+.It JunSolstice
+The solar solstice in June.
+.It SepEquinox
+The solar equinox in March.
+.It DecSolstice
+The solar solstice in December.
+.It ChineseNewYear
+The first day of the Chinese year.
+.El
+These names may be reassigned to their local names via an assignment
+like
+.Dq Easter=Pasen
+in the calendar file.
 .Pp
 Other lines should begin with a month and day.
 They may be entered in almost any format, either numeric or as character
@@ -122,11 +154,11 @@ Two numbers default to the month followe
 Lines with leading tabs default to the last entered date, allowing
 multiple line specifications for a single date.
 .Pp
-``Easter'', is Easter for this year, and may be followed by a positive
-or negative integer.
-.Pp
-``Paskha'', is Orthodox Easter for this year, and may be followed by a
-positive or negative integer.
+The names of the recognized special days may be followed by a
+positive or negative integer, like:
+.Dq Easter+3
+or
+.Dq Pashka-4 .
 .Pp
 Weekdays may be followed by ``-4'' ...\& ``+5'' (aliases for
 last, first, second, third, fourth) for moving events like
@@ -191,7 +223,8 @@ calendar file to use if no calendar file
 do not send mail if this file exists.
 .El
 .Pp
-The following default calendar files are provided:
+The following default calendar files are provided in
+.Pa /usr/share/calendars:
 .Pp
 .Bl -tag -width calendar.southafrica -compact
 .It Pa calendar.all
@@ -208,6 +241,8 @@ so that roving holidays are set correctl
 Days of special significance to computer people.
 .It Pa calendar.croatian
 Calendar of events in Croatia.
+.It Pa calendar.dutch
+Calendar of events in the Netherlands.
 .It Pa calendar.freebsd
 Birthdays of
 .Fx
@@ -259,7 +294,28 @@ A
 .Nm
 command appeared in
 .At v7 .
+.Sh NOTES
+Chinese New Year is calculated at 120 degrees east of Greenwich,
+which roughly corresponds with the east coast of China.
+For people west of China, this might result that the start of Chinese
+New Year and the day of the related new moon might differ.
+.Pp
+The phases of the moon and the longitude of the sun are calculated
+against the local position which corresponds with 30 degrees times
+the time-difference towards Greenwich.
+.Pp
+The new and full moons are happening on the day indicated: They
+might happen in the time period in the early night or in the late
+evening.
+It doesn't indicate that they are starting in the night on that date.
+.Pp
+Because of minor differences between the output of the formulas
+used and other sources on the Internet, Druids and Werewolves should
+double-check the start and end time of solar and lunar events.
 .Sh BUGS
 The
 .Nm
-utility does not handle Jewish holidays and moon phases.
+utility does not handle Jewish holidays.
+.Pp
+There is no possibility to properly specify the local position
+needed for solar and lunar calculations.

Modified: head/usr.bin/calendar/calendar.c
==============================================================================
--- head/usr.bin/calendar/calendar.c    Mon Mar 29 06:31:58 2010        
(r205820)
+++ head/usr.bin/calendar/calendar.c    Mon Mar 29 06:49:20 2010        
(r205821)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1989, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -52,29 +52,38 @@ __FBSDID("$FreeBSD$");
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #include <unistd.h>
 
 #include "calendar.h"
 
+#define        UTCOFFSET_NOTSET        100     /* Expected between -24 and +24 
*/
+#define        LONGITUDE_NOTSET        1000    /* Expected between -360 and 
+360 */
+
 struct passwd  *pw;
 int            doall = 0;
+int            debug = 0;
+char           *DEBUG = NULL;
 time_t         f_time = 0;
-
-int    f_dayAfter = 0;         /* days after current date */
-int    f_dayBefore = 0;        /* days before current date */
-int    Friday = 5;             /* day before weekend */
+double         UTCOffset = UTCOFFSET_NOTSET;
+int            EastLongitude = LONGITUDE_NOTSET;
 
 static void    usage(void) __dead2;
 
 int
 main(int argc, char *argv[])
 {
+       int     f_dayAfter = 0;         /* days after current date */
+       int     f_dayBefore = 0;        /* days before current date */
+       int     Friday = 5;             /* day before weekend */
+
        int ch;
+       struct tm tp1, tp2;
 
        (void)setlocale(LC_ALL, "");
 
-       while ((ch = getopt(argc, argv, "-A:aB:F:f:t:W:")) != -1)
+       while ((ch = getopt(argc, argv, "-A:aB:dD:F:f:l:t:U:W:")) != -1)
                switch (ch) {
                case '-':               /* backward contemptible */
                case 'a':
@@ -89,14 +98,10 @@ main(int argc, char *argv[])
                        calendarFile = optarg;
                        break;
 
-               case 't': /* other date, undocumented, for tests */
-                       f_time = Mktime(optarg);
-                       break;
-
                case 'W': /* we don't need no steenking Fridays */
                        Friday = -1;
-
                        /* FALLTHROUGH */
+
                case 'A': /* days after current date */
                        f_dayAfter = atoi(optarg);
                        break;
@@ -105,9 +110,25 @@ main(int argc, char *argv[])
                        f_dayBefore = atoi(optarg);
                        break;
 
-               case 'F':
+               case 'F': /* Change the time: When does weekend start? */
                        Friday = atoi(optarg);
                        break;
+               case 'l': /* Change longitudal position */
+                       EastLongitude = strtol(optarg, NULL, 10);
+                       break;
+               case 'U': /* Change UTC offset */
+                       UTCOffset = strtod(optarg, NULL);
+                       break;
+
+               case 'd':
+                       debug = 1;
+                       break;
+               case 'D':
+                       DEBUG = optarg;
+                       break;
+               case 't': /* other date, undocumented, for tests */
+                       f_time = Mktime(optarg);
+                       break;
 
                case '?':
                default:
@@ -124,7 +145,60 @@ main(int argc, char *argv[])
        if (f_time <= 0)
                (void)time(&f_time);
 
-       settime(f_time);
+       /* if not set, determine where I could be */
+       {
+               if (UTCOffset == UTCOFFSET_NOTSET &&
+                   EastLongitude == LONGITUDE_NOTSET) {
+                       /* Calculate on difference between here and UTC */
+                       time_t t;
+                       struct tm tm;
+                       long utcoffset, hh, mm, ss;
+                       double uo;
+
+                       time(&t);
+                       localtime_r(&t, &tm);
+                       utcoffset = tm.tm_gmtoff;
+                       /* seconds -> hh:mm:ss */
+                       hh = utcoffset / SECSPERHOUR;
+                       utcoffset %= SECSPERHOUR;
+                       mm = utcoffset / SECSPERMINUTE;
+                       utcoffset %= SECSPERMINUTE;
+                       ss = utcoffset;
+
+                       /* hh:mm:ss -> hh.mmss */
+                       uo = mm + (100.0 * (ss / 60.0));
+                       uo /=  60.0 / 100.0;
+                       uo = hh + uo / 100;
+
+                       UTCOffset = uo;
+                       EastLongitude = UTCOffset * 15;
+               } else if (UTCOffset == UTCOFFSET_NOTSET) {
+                       /* Base on information given */
+                       UTCOffset = EastLongitude / 15;
+               } else if (EastLongitude == LONGITUDE_NOTSET) {
+                       /* Base on information given */
+                       EastLongitude = UTCOffset * 15;
+               }
+       }
+
+       settimes(f_time, f_dayBefore, f_dayAfter, Friday, &tp1, &tp2);
+       generatedates(&tp1, &tp2);
+
+       /*
+        * FROM now on, we are working in UTC.
+        * This will only affect moon and sun related events anyway.
+        */
+       if (setenv("TZ", "UTC", 1) != 0)
+               errx(1, "setenv: %s", strerror(errno));
+       tzset();
+
+       if (debug)
+               dumpdates();
+
+       if (DEBUG != NULL) {
+               dodebug(DEBUG);
+               exit(0);
+       }
 
        if (doall)
                while ((pw = getpwent()) != NULL) {
@@ -145,9 +219,11 @@ static void __dead2
 usage(void)
 {
 
-       fprintf(stderr, "%s\n%s\n",
+       fprintf(stderr, "%s\n%s\n%s\n",
            "usage: calendar [-a] [-A days] [-B days] [-F friday] "
            "[-f calendarfile]",
-           "                [-t dd[.mm[.year]]] [-W days]");
+           "                [-d] [-t dd[.mm[.year]]] [-W days]",
+           "                [-U utcoffset] [-l longitude]"
+           );
        exit(1);
 }

Modified: head/usr.bin/calendar/calendar.h
==============================================================================
--- head/usr.bin/calendar/calendar.h    Mon Mar 29 06:31:58 2010        
(r205820)
+++ head/usr.bin/calendar/calendar.h    Mon Mar 29 06:49:20 2010        
(r205821)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1989, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -36,43 +36,163 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 
+#define        SECSPERDAY      (24 * 60 * 60)
+#define        SECSPERHOUR     (60 * 60)
+#define        SECSPERMINUTE   (60)
+#define        MINSPERHOUR     (60)
+#define        HOURSPERDAY     (24)
+#define        FSECSPERDAY     (24.0 * 60.0 * 60.0)
+#define        FSECSPERHOUR    (60.0 * 60.0)
+#define        FSECSPERMINUTE  (60.0)
+#define        FMINSPERHOUR    (60.0)
+#define        FHOURSPERDAY    (24.0)
+
+#define        DAYSPERYEAR     365
+#define        DAYSPERLEAPYEAR 366
+
+/* Not yet categorized */
+
 extern struct passwd *pw;
 extern int doall;
-extern struct iovec header[];
-extern struct tm *tp;
+extern time_t t1, t2;
 extern const char *calendarFile;
-extern int *cumdays;
 extern int yrdays;
-extern struct fixs neaster, npaskha;
-
-void   cal(void);
-void   closecal(FILE *);
-int    getday(char *);
-int    getdayvar(char *);
-int    getfield(char *, char **, int *);
-int    getmonth(char *);
-int    geteaster(char *, int);
-int    getpaskha(char *, int);
-int    easter(int);
-int    isnow(char *, int *, int *, int *);
-FILE   *opencal(void);
-void   settime(time_t);
-time_t Mktime(char *);
-void   setnnames(void);
+extern struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
+extern struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
+extern double UTCOffset;
+extern int EastLongitude;
 
 #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 */
-
-extern int     f_dayAfter;     /* days after current date */
-extern int     f_dayBefore;    /* days before current date */
-extern int     Friday;         /* day before weekend */
+/* Flags to determine the returned values by determinestyle() in parsedata.c */
+#define        F_NONE                  0x00000
+#define        F_MONTH                 0x00001
+#define        F_DAYOFWEEK             0x00002
+#define        F_DAYOFMONTH            0x00004
+#define        F_MODIFIERINDEX         0x00008
+#define        F_MODIFIEROFFSET        0x00010
+#define        F_SPECIALDAY            0x00020
+#define        F_ALLMONTH              0x00040
+#define        F_ALLDAY                0x00080
+#define        F_VARIABLE              0x00100
+#define        F_EASTER                0x00200
+#define        F_CNY                   0x00400
+#define        F_PASKHA                0x00800
+#define        F_NEWMOON               0x01000
+#define        F_FULLMOON              0x02000
+#define        F_MAREQUINOX            0x04000
+#define        F_SEPEQUINOX            0x08000
+#define        F_JUNSOLSTICE           0x10000
+#define        F_DECSOLSTICE           0x20000
+
+#define        STRING_EASTER           "Easter"
+#define        STRING_PASKHA           "Paskha"
+#define        STRING_CNY              "ChineseNewYear"
+#define STRING_NEWMOON         "NewMoon"
+#define STRING_FULLMOON                "FullMoon"
+#define STRING_MAREQUINOX      "MarEquinox"
+#define STRING_SEPEQUINOX      "SepEquinox"
+#define STRING_JUNSOLSTICE     "JunSolstice"
+#define STRING_DECSOLSTICE     "DecSolstice"
+
+#define        MAXCOUNT                125     /* Random number of maximum 
number of
+                                        * repeats of an event. Should be 52
+                                        * (number of weeks per year), if you
+                                        * want to show two years then it
+                                        * should be 104. If you are seeing
+                                        * more than this you are using this
+                                        * program wrong.
+                                        */
+
+/* 
+ * All the astronomical calculations are carried out for the meridian 120
+ * degrees east of Greenwich.
+ */
+#define UTCOFFSET_CNY          8.0             
+
+extern int     debug;          /* show parsing of the input */
+extern int     year1, year2;
+
+/* events.c */
+/*
+ * Event sorting related functions:
+ * - Use event_add() to create a new event
+ * - Use event_continue() to add more text to the last added event
+ * - Use event_print_all() to display them in time chronological order
+ */
+struct event *event_add(int, int, int, char *, int, char *, char *);
+void   event_continue(struct event *events, char *txt);
+void   event_print_all(FILE *fp);
+struct event {
+       int     year;
+       int     month;
+       int     day;
+       int     var;
+       char    *date;
+       char    *text;
+       char    *extra;
+       struct event *next;
+};
+
+/* locale.c */
 
 struct fixs {
        char    *name;
-       int     len;
+       size_t  len;
 };
+
+extern const char *days[];
+extern const char *fdays[];
+extern const char *fmonths[];
+extern const char *months[];
+extern const char *sequences[];
+extern struct fixs fndays[8];          /* full national days names */
+extern struct fixs fnmonths[13];       /* full national months names */
+extern struct fixs ndays[8];           /* short national days names */
+extern struct fixs nmonths[13];                /* short national month names */
+extern struct fixs nsequences[10];
+
+void   setnnames(void);
+void   setnsequences(char *);
+
+/* day.c */
+extern const struct tm tm0;
+extern char dayname[];
+void   settimes(time_t,int before, int after, int friday, struct tm *tp1, 
struct tm *tp2);
+time_t Mktime(char *);
+
+/* parsedata.c */
+int    parsedaymonth(char *, int *, int *, int *, int *, char **);
+void   dodebug(char *type);
+
+/* io.c */
+void   cal(void);
+void   closecal(FILE *);
+FILE   *opencal(void);
+
+/* ostern.c / pashka.c */
+int    paskha(int);
+int    easter(int);
+
+/* dates.c */
+extern int cumdaytab[][14];
+extern int mondaytab[][14];
+extern int debug_remember;
+void   generatedates(struct tm *tp1, struct tm *tp2);
+void   dumpdates(void);
+int    remember_ymd(int y, int m, int d);
+int    remember_yd(int y, int d, int *rm, int *rd);
+int    first_dayofweek_of_year(int y);
+int    first_dayofweek_of_month(int y, int m);
+int    walkthrough_dates(struct event **e);
+void   addtodate(struct event *e, int year, int month, int day);
+
+/* pom.c */
+#define        MAXMOONS        18
+void   pom(int year, double UTCoffset, int *fms, int *nms);
+void   fpom(int year, double utcoffset, double *ffms, double *fnms);
+
+/* sunpos.c */
+void   equinoxsolstice(int year, double UTCoffset, int *equinoxdays, int 
*solsticedays);
+void   fequinoxsolstice(int year, double UTCoffset, double *equinoxdays, 
double *solsticedays);
+int    calculatesunlongitude30(int year, int degreeGMToffset, int 
*ichinesemonths);

Added: head/usr.bin/calendar/dates.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/usr.bin/calendar/dates.c       Mon Mar 29 06:49:20 2010        
(r205821)
@@ -0,0 +1,451 @@
+/*-
+ * Copyright (c) 1992-2009 Edwin Groothuis. 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;
+}

Modified: head/usr.bin/calendar/day.c
==============================================================================
--- head/usr.bin/calendar/day.c Mon Mar 29 06:31:58 2010        (r205820)
+++ head/usr.bin/calendar/day.c Mon Mar 29 06:49:20 2010        (r205821)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1989, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -34,9 +34,6 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <ctype.h>
 #include <err.h>
 #include <locale.h>
 #include <stdio.h>
@@ -46,120 +43,38 @@ __FBSDID("$FreeBSD$");
 
 #include "calendar.h"
 
-struct tm              *tp;
-static const struct tm tm0;
-int                    *cumdays, yrdays;
-char                   dayname[10];
-
-

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to