Example #1
0
/* Advance to time indicated by timestring, of the format "HH:MM".
 */
TimedAdvance::TimedAdvance(std::string timestring, uint16 r)
    : TimedCallback(NULL, NULL, 1000/TIMEADVANCE_PER_SECOND, true),
      clock(Game::get_game()->get_clock()),
      minutes_this_hour(0), minutes(0)
{
    uint8 hour = 0, minute = 0;

    get_time_from_string(hour, minute, timestring); // set stop time

    // set number of hours and minutes to advance
    uint16 advance_h = (clock->get_hour() == hour) ? 24
                       : (clock->get_hour() < hour) ? (hour-clock->get_hour())
                       : (24-(clock->get_hour()-hour));
    uint16 advance_m;
    if(clock->get_minute()<=minute)
        advance_m = minute - clock->get_minute();
    else
    {
        advance_m = (60 - (clock->get_minute()-minute));
        if(advance_h > 0)
            advance_h -= 1;
        else
            advance_h = 23;
    }
    // go
    init((advance_h * 60) + advance_m, r);
}
Example #2
0
bool cdkey_ban_list::banned_client::load(CInifile* ini, shared_str const & name_sect)
{
	if (!ini->line_exist(name_sect, CLIENT_HEX_DIGEST_KEY) ||
		!ini->line_exist(name_sect, CLIENT_BAN_END_TIME_KEY))
	{
		return false;
	}
	client_hexstr_digest = ini->r_string(name_sect, CLIENT_HEX_DIGEST_KEY);
	LPCSTR tmp_string = ini->r_string(name_sect, CLIENT_BAN_END_TIME_KEY);
	
	ban_end_time = get_time_from_string(tmp_string);
	if (ban_end_time == 0)
	{
		Msg("! ERROR bad ban_end_time in section [%s]", name_sect.c_str());
		return false;
	}
	tmp_string = ini->r_string(name_sect, CLIENT_BAN_START_TIME_KEY);
	if (tmp_string)
		ban_start_time = get_time_from_string(tmp_string);
	
	tmp_string = ini->r_string(name_sect, CLIENT_NAME_KEY);
	if (tmp_string)
		client_name = tmp_string;

	tmp_string = ini->r_string(name_sect, CLIENT_IP_KEY);
	if (tmp_string)
		client_ip_addr.set(tmp_string);
	
	tmp_string = ini->r_string(name_sect, ADMIN_NAME_KEY);
	if (tmp_string)
		admin_name = tmp_string;
	tmp_string = ini->r_string(name_sect, ADMIN_IP_KEY);
	if (tmp_string)
		admin_ip_addr.set(tmp_string);
	tmp_string = ini->r_string(name_sect, ADMIN_HEX_DIGEST_KEY);
	if (tmp_string)
		admin_hexstr_digest = tmp_string;
	return true;	
}
Example #3
0
int main( int argc, char **argv)
{
   FILE *ifile = fopen( argc == 1 ? "get_test.txt" : argv[1], "rb");

   if( ifile)
      {
      char buff[80];
      double jd = 0;
      int i;
      unsigned time_format = 0;

      setvbuf( stdout, NULL, _IONBF, 0);
      while( fgets( buff, sizeof( buff), ifile))
         {
         for( i = 0; buff[i] >= ' '; i++)
            ;
         buff[i] = '\0';
         if( !memcmp( buff, "format", 6))
            {
            sscanf( buff + 6, "%x", &time_format);
            printf( "%s\n", buff);
            }
         else if( *buff != ';')
            {
            char obuff[80];
            int is_ut;

            jd = get_time_from_string( jd, buff, (int)time_format, &is_ut);
            full_ctime( obuff, jd, FULL_CTIME_MILLISECS | CALENDAR_JULIAN_GREGORIAN);
            printf( "%s %d %s\n", obuff, is_ut, buff);
            }
         else
            printf( "%s\n", buff);
         }
      fclose( ifile);
      }
   return( ifile ? 0 : -1);
}
Example #4
0
int main( const int argc, const char **argv)
{
   char tbuff[300], mpc_code[20];
   char **summary_lines = NULL;
   const char *separate_residual_file_name = NULL;
   const char *mpec_path = NULL;
   int n_ids, i, starting_object = 0;
   int n_processes = 1;
   OBJECT_INFO *ids;
   int total_objects = 0;
   FILE *ifile;
   extern int process_count;
   int n_lines_written = 0;
   FILE *summary_ofile = NULL;
   extern int forced_central_body;
   extern int use_config_directory;          /* miscell.c */
   int element_precision = 5;
   bool all_heliocentric = true;
   bool use_colors = true;
   bool show_processing_steps = true;
   int ephemeris_output_options = OPTION_SHOW_SIGMAS | OPTION_ROUND_TO_NEAREST_STEP;
   time_t update_time, t0;
   double ephem_end_jd = 0.;
   extern bool is_default_ephem;
   bool drop_single_obs = true;
   const char *ephem_option_string = NULL;
#ifdef FORKING
   int child_status;
#endif

   if( !strcmp( argv[0], "fo"))
      use_config_directory = true;
   else
      use_config_directory = false;
   *mpc_code = '\0';
   for( i = 1; i < argc; i++)       /* check to see if we're debugging: */
      if( argv[i][0] == '-')
         {
         const char *arg = get_arg( argc, argv, i);

         switch( argv[i][1])
            {
            case 'a':
               {
               extern int separate_periodic_comet_apparitions;

               separate_periodic_comet_apparitions ^= 1;
               }
               break;
            case 'b':
               separate_residual_file_name = arg;
               break;
            case 'c':
               {
               extern int combine_all_observations;

               combine_all_observations = 1;
               }
               break;
            case 'C':
               strlcpy( mpc_code, arg, sizeof( mpc_code));
               break;
            case 'd':
               debug_level = atoi( arg);
               if( !debug_level)
                  debug_level = 1;
               debug_printf( "fo: debug_level = %d; %s %s\n",
                           debug_level, __DATE__, __TIME__);
               break;
            case 'e':
               {
               extern const char *ephemeris_filename;

               ephemeris_filename = arg;
               is_default_ephem = false;
               }
               break;
            case 'E':
               ephem_option_string = arg;
               break;
            case 'f':                     /* obj desig specified;  fall through */
               break;
            case 'h':                     /* show planet-centric orbits */
               all_heliocentric = false;
               break;
#ifdef FORKING
            case 'k':
               unlink_partial_files = false;
               break;
#endif
            case 'i':
               {
               extern int ignore_prev_solns;

               ignore_prev_solns = 1;
               }
               break;
            case 'm':
               mpec_path = arg;
               break;
            case 'M':
               {
               extern const char *mpcorb_dot_sof_filename;

               mpcorb_dot_sof_filename = arg;
               }
               break;
            case 'n':
               starting_object = atoi( arg);
               break;
            case 'O':          /* write output files to specified dir */
               {
               extern const char *output_directory;

               output_directory = arg;
               }
               break;
            case 'o':            /* obj designation / ephemeris from orbital */
               break;            /* elems:  fall through, handle below */
            case 'p':
               {
               FILE *ifile = fopen_ext( "dummy.txt", "tfcw");

               fclose( ifile);
               n_processes = atoi( arg);
               }
               break;
            case 'q':            /* "quiet" */
               show_processing_steps = false;
               break;
#ifdef FORKING
            case 'r':
               {                    /* set 'soft' & 'hard' limits for CPU */
               struct rlimit r;     /* run time,  in seconds,  to avoid   */
               int soft_limit, hard_limit;      /* runaway processes */

               if( sscanf( arg, "%d,%d", &soft_limit, &hard_limit) == 2)
                  {
                  r.rlim_cur = (rlim_t)soft_limit;
                  r.rlim_max = (rlim_t)hard_limit;
                  setrlimit( RLIMIT_CPU, &r);
                  }
               }
               break;
#endif
            case 's':
               sanity_test_observations( argv[1]);
               printf( "Sanity check complete\n");
               return( 0);
            case 'S':
               {
               char curr_time[50];

               full_ctime( curr_time, current_jd( ), FULL_CTIME_YMD);
               summary_ofile = fopen( arg, "wb");
               assert( summary_ofile);
               ifile = fopen_ext( "summ.htm", "fcrb");
               assert( ifile);
               while( fgets( tbuff, sizeof( tbuff), ifile))
                  {
                  text_search_and_replace( tbuff, "%TIME%", curr_time);
                  fputs( tbuff, summary_ofile);
                  }
               fclose( ifile);
               }
               break;
            case 't':
               if( argv[i][2] == 'e' || argv[i][2] == 'E')
                  {
                  double jd = get_time_from_string( curr_jd( ), argv[i] + 3,
                           CALENDAR_JULIAN_GREGORIAN | FULL_CTIME_YMD
                           | FULL_CTIME_TWO_DIGIT_YEAR, NULL);

                  if( argv[i][2] == 'e')
                     ephem_end_jd = jd;
                  else
                     {
                     extern double override_epoch_shown;

                     override_epoch_shown = jd;
                     }
                  }
               else
                  total_objects = atoi( arg);
               break;
            case 'v':
               use_colors = false;
               break;
            case 'z':
               use_config_directory = true;
               break;
            default:
               printf( "Unknown command-line option '%s'\n", argv[i]);
               return( -1);
            }
         }
   for( i = 1; i < argc; i++)
      {
      const char *tptr = strchr( argv[i], '=');

      if( tptr && argv[i][0] != '-')
         {
         const size_t len = tptr - argv[i];

         memcpy( tbuff, argv[i], len);
         tbuff[len] = '\0';
         set_environment_ptr( tbuff, argv[i] + len + 1);
         }
      }

               /* get_defaults( ) collects a lot of data that's for the  */
               /* interactive find_orb program.  But it also sets some   */
               /* important internal values for blunder detection,  etc. */
               /* So we still call it:                                   */
   get_defaults( &ephemeris_output_options,
                         NULL, &element_precision, NULL, NULL);
   if( all_heliocentric)
      forced_central_body = 0;
   if( ephem_option_string)
      ephemeris_output_options = (int)parse_bit_string( ephem_option_string);

   load_up_sigma_records( "sigma.txt");
   if( debug_level)
      debug_printf( "%d sigma recs read\n", i);

   if( argc < 2)
      {
      printf( "'fo' needs the name of an input file of MPC-formatted\n");
      printf( "astrometry as a command-line argument.\n");
      return( -2);
      }

   if( reset_astrometry_filename( argc, argv))
      drop_single_obs = false;

   ids = find_objects_in_file( argv[1], &n_ids, NULL);
   if( n_ids <= 0)
      {        /* no objects found,  or file not found */
      const char *err_msg;

      if( n_ids == -1)
         err_msg = "Couldn't locate the file";
      else
         err_msg = "No objects found in file";
      printf( "%s '%s'\n", err_msg, argv[1]);
      return( -1);
      }

   if( drop_single_obs)
      n_ids = remove_single_observation_objects( ids, n_ids);
   if( show_processing_steps)
      printf( "Processing %d objects\n", n_ids);
   if( !total_objects)
      total_objects = n_ids;

   t0 = update_time = time( NULL);
#ifdef FORKING
   while( process_count < n_processes - 1)
      {
      const pid_t childpid = fork( );

      if( childpid == -1)      /* fork( ) returns -1 on failure */
         {
         perror("fork"); /* display error message */
         exit(0);
         }
      else if( childpid == 0)     /* we're a child process */
         {
//       printf( "Hi!  I'm child %d.  My PID is %d; parent's is %d\n",
//                process_count, getpid( ), getppid( ));
         }
      else
         break;       /* break out of loop,  signalling we're a parent */
      process_count++;
      }
   if( n_processes > 1)
      process_count++;
   if( show_processing_steps)
      printf( "Process count %d\n", process_count);
#endif

   if( summary_ofile)
      summary_lines = (char **)calloc( n_ids - starting_object + 1,
                                                    sizeof( char *));
   ifile = fopen( argv[1], "rb");
   if( total_objects > n_ids - starting_object)
      total_objects = n_ids - starting_object;
   for( i = starting_object; i < starting_object + total_objects; i++)
      if( n_processes == 1 || i % n_processes == process_count - 1)
         {
         const char *orbit_constraints = "";
         OBSERVE FAR *obs;
         const int n_obs = ids[i].n_obs;

         if( n_processes == 1 && show_processing_steps)
            printf( "%d: %s", i + 1, ids[i].obj_name);
         if( n_obs < 2 && drop_single_obs)
            printf( "; skipping\n");
         else
            {
            extern int append_elements_to_element_file;
            extern int n_obs_actually_loaded;
            extern char orbit_summary_text[];
            long file_offset = ids[i].file_offset - 40L;
            int element_options = ELEM_OUT_ALTERNATIVE_FORMAT;
            double epoch_shown, curr_epoch, orbit[12];

            if( all_heliocentric)
               element_options |= ELEM_OUT_HELIOCENTRIC_ONLY;
                /* Start a bit ahead of the actual data,  just in case */
                /* there's a #Sigma: or similar command in there: */
            if( file_offset < 0L)
               file_offset = 0L;
            fseek( ifile, file_offset, SEEK_SET);
            obs = load_object( ifile, ids + i, &curr_epoch, &epoch_shown, orbit);

            if( (n_obs_actually_loaded > 1 || !drop_single_obs) && curr_epoch > 0.)
               {
               int n_obs_included = 0;
               unsigned j = 0;

               write_out_elements_to_file( orbit, curr_epoch, epoch_shown,
                     obs, n_obs_actually_loaded, orbit_constraints, element_precision,
                     0, element_options);
               strcpy( tbuff, orbit_summary_text);
               if( use_colors)
                  colorize_text( tbuff);
               if( show_processing_steps)
                  {
                  if( n_processes > 1)
                     {
                     if( process_count == 1 && time( NULL) != update_time)
                        {
                        int elapsed, n_done = i - starting_object + 1;

                        update_time = time( NULL);
                        elapsed = (int)update_time - (int)t0;
                        printf( "%d seconds elapsed, %d remain\n", elapsed,
                               elapsed * (total_objects - n_done) / n_done);
                        }
                     printf( "(%d) %d: %s", process_count, i + 1, ids[i].obj_name);
                     }
                  printf( "; %s ", tbuff);
                  }
               if( separate_residual_file_name)
                  {
                  extern bool residual_file_in_config_dir;

                  residual_file_in_config_dir = false;
                  write_residuals_to_file( separate_residual_file_name, argv[1],
                               n_obs_actually_loaded, obs, RESIDUAL_FORMAT_PRECISE
                               | RESIDUAL_FORMAT_COMPUTER_FRIENDLY
                               | RESIDUAL_FORMAT_FOUR_DIGIT_YEARS
                               | RESIDUAL_FORMAT_EXTRA);
                  residual_file_in_config_dir = true;
                  }
               if( !mpec_path)
                  append_elements_to_element_file = 1;
               if( mpec_path || !is_default_ephem)
                  {
                  int n_orbits_in_ephem = 1;
                  int n_ephemeris_steps = 50;
                  char ephemeris_step_size[20];
                  extern const char *ephemeris_filename;
                  extern const char *residual_filename;
                  extern int available_sigmas;
                  extern double ephemeris_mag_limit;
                  double *orbits_to_use = orbit;
                  const double jd_start = get_time_from_string( curr_jd( ),
                           get_environment_ptr( "EPHEM_START"),
                           CALENDAR_JULIAN_GREGORIAN | FULL_CTIME_YMD
                           | FULL_CTIME_TWO_DIGIT_YEAR, NULL);

                  sscanf( get_environment_ptr( "EPHEM_STEPS"), "%d %9s",
                         &n_ephemeris_steps, ephemeris_step_size);
                  if( ephem_end_jd)
                     {
                     n_ephemeris_steps = 1;
                     snprintf( ephemeris_step_size,
                           sizeof( ephemeris_step_size),
                           "%f", ephem_end_jd - jd_start);
                     }
                  if( !*mpc_code)
                     sscanf( get_environment_ptr( "CONSOLE_OPTS"), "%9s",
                                 mpc_code);
                  create_obs_file( obs, n_obs_actually_loaded, 0);
                  ephemeris_mag_limit = 999.;
                  if( available_sigmas == COVARIANCE_AVAILABLE)
                     {
                     n_orbits_in_ephem = 2;
                     compute_variant_orbit( orbit + 6, orbit, 1.);
                     }
                  if( available_sigmas == SR_SIGMAS_AVAILABLE)
                     {
                     extern double *sr_orbits;
                     extern unsigned n_sr_orbits;

                     orbits_to_use = sr_orbits;
                     n_orbits_in_ephem = n_sr_orbits;
                     }
                  if( !ephemeris_in_a_file_from_mpc_code( ephemeris_filename,
                              orbits_to_use, obs, n_obs_actually_loaded,
                              curr_epoch, jd_start, ephemeris_step_size,
                              n_ephemeris_steps, mpc_code,
                              ephemeris_output_options,
                              n_orbits_in_ephem))
                     {
                     write_residuals_to_file( residual_filename, argv[1],
                                    n_obs_actually_loaded, obs, RESIDUAL_FORMAT_SHORT);
                     if( mpec_path)
                        {
                        char fullpath[100];

                        sprintf( fullpath, "%s/%s.htm", mpec_path, ids[i].packed_desig);
                        text_search_and_replace( fullpath, " ", "");

                        make_pseudo_mpec( fullpath, ids[i].obj_name);
                        get_summary_info( tbuff, fullpath);
                        if( summary_ofile)
                           {
                           FILE *ephemeris_ifile = fopen_ext( ephemeris_filename, "tfcrb");
                           char new_line[420];

                           tbuff[14] = '\0';
                           snprintf( new_line, sizeof( new_line), "<a href=\"%s\">%s</a>%s",
                                    fullpath, tbuff, tbuff + 15);
                           memset( tbuff, 0, sizeof( tbuff));
                           while( j < 4 && fgets_trimmed( tbuff, sizeof( tbuff),
                                                         ephemeris_ifile))
                              j++;
                           if( j == 4)
                              {
                              tbuff[23] = tbuff[39] = tbuff[73] = '\0';
                              sprintf( new_line + strlen( new_line), "  %s  %s  %s",
                                       tbuff + 15, tbuff + 30, tbuff + 57);
                                             /* now add sigma from end of ephem: */
                              while( fgets_trimmed( tbuff, sizeof( tbuff), ephemeris_ifile))
                                 ;
                              tbuff[73] = '\0';
                              sprintf( new_line + strlen( new_line), "%s", tbuff + 68);
                              }
                           fclose( ephemeris_ifile);
                           summary_lines[n_lines_written]
                                      = (char *)malloc( strlen( new_line) + 1);
                           strcpy( summary_lines[n_lines_written], new_line);
                           n_lines_written++;
                           }
                        }
                     }
                  }

               for( j = 0; j < (unsigned)n_obs_actually_loaded; j++)
                  if( obs[j].is_included)
                     n_obs_included++;
               if( n_obs_included != n_obs_actually_loaded
                              && show_processing_steps)
                  {
                  if( use_colors)        /* reverse colors to draw attn */
                     printf( "\033[30;47m");
                  printf( " %d /", n_obs_included);
                  }
               }
            else
               printf( "; not enough observations\n");
            unload_observations( obs, n_obs_actually_loaded);
            }
         object_comment_text( tbuff, ids + i);
                  /* Abbreviate 'observations:' to 'obs:' */
         text_search_and_replace( tbuff, "ervations", "");
         if( show_processing_steps)
            printf( "  %s\n", tbuff);
         if( use_colors)
            printf( "\033[0m");
         }
   free( ids);
   if( summary_ofile)
      {
      int pass;

      for( pass = 0; pass < 4; pass++)
         {
         const char *headers[4] = {
               "<h3><a name=\"desig\">Sorted by designation</a></h3>",
               "<h3><a name=\"unc\">Sorted by current ephemeris uncertainty</a></h3>",
               "<h3><a name=\"moid\">Sorted by Earth MOID</a></h3>",
               "<h3><a name=\"mag\">Sorted by magnitude</a></h3>" };
         const char *ephem_header =
             "Object            Semimajor axis    Eccentricity        Incl         "
             "MOID           RA        dec      Elong mag  Sig1  Sig2";

         fprintf( summary_ofile, "\n%s\n", headers[pass]);
         fprintf( summary_ofile, "%s\n\n", ephem_header);
         if( pass)
            {
            static int columns[] = { 0, 123, 77, 118 };

            summ_sort_column = columns[pass];
            qsort( summary_lines, n_lines_written, sizeof( char *), summ_compare);
            }
         for( i = 0; summary_lines[i]; i++)
            {
            fprintf( summary_ofile, "%s%s", summary_lines[i],
                ( i % 5 == 4) ? "\n\n" : "\n");
            }
         }
      for( i = 0; summary_lines[i]; i++)
         free( summary_lines[i]);
      free( summary_lines);
      fprintf( summary_ofile, "</body> </html>\n");
      fclose( summary_ofile);
      }
   fclose( ifile);
#ifdef FORKING
   if( show_processing_steps)
      printf( "Process %d is done\n", process_count);
   wait( &child_status); /* wait for child to exit, and store its status */
   if( process_count == 1)
      {
      extern const char *elements_filename;
      extern const char *mpc_fmt_filename;

      combine_element_files( elements_filename, n_processes);
      combine_element_files( mpc_fmt_filename, n_processes);
      combine_element_files( sof_filename, n_processes);
      combine_element_files( sofv_filename, n_processes);
      for( i = 0; i < n_processes; i++)
         {                             /* clean up temp files: */
         process_count = i + 1;
         unlink_config_file( "monte.txt");
         unlink_config_file( "guide.txt");
         unlink_config_file( "covar.txt");
         unlink_config_file( "sr_elems.txt");
         unlink_config_file( "mpc_sr.txt");
//       unlink_config_file( sof_filename);
         }
      }
#ifdef TEST_PLANET_CACHING_HASH_FUNCTION
   if( process_count == 0)
      {
      extern int64_t planet_ns;
      extern long total_n_searches, total_n_probes, max_probes_required;

      printf( "  tp:%ld.%09ld\n",
                  (long)( planet_ns / (int64_t)1000000000),
                  (long)( planet_ns % (int64_t)1000000000));
      printf( "%ld searches; %ld probes; %ld max probes\n",
                  total_n_searches, total_n_probes, max_probes_required);
      }
#endif
#endif
   clean_up_find_orb_memory( );
   return( 0);
}
Example #5
0
int main( const int argc, const char **argv)
{
   FILE *ifile = fopen( argv[1], "rb");
   char buff[200], results[6][100];
   char exp_text[100];
   double roll_ang = 0.;

   assert( ifile);
   *exp_text = '\0';
   printf( "# (J95) Great Shefford logs,  processed with j95_xvt.c (q.v.)\n");
#ifdef __TIMESTAMP__
   printf( "# Source file date %s\n", __TIMESTAMP__);
#else
   printf( "# Version %s %s\n", __DATE__, __TIME__);
#endif
   printf( "# Input file '%s'\n", argv[1]);
   while( fgets( buff, sizeof( buff), ifile))
      {
      size_t i, j, k;
      double jd;
      char *time_str = results[1];

      for( i = j = 0; buff[i]; i++)    /* remove quote marks */
         if( buff[i] != '"')
            buff[j++] = buff[i];
      buff[j] = '\0';
      for( i = j = 0; i < 6; i++)
         {
         k = j;
         while( buff[k] != ',' && buff[k] >= ' ')
            k++;
         assert( k > j);
         assert( buff[k] == ',' || i == 5);
         memcpy( results[i], buff + j, k - j);
         results[i][k - j] = '\0';
         j = k + 1;        /* skip the comma */
         }
      jd = get_time_from_string( 0., time_str, FULL_CTIME_DMY, NULL);
      if( jd > 2e+6)
         {
         const double exposure_time = atof( results[4]) / seconds_per_day;
         const double ra = get_angle( results[2]) * 15.;
         const double dec = get_angle( results[3]);
         const double new_roll_ang = atof( results[5]);

         if( strcmp( exp_text, results[4]))
            {
            strcpy( exp_text, results[4]);
            printf( "# Exposure: %s s\n", exp_text);
            }
         if( fabs( roll_ang - new_roll_ang) > .5)
            {
            roll_ang = new_roll_ang;
            printf( "# Tilt: %.1f\n", roll_ang);
            }
         jd += exposure_time / 2.;
         full_ctime( time_str, jd, FULL_CTIME_YMD | FULL_CTIME_MILLISECS
                        | FULL_CTIME_MONTHS_AS_DIGITS | FULL_CTIME_LEADING_ZEROES);
         time_str[4] = time_str[7] = '-';
         time_str[10] = 'T';
         printf( "%.3f,%.3f,%s,J95,%s\n",
                              ra, dec, time_str, results[0]);
         }
      }
   fclose( ifile);
   return( 0);
}
Example #6
0
double DLL_FUNC get_time_from_string( double initial_jd,
         const char *time_str, const int time_format, int *is_ut)
{
   const double J2000 = 2451544.5;         /* 1.0 Jan 2000 = JD 2451544.5 */
   const int calendar = (time_format & CALENDAR_MASK);
            /* Certain solar-lunar calendars can have 13 months in a year: */
   const int max_month =
             ((calendar == CALENDAR_HEBREW || calendar == CALENDAR_CHINESE)
                    ? 13 : 12);
   int iday, month, hour, minute, n_bytes;
   int ival, i, colon_found = 0, is_bc = 0;
   int am_pm_indicator = AM_PM_UNSET;
   long year;
   double sec, dday;
   double rval = 0., offset = 0., tval;
   char buff[80];
   char symbol = 0;
   char *str = buff;

   if( is_ut)
      *is_ut = 0;
   while( *time_str == ' ')         /* skip leading spaces */
      time_str++;
   if( strlen( time_str) >= sizeof( buff) || !*time_str)
      return( initial_jd);       /* check/avoid possible buffer overflow */
             /* Ensure spaces between letters and digits.  For example,   */
             /* if time_str="11Nov 1918",  set str="11 Nov 1918".         */
             /* 'Q' is an exception to avoid '1q' becoming '1 q'.         */
   *str = tolower( *time_str++);
   i = 1;
   while( (size_t)i < sizeof( buff) - 1 && *time_str)
      {
      if( (isalpha( *time_str) && isdigit( time_str[-1]))
                         || (isdigit( *time_str) && isalpha( time_str[-1])))
         if( *time_str != 'q' && *time_str != 'Q')
            str[i++] = ' ';
      str[i++] = (char)tolower( *time_str++);
      }
   str[i] = '\0';
   remove_trailing_spaces( str);
   while( *str && (tval = collect_time_offset( str)) != 0.)
      {
      remove_trailing_spaces( str);
      offset += tval;
      }

   i = strlen( str);
   if( i > 1)
      {
      const int phase = get_phase_idx( str + i - 2);

      if( phase != PHASE_IDX_UNDEFINED)
         {
         str[i - 2] = '\0';
         rval = get_time_from_string( initial_jd, str, time_format, NULL);
         if( rval && is_ut)
            *is_ut = 1;
         return( set_from_lunar( phase, rval) + offset);
         }
      }

   is_bc = check_for_bc( str);

   if( *str == 'j')           /* decimal JD */
      {                       /* may begin with 'j' or 'jd' */
      if( str[1] == 'd')
         str++;
      rval = atof( str + 1);
      if( rval && is_ut)
         *is_ut = 1;
      }

   if( *str == 'y')      /* decimal years */
      rval = J2000 + (atof( str + 1) - 2000.) * 365.25;

   if( !memcmp( str, "mjd", 3))                 /* modified JD */
      {
      rval = atof( str + 3) + 2400000.5;
      if( is_ut)
         *is_ut = 1;
      }

   if( !memcmp( str, "now", 3))
      {
      static const double jan_1970 = 2440587.5;

      str += 3;
      while( *str == ' ')
         str++;
      initial_jd = jan_1970 + (double)time( NULL) / 86400.;
      }

   if( !*str)
      rval = initial_jd;

   if( rval)
      return( rval + offset);

               /* The common European format of separating day/month/year */
               /* with .s causes trouble,  because the code wants to see  */
               /* those as decimal numbers.  So if the input string starts */
               /* with three integers separated by dots,  we change both   */
               /* dots to '/' characters, then proceed normally:           */
   if( sscanf( str, "%d.%d.%d%n", &iday, &month, &hour, &n_bytes) == 3)
      for( i = 0; i < n_bytes; i++)
         if( str[i] == '.')
            str[i] = '/';

   sec = split_time( initial_jd, &year, &month, &iday, &hour,
                                         &minute, calendar);

               /* FITS times are always in the form YYYY-MM-DDTHH:MM:SS, */
               /* sometimes followed by .S.  This is handled separately, */
               /* in part to ensure that the month and day don't get     */
               /* swapped around:  they are _always_ in that order. Also */
               /* note that after spaces are added and the 'T' lowercased, */
               /* it actually reads YYYY-MM-DD t HH:MM:SS.                 */
   i = strlen( str);
   if( i > 18 && str[11] == 't')
      if( str[4] == '-' && str[7] == '-' && str[15] == ':')
         {
         symbol = 'f';
         sscanf( str, "%ld-%d-%d", &year, &month, &iday);
         }

   if( i >= 4)
      {
      const char *search_text[4] = { " am", " a.m.", " pm", " p.m." };
      int j;

      for( j = 0; j < 4; j++)
         {
         const int slen = 3 + ((j & 1) << 1);

         if( !strcmp( str + i - slen, search_text[j]))
            {
            i -= slen;
            str[i] = '\0';
            am_pm_indicator = (j >= 2 ? AM_PM_SET_TO_PM :
                                        AM_PM_SET_TO_AM);
            j = 4;   /* break out of loop */
            }
         }
      }

            /* If the input text ends with something containing ':'s,     */
            /* assume there is a time to be extracted.  Back up along the */
            /* string,  looking for the start of the time string (which   */
            /* may be the beginning of the string,  or just after a space, */
            /* or (for FITS input) just after a 'T'... for simplicity,     */
            /* that last test just checks for any alphabetical char.)      */
   for( i = strlen( str); i && str[i - 1] != ' ' && !isalpha( str[i - 1]); i--)
      if( str[i - 1] == ':')
         colon_found = 1;

   if( strcmp( str + i, ":"))
      {
      const int saved_hour = hour;

      minute = hour = 0;
      sec = 0.;
      if( colon_found)
         {
         double dminute = 0.;

         if( str[i] != ':')
            {
            sscanf( str + i, "%d:%lf:%lf", &hour, &dminute, &sec);
            sec += dminute * 60.;
            if( am_pm_indicator == AM_PM_SET_TO_AM)
               if( hour == 12)
                  hour = 0;
            if( am_pm_indicator == AM_PM_SET_TO_PM)
               if( hour != 12)
                  hour += 12;
            }
         else      /* :MM:SS means "leave the hour unchanged" */
            {
            hour = saved_hour;
            sscanf( str + i + 1, "%lf:%lf", &dminute, &sec);
            sec += dminute * 60.;
            }
         }
      }
   if( colon_found)           /* lop the time off, leaving only the date: */
      str[i ? i - 1 : 0] = '\0';

   dday = (double)iday;
   i = 0;
   if( *str && symbol != 'f')
      {
      for( i = 1; str[i] && !strchr( "-:/ ", str[i]); i++)
         ;
      symbol = str[i];
      }
   switch( symbol)
      {
      case 'f':               /* FITS-format time: see above */
         break;
      case ':':               /* time of day */
         break;
      case '-':               /* dash-delimited such as '2009-01-20' */
      case ' ':               /* space-delimited format such as "25 dec 1980" */
      case '/':               /* common day/month/year dividing symbol */
         {
         int month_found = 0, n_fields_found = 2;
         int year_found = 0, day_found = 0;
         char tstr[80];
         double ivals[3];

         memcpy( tstr, str, i);
         tstr[i] = '\0';
         ival = month_name_to_index( tstr);
         if( ival)         /* month given first, such as 'jan 25' */
            {
            month_found = 1;
            ivals[0] = (double)ival;
            }
         else
            {
            ivals[0] = atof( tstr);
            if( strchr( tstr, '.'))   /* decimal day given */
               day_found = 1;
            }
         str += i + 1;
         for( i = 0; str[i] && str[i] != symbol && str[i] != ' '; i++)
            ;
         memcpy( tstr, str, i);
         tstr[i] = '\0';
         str += i;
         ival = month_name_to_index( tstr);
         if( ival)         /* month given second, such as '25-jan' */
            {
            month_found = 2;
            ivals[1] = (double)ival;
            }
         else
            {
            ivals[1] = atof( tstr);
            if( strchr( tstr, '.'))   /* decimal day given */
               day_found = 2;
            }

         if( *str == symbol)     /* maybe a third field was entered, but */
            {                       /* could be a time;  check for a ':' */
            str++;
            if( sscanf( str, "%79s", tstr) == 1)
               if( (ival = month_name_to_index( tstr)) != 0)
                  {
                  month_found = 3;
                  n_fields_found = 3;
                  ivals[2] = (double)ival;
                  str += strlen( tstr);
                  }
            if( n_fields_found == 2)
               if( sscanf( str, "%lf%n", &ivals[2], &n_bytes) == 1)
                  if( str[n_bytes] != ':')
                     {
                     str += n_bytes;
                     if( strchr( tstr, '.'))
                        day_found = 3;
                     n_fields_found = 3;
                     }
            }
                     /* if one of the fields is negative, or if it's    */
                     /* greater than 32 and is the largest entry,  it   */
                     /* can be assumed to be the year:                  */
         for( i = 0; i < n_fields_found; i++)
            if( ivals[i] < 0.)
               {
               year_found = i + 1;   /* if we see a negative number, */
               i = n_fields_found;   /* we can stop looking further: */
               }
            else if( ivals[i] > 32.)
               if( !year_found || ivals[i] > ivals[year_found - 1])
                  year_found = i + 1;
         if( year_found || n_fields_found == 2)
            for( i = 0; i < n_fields_found; i++)
               if( ivals[i] > (double)max_month + .0001 && ivals[i] < 32.
                                      && i + 1 != year_found)
                  day_found = i + 1;

         if( n_fields_found == 2)
            {
            if( month_found)
               {
               double dval = ivals[2 - month_found];

               month = (int)ivals[month_found - 1];
               if( dval > .999 && dval < 32.)
                  dday = dval;
               else
                  year = (int)dval;
               }
            else if( year_found)         /* year/day of year format: */
               {
               year = (int)ivals[year_found - 1];
               month = 1;
               dday  = ivals[2 - year_found];
               }
            else if( day_found)     /* day/month, order is clear from */
               {                    /* the day being > 12 or having a decimal*/
               dday = ivals[day_found - 1];
               month = (int)ivals[2 - day_found];
               }
            else    /* can't tell what's day/month/year solely from input: */
               if( (time_format & FULL_CTIME_MONTH_DAY) || symbol == 'f')
                  {
                  month = (int)ivals[0];
                  dday = (int)ivals[1];
                  }
               else              /* day/month */
                  {
                  month = (int)ivals[1];
                  dday = (int)ivals[0];
                  }
            }
         else        /* three fields entered: */
            {
            const int year_first = (time_format & FULL_CTIME_YEAR_FIRST);

            if( !year_found)
               {
               if( !month_found)
                  {
                  if( !day_found || day_found == 2)
                     {
                     year_found = (year_first ? 1 : 3);
                     if( !day_found)   /* must rely solely on time format */
                        {              /* settings;  no fields autofound  */
                        day_found = (year_first ? 2 : 1);
                        if( (time_format & FULL_CTIME_MONTH_DAY) || symbol == 'f')
                           day_found++;      /* ymd or mdy case */
                        }
                     }
                  else     /* if day is 1st or last, year is last or 1st */
                     year_found = 4 - day_found;
                  }
               else if( !day_found)    /* only the month was found: */
                  {
                  if( month_found == 2)
                     year_found = (year_first ? 1 : 3);
                  else   /* if month is 1st or last, year must be last/1st */
                     year_found = 4 - month_found;
                  }
               }
            else        /* year_found... */
               if( !month_found && !day_found)  /* ...but nothing else */
                  {
                  if( (time_format & FULL_CTIME_MONTH_DAY) || symbol == 'f')
                     month_found = (year_found == 1 ? 2 : 1);
                  else
                     day_found = (year_found == 1 ? 2 : 1);
                  }
                  /* We now have the year nailed down.  If either the day */
                  /* or month is still not nailed down, we can find it    */
                  /* easily, since the 'found' values must sum up to 6:   */

            if( !day_found)
               day_found = 6 - year_found - month_found;
            else if( !month_found)
               month_found = 6 - year_found - day_found;
            year = (int)floor( ivals[year_found - 1] + .5);
            dday = ivals[day_found - 1];
            month = (int)( ivals[month_found - 1] + .5);
            }

         if( year > 0 && year < 100 && !is_bc)
            if( time_format & FULL_CTIME_TWO_DIGIT_YEAR)
               year += (year < 40 ? 2000 : 1900);
         }
         break;
      case '\0':       /* no dividing symbols found */
         if( *str)
            {
            ival = month_name_to_index( str);
            if( ival)
               month = ival;
            else if( (ival = day_of_week_name_to_index( str)) >= 0)
               {
               ival -= ((long)(initial_jd + 1.5)) % 7;
               if( ival < -3)
                  ival += 7;
               else if( ival > 3)
                  ival -= 7;
               dday += ival;
               }
            else
               {
               n_bytes = 0;
               if( sscanf( str, "%d%n", &ival, &n_bytes) == 1)
                  {
                  double tval = 0.;

                  str += n_bytes;
                  if( *str == '.')     /* also a fractional part to this: */
                     {
                     int n_bytes_in_fraction;

                     sscanf( str, "%lf%n", &tval, &n_bytes_in_fraction);
                     str += n_bytes_in_fraction;
                     }
                  tval += (double)ival;
                  switch( n_bytes)
                     {
                     case 1:
                     case 2:                 /* reset day */
                        dday = tval;
                        break;
                     case 3:                 /* reset day of year */
                        dday = tval;
                        month = 1;
                        break;
                     case 4:                 /* reset year, which may be */
                     case 5:                 /* four or five digits long */
                        if( (double)ival == tval)
                           {                    /* set 1 Jan of the year */
                           dday = 1.;
                           month = 1;
                           year = ival;
                           }
                        else        /* true decimal year */
                           return( J2000 + (tval - 2000.) * 365.25 + offset);
                        break;
                     case 7:               /* JD */
                        if( is_ut)
                           *is_ut = 1;
                        return( tval + offset);
                     case 6:     /* YYMMDD(.DD)   */
                     case 8:     /* YYYYMMDD(.DD) */
                        year = ival / 10000L;
                        if( n_bytes == 6)
                           year += (year < 40 ? 2000 : 1900);
                        month = (ival / 100) % 100L;
                        dday = (double)( ival % 100L);
                        dday += tval - (double)ival;
                        break;
                     }
                  }
               else        /* couldn't make sense of input text */
                  return( 0.);
               }
            }
         break;
      default:
         return( 0.);
//       break;
      }

   if( is_bc)
      year = 1 - year;
   iday = (int)dday;
   dday -= (double)iday;
   rval = (double)dmy_to_day( iday, month, year, calendar) + dday - .5 +
                 (double)hour / 24. + (double)minute / 1440. + sec / 86400.;
   return( rval + offset);
}