parsedata.c revision 256281
133965Sjdp/*- 260484Sobrien * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>. 360484Sobrien * All rights reserved. 433965Sjdp * 533965Sjdp * Redistribution and use in source and binary forms, with or without 633965Sjdp * modification, are permitted provided that the following conditions 733965Sjdp * are met: 833965Sjdp * 1. Redistributions of source code must retain the above copyright 933965Sjdp * notice, this list of conditions and the following disclaimer. 1033965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1133965Sjdp * notice, this list of conditions and the following disclaimer in the 1233965Sjdp * documentation and/or other materials provided with the distribution. 1333965Sjdp * 1433965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1533965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1633965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1733965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1833965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1933965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2033965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2133965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2233965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2333965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2433965Sjdp * SUCH DAMAGE. 2533965Sjdp * 2633965Sjdp */ 2733965Sjdp 2833965Sjdp#include <sys/cdefs.h> 2933965Sjdp__FBSDID("$FreeBSD: stable/10/usr.bin/calendar/parsedata.c 251647 2013-06-12 07:52:49Z grog $"); 3033965Sjdp 3133965Sjdp#include <ctype.h> 3233965Sjdp#include <math.h> 3333965Sjdp#include <stdio.h> 3433965Sjdp#include <stdlib.h> 3561843Sobrien#include <string.h> 3633965Sjdp#include <err.h> 3733965Sjdp 3833965Sjdp#include "calendar.h" 3933965Sjdp 4033965Sjdpstatic char *showflags(int flags); 4133965Sjdpstatic int isonlydigits(char *s, int nostar); 4233965Sjdpstatic const char *getmonthname(int i); 4333965Sjdpstatic int checkmonth(char *s, size_t *len, size_t *offset, const char **month); 4460484Sobrienstatic const char *getdayofweekname(int i); 4560484Sobrienstatic int checkdayofweek(char *s, size_t *len, size_t *offset, const char **dow); 4660484Sobrienstatic int indextooffset(char *s); 4760484Sobrienstatic int parseoffset(char *s); 4860484Sobrienstatic char *floattoday(int year, double f); 4960484Sobrienstatic char *floattotime(double f); 5033965Sjdpstatic int wdayom (int day, int offset, int month, int year); 5133965Sjdp 5233965Sjdp/* 5333965Sjdp * Expected styles: 5433965Sjdp * 5538889Sjdp * Date ::= Month . ' ' . DayOfMonth | 5633965Sjdp * Month . ' ' . DayOfWeek . ModifierIndex | 5733965Sjdp * Month . '/' . DayOfMonth | 5833965Sjdp * Month . '/' . DayOfWeek . ModifierIndex | 5933965Sjdp * DayOfMonth . ' ' . Month | 6033965Sjdp * DayOfMonth . '/' . Month | 6133965Sjdp * DayOfWeek . ModifierIndex . ' ' .Month | 6233965Sjdp * DayOfWeek . ModifierIndex . '/' .Month | 6333965Sjdp * DayOfWeek . ModifierIndex | 6433965Sjdp * SpecialDay . ModifierOffset 6533965Sjdp * 6633965Sjdp * Month ::= MonthName | MonthNumber | '*' 6733965Sjdp * MonthNumber ::= '0' ... '9' | '00' ... '09' | '10' ... '12' 6833965Sjdp * MonthName ::= MonthNameShort | MonthNameLong 6933965Sjdp * MonthNameLong ::= 'January' ... 'December' 7033965Sjdp * MonthNameShort ::= 'Jan' ... 'Dec' | 'Jan.' ... 'Dec.' 7133965Sjdp * 7233965Sjdp * DayOfWeek ::= DayOfWeekShort | DayOfWeekLong 7333965Sjdp * DayOfWeekShort ::= 'Mon' .. 'Sun' 7433965Sjdp * DayOfWeekLong ::= 'Monday' .. 'Sunday' 7533965Sjdp * DayOfMonth ::= '0' ... '9' | '00' ... '09' | '10' ... '29' | 7633965Sjdp * '30' ... '31' | '*' 7733965Sjdp * 7833965Sjdp * ModifierOffset ::= '' | '+' . ModifierNumber | '-' . ModifierNumber 7933965Sjdp * ModifierNumber ::= '0' ... '9' | '00' ... '99' | '000' ... '299' | 8033965Sjdp * '300' ... '359' | '360' ... '365' 8133965Sjdp * ModifierIndex ::= 'Second' | 'Third' | 'Fourth' | 'Fifth' | 8233965Sjdp * 'First' | 'Last' 8333965Sjdp * 8433965Sjdp * SpecialDay ::= 'Easter' | 'Paskha' | 'ChineseNewYear' 8533965Sjdp * 8633965Sjdp */ 8733965Sjdpstatic int 8833965Sjdpdeterminestyle(char *date, int *flags, 8933965Sjdp char *month, int *imonth, char *dayofmonth, int *idayofmonth, 9033965Sjdp char *dayofweek, int *idayofweek, char *modifieroffset, 9133965Sjdp char *modifierindex, char *specialday, char *year, int *iyear) 9233965Sjdp{ 9333965Sjdp char *p, *p1, *p2, *py; 9433965Sjdp const char *dow, *pmonth; 9533965Sjdp char pold; 9633965Sjdp size_t len, offset; 9733965Sjdp 9833965Sjdp *flags = F_NONE; 9933965Sjdp *month = '\0'; 10033965Sjdp *imonth = 0; 10133965Sjdp *year = '\0'; 10233965Sjdp *iyear = 0; 10333965Sjdp *dayofmonth = '\0'; 10433965Sjdp *idayofmonth = 0; 10533965Sjdp *dayofweek = '\0'; 10633965Sjdp *idayofweek = 0; 10733965Sjdp *modifieroffset = '\0'; 10833965Sjdp *modifierindex = '\0'; 10933965Sjdp *specialday = '\0'; 11033965Sjdp 11133965Sjdp#define CHECKSPECIAL(s1, s2, lens2, type) \ 11233965Sjdp if (s2 != NULL && strncmp(s1, s2, lens2) == 0) { \ 11333965Sjdp *flags |= F_SPECIALDAY; \ 11433965Sjdp *flags |= type; \ 11533965Sjdp *flags |= F_VARIABLE; \ 11633965Sjdp if (strlen(s1) == lens2) { \ 11733965Sjdp strcpy(specialday, s1); \ 11833965Sjdp return (1); \ 11933965Sjdp } \ 12033965Sjdp strncpy(specialday, s1, lens2); \ 12133965Sjdp specialday[lens2] = '\0'; \ 12233965Sjdp strcpy(modifieroffset, s1 + lens2); \ 12333965Sjdp *flags |= F_MODIFIEROFFSET; \ 12433965Sjdp return (1); \ 12533965Sjdp } 12633965Sjdp 12733965Sjdp if ((p = strchr(date, ' ')) == NULL) { 12833965Sjdp if ((p = strchr(date, '/')) == NULL) { 12933965Sjdp CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY), 13033965Sjdp F_CNY); 13133965Sjdp CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY); 13233965Sjdp CHECKSPECIAL(date, STRING_NEWMOON, 13333965Sjdp strlen(STRING_NEWMOON), F_NEWMOON); 13433965Sjdp CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len, 13533965Sjdp F_NEWMOON); 13633965Sjdp CHECKSPECIAL(date, STRING_FULLMOON, 13733965Sjdp strlen(STRING_FULLMOON), F_FULLMOON); 13833965Sjdp CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len, 13933965Sjdp F_FULLMOON); 14033965Sjdp CHECKSPECIAL(date, STRING_PASKHA, 14133965Sjdp strlen(STRING_PASKHA), F_PASKHA); 14233965Sjdp CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA); 14333965Sjdp CHECKSPECIAL(date, STRING_EASTER, 14433965Sjdp strlen(STRING_EASTER), F_EASTER); 14533965Sjdp CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER); 14633965Sjdp CHECKSPECIAL(date, STRING_MAREQUINOX, 14733965Sjdp strlen(STRING_MAREQUINOX), F_MAREQUINOX); 14833965Sjdp CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len, 14938889Sjdp F_SEPEQUINOX); 15033965Sjdp CHECKSPECIAL(date, STRING_SEPEQUINOX, 15160484Sobrien strlen(STRING_SEPEQUINOX), F_SEPEQUINOX); 15260484Sobrien CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len, 15360484Sobrien F_SEPEQUINOX); 15460484Sobrien CHECKSPECIAL(date, STRING_JUNSOLSTICE, 15560484Sobrien strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE); 15633965Sjdp CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len, 15733965Sjdp F_JUNSOLSTICE); 15833965Sjdp CHECKSPECIAL(date, STRING_DECSOLSTICE, 15960484Sobrien strlen(STRING_DECSOLSTICE), F_DECSOLSTICE); 16060484Sobrien CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len, 16160484Sobrien F_DECSOLSTICE); 16260484Sobrien if (checkdayofweek(date, &len, &offset, &dow) != 0) { 16360484Sobrien *flags |= F_DAYOFWEEK; 16433965Sjdp *flags |= F_VARIABLE; 16533965Sjdp *idayofweek = offset; 16633965Sjdp if (strlen(date) == len) { 16733965Sjdp strcpy(dayofweek, date); 16833965Sjdp return (1); 16933965Sjdp } 17033965Sjdp strncpy(dayofweek, date, len); 17133965Sjdp dayofweek[len] = '\0'; 17233965Sjdp strcpy(modifierindex, date + len); 17333965Sjdp *flags |= F_MODIFIERINDEX; 17433965Sjdp return (1); 17533965Sjdp } 17633965Sjdp if (isonlydigits(date, 1)) { 17733965Sjdp /* Assume month number only */ 17833965Sjdp *flags |= F_MONTH; 17933965Sjdp *imonth = (int)strtol(date, (char **)NULL, 10); 18033965Sjdp strcpy(month, getmonthname(*imonth)); 18133965Sjdp return(1); 18233965Sjdp } 18333965Sjdp return (0); 18433965Sjdp } 18560484Sobrien } 18633965Sjdp 18733965Sjdp /* 18833965Sjdp * After this, leave by goto-ing to "allfine" or "fail" to restore the 18933965Sjdp * original data in `date'. 19033965Sjdp */ 19133965Sjdp pold = *p; 19233965Sjdp *p = 0; 19333965Sjdp p1 = date; 19433965Sjdp p2 = p + 1; 19533965Sjdp /* Now p2 points to the next field and p1 to the first field */ 19660484Sobrien 19733965Sjdp if ((py = strchr(p2, '/')) != NULL) { 19833965Sjdp /* We have a year in the string. Now this is getting tricky */ 19933965Sjdp strcpy(year, p1); 20033965Sjdp *iyear = (int)strtol(year, NULL, 10); 20133965Sjdp p1 = p2; 20233965Sjdp p2 = py + 1; 20333965Sjdp *py = 0; 20433965Sjdp *flags |= F_YEAR; 20533965Sjdp } 20633965Sjdp 20760484Sobrien /* Check if there is a month-string in the date */ 20833965Sjdp if ((checkmonth(p1, &len, &offset, &pmonth) != 0) 20933965Sjdp || (checkmonth(p2, &len, &offset, &pmonth) != 0 && (p2 = p1))) { 21033965Sjdp /* p2 is the non-month part */ 21133965Sjdp *flags |= F_MONTH; 21233965Sjdp *imonth = offset; 21333965Sjdp 21433965Sjdp strcpy(month, getmonthname(offset)); 21533965Sjdp if (isonlydigits(p2, 1)) { 21633965Sjdp strcpy(dayofmonth, p2); 21733965Sjdp *idayofmonth = (int)strtol(p2, (char **)NULL, 10); 21833965Sjdp *flags |= F_DAYOFMONTH; 21961843Sobrien goto allfine; 22033965Sjdp } 22160484Sobrien if (strcmp(p2, "*") == 0) { 22260484Sobrien *flags |= F_ALLDAY; 22360484Sobrien goto allfine; 22460484Sobrien } 22560484Sobrien 22660484Sobrien if (checkdayofweek(p2, &len, &offset, &dow) != 0) { 22760484Sobrien *flags |= F_DAYOFWEEK; 22860484Sobrien *flags |= F_VARIABLE; 22960484Sobrien *idayofweek = offset; 23033965Sjdp strcpy(dayofweek, getdayofweekname(offset)); 23133965Sjdp if (strlen(p2) == len) 23233965Sjdp goto allfine; 23333965Sjdp strcpy(modifierindex, p2 + len); 23433965Sjdp *flags |= F_MODIFIERINDEX; 23560484Sobrien goto allfine; 23660484Sobrien } 23733965Sjdp goto fail; 23833965Sjdp } 23933965Sjdp 24033965Sjdp /* Check if there is an every-day or every-month in the string */ 24133965Sjdp if ((strcmp(p1, "*") == 0 && isonlydigits(p2, 1)) 24233965Sjdp || (strcmp(p2, "*") == 0 && isonlydigits(p1, 1) && (p2 = p1))) { 24333965Sjdp int d; 24433965Sjdp 24533965Sjdp *flags |= F_ALLMONTH; 24633965Sjdp *flags |= F_DAYOFMONTH; 24733965Sjdp d = (int)strtol(p2, (char **)NULL, 10); 24833965Sjdp *idayofmonth = d; 24960484Sobrien sprintf(dayofmonth, "%d", d); 25033965Sjdp goto allfine; 25160484Sobrien } 25260484Sobrien 25377298Sobrien /* Month as a number, then a weekday */ 25460484Sobrien if (isonlydigits(p1, 1) 25560484Sobrien && checkdayofweek(p2, &len, &offset, &dow) != 0) { 25660484Sobrien int d; 25760484Sobrien 25860484Sobrien *flags |= F_MONTH; 25960484Sobrien *flags |= F_DAYOFWEEK; 26060484Sobrien *flags |= F_VARIABLE; 26160484Sobrien 26260484Sobrien *idayofweek = offset; 26360484Sobrien d = (int)strtol(p1, (char **)NULL, 10); 26460484Sobrien *imonth = d; 26560484Sobrien strcpy(month, getmonthname(d)); 26660484Sobrien 26760484Sobrien strcpy(dayofweek, getdayofweekname(offset)); 26860484Sobrien if (strlen(p2) == len) 26960484Sobrien goto allfine; 27060484Sobrien strcpy(modifierindex, p2 + len); 27160484Sobrien *flags |= F_MODIFIERINDEX; 27260484Sobrien goto allfine; 27360484Sobrien } 27460484Sobrien 27560484Sobrien /* If both the month and date are specified as numbers */ 27660484Sobrien if (isonlydigits(p1, 1) && isonlydigits(p2, 0)) { 27760484Sobrien /* Now who wants to be this ambigious? :-( */ 27860484Sobrien int m, d; 27977298Sobrien 28060484Sobrien if (strchr(p2, '*') != NULL) 28133965Sjdp *flags |= F_VARIABLE; 28260484Sobrien 28360484Sobrien m = (int)strtol(p1, (char **)NULL, 10); 28433965Sjdp d = (int)strtol(p2, (char **)NULL, 10); 28533965Sjdp 28633965Sjdp *flags |= F_MONTH; 28733965Sjdp *flags |= F_DAYOFMONTH; 28860484Sobrien 28933965Sjdp if (m > 12) { 29033965Sjdp *imonth = d; 29133965Sjdp *idayofmonth = m; 29233965Sjdp strcpy(month, getmonthname(d)); 29333965Sjdp sprintf(dayofmonth, "%d", m); 29433965Sjdp } else { 29533965Sjdp *imonth = m; 29633965Sjdp *idayofmonth = d; 29733965Sjdp strcpy(month, getmonthname(m)); 29833965Sjdp sprintf(dayofmonth, "%d", d); 29933965Sjdp } 30033965Sjdp goto allfine; 30133965Sjdp } 30233965Sjdp 30360484Sobrien /* FALLTHROUGH */ 30460484Sobrienfail: 30560484Sobrien *p = pold; 30633965Sjdp return (0); 30761843Sobrienallfine: 30861843Sobrien *p = pold; 30961843Sobrien return (1); 31061843Sobrien 31177298Sobrien} 31261843Sobrien 31361843Sobrienvoid 31477298Sobrienremember(int *rememberindex, int *y, int *m, int *d, char **ed, int yy, int mm, 31561843Sobrien int dd, char *extra); 31661843Sobrienvoid 31733965Sjdpremember(int *rememberindex, int *y, int *m, int *d, char **ed, int yy, int mm, 31833965Sjdp int dd, char *extra) 31933965Sjdp{ 32033965Sjdp static int warned = 0; 32133965Sjdp 32233965Sjdp if (*rememberindex >= MAXCOUNT - 1) { 32333965Sjdp if (warned == 0) 32433965Sjdp warnx("Index > %d, ignored", MAXCOUNT); 32533965Sjdp warned++; 32633965Sjdp return; 32733965Sjdp } 32833965Sjdp y[*rememberindex] = yy; 32933965Sjdp m[*rememberindex] = mm; 33033965Sjdp d[*rememberindex] = dd; 33133965Sjdp if (extra != NULL) 33233965Sjdp strcpy(ed[*rememberindex], extra); 33333965Sjdp else 33433965Sjdp ed[*rememberindex][0] = '\0'; 33533965Sjdp *rememberindex += 1; 33633965Sjdp} 33733965Sjdp 33833965Sjdpstatic void 33933965Sjdpdebug_determinestyle(int dateonly, char *date, int flags, char *month, 34060484Sobrien int imonth, char *dayofmonth, int idayofmonth, char *dayofweek, 34133965Sjdp int idayofweek, char *modifieroffset, char *modifierindex, char *specialday, 34233965Sjdp char *year, int iyear) 34333965Sjdp{ 34433965Sjdp 34533965Sjdp if (dateonly != 0) { 34633965Sjdp printf("-------\ndate: |%s|\n", date); 34733965Sjdp if (dateonly == 1) 34833965Sjdp return; 34933965Sjdp } 35033965Sjdp printf("flags: %x - %s\n", flags, showflags(flags)); 35133965Sjdp if (modifieroffset[0] != '\0') 35233965Sjdp printf("modifieroffset: |%s|\n", modifieroffset); 35333965Sjdp if (modifierindex[0] != '\0') 35433965Sjdp printf("modifierindex: |%s|\n", modifierindex); 35533965Sjdp if (year[0] != '\0') 35633965Sjdp printf("year: |%s| (%d)\n", year, iyear); 35733965Sjdp if (month[0] != '\0') 35833965Sjdp printf("month: |%s| (%d)\n", month, imonth); 35933965Sjdp if (dayofmonth[0] != '\0') 36033965Sjdp printf("dayofmonth: |%s| (%d)\n", dayofmonth, idayofmonth); 36133965Sjdp if (dayofweek[0] != '\0') 36233965Sjdp printf("dayofweek: |%s| (%d)\n", dayofweek, idayofweek); 36333965Sjdp if (specialday[0] != '\0') 36433965Sjdp printf("specialday: |%s|\n", specialday); 36533965Sjdp} 36633965Sjdp 36733965Sjdpstatic struct yearinfo { 36833965Sjdp int year; 36933965Sjdp int ieaster, ipaskha, firstcnyday; 37033965Sjdp double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; 37133965Sjdp double ffullmooncny[MAXMOONS], fnewmooncny[MAXMOONS]; 37233965Sjdp int ichinesemonths[MAXMOONS]; 37333965Sjdp double equinoxdays[2], solsticedays[2]; 37460484Sobrien int *monthdays; 37533965Sjdp struct yearinfo *next; 37633965Sjdp} *years, *yearinfo; 37733965Sjdp 37860484Sobrien/* 37960484Sobrien * Calculate dates with offset from weekdays, like Thurs-3, Wed+2, etc. 38060484Sobrien * day is the day of the week, 38160484Sobrien * offset the ordinal number of the weekday in the month. 38260484Sobrien */ 38360484Sobrienstatic int 38433965Sjdpwdayom (int day, int offset, int month, int year) 38533965Sjdp{ 38633965Sjdp/* Weekday of first day in month */ 38733965Sjdp int wday1; /* first day of month */ 38833965Sjdp/* Weekday of last day in month */ 38933965Sjdp int wdayn; 39033965Sjdp int d; 39133965Sjdp 39261843Sobrien wday1 = first_dayofweek_of_month(year, month); 39361843Sobrien if (wday1 < 0) /* not set */ 39461843Sobrien return (wday1); 39561843Sobrien /* 39677298Sobrien * Date of zeroth or first of our weekday in month, depending on the 39761843Sobrien * relationship with the first of the month. The range is -6:6. 39861843Sobrien */ 39961843Sobrien d = (day - wday1 + 1) % 7; 40061843Sobrien /* 40161843Sobrien * Which way are we counting? Offset 0 is invalid, abs (offset) > 5 is 40233965Sjdp * meaningless, but that's OK. Offset 5 may or may not be meaningless, 40333965Sjdp * so there's no point in complaining for complaining's sake. 40433965Sjdp */ 40533965Sjdp if (offset < 0) { /* back from end of month */ 40633965Sjdp /* FIXME */ 40761843Sobrien wdayn = d; 40833965Sjdp while (wdayn <= yearinfo->monthdays[month]) 40933965Sjdp wdayn += 7; 41033965Sjdp d = offset * 7 + wdayn; 41133965Sjdp } else if (offset > 0){ 41233965Sjdp if (d > 0) 41333965Sjdp d += offset * 7 - 7; 41433965Sjdp else 41533965Sjdp d += offset * 7; 41633965Sjdp } else 41733965Sjdp warnx ("Invalid offset 0"); 41833965Sjdp return (d); 41933965Sjdp} 42033965Sjdp 42133965Sjdp/* 42233965Sjdp * Possible date formats include any combination of: 42333965Sjdp * 3-charmonth (January, Jan, Jan) 42433965Sjdp * 3-charweekday (Friday, Monday, mon.) 42533965Sjdp * numeric month or day (1, 2, 04) 42633965Sjdp * 42733965Sjdp * Any character may separate them, or they may not be separated. Any line, 42833965Sjdp * following a line that is matched, that starts with "whitespace", is shown 42933965Sjdp * along with the matched line. 43033965Sjdp */ 43133965Sjdpint 43233965Sjdpparsedaymonth(char *date, int *yearp, int *monthp, int *dayp, int *flags, 43333965Sjdp char **edp) 43433965Sjdp{ 43577298Sobrien char month[100], dayofmonth[100], dayofweek[100], modifieroffset[100]; 43677298Sobrien char syear[100]; 43777298Sobrien char modifierindex[100], specialday[100]; 43877298Sobrien int idayofweek = -1, imonth = -1, idayofmonth = -1, iyear = -1; 43977298Sobrien int year, remindex; 44077298Sobrien int d, m, dow, rm, rd, offset; 44177298Sobrien char *ed; 44277298Sobrien int retvalsign = 1; 44377298Sobrien 44477298Sobrien /* 44577298Sobrien * CONVENTION 44633965Sjdp * 44733965Sjdp * Month: 1-12 44833965Sjdp * Monthname: Jan .. Dec 44933965Sjdp * Day: 1-31 45033965Sjdp * Weekday: Mon .. Sun 45133965Sjdp * 45233965Sjdp */ 45333965Sjdp 45433965Sjdp *flags = 0; 45533965Sjdp 45633965Sjdp if (debug) 45733965Sjdp debug_determinestyle(1, date, *flags, month, imonth, 45833965Sjdp dayofmonth, idayofmonth, dayofweek, idayofweek, 45933965Sjdp modifieroffset, modifierindex, specialday, syear, iyear); 46033965Sjdp if (determinestyle(date, flags, month, &imonth, dayofmonth, 46133965Sjdp &idayofmonth, dayofweek, &idayofweek, modifieroffset, 46233965Sjdp modifierindex, specialday, syear, &iyear) == 0) { 46333965Sjdp if (debug) 46433965Sjdp printf("Failed!\n"); 46533965Sjdp return (0); 46633965Sjdp } 46733965Sjdp 46833965Sjdp if (debug) 46933965Sjdp debug_determinestyle(0, date, *flags, month, imonth, 47033965Sjdp dayofmonth, idayofmonth, dayofweek, idayofweek, 47133965Sjdp modifieroffset, modifierindex, specialday, syear, iyear); 47233965Sjdp 47333965Sjdp remindex = 0; 47433965Sjdp for (year = year1; year <= year2; year++) { 47533965Sjdp 47633965Sjdp int lflags = *flags; 47733965Sjdp /* If the year is specified, only do it if it is this year! */ 47833965Sjdp if ((lflags & F_YEAR) != 0) 47933965Sjdp if (iyear != year) 48033965Sjdp continue; 48133965Sjdp lflags &= ~F_YEAR; 48233965Sjdp 48333965Sjdp /* Get important dates for this year */ 48433965Sjdp yearinfo = years; 48533965Sjdp while (yearinfo != NULL) { 48633965Sjdp if (yearinfo->year == year) 48733965Sjdp break; 48833965Sjdp yearinfo = yearinfo -> next; 48933965Sjdp } 49033965Sjdp if (yearinfo == NULL) { 49133965Sjdp yearinfo = (struct yearinfo *)calloc(1, 49233965Sjdp sizeof(struct yearinfo)); 49333965Sjdp if (yearinfo == NULL) 49433965Sjdp errx(1, "Unable to allocate more years"); 49533965Sjdp yearinfo->year = year; 49633965Sjdp yearinfo->next = years; 49733965Sjdp years = yearinfo; 49833965Sjdp 49960484Sobrien yearinfo->monthdays = monthdaytab[isleap(year)]; 50033965Sjdp yearinfo->ieaster = easter(year); 50133965Sjdp yearinfo->ipaskha = paskha(year); 50233965Sjdp fpom(year, UTCOffset, yearinfo->ffullmoon, 50333965Sjdp yearinfo->fnewmoon); 50433965Sjdp fpom(year, UTCOFFSET_CNY, yearinfo->ffullmooncny, 50533965Sjdp yearinfo->fnewmooncny); 50633965Sjdp fequinoxsolstice(year, UTCOffset, 50733965Sjdp yearinfo->equinoxdays, yearinfo->solsticedays); 50833965Sjdp 50933965Sjdp /* 51033965Sjdp * CNY: Match day with sun longitude at 330` with new 51133965Sjdp * moon 51233965Sjdp */ 51333965Sjdp yearinfo->firstcnyday = calculatesunlongitude30(year, 51433965Sjdp UTCOFFSET_CNY, yearinfo->ichinesemonths); 51533965Sjdp for (m = 0; yearinfo->fnewmooncny[m] >= 0; m++) { 51633965Sjdp if (yearinfo->fnewmooncny[m] > 51733965Sjdp yearinfo->firstcnyday) { 51833965Sjdp yearinfo->firstcnyday = 51933965Sjdp floor(yearinfo->fnewmooncny[m - 1]); 52033965Sjdp break; 52133965Sjdp } 52233965Sjdp } 52333965Sjdp } 52433965Sjdp 52533965Sjdp /* Same day every year */ 52633965Sjdp if (lflags == (F_MONTH | F_DAYOFMONTH)) { 52733965Sjdp if (!remember_ymd(year, imonth, idayofmonth)) 52833965Sjdp continue; 52933965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 53033965Sjdp year, imonth, idayofmonth, NULL); 53133965Sjdp continue; 53233965Sjdp } 53333965Sjdp 53433965Sjdp /* XXX Same day every year, but variable */ 53533965Sjdp if (lflags == (F_MONTH | F_DAYOFMONTH | F_VARIABLE)) { 53633965Sjdp if (!remember_ymd(year, imonth, idayofmonth)) 53733965Sjdp continue; 53833965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 53933965Sjdp year, imonth, idayofmonth, NULL); 54033965Sjdp continue; 54133965Sjdp } 54238889Sjdp 54338889Sjdp /* Same day every month */ 54438889Sjdp if (lflags == (F_ALLMONTH | F_DAYOFMONTH)) { 54533965Sjdp for (m = 1; m <= 12; m++) { 54633965Sjdp if (!remember_ymd(year, m, idayofmonth)) 54733965Sjdp continue; 54833965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 54933965Sjdp year, m, idayofmonth, NULL); 55033965Sjdp } 55133965Sjdp continue; 55233965Sjdp } 55333965Sjdp 55433965Sjdp /* Every day of a month */ 55533965Sjdp if (lflags == (F_ALLDAY | F_MONTH)) { 55633965Sjdp for (d = 1; d <= yearinfo->monthdays[imonth]; d++) { 55733965Sjdp if (!remember_ymd(year, imonth, d)) 55833965Sjdp continue; 55933965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 56033965Sjdp year, imonth, d, NULL); 56133965Sjdp } 56233965Sjdp continue; 56360484Sobrien } 56460484Sobrien 56560484Sobrien /* One day of every month */ 56633965Sjdp if (lflags == (F_ALLMONTH | F_DAYOFWEEK)) { 56733965Sjdp for (m = 1; m <= 12; m++) { 56833965Sjdp if (!remember_ymd(year, m, idayofmonth)) 56960484Sobrien continue; 57060484Sobrien remember(&remindex, yearp, monthp, dayp, edp, 57160484Sobrien year, m, idayofmonth, NULL); 57233965Sjdp } 57360484Sobrien continue; 57460484Sobrien } 57533965Sjdp 57633965Sjdp /* Every dayofweek of the year */ 57733965Sjdp if (lflags == (F_DAYOFWEEK | F_VARIABLE)) { 57833965Sjdp dow = first_dayofweek_of_year(year); 57933965Sjdp d = (idayofweek - dow + 8) % 7; 58033965Sjdp while (d <= 366) { 58133965Sjdp if (remember_yd(year, d, &rm, &rd)) 58233965Sjdp remember(&remindex, 58333965Sjdp yearp, monthp, dayp, edp, 58433965Sjdp year, rm, rd, NULL); 58533965Sjdp d += 7; 58633965Sjdp } 58733965Sjdp continue; 58833965Sjdp } 58933965Sjdp 59033965Sjdp /* 59133965Sjdp * Every so-manied dayofweek of every month of the year: 59233965Sjdp * Thu-3 59333965Sjdp */ 59433965Sjdp if (lflags == (F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { 59533965Sjdp offset = indextooffset(modifierindex); 59633965Sjdp 59733965Sjdp for (m = 0; m <= 12; m++) { 59833965Sjdp d = wdayom (idayofweek, offset, m, year); 59933965Sjdp if (remember_ymd(year, m, d)) { 60033965Sjdp remember(&remindex, 60133965Sjdp yearp, monthp, dayp, edp, 60233965Sjdp year, m, d, NULL); 60333965Sjdp continue; 60433965Sjdp } 60533965Sjdp } 60660484Sobrien continue; 60733965Sjdp } 60833965Sjdp 60960484Sobrien /* 61033965Sjdp * A certain dayofweek of a month 61133965Sjdp * Jan/Thu-3 61233965Sjdp */ 61333965Sjdp if (lflags == 61433965Sjdp (F_MONTH | F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { 61533965Sjdp offset = indextooffset(modifierindex); 61660484Sobrien dow = first_dayofweek_of_month(year, imonth); 61760484Sobrien d = (idayofweek - dow + 8) % 7; 61860484Sobrien 61960484Sobrien if (offset > 0) { 62060484Sobrien while (d <= yearinfo->monthdays[imonth]) { 62160484Sobrien if (--offset == 0 62260484Sobrien && remember_ymd(year, imonth, d)) { 62360484Sobrien remember(&remindex, 62460484Sobrien yearp, monthp, dayp, edp, 62533965Sjdp year, imonth, d, NULL); 62633965Sjdp continue; 62733965Sjdp } 62860484Sobrien d += 7; 62933965Sjdp } 63033965Sjdp continue; 63133965Sjdp } 63233965Sjdp if (offset < 0) { 63333965Sjdp while (d <= yearinfo->monthdays[imonth]) 63433965Sjdp d += 7; 63533965Sjdp while (offset != 0) { 63633965Sjdp offset++; 63733965Sjdp d -= 7; 63833965Sjdp } 63933965Sjdp if (remember_ymd(year, imonth, d)) 64033965Sjdp remember(&remindex, 64133965Sjdp yearp, monthp, dayp, edp, 64233965Sjdp year, imonth, d, NULL); 64333965Sjdp continue; 64433965Sjdp } 64533965Sjdp continue; 64633965Sjdp } 64733965Sjdp 64833965Sjdp /* Every dayofweek of the month */ 64933965Sjdp if (lflags == (F_DAYOFWEEK | F_MONTH | F_VARIABLE)) { 65033965Sjdp dow = first_dayofweek_of_month(year, imonth); 65133965Sjdp d = (idayofweek - dow + 8) % 7; 65233965Sjdp while (d <= yearinfo->monthdays[imonth]) { 65333965Sjdp if (remember_ymd(year, imonth, d)) 65433965Sjdp remember(&remindex, 65533965Sjdp yearp, monthp, dayp, edp, 65633965Sjdp year, imonth, d, NULL); 65733965Sjdp d += 7; 65833965Sjdp } 65933965Sjdp continue; 66033965Sjdp } 66133965Sjdp 66233965Sjdp /* Easter */ 66333965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 66433965Sjdp (F_SPECIALDAY | F_VARIABLE | F_EASTER)) { 66533965Sjdp offset = 0; 66633965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 66733965Sjdp offset = parseoffset(modifieroffset); 66833965Sjdp if (remember_yd(year, yearinfo->ieaster + offset, 66960484Sobrien &rm, &rd)) 67033965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 67133965Sjdp year, rm, rd, NULL); 67233965Sjdp continue; 67360484Sobrien } 67433965Sjdp 67533965Sjdp /* Paskha */ 67633965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 67760484Sobrien (F_SPECIALDAY | F_VARIABLE | F_PASKHA)) { 67833965Sjdp offset = 0; 67933965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 68033965Sjdp offset = parseoffset(modifieroffset); 68133965Sjdp if (remember_yd(year, yearinfo->ipaskha + offset, 68233965Sjdp &rm, &rd)) 68360484Sobrien remember(&remindex, yearp, monthp, dayp, edp, 68460484Sobrien year, rm, rd, NULL); 68533965Sjdp continue; 68633965Sjdp } 68733965Sjdp 68833965Sjdp /* Chinese New Year */ 68933965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 69060484Sobrien (F_SPECIALDAY | F_VARIABLE | F_CNY)) { 69160484Sobrien offset = 0; 69233965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 69333965Sjdp offset = parseoffset(modifieroffset); 69433965Sjdp if (remember_yd(year, yearinfo->firstcnyday + offset, 69533965Sjdp &rm, &rd)) 69633965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 69733965Sjdp year, rm, rd, NULL); 69860484Sobrien continue; 69960484Sobrien } 70033965Sjdp 70133965Sjdp /* FullMoon */ 70233965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 70333965Sjdp (F_SPECIALDAY | F_VARIABLE | F_FULLMOON)) { 70460484Sobrien int i; 70560484Sobrien 70633965Sjdp offset = 0; 70733965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 70833965Sjdp offset = parseoffset(modifieroffset); 70933965Sjdp for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { 71033965Sjdp if (remember_yd(year, 71133965Sjdp floor(yearinfo->ffullmoon[i]) + offset, 71233965Sjdp &rm, &rd)) { 71333965Sjdp ed = floattotime( 71433965Sjdp yearinfo->ffullmoon[i]); 71533965Sjdp remember(&remindex, 71633965Sjdp yearp, monthp, dayp, edp, 71733965Sjdp year, rm, rd, ed); 71833965Sjdp } 71933965Sjdp } 72033965Sjdp continue; 72133965Sjdp } 72233965Sjdp 72333965Sjdp /* NewMoon */ 72433965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 72533965Sjdp (F_SPECIALDAY | F_VARIABLE | F_NEWMOON)) { 72633965Sjdp int i; 72733965Sjdp 72833965Sjdp offset = 0; 72933965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 73033965Sjdp offset = parseoffset(modifieroffset); 73133965Sjdp for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { 73233965Sjdp if (remember_yd(year, 73361843Sobrien floor(yearinfo->fnewmoon[i]) + offset, 73433965Sjdp &rm, &rd)) { 73561843Sobrien ed = floattotime(yearinfo->fnewmoon[i]); 73661843Sobrien remember(&remindex, 73761843Sobrien yearp, monthp, dayp, edp, 73861843Sobrien year, rm, rd, ed); 73961843Sobrien } 74033965Sjdp } 74161843Sobrien continue; 74233965Sjdp } 74333965Sjdp 74433965Sjdp /* (Mar|Sep)Equinox */ 74533965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 74633965Sjdp (F_SPECIALDAY | F_VARIABLE | F_MAREQUINOX)) { 74733965Sjdp offset = 0; 74833965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 74933965Sjdp offset = parseoffset(modifieroffset); 75033965Sjdp if (remember_yd(year, yearinfo->equinoxdays[0] + offset, 75133965Sjdp &rm, &rd)) { 75233965Sjdp ed = floattotime(yearinfo->equinoxdays[0]); 75333965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 75433965Sjdp year, rm, rd, ed); 75533965Sjdp } 75633965Sjdp continue; 75733965Sjdp } 75833965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 75933965Sjdp (F_SPECIALDAY | F_VARIABLE | F_SEPEQUINOX)) { 76033965Sjdp offset = 0; 76133965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 76233965Sjdp offset = parseoffset(modifieroffset); 76333965Sjdp if (remember_yd(year, yearinfo->equinoxdays[1] + offset, 76433965Sjdp &rm, &rd)) { 76533965Sjdp ed = floattotime(yearinfo->equinoxdays[1]); 76633965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 76733965Sjdp year, rm, rd, ed); 76833965Sjdp } 76933965Sjdp continue; 77033965Sjdp } 77133965Sjdp 77233965Sjdp /* (Jun|Dec)Solstice */ 77333965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 77433965Sjdp (F_SPECIALDAY | F_VARIABLE | F_JUNSOLSTICE)) { 77560484Sobrien offset = 0; 77660484Sobrien if ((lflags & F_MODIFIEROFFSET) != 0) 77760484Sobrien offset = parseoffset(modifieroffset); 77833965Sjdp if (remember_yd(year, 77933965Sjdp yearinfo->solsticedays[0] + offset, &rm, &rd)) { 78033965Sjdp ed = floattotime(yearinfo->solsticedays[0]); 78133965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 78233965Sjdp year, rm, rd, ed); 78333965Sjdp } 78433965Sjdp continue; 78533965Sjdp } 78633965Sjdp if ((lflags & ~F_MODIFIEROFFSET) == 78733965Sjdp (F_SPECIALDAY | F_VARIABLE | F_DECSOLSTICE)) { 78833965Sjdp offset = 0; 78933965Sjdp if ((lflags & F_MODIFIEROFFSET) != 0) 79033965Sjdp offset = parseoffset(modifieroffset); 79133965Sjdp if (remember_yd(year, 79233965Sjdp yearinfo->solsticedays[1] + offset, &rm, &rd)) { 79333965Sjdp ed = floattotime(yearinfo->solsticedays[1]); 79433965Sjdp remember(&remindex, yearp, monthp, dayp, edp, 79533965Sjdp year, rm, rd, ed); 79633965Sjdp } 79733965Sjdp continue; 79833965Sjdp } 79933965Sjdp 80033965Sjdp if (debug) { 80133965Sjdp printf("Unprocessed:\n"); 80233965Sjdp debug_determinestyle(2, date, lflags, month, imonth, 80333965Sjdp dayofmonth, idayofmonth, dayofweek, idayofweek, 80433965Sjdp modifieroffset, modifierindex, specialday, syear, 80533965Sjdp iyear); 80633965Sjdp } 80733965Sjdp retvalsign = -1; 80833965Sjdp } 80933965Sjdp 81033965Sjdp if (retvalsign == -1) 81133965Sjdp return (-remindex - 1); 81233965Sjdp else 81333965Sjdp return (remindex); 81433965Sjdp} 81533965Sjdp 81633965Sjdpstatic char * 81733965Sjdpshowflags(int flags) 81833965Sjdp{ 81933965Sjdp static char s[1000]; 82033965Sjdp s[0] = '\0'; 82133965Sjdp 82233965Sjdp if ((flags & F_YEAR) != 0) 82360484Sobrien strcat(s, "year "); 82460484Sobrien if ((flags & F_MONTH) != 0) 82533965Sjdp strcat(s, "month "); 82633965Sjdp if ((flags & F_DAYOFWEEK) != 0) 82777298Sobrien strcat(s, "dayofweek "); 82877298Sobrien if ((flags & F_DAYOFMONTH) != 0) 82933965Sjdp strcat(s, "dayofmonth "); 83033965Sjdp if ((flags & F_MODIFIERINDEX) != 0) 83133965Sjdp strcat(s, "modifierindex "); 83233965Sjdp if ((flags & F_MODIFIEROFFSET) != 0) 83333965Sjdp strcat(s, "modifieroffset "); 83433965Sjdp if ((flags & F_SPECIALDAY) != 0) 83533965Sjdp strcat(s, "specialday "); 83633965Sjdp if ((flags & F_ALLMONTH) != 0) 83733965Sjdp strcat(s, "allmonth "); 83833965Sjdp if ((flags & F_ALLDAY) != 0) 83933965Sjdp strcat(s, "allday "); 84033965Sjdp if ((flags & F_VARIABLE) != 0) 84133965Sjdp strcat(s, "variable "); 84233965Sjdp if ((flags & F_CNY) != 0) 84333965Sjdp strcat(s, "chinesenewyear "); 84460484Sobrien if ((flags & F_PASKHA) != 0) 84560484Sobrien strcat(s, "paskha "); 84633965Sjdp if ((flags & F_EASTER) != 0) 84733965Sjdp strcat(s, "easter "); 84833965Sjdp if ((flags & F_FULLMOON) != 0) 84933965Sjdp strcat(s, "fullmoon "); 85033965Sjdp if ((flags & F_NEWMOON) != 0) 85133965Sjdp strcat(s, "newmoon "); 85233965Sjdp if ((flags & F_MAREQUINOX) != 0) 85333965Sjdp strcat(s, "marequinox "); 85433965Sjdp if ((flags & F_SEPEQUINOX) != 0) 85533965Sjdp strcat(s, "sepequinox "); 85633965Sjdp if ((flags & F_JUNSOLSTICE) != 0) 85733965Sjdp strcat(s, "junsolstice "); 85833965Sjdp if ((flags & F_DECSOLSTICE) != 0) 85933965Sjdp strcat(s, "decsolstice "); 86033965Sjdp 86133965Sjdp return s; 86233965Sjdp} 86333965Sjdp 86433965Sjdpstatic const char * 86533965Sjdpgetmonthname(int i) 86633965Sjdp{ 86733965Sjdp if (i <= 0 || i > 12) 86833965Sjdp return (""); 86933965Sjdp if (nmonths[i - 1].len != 0 && nmonths[i - 1].name != NULL) 87060484Sobrien return (nmonths[i - 1].name); 87133965Sjdp return (months[i - 1]); 87233965Sjdp} 87360484Sobrien 87433965Sjdpstatic int 87560484Sobriencheckmonth(char *s, size_t *len, size_t *offset, const char **month) 87660484Sobrien{ 87733965Sjdp struct fixs *n; 87833965Sjdp int i; 87960484Sobrien 88060484Sobrien for (i = 0; fnmonths[i].name != NULL; i++) { 88160484Sobrien n = fnmonths + i; 88260484Sobrien if (strncasecmp(s, n->name, n->len) == 0) { 88333965Sjdp *len = n->len; 88433965Sjdp *month = n->name; 88533965Sjdp *offset = i + 1; 88633965Sjdp return (1); 88733965Sjdp } 88860484Sobrien } 88933965Sjdp for (i = 0; nmonths[i].name != NULL; i++) { 89033965Sjdp n = nmonths + i; 89133965Sjdp if (strncasecmp(s, n->name, n->len) == 0) { 89233965Sjdp *len = n->len; 89333965Sjdp *month = n->name; 89433965Sjdp *offset = i + 1; 89560484Sobrien return (1); 89633965Sjdp } 89733965Sjdp } 89833965Sjdp for (i = 0; fmonths[i] != NULL; i++) { 89933965Sjdp *len = strlen(fmonths[i]); 90033965Sjdp if (strncasecmp(s, fmonths[i], *len) == 0) { 90133965Sjdp *month = fmonths[i]; 90233965Sjdp *offset = i + 1; 90333965Sjdp return (1); 90433965Sjdp } 90533965Sjdp } 90633965Sjdp for (i = 0; months[i] != NULL; i++) { 90733965Sjdp if (strncasecmp(s, months[i], 3) == 0) { 90833965Sjdp *len = 3; 90933965Sjdp *month = months[i]; 91033965Sjdp *offset = i + 1; 91133965Sjdp return (1); 91260484Sobrien } 91360484Sobrien } 91433965Sjdp return (0); 91533965Sjdp} 91633965Sjdp 91760484Sobrienstatic const char * 91833965Sjdpgetdayofweekname(int i) 91933965Sjdp{ 92033965Sjdp if (ndays[i].len != 0 && ndays[i].name != NULL) 92133965Sjdp return (ndays[i].name); 92233965Sjdp return (days[i]); 92360484Sobrien} 92433965Sjdp 92533965Sjdpstatic int 92633965Sjdpcheckdayofweek(char *s, size_t *len, size_t *offset, const char **dow) 92733965Sjdp{ 92833965Sjdp struct fixs *n; 92933965Sjdp int i; 93033965Sjdp 93133965Sjdp for (i = 0; fndays[i].name != NULL; i++) { 93233965Sjdp n = fndays + i; 93333965Sjdp if (strncasecmp(s, n->name, n->len) == 0) { 93433965Sjdp *len = n->len; 93560484Sobrien *dow = n->name; 93660484Sobrien *offset = i; 93733965Sjdp return (1); 93833965Sjdp } 93933965Sjdp } 94033965Sjdp for (i = 0; ndays[i].name != NULL; i++) { 94133965Sjdp n = ndays + i; 94233965Sjdp if (strncasecmp(s, n->name, n->len) == 0) { 94333965Sjdp *len = n->len; 94460484Sobrien *dow = n->name; 94560484Sobrien *offset = i; 94660484Sobrien return (1); 94733965Sjdp } 94833965Sjdp } 94933965Sjdp for (i = 0; fdays[i] != NULL; i++) { 95033965Sjdp *len = strlen(fdays[i]); 95133965Sjdp if (strncasecmp(s, fdays[i], *len) == 0) { 95233965Sjdp *dow = fdays[i]; 95333965Sjdp *offset = i; 95433965Sjdp return (1); 95533965Sjdp } 95633965Sjdp } 95733965Sjdp for (i = 0; days[i] != NULL; i++) { 95833965Sjdp if (strncasecmp(s, days[i], 3) == 0) { 95933965Sjdp *len = 3; 96033965Sjdp *dow = days[i]; 96133965Sjdp *offset = i; 96233965Sjdp return (1); 96333965Sjdp } 96433965Sjdp } 96533965Sjdp return (0); 96633965Sjdp} 96733965Sjdp 96833965Sjdpstatic int 96933965Sjdpisonlydigits(char *s, int nostar) 97033965Sjdp{ 97133965Sjdp int i; 97261843Sobrien for (i = 0; s[i] != '\0'; i++) { 97333965Sjdp if (nostar == 0 && s[i] == '*' && s[i + 1] == '\0') 97461843Sobrien return 1; 97561843Sobrien if (!isdigit((unsigned char)s[i])) 97661843Sobrien return (0); 97761843Sobrien } 97861843Sobrien return (1); 97961843Sobrien} 98061843Sobrien 98161843Sobrienstatic int 98233965Sjdpindextooffset(char *s) 98361843Sobrien{ 98433965Sjdp int i; 98533965Sjdp struct fixs *n; 98633965Sjdp char *es; 98733965Sjdp 98833965Sjdp if (s[0] == '+' || s[0] == '-') { 98933965Sjdp i = strtol (s, &es, 10); 99033965Sjdp if (*es != '\0') /* trailing junk */ 99133965Sjdp errx (1, "Invalid specifier format: %s\n", s); 99233965Sjdp return (i); 99333965Sjdp } 99433965Sjdp 99533965Sjdp for (i = 0; i < 6; i++) { 99633965Sjdp if (strcasecmp(s, sequences[i]) == 0) { 99733965Sjdp if (i == 5) 99833965Sjdp return (-1); 99933965Sjdp return (i + 1); 100033965Sjdp } 100133965Sjdp } 100233965Sjdp for (i = 0; i < 6; i++) { 100333965Sjdp n = nsequences + i; 100433965Sjdp if (n->len == 0) 100533965Sjdp continue; 100633965Sjdp if (strncasecmp(s, n->name, n->len) == 0) { 100760484Sobrien if (i == 5) 100860484Sobrien return (-1); 100933965Sjdp return (i + 1); 101033965Sjdp } 101133965Sjdp } 101233965Sjdp return (0); 101333965Sjdp} 101460484Sobrien 101560484Sobrienstatic int 101633965Sjdpparseoffset(char *s) 101733965Sjdp{ 101833965Sjdp return strtol(s, NULL, 10); 101933965Sjdp} 102033965Sjdp 102133965Sjdpstatic char * 102233965Sjdpfloattotime(double f) 102333965Sjdp{ 102433965Sjdp static char buf[100]; 102533965Sjdp int hh, mm, ss, i; 102633965Sjdp 102733965Sjdp f -= floor(f); 102833965Sjdp i = f * SECSPERDAY; 102933965Sjdp 103033965Sjdp hh = i / SECSPERHOUR; 103133965Sjdp i %= SECSPERHOUR; 103233965Sjdp mm = i / SECSPERMINUTE; 103333965Sjdp i %= SECSPERMINUTE; 103433965Sjdp ss = i; 103533965Sjdp 103633965Sjdp sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); 103733965Sjdp return (buf); 103833965Sjdp} 103933965Sjdp 104033965Sjdpstatic char * 104133965Sjdpfloattoday(int year, double f) 104233965Sjdp{ 104333965Sjdp static char buf[100]; 104433965Sjdp int i, m, d, hh, mm, ss; 104533965Sjdp int *cumdays = cumdaytab[isleap(year)]; 104633965Sjdp 104733965Sjdp for (i = 0; 1 + cumdays[i] < f; i++) 104833965Sjdp ; 104933965Sjdp m = --i; 105033965Sjdp d = floor(f - 1 - cumdays[i]); 105133965Sjdp f -= floor(f); 105233965Sjdp i = f * SECSPERDAY; 105333965Sjdp 105433965Sjdp hh = i / SECSPERHOUR; 105533965Sjdp i %= SECSPERHOUR; 105633965Sjdp mm = i / SECSPERMINUTE; 105733965Sjdp i %= SECSPERMINUTE; 105833965Sjdp ss = i; 105933965Sjdp 106033965Sjdp sprintf(buf, "%02d-%02d %02d:%02d:%02d", m, d, hh, mm, ss); 106133965Sjdp return (buf); 106233965Sjdp} 106333965Sjdp 106433965Sjdpvoid 106533965Sjdpdodebug(char *what) 106633965Sjdp{ 106733965Sjdp int year; 106833965Sjdp 106933965Sjdp printf("UTCOffset: %g\n", UTCOffset); 107033965Sjdp printf("eastlongitude: %d\n", EastLongitude); 107133965Sjdp 107233965Sjdp if (strcmp(what, "moon") == 0) { 107333965Sjdp double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; 107433965Sjdp int i; 107533965Sjdp 107633965Sjdp for (year = year1; year <= year2; year++) { 107733965Sjdp fpom(year, UTCOffset, ffullmoon, fnewmoon); 107833965Sjdp printf("Full moon %d:\t", year); 107933965Sjdp for (i = 0; ffullmoon[i] >= 0; i++) { 108033965Sjdp printf("%g (%s) ", ffullmoon[i], 108133965Sjdp floattoday(year, ffullmoon[i])); 108233965Sjdp } 108333965Sjdp printf("\nNew moon %d:\t", year); 108433965Sjdp for (i = 0; fnewmoon[i] >= 0; i++) { 108533965Sjdp printf("%g (%s) ", fnewmoon[i], 108633965Sjdp floattoday(year, fnewmoon[i])); 108733965Sjdp } 108833965Sjdp printf("\n"); 108933965Sjdp 109033965Sjdp } 109133965Sjdp 109233965Sjdp return; 109333965Sjdp } 109433965Sjdp 109533965Sjdp if (strcmp(what, "sun") == 0) { 109633965Sjdp double equinoxdays[2], solsticedays[2]; 109733965Sjdp for (year = year1; year <= year2; year++) { 109833965Sjdp printf("Sun in %d:\n", year); 109933965Sjdp fequinoxsolstice(year, UTCOffset, equinoxdays, 110033965Sjdp solsticedays); 110133965Sjdp printf("e[0] - %g (%s)\n", 110233965Sjdp equinoxdays[0], 110333965Sjdp floattoday(year, equinoxdays[0])); 110433965Sjdp printf("e[1] - %g (%s)\n", 110533965Sjdp equinoxdays[1], 110633965Sjdp floattoday(year, equinoxdays[1])); 110733965Sjdp printf("s[0] - %g (%s)\n", 110833965Sjdp solsticedays[0], 110933965Sjdp floattoday(year, solsticedays[0])); 111033965Sjdp printf("s[1] - %g (%s)\n", 111133965Sjdp solsticedays[1], 111233965Sjdp floattoday(year, solsticedays[1])); 111333965Sjdp } 111433965Sjdp return; 111533965Sjdp } 111660484Sobrien} 111760484Sobrien