home *** CD-ROM | disk | FTP | other *** search
/ Collection of Education / collectionofeducationcarat1997.iso / SCIENCE / EPHEM421.ZIP / MAIN.C < prev    next >
C/C++ Source or Header  |  1990-09-13  |  26KB  |  965 lines

  1. /* main "ephem" program. 
  2.  * -------------------------------------------------------------------
  3.  * Copyright (c) 1990 by Elwood Charles Downey
  4.  * 
  5.  * Permission is granted to make and distribute copies of this program
  6.  * free of charge, provided the copyright notice and this permission
  7.  * notice are preserved on all copies.  All other rights reserved.
  8.  * -------------------------------------------------------------------
  9.  * set options.
  10.  * init screen and circumstances.
  11.  * enter infinite loop updating screen and allowing operator input.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <signal.h>
  16. #include <setjmp.h>
  17. #include <math.h>
  18. #ifdef VMS
  19. #include <stdlib.h>
  20. #endif
  21. #include "astro.h"
  22. #include "circum.h"
  23. #include "screen.h"
  24.  
  25. extern char *strncpy();
  26. extern char *getenv();
  27.  
  28. /* shorthands for fields of a Now structure, now.
  29.  * first undo the ones for a Now pointer from circum.h.
  30.  */
  31. #undef mjd
  32. #undef lat
  33. #undef lng
  34. #undef tz
  35. #undef temp
  36. #undef pressure
  37. #undef height
  38. #undef epoch
  39. #undef tznm
  40.  
  41. #define mjd    now.n_mjd
  42. #define lat    now.n_lat
  43. #define lng    now.n_lng
  44. #define tz    now.n_tz
  45. #define temp    now.n_temp
  46. #define pressure now.n_pressure
  47. #define height    now.n_height
  48. #define epoch    now.n_epoch
  49. #define tznm    now.n_tznm
  50.  
  51. static jmp_buf fpe_err_jmp;    /* used to recover from SIGFPE */
  52. static char *cfgfile;        /* !0 if -c used */
  53. static char cfgdef[] = "ephem.cfg"; /* default configuration file name */
  54. static Now now;        /* where when and how, right now */
  55. static double tminc;    /* hrs to inc time by each loop; RTC means use clock */
  56. static int nstep;    /* steps to go before stopping */
  57. static int spause;    /* secs to pause between steps */
  58. static int optwi;    /* set when want to display dawn/dusk/len-of-night */
  59. static int oppl;    /* mask of (1<<planet) bits; set when want to show it */
  60.  
  61. main (ac, av)
  62. int ac;
  63. char *av[];
  64. {
  65.     void bye();
  66.     void on_fpe();
  67.     static char freerun[] =
  68.         "Running... press any key to stop to make changes.";
  69.     static char prmpt[] =
  70. "Move to another field, RETURN to change this field, ? for help, or q to run";
  71.     static char hlp[] =
  72.     "arrow keys move to field; any key stops running; ^d exits; ^l redraws";
  73.     int curr = R_NSTEP, curc = C_NSTEPV;    /* must start somewhere */
  74.     int sflag = 0;    /* not silent, by default */
  75.     int one = 1;    /* use a variable so optimizer doesn't get disabled */
  76.     int srchdone = 0; /* true when search funcs say so */
  77.     int newcir = 2;    /* set when circumstances change - means don't tminc */
  78.  
  79.     while ((--ac > 0) && (**++av == '-')) {
  80.         char *s;
  81.         for (s = *av+1; *s != '\0'; s++)
  82.         switch (*s) {
  83.         case 's': /* no credits "silent" (don't publish this) */
  84.             sflag++;
  85.             break;
  86.         case 'c': /* set name of config file to use */
  87.             if (--ac <= 0) usage("-c but no config file");
  88.             cfgfile = *++av;
  89.             break;
  90.         case 'd': /* set alternate database file name */
  91.             if (--ac <= 0) usage("-d but no database file");
  92.             obj_setdbfilename (*++av);
  93.             break;
  94.         default:
  95.             usage("Bad - option");
  96.         }
  97.     }
  98.  
  99.     if (!sflag)
  100.         credits();
  101.  
  102.     /* fresh screen.
  103.      * crack config file, THEN args so args may override.
  104.      */
  105.     c_erase();
  106.     read_cfgfile ();
  107.     read_fieldargs (ac, av);
  108.  
  109.     /* set up to clean up screen and tty if interrupted.
  110.      * also set up to stop if get floating error.
  111.      */
  112.     (void) signal (SIGINT, bye);
  113.     (void) signal (SIGFPE, on_fpe);
  114.  
  115.     /* update screen forever (until QUIT) */
  116.     while (one) {
  117.  
  118.         /* if get a floating error, longjmp() here and stop looping */
  119.         if (setjmp (fpe_err_jmp))
  120.         nstep = 0;
  121.         else {
  122.         nstep -= 1;
  123.  
  124.         /* recalculate everything and update all the fields */
  125.         redraw_screen (newcir);
  126.         mm_newcir (0);
  127.  
  128.         /* let searching functions change tminc and check for done */
  129.         srchdone = srch_eval (mjd, &tminc) < 0;
  130.         print_tminc(0);    /* to show possibly new search increment */
  131.  
  132.         /* update plot and listing files, now that all fields are up
  133.          * to date and search function has been evaluated.
  134.          */
  135.         plot();
  136.         listing();
  137.  
  138.         /* handle spause if we are really looping */
  139.         if (nstep > 0)
  140.             slp_sync();
  141.         }
  142.  
  143.         /* stop loop to allow op to change parameters:
  144.          * if a search evaluation converges (or errors out),
  145.          * or if steps are done,
  146.          * or if op hits any key.
  147.          */
  148.         newcir = 0;
  149.         if (srchdone || nstep <= 0 || (chk_char()==0 && read_char()!=0)) {
  150.         int fld;
  151.  
  152.         /* update screen with the current stuff if stopped during
  153.          * unattended plotting or listing since last redraw_screen()
  154.          * didn't.
  155.          */
  156.         if ((plot_ison() || listing_ison()) && nstep > 0)
  157.             redraw_screen (1);
  158.  
  159.         /* return nstep to default of 1 */
  160.         if (nstep <= 0) {
  161.             nstep = 1;
  162.             print_nstep (0);
  163.         }
  164.  
  165.         /* change fields until END.
  166.          * update all time fields if any are changed
  167.          * and print NEW CIRCUMSTANCES if any have changed.
  168.          * QUIT causes bye() to be called and we never return.
  169.          */
  170.         while(fld = sel_fld(curr,curc,alt_menumask()|F_CHG,prmpt,hlp)) {
  171.             if (chg_fld ((char *)0, fld)) {
  172.             mm_now (&now, 1);
  173.             mm_newcir(1);
  174.             newcir = 1;
  175.             }
  176.             curr = unpackr (fld);
  177.             curc = unpackc (fld);
  178.         }
  179.         if (nstep > 1)
  180.             f_prompt (freerun);
  181.         }
  182.  
  183.         /* increment time only if op didn't change cirumstances */
  184.         if (!newcir)
  185.         inc_mjd (&now, tminc);
  186.     }
  187.  
  188.     return (0);
  189. }
  190.  
  191. /* read in ephem's configuration file, if any.
  192.  * if errors in file, call usage() (which exits).
  193.  * if use -d, require it; else try $EPHEMCFG and ephem.cfg but don't
  194.  *   complain if can't find these since, after all, one is not required.
  195.  * skip blank lines and lines that begin with '#', '*', ' ' or '\t'.
  196.  */
  197. static
  198. read_cfgfile()
  199. {
  200.     char buf[128];
  201.     FILE *fp;
  202.     char *fn;
  203.  
  204.     /* open the config file. 
  205.      * only REQUIRED if used -d option.
  206.      * if succcessful, fn points to file name.
  207.      */
  208.     if (cfgfile) {
  209.         fn = cfgfile;
  210.         fp = fopen (fn, "r");
  211.         if (!fp) {
  212.         (void) sprintf (buf, "Can not open %s", fn);
  213.         usage (buf);    /* does not return */
  214.         }
  215.     } else {
  216.         fn = getenv ("EPHEMCFG");
  217.         if (!fn)
  218.         fn = cfgdef;
  219.     }
  220.     fp = fopen (fn, "r");
  221.     if (!fp)
  222.         return;    /* oh well; after all, it's not required */
  223.  
  224.     while (fgets (buf, sizeof(buf), fp)) {
  225.         switch (buf[0]) {
  226.         case '#': case '*': case ' ': case '\t': case '\n':
  227.         continue;
  228.         }
  229.         buf[strlen(buf)-1] = '\0';        /* discard trailing \n */
  230.         if (crack_fieldset (buf) < 0) {
  231.         char why[NC];
  232.         (void) sprintf (why, "Bad field spec in %s: %s\n", fn, buf);
  233.         usage (why);
  234.         }
  235.     }
  236.     (void) fclose (fp);
  237. }
  238.  
  239.  
  240. /* draw all the stuff on the screen, using the current menu.
  241.  * if how_much == 0 then just update fields that need it;
  242.  * if how_much == 1 then redraw all fields;
  243.  * if how_much == 2 then erase the screen and redraw EVERYTHING.
  244.  */
  245. redraw_screen (how_much)
  246. int how_much;
  247. {
  248.     if (how_much == 2)
  249.         c_erase();
  250.  
  251.     /* print the single-step message if this is the last loop */
  252.     if (nstep < 1)
  253.         print_updating();
  254.  
  255.     if (how_much == 2) {
  256.         mm_borders();
  257.         mm_labels();
  258.         srch_prstate(1);
  259.         plot_prstate(1);
  260.         listing_prstate(1);
  261.         alt_labels();
  262.     }
  263.  
  264.     /* if just updating changed fields while plotting or listing
  265.      * unattended then suppress most screen updates except
  266.      * always show nstep to show plot loops to go and
  267.      * always show tminc to show search convergence progress.
  268.      */
  269.     print_nstep(how_much);
  270.     print_tminc(how_much);
  271.     print_spause(how_much);
  272.     if (how_much == 0 && (plot_ison() || listing_ison()) && nstep > 0)
  273.         f_off();
  274.  
  275.     /* print all the time-related fields */
  276.     mm_now (&now, how_much);
  277.  
  278.     if (optwi)
  279.         mm_twilight (&now, how_much);
  280.  
  281.     /* print solar system body info */
  282.     print_bodies (how_much);
  283.  
  284.     f_on();
  285. }
  286.  
  287. /* clean up and exit.
  288.  */
  289. void
  290. bye()
  291. {
  292.     c_erase();
  293.     byetty();
  294.     exit (0);
  295. }
  296.  
  297. /* this gets called when a floating point error occurs.
  298.  * we force a jump back into main() with looping terminated.
  299.  */
  300. static
  301. void
  302. on_fpe()
  303. {
  304.     (void) signal (SIGFPE, on_fpe);
  305.     f_msg ("Floating point error has occurred - computations aborted.");
  306.     longjmp (fpe_err_jmp, 1);
  307. }
  308.  
  309. us