home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume39 / hebcal / part01 next >
Text File  |  1993-09-28  |  63KB  |  2,231 lines

  1. Newsgroups: comp.sources.misc,soc.culture.jewish
  2. From: sadinoff@unagi.cis.upenn.edu (Danny Sadinoff)
  3. Subject: v39i108:  hebcal - A Jewish calendar generator, v2.1, Part01/01
  4. Message-ID: <1993Sep28.125353.6997@sparky.sterling.com>
  5. X-Md4-Signature: 4dbb81a4e209c59989672edb5ed29909
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: University of Pennsylvania
  8. Date: Tue, 28 Sep 1993 12:53:53 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: sadinoff@unagi.cis.upenn.edu (Danny Sadinoff)
  12. Posting-number: Volume 39, Issue 108
  13. Archive-name: hebcal/part01
  14. Environment: UNIX
  15. Supersedes: hebcal: Volume 35, Issue 76
  16.  
  17.             [ THIS PROGRAM IS GUILTWARE  -Kent+ ]
  18.  
  19. Hebcal 2.1  - a program for printing Jewish calendars
  20.   by Danny Sadinoff
  21.  
  22. DESCRIPTION
  23. Hebcal is a program which prints out the days in the Jewish calendar
  24. for a given gregorian year.  Hebcal is fairly flexible in terms of which
  25. events in the Jewish calendar it displays.  Each of the following can
  26. be individualy turned on or off:
  27.  
  28.   The Hebrew date
  29.   Jewish Holdiays (including Yom Ha'atzmaut and Yom HaShoah etc.)
  30.   The weekly Sedrah
  31.   The day of the week
  32.   The days of the Omer
  33.  
  34. CHANGES 
  35. Since version 2.0:
  36.   Fixed some minor bugs: the date of purim katan and taanit bechorot.
  37.   Added -a Ashkenazis hebrew option.
  38.   Added -y 2 digit year option
  39.   Added -r Tab-delinated format option.
  40.  
  41.  
  42. DISTRIBUTION
  43. This program is GUILTWARE. 
  44. It may be distributed freely, with a few conditions:
  45.    1) The package must be distributed INTACT with ALL source code, as
  46.    well as this file.  You are welcome to modify the code,
  47.    but DON'T distribute it modified.  This section should certainly
  48.    appear with every distributed copy.
  49.    
  50.    2) If you are going to use this program, please drop me a line.
  51.    I'd like to know who you are, what version you're using, and how
  52.    you're using hebcal, and anything else you'd like to tell me, so
  53.    that I can adjust the program to meet users' needs.
  54.  
  55.    I am NOT demanding payment for the use of my program, but writing
  56.    this program DID take time.  Feel free to send $10 to
  57.    me at my US Mail address. (hint)
  58.  
  59.    send US Mail to:        send email to:
  60.     Danny Sadinoff       sadinoff@eniac.seas.upenn.edu
  61.     1 Cove La. 
  62.     Great Neck, NY 11024
  63.  
  64.    Email respondents will receive notifications of new versions as they
  65.    come out, as will US Mail responents (if they send me postage for a disk).
  66.  
  67.  
  68. COMPILATION
  69. The code has K&R "old style" declarations in it, so it should compile
  70. on most machines.
  71. The distribution includes a "Makefile" so once you've unpacked all the
  72. files, (including this one) just run the command "make" and that
  73. should compile everything for you.
  74.  
  75. The file hebcal.1 is the manual page.  For information on using man in
  76. conjunction with local manpages, see the manpage for man.  Briefly, to
  77. read a manpage, type 
  78. nroff -man <filename> | more
  79.  
  80.  
  81. DISCLAIMER
  82. I tried to make this program as accurate as possible.  However, I
  83. take no responsibility for any horrible consequences which may come
  84. about as a result of faulty output from this program.  This program
  85. should in no way be invested with halachic authority.
  86.  
  87. The secular dates before september 1752 are off by two weeks due to
  88. the correction that took place then.
  89.  
  90. The secular dates before 1522 become progressively meaningless, as I
  91. made no correction for the changeover from julian to gregorian
  92. calendars; but the Hebrew dates and years are correct.
  93.  
  94. COMING SOON
  95. Features to be included in future versions:
  96.   - The ability to specify and output a particular HEBREW year, month
  97.     or date. 
  98.   - hebrew output.
  99.  
  100. GRIPES
  101. send questions, comments or complaints to:
  102. Danny Sadinoff
  103. sadinoff@eniac.seas.upenn.edu
  104. --------------------------
  105. #! /bin/sh
  106. # This is a shell archive.  Remove anything before this line, then feed it
  107. # into a shell via "sh file" or similar.  To overwrite existing files,
  108. # type "sh file -c".
  109. # Contents:  README Makefile danlib.c danlib.h error.c error.h getopt.c
  110. #   getopt.h greg.c greg.h hebcal.1 hebcal.c hebcal.h proto.h start.c
  111. # Wrapped by kent@sparky on Tue Sep 28 07:40:04 1993
  112. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  113. echo If this archive is complete, you will see the following message:
  114. echo '          "shar: End of archive 1 (of 1)."'
  115. if test -f 'README' -a "${1}" != "-c" ; then 
  116.   echo shar: Will not clobber existing file \"'README'\"
  117. else
  118.   echo shar: Extracting \"'README'\" \(5984 characters\)
  119.   sed "s/^X//" >'README' <<'END_OF_FILE'
  120. XHebcal 2.1  - a program for printing Jewish calendars
  121. X  by Danny Sadinoff
  122. X
  123. XDESCRIPTION
  124. XHebcal is a program which prints out the days in the Jewish calendar
  125. Xfor a given gregorian year.  Hebcal is fairly flexible in terms of which
  126. Xevents in the Jewish calendar it displays.  Each of the following can
  127. Xbe individualy turned on or off:
  128. X
  129. X  The Hebrew date
  130. X  Jewish Holdiays (including Yom Ha'atzmaut and Yom HaShoah etc.)
  131. X  The weekly Sedrah
  132. X  The day of the week
  133. X  The days of the Omer
  134. X
  135. XCHANGES 
  136. XSince version 2.0:
  137. X  Fixed some minor bugs: the date of purim katan and taanit bechorot.
  138. X  Added -a Ashkenazis hebrew option.
  139. X  Added -y 2 digit year option
  140. X  Added -r Tab-delinated format option.
  141. X
  142. XSince version 1.4:
  143. X  Optimized code, with an eye towards the -t and -T switches
  144. X  Added -i user events option.
  145. X  Added -S "what's this week's sedra?" option
  146. X
  147. XSince version 1.3:
  148. X  This is a quickie fix of the new Chanukah routine added in the last release
  149. X  I also changed the suffix of the manpage from .l to .1, since it was
  150. X     causing some versions of make to compile the manpage as a lex
  151. X     file, destroying the source code in the process.
  152. X  Added Yom Yerushalayim 
  153. X   changed output format from "24 of Kislev" to "24th of Kislev"
  154. X
  155. XSince version 1.2:
  156. X  Fixed a critical bug which put Purim on the 15th of Adar, instead of
  157. X    the 14th
  158. X  Now uses sys/types.h instead of stdlib.h
  159. X  Added the rest of the 8 days of Chanukah
  160. X  Added -e European output switch.
  161. X
  162. XSince version 1.1, the following changes were made:
  163. X  Changed usage-- the -p "parshiot" switch was changed to "-s" sedrot switch
  164. X  Fixed certain slippery variable type bugs
  165. X  Changed code to K&R old style
  166. X  Added Manpage
  167. X  Decided to change the "Distribu-Ware" to a normal shareware.
  168. X
  169. XDISTRIBUTION
  170. XThis program is GUILTWARE. 
  171. XIt may be distributed freely, with a few conditions:
  172. X   1) The package must be distributed INTACT with ALL source code, as
  173. X   well as this file.  You are welcome to modify the code,
  174. X   but DON'T distribute it modified.  This section should certainly
  175. X   appear with every distributed copy.
  176. X   
  177. X   2) If you are going to use this program, please drop me a line.
  178. X   I'd like to know who you are, what version you're using, and how
  179. X   you're using hebcal, and anything else you'd like to tell me, so
  180. X   that I can adjust the program to meet users' needs.
  181. X
  182. X   I am NOT demanding payment for the use of my program, but writing
  183. X   this program DID take time.  Feel free to send $10 to
  184. X   me at my US Mail address. (hint)
  185. X
  186. X   send US Mail to:        send email to:
  187. X    Danny Sadinoff       sadinoff@eniac.seas.upenn.edu
  188. X    1 Cove La. 
  189. X    Great Neck, NY 11024
  190. X
  191. X   Email respondents will receive notifications of new versions as they
  192. X   come out, as will US Mail responents (if they send me postage for a disk).
  193. X
  194. XCOMPILATION
  195. XThe code has K&R "old style" declarations in it, so it should compile
  196. Xon most machines.
  197. XThe distribution includes a "Makefile" so once you've unpacked all the
  198. Xfiles, (including this one) just run the command "make" and that
  199. Xshould compile everything for you.
  200. X
  201. XThe file hebcal.1 is the manual page.  For information on using man in
  202. Xconjunction with local manpages, see the manpage for man.  Briefly, to
  203. Xread a manpage, type 
  204. Xnroff -man <filename> | more
  205. X
  206. X
  207. XOPERATION:
  208. XThe operation of hebcal is fairly simple.  Hebcal defaults to printing
  209. Xout the holidays for the current gregorian year.  With the
  210. Xcommand-line options, a specific gregorian year, month or date can be
  211. Xspecified.  
  212. X
  213. XGiven one numeric argument, hebcal will print out the calendar 
  214. Xfor that year.  Given two numeric argumetnts mm yyyy, it
  215. Xprints out the calendar for month mm of year yyyy.  Given three
  216. Xnumeric arguments mm dd yyyy, it will print out the hebrew calendar
  217. Xentries for day dd of month mm of year yyyy.  In the last case, the -d
  218. Xoption is automatically enabled.
  219. X
  220. XNOTE 
  221. XBe sure to give the whole year to hebcal.  
  222. Xhebcal 92 will return the calendar for a time somewhere in the Roman 
  223. Xera, not in the twentieth century.  Use hebcal 1992 instead.
  224. X
  225. Xusage: hebcal [-adehorsStTwy] [-i filename] [[month [day]] year]  
  226. X       hebcal help --- prints this message. 
  227. X
  228. XOPTIONS:  
  229. X   -a : Ashkenazis Hebrew
  230. X   -d : add hebrew dates
  231. X   -e : use European dates (dd mm yyyy) for OUTPUT ONLY (input format
  232. X        the same)
  233. X   -h : suppress holidays
  234. X   -i : draw user-defined calendar events from the specified file
  235. X   -o : add days of the omer
  236. X   -r : use tab-delinated format
  237. X   -s : add weekly sedrot on Saturdays
  238. X   -S : add sedra of the week every day
  239. X   -t : only output today's date.  This switch implies the -d switch.
  240. X   -T : only output today's date, suppressing gregorian date. This
  241. X        switch implies the -d and -o switches.
  242. X   -w : add day of the week
  243. X   -y : use two-digit year
  244. X
  245. X
  246. XExamples: 
  247. Xexample% hebcal -ho
  248. X4/19/1992 1st day of the Omer
  249. X4/20/1992 2nd day of the Omer
  250. X4/21/1992 3rd day of the Omer
  251. X4/22/1992 4th day of the Omer
  252. X4/23/1992 5th day of the Omer
  253. X4/24/1992 6th day of the Omer
  254. X.
  255. X.
  256. X6/5/1992 48th day of the Omer
  257. X6/6/1992 49th day of the Omer
  258. X
  259. Xto find out what's happening in today's Jewish calendar, use
  260. Xexample% hebcal -ToS
  261. X19 of Nisan, 5752
  262. XPesach V (CH"M)
  263. X4th day of the Omer
  264. X
  265. X
  266. XDISCLAIMER
  267. XI tried to make this program as accurate as possible.  However, I
  268. Xtake no responsibility for any horrible consequences which may come
  269. Xabout as a result of faulty output from this program.  This program
  270. Xshould in no way be invested with halachic authority.
  271. X
  272. XThe secular dates before september 1752 are off by two weeks due to
  273. Xthe correction that took place then.
  274. X
  275. XThe secular dates before 1522 become progressively meaningless, as I
  276. Xmade no correction for the changeover from julian to gregorian
  277. Xcalendars; but the Hebrew dates and years are correct.
  278. X
  279. XCOMING SOON
  280. XFeatures to be included in future versions:
  281. X  - The ability to specify and output a particular HEBREW year, month
  282. X    or date. 
  283. X  - hebrew output.
  284. X
  285. XGRIPES
  286. Xsend questions, comments or complaints to:
  287. XDanny Sadinoff
  288. Xsadinoff@eniac.seas.upenn.edu
  289. END_OF_FILE
  290.   if test 5984 -ne `wc -c <'README'`; then
  291.     echo shar: \"'README'\" unpacked with wrong size!
  292.   fi
  293.   # end of 'README'
  294. fi
  295. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  296.   echo shar: Will not clobber existing file \"'Makefile'\"
  297. else
  298.   echo shar: Extracting \"'Makefile'\" \(126 characters\)
  299.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  300. XCFLAGS = -O
  301. XCC = cc
  302. XOBJ= start.o hebcal.o greg.o error.o danlib.o getopt.o
  303. Xhebcal:  $(OBJ)
  304. X     $(CC) $(OBJ) -o hebcal $(CFLAGS)
  305. END_OF_FILE
  306.   if test 126 -ne `wc -c <'Makefile'`; then
  307.     echo shar: \"'Makefile'\" unpacked with wrong size!
  308.   fi
  309.   # end of 'Makefile'
  310. fi
  311. if test -f 'danlib.c' -a "${1}" != "-c" ; then 
  312.   echo shar: Will not clobber existing file \"'danlib.c'\"
  313. else
  314.   echo shar: Extracting \"'danlib.c'\" \(1285 characters\)
  315.   sed "s/^X//" >'danlib.c' <<'END_OF_FILE'
  316. X#include <stdio.h>
  317. X#include <sys/types.h>
  318. X#include <ctype.h>
  319. X#include "danlib.h"
  320. X#include "error.h"
  321. X
  322. X/* Some generally useful routines */
  323. X  
  324. Xvoid initStr(s,size)
  325. Xchar **s;
  326. Xint size;
  327. X{
  328. X  /* allocate space for a string */
  329. X  if ((*s = (char *)malloc((size_t) (size + 1) * sizeof(char))) == NULL)
  330. X    die("\n Memory Error: Couldn't allocate string\n","");
  331. X
  332. X  **s = '\0';
  333. X}
  334. X
  335. Xint isAllNums(s)
  336. Xchar * s;
  337. X{
  338. X/* returns true if a string contains only digits, dashes and newlines */
  339. X  int n = 0, len = strlen(s);
  340. X  
  341. X  for(n=0;
  342. X      (n < len)  &&  ( isdigit(s[n]) || (s[n] == '-') || (s[n] == '\n'));
  343. X      n++);
  344. X  return (n == len);
  345. X}
  346. X
  347. Xchar * numSuffix(i)
  348. Xint i;
  349. X{
  350. X/* returns he proper ordinal suffix of a number */
  351. X  if ((i / 10) == 1) return "th";
  352. X  switch (i % 10) {
  353. X  case 1 : return "st";
  354. X  case 2 : return "nd";
  355. X  case 3 : return "rd";
  356. X  default: return "th";
  357. X  }
  358. X}
  359. X
  360. Xchar * itoa (i) 
  361. Xint i;
  362. X{
  363. X  static char ret[7];
  364. X  int c = 0;
  365. X  char tmp;
  366. X
  367. X  if (i < 0) {            /* is i negative? */
  368. X    ret[c++] = '-';        /* then put a minus */
  369. X    i = abs(i);
  370. X  }
  371. X  
  372. X  while (i >0) {        /* compose the number */
  373. X    ret[c++] = (i % 10) + '0';
  374. X    i /= 10;
  375. X  }
  376. X  i = c-1;
  377. X  
  378. X  for (c =0; c < i; c++) {    /* reverse the number */
  379. X    tmp = ret[c];
  380. X    ret[c] = ret[i-c];
  381. X    ret[i-c] = tmp;
  382. X  } 
  383. X
  384. X  return ret;
  385. X}
  386. X
  387. END_OF_FILE
  388.   if test 1285 -ne `wc -c <'danlib.c'`; then
  389.     echo shar: \"'danlib.c'\" unpacked with wrong size!
  390.   fi
  391.   # end of 'danlib.c'
  392. fi
  393. if test -f 'danlib.h' -a "${1}" != "-c" ; then 
  394.   echo shar: Will not clobber existing file \"'danlib.h'\"
  395. else
  396.   echo shar: Extracting \"'danlib.h'\" \(187 characters\)
  397.   sed "s/^X//" >'danlib.h' <<'END_OF_FILE'
  398. X#ifndef __DANLIB__
  399. X#define __DANLIB
  400. X
  401. X#define CHAR2NUM(x) ((x) - '0')
  402. X#define LAST_INDEX(x) (sizeof x / sizeof x[0])
  403. X
  404. Xint isAllNums();
  405. Xvoid initStr();
  406. Xchar * numSuffix(), *itoa();
  407. X
  408. X#endif
  409. END_OF_FILE
  410.   if test 187 -ne `wc -c <'danlib.h'`; then
  411.     echo shar: \"'danlib.h'\" unpacked with wrong size!
  412.   fi
  413.   # end of 'danlib.h'
  414. fi
  415. if test -f 'error.c' -a "${1}" != "-c" ; then 
  416.   echo shar: Will not clobber existing file \"'error.c'\"
  417. else
  418.   echo shar: Extracting \"'error.c'\" \(589 characters\)
  419.   sed "s/^X//" >'error.c' <<'END_OF_FILE'
  420. X#include "error.h"
  421. X
  422. Xextern int errno, sys_nerr;
  423. Xextern char *sys_errlist[], *progname;
  424. X
  425. Xvoid die (s1,s2)    /* print error message and die */
  426. Xchar *s1, *s2;
  427. X{
  428. X  if (progname)
  429. X    fprintf(stderr, "%s: ", progname);
  430. X  fprintf(stderr, s1, s2);
  431. X  if (errno > 0 && errno < sys_nerr)
  432. X    fprintf(stderr, " (%s)\n", sys_errlist[errno]);
  433. X  exit(1);
  434. X}
  435. X
  436. Xvoid warn (s1,s2) /* print error message but don't die */
  437. Xchar *s1, *s2;
  438. X{
  439. X  if (progname)
  440. X    fprintf(stderr, "%s: ", progname);
  441. X  fprintf(stderr, s1, s2);
  442. X  if (errno > 0 && errno < sys_nerr)
  443. X    fprintf(stderr, " (%s)\n", sys_errlist[errno]);
  444. X}
  445. END_OF_FILE
  446.   if test 589 -ne `wc -c <'error.c'`; then
  447.     echo shar: \"'error.c'\" unpacked with wrong size!
  448.   fi
  449.   # end of 'error.c'
  450. fi
  451. if test -f 'error.h' -a "${1}" != "-c" ; then 
  452.   echo shar: Will not clobber existing file \"'error.h'\"
  453. else
  454.   echo shar: Extracting \"'error.h'\" \(102 characters\)
  455.   sed "s/^X//" >'error.h' <<'END_OF_FILE'
  456. X#ifndef __ERROR__
  457. X#define __ERROR__
  458. X#include <stdio.h>
  459. X#include <errno.h>
  460. X
  461. Xvoid die(), warn();
  462. X#endif
  463. END_OF_FILE
  464.   if test 102 -ne `wc -c <'error.h'`; then
  465.     echo shar: \"'error.h'\" unpacked with wrong size!
  466.   fi
  467.   # end of 'error.h'
  468. fi
  469. if test -f 'getopt.c' -a "${1}" != "-c" ; then 
  470.   echo shar: Will not clobber existing file \"'getopt.c'\"
  471. else
  472.   echo shar: Extracting \"'getopt.c'\" \(1927 characters\)
  473.   sed "s/^X//" >'getopt.c' <<'END_OF_FILE'
  474. X/* optarg - parse command-line arguments */
  475. X/* Author: AT&T */
  476. X
  477. X#include <stdio.h>
  478. X
  479. X#define ERR(S, C) if(opterr){\
  480. X    char errbuf[3];\
  481. X    errbuf[0] = C; errbuf[1] = '\n'; errbuf[2] = '\0';\
  482. X    fprintf(stderr,"%s", argv[0]);\
  483. X    fprintf(stderr, "%s", S);\
  484. X    fprintf(stderr, "%s", errbuf);}
  485. X
  486. Xextern int strcmp();
  487. Xextern char *strchr();
  488. Xextern int strlen();
  489. X
  490. Xint    opterr = 1;        /* getopt prints errors if this is on */
  491. Xint    optind = 1;        /* token pointer */
  492. Xint    optopt;            /* option character passed back to user */
  493. Xchar    *optarg;        /* flag argument (or value) */
  494. X
  495. Xint    /* return option character, EOF if no more or ? if problem */
  496. Xgetopt(argc, argv, opts)
  497. Xint    argc;
  498. Xchar    **argv;
  499. Xchar    *opts;                /* option string */
  500. X{
  501. X    static int sp = 1;        /* character index in current token */
  502. X    register char *cp;        /* pointer into current token */
  503. X
  504. X    if(sp == 1)
  505. X        /* check for more flag-like tokens */
  506. X        if(optind >= argc ||
  507. X           argv[optind][0] != '-' || argv[optind][1] == '\0')
  508. X            return(EOF);
  509. X        else if(strcmp(argv[optind], "--") == 0) {
  510. X            optind++;
  511. X            return(EOF);
  512. X        }
  513. X    optopt = argv[optind][sp];
  514. X    if(optopt == ':' || (cp=strchr(opts, optopt)) == 0) {
  515. X        ERR(": illegal option -- ", optopt);
  516. X        /* if no chars left in this token, move to next token */
  517. X        if(argv[optind][++sp] == '\0') {
  518. X            optind++;
  519. X            sp = 1;
  520. X        }
  521. X        return('?');
  522. X    }
  523. X
  524. X    if(*++cp == ':') {    /* if a value is expected, get it */
  525. X        if(argv[optind][sp+1] != '\0')
  526. X            /* flag value is rest of current token */
  527. X            optarg = &argv[optind++][sp+1];
  528. X        else if(++optind >= argc) {
  529. X            ERR(": option requires an argument -- ", optopt);
  530. X            sp = 1;
  531. X            return('?');
  532. X        } else
  533. X            /* flag value is next token */
  534. X            optarg = argv[optind++];
  535. X        sp = 1;
  536. X    } else {
  537. X        /* set up to look at next char in token, next time */
  538. X        if(argv[optind][++sp] == '\0') {
  539. X            /* no more in current token, so setup next token */
  540. X            sp = 1;
  541. X            optind++;
  542. X        }
  543. X        optarg = 0;
  544. X    }
  545. X    return(optopt);/* return the current flag character found */
  546. X}
  547. END_OF_FILE
  548.   if test 1927 -ne `wc -c <'getopt.c'`; then
  549.     echo shar: \"'getopt.c'\" unpacked with wrong size!
  550.   fi
  551.   # end of 'getopt.c'
  552. fi
  553. if test -f 'getopt.h' -a "${1}" != "-c" ; then 
  554.   echo shar: Will not clobber existing file \"'getopt.h'\"
  555. else
  556.   echo shar: Extracting \"'getopt.h'\" \(336 characters\)
  557.   sed "s/^X//" >'getopt.h' <<'END_OF_FILE'
  558. X#ifndef GETOPT_H
  559. X#define GETOPT_H
  560. X#include "proto.h"                /* define PROTO */
  561. X
  562. Xint getopt PROTO((int, char **, char *));
  563. Xextern char *optarg;                /* current argv string */
  564. Xextern int optind;                /* current argv index */
  565. Xextern int optopt;                /* option character */
  566. Xextern int opterr;                /* getopt prints errors if 1 */
  567. X#endif /* GETOPT_H */
  568. END_OF_FILE
  569.   if test 336 -ne `wc -c <'getopt.h'`; then
  570.     echo shar: \"'getopt.h'\" unpacked with wrong size!
  571.   fi
  572.   # end of 'getopt.h'
  573. fi
  574. if test -f 'greg.c' -a "${1}" != "-c" ; then 
  575.   echo shar: Will not clobber existing file \"'greg.c'\"
  576. else
  577.   echo shar: Extracting \"'greg.c'\" \(2697 characters\)
  578.   sed "s/^X//" >'greg.c' <<'END_OF_FILE'
  579. X#include "greg.h"
  580. X
  581. X/* greg.c gregorian calendar module for hebrew calendar program
  582. X   By Danny Sadinoff
  583. X   (C) 1992
  584. X
  585. X*/
  586. X
  587. Xchar * eMonths[] = { 
  588. X  "January","February","March","April","May","June","July",
  589. X  "August","September","October","November","December"
  590. X  };
  591. X              
  592. Xint MonthLengths[][12] ={ 
  593. X  {31,28,31,30,31,30,31,31,30,31,30,31},
  594. X  {31,29,31,30,31,30,31,31,30,31,30,31}
  595. X};
  596. X
  597. Xchar * DayNames[] = {
  598. X  "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"
  599. X  };
  600. X
  601. Xchar * ShortDayNames[] = {
  602. X  "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
  603. X  };
  604. X
  605. Xstatic void checkRange (dt,routine)
  606. Xdate_t dt;
  607. Xchar * routine;
  608. X{
  609. X  if ((dt.mm > 13)||(dt.dd > 31) || (dt.yy > 7000) || 
  610. X      (dt.mm <0)  ||(dt.dd <0  ) || (dt.yy < -7000))
  611. X    die("Date out of range from routine %s.",routine);
  612. X}
  613. X
  614. Xstatic long int daysSinceOrigin (dt)
  615. Xdate_t dt;
  616. X{
  617. X  int m,y;
  618. X  long int days = 0L;
  619. X
  620. X  checkRange(dt,"daysSinceOrigin");
  621. X
  622. X  for (y =1; y < dt.yy; y++)
  623. X    days += DAYS_IN(y);
  624. X  y = dt.yy;
  625. X  for (m= JAN; m < dt.mm; m++)
  626. X    days += MonthLengths[LEAP(y)][m];
  627. X  days += dt.dd -1;
  628. X  return days;
  629. X}
  630. X
  631. Xint diffDays(d1,d2)
  632. Xdate_t d1, d2;
  633. X{
  634. X  return (int) (daysSinceOrigin(d1) - daysSinceOrigin(d2));
  635. X}
  636. X
  637. Xint exceeds (d1,d2)
  638. Xdate_t d1, d2;
  639. X{
  640. X  if (d1.yy > d2.yy)
  641. X    return 1;
  642. X  else if (d1.yy < d2.yy)
  643. X    return 0;
  644. X  else if (d1.mm > d2.mm)
  645. X    return 1;
  646. X  else if (d1.mm < d2.mm)
  647. X    return 0;
  648. X  else if (d1.dd > d2.dd)
  649. X    return 1;
  650. X  else return 0;
  651. X}
  652. X
  653. Xvoid decDate (dt,n) /* decrements dt by n days */
  654. Xdate_t *dt;
  655. Xint n;
  656. X{
  657. X/*under construction*/
  658. X/*  while (n > 365) {
  659. X    n -= DAYS_IN(dt->yy -1);
  660. X    dt ->yy--;
  661. X  }
  662. X
  663. X
  664. X  if ((dt->mm == FEB) && (dt->dd == 29) && !LEAP(dt->yy))
  665. X    dt->dd--;
  666. X*/
  667. X  
  668. X  while (n--) 
  669. X    if (dt->dd ==1) {
  670. X      if (dt->mm == JAN) {
  671. X    dt->yy--;
  672. X    dt->mm = DEC;
  673. X    dt->dd = 31;
  674. X      }
  675. X      else {
  676. X    dt->mm--;
  677. X    dt->dd = MonthLengths[LEAP(dt->yy)][dt->mm];
  678. X      }
  679. X    }
  680. X    else dt->dd--;
  681. X}
  682. X
  683. Xvoid incDate (dt,n)   /* increments dt by n days */
  684. Xdate_t *dt;
  685. Xint n;
  686. X{
  687. X/*  while (n > 365) {
  688. X    n -= DAYS_IN(dt->yy);
  689. X    dt->yy++;
  690. X  }
  691. X
  692. X  if ((dt->mm == FEB) && (dt->dd == 29) && !LEAP(dt->yy) ) {
  693. X    dt-> mm = MAR;
  694. X    dt-> dd = 1;
  695. X  }
  696. X*/
  697. X  while (n--) 
  698. X   if ((dt->dd + 1) > MonthLengths[LEAP(dt->yy)][dt->mm]) 
  699. X     if (dt->mm == DEC) {
  700. X       dt->yy++;
  701. X       dt->mm = JAN;
  702. X       dt->dd = 1;
  703. X     }
  704. X     else {
  705. X       dt->mm++;
  706. X       dt->dd =1;
  707. X     }
  708. X   else 
  709. X     dt->dd ++;
  710. X}
  711. X
  712. Xint dayOfWeek(d1)  /* sunday = 0 */
  713. Xdate_t d1;
  714. X{
  715. X  return (int) ((daysSinceOrigin(d1) + 1) % 7 ) ;
  716. X}
  717. X
  718. Xvoid setDate (d) 
  719. Xdate_t *d;
  720. X{
  721. X  time_t secs;
  722. X  struct tm *loctm;
  723. X
  724. X  secs = time(NULL);
  725. X  loctm = localtime(&secs);
  726. X  d->yy = 1900 + loctm->tm_year;
  727. X  d->mm = loctm->tm_mon;
  728. X  d->dd = loctm->tm_mday;
  729. X}
  730. X
  731. X
  732. END_OF_FILE
  733.   if test 2697 -ne `wc -c <'greg.c'`; then
  734.     echo shar: \"'greg.c'\" unpacked with wrong size!
  735.   fi
  736.   # end of 'greg.c'
  737. fi
  738. if test -f 'greg.h' -a "${1}" != "-c" ; then 
  739.   echo shar: Will not clobber existing file \"'greg.h'\"
  740. else
  741.   echo shar: Extracting \"'greg.h'\" \(875 characters\)
  742.   sed "s/^X//" >'greg.h' <<'END_OF_FILE'
  743. X#ifndef __GREG__
  744. X#define __GREG__
  745. X
  746. X#include <stdio.h>
  747. X#include <sys/types.h>
  748. X#include <time.h>
  749. X#include "error.h"
  750. X
  751. X#define LEAP(x) (!((x) % 4) && ( ((x) % 100) || !((x) % 400)))
  752. X#define DAYS_IN(x) (LEAP((x))?366:365)
  753. X
  754. X#define JAN 0
  755. X#define FEB 1
  756. X#define MAR 2
  757. X#define APR 3
  758. X#define MAY 4
  759. X#define JUN 5
  760. X#define JUL 6
  761. X#define AUG 7
  762. X#define SEP 8
  763. X#define OCT 9
  764. X#define NOV 10
  765. X#define DEC 11
  766. X
  767. X#define SUN 0
  768. X#define MON 1
  769. X#define TUE 2
  770. X#define WED 3
  771. X#define THU 4
  772. X#define FRI 5
  773. X#define SAT 6
  774. X
  775. Xextern char * eMonths[];
  776. Xextern int MonthLengths[][12] ;
  777. Xextern char * DayNames[] ;
  778. Xextern char * ShortDayNames[];
  779. Xextern char * eDays[] ;
  780. X
  781. Xtypedef struct {
  782. X  int mm;    /* months since january 0,11*/
  783. X  int dd;    /* day of month 1,31 */
  784. X  int yy;    /* years since year 1 BCE i.e. -1 = 2 BCE */
  785. X  } date_t;
  786. X
  787. Xint diffDays(), exceeds(), dayOfWeek();
  788. Xvoid decDate (), incDate(), setDate();
  789. X
  790. X#endif
  791. END_OF_FILE
  792.   if test 875 -ne `wc -c <'greg.h'`; then
  793.     echo shar: \"'greg.h'\" unpacked with wrong size!
  794.   fi
  795.   # end of 'greg.h'
  796. fi
  797. if test -f 'hebcal.1' -a "${1}" != "-c" ; then 
  798.   echo shar: Will not clobber existing file \"'hebcal.1'\"
  799. else
  800.   echo shar: Extracting \"'hebcal.1'\" \(4969 characters\)
  801.   sed "s/^X//" >'hebcal.1' <<'END_OF_FILE'
  802. X.TH HEBCAL 1 "Hebcal Version 2.1" "Danny Sadinoff"
  803. X.SH NAME
  804. Xhebcal - a Jewish calendar generator
  805. X.SH SYNOPSIS
  806. X.B hebcal
  807. X[ 
  808. X\-adehorsStTwy
  809. X] [ 
  810. X\-i
  811. X.I file
  812. X] [[
  813. X.I month
  814. X[
  815. X.I day
  816. X]]
  817. X.I year
  818. X]
  819. X.br
  820. X.B hebcal help
  821. X.SH DESCRIPTION
  822. XWith no arguments, 
  823. X.B hebcal
  824. Xwill print to stdout the 
  825. Xdates of the Jewish holidays in the current
  826. Xsecular year.  Each line is prefixed with a gregorian date of the form
  827. Xmm/dd/yyyy.  
  828. X.sp
  829. XBy specifying 
  830. X.I month,
  831. X.I day,
  832. Xor 
  833. X.I year 
  834. Xoutput can be limited to a particular month or date
  835. Xin a particular year.  
  836. X.sp
  837. X.I year
  838. Xis an integer (it can be negative).  So 92 is during the Roman period,
  839. Xnot the late twentieth century.
  840. X.sp
  841. X.I month
  842. Xis a number from 1..12.
  843. X.sp
  844. X.I day 
  845. Xis a number from 1..31.
  846. X.sp
  847. XFor example, the command
  848. X.nf
  849. X
  850. X    hebcal 10 1992
  851. X
  852. X.fi
  853. Xwill print out the holidays occurring in October of 1992.
  854. X.PP
  855. XNOTE:  hebcal 92 is 
  856. X.I not
  857. Xthe same as hebcal 1992.  The year is assumed to be complete, so the
  858. Xformer calendar preceeds the latter by nineteen centuries.
  859. X.PP
  860. XA few other bells and whistles include the weekly 
  861. X.I sedra
  862. Xas well as the day of the week, the count of the 
  863. X.I omer,
  864. Xand the Hebrew date.
  865. X.PP
  866. XOutput from hebcal can be used to drive calendar(1).  
  867. XDay\-to\-day use for hebcal is provided for in the 
  868. X.B -T
  869. X and 
  870. X.B -t
  871. Xswitches, which print out Jewish calendar entries for the current date.
  872. X.PP
  873. X.SH OPTIONS
  874. X.TP 1.0i
  875. X.B "  -a"
  876. XUse Ashkenazis hebrew.
  877. X.TP
  878. X.B "  -d"
  879. XAdd the Hebrew date to the output.
  880. X.TP
  881. X.B "  -e"
  882. XChange the output format to European\-style dates: dd.mm.yyyy
  883. X.TP
  884. X.B "  -h"
  885. XSuppress holidays in output.  User defined calendar events are
  886. Xunaffected by this switch.
  887. X.TP
  888. X.B "  -i "
  889. XRead extra events from specified file.  These events are printed
  890. Xregardless of the 
  891. X.B -h 
  892. Xsuppress holidays switch.
  893. X.br
  894. XThere is one holiday per line in 
  895. X.I file,
  896. Xeach with the format
  897. X.br
  898. X.I month day description
  899. X.br
  900. Xwhere 
  901. X.I month 
  902. Xis a number from 1 to 12,
  903. X.I day
  904. Xis a number from 1 to 30, and 
  905. X.I description
  906. Xis a newline-terminated string describing the holiday.
  907. X.br
  908. XHere is the list of Hebrew months and their code numbers:
  909. X.br
  910. X1    Tishrei
  911. X.br
  912. X2    Cheshvan
  913. X.br
  914. X3    Kislev
  915. X.br
  916. X4    Tevet
  917. X.br
  918. X5    Shvat
  919. X.br
  920. X6    Adar (Adar II on leap years)
  921. X.br
  922. X6a    Adar (Adar I on leap years)
  923. X.br
  924. X6b    same as 6
  925. X.br
  926. X7    Nisan
  927. X.br
  928. X8    Iyyar
  929. X.br
  930. X9    Sivan
  931. X.br
  932. X10    Tamuz
  933. X.br
  934. X11    Av
  935. X.br
  936. X12    Elul
  937. X.br 
  938. XPlease note the special option associated with Adar.  If a person died
  939. Xin Adar of a non-leap year, the 
  940. X.I yahrtzeit
  941. Xlands in Adar II of a leap year, so the event gets the 6b (or 6) month
  942. Xcode.  Only people who died on leap years in Adar II should have their
  943. X.I yahrtzeits
  944. Xon 6a.  The same rule applies for Jewish birthdays (this is used when
  945. Xcalculating 
  946. X.I bar-mitzvah 
  947. Xor 
  948. X.I bat-mitzvah 
  949. Xdates).
  950. X.TP
  951. X.B "  -o"
  952. XAdd the count of the 
  953. X.I omer
  954. Xto the output.
  955. X.TP
  956. X.B "  -r"
  957. XUse a tab-delineated format
  958. X.TP
  959. X.B "  -s"
  960. XAdd the weekly 
  961. X.I sedra 
  962. Xto the output on Saturdays.
  963. X.TP
  964. X.B "  -S"
  965. XAdd the weekly 
  966. X.I sedra 
  967. Xto the output every day.
  968. X.TP
  969. X.B "  -t"
  970. XPrint calendar information for today's date only.  -d is
  971. Xasserted with this option. 
  972. X.TP
  973. X.B "  -T"
  974. XSame as -t, only without the gregorian date.  This option is useful in
  975. Xlogin scripts, just to see what's happening today in the Jewish calendar.
  976. X.TP
  977. X.B "  -w"
  978. XAdd the day of the week to the output.
  979. X.TP
  980. X.B "  -y"
  981. XPrint only the last two digits of the year.
  982. X.SH EXAMPLES
  983. X.LP
  984. XTo find the days of the 
  985. X.I omer 
  986. Xin 1997, printing the days of the week:
  987. X.RS
  988. X.nf
  989. X.ft B
  990. Xexample% hebcal -how 1997
  991. X.br
  992. X4/23/97 Wed, 1st day of the Omer
  993. X.br
  994. X4/24/97 Thu, 2nd day of the Omer
  995. X.br
  996. X4/25/97 Fri, 3rd day of the Omer
  997. X.br
  998. X .
  999. X.br
  1000. X .
  1001. X.br
  1002. X .
  1003. X.br
  1004. X6/9/97 Mon, 48th day of the Omer
  1005. X.br
  1006. X6/10/97 Tue, 49th day of the Omer
  1007. X.RE
  1008. X.LP
  1009. XTo just print the weekly 
  1010. X.I sedrot
  1011. Xof December 2000
  1012. X.RS
  1013. X.nf
  1014. X.ft B
  1015. Xexample% hebcal -hp 12 2000
  1016. X.br
  1017. X12/2/00 Parshat Toldot
  1018. X.br
  1019. X12/9/00 Parshat Vayetzei
  1020. X.br
  1021. X12/16/00 Parshat Vayishlach
  1022. X.br
  1023. X12/23/00 Parshat Vayeshev
  1024. X.br
  1025. X12/30/00 Parshat Miketz
  1026. X.br
  1027. X.RE
  1028. X.LP 
  1029. XTo find out what's happening in the Jewish calendar today , use
  1030. X.RS
  1031. X.nf
  1032. X.ft B
  1033. Xexample% hebcal -ToS
  1034. X.br
  1035. X19 of Nisan, 5752
  1036. X.br
  1037. XParshat Achrei Mot
  1038. X.br
  1039. XPesach V (CH"M)
  1040. X.br
  1041. X4th day of the Omer
  1042. X.br
  1043. X.RE
  1044. X.SH AUTHOR
  1045. XDanny Sadinoff, University of Pennsylvania
  1046. X.SH SEE ALSO
  1047. Xcalendar(1), hcal(1), hdate(1), omer(1), rise(1)
  1048. X.sp
  1049. XThe motivation for the algorithms in this program is the
  1050. X.I "Tur Shulchan Aruch.  "
  1051. XA well written treatment of the Jewish calendar is given in 
  1052. X.I Understanding the Jewish Calendar
  1053. Xby Rabbi Nathan Bushwick.  A more complete bibliography on the topic
  1054. Xcan be found there.
  1055. X.SH DISCLAIMER
  1056. XThis is just a program I wrote one summer.  It should not be invested
  1057. Xwith any sort of halachic authority.
  1058. X.SH BUGS
  1059. XHebrew dates are only valid before sundown on that secular date
  1060. X.sp
  1061. XHebcal performs no checking for changes between the julian and
  1062. Xgregorian calendar, so secular dates before 1752 are untrustworthy.
  1063. X.sp 
  1064. XHebcal cannot currently handle date computations before 2 C.E.  sorry.
  1065. X.SH BUG REPORTS TO
  1066. XDanny Sadinoff
  1067. X.br
  1068. Xsadinoff@eniac.seas.upenn.edu
  1069. END_OF_FILE
  1070.   if test 4969 -ne `wc -c <'hebcal.1'`; then
  1071.     echo shar: \"'hebcal.1'\" unpacked with wrong size!
  1072.   fi
  1073.   # end of 'hebcal.1'
  1074. fi
  1075. if test -f 'hebcal.c' -a "${1}" != "-c" ; then 
  1076.   echo shar: Will not clobber existing file \"'hebcal.c'\"
  1077. else
  1078.   echo shar: Extracting \"'hebcal.c'\" \(24526 characters\)
  1079.   sed "s/^X//" >'hebcal.c' <<'END_OF_FILE'
  1080. X#include "hebcal.h"
  1081. X#include "danlib.h"
  1082. X#include <string.h>
  1083. X  
  1084. X  
  1085. X  /* hebcal.c main module for hebrew calendar program
  1086. X     By Danny Sadinoff
  1087. X     (C) 1993
  1088. X     
  1089. X     $Date: 93/09/26 16:26:59 $
  1090. X     $Revision: 2.1 $
  1091. X     
  1092. X     */ 
  1093. X  
  1094. X  int ashkenazis_sw, sedrot_sw, hebDates_sw, euroDates_sw, specMonth_sw,
  1095. X  specDay_sw, inputFile_sw, weekday_sw, suppressHolidays_sw,
  1096. X  suppressGreg_sw, printOmer_sw, sedraAllWeek_sw, yearDigits_sw,
  1097. X  tabs_sw, omer;
  1098. X
  1099. XFILE *inFile;
  1100. X
  1101. Xholstorep_t holidays[13][MAXDAYS],union_Adar[MAXDAYS];
  1102. X
  1103. Xyear_t legend[2][8] = {
  1104. X  {                             /* stam years */
  1105. X    {"1BX",353,29,29,1,1,1,1,0,1,1},    /* BX */
  1106. X    {"1BS",355,30,30,1,1,1,1,1,1,1},    /* BS */
  1107. X    {"2GC",354,29,30,1,1,1,1,1,1,1},    /* GC */
  1108. X    {"4HC",354,29,30,1,1,1,1,0,1,0},    /* HC */ 
  1109. X    {"0error - HX",354,29,29,1,1,1,1,0,1,0},    /* error! hx */
  1110. X    {"4HS",355,30,30,0,1,1,1,0,1,0},    /* HS */
  1111. X    {"6ZX",353,29,29,1,1,1,1,0,1,0},    /* ZX */
  1112. X    {"6ZS",355,30,30,1,1,1,1,0,1,1},    /* ZS */
  1113. X  },
  1114. X  {                             /* leap years */
  1115. X    {"1BX",383,29,29,0,0,0,0,1,1,1},    /* BX */
  1116. X    {"1BS",385,30,30,0,0,0,0,0,1,0},    /* BS */
  1117. X    {"2GC",384,29,30,0,0,0,0,0,1,0},    /* GC */
  1118. X    {"0error - HC",383,29,30,0,0,0,0,0,0,0},    /* error ! hc */
  1119. X    {"4HX",383,29,29,0,0,0,0,0,0,0},    /* HX */
  1120. X    {"4HS",385,30,30,0,0,0,0,0,0,1},    /* HS */
  1121. X    {"6ZX",383,29,29,0,0,0,0,0,1,1},    /* ZX */
  1122. X    {"6ZS",385,30,30,0,0,0,0,1,1,1},    /* ZS */
  1123. X  }
  1124. X};
  1125. X
  1126. Xint leapYears[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
  1127. X/*enum {BX,BS,GC,HC,HX,HS,ZX,ZS}; */
  1128. X#define BX 0
  1129. X#define BS 1
  1130. X#define GC 2
  1131. X#define HC 3
  1132. X#define HX 4
  1133. X#define HS 5
  1134. X#define ZX 6
  1135. X#define ZS 7
  1136. X
  1137. Xint luach[][19] = 
  1138. X{
  1139. X  {HC,BX,HS,HC,BS,ZX,HC,BS,BX,HS,GC,BS,ZX,GC,BS,ZS,HX,GC,ZS},
  1140. X  {ZS,HC,BX,ZS,HC,BX,ZS,HS,HC,BX,HS,HC,BS,ZX,HC,BS,ZX,HS,GC},
  1141. X  {BS,ZX,GC,BS,ZS,HX,GC,ZS,ZS,HC,BX,ZS,HC,BS,BX,HC,BS,BS,ZX},
  1142. X  {HC,HS,ZX,HC,HS,ZS,ZX,GC,BS,ZS,HX,GC,ZS,HS,HC,BX,HS,HC,BX},
  1143. X  {ZS,HC,BS,BX,HC,BS,BS,ZX,HC,BS,ZX,HS,GC,ZS,ZS,HC,BX,ZS,HX},
  1144. X  {GC,ZS,HS,HC,BX,HS,HC,BX,ZS,HC,BS,BX,HS,GC,BS,ZX,GC,BS,ZS},
  1145. X  {ZX,GC,ZS,ZS,HC,BX,ZS,HX,GC,ZS,HS,HC,BX,HS,HC,BS,ZX,HC,BS},
  1146. X  {BS,ZX,GC,BS,ZS,HX,GC,ZS,ZX,GC,ZS,ZS,HC,BX,ZS,HC,BS,BX,HS},
  1147. X  {HC,BS,ZX,HC,BS,ZX,HS,GC,BS,ZX,GC,BS,ZS,HX,GC,ZS,HS,HC,BX},
  1148. X  {ZS,HC,BX,ZS,HC,BS,BX,HS,HC,BS,ZX,HC,BS,ZX,HS,GC,ZS,ZX,GC},
  1149. X  {BS,ZS,HX,GC,ZS,HS,HC,BX,ZS,HC,BX,ZS,HC,BS,BX,HS,GC,BS,ZX}, /* 10,11 GX? */
  1150. X  {HC,BS,ZS,ZX,GC,ZS,ZS,HX,GC,ZS,HX,GC,ZS,HS,HC,BX,HS,HC,BS},
  1151. X  {BX,HC,BS,BS,ZX,GC,BS,ZX,HS,GC,ZS,ZS,HC,BX,ZS,HC,BX,ZS,HS}
  1152. X};
  1153. X
  1154. Xstruct {
  1155. X  char * name;
  1156. X  int length;
  1157. X}hMonths[][14] = {
  1158. X  {  
  1159. X    {"Tishrei",30}, {"Cheshvan",29}, {"Kislev",30},
  1160. X    {"Tevet",29}, {"Sh'vat",30}, {"Adar",29},
  1161. X    {"Nisan",30}, {"Iyyar",29}, {"Sivan",30},
  1162. X    {"Tamuz",29}, {"Av",30},{"Elul",29},{"Tishrei",30}},
  1163. X  {
  1164. X    {"Tishrei",30}, {"Cheshvan",29}, {"Kislev",30},
  1165. X    {"Tevet",29}, {"Sh'vat",30}, {"Adar I",29}, {"Adar II",30},
  1166. X    {"Nisan",30}, {"Iyyar",29}, {"Sivan",30},
  1167. X    {"Tamuz",29}, {"Av",30},{"Elul",29},{"Tishrei",30}}    
  1168. X};
  1169. X
  1170. X#define TISHREI 0
  1171. X#define CHESHVAN 1
  1172. X#define KISLEV 2
  1173. X#define ADAR_2 6
  1174. X
  1175. X#define LANGUAGE(str) (ashkenazis_sw && (str)[1] ? ((str)[1]) : ((str)[0]))
  1176. X
  1177. Xchar * sedrot[][2] = {
  1178. X  {"Bereshit","Bereshis"},
  1179. X  {"Noach","Noach"}, {"Lech-Lecha","Lech-Lecha"},
  1180. X  {"Vayera","Vayera"},{"Chayei Sara","Chayei Sara"},
  1181. X  {"Toldot","Toldos"}, {"Vayetzei","Vayetzei"},
  1182. X  {"Vayishlach","Vayishlach"}, {"Vayeshev","Vayeshev"},
  1183. X  {"Miketz","Miketz"}, {"Vayigash","Vayigash"},
  1184. X  {"Vayechi","Vayechi"},
  1185. X  
  1186. X  {"Shemot","Shemos"}, {"Vaera","Vaera"}, {"Bo","Bo"},
  1187. X  {"Beshalach","Beshalach"}, {"Yitro","Yisro"},
  1188. X  {"Mishpatim","Mishpatim"},{"Terumah","Terumah"},
  1189. X  {"Tetzaveh","Tetzaveh"}, {"Ki Tisa","Ki Sisa"},
  1190. X  {"Vayakhel","Vayakhel"}, {"Pekudei","Pekudei"},
  1191. X  
  1192. X  {"Vayikra","Vayikra"}, {"Tzav","Tzav"},
  1193. X  {"Shmini","Shmini"}, {"Tazria","Sazria"},
  1194. X  {"Metzora","Metzora"}, {"Achrei Mot","Achrei Mos"},
  1195. X  {"Kedoshim","Kedoshim"}, {"Emor","Emor"},
  1196. X  {"Behar","Behar"}, {"Bechukotai","Bechukosai"},
  1197. X  
  1198. X  {"Bamidbar","Bamidbar"}, {"Nasso","Nasso"}, {"Beha'alotcha","Beha'aloscha"},
  1199. X  {"Sh'lach","Sh'lach"}, {"Korach","Korach"}, {"Chukat","Chukas"},
  1200. X  {"Balak","Balak"}, {"Pinchas","Pinchas"}, {"Matot","Matos"},
  1201. X  {"Masei","Masei"},
  1202. X  
  1203. X  {"Devarim","Devarim"}, {"Vaetchanan","Vaeschanan"},
  1204. X  {"Eikev","Eikev"},{"Re'eh","Re'eh"},
  1205. X  {"Shoftim","Shoftim"},{"Ki Teitzei","Ki Seitzei"},
  1206. X  {"Ki Tavo","Ki Savo"}, {"Nitzavim","Nitzavim"},
  1207. X  {"Vayeilech","Vayeilech"},{"Ha'Azinu","Ha'Azinu"},
  1208. X  {"V'Zot Habracha","V'Zos Habracha"}
  1209. X};
  1210. X
  1211. X#define VAYAKHEL 21
  1212. X#define TAZRIA 26
  1213. X#define ACHREI 28
  1214. X#define BEHAR 31
  1215. X#define CHUKAT 38
  1216. X#define MATOT 41
  1217. X#define NITZAVIM 50
  1218. X
  1219. X#define NM_LEN 60
  1220. X
  1221. X#define OWNSEDRA 1
  1222. X#define NIDCHE 2
  1223. X#define MUKDAM 4
  1224. X#define MUKDAM2 8
  1225. X#define SKIP_NORMAL_ADAR 16
  1226. X#define USER_EVENT 32
  1227. X
  1228. Xholinput_t inp_holidays[] = {   /* 5 = Adar I */
  1229. X  /* 6 = Adar = Adar II */
  1230. X  {{0,1},{"Rosh Hashana I"},OWNSEDRA},{{0,2},{"Rosh Hashana II"},OWNSEDRA},
  1231. X  {{0,3},{"Tzom Gedalia"},NIDCHE},
  1232. X  {{0,9},{"Erev Yom Kippur"}},
  1233. X  {{0,10},{"Yom Kippur"},OWNSEDRA},
  1234. X  
  1235. X  {{0,15},{"Sukkot I","Sukkos I"},OWNSEDRA},
  1236. X  {{0,16},{"Sukkot II","Sukkos II"},OWNSEDRA},
  1237. X  {{0,17},{"Sukkot III (CH''M)","Sukkos III (CH''M)"},OWNSEDRA},
  1238. X  {{0,18},{"Sukkot IV (CH''M)","Sukkos IV (CH''M)"},OWNSEDRA},
  1239. X  {{0,19},{"Sukkot V (CH''M)","Sukkos V (CH''M)"},OWNSEDRA},
  1240. X  {{0,20},{"Sukkot VI (CH''M)","Sukkos VI (CH''M)"},OWNSEDRA},
  1241. X  {{0,21},{"Sukkot VII (Hoshana Raba)","Sukkos VII (Hoshana Raba)"},OWNSEDRA},
  1242. X  {{0,22},{"Shmini Atzeret","Shmini Atzeres"},OWNSEDRA},
  1243. X  {{0,23},{"Simchat Torah","Simchas Torah"},OWNSEDRA},
  1244. X  
  1245. X  {{2,25},{"Chanukah I"}},
  1246. X  {{2,26},{"Chanukah II"}},{{2,27},{"Chanukah III"}},{{2,28},{"Chanukah IV"}},
  1247. X  
  1248. X  {{3,10},{"Asara B'Tevet"},NIDCHE},
  1249. X  
  1250. X  {{4,15},{"Tu B'Shvat"}},
  1251. X  
  1252. X  {{5,14},{"Purim katan"},SKIP_NORMAL_ADAR},
  1253. X  
  1254. X  {{6,13},{"Ta'anit Esther","Ta'anis Esther"},MUKDAM},
  1255. X  {{6,14},{"Purim"}},
  1256. X  {{6,15},{"Shushan Purim"}},
  1257. X  
  1258. X  {{7,14},{"Erev Pesach"}},
  1259. X  {{7,14},{"Ta'anit Bechorot","Ta'anis Bechorot"},MUKDAM},
  1260. X  {{7,15},{"Pesach I"},OWNSEDRA},
  1261. X  {{7,16},{"Pesach II"},OWNSEDRA},
  1262. X  {{7,17},{"Pesach III (CH''M)"},OWNSEDRA},
  1263. X  {{7,18},{"Pesach IV (CH''M)"},OWNSEDRA},
  1264. X  {{7,19},{"Pesach V (CH''M)"},OWNSEDRA},
  1265. X  {{7,20},{"Pesach VI (CH''M)"},OWNSEDRA},
  1266. X  {{7,21},{"Pesach VII"},OWNSEDRA},
  1267. X  {{7,22},{"Pesach VIII"},OWNSEDRA},
  1268. X  {{7,27},{"Yom HaShoah"}},
  1269. X  
  1270. X  {{8,4},{"Yom HaZikaron"},MUKDAM2},
  1271. X  {{8,5},{"Yom Ha'atzmaut"},MUKDAM},
  1272. X  {{8,28},{"Yom Yerushalayim"},MUKDAM},  /* not certain about mukdam status  of the yoms */
  1273. X  
  1274. X  {{9,6},{"Shavuot I","Shavuos I"},OWNSEDRA},
  1275. X  {{9,7},{"Shavuot II","Shavuos II"},OWNSEDRA},
  1276. X  
  1277. X  {{10,17},{"Shiva Assar B'Tamuz"},NIDCHE},
  1278. X  
  1279. X  {{11,9},{"Tish'a B'Av"},NIDCHE},
  1280. X  
  1281. X  {{12,29},{"Erev Rosh Hashana"}}
  1282. X};
  1283. X
  1284. Xholstore_t chanukah_arr[5] =
  1285. X{
  1286. X  {""},
  1287. X  {"Chanukah V"},
  1288. X  {"Chanukah VI"}, 
  1289. X  {"Chanukah VII"},
  1290. X  {"Chanukah VIII"}
  1291. X};
  1292. X
  1293. X#define SIMCHAT_DAY 23
  1294. X#define LEAP_YR_HEB(x) (leapYears[((x) -1) % 19])
  1295. X#define MONTHS_IN_HEB(x) (LEAP_YR_HEB(x) ? 13 :12)
  1296. X
  1297. Xyear_t yearData(yr)
  1298. X     int yr;
  1299. X{
  1300. X  return legend[LEAP_YR_HEB(yr)][luach[((yr-1)/19+7)%13][(yr-1) %19]];
  1301. X}
  1302. X
  1303. Xint daysInHebMonth(month, year) 
  1304. X     int month, year;
  1305. X{
  1306. X  year_t theYear;
  1307. X  
  1308. X  theYear = yearData(year);
  1309. X  if (month == CHESHVAN) 
  1310. X    return theYear.daysInCheshvan;
  1311. X  else if (month == KISLEV)
  1312. X    return theYear.daysInKislev;
  1313. X  else return hMonths[LEAP_YR_HEB(year)][month].length;
  1314. X}
  1315. X
  1316. Xdate_t nextHebDate (dth) 
  1317. X     date_t dth;
  1318. X{
  1319. X  dth.dd++;
  1320. X  if (dth.dd > daysInHebMonth(dth.mm,dth.yy))
  1321. X    if (dth.mm ==  MONTHS_IN_HEB(dth.yy)-1)
  1322. X      {
  1323. X        dth.yy++;
  1324. X        dth.mm =0;
  1325. X        dth.dd =1;
  1326. X      }
  1327. X    else 
  1328. X      {
  1329. X        dth.mm++;
  1330. X        dth.dd =1;
  1331. X      }
  1332. X  return dth;
  1333. X}
  1334. X
  1335. Xdate_t prevHebDate (dth) 
  1336. X     date_t dth;
  1337. X{
  1338. X  dth.dd--;
  1339. X  if (dth.dd == 0)
  1340. X    if (dth.mm == 0)
  1341. X      {
  1342. X        dth.yy--;
  1343. X        dth.mm = MONTHS_IN_HEB(dth.yy) -1 ;
  1344. X        dth.dd = daysInHebMonth(dth.mm,dth.yy);
  1345. X      }
  1346. X    else 
  1347. X      {
  1348. X        dth.mm--;
  1349. X        dth.dd = daysInHebMonth(dth.mm,dth.yy);
  1350. X      }
  1351. X  return dth;
  1352. X}
  1353. X
  1354. Xholstorep_t getHolstorep (s)    /* return a pointer to a new */
  1355. X     char *s;                               /* holiday */
  1356. X{
  1357. X  holstorep_t tmp;
  1358. X  if (!(tmp = (holstorep_t)malloc ( (size_t) sizeof (holstore_t))))
  1359. X    die("Unable to allocate memory for holiday. Called from %s",s);
  1360. X  tmp->next = NULL;
  1361. X  tmp->name = NULL;
  1362. X  tmp->typeMask = 0;
  1363. X  return tmp;
  1364. X}
  1365. X
  1366. X
  1367. Xint PushHoliday (hp,lp) /*pushes a copy of a holiday on to a holiday list */
  1368. X     holstorep_t 
  1369. X       hp,                      /* the holiday to be added */
  1370. X       *lp;                     /* pointer to the list to be added to.*/
  1371. X{
  1372. X  holstorep_t temp;
  1373. X  
  1374. X  temp = getHolstorep("PushHoliday");
  1375. X  initStr(&temp->name,MAX_LINE_LEN);
  1376. X  strcpy(temp->name,hp->name);
  1377. X  temp->typeMask = hp->typeMask;
  1378. X  
  1379. X  if (!*lp)
  1380. X    /* if there are no holidays here yet, start a new bucket*/
  1381. X    *lp = temp; 
  1382. X  else 
  1383. X    {
  1384. X      temp->next = *lp;         /* put hp at the head of the list */
  1385. X      *lp = temp;
  1386. X    }
  1387. X  return temp->typeMask;
  1388. X}
  1389. X
  1390. X
  1391. Xvoid InitHolidays(roshDt)       /* set up the stored holidays array */
  1392. X     date_t roshDt;
  1393. X{
  1394. X  
  1395. X  int d,m;
  1396. X  holstorep_t tmpholp;
  1397. X  holinputp_t todayinp;
  1398. X  
  1399. X  for (m = 0; m<= 12; m++)      /* clear holidays buckets */
  1400. X    for (d = 0; d < MAXDAYS; d++)
  1401. X      holidays[m][d] = NULL;
  1402. X  
  1403. X  for (m = 0,todayinp = inp_holidays; /* load holiday buckets */
  1404. X       m < LAST_INDEX(inp_holidays); 
  1405. X       m++, todayinp++)
  1406. X    {
  1407. X      tmpholp = getHolstorep("InitHolidays");      /* allocate hsnode*/
  1408. X      tmpholp->typeMask = todayinp->typeMask;      /* load the new holiday into it. */
  1409. X      tmpholp->name = LANGUAGE(todayinp->name);
  1410. X      PushHoliday(tmpholp,&holidays[todayinp->date.mm][todayinp->date.dd]);
  1411. X      if ((todayinp->date.mm == 5 || todayinp->date.mm == 6) && 
  1412. X          !(tmpholp->typeMask & SKIP_NORMAL_ADAR))
  1413. X        PushHoliday(tmpholp,&union_Adar[todayinp->date.dd]);
  1414. X    }
  1415. X  
  1416. X  if (inputFile_sw)             /* get user-defined "holidays" */
  1417. X    {
  1418. X      char *s,*monthStr,*adarp,*eventStr,nextChar;
  1419. X      int index,hYear,inMonth,inDay,lineNum = 1;
  1420. X      
  1421. X      
  1422. X      hYear = JUL2HEB(roshDt.yy)+1;
  1423. X      initStr(&s,MAX_LINE_LEN);
  1424. X      initStr(&monthStr,MAX_LINE_LEN);
  1425. X      nextChar = (char) getc(inFile); /* priming getc */
  1426. X      while (!feof(inFile))
  1427. X        {
  1428. X          ungetc(nextChar,inFile); 
  1429. X          if (!fgets(s,MAX_LINE_LEN,inFile))
  1430. X            die ("input file read error at line number %s.\n",itoa(lineNum));
  1431. X          
  1432. X          if (!sscanf(s,"%s %d%n",monthStr,&inDay,&index))
  1433. X            die ("Error in input file at line %s\n",itoa(lineNum));
  1434. X          
  1435. X          if (isAllNums(monthStr) && (inMonth = atoi(monthStr)) < 6)
  1436. X            inMonth--;
  1437. X          else if (adarp = strchr(monthStr,'a'))
  1438. X            {
  1439. X              *adarp = '\0';    /* terminate the string at the 'a' */
  1440. X              if (isAllNums(monthStr))
  1441. X                inMonth = atoi(monthStr)-1;
  1442. X              else die ("Error in input file at line %s\n",itoa(lineNum));
  1443. X            }
  1444. X          else if (adarp = strchr(monthStr,'b'))
  1445. X            {   /* this case puts the event in month 6 = Adar II*/
  1446. X              *adarp = '\0';    
  1447. X              if (isAllNums(monthStr))
  1448. X                inMonth = atoi(monthStr); /* note no decrement */
  1449. X              else die ("Error in input file at line %s\n",itoa(lineNum));
  1450. X            }
  1451. X          
  1452. X          if (inMonth >12 || inMonth <0)
  1453. X            die ("Month out of range in input file at line %s\n",itoa(lineNum));
  1454. X          
  1455. X          if(inDay <0 || inDay >30)
  1456. X            die ("Date out of range in input file at line %s\n",itoa(lineNum));
  1457. X          
  1458. X#if 0
  1459. X          if ((inMonth == 5) && !LEAP_YR_HEB(hYear))
  1460. X            warn("Warning:user event scheduled on Adar I in nonleap year. line %s\n",
  1461. X                 itoa(lineNum));
  1462. X#endif   
  1463. X          if (inDay > daysInHebMonth(inMonth,hYear))
  1464. X            warn("Warning:user event scheduled on date not appearing this year. line %s\n",
  1465. X                 itoa(lineNum));
  1466. X          
  1467. X          eventStr = s +index +1; /* get the name of the event */
  1468. X          if (eventStr[strlen(eventStr)-1] == '\n')
  1469. X            eventStr[strlen(eventStr)-1] = '\0'; /* chop off the \n */
  1470. X          
  1471. X          /* store the holiday in the LUT */
  1472. X          tmpholp = getHolstorep("InitHolidays:inputFile");
  1473. X          initStr(&tmpholp->name,MAX_LINE_LEN);
  1474. X          strcpy(tmpholp->name,eventStr); /* load the user holiday into it. */
  1475. X          tmpholp->typeMask = USER_EVENT;
  1476. X          PushHoliday(tmpholp,&holidays[inMonth][inDay]);
  1477. X          if (inMonth == 5 || inMonth == 6) 
  1478. X            PushHoliday(tmpholp,&union_Adar[inDay]);
  1479. X          
  1480. X          lineNum++;
  1481. X          nextChar = (char) getc(inFile); /* force an EOF */
  1482. X        }
  1483. X    }
  1484. X}      
  1485. X
  1486. X
  1487. X
  1488. Xvoid getHebHolidays (dth,weekday, holiList) 
  1489. X     date_t dth;             /* returns a linked list of holidays for that date*/ 
  1490. X     int weekday;
  1491. X     holstorep_t *holiList;     /* the typeMask on the first element of */
  1492. X     /* the returned list must reflect */
  1493. X     /* the union of all component masks */
  1494. X{
  1495. X  char * funName = "getHebHolidays";
  1496. X  int tmpMask;
  1497. X  holstorep_t tmpholip, chp;
  1498. X  static holstorep_t todayp, yesterp, morrowp, morrow2p;
  1499. X  static int chanukah_day,first;
  1500. X  
  1501. X#define CORRECTION(yy,mm) (LEAP_YR_HEB(yy) ? 0 : (((mm) > 4) ? 1: 0))
  1502. X  
  1503. X  if (first) 
  1504. X    {
  1505. X      todayp  = holidays[dth.mm][dth.dd];
  1506. X      yesterp = holidays[prevHebDate(dth).mm][prevHebDate(dth).dd];
  1507. X      morrowp = holidays[nextHebDate(dth).mm][nextHebDate(dth).dd];
  1508. X      morrow2p = holidays[nextHebDate(nextHebDate(dth)).mm]
  1509. X        [nextHebDate(nextHebDate(dth)).dd];
  1510. X      first = 0;
  1511. X    }
  1512. X  else
  1513. X    {
  1514. X      date_t morrow2dt;
  1515. X      
  1516. X      morrow2dt = nextHebDate(nextHebDate(dth));
  1517. X      yesterp = todayp;
  1518. X      todayp = morrowp;
  1519. X      morrowp = morrow2p;
  1520. X      if (!LEAP_YR_HEB(dth.yy) && morrow2dt.mm == 5)
  1521. X        morrow2p = union_Adar[morrow2dt.dd];
  1522. X      else
  1523. X        morrow2p = holidays[morrow2dt.mm +CORRECTION(dth.yy,morrow2dt.mm)]
  1524. X          [morrow2dt.dd];
  1525. X    }
  1526. X  
  1527. X  tmpMask =0;
  1528. X  *holiList = NULL;
  1529. X
  1530. X
  1531. X#define NISAN (6 + LEAP_YR_HEB(dth.yy))
  1532. X#define SIVAN (NISAN + 2)
  1533. X  if (dth.mm == NISAN && dth.dd == 16) /* 2nd day of pesach */
  1534. X    omer++;
  1535. X  if (omer && dth.mm == SIVAN && dth.dd == 6 ) /*shavuot*/
  1536. X    omer = 0;
  1537. X
  1538. X  for (chp = todayp; chp; chp = chp->next)
  1539. X    {
  1540. X      /* for normal holidays */
  1541. X      if (!(weekday == SAT && chp->typeMask & NIDCHE) &&
  1542. X          !(chp->typeMask & MUKDAM  && (weekday == FRI || weekday == SAT)) &&
  1543. X          !(chp->typeMask & MUKDAM2 && (weekday == THU || weekday == FRI)))
  1544. X    tmpMask |= PushHoliday(chp,holiList);    /* do normal holidays*/
  1545. X    }
  1546. X  
  1547. X  if (weekday == SUN && yesterp)      /* fast days which are nidche */
  1548. X    for (chp = yesterp; chp; chp = chp->next)
  1549. X      if (chp->typeMask & NIDCHE)
  1550. X        {
  1551. X          char *st;
  1552. X          
  1553. X          initStr(&st,NM_LEN);
  1554. X          strncat(st,chp->name,NM_LEN);
  1555. X          strncat(st," [nidche]",NM_LEN);
  1556. X          tmpMask |= PushHoliday(chp,holiList);
  1557. X          (*holiList)->name = st;
  1558. X        }
  1559. X  
  1560. X  /* if the date actually falls */
  1561. X  /* on friday or shabbat*/
  1562. X  if (weekday == THU)
  1563. X    {
  1564. X      for (chp = morrowp; chp; chp = chp->next)
  1565. X        if (chp->typeMask & MUKDAM)
  1566. X          {
  1567. X            char *st;
  1568. X            
  1569. X            initStr(&st,NM_LEN);
  1570. X            strncat(st,chp->name,NM_LEN);
  1571. X            strncat(st," [mukdam]",NM_LEN);
  1572. X            tmpMask |= PushHoliday(chp,holiList);
  1573. X            (*holiList)->name = st;
  1574. X          }
  1575. X      for (chp = morrow2p; chp; chp = chp->next)
  1576. X        if (chp->typeMask & MUKDAM)
  1577. X          {
  1578. X            char *st;
  1579. X            
  1580. X            initStr(&st,NM_LEN);
  1581. X            strncat(st,chp->name,NM_LEN);
  1582. X            strncat(st," [mukdam]",NM_LEN);
  1583. X            tmpMask |= PushHoliday(chp,holiList);
  1584. X            (*holiList)->name = st;
  1585. X          }
  1586. X    }
  1587. X  
  1588. X  /* if the date actually falls */
  1589. X  /* on thursday or friday*/
  1590. X  if (weekday == WED)
  1591. X    {
  1592. X      for (chp = morrowp; chp; chp = chp->next)
  1593. X        if (chp->typeMask & MUKDAM2)
  1594. X          {
  1595. X            char *st;
  1596. X            
  1597. X            initStr(&st,NM_LEN);
  1598. X            strncat(st,chp->name,NM_LEN);
  1599. X            strncat(st," [mukdam]",NM_LEN);
  1600. X            tmpMask |= PushHoliday(chp,holiList);
  1601. X            (*holiList)->name = st;
  1602. X          }
  1603. X      for (chp = morrow2p; chp; chp = chp->next)
  1604. X        if (chp->typeMask & MUKDAM2)
  1605. X          {
  1606. X            char *st;
  1607. X            
  1608. X            initStr(&st,NM_LEN);
  1609. X            strncat(st,chp->name,NM_LEN);
  1610. X            strncat(st," [mukdam]",NM_LEN);
  1611. X            tmpMask |= PushHoliday(chp,holiList);
  1612. X            (*holiList)->name = st;
  1613. X          }
  1614. X    }
  1615. X  
  1616. X  /* Lag B'Omer Processing */
  1617. X  if (omer == 33) {
  1618. X    tmpholip = getHolstorep(funName);
  1619. X    initStr(&tmpholip->name,NM_LEN); 
  1620. X    strncpy(tmpholip->name,"Lag B'Omer",NM_LEN);
  1621. X    tmpMask |= PushHoliday(tmpholip,holiList);
  1622. X  }
  1623. X  
  1624. X  if (dth.dd == 29 && dth.mm == 2) 
  1625. X    chanukah_day = 1;
  1626. X  
  1627. X  if (chanukah_day) {
  1628. X    tmpMask |= PushHoliday(&chanukah_arr[chanukah_day],holiList);
  1629. X    if (chanukah_day == 4)
  1630. X      chanukah_day = 0;
  1631. X    else chanukah_day++;
  1632. X  }
  1633. X  
  1634. X  
  1635. X  /* rosh Chodesh Processing... */
  1636. X  if (dth.dd == 1 && dth.mm){   /* every 1st of the month except tishrei */
  1637. X    tmpholip = getHolstorep(funName);
  1638. X    initStr(&tmpholip->name,NM_LEN); 
  1639. X    strcat(tmpholip->name,"Rosh Chodesh ");
  1640. X    if (!tabs_sw)
  1641. X      strncat(tmpholip->name,hMonths[LEAP_YR_HEB(dth.yy)][dth.mm].name,NM_LEN);
  1642. X    tmpMask |= PushHoliday(tmpholip,holiList);
  1643. X  }
  1644. X  if (dth.dd == 30){
  1645. X    tmpholip = getHolstorep(funName);
  1646. X    initStr(&tmpholip->name,NM_LEN);
  1647. X    strcat(tmpholip->name,"Rosh Chodesh ");
  1648. X    if (!tabs_sw)
  1649. X      strncat(tmpholip->name,hMonths[LEAP_YR_HEB(dth.yy)][dth.mm+1].name,NM_LEN);
  1650. X    tmpMask |= PushHoliday(tmpholip,holiList);
  1651. X  }
  1652. X  
  1653. X  if (*holiList) (*holiList)->typeMask = tmpMask;
  1654. X  
  1655. X}
  1656. X
  1657. Xvoid incHebJulDate(dth,dtj,wkday)
  1658. X     date_t *dth, *dtj;
  1659. X     int *wkday;
  1660. X{
  1661. X  /* increments both hebrew and julian calendars */
  1662. X  
  1663. X  incDate (dtj,1);
  1664. X  *wkday = dayOfWeek(*dtj);
  1665. X  *dth = nextHebDate(*dth);
  1666. X}   
  1667. X
  1668. Xvoid PrintWeekday (dt) 
  1669. X     date_t dt;
  1670. X{
  1671. X  printf ("%s, ",ShortDayNames[dayOfWeek(dt)]);
  1672. X}
  1673. X
  1674. Xvoid PrintJulDate (dt) 
  1675. X     date_t dt;
  1676. X{
  1677. X  if (!suppressGreg_sw) {
  1678. X    if (euroDates_sw)
  1679. X      printf ("%d.%d.",dt.dd,dt.mm+1);
  1680. X    else
  1681. X      printf ("%d/%d/",dt.mm+1,dt.dd);
  1682. X    
  1683. X    if (yearDigits_sw)
  1684. X      printf("%d",dt.yy % 100);
  1685. X    else
  1686. X      printf("%d",dt.yy);
  1687. X    
  1688. X    if (tabs_sw)
  1689. X      printf("\t");
  1690. X    else
  1691. X      printf(" ");
  1692. X  }
  1693. X  
  1694. X  if (weekday_sw)
  1695. X    PrintWeekday(dt);
  1696. X}
  1697. X
  1698. X
  1699. Xchar *DoSedra (sedra, ydat,increment) /* returns a string "Parshat <parsha>" */
  1700. X     int *sedra,increment;      /* based on the current parsha number */
  1701. X     year_t ydat;
  1702. X{
  1703. X#define PLENGTH 40
  1704. X  static char s[PLENGTH+1];
  1705. X  static char * p;
  1706. X  
  1707. X  if (ashkenazis_sw) p = "Parshas ";
  1708. X  else               p = "Parshat ";
  1709. X  
  1710. X  if (increment) increment = 1;
  1711. X  *s = '\0';
  1712. X  if (!tabs_sw)
  1713. X    strncat(s,p,PLENGTH);
  1714. X  strncat(s,sedrot[*sedra][ashkenazis_sw],PLENGTH);
  1715. X  switch (*sedra)
  1716. X    {
  1717. X    case VAYAKHEL :
  1718. X      if (ydat.vayakhelPikudei)
  1719. X        {
  1720. X          strncat(s,"-",PLENGTH);
  1721. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1722. X          *sedra += 2*increment;
  1723. X        }
  1724. X      else *sedra += 1*increment;
  1725. X      break;
  1726. X    case TAZRIA:
  1727. X      if (ydat.tazriaMetzorah)
  1728. X        {
  1729. X          strncat(s,"-",PLENGTH);
  1730. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1731. X          *sedra += 2*increment;
  1732. X        }
  1733. X      else *sedra += 1*increment;
  1734. X      break;
  1735. X    case ACHREI :
  1736. X      if (ydat.achreiKedoshim)
  1737. X        {
  1738. X          strncat(s,"-",PLENGTH);
  1739. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1740. X          *sedra += 2*increment;
  1741. X        }
  1742. X      else *sedra += 1*increment;
  1743. X      break;
  1744. X    case BEHAR :
  1745. X      if (ydat.beharBech)
  1746. X        {
  1747. X          strncat(s,"-",PLENGTH);
  1748. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1749. X          *sedra += 2*increment;
  1750. X        }
  1751. X      else *sedra += 1*increment;
  1752. X      break;
  1753. X    case CHUKAT :
  1754. X      if (ydat.chukatBalak)
  1755. X        {
  1756. X          strncat(s,"-",PLENGTH);
  1757. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1758. X          *sedra += 2*increment;
  1759. X        }
  1760. X      else *sedra += 1*increment;
  1761. X      break;
  1762. X    case MATOT :
  1763. X      if (ydat.matotMasei)
  1764. X        {
  1765. X          strncat(s,"-",PLENGTH);
  1766. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1767. X          *sedra += 2*increment;
  1768. X        }
  1769. X      else *sedra += 1*increment;
  1770. X      break;
  1771. X    case NITZAVIM :
  1772. X      if (ydat.nitzavimVayelech)
  1773. X        {
  1774. X          strncat(s,"-",PLENGTH);
  1775. X          strncat(s,sedrot[*sedra+1][ashkenazis_sw],PLENGTH);
  1776. X          *sedra += 2*increment;
  1777. X        }
  1778. X      else *sedra += 1*increment;
  1779. X      break;
  1780. X    case LAST_INDEX(sedrot)-1:
  1781. X      *sedra = 0;
  1782. X      break;
  1783. X    default:
  1784. X      *sedra += 1*increment;
  1785. X    }
  1786. X  
  1787. X  strncat(s,"\n",PLENGTH);
  1788. X  return s;
  1789. X}
  1790. X
  1791. Xvoid DoCalendar (roshDt,justMonth,justDay)
  1792. X     date_t roshDt;             /* rosh Hashana of preceeding year */
  1793. X     int justMonth,             /* print this month  */
  1794. X       justDay;                 /* print this day */
  1795. X{
  1796. X  int sedra,weekday;
  1797. X  date_t todayj, todayh;
  1798. X  holstorep_t holip;            /* a list of holidays for today */
  1799. X  year_t theYear;
  1800. X  todayj = roshDt;
  1801. X  
  1802. X  todayh.mm = 0;
  1803. X  todayh.dd = 1;
  1804. X  todayh.yy = JUL2HEB(roshDt.yy) + 1; /* because it's after R"H */
  1805. X  
  1806. X  
  1807. X  theYear = yearData(todayh.yy);
  1808. X  
  1809. X  if (CHAR2NUM(theYear.name[0]) != dayOfWeek(roshDt))
  1810. X    die ("Bad Day!\n","");  
  1811. X  
  1812. X  /* first scan forward to simchat Torah, keeping track of dates only. */
  1813. X  while (todayh.dd != SIMCHAT_DAY)
  1814. X    incHebJulDate(&todayh, &todayj,&weekday);
  1815. X  
  1816. X  sedra = 0;            /* initialize sedra */
  1817. X  
  1818. X  /* then continue until january 1st. */
  1819. X  do 
  1820. X    {
  1821. X      getHebHolidays(todayh,weekday,&holip);
  1822. X      if (weekday == SAT && !(holip && holip->typeMask & OWNSEDRA)) 
  1823. X        DoSedra(&sedra,theYear,1);
  1824. X      incHebJulDate(&todayh,&todayj,&weekday);
  1825. X    } while (!(todayj.mm==0 && todayj.dd==1));
  1826. X  
  1827. X  /* -------Main Year Loop-------*/
  1828. X  do 
  1829. X    {
  1830. X      if (hebDates_sw && 
  1831. X          (!specMonth_sw || (justMonth== todayj.mm)) &&
  1832. X          (!specDay_sw   || (justDay == todayj.dd)))
  1833. X        {
  1834. X          PrintJulDate(todayj);
  1835. X
  1836. X             printf ("%d%s of %s, %d\n",todayh.dd, /* print the hebrew date */
  1837. X                      numSuffix(todayh.dd),
  1838. X                      hMonths[LEAP_YR_HEB(todayh.yy)][todayh.mm].name,
  1839. X                      todayh.yy);
  1840. X        }
  1841. X      getHebHolidays(todayh,weekday,&holip);
  1842. X      
  1843. X      if (todayh.mm == TISHREI && todayh.dd == 1)
  1844. X        theYear = yearData(todayh.yy); /* if R"H reset YearData */
  1845. X      
  1846. X      
  1847. X      
  1848. X      if (sedraAllWeek_sw ||
  1849. X          (sedrot_sw && weekday==SAT &&
  1850. X           !(holip && holip->typeMask & OWNSEDRA)))
  1851. X        {
  1852. X          if ((!specMonth_sw || (justMonth == todayj.mm)) &&
  1853. X              (!specDay_sw   || (justDay == todayj.dd)))
  1854. X            {
  1855. X              PrintJulDate(todayj);
  1856. X              printf("%s",DoSedra(&sedra,theYear,weekday==SAT &&
  1857. X                                  !(holip && holip->typeMask & OWNSEDRA)));
  1858. X            }
  1859. X          else DoSedra(&sedra,theYear,weekday==SAT &&
  1860. X                       !(holip && holip->typeMask & OWNSEDRA));
  1861. X        }
  1862. X      
  1863. X      
  1864. X      if (sedrot_sw && 
  1865. X          todayh.mm == TISHREI && /* reset the sedra on simchat torah */
  1866. X          todayh.dd == SIMCHAT_DAY)
  1867. X        sedra =0;
  1868. X      
  1869. X      if ((!specMonth_sw || (justMonth == todayj.mm)) &&
  1870. X          (!specDay_sw   || (justDay == todayj.dd)))
  1871. X        for (;holip;holip = holip->next)
  1872. X          if (!suppressHolidays_sw || (holip->typeMask & USER_EVENT))
  1873. X            {
  1874. X              PrintJulDate(todayj);
  1875. X              printf ("%s\n",holip->name);
  1876. X            }
  1877. X      
  1878. X      /* print the omer if desired */
  1879. X      if (omer && printOmer_sw &&
  1880. X          (!specMonth_sw || (justMonth == todayj.mm)) &&
  1881. X          (!specDay_sw   || (justDay == todayj.dd)))
  1882. X        {
  1883. X          char *omerStr;
  1884. X          initStr(&omerStr,NM_LEN);
  1885. X          if (!tabs_sw) {
  1886. X            strncat(omerStr,itoa(omer),NM_LEN);
  1887. X            strncat(omerStr,numSuffix(omer),NM_LEN);
  1888. X            strncat(omerStr," day of the Omer",NM_LEN);
  1889. X          }
  1890. X          else {
  1891. X            strncat(omerStr,"Omer: ",NM_LEN);
  1892. X            strncat(omerStr,itoa(omer),NM_LEN);
  1893. X          }
  1894. X          PrintJulDate(todayj);
  1895. X      printf ("%s\n",omerStr);
  1896. X        }
  1897. X      if (omer) omer++;
  1898. X      
  1899. X      incHebJulDate(&todayh,&todayj,&weekday);
  1900. X      
  1901. X    } while (!(specMonth_sw && todayj.mm > justMonth) &&
  1902. X             (todayj.mm!=0 || todayj.dd!=1)); /* continue to january 1st */
  1903. X}
  1904. END_OF_FILE
  1905.   if test 24526 -ne `wc -c <'hebcal.c'`; then
  1906.     echo shar: \"'hebcal.c'\" unpacked with wrong size!
  1907.   fi
  1908.   # end of 'hebcal.c'
  1909. fi
  1910. if test -f 'hebcal.h' -a "${1}" != "-c" ; then 
  1911.   echo shar: Will not clobber existing file \"'hebcal.h'\"
  1912. else
  1913.   echo shar: Extracting \"'hebcal.h'\" \(813 characters\)
  1914.   sed "s/^X//" >'hebcal.h' <<'END_OF_FILE'
  1915. X#ifndef __HEBCAL__
  1916. X#define __HEBCAL__
  1917. X#include <stdio.h>
  1918. X#include "greg.h"
  1919. X#include "error.h"
  1920. X#define MAXDAYS 31
  1921. X#define JUL2HEB(x) ((x)+ 3760)
  1922. X#define MAX_LINE_LEN 100
  1923. X
  1924. Xtypedef struct {
  1925. X  
  1926. X  char * name;
  1927. X  int length;
  1928. X  
  1929. X  int daysInCheshvan;
  1930. X  int daysInKislev;
  1931. X  
  1932. X  int vayakhelPikudei;    /* double parsha flags */
  1933. X  int tazriaMetzorah;
  1934. X  int achreiKedoshim;
  1935. X  int beharBech;
  1936. X  int chukatBalak; 
  1937. X  int matotMasei;
  1938. X  int nitzavimVayelech;
  1939. X  
  1940. X} year_t;
  1941. X
  1942. Xtypedef struct hinode{   /* holiday input structure */
  1943. X    date_t date;
  1944. X    char *(name[2]);
  1945. X  int typeMask;
  1946. X  struct hinode *next;
  1947. X} holinput_t, *holinputp_t;
  1948. X
  1949. Xtypedef struct hsnode{  /* holiday storage structure */
  1950. X    char *name;
  1951. X  int typeMask;
  1952. X  struct hsnode *next;
  1953. X} holstore_t, *holstorep_t;
  1954. X
  1955. Xyear_t yearData();
  1956. Xvoid InitHolidays();
  1957. Xvoid DoCalendar ();
  1958. X
  1959. X#endif
  1960. END_OF_FILE
  1961.   if test 813 -ne `wc -c <'hebcal.h'`; then
  1962.     echo shar: \"'hebcal.h'\" unpacked with wrong size!
  1963.   fi
  1964.   # end of 'hebcal.h'
  1965. fi
  1966. if test -f 'proto.h' -a "${1}" != "-c" ; then 
  1967.   echo shar: Will not clobber existing file \"'proto.h'\"
  1968. else
  1969.   echo shar: Extracting \"'proto.h'\" \(159 characters\)
  1970.   sed "s/^X//" >'proto.h' <<'END_OF_FILE'
  1971. X#ifndef PROTO_H
  1972. X#define PROTO_H
  1973. X#if __STDC__==1 || PROTOTYPES_EXIST
  1974. X#define PROTO(A) A
  1975. X#else
  1976. X#define PROTO(A) ()
  1977. X#endif /*has prototypes */
  1978. X#endif /*PROTO_H*/
  1979. END_OF_FILE
  1980.   if test 159 -ne `wc -c <'proto.h'`; then
  1981.     echo shar: \"'proto.h'\" unpacked with wrong size!
  1982.   fi
  1983.   # end of 'proto.h'
  1984. fi
  1985. if test -f 'start.c' -a "${1}" != "-c" ; then 
  1986.   echo shar: Will not clobber existing file \"'start.c'\"
  1987. else
  1988.   echo shar: Extracting \"'start.c'\" \(6378 characters\)
  1989.   sed "s/^X//" >'start.c' <<'END_OF_FILE'
  1990. X#include <stdio.h>
  1991. X#include "hebcal.h"
  1992. X#include "getopt.h"
  1993. X
  1994. Xextern int
  1995. X  ashkenazis_sw, sedrot_sw, hebDates_sw, euroDates_sw,
  1996. X  specMonth_sw,specDay_sw,
  1997. X  inputFile_sw, weekday_sw, suppressHolidays_sw, suppressGreg_sw, 
  1998. X  printOmer_sw, sedraAllWeek_sw, yearDigits_sw, tabs_sw, omer;
  1999. X
  2000. Xextern FILE *inFile;
  2001. X
  2002. Xvoid RollBack(dtg,target) /* move rosh hashana dtj back until it's */
  2003. X     date_t *dtg;          /* in the year before target */
  2004. X     int target;
  2005. X{
  2006. X  int days,theyear;
  2007. X  
  2008. X  for (days = 0,theyear = dtg->yy ;theyear > target -1; theyear--)
  2009. X    days +=yearData(JUL2HEB(theyear)).length;
  2010. X  decDate (dtg,days); 
  2011. X  
  2012. X}
  2013. X
  2014. Xvoid RollForward(dtg,target)   /* move rosh hashana dtg forward until it's*/
  2015. X     date_t *dtg;               /*  in the year before target*/
  2016. X     int target; 
  2017. X{
  2018. X  int days,theyear;
  2019. X  
  2020. X  for (days = 0,theyear = dtg->yy ;theyear < target -1; theyear++)
  2021. X    days +=yearData(JUL2HEB(theyear+1)).length;
  2022. X  incDate (dtg,days); 
  2023. X  
  2024. X}
  2025. X
  2026. Xstatic int theYear,theMonth,theDay,yearDirty;
  2027. X
  2028. Xvoid handleArgs(argc, argv)
  2029. X     int argc;
  2030. X     char *argv[];
  2031. X{
  2032. X  char optchar;
  2033. X  date_t tempdt;
  2034. X  
  2035. X  char * usage = "usage: hebcal [-adehorsStTwy] [-i file] [[month [day]] year]\n               hebcal help\n";
  2036. X
  2037. X  setDate(&tempdt);        /* do this year */
  2038. X  theYear = tempdt.yy;
  2039. X  
  2040. X  while (EOF != (optchar = 
  2041. X         getopt(argc,argv,"adehorsStTwyi:")))
  2042. X    {
  2043. X      switch (optchar) 
  2044. X    {
  2045. X    case 'a':                      /* ashkenazis hebrew */
  2046. X      ashkenazis_sw =1;
  2047. X      break;
  2048. X    case 'd':                      /* print hebrew date */
  2049. X      hebDates_sw = 1;
  2050. X      break;
  2051. X    case 'i':                      /* input file */
  2052. X      inputFile_sw =1;
  2053. X      if (!(inFile = fopen(optarg,"r"))) 
  2054. X        die("could not open input file %s.",optarg);
  2055. X      break;
  2056. X    case 'e':
  2057. X      euroDates_sw=1;
  2058. X      break;
  2059. X    case 'h':
  2060. X      suppressHolidays_sw =1;
  2061. X      break;
  2062. X    case 'o':
  2063. X      printOmer_sw =1;
  2064. X      break;
  2065. X    case 'r' :            /* Tab-delineated Format */
  2066. X      tabs_sw = 1;
  2067. X      break;
  2068. X    case 's' :            /* print sedrot */
  2069. X      sedrot_sw = 1;
  2070. X      break;
  2071. X    case 'S':            /* print sedra every day. */
  2072. X      sedraAllWeek_sw =1;
  2073. X      break;
  2074. X    case 't':            /* do hebcal for today. */
  2075. X      specMonth_sw =1;
  2076. X      specDay_sw =1;
  2077. X      theMonth = tempdt.mm;    /* year and month specified */
  2078. X      theDay = tempdt.dd;    /* print theDay of theMonth */
  2079. X      yearDirty =1;
  2080. X      printOmer_sw =1;
  2081. X      break;
  2082. X    case 'T':            /* do hebcal for today, omit gregorian date. */
  2083. X      suppressGreg_sw = 1;
  2084. X      specMonth_sw =1;
  2085. X      specDay_sw =1;
  2086. X      theMonth = tempdt.mm;    /* year and month specified */
  2087. X      theDay = tempdt.dd;    /* print theDay of theMonth */
  2088. X      yearDirty =1;
  2089. X      printOmer_sw =1;
  2090. X      break;
  2091. X    case 'w' :            /* print days of the week */
  2092. X      weekday_sw = 1;
  2093. X      break;
  2094. X    case 'y' :            /* Print only last 2 digits of year */
  2095. X      yearDigits_sw = 1;
  2096. X      break;
  2097. X
  2098. X    default: die(usage,"");
  2099. X    }
  2100. X    }
  2101. X  
  2102. X  switch (argc - optind) /* suck up the date */
  2103. X    {    
  2104. X    case 0 : break;        /* process this year */
  2105. X    case 1 : 
  2106. X      if (isAllNums(argv[optind])) 
  2107. X    {
  2108. X      theYear = atoi(argv[optind]); /* just year specified */
  2109. X      yearDirty =1;            /* print whole year */
  2110. X    }
  2111. X      else if (!strcmp(argv[optind],"help")) 
  2112. X    {
  2113. X      printf ("Hebcal Version 2.1 By Danny Sadinoff\n");
  2114. X      printf (usage);
  2115. X      printf ("\nOPTIONS:\n");
  2116. X      printf ("   -a : use ashkenazis hebrew\n");
  2117. X      printf ("   -d : add hebrew dates\n");
  2118. X      printf ("   -e : ouput european dates DD.MM.YYYY\n");
  2119. X      printf ("   -h : suppress holidays\n");
  2120. X      printf ("   -i : get user events from specified file\n");
  2121. X      printf ("   -o : add days of the omer\n");
  2122. X      printf ("   -r : tab delineated format\n");
  2123. X      printf ("   -s : add weekly sedrot on Saturday\n");
  2124. X      printf ("   -S : print sedrah of the week on all calendar days\n");
  2125. X      printf ("   -t : only output for today's date\n");
  2126. X      printf ("   -T : print today's pertinent information, no gregorian date\n");
  2127. X      printf ("   -w : add day of the week\n");
  2128. X      printf ("   -y : print only last two digits of year\n\n");
  2129. X      printf ("hebcal help --- prints this message\n");
  2130. X      printf (" ---MORE--- hit enter to continue....\n");
  2131. X      gets (argv[0]);
  2132. X      printf ("Hebcal prints out hebrew calendars one solar year at a time.  Given one\n");
  2133. X      printf ("argument, it will print out the calendar for that year.  Given two numeric\n");
  2134. X      printf ("arguments mm yyyy, it prints out the calendar for month mm of year yyyy.\n");
  2135. X      printf ("\nFor example, \n");
  2136. X      printf ("   hebcal -ho\n");
  2137. X      printf ("will just print out the days of the omer for the current year.\n");
  2138. X      printf ("Note: use COMPLETE years.  You probably aren't interested in \n");
  2139. X      printf ("hebcal 93, but rather hebcal 1993.\n");
  2140. X      printf ("\n\nHebcal is not free.  If you wish to use it for more than a week,\n");
  2141. X      printf ("you must let me know you're using it:  sadinoff@eniac.seas.upenn.edu\n");
  2142. X      printf ("Checks are also welcome:  If you'd like to patronize good programming,\n");
  2143. X      printf ("send $10 to Danny Sadinoff\n");
  2144. X      printf ("            1 Cove La.    \n");
  2145. X      printf ("            Great Neck, NY\n");
  2146. X      printf ("                    11024\n");
  2147. X      exit (0);
  2148. X    }
  2149. X      else die (usage,"");
  2150. X      break;
  2151. X      
  2152. X    case 2:
  2153. X      if (!(isAllNums(argv[optind]) && isAllNums(argv[optind +1])))
  2154. X    die (usage,"");
  2155. X      specMonth_sw =1;
  2156. X      theMonth = atoi(argv[optind]) -1; /* year and month specified */
  2157. X      theYear = atoi(argv[++optind]); /* print theMonth of theYear */
  2158. X      yearDirty =1;
  2159. X      break;
  2160. X      
  2161. X    case 3:
  2162. X      if (!(isAllNums(argv[optind]) 
  2163. X        && isAllNums(argv[optind +1])
  2164. X        && isAllNums(argv[optind +2])))
  2165. X    die (usage,"");
  2166. X      specMonth_sw =1;
  2167. X      specDay_sw =1;
  2168. X      theMonth = atoi(argv[optind]) -1; /* year and month specified */
  2169. X      theDay = atoi(argv[++optind]); /* print theDay of theMonth */
  2170. X      theYear = atoi(argv[++optind]); /* print theMonth of theYear */
  2171. X      yearDirty =1;
  2172. X      break;
  2173. X    default: die (usage,"");
  2174. X    }
  2175. X}
  2176. X
  2177. X
  2178. Xchar * progname;
  2179. X
  2180. Xint main (argc, argv)
  2181. X     int argc;
  2182. X     char *argv[];
  2183. X{
  2184. X  date_t startDate;
  2185. X  
  2186. X  progname = "HEBCAL";
  2187. X  
  2188. X  startDate.dd = 28;
  2189. X  startDate.mm = SEP; /* any ol' rosh hashana */
  2190. X  startDate.yy = 1992;
  2191. X  
  2192. X  handleArgs(argc,argv);
  2193. X  
  2194. X  if (specDay_sw) hebDates_sw = 1;
  2195. X  
  2196. X  if (theYear < startDate.yy +1) /* go to R"H of the year before */
  2197. X    RollBack(&startDate,theYear);
  2198. X  else if (theYear > startDate.yy +1) /* start from there */
  2199. X    RollForward(&startDate,theYear);
  2200. X  
  2201. X  InitHolidays(startDate);
  2202. X  DoCalendar(startDate,theMonth,theDay);   
  2203. X  
  2204. X  return 0;
  2205. X}
  2206. END_OF_FILE
  2207.   if test 6378 -ne `wc -c <'start.c'`; then
  2208.     echo shar: \"'start.c'\" unpacked with wrong size!
  2209.   fi
  2210.   # end of 'start.c'
  2211. fi
  2212. echo shar: End of archive 1 \(of 1\).
  2213. cp /dev/null ark1isdone
  2214. MISSING=""
  2215. for I in 1 ; do
  2216.     if test ! -f ark${I}isdone ; then
  2217.     MISSING="${MISSING} ${I}"
  2218.     fi
  2219. done
  2220. if test "${MISSING}" = "" ; then
  2221.     echo You have the archive.
  2222.     rm -f ark[1-9]isdone
  2223. else
  2224.     echo You still must unpack the following archives:
  2225.     echo "        " ${MISSING}
  2226. fi
  2227. exit 0
  2228. exit 0 # Just in case...
  2229.