home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource1 / ast40dos / driver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-04  |  54.5 KB  |  1,757 lines

  1. /*
  2. ** Astrolog (Version 4.00) File: driver.c
  3. **
  4. ** IMPORTANT NOTICE: the graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1993 by Walter D. Pullen
  6. ** (cruiser1@stein.u.washington.edu). Permission is granted to freely
  7. ** use and distribute these routines provided one doesn't sell,
  8. ** restrict, or profit from them in any way. Modification is allowed
  9. ** provided these notices remain with any altered or edited versions of
  10. ** the program.
  11. **
  12. ** The main planetary calculation routines used in this program have
  13. ** been Copyrighted and the core of this program is basically a
  14. ** conversion to C of the routines created by James Neely as listed in
  15. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  16. ** available from Matrix Software. The copyright gives us permission to
  17. ** use the routines for personal use but not to sell them or profit from
  18. ** them in any way.
  19. **
  20. ** The PostScript code within the core graphics routines are programmed
  21. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  22. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  23. **
  24. ** The extended accurate ephemeris databases and formulas are from the
  25. ** calculation routines in the program "Placalc" and are programmed and
  26. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  27. ** (alois@azur.ch). The use of that source code is subject to
  28. ** regulations made by Astrodienst Zurich, and the code is not in the
  29. ** public domain. This copyright notice must not be changed or removed
  30. ** by any user of this program.
  31. **
  32. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  33. ** X Window graphics initially programmed 10/23-29/1991.
  34. ** PostScript graphics initially programmed 11/29-30/1992.
  35. ** Last code change made 12/31/1993.
  36. */
  37.  
  38. #include "astrolog.h"
  39.  
  40. char *filenamescreen = NULL, *filenameout, **extralines;
  41. int prog = FALSE, extracount = 0;
  42.  
  43.  
  44. /*
  45. ******************************************************************************
  46. ** Table Display Routines.
  47. ******************************************************************************
  48. */
  49.  
  50. /* A subprocedure of the credit displayed below, this prints out one line */
  51. /* of credit information on the screen. Given a string, it's displayed    */
  52. /* centered with left and right borders around it, in the given color.    */
  53.  
  54. #define CREDITWIDTH 74
  55.  
  56. void PrintW(string, col)
  57. char *string;
  58. int col;
  59. {
  60.   int i;
  61.  
  62.   if (!string) {
  63.  
  64.     /* Null string means print the top, bottom, or a separator row. */
  65.  
  66.     if (col < 0)
  67.       AnsiColor(RED);
  68.     printc(col ? (col > 0 ? BOXSW : BOXNW) : BOXJE);
  69.     PrintTab(BOXH, CREDITWIDTH);
  70.     printc(col ? (col > 0 ? BOXSE : BOXNE) : BOXJW);
  71.   } else {
  72.     i = StringLen(string);
  73.     printc(BOXV);
  74.     PrintTab(' ', (CREDITWIDTH-i)/2 + (i&1));
  75.     AnsiColor(col);
  76.     fprintf(S, "%s", string);
  77.     PrintTab(' ', (CREDITWIDTH-i)/2);
  78.     AnsiColor(RED);
  79.     printc(BOXV);
  80.   }
  81.   printl();
  82. }
  83.  
  84.  
  85. /* Display a list of credits showing those who helped create the various  */
  86. /* parts of Astrolog, as well as important copyright and version info, as */
  87. /* displayed with the -Hc switch.                                         */
  88.  
  89. void DisplayCredits()
  90. {
  91.   char string[STRING];
  92.  
  93.   PrintW(NULL, -1);
  94.   sprintf(string, "%s version %s", appname, VERSION);
  95.   PrintW(string, WHITE);
  96.   sprintf(string, "As of %s", DATE);
  97.   PrintW(string, LTGRAY);
  98.   PrintW("By Walter D. Pullen (cruiser1@stein.u.washington.edu)", CYAN);
  99.   PrintW(NULL, 0);
  100.   PrintW("Main planetary calculation formulas were converted from", GREEN);
  101.   PrintW(
  102.     "routines by James Neely, as listed in 'Manual of Computer Programming",
  103.     GREEN);
  104.   PrintW(
  105.     "for Astrologers' by Michael Erlewine, available from Matrix Software.",
  106.     GREEN);
  107.   PrintW("PostScript graphics routines by Brian D. Willoughby", YELLOW);
  108.   PrintW(
  109.     "Extended ephemeris calculation and formulas are by Alois Treindl,",
  110.     MAGENTA);
  111.   PrintW(
  112.     "as in the package 'Placalc', available from Astrodienst AG.", MAGENTA);
  113.   PrintW(
  114.     "IMPORTANT: Astrolog is 'freeware', but is copyrighted and not in public",
  115.     LTGRAY);
  116.   PrintW(
  117.     "domain. Permission is granted to freely use and distribute these",
  118.     LTGRAY);
  119.   PrintW(
  120.     "routines provided one does not sell, restrict, or profit from the",
  121.     LTGRAY);
  122.   PrintW(
  123.     "program or its output in any way. Modification is allowed provided",
  124.     LTGRAY);
  125.   PrintW(
  126.     "these exact notices remain with any altered or edited versions of the",
  127.     LTGRAY);
  128.   PrintW(
  129.     "program. These conditions are true of both the program in whole and of",
  130.     LTGRAY);
  131.   PrintW(
  132.     "all parts by any individual author. Violators are subject to copyright",
  133.     LTGRAY);
  134.   PrintW(
  135.     "law penalties, and negative karmic debts to aforementioned contributors.",
  136.     LTGRAY);
  137.   PrintW(NULL, 0);
  138.   PrintW(
  139.     "Special thanks to all those unmentioned, seen and unseen, who have",
  140.      BLUE);
  141.   PrintW(
  142.     "pointed out problems, suggested featues, and sent many positive vibes!",
  143.     BLUE);
  144.   PrintW(NULL, 1);
  145.   AnsiColor(DEFAULT);
  146. }
  147.  
  148.  
  149. /* Print out a command switch or keypress info line to the screen, as done  */
  150. /* with the -H switch or 'H' key in a graphic window. This is just printing */
  151. /* out the string, except in Ansi mode we set the proper colors: Red for    */
  152. /* header lines, Green for individual switches or keys, and White for the   */
  153. /* rest of the line telling what it does. We also prefix each switch with   */
  154. /* either Unix's '-' or PC's '/', whichever is appropriate for the system.  */
  155.  
  156. void Prints(string)
  157. char *string;
  158. {
  159.   int dash;
  160.   char c;
  161.  
  162.   dash = string[1];
  163.   if (*string != ' ')
  164.     AnsiColor(RED);
  165.   else if (dash != ' ')
  166.     AnsiColor(dash == 'P' || string[3] == ' ' || string[3] == ':' ?
  167.       GREEN : DKGREEN);
  168.   else
  169.     AnsiColor(DEFAULT);
  170.   while ((c = *string) && c != ':' &&
  171.     (dash != 'P' || (c != ' ' || *(string+1) != 't'))) {
  172.     if (c != '_')
  173.       printc(c);
  174.     else
  175.       printc(DASH);
  176.     string++;
  177.   }
  178.   if (*string)
  179.     printc(*string++);
  180.   AnsiColor(DEFAULT);
  181.   while (c = *string) {
  182.     if (c != '_')
  183.       printc(c);
  184.     else
  185.       printc(DASH);
  186.     string++;
  187.   }
  188.   printl();
  189. }
  190.  
  191.  
  192. /* Print a list of every command switch that can be passed to the program, */
  193. /* and a description of what it does. This is what the -H switch prints.   */
  194.  
  195. void DisplaySwitches()
  196. {
  197.   char string[STRING];
  198.  
  199.   sprintf(string, "%s (version %s) command switches:", appname, VERSION);
  200.   Prints(string);
  201.   Prints(" _H: Display this help list.");
  202.   Prints(" _Hc: Display program credits and copyrights.");
  203.   Prints(" _H0: Display names of zodiac signs and houses.");
  204.   Prints(" _O: Display available planets and other celestial objects.");
  205.   Prints(" _O0: Like _O but ignore object restrictions.");
  206.   Prints(" _A: Display available aspects, their angles, and present orbs.");
  207. #ifdef INTERPRET
  208.   Prints(" _I0: Display meanings of signs, houses, planets, and aspects.");
  209. #endif
  210.   Prints(" _Q: Prompt for more command switches after display finished.");
  211. #ifdef SWITCHES
  212.   Prints(" _Q0: Like _Q but prompt for additional switches on startup.");
  213. #endif
  214.   Prints("\nSwitches which determine the type of chart to display:");
  215.   Prints(" _v: Display list of object positions (chosen by default).");
  216.   Prints(" _v0: Like _v but express velocities relative to average speed.");
  217.   Prints(" _w [<rows>]: Display chart in a graphic house wheel format.");
  218.   Prints(" _w0 [..]: Like _w but reverse order of objects in houses 4..9.");
  219.   Prints(" _g: Display aspect and midpoint grid among planets.");
  220.   Prints(" _g0: Like _g but flag aspect configurations (e.g. Yod's) too.");
  221.   Prints(" _g0: For comparison charts, show midpoints instead of aspects.");
  222.   Prints(" _ga: Like _g but indicate applying instead of difference orbs.");
  223.   Prints(" _m: Display all object midpoints in sorted zodiac order.");
  224.   Prints(" _m0: Like _m but list aspects ordered by influence instead.");
  225.   Prints(" _m[0]a: Like _m0 but indicate applying and separating orbs.");
  226.   Prints(" _Z: Display planet locations with respect to the local horizon.");
  227. #ifdef GRAPH
  228.   Prints(" _Z0: For graphics charts, like _Z but have a polar center.");
  229. #endif
  230.   Prints(" _Zd: Search day for object local rising and setting times.");
  231.   Prints(" _S: Display x,y,z coordinate positions of planets in space.");
  232.   Prints(" _j: Display astrological influences of each object in chart.");
  233.   Prints(" _j0: Like _j but include influences of each zodiac sign as well.");
  234.   Prints(" _L [<step>]: Display astro-graph locations of planetary angles.");
  235.   Prints(" _L0 [..]: Like _L but display list of latitude crossings too.");
  236.   Prints(" _K: Display a calendar for given month.");
  237.   Prints(" _Ky: Like _K but display a calendar for the entire year.");
  238.   Prints(" _d: Print all aspects and changes occurring in a day.");
  239.   Prints(" _dm: Like _d but print all aspects for the entire month.");
  240.   Prints(" _dp <month> <year>: Print aspects within progressed chart.");
  241.   Prints(" _dpy <year>: Like _dp but search for aspects within entire year.");
  242.   Prints(" _D: Like _d but display aspects by influence instead of time.");
  243.   Prints(" _E: Display planetary ephemeris for given month.");
  244.   Prints(" _Ey: Display planetary ephemeris for the entire year.");
  245.   Prints(" _e: Print all charts together (i.e. _v_w_g0_m_Z_S_j0_L0_K_d_D_E).");
  246.   Prints(
  247.     " _t <month> <year>: Compute all transits to natal planets in month.");
  248.   Prints(
  249.     " _tp <month> <year>: Compute progressions in month for chart.");
  250.   Prints(" _t[p]y: <year>: Compute transits/progressions for entire year.");
  251. #ifdef TIME
  252.   Prints(" _t[py]n: Compute transits to natal planets for current time now.");
  253. #endif
  254.   Prints(" _T <month> <day> <year>: Display transits ordered by influence.");
  255.   Prints(" _Tp <month> <day> <year>: Print progressions instead of transits.");
  256. #ifdef TIME
  257.   Prints(" _T[p]n: Display transits ordered by influence for current date.");
  258. #endif
  259. #ifdef INTERPRET
  260.   Prints(" _I [<columns>]: Print interpretation of selected charts.");
  261. #endif
  262.   Prints("\nSwitches which affect how the chart parameters are obtained:");
  263. #ifdef TIME
  264.   Prints(" _n: Compute chart for this exact moment using current time.");
  265.   Prints(" _n[d,m,y]: Compute chart for start of current day, month, year.");
  266. #endif
  267.   Prints(" _a <month> <date> <year> <time> <zone> <long> <lat>:");
  268.   Prints("     Compute chart automatically given specified data.");
  269.   Prints(" _z: Assume Daylight time (change default zone appropriately).");
  270.   Prints(" _z <zone>: Change the default time zone (for _d_q_T_E options).");
  271.   Prints(" _l <long> <lat>: Change the default longitude & latitude.");
  272.   Prints(" _q <month> <date> <year> <time>: Compute chart with defaults.");
  273.   Prints(" _qd <month> <date> <year>: Compute chart for noon on date.");
  274.   Prints(" _qm <month> <year>: Compute chart for first of month.");
  275.   Prints(" _qy <year>: Compute chart for first day of year.");
  276.   Prints(" _qj <day>: Compute chart for time of specified Julian day.");
  277.   Prints(" _i <file>: Compute chart based on info in file.");
  278.   Prints(" _o <file> [..]: Write parameters of current chart to file.");
  279.   Prints(" _o0 <file> [..]: Like _o but output planet/house positions.");
  280.   Prints(" _os <file>: Redirect output of text charts to file.");
  281.   Prints("\nSwitches which affect what information is used in a chart:");
  282.   Prints(" _R [<obj1> [<obj2> ..]]: Restrict specific bodies from displays.");
  283.   Prints(" _R0 [<obj1> ..]: Like _R but restrict everything first.");
  284.   Prints(" _R1 [<obj1> ..]: Like _R0 but unrestrict and show all objects.");
  285.   Prints(" _R[C,u,U]: Restrict all minor cusps, all uranians, or stars.");
  286.   Prints(" _RT[0,1,C,u,U] [..]: Restrict transiting planets in _T lists.");
  287.   Prints(" _C: Include non-angular house cusps in charts.");
  288.   Prints(" _u: Include transneptunian/uranian bodies in charts.");
  289.   Prints(" _U: Include locations of fixed background stars in charts.");
  290.   Prints(" _U[z,l,n,b]: Order by azimuth, altitude, name, or brightness.");
  291.   Prints(" _A <0-18>: Specify the number of aspects to use in charts.");
  292.   Prints(" _Ao <aspect> <orb>: Specify maximum orb for an aspect.");
  293.   Prints(" _Am <planet> <orb>: Specify maximum orb allowed to a planet.");
  294.   Prints(" _Ad <planet> <orb>: Specify orb addition given to a planet.");
  295.   Prints("\nSwitches which affect how a chart is computed:");
  296. #ifdef PLACALC
  297.   Prints(" _b: Use ephemeris files for more accurate location computations.");
  298.   Prints(" _b0: Like _b but display locations to the nearest second too.");
  299. #endif
  300.   Prints(" _c <value>: Select a different default system of houses.");
  301.   Prints("     (0 = Placidus, 1 = Koch, 2 = Equal, 3 = Campanus,");
  302.   Prints("     4 = Meridian, 5 = Regiomontanus, 6 = Porphyry, 7 = Morinus,");
  303.   Prints("     8 = Topocentric, 9 = None.)");
  304.   Prints(" _s: Compute a sidereal instead of the normal tropical chart.");
  305.   Prints(" _s0: Display locations as right ascension instead of degrees.");
  306.   Prints(" _h [<objnum>]: Compute positions centered on specified object.");
  307.   Prints(" _p <month> <day> <year>: Cast 2ndary progressed chart for date.");
  308.   Prints(" _p0 <month> <day> <year>: Cast solar arc chart for date.");
  309. #ifdef TIME
  310.   Prints(" _p[0]n: Cast progressed chart based on current date now.");
  311. #endif
  312.   Prints(" _pd <days>: Set no. of days to progress / day (default 365.25).");
  313.   Prints(" _x <1-360>: Cast harmonic chart based on specified factor.");
  314.   Prints(" _1 [<objnum>]: Cast chart with specified object on Ascendant.");
  315.   Prints(" _2 [<objnum>]: Cast chart with specified object on Midheaven.");
  316.   Prints(" _3: Display objects in their zodiac decan positions.");
  317.   Prints(" _f: Display houses as sign positions (flip them).");
  318.   Prints(" _G: Compute houses based on geographic location only.");
  319.   Prints(" _F <objnum> <sign> <deg>: Force object's position to be value.");
  320.   Prints(" _+ [<days>]: Cast chart for specified no. of days in the future.");
  321.   Prints(" _- [<days>]: Cast chart for specified no. of days in the past.");
  322.   Prints(" _+[m,y] [<value>]: Cast chart for no. of months/years in future.");
  323.   Prints("\nSwitches for relationship and comparison charts:");
  324.   Prints(" _r <file1> <file2>: Compute a relationship synastry chart.");
  325.   Prints(" _rc <file1> <file2>: Compute a composite chart.");
  326.   Prints(" _rm <file1> <file2>: Compute a time space midpoint chart.");
  327.   Prints(" _rd <file1> <file2>: Print time span between files' dates.");
  328. #ifdef BIORHYTHM
  329.   Prints(" _rb <file1> <file2>: Display biorhythm for file1 at time file2.");
  330. #endif
  331.   Prints(" _r0 <file1> <file2>: Keep the charts separate in comparison.");
  332.   Prints(" _rp <file1> <file2>: Like _r0 but do file1 with progr. to file2.");
  333. #ifdef TIME
  334.   Prints(" _y <file>: Display current house transits for particular chart.");
  335. #ifdef BIORHYTHM
  336.   Prints(" _y[b,d,p] <file>: Print biorhythm/datediff for current time now.");
  337. #endif
  338. #endif /* TIME */
  339.   Prints("\nSwitches to access graphics options:");
  340.   Prints(" _k: Display text charts using Ansi characters and color.");
  341. #ifdef MSG
  342.   Prints(" _V: <25,43,50>: Start up with text mode set to number of rows.");
  343. #endif
  344.  
  345.   /* If graphics features are compiled in, call an additional procedure to */
  346.   /* display the command switches offered dealing with the graphics stuff. */
  347.  
  348. #ifdef GRAPH
  349.   XDisplaySwitches();
  350. #endif
  351. }
  352.  
  353.  
  354. /* Print out a list of the various objects - planets, asteroids, house     */
  355. /* cusps, stars - recognized by the program, and their index values. This  */
  356. /* is displayed when the -O switch is invoked. For some objects, display   */
  357. /* additional information, e.g. ruling signs for planets, brightnesses and */
  358. /* positions in the sky for fixed stars, etc.                              */
  359.  
  360. void PrintObjects(all)
  361. int all;
  362. {
  363.   int i, j;
  364.   real Off;
  365.  
  366.   if (!(operation & DASHC))
  367.     for (i = C_LO; i <= C_HI; i++)    /* Set up restrictions properly: Minor */
  368.       ignore[i] = TRUE;               /* cusps and uranians included only if */
  369.   if (!(operation & DASHu))           /* -C and -u switches are in effect.   */
  370.     for (i = U_LO; i <= U_HI; i++)
  371.       ignore[i] = TRUE;
  372.   fprintf(S, "%s planets and objects:\n", appname);
  373.   fprintf(S, "No. Name       Rule Co-Rule Fall Co-Fall Exalt Debilitate\n\n");
  374.   for (i = 1; i <= BASE; i++) if (all || !ignore[i]) {
  375.     AnsiColor(objectansi[i]);
  376.     fprintf(S, "%2d %-12s", i, objectname[i]);
  377.     if (i <= OBJECTS) {                      /* Print rulerships, etc */
  378.       if (ruler1[i]) {                       /* for the planets.      */
  379.         j = ruler2[i];
  380.         fprintf(S, "%c%c%c  %c%c%c     ", SIGNAM(ruler1[i]),
  381.           j ? signname[j][0] : ' ', j ? signname[j][1] : ' ',
  382.           j ? signname[j][2] : ' ');
  383.         fprintf(S, "%c%c%c  %c%c%c     ", SIGNAM(Mod12(ruler1[i]+6)),
  384.           j ? signname[Mod12(j+6)][0] : ' ',
  385.           j ? signname[Mod12(j+6)][1] : ' ',
  386.           j ? signname[Mod12(j+6)][2] : ' ');
  387.         fprintf(S, "%c%c%c   %c%c%c", SIGNAM(exalt[i]),
  388.           SIGNAM(Mod12(exalt[i]+6)));
  389.       }
  390.     } else {
  391.       if (ruler1[i]) {
  392.         fprintf(S, "%c%c%c          %c%c%c", SIGNAM(ruler1[i]),
  393.           SIGNAM(Mod12(ruler1[i]+6)));
  394.         fprintf(S, "          %c%c%c   %c%c%c", SIGNAM(exalt[i]),
  395.           SIGNAM(Mod12(exalt[i]+6)));
  396.       }
  397.       if (i <= C_HI)
  398.         fprintf(S, "  Minor House Cusp #%d", i-OBJECTS);
  399.       else
  400.         fprintf(S, "  Uranian #%d", i-U_LO+1);
  401.     }
  402.     printl();
  403.   }
  404.  
  405.   /* Now, if -U in effect, read in and display stars in specified order. */
  406.  
  407.   if (all || universe) {
  408.     Off = ProcessInput(TRUE);
  409.     ComputeStars(operation & DASHs ? 0.0 : -Off);
  410.     for (i = S_LO; i <= S_HI; i++) if (all | !ignore[i]) {
  411.       j = BASE+starname[i-BASE];
  412.       AnsiColor(objectansi[j]);
  413.       fprintf(S, "%2d %-12s", i, objectname[j]);
  414.       fprintf(S, "Star #%2d   ", i-BASE);
  415.       PrintZodiac(planet[j]);
  416.       fprintf(S, "    ");
  417.       PrintAltitude(planetalt[j]);
  418.       fprintf(S, " %5.2f\n", starbright[j-BASE]);
  419.     }
  420.   }
  421.   AnsiColor(DEFAULT);
  422. }
  423.  
  424.  
  425. /* Print out a list of all the aspects recognized by the program, and info  */
  426. /* about them: their names, index numbers, degree angles, present orbs, and */
  427. /* the description of their glyph. This gets displayed when the -A switch   */
  428. /* is invoked (without any argument).                                       */
  429.  
  430. void PrintAspects()
  431. {
  432.   int i;
  433.  
  434.   fprintf(S, "%s aspects:\nNo. Name         Abbrev. Angle    Orb", appname);
  435.   fprintf(S, "          Description of glyph\n\n");
  436.   for (i = 1; i <= ASPECTS; i++) {
  437.     AnsiColor(aspectansi[i]);
  438.     fprintf(S, "%2d %-15s(%s) %6.2f +/- %1.0f degrees - %s\n",
  439.       i, aspectname[i], aspectabbrev[i],
  440.       aspectangle[i], aspectorb[i], aspectglyph[i]);
  441.   }
  442.   AnsiColor(DEFAULT);
  443. }
  444.  
  445.  
  446. /* Print out a list of the 12 signs and houses of the zodiac, and their    */
  447. /* standard and traditional names, as done when the -H0 switch is invoked. */
  448.  
  449. void PrintSigns()
  450. {
  451.   int i;
  452.  
  453.   fprintf(S, "%s signs and houses:\n", appname);
  454.   fprintf(S, "Sign        English name      House Traditional name\n\n");
  455.   for (i = 1; i <= SIGNS; i++) {
  456.     AnsiColor(signansi(i));
  457.     fprintf(S, "%-12sthe %-14s%2d%s  House of %s\n",
  458.       signname[i], signenglish[i], i, post[i], housetradition[i]);
  459.   }
  460.   AnsiColor(DEFAULT);
  461. }
  462.  
  463.  
  464. /*
  465. ******************************************************************************
  466. ** File IO Routines.
  467. ******************************************************************************
  468. */
  469.  
  470. /* Print an error message signifying that a particular option in the        */
  471. /* defaults file is invalid. This is a subprocedure of InputDefaults below. */
  472.  
  473. void BadDef(option)
  474. char *option;
  475. {
  476.   char string[STRING];
  477.  
  478.   sprintf(string, "Bad default %s in %s.", option, DEFAULT_INFOFILE);
  479.   PrintError(string);
  480. }
  481.  
  482.  
  483. /* Read in a set of default program values used in the program, such as */
  484. /* present location, time zone, the system of houses to use, the number */
  485. /* of aspects and what orbs to use, and so on. These values are always  */
  486. /* read in at the beginning of program execution.                       */
  487.  
  488. /* The NEXTDEFAULT macro means to skip all comments in the file until we   */
  489. /* reach the beginning of the next set of data, delimited with a '=' sign. */
  490.  
  491. #define NEXTDEFAULT while(getc(data) != '=');
  492.  
  493. bool InputDefaults()
  494. {
  495.   FILE *data;
  496.   char name[STRING];
  497.   int i, j;
  498.  
  499.   filename = DEFAULT_INFOFILE;     /* First lets open the info file.      */
  500.   data = fopen(filename, "r");     /* Look for file in current directory. */
  501.   if (data == NULL) {
  502.     sprintf(name, "%s%s", DEFAULT_DIR, filename);   /* Look for file in   */
  503.     data = fopen(name, "r");                        /* default directory. */
  504.     if (data == NULL)          /* If file not found anywhere, then forget */
  505.       return FALSE;            /* it and use the compile time defaults.   */
  506.   }
  507.   NEXTDEFAULT; fscanf(data, "%s", name);
  508.   if (StringCmp(name, VERSION) != 0) {
  509.     sprintf(name, "%s: Bad information in default parameter file '%s'.",
  510.       appname, filename);
  511.     PrintWarning(name);
  512.     PrintWarning(
  513.       "Delete this file or obtain one compatible with current version.");
  514.     Terminate(_ERROR);
  515.     return FALSE;
  516.   }
  517.   NEXTDEFAULT; fscanf(data, "%lf", &defzone);        /* Time zone    */
  518.   if (!IsValidZon(defzone))
  519.     BadDef("Time Zone");
  520.   NEXTDEFAULT; fscanf(data, "%lf", &deflong);        /* Longitude    */
  521.   if (!IsValidLon(deflong))
  522.     BadDef("Longitude");
  523.   NEXTDEFAULT; fscanf(data, "%lf", &deflat);         /* Latitude     */
  524.   if (!IsValidLat(deflat))
  525.     BadDef("Latitude");
  526.   NEXTDEFAULT; fscanf(data, "%d",  &aspects);        /* # of aspects */
  527.   if (!IsValidAspect(aspects))
  528.     BadDef("Aspect Number");
  529.   NEXTDEFAULT; fscanf(data, "%d",  &housesystem);    /* House type   */
  530.   if (!IsValidSystem(housesystem))
  531.     BadDef("House System");
  532.   NEXTDEFAULT; fscanf(data, "%d",  &ansi);           /* Ansi text?     */
  533.   NEXTDEFAULT; fscanf(data, "%d",  &divisions);      /* For -d and -T  */
  534.   if (!IsValidDivision(divisions))
  535.     BadDef("Searching Divisions");
  536.   NEXTDEFAULT; fscanf(data, "%d",  &placalc);        /* Use ephemeris  */
  537.   NEXTDEFAULT; fscanf(data, "%d",  &seconds);        /* Zodiac seconds */
  538.   seconds = seconds != 0;
  539.   NEXTDEFAULT; fscanf(data, "%d",  &wheelrows);      /* For -w charts  */
  540.   if (!IsValidWheel(wheelrows))
  541.     BadDef("Wheel Rows");
  542.   NEXTDEFAULT; fscanf(data, "%d",  &screenwidth);    /* For -I charts  */
  543.   if (!IsValidScreen(screenwidth))
  544.     BadDef("Screen Width");
  545.   NEXTDEFAULT; fscanf(data, "%d",  &eurodate);       /* D/M/Y vs. M/D/Y?     */
  546.   NEXTDEFAULT; fscanf(data, "%d",  &eurotime);       /* 24hr vs. 12hr clock? */
  547.   NEXTDEFAULT; fscanf(data, "%d",  &smartcusp);      /* Logical -C displays? */
  548.   NEXTDEFAULT; fscanf(data, "%d",  &column80);       /* Clip text at col 80? */
  549.   NEXTDEFAULT;
  550.   for (i = 1; i <= BASE; i++) {            /* Object restrictions         */
  551.     fscanf(data, "%d", &j);
  552.     ignore[i] = j > 0;
  553.   }
  554.   NEXTDEFAULT;
  555.   for (i = 1; i <= BASE; i++) {            /* Transit object restrictions */
  556.     fscanf(data, "%d", &j);
  557.     ignore2[i] = j > 0;
  558.   }
  559.   NEXTDEFAULT;
  560.   fscanf(data, "%d", &j); ignore[0]  = j > 0;    /* Restrict sign changes */
  561.   NEXTDEFAULT;
  562.   fscanf(data, "%d", &j); ignore2[0] = j > 0;    /* Restrict dir. changes */
  563.   NEXTDEFAULT;
  564.   for (i = 1; i <= ASPECTS; i++)           /* Orbs for aspects  */
  565.     fscanf(data, "%lf", &aspectorb[i]);
  566.   NEXTDEFAULT;
  567.   for (i = 1; i <= BASE; i++)              /* Orbs for planets  */
  568.     fscanf(data, "%lf", &planetorb[i]);
  569.   NEXTDEFAULT;
  570.   for (i = 1; i <= BASE; i++)              /* Extra planet orbs */
  571.     fscanf(data, "%lf", &planetadd[i]);
  572.   NEXTDEFAULT; fscanf(data, "%lf", &objectinf[BASE+1]);     /* Rules sign  */
  573.   NEXTDEFAULT; fscanf(data, "%lf", &objectinf[BASE+2]);     /* Exalts in   */
  574.   NEXTDEFAULT; fscanf(data, "%lf",  &houseinf[SIGNS+1]);    /* Rules house */
  575.   NEXTDEFAULT; fscanf(data, "%lf",  &houseinf[SIGNS+2]);    /* Exalts in   */
  576.   NEXTDEFAULT;
  577.   for (i = 1; i <= BASE; i++)
  578.     fscanf(data, "%lf", &objectinf[i]);    /* Influence of each object */
  579.   for (i = 1; i <= SIGNS; i++)
  580.     fscanf(data, "%lf", &houseinf[i]);     /* Influence of each house  */
  581.   for (i = 1; i <= ASPECTS; i++)
  582.     fscanf(data, "%lf", &aspectinf[i]);    /* Influence of each aspect */
  583.   NEXTDEFAULT;
  584.   for (i = 1; i <= BASE; i++)
  585.     fscanf(data, "%lf", &transitinf[i]);   /* Each object when transiting */
  586.  
  587.   /* Graphics defaults begin here. These are only read in with certain     */
  588.   /* compile options. They need to be read in last for file compatibility. */
  589.  
  590. #ifdef GRAPH
  591.   NEXTDEFAULT; fscanf(data, "%d", &chartx);       /* Horizontal graph size */
  592.   if (!IsValidGraphx(chartx))
  593.     BadDef("Horizontal Bitmap Size");
  594.   NEXTDEFAULT; fscanf(data, "%d", &charty);       /* Vertical graph size   */
  595.   if (!IsValidGraphx(chartx))
  596.     BadDef("Vertical Bitmap Size");
  597.   NEXTDEFAULT; fscanf(data, "%d", &gridobjects);  /* Aspect grid cells     */
  598.   if (!IsValidGrid(gridobjects))
  599.     BadDef("Aspect Grid Cells");
  600.   NEXTDEFAULT;
  601.   do {
  602.     bitmapmode = getc(data);
  603.   } while (bitmapmode <= ' ');
  604.   if (!IsValidBmpmode(bitmapmode))                /* Bitmap file mode        */
  605.     BadDef("Bitmap File Mode");
  606.   NEXTDEFAULT; fscanf(data, "%d", &xfont);        /* Font simulation flag    */
  607. #ifdef MSG
  608.   NEXTDEFAULT; fscanf(data, "%d", &hiresmode);    /* Normal graphics mode    */
  609.   if (!IsValidResmode(hiresmode))
  610.     BadDef("High Resolution Size");
  611.   NEXTDEFAULT; fscanf(data, "%d", &loresmode);    /* Animation graphics mode */
  612.   if (!IsValidResmode(loresmode))
  613.     BadDef("Low Resolution Size");
  614. #endif
  615. #endif /* GRAPH */
  616.   fclose(data);
  617.   return TRUE;
  618. }
  619.  
  620.  
  621. /* Take the current chart information, and write it out to the file   */
  622. /* as indicated by the -o switch. This is only executed at the end of */
  623. /* program execution if the -o switch is in effect.                   */
  624.  
  625. bool OutputData()
  626. {
  627.   char string[STRING];
  628.   FILE *data;
  629.   int i, j;
  630.   real k;
  631.  
  632.   data = fopen(filenameout, "w");    /* Create and open the file for output. */
  633.   if (data == NULL) {
  634.     sprintf(string, "File %s can not be created.", filenameout);
  635.     PrintError(string);
  636.     return FALSE;
  637.   }
  638.   if (!(operation & DASHo0)) {
  639.  
  640.     /* Write the chart information to the file. */
  641.  
  642.     if (Mon < 1) {
  643.       fclose(data);
  644.       PrintError("Can't output chart with no time/space to file.");
  645.       return FALSE;
  646.     }
  647.     fprintf(data, "%d\n%d\n%d\n%.2f\n%.2f\n%.2f\n%.2f\n",
  648.       Mon, Day, Yea, Tim, Zon, Lon, Lat);
  649.   } else {
  650.  
  651.     /* However, if the -o0 switch is in effect, then write the actual */
  652.     /* positions of the planets and houses to the file instead.       */
  653.  
  654.     for (i = 1; i <= BASE; i++) {
  655.       j = (int) planet[i];
  656.       fprintf(data, "%c%c%c: %2d %2d %10.7f\n", OBJNAM(i),
  657.         j%30, j/30+1, FRACT(planet[i])*60.0);                /* Position */
  658.       k = planetalt[i];
  659.       fprintf(data, "[%c]: %3d %12.8f\n",                    /* Altitude */
  660.         ret[i] >= 0.0 ? 'D' : 'R', (int)(Sgn(k)*
  661.         floor(dabs(k))), (k-(real)(int)k)*60.0);          /* Retrograde? */
  662.       if (i == OBJECTS) {
  663.         if (operation & DASHu)    /* Skip minor cusps to write uranians  */
  664.           i = C_HI;
  665.         else
  666.           i = total;
  667.       }
  668.     }
  669.     for (i = 1; i <= SIGNS/2; i++) {   /* Write first six cusp positions */ 
  670.       j = (int) house[i];
  671.       fprintf(data, "H_%c: %2d %2d %10.7f\n",
  672.         'a'+i-1, j%30, j/30+1, FRACT(house[i])*60.0);
  673.     }
  674.   }
  675.  
  676.   /* Now write any extra strings that were on the command line after the -o */
  677.   /* specification but before the next switch, to the file as comments.     */
  678.  
  679.   for (i = 1; i < extracount; i++) {
  680.     extralines++;
  681.     fprintf(data, "%s\n", extralines[1]);
  682.   }
  683.   fclose(data);
  684.   return TRUE;
  685. }
  686.  
  687.  
  688. /*
  689. ******************************************************************************
  690. ** Program Dispatch Procedures.
  691. ******************************************************************************
  692. */
  693.  
  694. /* Initialize an Ansi color array with the color to print each object in. */
  695.  
  696. void InitColors()
  697. {
  698.   int i;
  699.  
  700.   objectansi[0] = elemansi[_EAR];
  701.   for (i = 1; i <= 10; i++)
  702.     objectansi[i] = signansi(ruler1[i]);
  703.   for (i = 11; i <= 15; i++)
  704.     objectansi[i] = MAGENTA;
  705.   for (i = 16; i <= 20; i++)
  706.     objectansi[i] = DKCYAN;
  707.   objectansi[_MC] = elemansi[_EAR]; objectansi[_ASC] = elemansi[_FIR];
  708.   objectansi[21] = elemansi[_AIR]; objectansi[22] = elemansi[_WAT];
  709.   objectansi[23] = elemansi[_EAR]; objectansi[24] = elemansi[_AIR];
  710.   for (i = U_LO; i <= U_HI; i++)
  711.     objectansi[i] = PURPLE;
  712.   for (i = S_LO; i <= S_HI; i++)
  713.     objectansi[i] = starbright[i-BASE] < 1.0 ? ORANGE : MAROON;
  714. }
  715.  
  716.  
  717. /* This is the dispatch procedure for all the generic table information      */
  718. /* routines, such as those displaying the -H switch list, the list of signs, */
  719. /* objects, default interpretations, and so on not requiring a date or time. */
  720.  
  721. int PrintTables()
  722. {
  723.   if (andisplay < 2)
  724.     return FALSE;
  725.   if (andisplay & DASHHc) {
  726.     DisplayCredits();
  727.     if (andisplay - (andisplay & DASHHc*2-1))
  728.       printl2();
  729.   }
  730.   if (andisplay & DASHH) {
  731.     DisplaySwitches();
  732.     if (andisplay - (andisplay & DASHH*2-1))
  733.       printl2();
  734.   }
  735.   if (andisplay & DASHH0) {
  736.     PrintSigns();
  737.     if (andisplay - (andisplay & DASHH0*2-1))
  738.       printl2();
  739.   }
  740.   if (andisplay & DASHO) {
  741.     PrintObjects((andisplay & DASHO0) > 0);
  742.     if (andisplay - (andisplay & DASHO*2-1))
  743.       printl2();
  744.   }
  745.   if (andisplay & DASHA) {
  746.     PrintAspects();
  747.     if (andisplay - (andisplay & DASHA*2-1))
  748.       printl2();
  749.   }
  750. #ifdef INTERPRET
  751.   if (andisplay & DASHI0) {
  752.     InterpretGeneral();
  753.     InterpretAspectGeneral();
  754.   }
  755. #endif
  756.  
  757.   /* If we also already have enough information to generate a chart,    */
  758.   /* then go on and do so, else exit. (So things like "-O -i file" will */
  759.   /* work, but things like just "-H" will print and exit right away.)   */
  760.  
  761.   if (autom)
  762.     printl2();
  763.   return !autom;
  764. }
  765.  
  766.  
  767. /* This is the dispatch procedure for the entire program. After all the   */
  768. /* command switches have been processed, this routine is called to        */
  769. /* actually call the various routines to generate and display the charts. */
  770.  
  771. void Action()
  772. {
  773.   char string[STRING];
  774.   int i;
  775.  
  776.   AnsiColor(DEFAULT);
  777.   InitColors();
  778.  
  779.   /* First let's adjust the restriction status of the minor cusps, uranians, */
  780.   /* and fixed stars based on whether -C, -u, and -U switches are in effect. */
  781.  
  782.   if (!(operation & DASHC))
  783.     for (i = C_LO; i <= C_HI; i++)
  784.       ignore[i] = ignore2[i] = TRUE;
  785.   if (!(operation & DASHu))
  786.     for (i = U_LO; i <= U_HI; i++)
  787.       ignore[i] = ignore2[i] = TRUE;
  788.   if (!universe)
  789.     for (i = S_LO; i <= S_HI; i++)
  790.       ignore[i] = ignore2[i] = TRUE;
  791.  
  792.   /* If the -os switch is in effect, open a file and set a global to */
  793.   /* internally 'redirect' all screen output to.                     */
  794.  
  795.   if (filenamescreen) {
  796.     S = fopen(filenamescreen, "w");
  797.     if (S == NULL) {
  798.       sprintf(string, "File %s can not be created.", filenamescreen);
  799.       PrintError(string);
  800.       S = stdout;
  801.     }
  802.   } else
  803.     S = stdout;
  804.  
  805.   if (PrintTables())    /* Print out any generic tables specified.        */
  806.     return;             /* If nothing else to do, we can exit right away. */
  807.  
  808.   /* If -+ or -- switches in effect, then add the specified delta value to */
  809.   /* the date and use that as a new date before proceeding to make chart.  */
  810.  
  811.   if (Delta != 0) {
  812.     JD = (real)MdyToJulian(MM, DD+Delta, YY);
  813.     JulianToMdy(JD, &MM, &DD, &YY);
  814.   }
  815.  
  816.   /* Here we either do a normal chart or some kind of relationship chart. */
  817.  
  818.   if (!relation) {
  819.     if (!autom && !InputData("tty"))  /* If chart info not in mem yet, then */
  820.       return;                         /* prompt the user for the time, etc. */
  821.     SetMain(MM, DD, YY, TT, ZZ, OO, AA);
  822.     CastChart(TRUE);
  823.   } else
  824.     CastRelation(TRUE);
  825.   SetSave(Mon, Day, Yea, Tim, Zon, Lon, Lat);
  826.  
  827. #ifdef GRAPH
  828.   if (operation & DASHX)    /* If any of the X window switches in effect, */
  829.     XAction();              /* then go make a graphics chart...           */
  830.   else
  831. #endif
  832.     PrintChart(prog);       /* Otherwise print chart on text screen.      */
  833.  
  834.   if (operation & DASHo)    /* If -o switch in effect, then write */
  835.     OutputData();           /* the chart information to a file.   */
  836.  
  837.   if (S != stdout)    /* If we were internally directing chart display to a */
  838.     fclose(S);        /* file as with the -os switch, close it here.        */
  839. }
  840.  
  841.  
  842. /* Reset a few variables to their default values they have upon startup of */
  843. /* the program. We don't reset all variables, just the most volatile ones. */
  844. /* This is called when in the -Q loop to reset things like which charts to */
  845. /* display, but leave setups such as object restrictions and orbs alone.   */
  846.  
  847. void InitVariables()
  848. {
  849.   filenamescreen = NULL;
  850.   relation = 0;
  851.   todisplay = exdisplay = andisplay = operation = 0x0;
  852.   interpret = progress = autom = FALSE;
  853. }
  854.  
  855.  
  856. /* This routine is called by the main program to actually prompt the user    */
  857. /* for command switches and parameters, entered in the same format as they   */
  858. /* would be on a Unix command line. This is only executed for certain non-   */
  859. /* Unix systems which don't allow passing of a command line to the program,  */
  860. /* or when -Q is in effect. The result of this routine is passed back to the */
  861. /* main program which then processes it just like in a Unix system.          */
  862.  
  863. #define MAXSWITCHES 30
  864.  
  865. int InputSwitches(line, argv)
  866. char *line, *argv[MAXSWITCHES];
  867. {
  868.   FILE *data;
  869.   int argc = 1, i = 0, j = 1;
  870.   char *c = line;
  871.  
  872.   data = S; S = stdout;
  873.   AnsiColor(WHITE);
  874.   fprintf(S, "** %s version %s ", appname, VERSION);
  875.   fprintf(S, "(See '%cHc' switch for copyrights and credits.) **\n", DASH);
  876.   AnsiColor(DEFAULT);
  877.   fprintf(S, "Enter all parameter options below. ");
  878.   fprintf(S, "(Enter '%cH' for help. Enter '.' to exit.)\n", DASH);
  879.   S = data;
  880.   InputString("Input command line", line);
  881.   argv[0] = APPNAME;
  882.  
  883.   /* Split the entered line up into its individual switch strings. */
  884.   while (*c) {
  885.     if (*c == ' ') {
  886.       if (j)
  887.         ;           /* Skip over the current run of spaces between strings. */
  888.       else {
  889.         *c = 0;     /* First space after a string, end it here. */
  890.         j = TRUE;
  891.       }
  892.     } else {
  893.       if (j) {
  894.         argv[argc++] = c;    /* First char after spaces, begin it here. */
  895.         j = FALSE;
  896.       } else
  897.         ;                    /* Skip over the current string. */
  898.     }
  899.     c++;
  900.   }
  901.   argv[argc] = NULL;    /* Set last string in switch array to Null. */
  902.   printl();
  903.   return argc;
  904. }
  905.  
  906.  
  907. /*
  908. ******************************************************************************
  909. ** Main Program.
  910. ******************************************************************************
  911. */
  912.  
  913. /* Process a command line switch passed to the program. Read each entry in */
  914. /* the argument list and set all the program modes and charts to display.  */
  915.  
  916. bool ProcessSwitches(argc, argv)
  917. int argc;
  918. char **argv;
  919. {
  920.   int pos, i;
  921.   real k;
  922.   char string[STRING], cpos, *c;
  923.  
  924.   argc--; argv++;
  925.   while (argc) {
  926.     pos  = 1 + (argv[0][0] == '-' || argv[0][0] == '/');  /* Leading dash? */
  927.     cpos = argv[0][pos];
  928.     switch (argv[0][pos-1]) {
  929.  
  930.     case 'H':
  931.       if (cpos == 'c')
  932.         andisplay ^= DASHHc;
  933.       else if (cpos == '0')
  934.         andisplay ^= DASHH0;
  935.       else
  936.         andisplay ^= DASHH;
  937.       break;
  938.  
  939.     case 'O':
  940.       if (cpos == '0')
  941.         andisplay ^= DASHO0;
  942.       andisplay ^= DASHO;
  943.       break;
  944.  
  945.     case 'Q':
  946.       if (cpos == '0')
  947.         operation ^= DASHQ0;
  948.       operation ^= DASHQ;
  949.       break;
  950.  
  951.     /* Switches which determine the type of chart to display: */
  952.  
  953.     case 'v':
  954.       if (cpos == '0')
  955.         exdisplay ^= DASHv0;
  956.       todisplay ^= DASHv;
  957.       break;
  958.  
  959.     case 'w':
  960.       if (cpos == '0')
  961.         exdisplay ^= DASHw0;
  962.       if (argc > 1 && (i = atoi(argv[1]))) {
  963.         wheelrows = i;
  964.         argc--; argv++;
  965.       }
  966.       if (!IsValidWheel(wheelrows)) {
  967.         BadVal("w", wheelrows);
  968.         return FALSE;
  969.       }
  970.       todisplay ^= DASHw;
  971.       break;
  972.  
  973.     case 'g':
  974.       if (cpos == '0')
  975.         exdisplay ^= DASHg0;
  976.       else if (cpos == 'a') {
  977.         exdisplay ^= DASHga;
  978.         if (argv[0][pos+1] == '0')
  979.           exdisplay ^= DASHg0;
  980.       }
  981. #ifdef X11
  982.       else if (cpos == 'e') {
  983.         if (argc <= 1) {
  984.           TooFew("geometry");
  985.           return FALSE;
  986.         }
  987.         chartx = atoi(argv[1]);
  988.         if (argc > 2 && (charty = atoi(argv[2]))) {
  989.           argc--; argv++;
  990.         } else
  991.           charty = chartx;
  992.         if (!IsValidGraphx(chartx)) {
  993.           BadVal("geometry", chartx);
  994.           return FALSE;
  995.         }
  996.         if (!IsValidGraphy(charty)) {
  997.           BadVal("geometry", charty);
  998.           return FALSE;
  999.         }
  1000.         argc--; argv++;
  1001.         break;
  1002.       }
  1003. #endif
  1004.       todisplay ^= DASHg;
  1005.       break;
  1006.  
  1007.     case 'm':
  1008.       if (cpos == '0') {
  1009.         exdisplay ^= DASHm0;
  1010.         if (argv[0][pos+1] == 'a')
  1011.           exdisplay ^= DASHga;
  1012.       } else if (cpos == 'a')
  1013.         exdisplay ^= DASHm0 | DASHga;
  1014.       todisplay ^= DASHm;
  1015.       break;
  1016.  
  1017.     case 'Z':
  1018.       if (cpos == '0')
  1019.         exdisplay ^= DASHZ0;
  1020.       else if (cpos == 'd')
  1021.         exdisplay ^= DASHZd;
  1022.       todisplay ^= DASHZ;
  1023.       break;
  1024.  
  1025.     case 'S':
  1026.       todisplay ^= DASHS;
  1027.       break;
  1028.  
  1029.     case 'j':
  1030.       if (cpos == '0')
  1031.         exdisplay ^= DASHj0;
  1032.       todisplay ^= DASHj;
  1033.       break;
  1034.  
  1035.     case 'L':
  1036.       if (cpos == '0')
  1037.         exdisplay ^= DASHL0;
  1038.       if (argc > 1 && (i = atoi(argv[1]))) {
  1039.         graphstep = i;
  1040.         argc--; argv++;
  1041.       }
  1042.       if (graphstep < 1 || 160%graphstep > 0) {
  1043.         BadVal("L", graphstep);
  1044.         return FALSE;
  1045.       }
  1046.       todisplay ^= DASHL;
  1047.       break;
  1048.  
  1049.     case 'K':
  1050.       if (cpos == 'y')
  1051.         exdisplay ^= DASHKy;
  1052.       todisplay ^= DASHK;
  1053.       break;
  1054.  
  1055.     case 'd':
  1056.       if (cpos == 'p') {
  1057.         i = (argv[0][pos+1] == 'y');
  1058.         if (argc <= 2-i) {
  1059.           TooFew("dp");
  1060.           return FALSE;
  1061.         }
  1062.         prog = TRUE;
  1063.         exdisplay |= DASHdm;
  1064.         if (i) {
  1065.           Mon2 = 0;
  1066.           Yea2 = atoi(argv[1]);
  1067.         } else {
  1068.           Mon2 = atoi(argv[1]);
  1069.           Yea2 = atoi(argv[2]);
  1070.           if (!IsValidMon(Mon2)) {
  1071.             BadVal2("dp", Mon2);
  1072.             return FALSE;
  1073.           }
  1074.         }
  1075.         if (!IsValidYea(Yea2)) {
  1076.           BadVal2("dp", Yea2);
  1077.           return FALSE;
  1078.         }
  1079.         argc -= 2-i; argv += 2-i;
  1080.       } else if (cpos == 'm')
  1081.         exdisplay ^= DASHdm;
  1082. #ifdef X11
  1083.       else if (cpos == 'i') {    /* -display switch for X */
  1084.         if (argc <= 1) {
  1085.           TooFew("display");
  1086.           return FALSE;
  1087.         }
  1088.         dispname = argv[1];
  1089.         argc--; argv++;
  1090.       }
  1091. #endif
  1092.       todisplay ^= DASHd;
  1093.       break;
  1094.  
  1095.     case 'D':
  1096.       todisplay ^= DASHD;
  1097.       break;
  1098.  
  1099.     case 'E':
  1100.       if (cpos == 'y')
  1101.         exdisplay ^= DASHEy;
  1102.       todisplay ^= DASHE;
  1103.       break;
  1104.  
  1105.     case 'e':
  1106.       todisplay ^= DASHe;
  1107.       exdisplay ^= DASHg0 | DASHj0 | DASHL0;
  1108.       break;
  1109.  
  1110.     case 't':
  1111.       todisplay ^= DASHt;
  1112.       Zon2 = defzone; Lon2 = deflong; Lat2 = deflat;
  1113.       if (cpos == 'p') {
  1114.         prog = TRUE;
  1115.         cpos = argv[0][++pos];
  1116.       }
  1117.       if (i = (cpos == 'y'))
  1118.         cpos = argv[0][++pos];
  1119. #ifdef TIME
  1120.       if (cpos == 'n') {
  1121.         GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2);
  1122.         if (i)
  1123.           Mon2 = 0;
  1124.         break;
  1125.       }
  1126. #endif
  1127.       if (argc <= 2-i) {
  1128.         TooFew("t");
  1129.         return FALSE;
  1130.       }
  1131.       if (i)
  1132.         Mon2 = 0;
  1133.       else {
  1134.         Mon2 = atoi(argv[1]);
  1135.         if (!IsValidMon(Mon2)) {
  1136.           BadVal2("t", Mon2);
  1137.           return FALSE;
  1138.         }
  1139.       }
  1140.       Yea2 = atoi(argv[2-i]);
  1141.       argc -= 2-i; argv += 2-i;
  1142.       break;
  1143.  
  1144.     case 'T':
  1145.       todisplay ^= DASHT;
  1146.       Zon2 = defzone; Lon2 = deflong; Lat2 = deflat;
  1147.       if (cpos == 'p') {
  1148.         prog = TRUE;
  1149.         cpos = argv[0][++pos];
  1150.       }
  1151. #ifdef TIME
  1152.       if (cpos == 'n') {
  1153.         GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2);
  1154.         break;
  1155.       }
  1156. #endif
  1157.       if (argc <= 3) {
  1158.         TooFew("T");
  1159.         return FALSE;
  1160.       }
  1161.       Mon2 = atoi(argv[1]);
  1162.       Day2 = atoi(argv[2]);
  1163.       Yea2 = atoi(argv[3]);
  1164.       if (!IsValidMon(Mon2)) {
  1165.         BadVal2("T", Mon2);
  1166.         return FALSE;
  1167.       } else if (!IsValidDay(Day2, Mon2, Yea2)) {
  1168.         BadVal2("T", Day2);
  1169.         return FALSE;
  1170.       } else if (!IsValidYea(Yea2)) {
  1171.         BadVal2("T", Yea2);
  1172.         return FALSE;
  1173.       }
  1174.       argc -= 3; argv += 3;
  1175.       break;
  1176.  
  1177. #ifdef INTERPRET
  1178.     case 'I':
  1179.       if (argc > 1 && (screenwidth = atoi(argv[1]))) {
  1180.         argc--; argv++;
  1181.       } else
  1182.         screenwidth = SCREENWIDTH;
  1183.       if (!IsValidScreen(screenwidth)) {
  1184.         BadVal("I", screenwidth);
  1185.         return FALSE;
  1186.       }
  1187.       if (cpos == '0') {
  1188.         andisplay ^= DASHI0;
  1189.         break;
  1190.       }
  1191.       interpret = !interpret;
  1192.       break;
  1193. #endif
  1194.  
  1195.     /* Switches which affect how the chart parameters are obtained: */
  1196.  
  1197. #ifdef TIME
  1198.     case 'n':
  1199.       InputData("now");
  1200.       if (cpos == 'd')
  1201.         TT = 0.0;
  1202.       else if (cpos == 'm') {
  1203.         DD = 1; TT = 0.0;
  1204.       } else if (cpos == 'y') {
  1205.         MM = DD = 1; TT = 0.0;
  1206.       }
  1207.       break;
  1208. #endif
  1209.  
  1210.     case 'a':
  1211.       if (argc <= 7) {
  1212.         TooFew("a");
  1213.         return FALSE;
  1214.       }
  1215.       autom = TRUE;
  1216.       SetCore(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]),
  1217.         atof(argv[4]), atof(argv[5]), atof(argv[6]), atof(argv[7]));
  1218.       if (!IsValidMon(MM)) {
  1219.         BadVal("a", MM);
  1220.         return FALSE;
  1221.       } else if (!IsValidYea(YY)) {
  1222.         BadVal("a", YY);
  1223.         return FALSE;
  1224.       } else if (!IsValidDay(DD, MM, YY)) {
  1225.         BadVal("a", DD);
  1226.         return FALSE;
  1227.       } else if (!IsValidTim(TT)) {
  1228.         BadVal2("a", TT);
  1229.         return FALSE;
  1230.       } else if (!IsValidZon(ZZ)) {
  1231.         BadVal2("a", ZZ);
  1232.         return FALSE;
  1233.       } else if (!IsValidLon(OO)) {
  1234.         BadVal2("a", OO);
  1235.         return FALSE;
  1236.       } else if (!IsValidLat(AA)) {
  1237.         BadVal2("a", AA);
  1238.         return FALSE;
  1239.       }
  1240.       argc -= 7; argv += 7;
  1241.       break;
  1242.  
  1243.     case 'z':
  1244.       if (argc <= 1 || (atoi(argv[1]) == 0 && argv[1][0] != '0'))
  1245.         defzone -= 1.0;
  1246.       else {
  1247.         defzone = atof(argv[1]);
  1248.         if (!IsValidZon(defzone)) {
  1249.           BadVal2("z", defzone);
  1250.           return FALSE;
  1251.         }
  1252.         argc--; argv++;
  1253.       }
  1254.       break;
  1255.  
  1256.     case 'l':
  1257.       if (argc <= 2) {
  1258.         TooFew("l");
  1259.         return FALSE;
  1260.       }
  1261.       deflong = atof(argv[1]);
  1262.       deflat  = atof(argv[2]);
  1263.       if (!IsValidLon(deflong)) {
  1264.         BadVal2("l", deflong);
  1265.         return FALSE;
  1266.       } else if (!IsValidLat(deflat)) {
  1267.         BadVal2("l", deflat);
  1268.         return FALSE;
  1269.       }
  1270.       argc -= 2; argv += 2;
  1271.       break;
  1272.  
  1273.     case 'q':
  1274.       i = (cpos == 'd') + 2*(cpos == 'm') + 3*(cpos == 'y' || cpos == 'j');
  1275.       if (argc <= 4-i) {
  1276.         TooFew("q");
  1277.         return FALSE;
  1278.       }
  1279.       autom = TRUE;
  1280.       if (cpos == 'j') {
  1281.         JD = atof(argv[1])+ROUND;
  1282.         TT = FRACT(JD);
  1283.         JulianToMdy(JD-TT, &MM, &DD, &YY);
  1284.         TT *= 24.0; ZZ = 0.0;
  1285.         TT = DegToDec(TT);
  1286.       } else {
  1287.         MM = i > 2 ? 1 : atoi(argv[1]);
  1288.         DD = i > 1 ? 1 : atoi(argv[2-(i>2)]); YY = atoi(argv[4-i-(i<1)]);
  1289.         TT = i == 0 ? atof(argv[4]) : (i > 1 ? 0.0 : 12.0); ZZ = defzone;
  1290.         if (!IsValidMon(MM)) {
  1291.           BadVal("q", MM);
  1292.           return FALSE;
  1293.         } else if (!IsValidDay(DD, MM, YY)) {
  1294.           BadVal("q", DD);
  1295.           return FALSE;
  1296.         } else if (!IsValidYea(YY)) {
  1297.           BadVal("q", YY);
  1298.           return FALSE;
  1299.         } else if (TT < -2.0 || TT > 24.0) {
  1300.           BadVal2("q", TT);
  1301.           return FALSE;
  1302.         }
  1303.       }
  1304.       OO = deflong; AA = deflat;
  1305.       argc -= 4-i; argv += 4-i;
  1306.       break;
  1307.  
  1308.     case 'i':
  1309.       if (argc <= 1) {
  1310.         TooFew("i");
  1311.         return FALSE;
  1312.       }
  1313.       if (!InputData(argv[1]))
  1314.         return FALSE;
  1315.       argc--; argv++;
  1316.       break;
  1317.  
  1318.     case 'o':
  1319.       if (argc <= 1) {
  1320.         TooFew("o");
  1321.         return FALSE;
  1322.       }
  1323.       if (cpos == 's') {
  1324.         filenamescreen = argv[1];
  1325.         argc--; argv++;
  1326.         break;
  1327.       } else if (cpos == '0')
  1328.         operation ^= DASHo0;
  1329.       operation ^= DASHo;
  1330.       filenameout = argv[1];
  1331.       extralines = argv;
  1332.       do {
  1333.         argc--; argv++;
  1334.         extracount++;
  1335.       } while (argc > 1 && argv[1][0] != '-' && argv[1][0] != '/');
  1336.       break;
  1337.  
  1338.     /* Switches which affect what information is used in a chart: */
  1339.  
  1340.     case 'R':
  1341.       if (cpos == 'T') {
  1342.         c = (char *)ignore2;
  1343.         cpos = argv[0][++pos];
  1344.       } else
  1345.         c = (char *)ignore;
  1346.       if (cpos == '0')
  1347.         for (i = 0; i <= total; i++)
  1348.           c[i] = TRUE;
  1349.       else if (cpos == '1') {
  1350.         for (i = 0; i <= total; i++)
  1351.           c[i] = FALSE;
  1352.         operation |= DASHC | DASHu;
  1353.         universe = TRUE;
  1354.       } else if (cpos == 'C')
  1355.         for (i = C_LO; i <= C_HI; i++)
  1356.           c[i] = !c[i];
  1357.       else if (cpos == 'u')
  1358.         for (i = U_LO; i <= U_HI; i++)
  1359.           c[i] = !c[i];
  1360.       else if (cpos == 'U')
  1361.         for (i = S_LO; i <= S_HI; i++)
  1362.           c[i] = !c[i];
  1363.       else if (argc <= 1 || (!atoi(argv[1]))) {
  1364.         for (i = 11; i <= 15; i++)
  1365.           c[i] = !c[i];
  1366.         c[_FOR] = !c[_FOR]; c[_VTX] = !c[_VTX];
  1367.       }
  1368.       while (argc > 1 && (i = atoi(argv[1])))
  1369.         if (!IsItem(i)) {
  1370.           BadVal("R", i);
  1371.           return FALSE;
  1372.         } else {
  1373.           c[i] = !c[i];
  1374.           argc--; argv++;
  1375.         }
  1376.       break;
  1377.  
  1378.     case 'C':
  1379.       operation ^= DASHC;
  1380.       break;
  1381.  
  1382.     case 'u':
  1383.       operation ^= DASHu;
  1384.       break;
  1385.  
  1386.     case 'U':
  1387.       if (cpos == 'n' || cpos == 'b' || cpos == 'z' || cpos == 'l')
  1388.         universe = cpos;
  1389.       else
  1390.         universe = !universe;
  1391.       break;
  1392.  
  1393.     case 'A':
  1394.       if (argc <= 1 || atoi(argv[1]) == 0) {
  1395.         andisplay ^= DASHA;
  1396.         break;
  1397.       }
  1398.       if (cpos != 'o' && cpos != 'm' && cpos != 'd') {
  1399.         aspects = atoi(argv[1]);
  1400.         if (!IsValidAspect(aspects)) {
  1401.           BadVal("A", aspects);
  1402.           return FALSE;
  1403.         }
  1404.         argc--; argv++;
  1405.       } else {
  1406.         if (argc <= 2) {
  1407.           TooFew("A");
  1408.           return FALSE;
  1409.         }
  1410.         i = atoi(argv[1]);
  1411.         if (i < 1 || i > (cpos == 'o' ? ASPECTS : BASE)) {
  1412.           BadVal("A", i);
  1413.           return FALSE;
  1414.         }
  1415.         k = atof(argv[2]);
  1416.         if (k < -DEGREES || k > DEGREES) {
  1417.           BadVal2("A", k);
  1418.           return FALSE;
  1419.         }
  1420.         if (cpos == 'm')
  1421.           planetorb[i] = k;
  1422.         else if (cpos == 'd')
  1423.           planetadd[i] = k;
  1424.         else
  1425.           aspectorb[i] = k;
  1426.         argc -= 2; argv += 2;
  1427.       }
  1428.       break;
  1429.  
  1430.     /* Switches which affect how a chart is computed: */
  1431.  
  1432.     case 'b':
  1433.       if (cpos == '0')
  1434.         seconds = !seconds;
  1435.       placalc = !placalc;
  1436.       break;
  1437.  
  1438.     case 'c':
  1439.       if (argc <= 1) {
  1440.         TooFew("c");
  1441.         return FALSE;
  1442.       }
  1443.       housesystem = atoi(argv[1]);
  1444.       if (!IsValidSystem(housesystem)) {
  1445.         BadVal("c", housesystem);
  1446.         return FALSE;
  1447.       }
  1448.       argc--; argv++;
  1449.       break;
  1450.  
  1451.     case 's':
  1452.       if (cpos != '0')
  1453.         operation ^= DASHs;
  1454.       else
  1455.         operation ^= DASHs0;
  1456.       break;
  1457.  
  1458.     case 'h':
  1459.       if (argc > 1 && (centerplanet = atoi(argv[1]))) {
  1460.         argc--; argv++;
  1461.       } else
  1462.         centerplanet = 1;
  1463.       if (centerplanet < 0 || centerplanet == _MOO ||
  1464.         !IsObject(centerplanet) || centerplanet > U_HI) {
  1465.         BadVal("h", centerplanet);
  1466.         return FALSE;
  1467.       }
  1468.       c = objectname[0];
  1469.       objectname[0] = objectname[centerplanet];
  1470.       objectname[centerplanet] = c;
  1471.       if (centerplanet < _MOO)
  1472.         centerplanet = 1-centerplanet;
  1473.       break;
  1474.  
  1475.     case 'p':
  1476.       if (cpos == '0') {
  1477.         operation |= DASHp0;
  1478.         cpos = (argv[0][++pos]);
  1479.       }
  1480.       progress = TRUE;
  1481. #ifdef TIME
  1482.       if (cpos == 'n') {
  1483.         GetTimeNow(&Mon, &Day, &Yea, &Tim, defzone);
  1484.         Jdp = (real)MdyToJulian(Mon, Day, Yea) + Tim / 24.0;
  1485.         break;
  1486.       }
  1487. #endif
  1488.       if (cpos == 'd') {
  1489.         if (argc <= 1) {
  1490.           TooFew("pd");
  1491.           return FALSE;
  1492.         }
  1493.         progday = atof(argv[1]);
  1494.         if (progday == 0.0) {
  1495.           BadVal2("pd", progday);
  1496.           return FALSE;
  1497.         }
  1498.         argc--; argv++;
  1499.         break;
  1500.       }
  1501.       if (argc <= 3) {
  1502.         TooFew("p");
  1503.         return FALSE;
  1504.       }
  1505.       Mon = atoi(argv[1]);
  1506.       Day = atoi(argv[2]);
  1507.       Yea = atoi(argv[3]);
  1508.       if (!IsValidMon(Mon)) {
  1509.         BadVal2("p", Mon);
  1510.         return FALSE;
  1511.       } else if (!IsValidDay(Day, Mon, Yea)) {
  1512.         BadVal2("p", Day);
  1513.         return FALSE;
  1514.       } else if (!IsValidYea(Yea)) {
  1515.         BadVal2("p", Yea);
  1516.         return FALSE;
  1517.       }
  1518.       Jdp = (real)MdyToJulian(Mon, Day, Yea) + defzone / 24.0;
  1519.       argc -= 3; argv += 3;
  1520.       break;
  1521.  
  1522.     case 'x':
  1523.       if (argc <= 1) {
  1524.         TooFew("x");
  1525.         return FALSE;
  1526.       }
  1527.       multiplyfactor = atoi(argv[1]);
  1528.       if (multiplyfactor < 1 || multiplyfactor > DEGREES) {
  1529.         BadVal("x", multiplyfactor);
  1530.         return FALSE;
  1531.       }
  1532.       argc--; argv++;
  1533.       break;
  1534.  
  1535.     case '1':
  1536.       if (argc > 1 && (onasc = atoi(argv[1]))) {
  1537.         argc--; argv++;
  1538.       } else
  1539.         onasc = 1;
  1540.       if (onasc < 1 || onasc > total) {
  1541.         BadVal("1", onasc);
  1542.         return FALSE;
  1543.       }
  1544.       break;
  1545.  
  1546.     case '2':
  1547.       if (argc > 1 && (onasc = atoi(argv[1]))) {
  1548.         argc--; argv++;
  1549.       } else
  1550.         onasc = 1;
  1551.       if (onasc < 1 || onasc > total) {
  1552.         BadVal("2", onasc);
  1553.         return FALSE;
  1554.       }
  1555.       onasc = -onasc;
  1556.       break;
  1557.  
  1558.     case '3':
  1559.       operation ^= DASH3;
  1560.       break;
  1561.  
  1562.     case 'f':
  1563.       operation ^= DASHf;
  1564.       break;
  1565.  
  1566.     case 'G':
  1567.       operation ^= DASHG;
  1568.       break;
  1569.  
  1570.     case 'F':
  1571.       if (argc <= 3) {
  1572.         TooFew("F");
  1573.         return FALSE;
  1574.       }
  1575.       i = atoi(argv[1]);
  1576.       if (!IsItem(i)) {
  1577.         BadVal("F", i);
  1578.         return FALSE;
  1579.       }
  1580.       force[i] = (atof(argv[2])-1.0)*30.0+DecToDeg(atof(argv[3]));
  1581.       if (force[i] < 0.0 || force[i] >= DEGREES) {
  1582.         BadVal2("F", force[i]);
  1583.         return FALSE;
  1584.       } else
  1585.         force[i] += DEGREES;
  1586.       argc -= 3; argv += 3;
  1587.       break;
  1588.  
  1589.     case '+':
  1590.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1591.         argc--; argv++;
  1592.       } else
  1593.         i = 1;
  1594.       Delta += i * (cpos == 'y' ? 365 : (cpos == 'm' ? 30 : 1));
  1595.       break;
  1596.  
  1597.     case '-': case '\0':
  1598.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1599.         argc--; argv++;
  1600.       } else
  1601.         i = 1;
  1602.       Delta -= i * (cpos == 'y' ? 365 : (cpos == 'm' ? 30 : 1));
  1603.       break;
  1604.  
  1605.     /* Switches for relationship and comparison charts: */
  1606.  
  1607.     case 'r':
  1608.       if (argc <= 2) {
  1609.         TooFew("r");
  1610.         return FALSE;
  1611.       }
  1612.       if (cpos == 'c')
  1613.         relation = DASHrc;
  1614.       else if (cpos == 'm')
  1615.         relation = DASHrm;
  1616.       else if (cpos == 'd')
  1617.         relation = DASHrd;
  1618. #ifdef BIORHYTHM
  1619.       else if (cpos == 'b')
  1620.         relation = DASHrb;
  1621. #endif
  1622.       else if (cpos == '0')
  1623.         relation = DASHr0;
  1624.       else if (cpos == 'p')
  1625.         relation = DASHrp;
  1626.       else
  1627.         relation = DASHr;
  1628.       filename = argv[1]; filename2 = argv[2];
  1629.       argc -= 2; argv += 2;
  1630.       break;
  1631.  
  1632. #ifdef TIME
  1633.     case 'y':
  1634.       if (argc <= 1) {
  1635.         TooFew("y");
  1636.         return FALSE;
  1637.       }
  1638.       if (cpos == 'd')
  1639.         relation = DASHrd;
  1640. #ifdef BIORHYTHM
  1641.       else if (cpos == 'b')
  1642.         relation = DASHrb;
  1643. #endif
  1644.       else if (cpos == 'p')
  1645.         relation = DASHrp;
  1646.       else
  1647.         relation = DASHr0;
  1648.       filename = argv[1]; filename2 = "now";
  1649.       argc--; argv++;
  1650.       break;
  1651. #endif
  1652.  
  1653.     /* Switches to access graphics options: */
  1654.  
  1655.     case 'k':
  1656.       ansi = !ansi;
  1657.       break;
  1658.  
  1659. #ifdef MSG
  1660.     case 'V':
  1661.       if (argc <= 1) {
  1662.         TooFew("V");
  1663.         return FALSE;
  1664.       }
  1665.       textrows = atoi(argv[1]);
  1666.       if (!IsValidTextrows(textrows)) {
  1667.         BadVal("V", textrows);
  1668.         return FALSE;
  1669.       }
  1670.       argc--; argv++;
  1671.       break;
  1672. #endif
  1673.  
  1674. #ifdef GRAPH
  1675.     case 'X':
  1676.       i = XProcessSwitches(argc, argv, pos);
  1677.       if (i < 0)
  1678.         return FALSE;
  1679.       operation |= DASHX;
  1680.       argc -= i; argv += i;
  1681.       break;
  1682. #endif
  1683.  
  1684.     case '.':               /* "-." is usually used to exit the -Q loop. */
  1685.       Terminate(_FORCE);
  1686.  
  1687.     case 'B':          /* For no useful reason, -B will sound a beep. */
  1688.       printc(BELL);
  1689.       break;
  1690.  
  1691.     default:
  1692.       sprintf(string, "Unknown switch '%s'.", argv[0]);
  1693.       PrintError(string);
  1694.       return FALSE;
  1695.     }
  1696.     argc--; argv++;
  1697.   }
  1698.   return TRUE;
  1699. }
  1700.  
  1701.  
  1702. /* The main program, the starting point for Astrolog, follows. This routine */
  1703. /* basically consists of a loop, inside which we read a command line, and   */
  1704. /* go process it, before actually calling a routine to do the neat stuff.   */
  1705.  
  1706. #ifdef SWITCHES
  1707. void main(argc, argv)
  1708. int argc;
  1709. char **argv;
  1710. {
  1711. #else
  1712. void main()
  1713. {
  1714.   int argc;
  1715.   char **argv;
  1716. #endif
  1717.   char commandline[256];
  1718.   char *pointers[MAXSWITCHES];
  1719.  
  1720.   InputDefaults();    /* Read in info from the astrolog.dat file. */
  1721. Begin:
  1722. #ifdef MSG
  1723.   if (textrows > 0) {
  1724.     _settextrows(textrows);
  1725.     textrows = -textrows;
  1726.   }
  1727. #endif
  1728.   if (noswitches) {                                 /* Go prompt for    */
  1729.     argc = InputSwitches(commandline, pointers);    /* switches if we   */
  1730.     argv = pointers;                                /* don't have them. */
  1731.   }
  1732.   progname = ProcessProgname(argv[0]);
  1733.   if (ProcessSwitches(argc, argv)) {
  1734.     if (!noswitches && (operation & DASHQ0)) {
  1735.       noswitches = TRUE;
  1736.       goto Begin;
  1737.     }
  1738. #ifdef MSG
  1739.     if (textrows > 0) {
  1740.       _settextrows(textrows);
  1741.       textrows = -textrows;
  1742.     }
  1743. #endif
  1744.     Action();
  1745.   }
  1746.   if (operation & DASHQ) {    /* If -Q in effect, loop back and get switch */
  1747.     printl2();                /* information for another chart to display. */
  1748.     InitVariables();
  1749.     operation |= DASHQ;
  1750.     noswitches = TRUE;
  1751.     goto Begin;
  1752.   }
  1753.   Terminate(_OK);    /* The only standard place to exit Astrolog is here. */
  1754. }
  1755.  
  1756. /* driver.c */
  1757.