1 /*
2 Hebcal - A Jewish Calendar Generator
3 Copyright (C) 1994 Danny Sadinoff
4 Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved.
5
6 https://github.com/hebcal/hebcal
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 Danny Sadinoff can be reached at
23 danny@sadinoff.com
24
25 */
26
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "myerror.h"
33 #include "hebcal.h"
34 #include "common.h"
35 #include "danlib.h"
36
37 #define _(String) lookup_translation(String)
38
39 #define NM_LEN MAX_LINE_LEN
40
41 holstorep_t holidays[14][MAXDAYS], var_holidays[14][MAXDAYS];
42
43 #define IGNORE_YEAR 0
44
45
46 holinput_t inp_holidays[] =
47 {
48 {
49 {TISHREI, 2, IGNORE_YEAR},
50 "Rosh Hashana II",
51 YOM_TOV_ENDS,
52 NULL
53 },
54 {
55 {TISHREI, 9, IGNORE_YEAR},
56 "Erev Yom Kippur",
57 LIGHT_CANDLES,
58 NULL
59 },
60 {
61 {TISHREI, 10, IGNORE_YEAR},
62 "Yom Kippur",
63 YOM_TOV_ENDS,
64 NULL
65 },
66
67 {
68 {TISHREI, 14, IGNORE_YEAR},
69 "Erev Sukkot",
70 LIGHT_CANDLES,
71 NULL
72 },
73 {
74 {TISHREI, 15, IGNORE_YEAR},
75 "Sukkot I",
76 CHUL_ONLY|LIGHT_CANDLES_TZEIS,
77 NULL
78 },
79 {
80 {TISHREI, 15, IGNORE_YEAR},
81 "Sukkot I",
82 YOM_TOV_ENDS|IL_ONLY,
83 NULL
84 },
85 {
86 {TISHREI, 16, IGNORE_YEAR},
87 "Sukkot II",
88 YOM_TOV_ENDS|CHUL_ONLY,
89 NULL
90 },
91 {
92 {TISHREI, 16, IGNORE_YEAR},
93 "Sukkot II (CH''M)",
94 IL_ONLY,
95 NULL
96 },
97 {
98 {TISHREI, 17, IGNORE_YEAR},
99 "Sukkot III (CH''M)",
100 0,
101 NULL
102 },
103 {
104 {TISHREI, 18, IGNORE_YEAR},
105 "Sukkot IV (CH''M)",
106 0,
107 NULL
108 },
109 {
110 {TISHREI, 19, IGNORE_YEAR},
111 "Sukkot V (CH''M)",
112 0,
113 NULL
114 },
115 {
116 {TISHREI, 20, IGNORE_YEAR},
117 "Sukkot VI (CH''M)",
118 0,
119 NULL
120 },
121 {
122 {TISHREI, 21, IGNORE_YEAR},
123 "Sukkot VII (Hoshana Raba)",
124 LIGHT_CANDLES,
125 NULL
126 },
127 {
128 {TISHREI, 22, IGNORE_YEAR},
129 "Shmini Atzeret",
130 CHUL_ONLY|LIGHT_CANDLES_TZEIS,
131 NULL
132 },
133 {
134 {TISHREI, 22, IGNORE_YEAR},
135 "Shmini Atzeret",
136 IL_ONLY|YOM_TOV_ENDS,
137 NULL
138 },
139 {
140 {TISHREI, 23, IGNORE_YEAR},
141 "Simchat Torah",
142 CHUL_ONLY|YOM_TOV_ENDS,
143 NULL
144 },
145
146 {
147 {KISLEV, 24, IGNORE_YEAR},
148 "Chanukah: 1 Candle",
149 CHANUKAH_CANDLES,
150 NULL
151 },
152 {
153 {KISLEV, 25, IGNORE_YEAR},
154 "Chanukah: 2 Candles",
155 CHANUKAH_CANDLES,
156 NULL
157 },
158 {
159 {KISLEV, 26, IGNORE_YEAR},
160 "Chanukah: 3 Candles",
161 CHANUKAH_CANDLES,
162 NULL
163 },
164 {
165 {KISLEV, 27, IGNORE_YEAR},
166 "Chanukah: 4 Candles",
167 CHANUKAH_CANDLES,
168 NULL
169 },
170 {
171 {KISLEV, 28, IGNORE_YEAR},
172 "Chanukah: 5 Candles",
173 CHANUKAH_CANDLES,
174 NULL
175 },
176 {
177 {KISLEV, 29, IGNORE_YEAR},
178 "Chanukah: 6 Candles",
179 CHANUKAH_CANDLES,
180 NULL
181 },
182 {
183 {SHVAT, 15, IGNORE_YEAR},
184 "Tu BiShvat",
185 0,
186 NULL
187 },
188 {
189 {NISAN, 14, IGNORE_YEAR},
190 "Erev Pesach",
191 LIGHT_CANDLES,
192 NULL
193 },
194 {
195 {NISAN, 15, IGNORE_YEAR},
196 "Pesach I",
197 CHUL_ONLY|LIGHT_CANDLES_TZEIS,
198 NULL
199 },
200 {
201 {NISAN, 15, IGNORE_YEAR},
202 "Pesach I",
203 IL_ONLY|YOM_TOV_ENDS,
204 NULL
205 },
206 {
207 {NISAN, 16, IGNORE_YEAR},
208 "Pesach II",
209 CHUL_ONLY|YOM_TOV_ENDS,
210 NULL
211 },
212 {
213 {NISAN, 16, IGNORE_YEAR},
214 "Pesach II (CH''M)",
215 IL_ONLY,
216 NULL
217 },
218 {
219 {NISAN, 17, IGNORE_YEAR},
220 "Pesach III (CH''M)",
221 0,
222 NULL
223 },
224 {
225 {NISAN, 18, IGNORE_YEAR},
226 "Pesach IV (CH''M)",
227 0,
228 NULL
229 },
230
231 {
232 {NISAN, 19, IGNORE_YEAR},
233 "Pesach V (CH''M)",
234 0,
235 NULL
236 },
237 {
238 {NISAN, 20, IGNORE_YEAR},
239 "Pesach VI (CH''M)",
240 LIGHT_CANDLES,
241 NULL
242 },
243 {
244 {NISAN, 21, IGNORE_YEAR},
245 "Pesach VII",
246 CHUL_ONLY|LIGHT_CANDLES_TZEIS,
247 NULL
248 },
249 {
250 {NISAN, 21, IGNORE_YEAR},
251 "Pesach VII",
252 IL_ONLY|YOM_TOV_ENDS,
253 NULL
254 },
255 {
256 {NISAN, 22, IGNORE_YEAR},
257 "Pesach VIII",
258 CHUL_ONLY|YOM_TOV_ENDS,
259 NULL
260 },
261
262 {
263 {IYYAR, 14, IGNORE_YEAR},
264 "Pesach Sheni",
265 0,
266 NULL
267 },
268
269 {
270 {IYYAR, 18, IGNORE_YEAR},
271 "Lag BaOmer",
272 0,
273 NULL
274 },
275
276 {
277 {SIVAN, 5, IGNORE_YEAR},
278 "Erev Shavuot",
279 LIGHT_CANDLES,
280 NULL
281 },
282 {
283 {SIVAN, 6, IGNORE_YEAR},
284 "Shavuot I",
285 CHUL_ONLY|LIGHT_CANDLES_TZEIS,
286 NULL
287 },
288 {
289 {SIVAN, 6, IGNORE_YEAR},
290 "Shavuot I",
291 IL_ONLY|YOM_TOV_ENDS,
292 NULL
293 },
294 {
295 {SIVAN, 7, IGNORE_YEAR},
296 "Shavuot II",
297 CHUL_ONLY|YOM_TOV_ENDS,
298 NULL
299 },
300 {
301 {AV, 15, IGNORE_YEAR},
302 "Tu B'Av",
303 0,
304 NULL
305 },
306 {
307 {ELUL, 29, IGNORE_YEAR},
308 "Erev Rosh Hashana",
309 LIGHT_CANDLES,
310 NULL
311 }
312 };
313
314 #define HOLIDAY_ASARA_B_TEVET LANGUAGE2(var_hol_names[0].name)
315 #define HOLIDAY_CHANUKAH_7_CANDLES LANGUAGE2(var_hol_names[1].name)
316 #define HOLIDAY_CHANUKAH_8_CANDLES LANGUAGE2(var_hol_names[2].name)
317 #define HOLIDAY_CHANUKAH_8TH_DAY LANGUAGE2(var_hol_names[3].name)
318 #define HOLIDAY_PURIM LANGUAGE2(var_hol_names[4].name)
319 #define HOLIDAY_PURIM_KATAN LANGUAGE2(var_hol_names[5].name)
320 #define HOLIDAY_SHABBAT_HACHODESH LANGUAGE2(var_hol_names[6].name)
321 #define HOLIDAY_SHABBAT_HAGADOL LANGUAGE2(var_hol_names[7].name)
322 #define HOLIDAY_SHABBAT_CHAZON LANGUAGE2(var_hol_names[8].name)
323 #define HOLIDAY_SHABBAT_NACHAMU LANGUAGE2(var_hol_names[9].name)
324 #define HOLIDAY_SHABBAT_PARAH LANGUAGE2(var_hol_names[10].name)
325 #define HOLIDAY_SHABBAT_SHEKALIM LANGUAGE2(var_hol_names[11].name)
326 #define HOLIDAY_SHABBAT_SHUVA LANGUAGE2(var_hol_names[12].name)
327 #define HOLIDAY_SHABBAT_ZACHOR LANGUAGE2(var_hol_names[13].name)
328 #define HOLIDAY_SHUSHAN_PURIM LANGUAGE2(var_hol_names[14].name)
329 #define HOLIDAY_TA_ANIT_BECHOROT LANGUAGE2(var_hol_names[15].name)
330 #define HOLIDAY_TA_ANIT_ESTHER LANGUAGE2(var_hol_names[16].name)
331 #define HOLIDAY_TISH_A_B_AV LANGUAGE2(var_hol_names[17].name)
332 #define HOLIDAY_TZOM_GEDALIAH LANGUAGE2(var_hol_names[18].name)
333 #define HOLIDAY_TZOM_TAMMUZ LANGUAGE2(var_hol_names[19].name)
334 #define HOLIDAY_YOM_HAATZMA_UT LANGUAGE2(var_hol_names[20].name)
335 #define HOLIDAY_YOM_HASHOAH LANGUAGE2(var_hol_names[21].name)
336 #define HOLIDAY_YOM_HAZIKARON LANGUAGE2(var_hol_names[22].name)
337 #define HOLIDAY_YOM_YERUSHALAYIM LANGUAGE2(var_hol_names[23].name)
338 #define HOLIDAY_EREV_PURIM LANGUAGE2(var_hol_names[24].name)
339 #define HOLIDAY_EREV_TISH_A_B_AV LANGUAGE2(var_hol_names[25].name)
340 #define HOLIDAY_LEIL_SELICHOT LANGUAGE2(var_hol_names[26].name)
341 #define HOLIDAY_SIGD LANGUAGE2(var_hol_names[27].name)
342 #define HOLIDAY_YOM_HAALIYAH LANGUAGE2(var_hol_names[28].name)
343
344 struct variable_holiday_names {
345 const char *name;
346 } var_hol_names[] = {
347 {"Asara B'Tevet"},
348 {"Chanukah: 7 Candles"},
349 {"Chanukah: 8 Candles"},
350 {"Chanukah: 8th Day"},
351 {"Purim"},
352 {"Purim Katan"},
353 {"Shabbat HaChodesh"},
354 {"Shabbat HaGadol"},
355 {"Shabbat Chazon"},
356 {"Shabbat Nachamu"},
357 {"Shabbat Parah"},
358 {"Shabbat Shekalim"},
359 {"Shabbat Shuva"},
360 {"Shabbat Zachor"},
361 {"Shushan Purim"},
362 {"Ta'anit Bechorot"},
363 {"Ta'anit Esther"},
364 {"Tish'a B'Av"},
365 {"Tzom Gedaliah"},
366 {"Tzom Tammuz"},
367 {"Yom HaAtzma'ut"},
368 {"Yom HaShoah"},
369 {"Yom HaZikaron"},
370 {"Yom Yerushalayim"},
371 {"Erev Purim"},
372 {"Erev Tish'a B'Av"},
373 {"Leil Selichot"},
374 {"Sigd"},
375 {"Yom HaAliyah"},
376 };
377
378 /*-------------------------------------------------------------------------*/
379
getHolstorep(void)380 holstorep_t getHolstorep( void )
381 { /* return a pointer to a new holiday */
382 holstorep_t tmp;
383 if (!(tmp = (holstorep_t) malloc ((size_t) (sizeof (holstore_t)))))
384 die ("Unable to allocate memory for holiday.", "");
385 tmp->next = NULL;
386 tmp->name = NULL;
387 tmp->typeMask = 0;
388 return tmp;
389 }
390
391 /*-------------------------------------------------------------------------*/
392
393 /* pushes a copy of a holiday on to a holiday */
394 /* list, returning the typemask of the pushed element */
PushHoliday(holstorep_t hp,holstorep_t * lp)395 int PushHoliday(
396 holstorep_t hp, /* the holiday to be added */
397 holstorep_t *lp /* pointer to the list to be added to. */
398 )
399 {
400 holstorep_t temp;
401
402 temp = getHolstorep ();
403 initStr (&temp->name, MAX_LINE_LEN);
404 strcpy (temp->name, hp->name);
405 temp->typeMask = hp->typeMask;
406
407 if ( ! *lp ) /* if there are no holidays here yet, start a new bucket */
408 *lp = temp;
409 else
410 {
411 temp->next = *lp; /* put hp at the head of the list */
412 *lp = temp;
413 }
414 return temp->typeMask;
415 }
416
417 /*-------------------------------------------------------------------------*/
418
load_variable_holidays(int hYear)419 static void load_variable_holidays( int hYear )
420 {
421 date_t tempDt;
422 long int roshHashana, passover, tishaBav, tevet10;
423 holstorep_t tmpholp;
424
425 tempDt.yy = hYear;
426 tempDt.mm = TISHREI;
427 tempDt.dd = 1;
428 roshHashana = hebrew2abs (tempDt);
429
430 tempDt.yy = hYear;
431 tempDt.mm = TEVET;
432 tempDt.dd = 10;
433 tevet10 = hebrew2abs (tempDt);
434
435 tempDt.mm = NISAN;
436 tempDt.dd = 15;
437 passover = hebrew2abs (tempDt);
438
439 tempDt.mm = AV;
440 tempDt.dd = 9;
441 tishaBav = hebrew2abs (tempDt);
442
443 tmpholp = getHolstorep (); /* allocate hsnode */
444 tmpholp->name = HOLIDAY_TZOM_GEDALIAH;
445 PushHoliday (tmpholp, &var_holidays[TISHREI]
446 [roshHashana % 7L == THU ? 4 : 3]);
447
448 tmpholp = getHolstorep ();
449 tmpholp->name = HOLIDAY_SHABBAT_SHUVA;
450 tempDt = abs2hebrew (day_on_or_before (SAT, 7L + roshHashana));
451 PushHoliday (tmpholp, &var_holidays[TISHREI][tempDt.dd]);
452
453
454 /* printf( "hyear is %d\n",hYear); */
455 if (short_kislev (hYear))
456 {
457 tmpholp = getHolstorep ();
458 tmpholp->name = HOLIDAY_CHANUKAH_7_CANDLES;
459 tmpholp->typeMask = CHANUKAH_CANDLES;
460 PushHoliday (tmpholp, &var_holidays[TEVET][1]);
461 tmpholp = getHolstorep ();
462 tmpholp->name = HOLIDAY_CHANUKAH_8_CANDLES;
463 tmpholp->typeMask = CHANUKAH_CANDLES;
464 PushHoliday (tmpholp, &var_holidays[TEVET][2]);
465 tmpholp = getHolstorep ();
466 tmpholp->name = HOLIDAY_CHANUKAH_8TH_DAY;
467 PushHoliday (tmpholp, &var_holidays[TEVET][3]);
468 }
469 else
470 {
471 tmpholp = getHolstorep ();
472 tmpholp->name = HOLIDAY_CHANUKAH_7_CANDLES;
473 tmpholp->typeMask = CHANUKAH_CANDLES;
474 PushHoliday (tmpholp, &var_holidays[KISLEV][30]);
475 tmpholp = getHolstorep ();
476 tmpholp->name = HOLIDAY_CHANUKAH_8_CANDLES;
477 tmpholp->typeMask = CHANUKAH_CANDLES;
478 PushHoliday (tmpholp, &var_holidays[TEVET][1]);
479 tmpholp = getHolstorep ();
480 tmpholp->name = HOLIDAY_CHANUKAH_8TH_DAY;
481 PushHoliday (tmpholp, &var_holidays[TEVET][2]);
482 }
483
484 tmpholp = getHolstorep ();
485 tmpholp->name = HOLIDAY_SHABBAT_SHEKALIM;
486 tempDt = abs2hebrew (day_on_or_before (SAT, passover - 43L));
487 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
488
489 tmpholp = getHolstorep ();
490 tmpholp->name = HOLIDAY_SHABBAT_ZACHOR;
491 tempDt = abs2hebrew (day_on_or_before (SAT, passover - 30L));
492 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
493
494 tmpholp = getHolstorep ();
495 tmpholp->name = HOLIDAY_TA_ANIT_ESTHER;
496 tempDt = abs2hebrew (passover - (passover % 7L == TUE ? 33L : 31));
497 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
498
499 if (LEAP_YR_HEB (hYear))
500 {
501 tmpholp = getHolstorep ();
502 tmpholp->name = HOLIDAY_PURIM_KATAN;
503 PushHoliday (tmpholp, &var_holidays[ADAR_I][14]);
504
505 tmpholp = getHolstorep ();
506 tmpholp->name = HOLIDAY_EREV_PURIM;
507 PushHoliday (tmpholp, &var_holidays[ADAR_II][13]);
508
509 tmpholp = getHolstorep ();
510 tmpholp->name = HOLIDAY_PURIM;
511 PushHoliday (tmpholp, &var_holidays[ADAR_II][14]);
512 }
513 else
514 {
515 tmpholp = getHolstorep ();
516 tmpholp->name = HOLIDAY_EREV_PURIM;
517 PushHoliday (tmpholp, &var_holidays[ADAR_I][13]);
518
519 tmpholp = getHolstorep ();
520 tmpholp->name = HOLIDAY_PURIM;
521 PushHoliday (tmpholp, &var_holidays[ADAR_I][14]);
522 }
523
524 tmpholp = getHolstorep ();
525 tmpholp->name = HOLIDAY_SHUSHAN_PURIM;
526 tempDt = abs2hebrew (passover - (passover % 7L == SUN ? 28L : 29));
527 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
528
529 tmpholp = getHolstorep ();
530 tmpholp->name = HOLIDAY_SHABBAT_PARAH;
531 tempDt = abs2hebrew (day_on_or_before (SAT, passover - 14L) - 7L);
532 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
533
534 tmpholp = getHolstorep ();
535 tmpholp->name = HOLIDAY_SHABBAT_HACHODESH;
536 tempDt = abs2hebrew (day_on_or_before (SAT, passover - 14L));
537 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
538
539 tmpholp = getHolstorep ();
540 tmpholp->name = HOLIDAY_TA_ANIT_BECHOROT;
541 if ((passover - 1L) % 7L == SAT)
542 { /* if the fast falls on Shabbat, move to Thursday */
543 tempDt = abs2hebrew (day_on_or_before (THU, passover));
544 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
545 }
546 else
547 PushHoliday (tmpholp, &var_holidays[NISAN][14]);
548
549
550 tmpholp = getHolstorep ();
551 tmpholp->name = HOLIDAY_SHABBAT_HAGADOL;
552 tempDt = abs2hebrew (day_on_or_before (SAT, passover - 1L));
553 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
554
555 if (hYear >= 5711 && !suppressModern_sw)
556 { /* Yom HaShoah first observed in 1951 */
557 long int nisan27;
558 int nisan_day = 27;
559
560 tempDt.mm = NISAN;
561 tempDt.dd = 27;
562 nisan27 = hebrew2abs (tempDt);
563
564 /* When the actual date of Yom Hashoah falls on a Friday, the
565 * state of Israel observes Yom Hashoah on the preceding
566 * Thursday. When it falls on a Sunday, Yom Hashoah is observed
567 * on the following Monday.
568 * http://www.ushmm.org/remembrance/dor/calendar/
569 */
570 if (nisan27 % 7L == FRI)
571 nisan_day = 26;
572 else if (nisan27 % 7L == SUN)
573 nisan_day = 28;
574
575 tmpholp = getHolstorep ();
576 tmpholp->name = HOLIDAY_YOM_HASHOAH;
577 PushHoliday (tmpholp, &var_holidays[NISAN][nisan_day]);
578 }
579
580 if (hYear > 5708 && !suppressModern_sw)
581 { /* only really makes sense after 1948 */
582 tmpholp = getHolstorep ();
583 tmpholp->name = HOLIDAY_YOM_HAZIKARON;
584 if (passover % 7L == SUN)
585 tempDt.dd = 3;
586 else if (passover % 7L == SAT)
587 tempDt.dd = 4;
588 else if( hYear < 5764 )
589 tempDt.dd = 5;
590 else if( passover % 7L == TUE ) /* no Yom Hazikaron on motzei shabbat allowed after 5764*/
591 tempDt.dd = 6;
592 else
593 tempDt.dd = 5;
594 PushHoliday (tmpholp, &var_holidays[IYYAR][tempDt.dd - 1]);
595
596 tmpholp = getHolstorep ();
597 tmpholp->name = HOLIDAY_YOM_HAATZMA_UT;
598 PushHoliday (tmpholp, &var_holidays[IYYAR][tempDt.dd]);
599 }
600
601 if (hYear > 5727 && !suppressModern_sw)
602 { /* only really makes sense after 1967 */
603 tmpholp = getHolstorep ();
604 tmpholp->name = HOLIDAY_YOM_YERUSHALAYIM;
605 PushHoliday (tmpholp, &var_holidays[IYYAR][28]);
606 }
607
608 if (hYear >= 5769 && !suppressModern_sw) {
609 tmpholp = getHolstorep ();
610 tmpholp->name = HOLIDAY_SIGD;
611 PushHoliday (tmpholp, &var_holidays[CHESHVAN][29]);
612 }
613
614 if (hYear >= 5777 && !suppressModern_sw) {
615 tmpholp = getHolstorep ();
616 tmpholp->name = HOLIDAY_YOM_HAALIYAH;
617 PushHoliday (tmpholp, &var_holidays[CHESHVAN][7]);
618 }
619
620 tmpholp = getHolstorep ();
621 tmpholp->name = HOLIDAY_TZOM_TAMMUZ;
622 if (tishaBav % 7L == SAT)
623 tempDt = abs2hebrew (tishaBav - 20L);
624 else
625 tempDt = abs2hebrew (tishaBav - 21L);
626 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
627
628 tmpholp = getHolstorep ();
629 tmpholp->name = HOLIDAY_SHABBAT_CHAZON;
630 tempDt = abs2hebrew (day_on_or_before (SAT, tishaBav));
631 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
632
633 tmpholp = getHolstorep ();
634 tmpholp->name = HOLIDAY_EREV_TISH_A_B_AV;
635 PushHoliday (tmpholp, &var_holidays[AV]
636 [tishaBav % 7L == SAT ? 9 : 8]);
637
638 tmpholp = getHolstorep ();
639 tmpholp->name = HOLIDAY_TISH_A_B_AV;
640 PushHoliday (tmpholp, &var_holidays[AV]
641 [tishaBav % 7L == SAT ? 10 : 9]);
642
643 tmpholp = getHolstorep ();
644 tmpholp->name = HOLIDAY_SHABBAT_NACHAMU;
645 tempDt = abs2hebrew (day_on_or_before (SAT, tishaBav + 7L));
646 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
647
648 tmpholp = getHolstorep ();
649 tmpholp->name = HOLIDAY_ASARA_B_TEVET;
650 if (tevet10 % 7L == SAT)
651 PushHoliday (tmpholp, &var_holidays[TEVET][11]);
652 else
653 PushHoliday (tmpholp, &var_holidays[TEVET][10]);
654
655 tempDt.mm = TISHREI;
656 tempDt.dd = 1;
657 tempDt.yy = hYear + 1;
658 tmpholp = getHolstorep ();
659 tmpholp->name = HOLIDAY_LEIL_SELICHOT;
660 tempDt = abs2hebrew (day_on_or_before (SAT, hebrew2abs (tempDt) - 4L));
661 PushHoliday (tmpholp, &var_holidays[tempDt.mm][tempDt.dd]);
662 }
663
664
665 /*-------------------------------------------------------------------------*/
666 /* this function stores the user "holidays" drawn from inFile in the
667 var_holidays array. The intent is that it will be loaded every new
668 Jewish year. Gross, I know, but an efficient version will have to wait
669 until %ID% + .1
670 */
671
init_user_holidays(int hyear)672 void init_user_holidays( int hyear )
673 {
674 holstorep_t tmpholp;
675
676 char *s, *monthStr, *eventStr, nextChar;
677 int index, inMonth, inDay, lineNum = 1;
678
679 initStr (&s, MAX_LINE_LEN);
680 initStr (&monthStr, MAX_LINE_LEN);
681 rewind (inFile);
682 nextChar = (char) getc (inFile); /* priming getc */
683 for (; !feof (inFile);
684 lineNum++, nextChar = (char) getc (inFile))
685 { /* force an EOF */
686 ungetc (nextChar, inFile);
687 if (!fgets (s, MAX_LINE_LEN, inFile))
688 {
689 warn ("input file read error. Skipping line %s", hc_itoa (lineNum));
690 continue;
691 }
692 if (s[0] == '\n') /* blank line */
693 continue;
694 if (!sscanf (s, "%s %d%n", monthStr, &inDay, &index))
695 {
696 warn ("Error in input file. Skipping line %s", hc_itoa (lineNum));
697 continue;
698 }
699 if (isAllNums (monthStr))
700 {
701 warn ("Numeric hebrew month in input file. Skipping line %s",
702 hc_itoa (lineNum));
703 continue;
704 }
705 if (!(inMonth = lookup_hebrew_month (monthStr)))
706 {
707 warn ("Unrecognized hebrew month in input file. Skipping line %s",
708 hc_itoa (lineNum));
709 continue;
710 }
711 if (inDay < 1 || inDay > 30)
712 {
713 warn ("Date out of range in input file. Skipping line %s",
714 hc_itoa (lineNum));
715 continue;
716 }
717
718 if (inMonth == ADAR_II && !LEAP_YR_HEB (hyear))
719 inMonth = ADAR_I;
720
721 eventStr = s + index + 1; /* get the name of the event */
722 if (eventStr[strlen (eventStr) - 1] == '\n')
723 eventStr[strlen (eventStr) - 1] = '\0'; /* chop off the \n */
724
725 /* store the holiday in the LUT */
726 tmpholp = getHolstorep ();
727 initStr (&tmpholp->name, MAX_LINE_LEN);
728 strcpy (tmpholp->name, eventStr); /* load the user holiday into it. */
729 tmpholp->typeMask = USER_EVENT;
730 PushHoliday (tmpholp, &var_holidays[inMonth][inDay]);
731
732 }
733 }
734
735
736 /*-------------------------------------------------------------------------*/
737 /* this function stores yahrtzeits found in yFile.
738 each record is stored in mm dd yyyy str format using GREGORIAN dates
739 */
740
init_yahrtzeits(int hyear)741 void init_yahrtzeits( int hyear )
742 {
743 holstorep_t tmpholp;
744
745 char *s, *monthStr, *eventStr, nextChar;
746 int index, inMonth, inDay, inYear, lineNum = 1;
747 date_t hDeath, gDeath;
748
749 initStr (&s, MAX_LINE_LEN);
750 initStr (&monthStr, MAX_LINE_LEN);
751 rewind (yFile);
752 nextChar = (char) getc (yFile); /* priming getc */
753 for (; !feof (yFile);
754 lineNum++, nextChar = (char) getc (yFile))
755 { /* force an EOF */
756 ungetc (nextChar, yFile);
757 if (!fgets (s, MAX_LINE_LEN, yFile))
758 {
759 warn ("yahrtzeit file read error. Skipping line %s", hc_itoa (lineNum));
760 continue;
761 }
762 if (s[0] == '\n') /* blank line */
763 continue;
764 if (sscanf (s, "%s %d %d%n", monthStr, &inDay, &inYear, &index) < 3)
765 {
766 warn ("Error in yahrtzeit file. Skipping line %s", hc_itoa (lineNum));
767 continue;
768 }
769 if (!isAllNums (monthStr))
770 {
771 warn ("Non-numeric month in yahrtzeit file. Skipping line %s",
772 hc_itoa (lineNum));
773 continue;
774 }
775 sscanf (monthStr, "%d", &inMonth);
776
777 if (inMonth > 12 || inMonth < 1 ||
778 inDay < 1 || inDay > MonthLengths[LEAP (inYear)][inMonth])
779 {
780
781 warn ("Date out of range in yahrtzeit file. Skipping line %s",
782 hc_itoa (lineNum));
783 continue;
784 }
785
786 gDeath.dd = inDay;
787 gDeath.mm = inMonth;
788 gDeath.yy = inYear;
789
790 hDeath = abs2hebrew (greg2abs (gDeath));
791
792 /* If it's Heshvan 30 it depends on the first anniversary; if
793 that was not Heshvan 30, use the day before Kislev 1. */
794
795 if (hDeath.mm == CHESHVAN && hDeath.dd == 30 &&
796 !long_cheshvan (hDeath.yy + 1))
797 {
798 hDeath.dd = 1;
799 hDeath.mm = KISLEV;
800 hDeath.yy = hyear;
801 hDeath = abs2hebrew (hebrew2abs (hDeath) - 1L);
802 }
803 /* If it's Kislev 30 it depends on the first anniversary; if
804 that was not Kislev 30, use the day before Teveth 1. */
805 else if (hDeath.mm == KISLEV && hDeath.dd == 30 &&
806 short_kislev (hDeath.yy + 1))
807 {
808 hDeath.dd = 1;
809 hDeath.mm = TEVET;
810 hDeath.yy = hyear;
811 hDeath = abs2hebrew (hebrew2abs (hDeath) - 1L);
812 }
813 /* If it's Adar II, use the same day in last month of
814 year (Adar or Adar II). */
815 else if (hDeath.mm == ADAR_II)
816 {
817 hDeath.mm = MONTHS_IN_HEB (hyear);
818 }
819 /* If it's the 30th in Adar I and year is not a leap year
820 (so Adar has only 29 days), use the last day in Shevat. */
821 else if (hDeath.mm == ADAR_I && hDeath.dd == 30 &&
822 !LEAP_YR_HEB (hyear))
823 {
824 hDeath.dd = 30;
825 hDeath.mm = SHVAT;
826 }
827 /* In all other cases, use the normal anniversary of the date of death. */
828
829 /* advance day to rosh chodesh if needed */
830 if (hDeath.mm == CHESHVAN && hDeath.dd == 30
831 && !long_cheshvan(hyear)) {
832 hDeath.mm = KISLEV;
833 hDeath.dd = 1;
834 } else if (hDeath.mm == KISLEV && hDeath.dd == 30
835 && short_kislev(hyear)) {
836 hDeath.mm = TEVET;
837 hDeath.dd = 1;
838 }
839
840 eventStr = s + index + 1; /* get the name of the event */
841 /* if (eventStr[strlen(eventStr)-1] == '\n') */
842 eventStr[strlen (eventStr) - 1] = '\0'; /* chop off the \n */
843
844 /* store the holiday in the LUT */
845 tmpholp = getHolstorep ();
846 initStr (&tmpholp->name, MAX_LINE_LEN);
847 strcpy (tmpholp->name, eventStr); /* load the user holiday into it. */
848 tmpholp->typeMask = USER_EVENT;
849 PushHoliday (tmpholp, &var_holidays[hDeath.mm][hDeath.dd]);
850
851 }
852 }
853
854
855
856 /*-------------------------------------------------------------------------*/
857 /** set up the stored holidays array. */
init_holidays(int hYear)858 void init_holidays( int hYear )
859 /* NB that this is dependant on the hYear. */
860 /* It must therefore be called at the beginning of every hebrew year. */
861 {
862
863 int d, m;
864 holstorep_t tmpholp, tmpholp2;
865 holinputp_t todayinp;
866 static int first = 1;
867
868 if (first)
869 {
870 for (m = 0, todayinp = inp_holidays; /* load constant holidays */
871 m < LAST_INDEX (inp_holidays);
872 m++, todayinp++)
873 {
874 if (!(todayinp->typeMask & (IL_ONLY|CHUL_ONLY))
875 || ((todayinp->typeMask & IL_ONLY) && israel_sw)
876 || ((todayinp->typeMask & CHUL_ONLY) && !israel_sw)) {
877 tmpholp = getHolstorep (); /* allocate hsnode */
878 tmpholp->typeMask = todayinp->typeMask; /*load the new holiday */
879 tmpholp->name = LANGUAGE2(todayinp->name);
880 PushHoliday (tmpholp, &holidays[todayinp->date.mm][todayinp->date.dd]);
881 }
882 }
883 first = 0;
884 }
885 else
886 {
887 for (m = 0; m <= 13; m++) /* clear variable holidays buckets */
888 {
889 for (d = 0; d <= 30; d++)
890 {
891 tmpholp = var_holidays[m][d];
892 while (tmpholp != NULL)
893 {
894 tmpholp2 = tmpholp;
895 tmpholp = tmpholp->next;
896 free (tmpholp2);
897 }
898 var_holidays[m][d] = NULL;
899 }
900 }
901 }
902
903 load_variable_holidays (hYear);
904
905 if (inputFile_sw) /* get user-defined "holidays" */
906 init_user_holidays (hYear);
907 if (yahrtzeitFile_sw) /* get yahrtzeit dates */
908 init_yahrtzeits (hYear);
909 }
910
911
912
913 /*-------------------------------------------------------------------------*/
freeHolidays(holstorep_t * holiList)914 void freeHolidays( holstorep_t *holiList )
915 {
916 holstorep_t next;
917 holstorep_t cur = *holiList;
918 while( cur ) {
919 next = cur->next;
920 free (cur->name);
921 free (cur);
922 cur = next;
923 }
924
925 *holiList = NULL;
926 }
927 /*-------------------------------------------------------------------------*/
928
929 /* sets holiList to a linked list of holidadys for that date. */
930 /* the return value is the | of all the typeMasks of the holidays */
getHebHolidays(date_t dth,holstorep_t * holiList)931 int getHebHolidays( date_t dth, holstorep_t *holiList )
932 {
933 int tmpMask;
934 holstorep_t tmpholip, chp; /* current holiday pointer */
935
936 tmpMask = 0;
937 *holiList = NULL;
938
939 for (chp = holidays[dth.mm][dth.dd]; /* static holidays */
940 chp;
941 chp = chp->next)
942 {
943 tmpMask |= PushHoliday (chp, holiList);
944 }
945 for (chp = var_holidays[dth.mm][dth.dd]; /* variable holidays */
946 chp;
947 chp = chp->next)
948 {
949 tmpMask |= PushHoliday (chp, holiList);
950 }
951
952 if (dth.dd == 1)
953 {
954
955 if(dth.mm == TISHREI) /* special processing for rosh hashana */
956 {
957 tmpholip = getHolstorep ();
958 initStr (&tmpholip->name, NM_LEN);
959 sprintf (tmpholip->name, "%s %d",
960 _("Rosh Hashana"),
961 dth.yy);
962 tmpholip->typeMask = LIGHT_CANDLES_TZEIS;
963 PushHoliday (tmpholip, &var_holidays[TISHREI][1]);
964 tmpMask |= PushHoliday (tmpholip, holiList);
965 }
966 else
967 {
968 if( ! suppress_rosh_chodesh_sw ) /* rosh Chodesh Processing... */
969 {
970 tmpholip = getHolstorep();
971 initStr (&tmpholip->name, NM_LEN);
972 sprintf (tmpholip->name, _("Rosh Chodesh %s"),
973 LANGUAGE2(hMonths[LEAP_YR_HEB (dth.yy)][dth.mm].name));
974 tmpMask |= PushHoliday (tmpholip, holiList);
975 }
976 }
977 }
978
979
980 if (dth.dd == 30 && ! suppress_rosh_chodesh_sw)
981 {
982 tmpholip = getHolstorep ();
983 initStr (&tmpholip->name, NM_LEN);
984 sprintf (tmpholip->name, _("Rosh Chodesh %s"),
985 LANGUAGE2(hMonths[LEAP_YR_HEB (dth.yy)][dth.mm + 1].name));
986 tmpMask |= PushHoliday (tmpholip, holiList);
987 }
988
989
990 return tmpMask;
991 }
992