1205821Sedwin/*- 2205872Sedwin * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>. 3205872Sedwin * All rights reserved. 4205821Sedwin * 5205821Sedwin * Redistribution and use in source and binary forms, with or without 6205821Sedwin * modification, are permitted provided that the following conditions 7205821Sedwin * are met: 8205821Sedwin * 1. Redistributions of source code must retain the above copyright 9205821Sedwin * notice, this list of conditions and the following disclaimer. 10205821Sedwin * 2. Redistributions in binary form must reproduce the above copyright 11205821Sedwin * notice, this list of conditions and the following disclaimer in the 12205821Sedwin * documentation and/or other materials provided with the distribution. 13227370Sgrog * 14205821Sedwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15205821Sedwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16205821Sedwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17205821Sedwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18205821Sedwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19205821Sedwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20205821Sedwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21205821Sedwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22205821Sedwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23205821Sedwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24205821Sedwin * SUCH DAMAGE. 25227370Sgrog * 26205821Sedwin */ 27205821Sedwin 28205821Sedwin#include <sys/cdefs.h> 29205821Sedwin__FBSDID("$FreeBSD$"); 30205821Sedwin 31205821Sedwin#include <ctype.h> 32205821Sedwin#include <math.h> 33205821Sedwin#include <stdio.h> 34205821Sedwin#include <stdlib.h> 35205821Sedwin#include <string.h> 36205821Sedwin#include <err.h> 37205821Sedwin 38205821Sedwin#include "calendar.h" 39205821Sedwin 40205821Sedwinstatic char *showflags(int flags); 41205821Sedwinstatic int isonlydigits(char *s, int nostar); 42205821Sedwinstatic const char *getmonthname(int i); 43205834Sdesstatic int checkmonth(char *s, size_t *len, size_t *offset, const char **month); 44205821Sedwinstatic const char *getdayofweekname(int i); 45205834Sdesstatic int checkdayofweek(char *s, size_t *len, size_t *offset, const char **dow); 46205821Sedwinstatic int indextooffset(char *s); 47205821Sedwinstatic int parseoffset(char *s); 48205821Sedwinstatic char *floattoday(int year, double f); 49205821Sedwinstatic char *floattotime(double f); 50251647Sgrogstatic int wdayom (int day, int offset, int month, int year); 51205821Sedwin 52205821Sedwin/* 53205821Sedwin * Expected styles: 54205821Sedwin * 55205821Sedwin * Date ::= Month . ' ' . DayOfMonth | 56205821Sedwin * Month . ' ' . DayOfWeek . ModifierIndex | 57205821Sedwin * Month . '/' . DayOfMonth | 58205821Sedwin * Month . '/' . DayOfWeek . ModifierIndex | 59205821Sedwin * DayOfMonth . ' ' . Month | 60205821Sedwin * DayOfMonth . '/' . Month | 61205821Sedwin * DayOfWeek . ModifierIndex . ' ' .Month | 62205821Sedwin * DayOfWeek . ModifierIndex . '/' .Month | 63205821Sedwin * DayOfWeek . ModifierIndex | 64205821Sedwin * SpecialDay . ModifierOffset 65205821Sedwin * 66205821Sedwin * Month ::= MonthName | MonthNumber | '*' 67205821Sedwin * MonthNumber ::= '0' ... '9' | '00' ... '09' | '10' ... '12' 68205821Sedwin * MonthName ::= MonthNameShort | MonthNameLong 69205821Sedwin * MonthNameLong ::= 'January' ... 'December' 70205821Sedwin * MonthNameShort ::= 'Jan' ... 'Dec' | 'Jan.' ... 'Dec.' 71205821Sedwin * 72205821Sedwin * DayOfWeek ::= DayOfWeekShort | DayOfWeekLong 73205821Sedwin * DayOfWeekShort ::= 'Mon' .. 'Sun' 74205821Sedwin * DayOfWeekLong ::= 'Monday' .. 'Sunday' 75205821Sedwin * DayOfMonth ::= '0' ... '9' | '00' ... '09' | '10' ... '29' | 76205821Sedwin * '30' ... '31' | '*' 77205821Sedwin * 78205821Sedwin * ModifierOffset ::= '' | '+' . ModifierNumber | '-' . ModifierNumber 79205821Sedwin * ModifierNumber ::= '0' ... '9' | '00' ... '99' | '000' ... '299' | 80205821Sedwin * '300' ... '359' | '360' ... '365' 81205821Sedwin * ModifierIndex ::= 'Second' | 'Third' | 'Fourth' | 'Fifth' | 82205821Sedwin * 'First' | 'Last' 83227370Sgrog * 84216697Sosa * SpecialDay ::= 'Easter' | 'Paskha' | 'ChineseNewYear' 85205821Sedwin * 86205821Sedwin */ 87205821Sedwinstatic int 88205821Sedwindeterminestyle(char *date, int *flags, 89205821Sedwin char *month, int *imonth, char *dayofmonth, int *idayofmonth, 90205821Sedwin char *dayofweek, int *idayofweek, char *modifieroffset, 91212035Sedwin char *modifierindex, char *specialday, char *year, int *iyear) 92205821Sedwin{ 93212035Sedwin char *p, *p1, *p2, *py; 94205821Sedwin const char *dow, *pmonth; 95205821Sedwin char pold; 96205821Sedwin size_t len, offset; 97205821Sedwin 98205821Sedwin *flags = F_NONE; 99205821Sedwin *month = '\0'; 100205821Sedwin *imonth = 0; 101212035Sedwin *year = '\0'; 102212035Sedwin *iyear = 0; 103205821Sedwin *dayofmonth = '\0'; 104205821Sedwin *idayofmonth = 0; 105205821Sedwin *dayofweek = '\0'; 106205821Sedwin *idayofweek = 0; 107205821Sedwin *modifieroffset = '\0'; 108205821Sedwin *modifierindex = '\0'; 109205821Sedwin *specialday = '\0'; 110205821Sedwin 111205821Sedwin#define CHECKSPECIAL(s1, s2, lens2, type) \ 112205821Sedwin if (s2 != NULL && strncmp(s1, s2, lens2) == 0) { \ 113205821Sedwin *flags |= F_SPECIALDAY; \ 114205821Sedwin *flags |= type; \ 115205821Sedwin *flags |= F_VARIABLE; \ 116205821Sedwin if (strlen(s1) == lens2) { \ 117205821Sedwin strcpy(specialday, s1); \ 118205821Sedwin return (1); \ 119205821Sedwin } \ 120205821Sedwin strncpy(specialday, s1, lens2); \ 121205821Sedwin specialday[lens2] = '\0'; \ 122205821Sedwin strcpy(modifieroffset, s1 + lens2); \ 123205821Sedwin *flags |= F_MODIFIEROFFSET; \ 124205821Sedwin return (1); \ 125205821Sedwin } 126205821Sedwin 127205821Sedwin if ((p = strchr(date, ' ')) == NULL) { 128205821Sedwin if ((p = strchr(date, '/')) == NULL) { 129205821Sedwin CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY), 130205821Sedwin F_CNY); 131205821Sedwin CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY); 132205821Sedwin CHECKSPECIAL(date, STRING_NEWMOON, 133205821Sedwin strlen(STRING_NEWMOON), F_NEWMOON); 134205821Sedwin CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len, 135205821Sedwin F_NEWMOON); 136205821Sedwin CHECKSPECIAL(date, STRING_FULLMOON, 137205821Sedwin strlen(STRING_FULLMOON), F_FULLMOON); 138205821Sedwin CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len, 139205821Sedwin F_FULLMOON); 140205821Sedwin CHECKSPECIAL(date, STRING_PASKHA, 141205821Sedwin strlen(STRING_PASKHA), F_PASKHA); 142205821Sedwin CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA); 143205821Sedwin CHECKSPECIAL(date, STRING_EASTER, 144205821Sedwin strlen(STRING_EASTER), F_EASTER); 145205821Sedwin CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER); 146205821Sedwin CHECKSPECIAL(date, STRING_MAREQUINOX, 147205821Sedwin strlen(STRING_MAREQUINOX), F_MAREQUINOX); 148205821Sedwin CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len, 149205821Sedwin F_SEPEQUINOX); 150205821Sedwin CHECKSPECIAL(date, STRING_SEPEQUINOX, 151205821Sedwin strlen(STRING_SEPEQUINOX), F_SEPEQUINOX); 152205821Sedwin CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len, 153205821Sedwin F_SEPEQUINOX); 154205821Sedwin CHECKSPECIAL(date, STRING_JUNSOLSTICE, 155205821Sedwin strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE); 156205821Sedwin CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len, 157205821Sedwin F_JUNSOLSTICE); 158205821Sedwin CHECKSPECIAL(date, STRING_DECSOLSTICE, 159205821Sedwin strlen(STRING_DECSOLSTICE), F_DECSOLSTICE); 160205821Sedwin CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len, 161205821Sedwin F_DECSOLSTICE); 162205821Sedwin if (checkdayofweek(date, &len, &offset, &dow) != 0) { 163205821Sedwin *flags |= F_DAYOFWEEK; 164205821Sedwin *flags |= F_VARIABLE; 165205821Sedwin *idayofweek = offset; 166205821Sedwin if (strlen(date) == len) { 167205821Sedwin strcpy(dayofweek, date); 168205821Sedwin return (1); 169205821Sedwin } 170205821Sedwin strncpy(dayofweek, date, len); 171205821Sedwin dayofweek[len] = '\0'; 172205821Sedwin strcpy(modifierindex, date + len); 173205821Sedwin *flags |= F_MODIFIERINDEX; 174205821Sedwin return (1); 175205821Sedwin } 176205821Sedwin if (isonlydigits(date, 1)) { 177205821Sedwin /* Assume month number only */ 178205821Sedwin *flags |= F_MONTH; 179205821Sedwin *imonth = (int)strtol(date, (char **)NULL, 10); 180205821Sedwin strcpy(month, getmonthname(*imonth)); 181205821Sedwin return(1); 182205821Sedwin } 183205821Sedwin return (0); 184205821Sedwin } 185205821Sedwin } 186205821Sedwin 187205821Sedwin /* 188251647Sgrog * After this, leave by goto-ing to "allfine" or "fail" to restore the 189205821Sedwin * original data in `date'. 190205821Sedwin */ 191205821Sedwin pold = *p; 192205821Sedwin *p = 0; 193205821Sedwin p1 = date; 194205821Sedwin p2 = p + 1; 195205821Sedwin /* Now p2 points to the next field and p1 to the first field */ 196205821Sedwin 197212035Sedwin if ((py = strchr(p2, '/')) != NULL) { 198212035Sedwin /* We have a year in the string. Now this is getting tricky */ 199212035Sedwin strcpy(year, p1); 200212035Sedwin *iyear = (int)strtol(year, NULL, 10); 201212035Sedwin p1 = p2; 202212035Sedwin p2 = py + 1; 203212035Sedwin *py = 0; 204212035Sedwin *flags |= F_YEAR; 205212035Sedwin } 206212035Sedwin 207205821Sedwin /* Check if there is a month-string in the date */ 208205821Sedwin if ((checkmonth(p1, &len, &offset, &pmonth) != 0) 209251647Sgrog || (checkmonth(p2, &len, &offset, &pmonth) != 0 && (p2 = p1))) { 210205821Sedwin /* p2 is the non-month part */ 211205821Sedwin *flags |= F_MONTH; 212205821Sedwin *imonth = offset; 213205821Sedwin 214205821Sedwin strcpy(month, getmonthname(offset)); 215205821Sedwin if (isonlydigits(p2, 1)) { 216205821Sedwin strcpy(dayofmonth, p2); 217205821Sedwin *idayofmonth = (int)strtol(p2, (char **)NULL, 10); 218205821Sedwin *flags |= F_DAYOFMONTH; 219205821Sedwin goto allfine; 220205821Sedwin } 221205821Sedwin if (strcmp(p2, "*") == 0) { 222205821Sedwin *flags |= F_ALLDAY; 223205821Sedwin goto allfine; 224205821Sedwin } 225205821Sedwin 226205821Sedwin if (checkdayofweek(p2, &len, &offset, &dow) != 0) { 227205821Sedwin *flags |= F_DAYOFWEEK; 228205821Sedwin *flags |= F_VARIABLE; 229205821Sedwin *idayofweek = offset; 230205821Sedwin strcpy(dayofweek, getdayofweekname(offset)); 231205821Sedwin if (strlen(p2) == len) 232205821Sedwin goto allfine; 233205821Sedwin strcpy(modifierindex, p2 + len); 234205821Sedwin *flags |= F_MODIFIERINDEX; 235205821Sedwin goto allfine; 236205821Sedwin } 237205821Sedwin goto fail; 238205821Sedwin } 239205821Sedwin 240205821Sedwin /* Check if there is an every-day or every-month in the string */ 241205821Sedwin if ((strcmp(p1, "*") == 0 && isonlydigits(p2, 1)) 242251647Sgrog || (strcmp(p2, "*") == 0 && isonlydigits(p1, 1) && (p2 = p1))) { 243205821Sedwin int d; 244205821Sedwin 245205821Sedwin *flags |= F_ALLMONTH; 246205821Sedwin *flags |= F_DAYOFMONTH; 247205821Sedwin d = (int)strtol(p2, (char **)NULL, 10); 248205821Sedwin *idayofmonth = d; 249205821Sedwin sprintf(dayofmonth, "%d", d); 250205821Sedwin goto allfine; 251205821Sedwin } 252205821Sedwin 253205821Sedwin /* Month as a number, then a weekday */ 254205821Sedwin if (isonlydigits(p1, 1) 255251647Sgrog && checkdayofweek(p2, &len, &offset, &dow) != 0) { 256205821Sedwin int d; 257205821Sedwin 258205821Sedwin *flags |= F_MONTH; 259205821Sedwin *flags |= F_DAYOFWEEK; 260205821Sedwin *flags |= F_VARIABLE; 261205821Sedwin 262205821Sedwin *idayofweek = offset; 263205821Sedwin d = (int)strtol(p1, (char **)NULL, 10); 264205821Sedwin *imonth = d; 265205821Sedwin strcpy(month, getmonthname(d)); 266205821Sedwin 267205821Sedwin strcpy(dayofweek, getdayofweekname(offset)); 268205821Sedwin if (strlen(p2) == len) 269205821Sedwin goto allfine; 270205821Sedwin strcpy(modifierindex, p2 + len); 271205821Sedwin *flags |= F_MODIFIERINDEX; 272205821Sedwin goto allfine; 273205821Sedwin } 274205821Sedwin 275205821Sedwin /* If both the month and date are specified as numbers */ 276205821Sedwin if (isonlydigits(p1, 1) && isonlydigits(p2, 0)) { 277205821Sedwin /* Now who wants to be this ambigious? :-( */ 278205821Sedwin int m, d; 279205821Sedwin 280205821Sedwin if (strchr(p2, '*') != NULL) 281205821Sedwin *flags |= F_VARIABLE; 282205821Sedwin 283205821Sedwin m = (int)strtol(p1, (char **)NULL, 10); 284205821Sedwin d = (int)strtol(p2, (char **)NULL, 10); 285205821Sedwin 286205821Sedwin *flags |= F_MONTH; 287205821Sedwin *flags |= F_DAYOFMONTH; 288205821Sedwin 289205821Sedwin if (m > 12) { 290205821Sedwin *imonth = d; 291205821Sedwin *idayofmonth = m; 292205821Sedwin strcpy(month, getmonthname(d)); 293205821Sedwin sprintf(dayofmonth, "%d", m); 294205821Sedwin } else { 295205821Sedwin *imonth = m; 296205821Sedwin *idayofmonth = d; 297205821Sedwin strcpy(month, getmonthname(m)); 298205821Sedwin sprintf(dayofmonth, "%d", d); 299205821Sedwin } 300205821Sedwin goto allfine; 301205821Sedwin } 302205821Sedwin 303205821Sedwin /* FALLTHROUGH */ 304205821Sedwinfail: 305205821Sedwin *p = pold; 306205821Sedwin return (0); 307205821Sedwinallfine: 308205821Sedwin *p = pold; 309205821Sedwin return (1); 310227370Sgrog 311205821Sedwin} 312205821Sedwin 313251647Sgrogvoid 314205821Sedwinremember(int *rememberindex, int *y, int *m, int *d, char **ed, int yy, int mm, 315251647Sgrog int dd, char *extra); 316251647Sgrogvoid 317251647Sgrogremember(int *rememberindex, int *y, int *m, int *d, char **ed, int yy, int mm, 318205821Sedwin int dd, char *extra) 319205821Sedwin{ 320205821Sedwin static int warned = 0; 321205821Sedwin 322205821Sedwin if (*rememberindex >= MAXCOUNT - 1) { 323205821Sedwin if (warned == 0) 324205821Sedwin warnx("Index > %d, ignored", MAXCOUNT); 325205821Sedwin warned++; 326205821Sedwin return; 327205821Sedwin } 328205821Sedwin y[*rememberindex] = yy; 329205821Sedwin m[*rememberindex] = mm; 330205821Sedwin d[*rememberindex] = dd; 331205821Sedwin if (extra != NULL) 332205821Sedwin strcpy(ed[*rememberindex], extra); 333205821Sedwin else 334205821Sedwin ed[*rememberindex][0] = '\0'; 335205821Sedwin *rememberindex += 1; 336205821Sedwin} 337205821Sedwin 338205821Sedwinstatic void 339205821Sedwindebug_determinestyle(int dateonly, char *date, int flags, char *month, 340205821Sedwin int imonth, char *dayofmonth, int idayofmonth, char *dayofweek, 341212035Sedwin int idayofweek, char *modifieroffset, char *modifierindex, char *specialday, 342212035Sedwin char *year, int iyear) 343205821Sedwin{ 344205821Sedwin 345205821Sedwin if (dateonly != 0) { 346205821Sedwin printf("-------\ndate: |%s|\n", date); 347205821Sedwin if (dateonly == 1) 348205821Sedwin return; 349205821Sedwin } 350205821Sedwin printf("flags: %x - %s\n", flags, showflags(flags)); 351205821Sedwin if (modifieroffset[0] != '\0') 352205821Sedwin printf("modifieroffset: |%s|\n", modifieroffset); 353205821Sedwin if (modifierindex[0] != '\0') 354205821Sedwin printf("modifierindex: |%s|\n", modifierindex); 355212035Sedwin if (year[0] != '\0') 356212035Sedwin printf("year: |%s| (%d)\n", year, iyear); 357205821Sedwin if (month[0] != '\0') 358205821Sedwin printf("month: |%s| (%d)\n", month, imonth); 359205821Sedwin if (dayofmonth[0] != '\0') 360205821Sedwin printf("dayofmonth: |%s| (%d)\n", dayofmonth, idayofmonth); 361205821Sedwin if (dayofweek[0] != '\0') 362205821Sedwin printf("dayofweek: |%s| (%d)\n", dayofweek, idayofweek); 363205821Sedwin if (specialday[0] != '\0') 364205821Sedwin printf("specialday: |%s|\n", specialday); 365205821Sedwin} 366205821Sedwin 367251647Sgrogstatic struct yearinfo { 368205821Sedwin int year; 369205821Sedwin int ieaster, ipaskha, firstcnyday; 370205821Sedwin double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; 371205821Sedwin double ffullmooncny[MAXMOONS], fnewmooncny[MAXMOONS]; 372205821Sedwin int ichinesemonths[MAXMOONS]; 373205821Sedwin double equinoxdays[2], solsticedays[2]; 374251647Sgrog int *monthdays; 375205821Sedwin struct yearinfo *next; 376251647Sgrog} *years, *yearinfo; 377251647Sgrog 378205821Sedwin/* 379251647Sgrog * Calculate dates with offset from weekdays, like Thurs-3, Wed+2, etc. 380251647Sgrog * day is the day of the week, 381251647Sgrog * offset the ordinal number of the weekday in the month. 382251647Sgrog */ 383251647Sgrogstatic int 384251647Sgrogwdayom (int day, int offset, int month, int year) 385251647Sgrog{ 386251647Sgrog/* Weekday of first day in month */ 387251647Sgrog int wday1; /* first day of month */ 388251647Sgrog/* Weekday of last day in month */ 389251647Sgrog int wdayn; 390251647Sgrog int d; 391251647Sgrog 392251647Sgrog wday1 = first_dayofweek_of_month(year, month); 393251647Sgrog if (wday1 < 0) /* not set */ 394251647Sgrog return (wday1); 395251647Sgrog /* 396251647Sgrog * Date of zeroth or first of our weekday in month, depending on the 397251647Sgrog * relationship with the first of the month. The range is -6:6. 398251647Sgrog */ 399251647Sgrog d = (day - wday1 + 1) % 7; 400251647Sgrog /* 401251647Sgrog * Which way are we counting? Offset 0 is invalid, abs (offset) > 5 is 402251647Sgrog * meaningless, but that's OK. Offset 5 may or may not be meaningless, 403251647Sgrog * so there's no point in complaining for complaining's sake. 404251647Sgrog */ 405251647Sgrog if (offset < 0) { /* back from end of month */ 406251647Sgrog /* FIXME */ 407251647Sgrog wdayn = d; 408251647Sgrog while (wdayn <= yearinfo->monthdays[month]) 409251647Sgrog wdayn += 7; 410251647Sgrog d = offset * 7 + wdayn; 411251647Sgrog } else if (offset > 0){ 412251647Sgrog if (d > 0) 413251647Sgrog d += offset * 7 - 7; 414251647Sgrog else 415251647Sgrog d += offset * 7; 416251647Sgrog } else 417251647Sgrog warnx ("Invalid offset 0"); 418251647Sgrog return (d); 419251647Sgrog} 420251647Sgrog 421251647Sgrog/* 422205821Sedwin * Possible date formats include any combination of: 423205821Sedwin * 3-charmonth (January, Jan, Jan) 424205821Sedwin * 3-charweekday (Friday, Monday, mon.) 425205821Sedwin * numeric month or day (1, 2, 04) 426205821Sedwin * 427205821Sedwin * Any character may separate them, or they may not be separated. Any line, 428205821Sedwin * following a line that is matched, that starts with "whitespace", is shown 429205821Sedwin * along with the matched line. 430205821Sedwin */ 431205821Sedwinint 432205821Sedwinparsedaymonth(char *date, int *yearp, int *monthp, int *dayp, int *flags, 433205821Sedwin char **edp) 434205821Sedwin{ 435205821Sedwin char month[100], dayofmonth[100], dayofweek[100], modifieroffset[100]; 436212035Sedwin char syear[100]; 437205821Sedwin char modifierindex[100], specialday[100]; 438212035Sedwin int idayofweek = -1, imonth = -1, idayofmonth = -1, iyear = -1; 439212035Sedwin int year, remindex; 440205821Sedwin int d, m, dow, rm, rd, offset; 441205821Sedwin char *ed; 442205821Sedwin int retvalsign = 1; 443205821Sedwin 444205821Sedwin /* 445205821Sedwin * CONVENTION 446205821Sedwin * 447205821Sedwin * Month: 1-12 448205821Sedwin * Monthname: Jan .. Dec 449227370Sgrog * Day: 1-31 450205821Sedwin * Weekday: Mon .. Sun 451205821Sedwin * 452205821Sedwin */ 453205821Sedwin 454205821Sedwin *flags = 0; 455205821Sedwin 456205821Sedwin if (debug) 457205821Sedwin debug_determinestyle(1, date, *flags, month, imonth, 458205821Sedwin dayofmonth, idayofmonth, dayofweek, idayofweek, 459212035Sedwin modifieroffset, modifierindex, specialday, syear, iyear); 460205821Sedwin if (determinestyle(date, flags, month, &imonth, dayofmonth, 461251647Sgrog &idayofmonth, dayofweek, &idayofweek, modifieroffset, 462251647Sgrog modifierindex, specialday, syear, &iyear) == 0) { 463205821Sedwin if (debug) 464205821Sedwin printf("Failed!\n"); 465205821Sedwin return (0); 466205821Sedwin } 467205821Sedwin 468205821Sedwin if (debug) 469205821Sedwin debug_determinestyle(0, date, *flags, month, imonth, 470205821Sedwin dayofmonth, idayofmonth, dayofweek, idayofweek, 471212035Sedwin modifieroffset, modifierindex, specialday, syear, iyear); 472205821Sedwin 473205821Sedwin remindex = 0; 474205821Sedwin for (year = year1; year <= year2; year++) { 475212035Sedwin 476212035Sedwin int lflags = *flags; 477212035Sedwin /* If the year is specified, only do it if it is this year! */ 478212035Sedwin if ((lflags & F_YEAR) != 0) 479212035Sedwin if (iyear != year) 480212035Sedwin continue; 481212035Sedwin lflags &= ~F_YEAR; 482212035Sedwin 483205821Sedwin /* Get important dates for this year */ 484205821Sedwin yearinfo = years; 485205821Sedwin while (yearinfo != NULL) { 486205821Sedwin if (yearinfo->year == year) 487205821Sedwin break; 488205821Sedwin yearinfo = yearinfo -> next; 489205821Sedwin } 490205821Sedwin if (yearinfo == NULL) { 491205821Sedwin yearinfo = (struct yearinfo *)calloc(1, 492205821Sedwin sizeof(struct yearinfo)); 493205821Sedwin if (yearinfo == NULL) 494205821Sedwin errx(1, "Unable to allocate more years"); 495205821Sedwin yearinfo->year = year; 496205821Sedwin yearinfo->next = years; 497205821Sedwin years = yearinfo; 498205821Sedwin 499251647Sgrog yearinfo->monthdays = monthdaytab[isleap(year)]; 500205821Sedwin yearinfo->ieaster = easter(year); 501218471Sosa yearinfo->ipaskha = paskha(year); 502205821Sedwin fpom(year, UTCOffset, yearinfo->ffullmoon, 503205821Sedwin yearinfo->fnewmoon); 504205821Sedwin fpom(year, UTCOFFSET_CNY, yearinfo->ffullmooncny, 505205821Sedwin yearinfo->fnewmooncny); 506205821Sedwin fequinoxsolstice(year, UTCOffset, 507205821Sedwin yearinfo->equinoxdays, yearinfo->solsticedays); 508205821Sedwin 509205821Sedwin /* 510205821Sedwin * CNY: Match day with sun longitude at 330` with new 511205821Sedwin * moon 512205821Sedwin */ 513205821Sedwin yearinfo->firstcnyday = calculatesunlongitude30(year, 514205821Sedwin UTCOFFSET_CNY, yearinfo->ichinesemonths); 515205821Sedwin for (m = 0; yearinfo->fnewmooncny[m] >= 0; m++) { 516205821Sedwin if (yearinfo->fnewmooncny[m] > 517205821Sedwin yearinfo->firstcnyday) { 518205821Sedwin yearinfo->firstcnyday = 519205821Sedwin floor(yearinfo->fnewmooncny[m - 1]); 520205821Sedwin break; 521205821Sedwin } 522205821Sedwin } 523205821Sedwin } 524205821Sedwin 525205821Sedwin /* Same day every year */ 526212035Sedwin if (lflags == (F_MONTH | F_DAYOFMONTH)) { 527205821Sedwin if (!remember_ymd(year, imonth, idayofmonth)) 528205821Sedwin continue; 529205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 530205821Sedwin year, imonth, idayofmonth, NULL); 531205821Sedwin continue; 532205821Sedwin } 533205821Sedwin 534205821Sedwin /* XXX Same day every year, but variable */ 535212035Sedwin if (lflags == (F_MONTH | F_DAYOFMONTH | F_VARIABLE)) { 536205821Sedwin if (!remember_ymd(year, imonth, idayofmonth)) 537205821Sedwin continue; 538205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 539205821Sedwin year, imonth, idayofmonth, NULL); 540205821Sedwin continue; 541205821Sedwin } 542205821Sedwin 543205821Sedwin /* Same day every month */ 544212035Sedwin if (lflags == (F_ALLMONTH | F_DAYOFMONTH)) { 545205821Sedwin for (m = 1; m <= 12; m++) { 546205821Sedwin if (!remember_ymd(year, m, idayofmonth)) 547205821Sedwin continue; 548205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 549205821Sedwin year, m, idayofmonth, NULL); 550205821Sedwin } 551205821Sedwin continue; 552205821Sedwin } 553205821Sedwin 554205821Sedwin /* Every day of a month */ 555212035Sedwin if (lflags == (F_ALLDAY | F_MONTH)) { 556251647Sgrog for (d = 1; d <= yearinfo->monthdays[imonth]; d++) { 557205821Sedwin if (!remember_ymd(year, imonth, d)) 558205821Sedwin continue; 559205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 560205821Sedwin year, imonth, d, NULL); 561205821Sedwin } 562205821Sedwin continue; 563205821Sedwin } 564205821Sedwin 565205821Sedwin /* One day of every month */ 566212035Sedwin if (lflags == (F_ALLMONTH | F_DAYOFWEEK)) { 567205821Sedwin for (m = 1; m <= 12; m++) { 568205821Sedwin if (!remember_ymd(year, m, idayofmonth)) 569205821Sedwin continue; 570205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 571205821Sedwin year, m, idayofmonth, NULL); 572205821Sedwin } 573205821Sedwin continue; 574205821Sedwin } 575205821Sedwin 576205821Sedwin /* Every dayofweek of the year */ 577212035Sedwin if (lflags == (F_DAYOFWEEK | F_VARIABLE)) { 578205821Sedwin dow = first_dayofweek_of_year(year); 579205821Sedwin d = (idayofweek - dow + 8) % 7; 580205821Sedwin while (d <= 366) { 581205821Sedwin if (remember_yd(year, d, &rm, &rd)) 582205821Sedwin remember(&remindex, 583205821Sedwin yearp, monthp, dayp, edp, 584205821Sedwin year, rm, rd, NULL); 585205821Sedwin d += 7; 586205821Sedwin } 587205821Sedwin continue; 588205821Sedwin } 589205821Sedwin 590251647Sgrog /* 591251647Sgrog * Every so-manied dayofweek of every month of the year: 592251647Sgrog * Thu-3 593251647Sgrog */ 594223928Sedwin if (lflags == (F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { 595223928Sedwin offset = indextooffset(modifierindex); 596223928Sedwin 597251647Sgrog for (m = 0; m <= 12; m++) { 598251647Sgrog d = wdayom (idayofweek, offset, m, year); 599223928Sedwin if (remember_ymd(year, m, d)) { 600223928Sedwin remember(&remindex, 601223928Sedwin yearp, monthp, dayp, edp, 602223928Sedwin year, m, d, NULL); 603223928Sedwin continue; 604223928Sedwin } 605223928Sedwin } 606223928Sedwin continue; 607223928Sedwin } 608223928Sedwin 609251647Sgrog /* 610251647Sgrog * A certain dayofweek of a month 611251647Sgrog * Jan/Thu-3 612251647Sgrog */ 613212035Sedwin if (lflags == 614205821Sedwin (F_MONTH | F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { 615205821Sedwin offset = indextooffset(modifierindex); 616205821Sedwin dow = first_dayofweek_of_month(year, imonth); 617205821Sedwin d = (idayofweek - dow + 8) % 7; 618205821Sedwin 619205821Sedwin if (offset > 0) { 620251647Sgrog while (d <= yearinfo->monthdays[imonth]) { 621205821Sedwin if (--offset == 0 622251647Sgrog && remember_ymd(year, imonth, d)) { 623205821Sedwin remember(&remindex, 624205821Sedwin yearp, monthp, dayp, edp, 625205821Sedwin year, imonth, d, NULL); 626205821Sedwin continue; 627205821Sedwin } 628205821Sedwin d += 7; 629205821Sedwin } 630205821Sedwin continue; 631205821Sedwin } 632205821Sedwin if (offset < 0) { 633251647Sgrog while (d <= yearinfo->monthdays[imonth]) 634205821Sedwin d += 7; 635205821Sedwin while (offset != 0) { 636205821Sedwin offset++; 637205821Sedwin d -= 7; 638205821Sedwin } 639205821Sedwin if (remember_ymd(year, imonth, d)) 640205821Sedwin remember(&remindex, 641205821Sedwin yearp, monthp, dayp, edp, 642205821Sedwin year, imonth, d, NULL); 643205821Sedwin continue; 644205821Sedwin } 645205821Sedwin continue; 646205821Sedwin } 647205821Sedwin 648205821Sedwin /* Every dayofweek of the month */ 649212035Sedwin if (lflags == (F_DAYOFWEEK | F_MONTH | F_VARIABLE)) { 650205821Sedwin dow = first_dayofweek_of_month(year, imonth); 651205821Sedwin d = (idayofweek - dow + 8) % 7; 652251647Sgrog while (d <= yearinfo->monthdays[imonth]) { 653205821Sedwin if (remember_ymd(year, imonth, d)) 654205821Sedwin remember(&remindex, 655205821Sedwin yearp, monthp, dayp, edp, 656205821Sedwin year, imonth, d, NULL); 657205821Sedwin d += 7; 658205821Sedwin } 659205821Sedwin continue; 660205821Sedwin } 661205821Sedwin 662205821Sedwin /* Easter */ 663212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 664205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_EASTER)) { 665205821Sedwin offset = 0; 666212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 667205821Sedwin offset = parseoffset(modifieroffset); 668205821Sedwin if (remember_yd(year, yearinfo->ieaster + offset, 669251647Sgrog &rm, &rd)) 670205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 671205821Sedwin year, rm, rd, NULL); 672205821Sedwin continue; 673205821Sedwin } 674205821Sedwin 675205821Sedwin /* Paskha */ 676212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 677205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_PASKHA)) { 678205821Sedwin offset = 0; 679212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 680205821Sedwin offset = parseoffset(modifieroffset); 681205821Sedwin if (remember_yd(year, yearinfo->ipaskha + offset, 682251647Sgrog &rm, &rd)) 683205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 684205821Sedwin year, rm, rd, NULL); 685205821Sedwin continue; 686205821Sedwin } 687205821Sedwin 688205821Sedwin /* Chinese New Year */ 689212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 690205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_CNY)) { 691205821Sedwin offset = 0; 692212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 693205821Sedwin offset = parseoffset(modifieroffset); 694205821Sedwin if (remember_yd(year, yearinfo->firstcnyday + offset, 695251647Sgrog &rm, &rd)) 696205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 697205821Sedwin year, rm, rd, NULL); 698205821Sedwin continue; 699205821Sedwin } 700205821Sedwin 701205821Sedwin /* FullMoon */ 702212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 703205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_FULLMOON)) { 704205821Sedwin int i; 705205821Sedwin 706205821Sedwin offset = 0; 707212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 708205821Sedwin offset = parseoffset(modifieroffset); 709205821Sedwin for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { 710205821Sedwin if (remember_yd(year, 711251647Sgrog floor(yearinfo->ffullmoon[i]) + offset, 712205821Sedwin &rm, &rd)) { 713205821Sedwin ed = floattotime( 714205821Sedwin yearinfo->ffullmoon[i]); 715205821Sedwin remember(&remindex, 716205821Sedwin yearp, monthp, dayp, edp, 717205821Sedwin year, rm, rd, ed); 718205821Sedwin } 719205821Sedwin } 720205821Sedwin continue; 721205821Sedwin } 722205821Sedwin 723205821Sedwin /* NewMoon */ 724212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 725205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_NEWMOON)) { 726205821Sedwin int i; 727205821Sedwin 728205821Sedwin offset = 0; 729212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 730205821Sedwin offset = parseoffset(modifieroffset); 731205821Sedwin for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { 732205821Sedwin if (remember_yd(year, 733251647Sgrog floor(yearinfo->fnewmoon[i]) + offset, 734251647Sgrog &rm, &rd)) { 735205821Sedwin ed = floattotime(yearinfo->fnewmoon[i]); 736205821Sedwin remember(&remindex, 737205821Sedwin yearp, monthp, dayp, edp, 738205821Sedwin year, rm, rd, ed); 739205821Sedwin } 740205821Sedwin } 741205821Sedwin continue; 742205821Sedwin } 743205821Sedwin 744205821Sedwin /* (Mar|Sep)Equinox */ 745212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 746205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_MAREQUINOX)) { 747205821Sedwin offset = 0; 748212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 749205821Sedwin offset = parseoffset(modifieroffset); 750205821Sedwin if (remember_yd(year, yearinfo->equinoxdays[0] + offset, 751251647Sgrog &rm, &rd)) { 752205821Sedwin ed = floattotime(yearinfo->equinoxdays[0]); 753205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 754205821Sedwin year, rm, rd, ed); 755205821Sedwin } 756205821Sedwin continue; 757205821Sedwin } 758212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 759205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_SEPEQUINOX)) { 760205821Sedwin offset = 0; 761212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 762205821Sedwin offset = parseoffset(modifieroffset); 763205821Sedwin if (remember_yd(year, yearinfo->equinoxdays[1] + offset, 764205821Sedwin &rm, &rd)) { 765205821Sedwin ed = floattotime(yearinfo->equinoxdays[1]); 766205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 767205821Sedwin year, rm, rd, ed); 768205821Sedwin } 769205821Sedwin continue; 770205821Sedwin } 771205821Sedwin 772205821Sedwin /* (Jun|Dec)Solstice */ 773212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 774205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_JUNSOLSTICE)) { 775205821Sedwin offset = 0; 776212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 777205821Sedwin offset = parseoffset(modifieroffset); 778205821Sedwin if (remember_yd(year, 779251647Sgrog yearinfo->solsticedays[0] + offset, &rm, &rd)) { 780205821Sedwin ed = floattotime(yearinfo->solsticedays[0]); 781205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 782205821Sedwin year, rm, rd, ed); 783205821Sedwin } 784205821Sedwin continue; 785205821Sedwin } 786212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 787205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_DECSOLSTICE)) { 788205821Sedwin offset = 0; 789212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 790205821Sedwin offset = parseoffset(modifieroffset); 791205821Sedwin if (remember_yd(year, 792251647Sgrog yearinfo->solsticedays[1] + offset, &rm, &rd)) { 793205821Sedwin ed = floattotime(yearinfo->solsticedays[1]); 794205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 795205821Sedwin year, rm, rd, ed); 796205821Sedwin } 797205821Sedwin continue; 798205821Sedwin } 799205821Sedwin 800227370Sgrog if (debug) { 801251647Sgrog printf("Unprocessed:\n"); 802251647Sgrog debug_determinestyle(2, date, lflags, month, imonth, 803251647Sgrog dayofmonth, idayofmonth, dayofweek, idayofweek, 804251647Sgrog modifieroffset, modifierindex, specialday, syear, 805251647Sgrog iyear); 806227370Sgrog } 807205821Sedwin retvalsign = -1; 808205821Sedwin } 809205821Sedwin 810205821Sedwin if (retvalsign == -1) 811205821Sedwin return (-remindex - 1); 812205821Sedwin else 813205821Sedwin return (remindex); 814205821Sedwin} 815205821Sedwin 816205821Sedwinstatic char * 817205821Sedwinshowflags(int flags) 818205821Sedwin{ 819205821Sedwin static char s[1000]; 820205821Sedwin s[0] = '\0'; 821205821Sedwin 822212035Sedwin if ((flags & F_YEAR) != 0) 823212035Sedwin strcat(s, "year "); 824205821Sedwin if ((flags & F_MONTH) != 0) 825205821Sedwin strcat(s, "month "); 826205821Sedwin if ((flags & F_DAYOFWEEK) != 0) 827205821Sedwin strcat(s, "dayofweek "); 828205821Sedwin if ((flags & F_DAYOFMONTH) != 0) 829205821Sedwin strcat(s, "dayofmonth "); 830205821Sedwin if ((flags & F_MODIFIERINDEX) != 0) 831205821Sedwin strcat(s, "modifierindex "); 832205821Sedwin if ((flags & F_MODIFIEROFFSET) != 0) 833205821Sedwin strcat(s, "modifieroffset "); 834205821Sedwin if ((flags & F_SPECIALDAY) != 0) 835205821Sedwin strcat(s, "specialday "); 836205821Sedwin if ((flags & F_ALLMONTH) != 0) 837205821Sedwin strcat(s, "allmonth "); 838205821Sedwin if ((flags & F_ALLDAY) != 0) 839205821Sedwin strcat(s, "allday "); 840205821Sedwin if ((flags & F_VARIABLE) != 0) 841205821Sedwin strcat(s, "variable "); 842205821Sedwin if ((flags & F_CNY) != 0) 843205821Sedwin strcat(s, "chinesenewyear "); 844205821Sedwin if ((flags & F_PASKHA) != 0) 845205821Sedwin strcat(s, "paskha "); 846205821Sedwin if ((flags & F_EASTER) != 0) 847205821Sedwin strcat(s, "easter "); 848205821Sedwin if ((flags & F_FULLMOON) != 0) 849205821Sedwin strcat(s, "fullmoon "); 850205821Sedwin if ((flags & F_NEWMOON) != 0) 851205821Sedwin strcat(s, "newmoon "); 852205821Sedwin if ((flags & F_MAREQUINOX) != 0) 853205821Sedwin strcat(s, "marequinox "); 854205821Sedwin if ((flags & F_SEPEQUINOX) != 0) 855205821Sedwin strcat(s, "sepequinox "); 856205821Sedwin if ((flags & F_JUNSOLSTICE) != 0) 857205821Sedwin strcat(s, "junsolstice "); 858205821Sedwin if ((flags & F_DECSOLSTICE) != 0) 859205821Sedwin strcat(s, "decsolstice "); 860205821Sedwin 861205821Sedwin return s; 862205821Sedwin} 863205821Sedwin 864205821Sedwinstatic const char * 865205821Sedwingetmonthname(int i) 866205821Sedwin{ 867223939Sedwin if (i <= 0 || i > 12) 868223939Sedwin return (""); 869205821Sedwin if (nmonths[i - 1].len != 0 && nmonths[i - 1].name != NULL) 870205821Sedwin return (nmonths[i - 1].name); 871205821Sedwin return (months[i - 1]); 872205821Sedwin} 873205821Sedwin 874205821Sedwinstatic int 875205834Sdescheckmonth(char *s, size_t *len, size_t *offset, const char **month) 876205821Sedwin{ 877205821Sedwin struct fixs *n; 878205821Sedwin int i; 879205821Sedwin 880205821Sedwin for (i = 0; fnmonths[i].name != NULL; i++) { 881205821Sedwin n = fnmonths + i; 882205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 883205821Sedwin *len = n->len; 884205821Sedwin *month = n->name; 885205821Sedwin *offset = i + 1; 886205821Sedwin return (1); 887205821Sedwin } 888205821Sedwin } 889205821Sedwin for (i = 0; nmonths[i].name != NULL; i++) { 890205821Sedwin n = nmonths + i; 891205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 892205821Sedwin *len = n->len; 893205821Sedwin *month = n->name; 894205821Sedwin *offset = i + 1; 895205821Sedwin return (1); 896205821Sedwin } 897205821Sedwin } 898205821Sedwin for (i = 0; fmonths[i] != NULL; i++) { 899205821Sedwin *len = strlen(fmonths[i]); 900205821Sedwin if (strncasecmp(s, fmonths[i], *len) == 0) { 901205821Sedwin *month = fmonths[i]; 902205821Sedwin *offset = i + 1; 903205821Sedwin return (1); 904205821Sedwin } 905205821Sedwin } 906205821Sedwin for (i = 0; months[i] != NULL; i++) { 907205821Sedwin if (strncasecmp(s, months[i], 3) == 0) { 908205821Sedwin *len = 3; 909205821Sedwin *month = months[i]; 910205821Sedwin *offset = i + 1; 911205821Sedwin return (1); 912205821Sedwin } 913205821Sedwin } 914205821Sedwin return (0); 915205821Sedwin} 916205821Sedwin 917205821Sedwinstatic const char * 918205821Sedwingetdayofweekname(int i) 919205821Sedwin{ 920205821Sedwin if (ndays[i].len != 0 && ndays[i].name != NULL) 921205821Sedwin return (ndays[i].name); 922205821Sedwin return (days[i]); 923205821Sedwin} 924205821Sedwin 925205821Sedwinstatic int 926205834Sdescheckdayofweek(char *s, size_t *len, size_t *offset, const char **dow) 927205821Sedwin{ 928205821Sedwin struct fixs *n; 929205821Sedwin int i; 930205821Sedwin 931205821Sedwin for (i = 0; fndays[i].name != NULL; i++) { 932205821Sedwin n = fndays + i; 933205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 934205821Sedwin *len = n->len; 935205821Sedwin *dow = n->name; 936205821Sedwin *offset = i; 937205821Sedwin return (1); 938205821Sedwin } 939205821Sedwin } 940205821Sedwin for (i = 0; ndays[i].name != NULL; i++) { 941205821Sedwin n = ndays + i; 942205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 943205821Sedwin *len = n->len; 944205821Sedwin *dow = n->name; 945205821Sedwin *offset = i; 946205821Sedwin return (1); 947205821Sedwin } 948205821Sedwin } 949205821Sedwin for (i = 0; fdays[i] != NULL; i++) { 950205821Sedwin *len = strlen(fdays[i]); 951205821Sedwin if (strncasecmp(s, fdays[i], *len) == 0) { 952205821Sedwin *dow = fdays[i]; 953205821Sedwin *offset = i; 954205821Sedwin return (1); 955205821Sedwin } 956205821Sedwin } 957205821Sedwin for (i = 0; days[i] != NULL; i++) { 958205821Sedwin if (strncasecmp(s, days[i], 3) == 0) { 959205821Sedwin *len = 3; 960205821Sedwin *dow = days[i]; 961205821Sedwin *offset = i; 962205821Sedwin return (1); 963205821Sedwin } 964205821Sedwin } 965205821Sedwin return (0); 966205821Sedwin} 967205821Sedwin 968205821Sedwinstatic int 969205821Sedwinisonlydigits(char *s, int nostar) 970205821Sedwin{ 971205821Sedwin int i; 972205821Sedwin for (i = 0; s[i] != '\0'; i++) { 973205821Sedwin if (nostar == 0 && s[i] == '*' && s[i + 1] == '\0') 974205821Sedwin return 1; 975207703Sache if (!isdigit((unsigned char)s[i])) 976205821Sedwin return (0); 977205821Sedwin } 978205821Sedwin return (1); 979205821Sedwin} 980205821Sedwin 981205821Sedwinstatic int 982205821Sedwinindextooffset(char *s) 983205821Sedwin{ 984205821Sedwin int i; 985205821Sedwin struct fixs *n; 986244166Sgrog char *es; 987205821Sedwin 988223928Sedwin if (s[0] == '+' || s[0] == '-') { 989244168Sgrog i = strtol (s, &es, 10); 990244166Sgrog if (*es != '\0') /* trailing junk */ 991244166Sgrog errx (1, "Invalid specifier format: %s\n", s); 992244166Sgrog return (i); 993223928Sedwin } 994223928Sedwin 995205821Sedwin for (i = 0; i < 6; i++) { 996205821Sedwin if (strcasecmp(s, sequences[i]) == 0) { 997205821Sedwin if (i == 5) 998205821Sedwin return (-1); 999205821Sedwin return (i + 1); 1000205821Sedwin } 1001205821Sedwin } 1002205821Sedwin for (i = 0; i < 6; i++) { 1003205821Sedwin n = nsequences + i; 1004205821Sedwin if (n->len == 0) 1005205821Sedwin continue; 1006205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 1007205821Sedwin if (i == 5) 1008205821Sedwin return (-1); 1009205821Sedwin return (i + 1); 1010205821Sedwin } 1011205821Sedwin } 1012205821Sedwin return (0); 1013205821Sedwin} 1014205821Sedwin 1015205821Sedwinstatic int 1016205821Sedwinparseoffset(char *s) 1017205821Sedwin{ 1018205821Sedwin return strtol(s, NULL, 10); 1019205821Sedwin} 1020205821Sedwin 1021205821Sedwinstatic char * 1022205821Sedwinfloattotime(double f) 1023205821Sedwin{ 1024205821Sedwin static char buf[100]; 1025205821Sedwin int hh, mm, ss, i; 1026205821Sedwin 1027205821Sedwin f -= floor(f); 1028205821Sedwin i = f * SECSPERDAY; 1029205821Sedwin 1030205821Sedwin hh = i / SECSPERHOUR; 1031205821Sedwin i %= SECSPERHOUR; 1032205821Sedwin mm = i / SECSPERMINUTE; 1033205821Sedwin i %= SECSPERMINUTE; 1034205821Sedwin ss = i; 1035205821Sedwin 1036205821Sedwin sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); 1037205821Sedwin return (buf); 1038205821Sedwin} 1039205821Sedwin 1040205821Sedwinstatic char * 1041205821Sedwinfloattoday(int year, double f) 1042205821Sedwin{ 1043205821Sedwin static char buf[100]; 1044205821Sedwin int i, m, d, hh, mm, ss; 1045205821Sedwin int *cumdays = cumdaytab[isleap(year)]; 1046205821Sedwin 1047205821Sedwin for (i = 0; 1 + cumdays[i] < f; i++) 1048212591Semaste ; 1049205821Sedwin m = --i; 1050205821Sedwin d = floor(f - 1 - cumdays[i]); 1051205821Sedwin f -= floor(f); 1052205821Sedwin i = f * SECSPERDAY; 1053205821Sedwin 1054205821Sedwin hh = i / SECSPERHOUR; 1055205821Sedwin i %= SECSPERHOUR; 1056205821Sedwin mm = i / SECSPERMINUTE; 1057205821Sedwin i %= SECSPERMINUTE; 1058205821Sedwin ss = i; 1059205821Sedwin 1060205821Sedwin sprintf(buf, "%02d-%02d %02d:%02d:%02d", m, d, hh, mm, ss); 1061205821Sedwin return (buf); 1062205821Sedwin} 1063205821Sedwin 1064205821Sedwinvoid 1065205821Sedwindodebug(char *what) 1066205821Sedwin{ 1067205821Sedwin int year; 1068205821Sedwin 1069205821Sedwin printf("UTCOffset: %g\n", UTCOffset); 1070205821Sedwin printf("eastlongitude: %d\n", EastLongitude); 1071205821Sedwin 1072205821Sedwin if (strcmp(what, "moon") == 0) { 1073205821Sedwin double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; 1074205821Sedwin int i; 1075205821Sedwin 1076205821Sedwin for (year = year1; year <= year2; year++) { 1077205821Sedwin fpom(year, UTCOffset, ffullmoon, fnewmoon); 1078205821Sedwin printf("Full moon %d:\t", year); 1079205821Sedwin for (i = 0; ffullmoon[i] >= 0; i++) { 1080205821Sedwin printf("%g (%s) ", ffullmoon[i], 1081205821Sedwin floattoday(year, ffullmoon[i])); 1082205821Sedwin } 1083205821Sedwin printf("\nNew moon %d:\t", year); 1084205821Sedwin for (i = 0; fnewmoon[i] >= 0; i++) { 1085205821Sedwin printf("%g (%s) ", fnewmoon[i], 1086205821Sedwin floattoday(year, fnewmoon[i])); 1087205821Sedwin } 1088205821Sedwin printf("\n"); 1089205821Sedwin 1090205821Sedwin } 1091227370Sgrog 1092205821Sedwin return; 1093205821Sedwin } 1094205821Sedwin 1095205821Sedwin if (strcmp(what, "sun") == 0) { 1096205821Sedwin double equinoxdays[2], solsticedays[2]; 1097205821Sedwin for (year = year1; year <= year2; year++) { 1098205821Sedwin printf("Sun in %d:\n", year); 1099205821Sedwin fequinoxsolstice(year, UTCOffset, equinoxdays, 1100205821Sedwin solsticedays); 1101205821Sedwin printf("e[0] - %g (%s)\n", 1102205821Sedwin equinoxdays[0], 1103205821Sedwin floattoday(year, equinoxdays[0])); 1104205821Sedwin printf("e[1] - %g (%s)\n", 1105205821Sedwin equinoxdays[1], 1106205821Sedwin floattoday(year, equinoxdays[1])); 1107205821Sedwin printf("s[0] - %g (%s)\n", 1108205821Sedwin solsticedays[0], 1109205821Sedwin floattoday(year, solsticedays[0])); 1110205821Sedwin printf("s[1] - %g (%s)\n", 1111205821Sedwin solsticedays[1], 1112205821Sedwin floattoday(year, solsticedays[1])); 1113205821Sedwin } 1114205821Sedwin return; 1115205821Sedwin } 1116205821Sedwin} 1117