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. 13205821Sedwin * 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. 25205821Sedwin * 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); 50205821Sedwin 51205821Sedwin/* 52205821Sedwin * Expected styles: 53205821Sedwin * 54205821Sedwin * Date ::= Month . ' ' . DayOfMonth | 55205821Sedwin * Month . ' ' . DayOfWeek . ModifierIndex | 56205821Sedwin * Month . '/' . DayOfMonth | 57205821Sedwin * Month . '/' . DayOfWeek . ModifierIndex | 58205821Sedwin * DayOfMonth . ' ' . Month | 59205821Sedwin * DayOfMonth . '/' . Month | 60205821Sedwin * DayOfWeek . ModifierIndex . ' ' .Month | 61205821Sedwin * DayOfWeek . ModifierIndex . '/' .Month | 62205821Sedwin * DayOfWeek . ModifierIndex | 63205821Sedwin * SpecialDay . ModifierOffset 64205821Sedwin * 65205821Sedwin * Month ::= MonthName | MonthNumber | '*' 66205821Sedwin * MonthNumber ::= '0' ... '9' | '00' ... '09' | '10' ... '12' 67205821Sedwin * MonthName ::= MonthNameShort | MonthNameLong 68205821Sedwin * MonthNameLong ::= 'January' ... 'December' 69205821Sedwin * MonthNameShort ::= 'Jan' ... 'Dec' | 'Jan.' ... 'Dec.' 70205821Sedwin * 71205821Sedwin * DayOfWeek ::= DayOfWeekShort | DayOfWeekLong 72205821Sedwin * DayOfWeekShort ::= 'Mon' .. 'Sun' 73205821Sedwin * DayOfWeekLong ::= 'Monday' .. 'Sunday' 74205821Sedwin * DayOfMonth ::= '0' ... '9' | '00' ... '09' | '10' ... '29' | 75205821Sedwin * '30' ... '31' | '*' 76205821Sedwin * 77205821Sedwin * ModifierOffset ::= '' | '+' . ModifierNumber | '-' . ModifierNumber 78205821Sedwin * ModifierNumber ::= '0' ... '9' | '00' ... '99' | '000' ... '299' | 79205821Sedwin * '300' ... '359' | '360' ... '365' 80205821Sedwin * ModifierIndex ::= 'Second' | 'Third' | 'Fourth' | 'Fifth' | 81205821Sedwin * 'First' | 'Last' 82205821Sedwin * 83216697Sosa * SpecialDay ::= 'Easter' | 'Paskha' | 'ChineseNewYear' 84205821Sedwin * 85205821Sedwin */ 86205821Sedwinstatic int 87205821Sedwindeterminestyle(char *date, int *flags, 88205821Sedwin char *month, int *imonth, char *dayofmonth, int *idayofmonth, 89205821Sedwin char *dayofweek, int *idayofweek, char *modifieroffset, 90212035Sedwin char *modifierindex, char *specialday, char *year, int *iyear) 91205821Sedwin{ 92212035Sedwin char *p, *p1, *p2, *py; 93205821Sedwin const char *dow, *pmonth; 94205821Sedwin char pold; 95205821Sedwin size_t len, offset; 96205821Sedwin 97205821Sedwin *flags = F_NONE; 98205821Sedwin *month = '\0'; 99205821Sedwin *imonth = 0; 100212035Sedwin *year = '\0'; 101212035Sedwin *iyear = 0; 102205821Sedwin *dayofmonth = '\0'; 103205821Sedwin *idayofmonth = 0; 104205821Sedwin *dayofweek = '\0'; 105205821Sedwin *idayofweek = 0; 106205821Sedwin *modifieroffset = '\0'; 107205821Sedwin *modifierindex = '\0'; 108205821Sedwin *specialday = '\0'; 109205821Sedwin 110205821Sedwin#define CHECKSPECIAL(s1, s2, lens2, type) \ 111205821Sedwin if (s2 != NULL && strncmp(s1, s2, lens2) == 0) { \ 112205821Sedwin *flags |= F_SPECIALDAY; \ 113205821Sedwin *flags |= type; \ 114205821Sedwin *flags |= F_VARIABLE; \ 115205821Sedwin if (strlen(s1) == lens2) { \ 116205821Sedwin strcpy(specialday, s1); \ 117205821Sedwin return (1); \ 118205821Sedwin } \ 119205821Sedwin strncpy(specialday, s1, lens2); \ 120205821Sedwin specialday[lens2] = '\0'; \ 121205821Sedwin strcpy(modifieroffset, s1 + lens2); \ 122205821Sedwin *flags |= F_MODIFIEROFFSET; \ 123205821Sedwin return (1); \ 124205821Sedwin } 125205821Sedwin 126205821Sedwin if ((p = strchr(date, ' ')) == NULL) { 127205821Sedwin if ((p = strchr(date, '/')) == NULL) { 128205821Sedwin CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY), 129205821Sedwin F_CNY); 130205821Sedwin CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY); 131205821Sedwin CHECKSPECIAL(date, STRING_NEWMOON, 132205821Sedwin strlen(STRING_NEWMOON), F_NEWMOON); 133205821Sedwin CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len, 134205821Sedwin F_NEWMOON); 135205821Sedwin CHECKSPECIAL(date, STRING_FULLMOON, 136205821Sedwin strlen(STRING_FULLMOON), F_FULLMOON); 137205821Sedwin CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len, 138205821Sedwin F_FULLMOON); 139205821Sedwin CHECKSPECIAL(date, STRING_PASKHA, 140205821Sedwin strlen(STRING_PASKHA), F_PASKHA); 141205821Sedwin CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA); 142205821Sedwin CHECKSPECIAL(date, STRING_EASTER, 143205821Sedwin strlen(STRING_EASTER), F_EASTER); 144205821Sedwin CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER); 145205821Sedwin CHECKSPECIAL(date, STRING_MAREQUINOX, 146205821Sedwin strlen(STRING_MAREQUINOX), F_MAREQUINOX); 147205821Sedwin CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len, 148205821Sedwin F_SEPEQUINOX); 149205821Sedwin CHECKSPECIAL(date, STRING_SEPEQUINOX, 150205821Sedwin strlen(STRING_SEPEQUINOX), F_SEPEQUINOX); 151205821Sedwin CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len, 152205821Sedwin F_SEPEQUINOX); 153205821Sedwin CHECKSPECIAL(date, STRING_JUNSOLSTICE, 154205821Sedwin strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE); 155205821Sedwin CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len, 156205821Sedwin F_JUNSOLSTICE); 157205821Sedwin CHECKSPECIAL(date, STRING_DECSOLSTICE, 158205821Sedwin strlen(STRING_DECSOLSTICE), F_DECSOLSTICE); 159205821Sedwin CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len, 160205821Sedwin F_DECSOLSTICE); 161205821Sedwin if (checkdayofweek(date, &len, &offset, &dow) != 0) { 162205821Sedwin *flags |= F_DAYOFWEEK; 163205821Sedwin *flags |= F_VARIABLE; 164205821Sedwin *idayofweek = offset; 165205821Sedwin if (strlen(date) == len) { 166205821Sedwin strcpy(dayofweek, date); 167205821Sedwin return (1); 168205821Sedwin } 169205821Sedwin strncpy(dayofweek, date, len); 170205821Sedwin dayofweek[len] = '\0'; 171205821Sedwin strcpy(modifierindex, date + len); 172205821Sedwin *flags |= F_MODIFIERINDEX; 173205821Sedwin return (1); 174205821Sedwin } 175205821Sedwin if (isonlydigits(date, 1)) { 176205821Sedwin /* Assume month number only */ 177205821Sedwin *flags |= F_MONTH; 178205821Sedwin *imonth = (int)strtol(date, (char **)NULL, 10); 179205821Sedwin strcpy(month, getmonthname(*imonth)); 180205821Sedwin return(1); 181205821Sedwin } 182205821Sedwin return (0); 183205821Sedwin } 184205821Sedwin } 185205821Sedwin 186205821Sedwin /* 187205821Sedwin * AFTER this, leave by goto-ing to "allfine" or "fail" to restore the 188205821Sedwin * original data in `date'. 189205821Sedwin */ 190205821Sedwin pold = *p; 191205821Sedwin *p = 0; 192205821Sedwin p1 = date; 193205821Sedwin p2 = p + 1; 194205821Sedwin /* Now p2 points to the next field and p1 to the first field */ 195205821Sedwin 196212035Sedwin if ((py = strchr(p2, '/')) != NULL) { 197212035Sedwin /* We have a year in the string. Now this is getting tricky */ 198212035Sedwin strcpy(year, p1); 199212035Sedwin *iyear = (int)strtol(year, NULL, 10); 200212035Sedwin p1 = p2; 201212035Sedwin p2 = py + 1; 202212035Sedwin *py = 0; 203212035Sedwin *flags |= F_YEAR; 204212035Sedwin } 205212035Sedwin 206212035Sedwin /* 207212035Sedwin printf("p1: %s\n", p1); 208212035Sedwin printf("p2: %s\n", p2); 209212035Sedwin printf("year: %s\n", year); 210212035Sedwin */ 211212035Sedwin 212205821Sedwin /* Check if there is a month-string in the date */ 213205821Sedwin if ((checkmonth(p1, &len, &offset, &pmonth) != 0) 214205821Sedwin || (checkmonth(p2, &len, &offset, &pmonth) != 0 && (p2 = p1))) { 215205821Sedwin /* p2 is the non-month part */ 216205821Sedwin *flags |= F_MONTH; 217205821Sedwin *imonth = offset; 218205821Sedwin 219205821Sedwin strcpy(month, getmonthname(offset)); 220205821Sedwin if (isonlydigits(p2, 1)) { 221205821Sedwin strcpy(dayofmonth, p2); 222205821Sedwin *idayofmonth = (int)strtol(p2, (char **)NULL, 10); 223205821Sedwin *flags |= F_DAYOFMONTH; 224205821Sedwin goto allfine; 225205821Sedwin } 226205821Sedwin if (strcmp(p2, "*") == 0) { 227205821Sedwin *flags |= F_ALLDAY; 228205821Sedwin goto allfine; 229205821Sedwin } 230205821Sedwin 231205821Sedwin if (checkdayofweek(p2, &len, &offset, &dow) != 0) { 232205821Sedwin *flags |= F_DAYOFWEEK; 233205821Sedwin *flags |= F_VARIABLE; 234205821Sedwin *idayofweek = offset; 235205821Sedwin strcpy(dayofweek, getdayofweekname(offset)); 236205821Sedwin if (strlen(p2) == len) 237205821Sedwin goto allfine; 238205821Sedwin strcpy(modifierindex, p2 + len); 239205821Sedwin *flags |= F_MODIFIERINDEX; 240205821Sedwin goto allfine; 241205821Sedwin } 242205821Sedwin 243205821Sedwin goto fail; 244205821Sedwin } 245205821Sedwin 246205821Sedwin /* Check if there is an every-day or every-month in the string */ 247205821Sedwin if ((strcmp(p1, "*") == 0 && isonlydigits(p2, 1)) 248205821Sedwin || (strcmp(p2, "*") == 0 && isonlydigits(p1, 1) && (p2 = p1))) { 249205821Sedwin int d; 250205821Sedwin 251205821Sedwin *flags |= F_ALLMONTH; 252205821Sedwin *flags |= F_DAYOFMONTH; 253205821Sedwin d = (int)strtol(p2, (char **)NULL, 10); 254205821Sedwin *idayofmonth = d; 255205821Sedwin sprintf(dayofmonth, "%d", d); 256205821Sedwin goto allfine; 257205821Sedwin } 258205821Sedwin 259205821Sedwin /* Month as a number, then a weekday */ 260205821Sedwin if (isonlydigits(p1, 1) 261205821Sedwin && checkdayofweek(p2, &len, &offset, &dow) != 0) { 262205821Sedwin int d; 263205821Sedwin 264205821Sedwin *flags |= F_MONTH; 265205821Sedwin *flags |= F_DAYOFWEEK; 266205821Sedwin *flags |= F_VARIABLE; 267205821Sedwin 268205821Sedwin *idayofweek = offset; 269205821Sedwin d = (int)strtol(p1, (char **)NULL, 10); 270205821Sedwin *imonth = d; 271205821Sedwin strcpy(month, getmonthname(d)); 272205821Sedwin 273205821Sedwin strcpy(dayofweek, getdayofweekname(offset)); 274205821Sedwin if (strlen(p2) == len) 275205821Sedwin goto allfine; 276205821Sedwin strcpy(modifierindex, p2 + len); 277205821Sedwin *flags |= F_MODIFIERINDEX; 278205821Sedwin goto allfine; 279205821Sedwin } 280205821Sedwin 281205821Sedwin /* If both the month and date are specified as numbers */ 282205821Sedwin if (isonlydigits(p1, 1) && isonlydigits(p2, 0)) { 283205821Sedwin /* Now who wants to be this ambigious? :-( */ 284205821Sedwin int m, d; 285205821Sedwin 286205821Sedwin if (strchr(p2, '*') != NULL) 287205821Sedwin *flags |= F_VARIABLE; 288205821Sedwin 289205821Sedwin m = (int)strtol(p1, (char **)NULL, 10); 290205821Sedwin d = (int)strtol(p2, (char **)NULL, 10); 291205821Sedwin 292205821Sedwin *flags |= F_MONTH; 293205821Sedwin *flags |= F_DAYOFMONTH; 294205821Sedwin 295205821Sedwin if (m > 12) { 296205821Sedwin *imonth = d; 297205821Sedwin *idayofmonth = m; 298205821Sedwin strcpy(month, getmonthname(d)); 299205821Sedwin sprintf(dayofmonth, "%d", m); 300205821Sedwin } else { 301205821Sedwin *imonth = m; 302205821Sedwin *idayofmonth = d; 303205821Sedwin strcpy(month, getmonthname(m)); 304205821Sedwin sprintf(dayofmonth, "%d", d); 305205821Sedwin } 306205821Sedwin goto allfine; 307205821Sedwin } 308205821Sedwin 309205821Sedwin /* FALLTHROUGH */ 310205821Sedwinfail: 311205821Sedwin *p = pold; 312205821Sedwin return (0); 313205821Sedwinallfine: 314205821Sedwin *p = pold; 315205821Sedwin return (1); 316205821Sedwin 317205821Sedwin} 318205821Sedwin 319205821Sedwinstatic void 320205821Sedwinremember(int *rememberindex, int *y, int *m, int *d, char **ed, int yy, int mm, 321205821Sedwin int dd, char *extra) 322205821Sedwin{ 323205821Sedwin static int warned = 0; 324205821Sedwin 325205821Sedwin if (*rememberindex >= MAXCOUNT - 1) { 326205821Sedwin if (warned == 0) 327205821Sedwin warnx("Index > %d, ignored", MAXCOUNT); 328205821Sedwin warned++; 329205821Sedwin return; 330205821Sedwin } 331205821Sedwin y[*rememberindex] = yy; 332205821Sedwin m[*rememberindex] = mm; 333205821Sedwin d[*rememberindex] = dd; 334205821Sedwin if (extra != NULL) 335205821Sedwin strcpy(ed[*rememberindex], extra); 336205821Sedwin else 337205821Sedwin ed[*rememberindex][0] = '\0'; 338205821Sedwin *rememberindex += 1; 339205821Sedwin} 340205821Sedwin 341205821Sedwinstatic void 342205821Sedwindebug_determinestyle(int dateonly, char *date, int flags, char *month, 343205821Sedwin int imonth, char *dayofmonth, int idayofmonth, char *dayofweek, 344212035Sedwin int idayofweek, char *modifieroffset, char *modifierindex, char *specialday, 345212035Sedwin char *year, int iyear) 346205821Sedwin{ 347205821Sedwin 348205821Sedwin if (dateonly != 0) { 349205821Sedwin printf("-------\ndate: |%s|\n", date); 350205821Sedwin if (dateonly == 1) 351205821Sedwin return; 352205821Sedwin } 353205821Sedwin printf("flags: %x - %s\n", flags, showflags(flags)); 354205821Sedwin if (modifieroffset[0] != '\0') 355205821Sedwin printf("modifieroffset: |%s|\n", modifieroffset); 356205821Sedwin if (modifierindex[0] != '\0') 357205821Sedwin printf("modifierindex: |%s|\n", modifierindex); 358212035Sedwin if (year[0] != '\0') 359212035Sedwin printf("year: |%s| (%d)\n", year, iyear); 360205821Sedwin if (month[0] != '\0') 361205821Sedwin printf("month: |%s| (%d)\n", month, imonth); 362205821Sedwin if (dayofmonth[0] != '\0') 363205821Sedwin printf("dayofmonth: |%s| (%d)\n", dayofmonth, idayofmonth); 364205821Sedwin if (dayofweek[0] != '\0') 365205821Sedwin printf("dayofweek: |%s| (%d)\n", dayofweek, idayofweek); 366205821Sedwin if (specialday[0] != '\0') 367205821Sedwin printf("specialday: |%s|\n", specialday); 368205821Sedwin} 369205821Sedwin 370205821Sedwinstruct yearinfo { 371205821Sedwin int year; 372205821Sedwin int ieaster, ipaskha, firstcnyday; 373205821Sedwin double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; 374205821Sedwin double ffullmooncny[MAXMOONS], fnewmooncny[MAXMOONS]; 375205821Sedwin int ichinesemonths[MAXMOONS]; 376205821Sedwin double equinoxdays[2], solsticedays[2]; 377205821Sedwin int *mondays; 378205821Sedwin struct yearinfo *next; 379205821Sedwin}; 380205821Sedwin/* 381205821Sedwin * Possible date formats include any combination of: 382205821Sedwin * 3-charmonth (January, Jan, Jan) 383205821Sedwin * 3-charweekday (Friday, Monday, mon.) 384205821Sedwin * numeric month or day (1, 2, 04) 385205821Sedwin * 386205821Sedwin * Any character may separate them, or they may not be separated. Any line, 387205821Sedwin * following a line that is matched, that starts with "whitespace", is shown 388205821Sedwin * along with the matched line. 389205821Sedwin */ 390205821Sedwinint 391205821Sedwinparsedaymonth(char *date, int *yearp, int *monthp, int *dayp, int *flags, 392205821Sedwin char **edp) 393205821Sedwin{ 394205821Sedwin char month[100], dayofmonth[100], dayofweek[100], modifieroffset[100]; 395212035Sedwin char syear[100]; 396205821Sedwin char modifierindex[100], specialday[100]; 397212035Sedwin int idayofweek = -1, imonth = -1, idayofmonth = -1, iyear = -1; 398212035Sedwin int year, remindex; 399205821Sedwin int d, m, dow, rm, rd, offset; 400205821Sedwin char *ed; 401205821Sedwin int retvalsign = 1; 402205821Sedwin 403205821Sedwin static struct yearinfo *years, *yearinfo; 404205821Sedwin 405205821Sedwin /* 406205821Sedwin * CONVENTION 407205821Sedwin * 408205821Sedwin * Month: 1-12 409205821Sedwin * Monthname: Jan .. Dec 410205821Sedwin * Day: 1-31 411205821Sedwin * Weekday: Mon .. Sun 412205821Sedwin * 413205821Sedwin */ 414205821Sedwin 415205821Sedwin *flags = 0; 416205821Sedwin 417205821Sedwin if (debug) 418205821Sedwin debug_determinestyle(1, date, *flags, month, imonth, 419205821Sedwin dayofmonth, idayofmonth, dayofweek, idayofweek, 420212035Sedwin modifieroffset, modifierindex, specialday, syear, iyear); 421205821Sedwin if (determinestyle(date, flags, month, &imonth, dayofmonth, 422205821Sedwin &idayofmonth, dayofweek, &idayofweek, modifieroffset, 423212035Sedwin modifierindex, specialday, syear, &iyear) == 0) { 424205821Sedwin if (debug) 425205821Sedwin printf("Failed!\n"); 426205821Sedwin return (0); 427205821Sedwin } 428205821Sedwin 429205821Sedwin if (debug) 430205821Sedwin debug_determinestyle(0, date, *flags, month, imonth, 431205821Sedwin dayofmonth, idayofmonth, dayofweek, idayofweek, 432212035Sedwin modifieroffset, modifierindex, specialday, syear, iyear); 433205821Sedwin 434205821Sedwin remindex = 0; 435205821Sedwin for (year = year1; year <= year2; year++) { 436212035Sedwin 437212035Sedwin int lflags = *flags; 438212035Sedwin /* If the year is specified, only do it if it is this year! */ 439212035Sedwin if ((lflags & F_YEAR) != 0) 440212035Sedwin if (iyear != year) 441212035Sedwin continue; 442212035Sedwin lflags &= ~F_YEAR; 443212035Sedwin 444205821Sedwin /* Get important dates for this year */ 445205821Sedwin yearinfo = years; 446205821Sedwin while (yearinfo != NULL) { 447205821Sedwin if (yearinfo->year == year) 448205821Sedwin break; 449205821Sedwin yearinfo = yearinfo -> next; 450205821Sedwin } 451205821Sedwin if (yearinfo == NULL) { 452205821Sedwin yearinfo = (struct yearinfo *)calloc(1, 453205821Sedwin sizeof(struct yearinfo)); 454205821Sedwin if (yearinfo == NULL) 455205821Sedwin errx(1, "Unable to allocate more years"); 456205821Sedwin yearinfo->year = year; 457205821Sedwin yearinfo->next = years; 458205821Sedwin years = yearinfo; 459205821Sedwin 460205821Sedwin yearinfo->mondays = mondaytab[isleap(year)]; 461205821Sedwin yearinfo->ieaster = easter(year); 462218471Sosa yearinfo->ipaskha = paskha(year); 463205821Sedwin fpom(year, UTCOffset, yearinfo->ffullmoon, 464205821Sedwin yearinfo->fnewmoon); 465205821Sedwin fpom(year, UTCOFFSET_CNY, yearinfo->ffullmooncny, 466205821Sedwin yearinfo->fnewmooncny); 467205821Sedwin fequinoxsolstice(year, UTCOffset, 468205821Sedwin yearinfo->equinoxdays, yearinfo->solsticedays); 469205821Sedwin 470205821Sedwin /* 471205821Sedwin * CNY: Match day with sun longitude at 330` with new 472205821Sedwin * moon 473205821Sedwin */ 474205821Sedwin yearinfo->firstcnyday = calculatesunlongitude30(year, 475205821Sedwin UTCOFFSET_CNY, yearinfo->ichinesemonths); 476205821Sedwin for (m = 0; yearinfo->fnewmooncny[m] >= 0; m++) { 477205821Sedwin if (yearinfo->fnewmooncny[m] > 478205821Sedwin yearinfo->firstcnyday) { 479205821Sedwin yearinfo->firstcnyday = 480205821Sedwin floor(yearinfo->fnewmooncny[m - 1]); 481205821Sedwin break; 482205821Sedwin } 483205821Sedwin } 484205821Sedwin } 485205821Sedwin 486205821Sedwin /* Same day every year */ 487212035Sedwin if (lflags == (F_MONTH | F_DAYOFMONTH)) { 488205821Sedwin if (!remember_ymd(year, imonth, idayofmonth)) 489205821Sedwin continue; 490205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 491205821Sedwin year, imonth, idayofmonth, NULL); 492205821Sedwin continue; 493205821Sedwin } 494205821Sedwin 495205821Sedwin /* XXX Same day every year, but variable */ 496212035Sedwin if (lflags == (F_MONTH | F_DAYOFMONTH | F_VARIABLE)) { 497205821Sedwin if (!remember_ymd(year, imonth, idayofmonth)) 498205821Sedwin continue; 499205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 500205821Sedwin year, imonth, idayofmonth, NULL); 501205821Sedwin continue; 502205821Sedwin } 503205821Sedwin 504205821Sedwin /* Same day every month */ 505212035Sedwin if (lflags == (F_ALLMONTH | F_DAYOFMONTH)) { 506205821Sedwin for (m = 1; m <= 12; m++) { 507205821Sedwin if (!remember_ymd(year, m, idayofmonth)) 508205821Sedwin continue; 509205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 510205821Sedwin year, m, idayofmonth, NULL); 511205821Sedwin } 512205821Sedwin continue; 513205821Sedwin } 514205821Sedwin 515205821Sedwin /* Every day of a month */ 516212035Sedwin if (lflags == (F_ALLDAY | F_MONTH)) { 517205821Sedwin for (d = 1; d <= yearinfo->mondays[imonth]; d++) { 518205821Sedwin if (!remember_ymd(year, imonth, d)) 519205821Sedwin continue; 520205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 521205821Sedwin year, imonth, d, NULL); 522205821Sedwin } 523205821Sedwin continue; 524205821Sedwin } 525205821Sedwin 526205821Sedwin /* One day of every month */ 527212035Sedwin if (lflags == (F_ALLMONTH | F_DAYOFWEEK)) { 528205821Sedwin for (m = 1; m <= 12; m++) { 529205821Sedwin if (!remember_ymd(year, m, idayofmonth)) 530205821Sedwin continue; 531205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 532205821Sedwin year, m, idayofmonth, NULL); 533205821Sedwin } 534205821Sedwin continue; 535205821Sedwin } 536205821Sedwin 537205821Sedwin /* Every dayofweek of the year */ 538212035Sedwin if (lflags == (F_DAYOFWEEK | F_VARIABLE)) { 539205821Sedwin dow = first_dayofweek_of_year(year); 540205821Sedwin d = (idayofweek - dow + 8) % 7; 541205821Sedwin while (d <= 366) { 542205821Sedwin if (remember_yd(year, d, &rm, &rd)) 543205821Sedwin remember(&remindex, 544205821Sedwin yearp, monthp, dayp, edp, 545205821Sedwin year, rm, rd, NULL); 546205821Sedwin d += 7; 547205821Sedwin } 548205821Sedwin continue; 549205821Sedwin } 550205821Sedwin 551223928Sedwin /* Every so-manied dayofweek of every month of the year */ 552223928Sedwin if (lflags == (F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { 553223928Sedwin offset = indextooffset(modifierindex); 554223928Sedwin 555223928Sedwin for (m = 0; m < 12; m++) { 556223928Sedwin dow = first_dayofweek_of_month(year, m); 557223928Sedwin d = (idayofweek - dow + 8) % 7; 558223928Sedwin d += (offset - 1) * 7; 559223928Sedwin if (remember_ymd(year, m, d)) { 560223928Sedwin remember(&remindex, 561223928Sedwin yearp, monthp, dayp, edp, 562223928Sedwin year, m, d, NULL); 563223928Sedwin continue; 564223928Sedwin } 565223928Sedwin } 566223928Sedwin continue; 567223928Sedwin } 568223928Sedwin 569205821Sedwin /* A certain dayofweek of a month */ 570212035Sedwin if (lflags == 571205821Sedwin (F_MONTH | F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { 572205821Sedwin offset = indextooffset(modifierindex); 573205821Sedwin dow = first_dayofweek_of_month(year, imonth); 574205821Sedwin d = (idayofweek - dow + 8) % 7; 575205821Sedwin 576205821Sedwin if (offset > 0) { 577205821Sedwin while (d <= yearinfo->mondays[imonth]) { 578205821Sedwin if (--offset == 0 579205821Sedwin && remember_ymd(year, imonth, d)) { 580205821Sedwin remember(&remindex, 581205821Sedwin yearp, monthp, dayp, edp, 582205821Sedwin year, imonth, d, NULL); 583205821Sedwin continue; 584205821Sedwin } 585205821Sedwin d += 7; 586205821Sedwin } 587205821Sedwin continue; 588205821Sedwin } 589205821Sedwin if (offset < 0) { 590205821Sedwin while (d <= yearinfo->mondays[imonth]) 591205821Sedwin d += 7; 592205821Sedwin while (offset != 0) { 593205821Sedwin offset++; 594205821Sedwin d -= 7; 595205821Sedwin } 596205821Sedwin if (remember_ymd(year, imonth, d)) 597205821Sedwin remember(&remindex, 598205821Sedwin yearp, monthp, dayp, edp, 599205821Sedwin year, imonth, d, NULL); 600205821Sedwin continue; 601205821Sedwin } 602205821Sedwin continue; 603205821Sedwin } 604205821Sedwin 605205821Sedwin /* Every dayofweek of the month */ 606212035Sedwin if (lflags == (F_DAYOFWEEK | F_MONTH | F_VARIABLE)) { 607205821Sedwin dow = first_dayofweek_of_month(year, imonth); 608205821Sedwin d = (idayofweek - dow + 8) % 7; 609205821Sedwin while (d <= yearinfo->mondays[imonth]) { 610205821Sedwin if (remember_ymd(year, imonth, d)) 611205821Sedwin remember(&remindex, 612205821Sedwin yearp, monthp, dayp, edp, 613205821Sedwin year, imonth, d, NULL); 614205821Sedwin d += 7; 615205821Sedwin } 616205821Sedwin continue; 617205821Sedwin } 618205821Sedwin 619205821Sedwin /* Easter */ 620212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 621205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_EASTER)) { 622205821Sedwin offset = 0; 623212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 624205821Sedwin offset = parseoffset(modifieroffset); 625205821Sedwin if (remember_yd(year, yearinfo->ieaster + offset, 626205821Sedwin &rm, &rd)) 627205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 628205821Sedwin year, rm, rd, NULL); 629205821Sedwin continue; 630205821Sedwin } 631205821Sedwin 632205821Sedwin /* Paskha */ 633212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 634205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_PASKHA)) { 635205821Sedwin offset = 0; 636212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 637205821Sedwin offset = parseoffset(modifieroffset); 638205821Sedwin if (remember_yd(year, yearinfo->ipaskha + offset, 639205821Sedwin &rm, &rd)) 640205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 641205821Sedwin year, rm, rd, NULL); 642205821Sedwin continue; 643205821Sedwin } 644205821Sedwin 645205821Sedwin /* Chinese New Year */ 646212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 647205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_CNY)) { 648205821Sedwin offset = 0; 649212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 650205821Sedwin offset = parseoffset(modifieroffset); 651205821Sedwin if (remember_yd(year, yearinfo->firstcnyday + offset, 652205821Sedwin &rm, &rd)) 653205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 654205821Sedwin year, rm, rd, NULL); 655205821Sedwin continue; 656205821Sedwin } 657205821Sedwin 658205821Sedwin /* FullMoon */ 659212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 660205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_FULLMOON)) { 661205821Sedwin int i; 662205821Sedwin 663205821Sedwin offset = 0; 664212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 665205821Sedwin offset = parseoffset(modifieroffset); 666205821Sedwin for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { 667205821Sedwin if (remember_yd(year, 668205821Sedwin floor(yearinfo->ffullmoon[i]) + offset, 669205821Sedwin &rm, &rd)) { 670205821Sedwin ed = floattotime( 671205821Sedwin yearinfo->ffullmoon[i]); 672205821Sedwin remember(&remindex, 673205821Sedwin yearp, monthp, dayp, edp, 674205821Sedwin year, rm, rd, ed); 675205821Sedwin } 676205821Sedwin } 677205821Sedwin continue; 678205821Sedwin } 679205821Sedwin 680205821Sedwin /* NewMoon */ 681212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 682205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_NEWMOON)) { 683205821Sedwin int i; 684205821Sedwin 685205821Sedwin offset = 0; 686212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 687205821Sedwin offset = parseoffset(modifieroffset); 688205821Sedwin for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { 689205821Sedwin if (remember_yd(year, 690205821Sedwin floor(yearinfo->fnewmoon[i]) + offset, 691205821Sedwin &rm, &rd)) { 692205821Sedwin ed = floattotime(yearinfo->fnewmoon[i]); 693205821Sedwin remember(&remindex, 694205821Sedwin yearp, monthp, dayp, edp, 695205821Sedwin year, rm, rd, ed); 696205821Sedwin } 697205821Sedwin } 698205821Sedwin continue; 699205821Sedwin } 700205821Sedwin 701205821Sedwin /* (Mar|Sep)Equinox */ 702212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 703205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_MAREQUINOX)) { 704205821Sedwin offset = 0; 705212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 706205821Sedwin offset = parseoffset(modifieroffset); 707205821Sedwin if (remember_yd(year, yearinfo->equinoxdays[0] + offset, 708205821Sedwin &rm, &rd)) { 709205821Sedwin ed = floattotime(yearinfo->equinoxdays[0]); 710205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 711205821Sedwin year, rm, rd, ed); 712205821Sedwin } 713205821Sedwin continue; 714205821Sedwin } 715212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 716205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_SEPEQUINOX)) { 717205821Sedwin offset = 0; 718212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 719205821Sedwin offset = parseoffset(modifieroffset); 720205821Sedwin if (remember_yd(year, yearinfo->equinoxdays[1] + offset, 721205821Sedwin &rm, &rd)) { 722205821Sedwin ed = floattotime(yearinfo->equinoxdays[1]); 723205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 724205821Sedwin year, rm, rd, ed); 725205821Sedwin } 726205821Sedwin continue; 727205821Sedwin } 728205821Sedwin 729205821Sedwin /* (Jun|Dec)Solstice */ 730212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 731205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_JUNSOLSTICE)) { 732205821Sedwin offset = 0; 733212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 734205821Sedwin offset = parseoffset(modifieroffset); 735205821Sedwin if (remember_yd(year, 736205821Sedwin yearinfo->solsticedays[0] + offset, &rm, &rd)) { 737205821Sedwin ed = floattotime(yearinfo->solsticedays[0]); 738205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 739205821Sedwin year, rm, rd, ed); 740205821Sedwin } 741205821Sedwin continue; 742205821Sedwin } 743212035Sedwin if ((lflags & ~F_MODIFIEROFFSET) == 744205821Sedwin (F_SPECIALDAY | F_VARIABLE | F_DECSOLSTICE)) { 745205821Sedwin offset = 0; 746212035Sedwin if ((lflags & F_MODIFIEROFFSET) != 0) 747205821Sedwin offset = parseoffset(modifieroffset); 748205821Sedwin if (remember_yd(year, 749205821Sedwin yearinfo->solsticedays[1] + offset, &rm, &rd)) { 750205821Sedwin ed = floattotime(yearinfo->solsticedays[1]); 751205821Sedwin remember(&remindex, yearp, monthp, dayp, edp, 752205821Sedwin year, rm, rd, ed); 753205821Sedwin } 754205821Sedwin continue; 755205821Sedwin } 756205821Sedwin 757205821Sedwin printf("Unprocessed:\n"); 758212035Sedwin debug_determinestyle(2, date, lflags, month, imonth, 759205821Sedwin dayofmonth, idayofmonth, dayofweek, idayofweek, 760212035Sedwin modifieroffset, modifierindex, specialday, syear, iyear); 761205821Sedwin retvalsign = -1; 762205821Sedwin } 763205821Sedwin 764205821Sedwin if (retvalsign == -1) 765205821Sedwin return (-remindex - 1); 766205821Sedwin else 767205821Sedwin return (remindex); 768205821Sedwin} 769205821Sedwin 770205821Sedwinstatic char * 771205821Sedwinshowflags(int flags) 772205821Sedwin{ 773205821Sedwin static char s[1000]; 774205821Sedwin s[0] = '\0'; 775205821Sedwin 776212035Sedwin if ((flags & F_YEAR) != 0) 777212035Sedwin strcat(s, "year "); 778205821Sedwin if ((flags & F_MONTH) != 0) 779205821Sedwin strcat(s, "month "); 780205821Sedwin if ((flags & F_DAYOFWEEK) != 0) 781205821Sedwin strcat(s, "dayofweek "); 782205821Sedwin if ((flags & F_DAYOFMONTH) != 0) 783205821Sedwin strcat(s, "dayofmonth "); 784205821Sedwin if ((flags & F_MODIFIERINDEX) != 0) 785205821Sedwin strcat(s, "modifierindex "); 786205821Sedwin if ((flags & F_MODIFIEROFFSET) != 0) 787205821Sedwin strcat(s, "modifieroffset "); 788205821Sedwin if ((flags & F_SPECIALDAY) != 0) 789205821Sedwin strcat(s, "specialday "); 790205821Sedwin if ((flags & F_ALLMONTH) != 0) 791205821Sedwin strcat(s, "allmonth "); 792205821Sedwin if ((flags & F_ALLDAY) != 0) 793205821Sedwin strcat(s, "allday "); 794205821Sedwin if ((flags & F_VARIABLE) != 0) 795205821Sedwin strcat(s, "variable "); 796205821Sedwin if ((flags & F_CNY) != 0) 797205821Sedwin strcat(s, "chinesenewyear "); 798205821Sedwin if ((flags & F_PASKHA) != 0) 799205821Sedwin strcat(s, "paskha "); 800205821Sedwin if ((flags & F_EASTER) != 0) 801205821Sedwin strcat(s, "easter "); 802205821Sedwin if ((flags & F_FULLMOON) != 0) 803205821Sedwin strcat(s, "fullmoon "); 804205821Sedwin if ((flags & F_NEWMOON) != 0) 805205821Sedwin strcat(s, "newmoon "); 806205821Sedwin if ((flags & F_MAREQUINOX) != 0) 807205821Sedwin strcat(s, "marequinox "); 808205821Sedwin if ((flags & F_SEPEQUINOX) != 0) 809205821Sedwin strcat(s, "sepequinox "); 810205821Sedwin if ((flags & F_JUNSOLSTICE) != 0) 811205821Sedwin strcat(s, "junsolstice "); 812205821Sedwin if ((flags & F_DECSOLSTICE) != 0) 813205821Sedwin strcat(s, "decsolstice "); 814205821Sedwin 815205821Sedwin return s; 816205821Sedwin} 817205821Sedwin 818205821Sedwinstatic const char * 819205821Sedwingetmonthname(int i) 820205821Sedwin{ 821223939Sedwin if (i <= 0 || i > 12) 822223939Sedwin return (""); 823205821Sedwin if (nmonths[i - 1].len != 0 && nmonths[i - 1].name != NULL) 824205821Sedwin return (nmonths[i - 1].name); 825205821Sedwin return (months[i - 1]); 826205821Sedwin} 827205821Sedwin 828205821Sedwinstatic int 829205834Sdescheckmonth(char *s, size_t *len, size_t *offset, const char **month) 830205821Sedwin{ 831205821Sedwin struct fixs *n; 832205821Sedwin int i; 833205821Sedwin 834205821Sedwin for (i = 0; fnmonths[i].name != NULL; i++) { 835205821Sedwin n = fnmonths + i; 836205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 837205821Sedwin *len = n->len; 838205821Sedwin *month = n->name; 839205821Sedwin *offset = i + 1; 840205821Sedwin return (1); 841205821Sedwin } 842205821Sedwin } 843205821Sedwin for (i = 0; nmonths[i].name != NULL; i++) { 844205821Sedwin n = nmonths + i; 845205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 846205821Sedwin *len = n->len; 847205821Sedwin *month = n->name; 848205821Sedwin *offset = i + 1; 849205821Sedwin return (1); 850205821Sedwin } 851205821Sedwin } 852205821Sedwin for (i = 0; fmonths[i] != NULL; i++) { 853205821Sedwin *len = strlen(fmonths[i]); 854205821Sedwin if (strncasecmp(s, fmonths[i], *len) == 0) { 855205821Sedwin *month = fmonths[i]; 856205821Sedwin *offset = i + 1; 857205821Sedwin return (1); 858205821Sedwin } 859205821Sedwin } 860205821Sedwin for (i = 0; months[i] != NULL; i++) { 861205821Sedwin if (strncasecmp(s, months[i], 3) == 0) { 862205821Sedwin *len = 3; 863205821Sedwin *month = months[i]; 864205821Sedwin *offset = i + 1; 865205821Sedwin return (1); 866205821Sedwin } 867205821Sedwin } 868205821Sedwin return (0); 869205821Sedwin} 870205821Sedwin 871205821Sedwinstatic const char * 872205821Sedwingetdayofweekname(int i) 873205821Sedwin{ 874205821Sedwin if (ndays[i].len != 0 && ndays[i].name != NULL) 875205821Sedwin return (ndays[i].name); 876205821Sedwin return (days[i]); 877205821Sedwin} 878205821Sedwin 879205821Sedwinstatic int 880205834Sdescheckdayofweek(char *s, size_t *len, size_t *offset, const char **dow) 881205821Sedwin{ 882205821Sedwin struct fixs *n; 883205821Sedwin int i; 884205821Sedwin 885205821Sedwin for (i = 0; fndays[i].name != NULL; i++) { 886205821Sedwin n = fndays + i; 887205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 888205821Sedwin *len = n->len; 889205821Sedwin *dow = n->name; 890205821Sedwin *offset = i; 891205821Sedwin return (1); 892205821Sedwin } 893205821Sedwin } 894205821Sedwin for (i = 0; ndays[i].name != NULL; i++) { 895205821Sedwin n = ndays + i; 896205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 897205821Sedwin *len = n->len; 898205821Sedwin *dow = n->name; 899205821Sedwin *offset = i; 900205821Sedwin return (1); 901205821Sedwin } 902205821Sedwin } 903205821Sedwin for (i = 0; fdays[i] != NULL; i++) { 904205821Sedwin *len = strlen(fdays[i]); 905205821Sedwin if (strncasecmp(s, fdays[i], *len) == 0) { 906205821Sedwin *dow = fdays[i]; 907205821Sedwin *offset = i; 908205821Sedwin return (1); 909205821Sedwin } 910205821Sedwin } 911205821Sedwin for (i = 0; days[i] != NULL; i++) { 912205821Sedwin if (strncasecmp(s, days[i], 3) == 0) { 913205821Sedwin *len = 3; 914205821Sedwin *dow = days[i]; 915205821Sedwin *offset = i; 916205821Sedwin return (1); 917205821Sedwin } 918205821Sedwin } 919205821Sedwin return (0); 920205821Sedwin} 921205821Sedwin 922205821Sedwinstatic int 923205821Sedwinisonlydigits(char *s, int nostar) 924205821Sedwin{ 925205821Sedwin int i; 926205821Sedwin for (i = 0; s[i] != '\0'; i++) { 927205821Sedwin if (nostar == 0 && s[i] == '*' && s[i + 1] == '\0') 928205821Sedwin return 1; 929207703Sache if (!isdigit((unsigned char)s[i])) 930205821Sedwin return (0); 931205821Sedwin } 932205821Sedwin return (1); 933205821Sedwin} 934205821Sedwin 935205821Sedwinstatic int 936205821Sedwinindextooffset(char *s) 937205821Sedwin{ 938205821Sedwin int i; 939205821Sedwin struct fixs *n; 940205821Sedwin 941223928Sedwin if (s[0] == '+' || s[0] == '-') { 942223928Sedwin char ss[9]; 943223928Sedwin for (i = -100; i < 100; i++) { 944223928Sedwin sprintf(ss, "%s%d", (i > 0) ? "+" : "", i); 945223928Sedwin if (strcmp(ss, s) == 0) 946223928Sedwin return (i); 947223928Sedwin } 948223928Sedwin return (0); 949223928Sedwin } 950223928Sedwin 951205821Sedwin for (i = 0; i < 6; i++) { 952205821Sedwin if (strcasecmp(s, sequences[i]) == 0) { 953205821Sedwin if (i == 5) 954205821Sedwin return (-1); 955205821Sedwin return (i + 1); 956205821Sedwin } 957205821Sedwin } 958205821Sedwin for (i = 0; i < 6; i++) { 959205821Sedwin n = nsequences + i; 960205821Sedwin if (n->len == 0) 961205821Sedwin continue; 962205821Sedwin if (strncasecmp(s, n->name, n->len) == 0) { 963205821Sedwin if (i == 5) 964205821Sedwin return (-1); 965205821Sedwin return (i + 1); 966205821Sedwin } 967205821Sedwin } 968205821Sedwin return (0); 969205821Sedwin} 970205821Sedwin 971205821Sedwinstatic int 972205821Sedwinparseoffset(char *s) 973205821Sedwin{ 974205821Sedwin 975205821Sedwin return strtol(s, NULL, 10); 976205821Sedwin} 977205821Sedwin 978205821Sedwinstatic char * 979205821Sedwinfloattotime(double f) 980205821Sedwin{ 981205821Sedwin static char buf[100]; 982205821Sedwin int hh, mm, ss, i; 983205821Sedwin 984205821Sedwin f -= floor(f); 985205821Sedwin i = f * SECSPERDAY; 986205821Sedwin 987205821Sedwin hh = i / SECSPERHOUR; 988205821Sedwin i %= SECSPERHOUR; 989205821Sedwin mm = i / SECSPERMINUTE; 990205821Sedwin i %= SECSPERMINUTE; 991205821Sedwin ss = i; 992205821Sedwin 993205821Sedwin sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); 994205821Sedwin return (buf); 995205821Sedwin} 996205821Sedwin 997205821Sedwinstatic char * 998205821Sedwinfloattoday(int year, double f) 999205821Sedwin{ 1000205821Sedwin static char buf[100]; 1001205821Sedwin int i, m, d, hh, mm, ss; 1002205821Sedwin int *cumdays = cumdaytab[isleap(year)]; 1003205821Sedwin 1004205821Sedwin for (i = 0; 1 + cumdays[i] < f; i++) 1005212591Semaste ; 1006205821Sedwin m = --i; 1007205821Sedwin d = floor(f - 1 - cumdays[i]); 1008205821Sedwin f -= floor(f); 1009205821Sedwin i = f * SECSPERDAY; 1010205821Sedwin 1011205821Sedwin hh = i / SECSPERHOUR; 1012205821Sedwin i %= SECSPERHOUR; 1013205821Sedwin mm = i / SECSPERMINUTE; 1014205821Sedwin i %= SECSPERMINUTE; 1015205821Sedwin ss = i; 1016205821Sedwin 1017205821Sedwin sprintf(buf, "%02d-%02d %02d:%02d:%02d", m, d, hh, mm, ss); 1018205821Sedwin return (buf); 1019205821Sedwin} 1020205821Sedwin 1021205821Sedwinvoid 1022205821Sedwindodebug(char *what) 1023205821Sedwin{ 1024205821Sedwin int year; 1025205821Sedwin 1026205821Sedwin printf("UTCOffset: %g\n", UTCOffset); 1027205821Sedwin printf("eastlongitude: %d\n", EastLongitude); 1028205821Sedwin 1029205821Sedwin if (strcmp(what, "moon") == 0) { 1030205821Sedwin double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; 1031205821Sedwin int i; 1032205821Sedwin 1033205821Sedwin for (year = year1; year <= year2; year++) { 1034205821Sedwin fpom(year, UTCOffset, ffullmoon, fnewmoon); 1035205821Sedwin printf("Full moon %d:\t", year); 1036205821Sedwin for (i = 0; ffullmoon[i] >= 0; i++) { 1037205821Sedwin printf("%g (%s) ", ffullmoon[i], 1038205821Sedwin floattoday(year, ffullmoon[i])); 1039205821Sedwin } 1040205821Sedwin printf("\nNew moon %d:\t", year); 1041205821Sedwin for (i = 0; fnewmoon[i] >= 0; i++) { 1042205821Sedwin printf("%g (%s) ", fnewmoon[i], 1043205821Sedwin floattoday(year, fnewmoon[i])); 1044205821Sedwin } 1045205821Sedwin printf("\n"); 1046205821Sedwin 1047205821Sedwin } 1048205821Sedwin 1049205821Sedwin return; 1050205821Sedwin } 1051205821Sedwin 1052205821Sedwin if (strcmp(what, "sun") == 0) { 1053205821Sedwin double equinoxdays[2], solsticedays[2]; 1054205821Sedwin for (year = year1; year <= year2; year++) { 1055205821Sedwin printf("Sun in %d:\n", year); 1056205821Sedwin fequinoxsolstice(year, UTCOffset, equinoxdays, 1057205821Sedwin solsticedays); 1058205821Sedwin printf("e[0] - %g (%s)\n", 1059205821Sedwin equinoxdays[0], 1060205821Sedwin floattoday(year, equinoxdays[0])); 1061205821Sedwin printf("e[1] - %g (%s)\n", 1062205821Sedwin equinoxdays[1], 1063205821Sedwin floattoday(year, equinoxdays[1])); 1064205821Sedwin printf("s[0] - %g (%s)\n", 1065205821Sedwin solsticedays[0], 1066205821Sedwin floattoday(year, solsticedays[0])); 1067205821Sedwin printf("s[1] - %g (%s)\n", 1068205821Sedwin solsticedays[1], 1069205821Sedwin floattoday(year, solsticedays[1])); 1070205821Sedwin } 1071205821Sedwin return; 1072205821Sedwin } 1073205821Sedwin} 1074