1 /* SWISSEPH
2 
3   Authors: Dieter Koch and Alois Treindl, Astrodienst Z�rich
4 
5 **************************************************************/
6 /* Copyright (C) 1997 - 2021 Astrodienst AG, Switzerland.  All rights reserved.
7 
8   License conditions
9   ------------------
10 
11   This file is part of Swiss Ephemeris.
12 
13   Swiss Ephemeris is distributed with NO WARRANTY OF ANY KIND.  No author
14   or distributor accepts any responsibility for the consequences of using it,
15   or for whether it serves any particular purpose or works at all, unless he
16   or she says so in writing.
17 
18   Swiss Ephemeris is made available by its authors under a dual licensing
19   system. The software developer, who uses any part of Swiss Ephemeris
20   in his or her software, must choose between one of the two license models,
21   which are
22   a) GNU Affero General Public License (AGPL)
23   b) Swiss Ephemeris Professional License
24 
25   The choice must be made before the software developer distributes software
26   containing parts of Swiss Ephemeris to others, and before any public
27   service using the developed software is activated.
28 
29   If the developer choses the AGPL software license, he or she must fulfill
30   the conditions of that license, which includes the obligation to place his
31   or her whole software project under the AGPL or a compatible license.
32   See https://www.gnu.org/licenses/agpl-3.0.html
33 
34   If the developer choses the Swiss Ephemeris Professional license,
35   he must follow the instructions as found in http://www.astro.com/swisseph/
36   and purchase the Swiss Ephemeris Professional Edition from Astrodienst
37   and sign the corresponding license contract.
38 
39   The License grants you the right to use, copy, modify and redistribute
40   Swiss Ephemeris, but only under certain conditions described in the License.
41   Among other things, the License requires that the copyright notices and
42   this notice be preserved on all copies.
43 
44   Authors of the Swiss Ephemeris: Dieter Koch and Alois Treindl
45 
46   The authors of Swiss Ephemeris have no control or influence over any of
47   the derived works, i.e. over software or services created by other
48   programmers which use Swiss Ephemeris functions.
49 
50   The names of the authors or of the copyright holder (Astrodienst) must not
51   be used for promoting any software, product or service which uses or contains
52   the Swiss Ephemeris. This copyright notice is the ONLY place where the
53   names of the authors can legally appear, except in cases where they have
54   given special permission in writing.
55 
56   The trademarks 'Swiss Ephemeris' and 'Swiss Ephemeris inside' may be used
57   for promoting such software, products or services.
58 */
59 
60 # define SMOD_LUNAR	1
61 # define SMOD_HOW	2	/* an option for Lunar */
62 # define SMOD_SOLAR	4
63 # define SMOD_LOCAL	8	/* an option for Solar */
64 # define SMOD_TOTAL	16
65 # define SMOD_ANNULAR	32	/* count as penumbral for Lunar */
66 # define SMOD_ANNTOT	64
67 # define SMOD_PARTIAL	128
68 # define SMOD_ALL	(SMOD_TOTAL| SMOD_ANNULAR|SMOD_PARTIAL|SMOD_ANNTOT)
69 # define SMOD_RISE	256
70 # define SMOD_METR	512
71 # define SMOD_HOCAL	1024
72 
73 
74 /* attention: Microsoft Compiler does not accept strings > 2048 char */
75 static char *infocmd0 = "\n\
76   Sweclips computes solar and lunar eclipses,\n\
77   rises, sets, and meridian transits for planets and fixed stars\n\
78   Input can either be a date or an absolute julian day number.\n\
79 \n";
80 
81 static char *infocmd1 = "\n\
82   Command line options:\n\
83         -lunar  lunar eclipse\n\
84         -solar  solar eclipse\n\
85         -hocal  hocallist format\n\
86         -local  local solar eclipse\n\
87         -annular\n\
88         -total\n\
89         -partial\n\
90         -rise   next rise and set\n\
91         -metr   next meridian transits (culminations)\n\
92         -lon...   geogr. longitude D.MMSS\n\
93         -lat...   geogr. longitude D.MMSS\n\
94 	-p.       planet (like swetest.c)\n\
95         -edirPATH change the directory of the ephemeris files \n\
96         -head   don\'t print the header before the planet data. This option\n\
97                 is useful when you want to paste the output into a\n\
98                 spreadsheet for displaying graphical ephemeris.\n\
99         +head   header before every step (with -s..) \n\
100         -bDATE  use this begin date instead of asking; use -b1.1.1992 if\n\
101                 the begin date string contains blanks; use format -bj2400000.5\n\
102                 to express the date as absolute Julian day number.\n\
103                 Note: the date format is day month year (European style).\n\
104                 \n";
105 
106 static char *infocmd2 = "\
107         -eswe   swiss ephemeris\n\
108         -ejpl   jpl ephemeris (DE406), or with ephemeris file name\n\
109                 -ejplDE200.cdrom \n\
110         -emos   moshier ephemeris\n\
111         -?, -h  display whole info\n\
112         -hcmd   display commands\n\
113         -hdate  display input date format\n";
114 
115 static char *infodate = "\n\
116   Date entry:\n\
117   In the interactive mode, when you are asked for a start date,\n\
118   you can enter data in one of the following formats:\n\
119 \n\
120         1.2.1991        three integers separated by a nondigit character for\n\
121                         day month year. Dates are interpreted as Gregorian\n\
122                         after 4.10.1582 and as Julian Calender before.\n\
123                         Time is always set to midnight.\n\
124                         If the three letters jul are appended to the date,\n\
125                         the Julian calendar is used even after 1582.\n\
126                         If the four letters greg are appended to the date,\n\
127                         the Gregorian calendar is used even before 1582.\n\
128 \n\
129         j2400123.67     the letter j followed by a real number, for\n\
130                         the absolute Julian daynumber of the start date.\n\
131                         Fraction .5 indicates midnight, fraction .0\n\
132                         indicates noon, other times of the day can be\n\
133                         chosen accordingly.\n\
134         \n";
135 /**************************************************************/
136 
137 #include "sweodef.h"
138 #include "swephexp.h"
139 
140 #if MSDOS
141 #  include <direct.h>
142 #  include <dos.h>
143 #  ifdef _MSC_VER
144 #    include <sys\types.h>
145 #  endif
146 #endif
147 
148 #ifdef MACOS
149 #  include <console.h>
150 #endif
151 
152 
153 #define J2000           2451545.0  /* 2000 January 1.5 */
154 #define square_sum(x)   (x[0]*x[0]+x[1]*x[1]+x[2]*x[2])
155 #define SEFLG_EPHMASK   (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH)
156 
157 #define BIT_ROUND_SEC   1
158 #define BIT_ROUND_MIN   2
159 #define BIT_ZODIAC      4
160 #define BIT_LZEROES     8
161 
162 # define ECL_LUN_PENUMBRAL       1       /* eclipse types for hocal list */
163 # define ECL_LUN_PARTIAL        2
164 # define ECL_LUN_TOTAL          3
165 # define ECL_SOL_PARTIAL        4
166 # define ECL_SOL_ANNULAR        5
167 # define ECL_SOL_TOTAL          6
168 
169 static char *zod_nam[] = {"ar", "ta", "ge", "cn", "le", "vi",
170                           "li", "sc", "sa", "cp", "aq", "pi"};
171 
172 static char *dms(double xv, int32 iflg);
173 static char *hms(double x, int32 iflag);
174 static int do_calc(double tjd, int ipl, long iflag, double *x, char *serr);
175 static void do_printf(char *info);
176 static int make_ephemeris_path(long iflag, char *argv0);
177 static char *hms_from_tjd(double x);
178 static int cut_str_any(char *s, char *cutlist, char *cpos[], int nmax);
179 static int letter_to_ipl(int letter);
180 
main(int argc,char * argv[])181 int main(int argc, char *argv[])
182 {
183   char saves[AS_MAXCH];
184   char s1[AS_MAXCH], s2[AS_MAXCH];
185   char serr[AS_MAXCH], serr_save[AS_MAXCH], serr_warn[AS_MAXCH],
186 sout[AS_MAXCH];
187   char *sp, *sp2;
188   char *fmt = "PLBRS";
189   int i, ii;
190   int smod = 0;
191   int ecl_type = 0;
192   int jmon, jday, jyear;
193   double jut = 0.0;
194   long nstep = 1;
195   double x[6];
196   char ephepath[AS_MAXCH];
197   char fname[AS_MAXCH];
198   char sdate[AS_MAXCH];
199   char *begindate = NULL;
200   long iflag = 0;
201   long eclflag;
202   double geopos[20], attr[20], tret[20];
203   double a, b, c;
204   int whicheph = SEFLG_SWIEPH;
205   short with_header = TRUE;
206   int gregflag = SE_GREG_CAL;
207   double tjd = 2415020.5, t_ut;
208   double dt;
209   int direction = 1;
210   AS_BOOL direction_flag = FALSE;
211   int32 ipl = 0;
212   char starname[AS_MAXCH];
213   int32 search_flag = 0;
214   char slon[30], slat[30];
215   serr[0] = serr_save[0] = serr_warn[0] = saves[0] = '\0';
216   starname[0] = '\0';
217   strcpy(ephepath, SE_EPHE_PATH);
218   strcpy(fname, SE_FNAME_DE406);
219   strcpy(slon, "8.33");         /* geographical position of Zurich */
220   strcpy(slat, "47.23");
221   /*
222    * command line
223    */
224   search_flag = SE_ECL_CENTRAL | SE_ECL_NONCENTRAL;
225   smod = SMOD_SOLAR;
226   for (i = 1; i < argc; i++) {
227     if (strncmp(argv[i], "-head", 5) == 0) {
228       with_header = FALSE;
229     } else if (strcmp(argv[i], "-lunar") == 0) {
230       smod |= SMOD_LUNAR;
231       smod &= ~SMOD_SOLAR;
232     } else if (strcmp(argv[i], "-hocal") == 0) {
233       smod |= SMOD_HOCAL;
234     } else if (strcmp(argv[i], "-solar") == 0) {
235       smod |= SMOD_SOLAR;
236     } else if (strcmp(argv[i], "-how") == 0) {
237       smod |= SMOD_HOW;
238     } else if (strcmp(argv[i], "-total") == 0) {
239       smod |= SMOD_TOTAL;
240     } else if (strcmp(argv[i], "-annular") == 0) {
241       smod |= SMOD_ANNULAR;
242     } else if (strcmp(argv[i], "-anntot") == 0) {
243       smod |= SMOD_ANNTOT;
244     } else if (strcmp(argv[i], "-partial") == 0) {
245       smod |= SMOD_PARTIAL;
246     } else if (strcmp(argv[i], "-noncentral") == 0) {
247       search_flag &= ~SE_ECL_CENTRAL;
248       search_flag |= SE_ECL_NONCENTRAL;
249     } else if (strcmp(argv[i], "-central") == 0) {
250       search_flag &= ~SE_ECL_NONCENTRAL;
251       search_flag |= SE_ECL_CENTRAL;
252     } else if (strcmp(argv[i], "-local") == 0) {
253       smod |= SMOD_LOCAL;
254     } else if (strcmp(argv[i], "-rise") == 0) {
255       smod |= SMOD_RISE;
256       smod &= ~SMOD_SOLAR;
257     } else if (strcmp(argv[i], "-metr") == 0) {
258       smod |= SMOD_METR;
259       smod &= ~SMOD_SOLAR;
260     } else if (strncmp(argv[i], "-j", 2) == 0) {
261       begindate = argv[i] + 1;
262     } else if (strncmp(argv[i], "-lon", 4) == 0) {
263       strcpy(slon, argv[i] + 4);
264     } else if (strncmp(argv[i], "-lat", 4) == 0) {
265       strcpy(slat, argv[i] + 4);
266     } else if (strncmp(argv[i], "-ejpl", 5) == 0) {
267       whicheph = SEFLG_JPLEPH;
268       strcpy(ephepath, SE_EPHE_PATH);
269       if (*(argv[i]+5) != '\0')
270         strcpy(fname, argv[i]+5);
271     } else if (strcmp(argv[i], "-eswe") == 0) {
272       whicheph = SEFLG_SWIEPH;
273       strcpy(ephepath, SE_EPHE_PATH);
274     } else if (strcmp(argv[i], "-emos") == 0) {
275       whicheph = SEFLG_MOSEPH;
276     } else if (strncmp(argv[i], "-edir", 5) == 0) {
277       if (*(argv[i]+5) != '\0')
278         strcpy(ephepath, argv[i]+5);
279     } else if (strncmp(argv[i], "-n", 2) == 0) {
280       nstep = atoi(argv[i]+2);
281     } else if (strcmp(argv[i], "-bwd") == 0) {
282       direction = -1;
283           direction_flag = TRUE;
284     } else if (strncmp(argv[i], "-b", 2) == 0) {
285       begindate = argv[i] + 2;
286     } else if (strncmp(argv[i], "-p", 2) == 0) {
287       sp = argv[i] + 2;
288       if (strlen(sp) == 1)
289 	ipl = letter_to_ipl(*sp);
290       else
291 	strcpy(starname, sp);
292     } else if (strncmp(argv[i], "-h", 2) == 0
293       || strncmp(argv[i], "-?", 2) == 0) {
294       sp = argv[i]+2;
295       if (*sp == 'c' || *sp == '\0') {
296         do_printf(infocmd0);
297         do_printf(infocmd1);
298         do_printf(infocmd2);
299       }
300       if (*sp == 'd' || *sp == '\0')
301         do_printf(infodate);
302       goto end_main;
303     } else {
304       sprintf(sout, "illegal option %s\n", argv[i]);
305       do_printf(sout);
306       exit(1);
307     }
308   }
309   if (smod & (SMOD_LUNAR | SMOD_SOLAR))  {
310     if ((smod & SMOD_ALL) == 0) /* no selective eclipse type set, set all */
311       smod |= SMOD_ALL;
312     if (smod & SMOD_TOTAL) search_flag |= SE_ECL_TOTAL;
313     if (smod & SMOD_ANNULAR) search_flag |= SE_ECL_ANNULAR | SE_ECL_PENUMBRAL;
314     if (smod & SMOD_PARTIAL) search_flag |= SE_ECL_PARTIAL;
315     if (smod & SMOD_ANNTOT) search_flag |= SE_ECL_ANNULAR_TOTAL;
316   }
317   if (with_header) {
318     for (i = 0; i < argc; i++) {
319       do_printf(argv[i]);
320       do_printf(" ");
321     }
322     do_printf("\n");
323   }
324   iflag = (iflag & ~SEFLG_EPHMASK) | whicheph;
325   if (strpbrk(fmt, "SsQ") != NULL)
326     iflag |= SEFLG_SPEED;
327   if (*ephepath != '\0')
328     swe_set_ephe_path(ephepath);
329   else if (make_ephemeris_path(iflag, argv[0]) == ERR) {
330     iflag = (iflag & ~SEFLG_EPHMASK) | SEFLG_MOSEPH;
331     whicheph = SEFLG_MOSEPH;
332   }
333   if (whicheph & SEFLG_JPLEPH)
334     swe_set_jpl_file(fname);
335   serr[0] = serr_save[0] = serr_warn[0] = '\0';
336   if (begindate == NULL) {
337     do_printf("\nDate ?");
338     sdate[0] = '\0';
339     gets(sdate);
340   } else {
341     strcpy(sdate, begindate);
342     begindate = ".";  /* to exit afterwards */
343   }
344   sp = sdate;
345   if (*sp == 'j') {   /* it's a day number */
346     if ((sp2 = strchr(sp, ',')) != NULL)
347       *sp2 = '.';
348     sscanf(sp+1,"%lf", &tjd);
349     if (tjd < 2299160.5)
350       gregflag = SE_JUL_CAL;
351     else
352       gregflag = SE_GREG_CAL;
353     if (strstr(sp, "jul") != NULL)
354       gregflag = SE_JUL_CAL;
355     else if (strstr(sp, "greg") != NULL)
356       gregflag = SE_GREG_CAL;
357     swe_revjul(tjd, gregflag, &jyear, &jmon, &jday, &jut);
358   } else {
359     if (sscanf (sp, "%d%*c%d%*c%d", &jday,&jmon,&jyear) < 1) exit(1);
360     if ((long) jyear * 10000L + (long) jmon * 100L + (long) jday <
361 15821015L)
362       gregflag = SE_JUL_CAL;
363     else
364       gregflag = SE_GREG_CAL;
365     if (strstr(sp, "jul") != NULL)
366       gregflag = SE_JUL_CAL;
367     else if (strstr(sp, "greg") != NULL)
368       gregflag = SE_GREG_CAL;
369     jut = 0;
370     tjd = swe_julday(jyear,jmon,jday,jut,gregflag);
371   }
372   if (with_header) {
373     sprintf(sout, "begin date (dmy) %d.%d.%d\n", jday, jmon, jyear);
374     do_printf(sout);
375 
376   }
377   /*
378    * for local eclipses: set geographic position of observer
379    */
380   if (smod & (SMOD_LOCAL|SMOD_RISE|SMOD_METR)) {
381     sscanf(slon,"%lf", &a);
382     b = fmod(a * 10000, 100);
383     c = a - b / 10000;
384     c = fmod(c, 1) * 100;
385     geopos[0] = a - fmod( a, 1) + c / 60 + b / 3600;
386     sscanf(slat,"%lf", &a);
387     b = fmod(a * 10000, 100);
388     c = a - b / 10000;
389     c = fmod(c, 1) * 100;
390     geopos[1] = a - fmod( a, 1) + c / 60 + b / 3600;
391     swe_set_topo(geopos[0], geopos[1], 0);
392   }
393   t_ut = tjd;
394   for (ii = 0; ii < nstep; ii++) {
395     *sout = '\0';
396     if ((smod & SMOD_LUNAR) && (smod & SMOD_HOW)) {
397       if ((eclflag = swe_lun_eclipse_how(t_ut, whicheph, geopos, attr, serr)) ==
398 ERR) {
399         do_printf(serr);
400         exit(0);
401       } else {
402 	ecl_type = 0;
403         if (eclflag & SE_ECL_TOTAL) {
404           sprintf(sout, "total lunar eclipse: %f o/o \n", attr[0]);
405 	  ecl_type = ECL_LUN_TOTAL;
406         } else if (eclflag & SE_ECL_PARTIAL)  {
407           sprintf(sout, "partial lunar eclipse: %f o/o \n", attr[0]);
408 	  ecl_type = ECL_LUN_PARTIAL;
409         } else if (eclflag & SE_ECL_PENUMBRAL)  {
410           sprintf(sout, "penumbral lunar eclipse: %f o/o \n", attr[0]);
411 	  ecl_type = ECL_LUN_PENUMBRAL;
412         } else {
413           sprintf(sout, "no lunar eclipse \n");
414 	}
415         do_printf(sout);
416       }
417     }
418     if ((smod & SMOD_LUNAR) && ! (smod & SMOD_HOW)) {
419       if ((eclflag = swe_lun_eclipse_when(t_ut, whicheph, search_flag,
420                 tret, direction_flag, serr)) == ERR) {
421         do_printf(serr);
422         exit(0);
423       }
424       t_ut = tret[0];
425       if ((eclflag & SE_ECL_TOTAL)) {
426         strcpy(sout, "total   ");
427 	ecl_type = ECL_LUN_TOTAL;
428       }
429       if ((eclflag & SE_ECL_PENUMBRAL)) {
430         strcpy(sout, "penumb. ");
431 	ecl_type = ECL_LUN_PENUMBRAL;
432       }
433       if ((eclflag & SE_ECL_PARTIAL)) {
434         strcpy(sout, "partial ");
435 	ecl_type = ECL_LUN_PARTIAL;
436       }
437       strcat(sout, "lunar eclipse ");
438       swe_revjul(t_ut, gregflag, &jyear, &jmon, &jday, &jut);
439       if ((eclflag = swe_lun_eclipse_how(t_ut, whicheph, geopos, attr, serr)) ==
440 ERR) {
441         do_printf(serr);
442         exit(0);
443       }
444       sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s\t%f o/o\n",
445       /* eclipse times, penumbral, partial, total begin and end */
446               jday, jmon, jyear, hms(jut,0), attr[0]);
447 	sprintf(sout + strlen(sout), "  %s ", hms_from_tjd(tret[6]));
448         if (tret[2] != 0)
449 	  sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[2]));
450         else
451           strcat(sout, "   -         ");
452         if (tret[4] != 0)
453 	  sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[4]));
454         else
455           strcat(sout, "   -         ");
456         if (tret[5] != 0)
457 	  sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[5]));
458         else
459           strcat(sout, "   -         ");
460         if (tret[3] != 0)
461 	  sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[3]));
462         else
463           strcat(sout, "   -         ");
464 	sprintf(sout + strlen(sout), "%s\n", hms_from_tjd(tret[7]));
465       if (smod & SMOD_HOCAL) {
466 	int ihou, imin, isec, isgn;
467 	double dfrc;
468 	swe_split_deg(jut, SE_SPLIT_DEG_ROUND_MIN, &ihou, &imin, &isec, &dfrc, &isgn);
469 #if 0
470 	sprintf(sout, "\"%04d %02d %02d %02d.%02d %d\",\n", jyear, jmon, jday, ihou, imin, ecl_type);
471 #else
472 	sprintf(sout, "%f, %.0f, /* %04d %02d %02d %02d.%02d %d */,\n", t_ut, (double) ecl_type, jyear, jmon, jday, ihou, imin, ecl_type);
473 #endif
474       }
475       do_printf(sout);
476     }
477     if ((smod & SMOD_SOLAR) && (smod & SMOD_LOCAL)) {
478       if ((eclflag = swe_sol_eclipse_when_loc(t_ut, whicheph, geopos, tret,
479 attr, direction_flag, serr)) == ERR) {
480         do_printf(serr);
481         exit(0);
482       } else {
483 	AS_BOOL has_found = FALSE;
484         t_ut = tret[0];
485         if ((smod & SMOD_TOTAL) && (eclflag & SE_ECL_TOTAL)) {
486           strcpy(sout, "total   ");
487 	  has_found = TRUE;
488 	  ecl_type = ECL_SOL_TOTAL;
489 	}
490         if ((smod & SMOD_ANNULAR) && (eclflag & SE_ECL_ANNULAR)) {
491           strcpy(sout, "annular ");
492 	  has_found = TRUE;
493 	  ecl_type = ECL_SOL_ANNULAR;
494 	}
495         if ((smod & SMOD_PARTIAL) && (eclflag & SE_ECL_PARTIAL)) {
496           strcpy(sout, "partial ");
497 	  has_found = TRUE;
498 	  ecl_type = ECL_SOL_PARTIAL;
499 	}
500 	if (!has_found) {
501 	  ii--;
502 	} else {
503 	  i = do_calc(t_ut + swe_deltat(t_ut), SE_ECL_NUT, 0, x, serr);
504 	  swe_revjul(t_ut, gregflag, &jyear, &jmon, &jday, &jut);
505 	  sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s\t%fo/o\n", jday, jmon, jyear, hms(jut,0), attr[0]);
506 	  dt = (tret[3] - tret[2]) * 24 * 60;
507 	  sprintf(sout + strlen(sout), "\t%d min %4.2f sec\t",
508                 (int) dt, fmod(dt, 1) * 60);
509 	  if (eclflag & SE_ECL_1ST_VISIBLE)
510 	    sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[1]));
511 	  else
512 	    strcat(sout, "   -         ");
513 	  if (eclflag & SE_ECL_2ND_VISIBLE)
514 	    sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[2]));
515 	  else
516 	    strcat(sout, "   -         ");
517 	  if (eclflag & SE_ECL_3RD_VISIBLE)
518 	    sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[3]));
519 	  else
520 	    strcat(sout, "   -         ");
521 	  if (eclflag & SE_ECL_4TH_VISIBLE)
522 	    sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[4]));
523 	  else
524 	    strcat(sout, "   -         ");
525 #if 0
526 	  sprintf(sout + strlen(sout), "\t%d min %4.2f sec   %s %s %s %s",
527                 (int) dt, fmod(dt, 1) * 60,
528                 strcpy(s1, hms(fmod(tret[1] + 0.5, 1) * 24, 0)),
529                 strcpy(s3, hms(fmod(tret[2] + 0.5, 1) * 24, 0)),
530                 strcpy(s4, hms(fmod(tret[3] + 0.5, 1) * 24, 0)),
531                 strcpy(s2, hms(fmod(tret[4] + 0.5, 1) * 24, 0)));
532 #endif
533 	  strcat(sout, "\n");
534 	  do_printf(sout);
535 	}
536       }
537     }   /* endif search_local */
538     if ((smod & SMOD_SOLAR) && ! (smod & SMOD_LOCAL)) {
539     /* * global search for eclipses */
540       if ((eclflag = swe_sol_eclipse_when_glob(t_ut, whicheph, search_flag,
541                 tret, direction_flag, serr)) == ERR) {
542         do_printf(serr);
543         exit(0);
544       }
545       t_ut = tret[0];
546       if ((eclflag & SE_ECL_TOTAL)) {
547         strcpy(sout, "total   ");
548 	ecl_type = ECL_SOL_TOTAL;
549       }
550       if ((eclflag & SE_ECL_ANNULAR)) {
551         strcpy(sout, "annular ");
552 	ecl_type = ECL_SOL_ANNULAR;
553       }
554       if ((eclflag & SE_ECL_ANNULAR_TOTAL)) {
555         strcpy(sout, "ann-tot ");
556 	ecl_type = ECL_SOL_ANNULAR;	/* by Alois: what is this ? */
557       }
558       if ((eclflag & SE_ECL_PARTIAL)) {
559         strcpy(sout, "partial ");
560 	ecl_type = ECL_SOL_PARTIAL;
561       }
562       if ((eclflag & SE_ECL_NONCENTRAL) && !(eclflag & SE_ECL_PARTIAL))
563         strcat(sout, "non-central ");
564       swe_sol_eclipse_where(t_ut, whicheph, geopos, attr, serr);
565       swe_revjul(t_ut, gregflag, &jyear, &jmon, &jday, &jut);
566       sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s\t%f km\t%f o/o\n",
567                 jday, jmon, jyear, hms(jut,0), attr[3], attr[0]);
568       sprintf(sout + strlen(sout), "\t%s ", hms_from_tjd(tret[2]));
569       if (tret[4] != 0)
570 	  sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[4]));
571       else
572           strcat(sout, "   -         ");
573       if (tret[5] != 0)
574 	  sprintf(sout + strlen(sout), "%s ", hms_from_tjd(tret[5]));
575       else
576           strcat(sout, "   -         ");
577       sprintf(sout + strlen(sout), "%s\n", hms_from_tjd(tret[3]));
578 #if 0
579       swe_revjul(tret[1], gregflag, &jyear, &jmon, &jday, &jut);
580       sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s\t%f km\n",
581                 jday, jmon, jyear, hms(jut,0), attr[3]);
582 #endif
583       sprintf(sout + strlen(sout), "\t%s\t%s",
584                 strcpy(s1, dms(geopos[0], BIT_ROUND_MIN)),
585                 strcpy(s2, dms(geopos[1], BIT_ROUND_MIN)));
586       if (!(eclflag & SE_ECL_PARTIAL) && !(eclflag & SE_ECL_NONCENTRAL)) {
587         if ((eclflag = swe_sol_eclipse_when_loc(t_ut - 10, whicheph,
588 geopos, tret, attr, 0, serr)) == ERR) {
589           do_printf(serr);
590           exit(0);
591         }
592         if (fabs(tret[0] - t_ut) > 1)
593           do_printf("when_loc returns wrong date\n");
594         dt = (tret[3] - tret[2]) * 24 * 60;
595         sprintf(sout + strlen(sout), "\t%d min %4.2f sec\t",
596                 (int) dt, fmod(dt, 1) * 60);
597       }
598       strcat(sout, "\n");
599       if (smod & SMOD_HOCAL) {
600 	int ihou, imin, isec, isgn;
601 	double dfrc;
602 	swe_split_deg(jut, SE_SPLIT_DEG_ROUND_MIN, &ihou, &imin, &isec, &dfrc, &isgn);
603 #if 0
604 	sprintf(sout, "\"%04d %02d %02d %02d.%02d %d\",\n", jyear, jmon, jday, ihou, imin, ecl_type);
605 #else
606 	sprintf(sout, "%f, %.0f, /* %04d %02d %02d %02d.%02d %d */\n", t_ut, (double) ecl_type, jyear, jmon, jday, ihou, imin, ecl_type);
607 #endif
608       }
609       do_printf(sout);
610     }
611     if (smod & SMOD_RISE) {
612       if (swe_rise_trans(t_ut, ipl, starname, whicheph, SE_CALC_RISE, geopos, 1013.25, 10, &(tret[0]), serr) != OK) {
613 	do_printf(serr);
614 	exit(0);
615       }
616       if (swe_rise_trans(t_ut, ipl, starname, whicheph, SE_CALC_SET, geopos, 1013.25, 10, &(tret[1]), serr) != OK) {
617 	do_printf(serr);
618 	exit(0);
619       }
620       strcpy(sout, "rise     ");
621       if (tret[0] == 0) strcat(sout, "         -                     ");
622       else {
623 	swe_revjul(tret[0], gregflag, &jyear, &jmon, &jday, &jut);
624 	sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s    ",
625 		  jday, jmon, jyear, hms(jut,0));
626       }
627       strcat(sout, "set      ");
628       if (tret[1] == 0) strcat(sout, "         -                     \n");
629       else {
630 	swe_revjul(tret[1], gregflag, &jyear, &jmon, &jday, &jut);
631 	sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s\n",
632 		  jday, jmon, jyear, hms(jut,0));
633       }
634       do_printf(sout);
635     }
636     if (smod & SMOD_METR) {
637       if (swe_rise_trans(t_ut, ipl, starname, whicheph, SE_CALC_MTRANSIT, geopos, 1013.25, 10, &(tret[0]), serr) != OK) {
638 	do_printf(serr);
639 	exit(0);
640       }
641       if (swe_rise_trans(t_ut, ipl, starname, whicheph, SE_CALC_ITRANSIT, geopos, 1013.25, 10, &(tret[1]), serr) != OK) {
642 	do_printf(serr);
643 	exit(0);
644       }
645       strcpy(sout, "mtransit ");
646       if (tret[0] == 0) strcat(sout, "         -                     ");
647       else {
648 	swe_revjul(tret[0], gregflag, &jyear, &jmon, &jday, &jut);
649 	sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s    ",
650 		  jday, jmon, jyear, hms(jut,0));
651       }
652       strcat(sout, "itransit ");
653       if (tret[1] == 0) strcat(sout, "         -                     \n");
654       else {
655 	swe_revjul(tret[1], gregflag, &jyear, &jmon, &jday, &jut);
656 	sprintf(sout + strlen(sout), "%2d.%2d.%4d\t%s\n",
657 		  jday, jmon, jyear, hms(jut,0));
658       }
659       do_printf(sout);
660     }
661     if ((smod & (SMOD_RISE | SMOD_METR)) && tret[1] > 0)
662       t_ut = tret[1] + 0.1;
663     else
664       t_ut += direction;
665   }
666   if (*serr_warn != '\0') {
667     do_printf("\nwarning: ");
668     do_printf(serr_warn);
669     do_printf("\n");
670   }
671   /* close open files and free allocated space */
672   end_main:
673   swe_close();
674   return  OK;
675 }
676 
hms_from_tjd(double x)677 static char *hms_from_tjd(double x)
678 {
679   static char s[AS_MAXCH];
680   sprintf(s, "%s ", hms(fmod(x + 1000000.5, 1) * 24, 0));
681   return s;
682 }
683 
hms(double x,int32 iflag)684 static char *hms(double x, int32 iflag)
685 {
686   static char s[AS_MAXCH], s2[AS_MAXCH], *sp;
687   char *c = ODEGREE_STRING;
688   x += 0.5 / 36000.0; /* round to 0.1 sec */
689   strcpy(s, dms(x, iflag));
690   sp = strstr(s, c);
691   if (sp != NULL) {
692     *sp = ':';
693     if (strlen(ODEGREE_STRING) > 1)
694       strcpy(s2, sp + strlen(ODEGREE_STRING));
695       strcpy(sp + 1, s2);
696     *(sp + 3) = ':';
697     *(sp + 8) = '\0';
698   }
699   return s;
700 }
701 
dms(double xv,int32 iflg)702 static char *dms(double xv, int32 iflg)
703 {
704   int izod;
705   int32 k, kdeg, kmin, ksec;
706   char *c = ODEGREE_STRING;
707   char *sp, s1[50];
708   static char s[50];
709   int sgn;
710   *s = '\0';
711   if (iflg & SEFLG_EQUATORIAL)
712     c = "h";
713   if (xv < 0) {
714     xv = -xv;
715     sgn = -1;
716   } else
717     sgn = 1;
718   if (iflg & BIT_ROUND_MIN)
719     xv = swe_degnorm(xv + 0.5/60);
720   if (iflg & BIT_ROUND_SEC)
721     xv = swe_degnorm(xv + 0.5/3600);
722   if (iflg & BIT_ZODIAC) {
723     izod = (int) (xv / 30);
724     xv = fmod(xv, 30);
725     kdeg = (int32) xv;
726     sprintf(s, "%2d %s ", kdeg, zod_nam[izod]);
727   } else {
728     kdeg = (int32) xv;
729     sprintf(s, " %3d%s", kdeg, c);
730   }
731   xv -= kdeg;
732   xv *= 60;
733   kmin = (int32) xv;
734   if ((iflg & BIT_ZODIAC) && (iflg & BIT_ROUND_MIN))
735     sprintf(s1, "%2d", kmin);
736   else
737     sprintf(s1, "%2d'", kmin);
738   strcat(s, s1);
739   if (iflg & BIT_ROUND_MIN)
740     goto return_dms;
741   xv -= kmin;
742   xv *= 60;
743   ksec = (int32) xv;
744   if (iflg & BIT_ROUND_SEC)
745     sprintf(s1, "%2d\"", ksec);
746   else
747     sprintf(s1, "%2d", ksec);
748   strcat(s, s1);
749   if (iflg & BIT_ROUND_SEC)
750     goto return_dms;
751   xv -= ksec;
752   k = (int32) (xv * 10000);
753   sprintf(s1, ".%04d", k);
754   strcat(s, s1);
755 return_dms:;
756   if (sgn < 0) {
757     sp = strpbrk(s, "0123456789");
758     *(sp-1) = '-';
759   }
760   if (iflg & BIT_LZEROES) {
761     while ((sp = strchr(s+2, ' ')) != NULL) *sp = '0';
762   }
763   return(s);
764 }
765 
766 /* make_ephemeris_path().
767  * ephemeris path includes
768  *   current working directory
769  *   + program directory
770  *   + default path from swephexp.h on current drive
771  *   +                              on program drive
772  *   +                              on drive C:
773  */
make_ephemeris_path(long iflag,char * argv0)774 static int make_ephemeris_path(long iflag, char *argv0)
775 {
776   char path[AS_MAXCH], s[AS_MAXCH];
777   char *sp;
778   char *dirglue = DIR_GLUE;
779   size_t pathlen = 0;
780   /* moshier needs no ephemeris path */
781   if (iflag & SEFLG_MOSEPH)
782     return OK;
783   /* current working directory */
784   sprintf(path, ".%c", *PATH_SEPARATOR);
785   /* program directory */
786   sp = strrchr(argv0, *dirglue);
787   if (sp != NULL) {
788     pathlen = sp - argv0;
789     if (strlen(path) + pathlen < AS_MAXCH-1) {
790       strcpy(s, argv0);
791       *(s+pathlen) = '\0';
792       sprintf(path + strlen(path), "%s%c", s, *PATH_SEPARATOR);
793     }
794   }
795 #if MSDOS
796 {
797   char *cpos[20];
798   char s[2 * AS_MAXCH], *s1 = s + AS_MAXCH;
799   char *sp[3];
800   int i, j, np;
801   strcpy(s1, SE_EPHE_PATH);
802   np = cut_str_any(s1, PATH_SEPARATOR, cpos, 20);
803   /*
804    * default path from swephexp.h
805    * - current drive
806    * - program drive
807    * - drive C
808    */
809   *s = '\0';
810   /* current working drive */
811   sp[0] = getcwd(NULL, 0);
812   if (sp[0] == NULL) {
813     do_printf("error in getcwd()\n");
814     exit(1);
815   }
816   if (*sp[0] == 'C')
817     sp[0] = NULL;
818   /* program drive */
819   if (*argv0 != 'C' && (sp[0] == NULL || *sp[0] != *argv0))
820     sp[1] = argv0;
821   else
822     sp[1] = NULL;
823     /* drive C */
824   sp[2] = "C";
825   for (i = 0; i < np; i++) {
826     strcpy(s, cpos[i]);
827     if (*s == '.')	/* current directory */
828       continue;
829     if (s[1] == ':')  /* drive already there */
830       continue;
831     for (j = 0; j < 3; j++) {
832       if (sp[j] != NULL && strlen(path) + 2 + strlen(s) < AS_MAXCH-1)
833 	sprintf(path + strlen(path), "%c:%s%c", *sp[j], s, *PATH_SEPARATOR);
834     }
835   }
836 }
837 #else
838     if (strlen(path) + pathlen < AS_MAXCH-1)
839       strcat(path, SE_EPHE_PATH);
840 #endif
841   return OK;
842 }
843 
do_calc(double tjd,int ipl,long iflag,double * x,char * serr)844 static int do_calc(double tjd, int ipl, long iflag, double *x, char *serr)
845 {
846   return swe_calc(tjd, ipl, iflag, x, serr);
847 }
848 
do_printf(char * info)849 static void do_printf(char *info)
850 {
851 #ifdef _WINDOWS
852   fprintf(fp, info);
853 #else
854   printf(info);
855 #endif
856 }
857 
858 /**************************************************************
859 cut the string s at any char in cutlist; put pointers to partial strings
860 into cpos[0..n-1], return number of partial strings;
861 if less than nmax fields are found, the first empty pointer is
862 set to NULL.
863 More than one character of cutlist in direct sequence count as one
864 separator only! cut_str_any("word,,,word2",","..) cuts only two parts,
865 cpos[0] = "word" and cpos[1] = "word2".
866 If more than nmax fields are found, nmax is returned and the
867 last field nmax-1 rmains un-cut.
868 **************************************************************/
cut_str_any(char * s,char * cutlist,char * cpos[],int nmax)869 static int cut_str_any(char *s, char *cutlist, char *cpos[], int nmax)
870 {
871   int n = 1;
872   cpos [0] = s;
873   while (*s != '\0') {
874     if ((strchr(cutlist, (int) *s) != NULL) && n < nmax) {
875       *s = '\0';
876       while (*(s + 1) != '\0' && strchr (cutlist, (int) *(s + 1)) != NULL) s++;
877       cpos[n++] = s + 1;
878     }
879     if (*s == '\n' || *s == '\r') {	/* treat nl or cr like end of string */
880       *s = '\0';
881       break;
882     }
883     s++;
884   }
885   if (n < nmax) cpos[n] = NULL;
886   return (n);
887 }	/* cutstr */
888 
letter_to_ipl(int letter)889 static int letter_to_ipl(int letter)
890 {
891   if (letter >= '0' && letter <= '9')
892     return letter - '0' + SE_SUN;
893   if (letter >= 'A' && letter <= 'I')
894     return letter - 'A' + SE_MEAN_APOG;
895   if (letter >= 'J' && letter <= 'X')
896     return letter - 'J' + SE_CUPIDO;
897   switch (letter) {
898   case 'm': return SE_MEAN_NODE;
899   case 'n':
900   case 'o': return SE_ECL_NUT;
901   case 't': return SE_TRUE_NODE;
902   case 'f': return SE_FIXSTAR;
903   }
904   return -1;
905 }
906