1*d19ef5a2SAaron LI /*-
2*d19ef5a2SAaron LI * SPDX-License-Identifier: BSD-3-Clause
3*d19ef5a2SAaron LI *
4*d19ef5a2SAaron LI * Copyright (c) 2020 The DragonFly Project. All rights reserved.
5*d19ef5a2SAaron LI *
6*d19ef5a2SAaron LI * This code is derived from software contributed to The DragonFly Project
7*d19ef5a2SAaron LI * by Aaron LI <aly@aaronly.me>
8*d19ef5a2SAaron LI *
9*d19ef5a2SAaron LI * Redistribution and use in source and binary forms, with or without
10*d19ef5a2SAaron LI * modification, are permitted provided that the following conditions
11*d19ef5a2SAaron LI * are met:
12*d19ef5a2SAaron LI *
13*d19ef5a2SAaron LI * 1. Redistributions of source code must retain the above copyright
14*d19ef5a2SAaron LI * notice, this list of conditions and the following disclaimer.
15*d19ef5a2SAaron LI * 2. Redistributions in binary form must reproduce the above copyright
16*d19ef5a2SAaron LI * notice, this list of conditions and the following disclaimer in
17*d19ef5a2SAaron LI * the documentation and/or other materials provided with the
18*d19ef5a2SAaron LI * distribution.
19*d19ef5a2SAaron LI * 3. Neither the name of The DragonFly Project nor the names of its
20*d19ef5a2SAaron LI * contributors may be used to endorse or promote products derived
21*d19ef5a2SAaron LI * from this software without specific, prior written permission.
22*d19ef5a2SAaron LI *
23*d19ef5a2SAaron LI * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*d19ef5a2SAaron LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25*d19ef5a2SAaron LI * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26*d19ef5a2SAaron LI * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27*d19ef5a2SAaron LI * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28*d19ef5a2SAaron LI * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29*d19ef5a2SAaron LI * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*d19ef5a2SAaron LI * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31*d19ef5a2SAaron LI * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32*d19ef5a2SAaron LI * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33*d19ef5a2SAaron LI * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34*d19ef5a2SAaron LI * SUCH DAMAGE.
35*d19ef5a2SAaron LI */
36*d19ef5a2SAaron LI
37*d19ef5a2SAaron LI #include <assert.h>
38*d19ef5a2SAaron LI #include <err.h>
39*d19ef5a2SAaron LI #include <math.h>
40*d19ef5a2SAaron LI #include <stddef.h>
41*d19ef5a2SAaron LI
42*d19ef5a2SAaron LI #include "calendar.h"
43*d19ef5a2SAaron LI #include "basics.h"
44*d19ef5a2SAaron LI #include "chinese.h"
45*d19ef5a2SAaron LI #include "dates.h"
46*d19ef5a2SAaron LI #include "days.h"
47*d19ef5a2SAaron LI #include "ecclesiastical.h"
48*d19ef5a2SAaron LI #include "gregorian.h"
49*d19ef5a2SAaron LI #include "moon.h"
50*d19ef5a2SAaron LI #include "nnames.h"
51*d19ef5a2SAaron LI #include "parsedata.h"
52*d19ef5a2SAaron LI #include "sun.h"
53*d19ef5a2SAaron LI #include "utils.h"
54*d19ef5a2SAaron LI
55*d19ef5a2SAaron LI static int find_days_yearly(int sday_id, int offset,
56*d19ef5a2SAaron LI struct cal_day **dayp, char **edp);
57*d19ef5a2SAaron LI static int find_days_moon(int sday_id, int offset,
58*d19ef5a2SAaron LI struct cal_day **dayp, char **edp);
59*d19ef5a2SAaron LI
60*d19ef5a2SAaron LI static int find_days_easter(int, struct cal_day **, char **);
61*d19ef5a2SAaron LI static int find_days_paskha(int, struct cal_day **, char **);
62*d19ef5a2SAaron LI static int find_days_advent(int, struct cal_day **, char **);
63*d19ef5a2SAaron LI static int find_days_cny(int, struct cal_day **, char **);
64*d19ef5a2SAaron LI static int find_days_cqingming(int, struct cal_day **, char **);
65*d19ef5a2SAaron LI static int find_days_cjieqi(int, struct cal_day **, char **);
66*d19ef5a2SAaron LI static int find_days_marequinox(int, struct cal_day **, char **);
67*d19ef5a2SAaron LI static int find_days_sepequinox(int, struct cal_day **, char **);
68*d19ef5a2SAaron LI static int find_days_junsolstice(int, struct cal_day **, char **);
69*d19ef5a2SAaron LI static int find_days_decsolstice(int, struct cal_day **, char **);
70*d19ef5a2SAaron LI static int find_days_newmoon(int, struct cal_day **, char **);
71*d19ef5a2SAaron LI static int find_days_fullmoon(int, struct cal_day **, char **);
72*d19ef5a2SAaron LI
73*d19ef5a2SAaron LI #define SPECIALDAY_INIT0 \
74*d19ef5a2SAaron LI { SD_NONE, NULL, 0, NULL, 0, NULL }
75*d19ef5a2SAaron LI #define SPECIALDAY_INIT(id, name, func) \
76*d19ef5a2SAaron LI { (id), name, sizeof(name)-1, NULL, 0, func }
77*d19ef5a2SAaron LI struct specialday specialdays[] = {
78*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_EASTER, "Easter", &find_days_easter),
79*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_PASKHA, "Paskha", &find_days_paskha),
80*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_ADVENT, "Advent", &find_days_advent),
81*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_CNY, "ChineseNewYear", &find_days_cny),
82*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_CQINGMING, "ChineseQingming", &find_days_cqingming),
83*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_CJIEQI, "ChineseJieqi", &find_days_cjieqi),
84*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_MAREQUINOX, "MarEquinox", &find_days_marequinox),
85*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_SEPEQUINOX, "SepEquinox", &find_days_sepequinox),
86*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_JUNSOLSTICE, "JunSolstice", &find_days_junsolstice),
87*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_DECSOLSTICE, "DecSolstice", &find_days_decsolstice),
88*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_NEWMOON, "NewMoon", &find_days_newmoon),
89*d19ef5a2SAaron LI SPECIALDAY_INIT(SD_FULLMOON, "FullMoon", &find_days_fullmoon),
90*d19ef5a2SAaron LI SPECIALDAY_INIT0,
91*d19ef5a2SAaron LI };
92*d19ef5a2SAaron LI
93*d19ef5a2SAaron LI
94*d19ef5a2SAaron LI static int
find_days_easter(int offset,struct cal_day ** dayp,char ** edp)95*d19ef5a2SAaron LI find_days_easter(int offset, struct cal_day **dayp, char **edp)
96*d19ef5a2SAaron LI {
97*d19ef5a2SAaron LI return find_days_yearly(SD_EASTER, offset, dayp, edp);
98*d19ef5a2SAaron LI }
99*d19ef5a2SAaron LI
100*d19ef5a2SAaron LI static int
find_days_paskha(int offset,struct cal_day ** dayp,char ** edp)101*d19ef5a2SAaron LI find_days_paskha(int offset, struct cal_day **dayp, char **edp)
102*d19ef5a2SAaron LI {
103*d19ef5a2SAaron LI return find_days_yearly(SD_PASKHA, offset, dayp, edp);
104*d19ef5a2SAaron LI }
105*d19ef5a2SAaron LI
106*d19ef5a2SAaron LI static int
find_days_advent(int offset,struct cal_day ** dayp,char ** edp)107*d19ef5a2SAaron LI find_days_advent(int offset, struct cal_day **dayp, char **edp)
108*d19ef5a2SAaron LI {
109*d19ef5a2SAaron LI return find_days_yearly(SD_ADVENT, offset, dayp, edp);
110*d19ef5a2SAaron LI }
111*d19ef5a2SAaron LI
112*d19ef5a2SAaron LI static int
find_days_cny(int offset,struct cal_day ** dayp,char ** edp)113*d19ef5a2SAaron LI find_days_cny(int offset, struct cal_day **dayp, char **edp)
114*d19ef5a2SAaron LI {
115*d19ef5a2SAaron LI return find_days_yearly(SD_CNY, offset, dayp, edp);
116*d19ef5a2SAaron LI }
117*d19ef5a2SAaron LI
118*d19ef5a2SAaron LI static int
find_days_cqingming(int offset,struct cal_day ** dayp,char ** edp)119*d19ef5a2SAaron LI find_days_cqingming(int offset, struct cal_day **dayp, char **edp)
120*d19ef5a2SAaron LI {
121*d19ef5a2SAaron LI return find_days_yearly(SD_CQINGMING, offset, dayp, edp);
122*d19ef5a2SAaron LI }
123*d19ef5a2SAaron LI
124*d19ef5a2SAaron LI static int
find_days_marequinox(int offset,struct cal_day ** dayp,char ** edp)125*d19ef5a2SAaron LI find_days_marequinox(int offset, struct cal_day **dayp, char **edp)
126*d19ef5a2SAaron LI {
127*d19ef5a2SAaron LI return find_days_yearly(SD_MAREQUINOX, offset, dayp, edp);
128*d19ef5a2SAaron LI }
129*d19ef5a2SAaron LI
130*d19ef5a2SAaron LI static int
find_days_sepequinox(int offset,struct cal_day ** dayp,char ** edp)131*d19ef5a2SAaron LI find_days_sepequinox(int offset, struct cal_day **dayp, char **edp)
132*d19ef5a2SAaron LI {
133*d19ef5a2SAaron LI return find_days_yearly(SD_SEPEQUINOX, offset, dayp, edp);
134*d19ef5a2SAaron LI }
135*d19ef5a2SAaron LI
136*d19ef5a2SAaron LI static int
find_days_junsolstice(int offset,struct cal_day ** dayp,char ** edp)137*d19ef5a2SAaron LI find_days_junsolstice(int offset, struct cal_day **dayp, char **edp)
138*d19ef5a2SAaron LI {
139*d19ef5a2SAaron LI return find_days_yearly(SD_JUNSOLSTICE, offset, dayp, edp);
140*d19ef5a2SAaron LI }
141*d19ef5a2SAaron LI
142*d19ef5a2SAaron LI static int
find_days_decsolstice(int offset,struct cal_day ** dayp,char ** edp)143*d19ef5a2SAaron LI find_days_decsolstice(int offset, struct cal_day **dayp, char **edp)
144*d19ef5a2SAaron LI {
145*d19ef5a2SAaron LI return find_days_yearly(SD_DECSOLSTICE, offset, dayp, edp);
146*d19ef5a2SAaron LI }
147*d19ef5a2SAaron LI
148*d19ef5a2SAaron LI /*
149*d19ef5a2SAaron LI * Find days of the yearly special day specified by $sday_id.
150*d19ef5a2SAaron LI */
151*d19ef5a2SAaron LI static int
find_days_yearly(int sday_id,int offset,struct cal_day ** dayp,char ** edp)152*d19ef5a2SAaron LI find_days_yearly(int sday_id, int offset, struct cal_day **dayp, char **edp)
153*d19ef5a2SAaron LI {
154*d19ef5a2SAaron LI struct cal_day *dp;
155*d19ef5a2SAaron LI struct date date;
156*d19ef5a2SAaron LI double t, longitude;
157*d19ef5a2SAaron LI char buf[32];
158*d19ef5a2SAaron LI int rd, approx, month;
159*d19ef5a2SAaron LI int year1, year2;
160*d19ef5a2SAaron LI int count = 0;
161*d19ef5a2SAaron LI
162*d19ef5a2SAaron LI year1 = gregorian_year_from_fixed(Options.day_begin);
163*d19ef5a2SAaron LI year2 = gregorian_year_from_fixed(Options.day_end);
164*d19ef5a2SAaron LI for (int y = year1; y <= year2; y++) {
165*d19ef5a2SAaron LI t = NAN;
166*d19ef5a2SAaron LI
167*d19ef5a2SAaron LI switch (sday_id) {
168*d19ef5a2SAaron LI case SD_EASTER:
169*d19ef5a2SAaron LI rd = easter(y);
170*d19ef5a2SAaron LI break;
171*d19ef5a2SAaron LI case SD_PASKHA:
172*d19ef5a2SAaron LI rd = orthodox_easter(y);
173*d19ef5a2SAaron LI break;
174*d19ef5a2SAaron LI case SD_ADVENT:
175*d19ef5a2SAaron LI rd = advent(y);
176*d19ef5a2SAaron LI break;
177*d19ef5a2SAaron LI case SD_CNY:
178*d19ef5a2SAaron LI rd = chinese_new_year(y);
179*d19ef5a2SAaron LI break;
180*d19ef5a2SAaron LI case SD_CQINGMING:
181*d19ef5a2SAaron LI rd = chinese_qingming(y);
182*d19ef5a2SAaron LI break;
183*d19ef5a2SAaron LI case SD_MAREQUINOX:
184*d19ef5a2SAaron LI case SD_JUNSOLSTICE:
185*d19ef5a2SAaron LI case SD_SEPEQUINOX:
186*d19ef5a2SAaron LI case SD_DECSOLSTICE:
187*d19ef5a2SAaron LI if (sday_id == SD_MAREQUINOX) {
188*d19ef5a2SAaron LI month = 3;
189*d19ef5a2SAaron LI longitude = 0.0;
190*d19ef5a2SAaron LI } else if (sday_id == SD_JUNSOLSTICE) {
191*d19ef5a2SAaron LI month = 6;
192*d19ef5a2SAaron LI longitude = 90.0;
193*d19ef5a2SAaron LI } else if (sday_id == SD_SEPEQUINOX) {
194*d19ef5a2SAaron LI month = 9;
195*d19ef5a2SAaron LI longitude = 180.0;
196*d19ef5a2SAaron LI } else {
197*d19ef5a2SAaron LI month = 12;
198*d19ef5a2SAaron LI longitude = 270.0;
199*d19ef5a2SAaron LI }
200*d19ef5a2SAaron LI date_set(&date, y, month, 1);
201*d19ef5a2SAaron LI approx = fixed_from_gregorian(&date);
202*d19ef5a2SAaron LI t = solar_longitude_atafter(longitude, approx);
203*d19ef5a2SAaron LI t += Options.location->zone; /* to standard time */
204*d19ef5a2SAaron LI rd = floor(t);
205*d19ef5a2SAaron LI break;
206*d19ef5a2SAaron LI default:
207*d19ef5a2SAaron LI errx(1, "%s: unknown special day: %d",
208*d19ef5a2SAaron LI __func__, sday_id);
209*d19ef5a2SAaron LI }
210*d19ef5a2SAaron LI
211*d19ef5a2SAaron LI if ((dp = find_rd(rd, offset)) != NULL) {
212*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
213*d19ef5a2SAaron LI warnx("%s: too many repeats", __func__);
214*d19ef5a2SAaron LI return count;
215*d19ef5a2SAaron LI }
216*d19ef5a2SAaron LI if (!isnan(t)) {
217*d19ef5a2SAaron LI format_time(buf, sizeof(buf), t);
218*d19ef5a2SAaron LI edp[count] = xstrdup(buf);
219*d19ef5a2SAaron LI }
220*d19ef5a2SAaron LI dayp[count++] = dp;
221*d19ef5a2SAaron LI }
222*d19ef5a2SAaron LI }
223*d19ef5a2SAaron LI
224*d19ef5a2SAaron LI return count;
225*d19ef5a2SAaron LI }
226*d19ef5a2SAaron LI
227*d19ef5a2SAaron LI /*
228*d19ef5a2SAaron LI * Find days of the 24 Chinese Jiéqì (节气)
229*d19ef5a2SAaron LI */
230*d19ef5a2SAaron LI static int
find_days_cjieqi(int offset,struct cal_day ** dayp,char ** edp)231*d19ef5a2SAaron LI find_days_cjieqi(int offset, struct cal_day **dayp, char **edp)
232*d19ef5a2SAaron LI {
233*d19ef5a2SAaron LI const struct chinese_jieqi *jq;
234*d19ef5a2SAaron LI struct cal_day *dp;
235*d19ef5a2SAaron LI struct date date;
236*d19ef5a2SAaron LI char buf[32];
237*d19ef5a2SAaron LI int year1, year2;
238*d19ef5a2SAaron LI int rd, rd_begin, rd_end;
239*d19ef5a2SAaron LI int count = 0;
240*d19ef5a2SAaron LI
241*d19ef5a2SAaron LI year1 = gregorian_year_from_fixed(Options.day_begin);
242*d19ef5a2SAaron LI year2 = gregorian_year_from_fixed(Options.day_end);
243*d19ef5a2SAaron LI for (int y = year1; y <= year2; y++) {
244*d19ef5a2SAaron LI date_set(&date, y, 1, 1);
245*d19ef5a2SAaron LI rd_begin = fixed_from_gregorian(&date);
246*d19ef5a2SAaron LI date.year++;
247*d19ef5a2SAaron LI rd_end = fixed_from_gregorian(&date);
248*d19ef5a2SAaron LI if (rd_end > Options.day_end)
249*d19ef5a2SAaron LI rd_end = Options.day_end;
250*d19ef5a2SAaron LI
251*d19ef5a2SAaron LI for (rd = rd_begin; rd <= rd_end; rd += 14) {
252*d19ef5a2SAaron LI rd = chinese_jieqi_onafter(rd, C_JIEQI_ALL, &jq);
253*d19ef5a2SAaron LI if (rd > rd_end)
254*d19ef5a2SAaron LI break;
255*d19ef5a2SAaron LI
256*d19ef5a2SAaron LI if ((dp = find_rd(rd, offset)) != NULL) {
257*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
258*d19ef5a2SAaron LI warnx("%s: too many repeats",
259*d19ef5a2SAaron LI __func__);
260*d19ef5a2SAaron LI return count;
261*d19ef5a2SAaron LI }
262*d19ef5a2SAaron LI snprintf(buf, sizeof(buf), "%s, %s",
263*d19ef5a2SAaron LI jq->name, jq->zhname);
264*d19ef5a2SAaron LI edp[count] = xstrdup(buf);
265*d19ef5a2SAaron LI dayp[count++] = dp;
266*d19ef5a2SAaron LI }
267*d19ef5a2SAaron LI }
268*d19ef5a2SAaron LI }
269*d19ef5a2SAaron LI
270*d19ef5a2SAaron LI return count;
271*d19ef5a2SAaron LI }
272*d19ef5a2SAaron LI
273*d19ef5a2SAaron LI static int
find_days_newmoon(int offset,struct cal_day ** dayp,char ** edp)274*d19ef5a2SAaron LI find_days_newmoon(int offset, struct cal_day **dayp, char **edp)
275*d19ef5a2SAaron LI {
276*d19ef5a2SAaron LI return find_days_moon(SD_NEWMOON, offset, dayp, edp);
277*d19ef5a2SAaron LI }
278*d19ef5a2SAaron LI
279*d19ef5a2SAaron LI static int
find_days_fullmoon(int offset,struct cal_day ** dayp,char ** edp)280*d19ef5a2SAaron LI find_days_fullmoon(int offset, struct cal_day **dayp, char **edp)
281*d19ef5a2SAaron LI {
282*d19ef5a2SAaron LI return find_days_moon(SD_FULLMOON, offset, dayp, edp);
283*d19ef5a2SAaron LI }
284*d19ef5a2SAaron LI
285*d19ef5a2SAaron LI /*
286*d19ef5a2SAaron LI * Find days of the moon events specified by $sday_id.
287*d19ef5a2SAaron LI */
288*d19ef5a2SAaron LI static int
find_days_moon(int sday_id,int offset,struct cal_day ** dayp,char ** edp)289*d19ef5a2SAaron LI find_days_moon(int sday_id, int offset, struct cal_day **dayp, char **edp)
290*d19ef5a2SAaron LI {
291*d19ef5a2SAaron LI struct cal_day *dp;
292*d19ef5a2SAaron LI struct date date;
293*d19ef5a2SAaron LI double t, t_begin, t_end;
294*d19ef5a2SAaron LI char buf[32];
295*d19ef5a2SAaron LI int year1, year2;
296*d19ef5a2SAaron LI int count = 0;
297*d19ef5a2SAaron LI
298*d19ef5a2SAaron LI year1 = gregorian_year_from_fixed(Options.day_begin);
299*d19ef5a2SAaron LI year2 = gregorian_year_from_fixed(Options.day_end);
300*d19ef5a2SAaron LI for (int y = year1; y <= year2; y++) {
301*d19ef5a2SAaron LI date_set(&date, y, 1, 1);
302*d19ef5a2SAaron LI t_begin = fixed_from_gregorian(&date) - Options.location->zone;
303*d19ef5a2SAaron LI date.year++;
304*d19ef5a2SAaron LI t_end = fixed_from_gregorian(&date) - Options.location->zone;
305*d19ef5a2SAaron LI if (t_end > Options.day_end + 1 - Options.location->zone)
306*d19ef5a2SAaron LI t_end = Options.day_end + 1 - Options.location->zone;
307*d19ef5a2SAaron LI /* NOTE: '+1' to include the ending day */
308*d19ef5a2SAaron LI
309*d19ef5a2SAaron LI for (t = t_begin; t <= t_end; ) {
310*d19ef5a2SAaron LI switch (sday_id) {
311*d19ef5a2SAaron LI case SD_NEWMOON:
312*d19ef5a2SAaron LI t = new_moon_atafter(t);
313*d19ef5a2SAaron LI break;
314*d19ef5a2SAaron LI case SD_FULLMOON:
315*d19ef5a2SAaron LI t = lunar_phase_atafter(180, t);
316*d19ef5a2SAaron LI break;
317*d19ef5a2SAaron LI default:
318*d19ef5a2SAaron LI errx(1, "%s: unknown moon event: %d",
319*d19ef5a2SAaron LI __func__, sday_id);
320*d19ef5a2SAaron LI }
321*d19ef5a2SAaron LI
322*d19ef5a2SAaron LI if (t > t_end)
323*d19ef5a2SAaron LI break;
324*d19ef5a2SAaron LI
325*d19ef5a2SAaron LI t += Options.location->zone; /* to standard time */
326*d19ef5a2SAaron LI if ((dp = find_rd(floor(t), offset)) != NULL) {
327*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
328*d19ef5a2SAaron LI warnx("%s: too many repeats",
329*d19ef5a2SAaron LI __func__);
330*d19ef5a2SAaron LI return count;
331*d19ef5a2SAaron LI }
332*d19ef5a2SAaron LI format_time(buf, sizeof(buf), t);
333*d19ef5a2SAaron LI edp[count] = xstrdup(buf);
334*d19ef5a2SAaron LI dayp[count++] = dp;
335*d19ef5a2SAaron LI }
336*d19ef5a2SAaron LI }
337*d19ef5a2SAaron LI }
338*d19ef5a2SAaron LI
339*d19ef5a2SAaron LI return count;
340*d19ef5a2SAaron LI }
341*d19ef5a2SAaron LI
342*d19ef5a2SAaron LI /**************************************************************************/
343*d19ef5a2SAaron LI
344*d19ef5a2SAaron LI /*
345*d19ef5a2SAaron LI * Find days of the specified year ($year), month ($month) and day ($day).
346*d19ef5a2SAaron LI * If year $year < 0, then year is ignored.
347*d19ef5a2SAaron LI */
348*d19ef5a2SAaron LI int
find_days_ymd(int year,int month,int day,struct cal_day ** dayp,char ** edp __unused)349*d19ef5a2SAaron LI find_days_ymd(int year, int month, int day,
350*d19ef5a2SAaron LI struct cal_day **dayp, char **edp __unused)
351*d19ef5a2SAaron LI {
352*d19ef5a2SAaron LI struct cal_day *dp = NULL;
353*d19ef5a2SAaron LI int count = 0;
354*d19ef5a2SAaron LI
355*d19ef5a2SAaron LI while ((dp = loop_dates(dp)) != NULL) {
356*d19ef5a2SAaron LI if (year >= 0 && year != dp->year)
357*d19ef5a2SAaron LI continue;
358*d19ef5a2SAaron LI if ((dp->month == month && dp->day == day) ||
359*d19ef5a2SAaron LI /* day of zero means the last day of previous month */
360*d19ef5a2SAaron LI (day == 0 && dp->last_dom && month == dp->month % 12 + 1)) {
361*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
362*d19ef5a2SAaron LI warnx("%s: too many repeats", __func__);
363*d19ef5a2SAaron LI return count;
364*d19ef5a2SAaron LI }
365*d19ef5a2SAaron LI dayp[count++] = dp;
366*d19ef5a2SAaron LI }
367*d19ef5a2SAaron LI }
368*d19ef5a2SAaron LI
369*d19ef5a2SAaron LI return count;
370*d19ef5a2SAaron LI }
371*d19ef5a2SAaron LI
372*d19ef5a2SAaron LI /*
373*d19ef5a2SAaron LI * Find days of the specified day of month ($dom) of all months.
374*d19ef5a2SAaron LI */
375*d19ef5a2SAaron LI int
find_days_dom(int dom,struct cal_day ** dayp,char ** edp __unused)376*d19ef5a2SAaron LI find_days_dom(int dom, struct cal_day **dayp, char **edp __unused)
377*d19ef5a2SAaron LI {
378*d19ef5a2SAaron LI struct cal_day *dp = NULL;
379*d19ef5a2SAaron LI int count = 0;
380*d19ef5a2SAaron LI
381*d19ef5a2SAaron LI while ((dp = loop_dates(dp)) != NULL) {
382*d19ef5a2SAaron LI if (dp->day == dom ||
383*d19ef5a2SAaron LI /* day of zero means the last day of previous month */
384*d19ef5a2SAaron LI (dom == 0 && dp->last_dom)) {
385*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
386*d19ef5a2SAaron LI warnx("%s: too many repeats", __func__);
387*d19ef5a2SAaron LI return count;
388*d19ef5a2SAaron LI }
389*d19ef5a2SAaron LI dayp[count++] = dp;
390*d19ef5a2SAaron LI }
391*d19ef5a2SAaron LI }
392*d19ef5a2SAaron LI
393*d19ef5a2SAaron LI return count;
394*d19ef5a2SAaron LI }
395*d19ef5a2SAaron LI
396*d19ef5a2SAaron LI /*
397*d19ef5a2SAaron LI * Find days of all days of the specified month ($month).
398*d19ef5a2SAaron LI */
399*d19ef5a2SAaron LI int
find_days_month(int month,struct cal_day ** dayp,char ** edp __unused)400*d19ef5a2SAaron LI find_days_month(int month, struct cal_day **dayp, char **edp __unused)
401*d19ef5a2SAaron LI {
402*d19ef5a2SAaron LI struct cal_day *dp = NULL;
403*d19ef5a2SAaron LI int count = 0;
404*d19ef5a2SAaron LI
405*d19ef5a2SAaron LI while ((dp = loop_dates(dp)) != NULL) {
406*d19ef5a2SAaron LI if (dp->month == month) {
407*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
408*d19ef5a2SAaron LI warnx("%s: too many repeats", __func__);
409*d19ef5a2SAaron LI return count;
410*d19ef5a2SAaron LI }
411*d19ef5a2SAaron LI dayp[count++] = dp;
412*d19ef5a2SAaron LI }
413*d19ef5a2SAaron LI }
414*d19ef5a2SAaron LI
415*d19ef5a2SAaron LI return count;
416*d19ef5a2SAaron LI }
417*d19ef5a2SAaron LI
418*d19ef5a2SAaron LI /*
419*d19ef5a2SAaron LI * If $index == 0, find days of every day-of-week ($dow) of the specified month
420*d19ef5a2SAaron LI * ($month). Otherwise, find days of the indexed day-of-week of the month.
421*d19ef5a2SAaron LI * If month $month < 0, then find days in every month.
422*d19ef5a2SAaron LI */
423*d19ef5a2SAaron LI int
find_days_mdow(int month,int dow,int index,struct cal_day ** dayp,char ** edp __unused)424*d19ef5a2SAaron LI find_days_mdow(int month, int dow, int index,
425*d19ef5a2SAaron LI struct cal_day **dayp, char **edp __unused)
426*d19ef5a2SAaron LI {
427*d19ef5a2SAaron LI struct cal_day *dp = NULL;
428*d19ef5a2SAaron LI int count = 0;
429*d19ef5a2SAaron LI
430*d19ef5a2SAaron LI while ((dp = loop_dates(dp)) != NULL) {
431*d19ef5a2SAaron LI if (month >= 0 && month != dp->month)
432*d19ef5a2SAaron LI continue;
433*d19ef5a2SAaron LI if (dp->dow[0] == dow) {
434*d19ef5a2SAaron LI if (index != 0 &&
435*d19ef5a2SAaron LI (index != dp->dow[1] && index != dp->dow[2])) {
436*d19ef5a2SAaron LI /* Not the indexed day-of-week of month */
437*d19ef5a2SAaron LI continue;
438*d19ef5a2SAaron LI }
439*d19ef5a2SAaron LI if (count >= CAL_MAX_REPEAT) {
440*d19ef5a2SAaron LI warnx("%s: too many repeats", __func__);
441*d19ef5a2SAaron LI return count;
442*d19ef5a2SAaron LI }
443*d19ef5a2SAaron LI dayp[count++] = dp;
444*d19ef5a2SAaron LI }
445*d19ef5a2SAaron LI }
446*d19ef5a2SAaron LI
447*d19ef5a2SAaron LI return count;
448*d19ef5a2SAaron LI }
449