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