#!/usr/local/bin/perl -w { # timecnv.pl WJS Jun 97 # Uses defgb to translate julian date <--> gregorian date and/or do # time zone conversions. # Input is a set of environment variables (see below). Output is # from an defgb command appropriate to do the desired conversions # Set environment variable $debug_env_var (currently TIMECNV_DEBUG) # to print debugging info. Setting this also sets debug mode for # pid_file_cleanup so that temp files are not cleaned up. This cleanup # switch can also be set independently - see pid_file_cleanup. $version = "timecnv.pl version 1.0 1 Oct 1997"; # 1 Oct 1997. WJS # Temporary object logic # 25 Sep 1997. WJS # "Widthify" by getting [width=] attribute from listvar 1.2 # For defgb 3.0, assume width is only attribute, and make dispwidths # file. defgb 3.1 will allow attributes in varlist file - much better. # 19 Sep 1997. WJS # Expect many defns from timecnv_driver.pl via hidden variables. # Allow integral Julian days/frac years, w/separate time input. # Not sure defgb will allow it at the moment, but... # Stuff doesn't come off form quite as I expected. As now coded, # cannot get null or missing val for most. Of course, coding could # change, so code for both. Sigh. # 28 Aug 1997. WJS # Mods to match html form. # Use CgiDie # 26 Aug 1997. WJS # [Needs pid_file_cleanup v 1.0] # [Needs make_path_info_string v 1.0] # [Needs parse_path_info v 1.0] # [Needs cgi-lib.pl. Got from internet via Chris' pointer] # [Begin 1.0] require ("cgi-lib.pl"); require ("pid_file_cleanup.pl"); $pid_file_cleanup_debug_env_var = "PID_FILE_CLEANUP_DEBUG"; chomp ($date = `date`); # Get input info # Form includes lots of stuff including # Variable name "on form" Value # path_info "Original" PATH_INFO (w/html escapes removed) # query_string "Original" QUERY_STRING (w/html escapes removed) # See also "File locations" and "Form input fields" &ReadParse(*form_input) || &CgiDie ($err_header,"Could not or did not get input from form\n"); ### # File locations, etc. If not passed along, default them (hence seeming # duplication of pieces of file information). # Communication here is w/timecnv_driver.pl, not the user via the form # Variable name "on form" Value # unique Some string unique to this timecnv job # jgofs_root Directory # object_root Directory (absolute) from which directories # that contain .objects files descend # util_dir Directory (absolute) containing path_info stuff # tmpdir[sic] Directory (absolute) for temp files # bin_dir Directory (absolute) containing listvar # method_dir Directory (absolute) containing defgb # object_dir Directory (relative to object root) con- # taining .objects file for temporary objects # listvar File spec (absolute) for listvar # make_path_info File spec (absolute) for make_path_info_string # parse_path_info File spec (absolute) for parse_path_info # defgb File spec (absolute) for defgb (defined($unique = $form_input{"unique"})) || ($unique = $$); # Directories (defined($jgofs_root = $form_input{"jgofs_root"})) || ($jgofs_root = "/data/globec"); (defined($object_root = $form_input{"object_root"})) || ($object_root = "$jgofs_root/objects"); (defined($util_dir = $form_input{"util_dir"})) || ($util_dir = "/export/home/wsass"); (defined($tmpdir = $form_input{"tmpdir"})) || ($tmpdir = "/tmp"); (defined($bin_dir = $form_input{"bin_dir"})) || ($bin_dir = "$jgofs_root/bin"); (defined($method_dir = $form_input{"method_dir"})) || ($method_dir = "$jgofs_root/methods"); (defined($object_dir = $form_input{"object_dir"})) || ($object_dir = "/tempobjects/globecwhoiedu"); # Programs (defined($listvar = $form_input{"listvar"})) || ($listvar = "$bin_dir/listvar"); (defined($make_path_info = $form_input{"make_path_info"})) || ($make_path_info = "$util_dir/make_path_info_string"); (defined($parse_path_info = $form_input{"parse_path_info"})) || ($parse_path_info = "$util_dir/parse_path_info"); (defined($defgb = $form_input{"defgb"})) || ($defgb = "$method_dir/defgb"); # Data files # _$unique is indicator to cleanup routine that ALL files that look like # file_root except for the $unique are eligible for cleanup. Ergo, # file_root must be unique to timecnv work. See pid_file_cleanup.pl # Don't confuse $listvar_file (output from listvar; input to this # program) with $varlist_file (output from this program; varlist optional # file input to defgb) or with $listvar (the program itself) (defined($listvar_file = $form_input{"listvar_file"})) || ($listvar_file = ""); $obj_name = "timecnv_$unique"; $file_root = "$tmpdir/$obj_name"; $varlist_file = "$file_root.varlist"; $ind_file = "$file_root.ind"; $tdparams_file = "$file_root.timedateparams"; ### defgb 3.1: omit next line; mod @temp_files, below $dispwidths_file = "$file_root.dispwidths"; # Logically temporary for this program, so save list for cleanup @temp_files = ($varlist_file,$ind_file,$tdparams_file,$dispwidths_file); $listvar_file && push(@temp_files,$listvar_file); $object_file = "$object_root$object_dir/.objects"; $err_header = "Job $unique of $version"; $JGOFS_maxlevel = 9; # Following variable names come from Bob's thesaurus $official_UTC_suffix = "_UTC"; $official_local_suffix = "_local"; $official_year_var = "year"; $official_month_var = "month"; $official_day_var = "day"; $official_time_var = "time"; $official_yrday_var = "yrday"; $official_yrday0_var = "yrday0"; $debug_env_var = "TIMECNV_DEBUG"; ### # Form input fields # In addition to the ones immediately below, there are # in_object, which has the form's PATH_INFO in it, and # in_parameters, which has the form's QUERY_STRING # # Descriptions: permissible vals separated by slashes # "" means absence is significant beyond just "not specd" # (note that in general, can't get "" from a form) $inutcflag_inp_var = "in_location"; # In time "utc"/"local" # Kinds of time disp data $timedisp_inp_var = "in_timedisp_varname"; # Variable name/"" $timedispzone_inp_var = "in_timedisp_zone"; # Time zone $timedispzoneabbrv_inp_var = "in_timedisp_zonename";# Zone name abbrev $timedisphrs_inp_var = "in_timedisp_disp_hours"; # Hours $timedispmin_inp_var = "in_timedisp_disp_min"; # Minutes $timedispformat_inp_var = "in_timedisp_type"; # "name"/"zone"/"disp"/"" $gyear_inp_var = "in_g_year"; # Year data (a varname)/"" $gcentury_inp_var = "in_g_century"; # Century (19 or 20)/"" $gdecade_inp_var = "in_g_decade"; # Decade (0-9)/"" $gdecade_year_inp_var = "in_g_yr"; # Year within decade (0-9)/"" $jyear_inp_var = "in_j_year"; # Year data (a varname)/"" $jcentury_inp_var = "in_j_century"; # Century (19 or 20)/"" $jdecade_inp_var = "in_j_decade"; # Decade (0-9)/"" $jdecade_year_inp_var = "in_j_yr"; # Year within decade (0-9)/"" $month_inp_var = "in_month"; # Month data (a varname) $monthformat_inp_var = "in_month_fmt"; # "integer"/"alpha" (11 or Nov) $day_inp_var = "in_day"; # Day data (a varname) $dayformat_inp_var = "in_day_fmt"; # "DD"/"DD.DDDD" (12 or 12.2) $timepiecesflag_inp_var = "in_time"; # "separate"/"combo-secs"/ # "combined"/"julian" $hour_inp_var = "in_t_hour"; # Hour data (a varname) $minute_inp_var = "in_t_minutes"; # Minute data (a varname) $second_inp_var = "in_t_seconds"; # Second data (a varname) $hourmin_inp_var = "in_t_hourmin"; # Combined hour/min data # (a varname) $hourminformat_inp_var = "in_t_hrminfmt"; # "HHMM"/"HHMM.MMMM" $hourminsec_inp_var = "in_t_hrminsecs"; # Combined hour/min/sec data # (a varname) $hourminsecformat_inp_var = "in_t_hrminsecfmt"; # "HH:MM:SS.SSSS"/"HH.HHHH" $injulday1jan_inp_var = "in_j_jan1"; # "day_0"/"day_1" $maxdaysinyear_inp_var = "in_j_365yr"; # "normal"/"fixed" (normal/ignore leap) $injulianflag_inp_var = "in_j_dayyr"; # "jday"/"fracyear" $julian_inp_var = "in_j_name"; # Julian data (a varname) $oututcflag_inp_var = "out_location"; # Out time "utc"/"local" $outjulgreg_inp_var = "out_calendar"; # Out time "julian"/"gregorian" $outjulday1jan_inp_var = "out_jan1"; # "day_0"/"day_1" $outjulianflag_inp_var = "out_j_fmt"; # "Julian_day"/"Julian_year" ### # Be sure all vars are defined (defined($debug = $ENV{$debug_env_var})) || ($debug = ""); (defined($timedisp = $form_input{$timedisp_inp_var})) || ($timedisp = ""); (defined($timedispzone = $form_input{$timedispzone_inp_var})) || ($timedispzone = ""); (defined($timedispzoneabbrv = $form_input{$timedispzoneabbrv_inp_var})) || ($timedispzoneabbrv = ""); (defined($timedisphrs = $form_input{$timedisphrs_inp_var})) || ($timedisphrs = ""); (defined($timedispmin = $form_input{$timedispmin_inp_var})) || ($timedispmin = ""); (defined($timedispformat = $form_input{$timedispformat_inp_var})) || ($timedispformat = ""); (defined($inutcflag = $form_input{$inutcflag_inp_var})) || ($inutcflag = ""); (defined($jyear = $form_input{$jyear_inp_var})) || ($jyear = ""); (defined($jcentury = $form_input{$jcentury_inp_var})) || ($jcentury = ""); (defined($jdecade = $form_input{$jdecade_inp_var})) || ($jdecade = ""); (defined($jdecade_year = $form_input{$jdecade_year_inp_var})) || ($jdecade_year = ""); (defined($gyear = $form_input{$gyear_inp_var})) || ($gyear = ""); (defined($gcentury = $form_input{$gcentury_inp_var})) || ($gcentury = ""); (defined($gdecade = $form_input{$gdecade_inp_var})) || ($gdecade = ""); (defined($gdecade_year = $form_input{$gdecade_year_inp_var})) || ($gdecade_year = ""); (defined($month = $form_input{$month_inp_var})) || ($month = ""); (defined($monthformat = $form_input{$monthformat_inp_var})) || ($monthformat = ""); (defined($day = $form_input{$day_inp_var})) || ($day = ""); (defined($dayformat = $form_input{$dayformat_inp_var})) || ($dayformat = ""); (defined($timepiecesflag = $form_input{$timepiecesflag_inp_var})) || ($timepiecesflag = ""); (defined($hour = $form_input{$hour_inp_var})) || ($hour = ""); # Form does not ask for next variable. Derived in code below # (defined($hourformat = $form_input{$hourformat_inp_var})) # || ($hourformat = ""); $hourformat = ""; (defined($minute = $form_input{$minute_inp_var})) || ($minute = ""); # Form does not ask for next variable. Defaulted in code below # (defined($minuteformat = $form_input{$minuteformat_inp_var})) # || ($minuteformat = ""); $minuteformat = ""; (defined($second = $form_input{$second_inp_var})) || ($second = ""); # Form does not ask for next variable. Defaulted in code below # (defined($secondformat = $form_input{$secondformat_inp_var})) # || ($secondformat = ""); $secondformat = ""; (defined($hourmin = $form_input{$hourmin_inp_var})) || ($hourmin = ""); (defined($hourminformat = $form_input{$hourminformat_inp_var})) || ($hourminformat = ""); (defined($hourminsec = $form_input{$hourminsec_inp_var})) || ($hourminsec = ""); (defined($hourminsecformat = $form_input{$hourminsecformat_inp_var})) || ($hourminsecformat = ""); (defined($julian = $form_input{$julian_inp_var})) || ($julian = ""); (defined($injulianflag = $form_input{$injulianflag_inp_var})) || ($injulianflag = ""); (defined($injulday1jan = $form_input{$injulday1jan_inp_var})) || ($injulday1jan = ""); (defined($maxdaysinyear = $form_input{$maxdaysinyear_inp_var})) || ($maxdaysinyear = ""); (defined($oututcflag = $form_input{$oututcflag_inp_var})) || ($oututcflag = ""); (defined($outjulgreg = $form_input{$outjulgreg_inp_var})) || ($outjulgreg = ""); (defined($outjulday1jan = $form_input{$outjulday1jan_inp_var})) || ($outjulday1jan = ""); (defined($outjulianflag = $form_input{$outjulianflag_inp_var})) || ($outjulianflag = ""); if ($debug) { print "\n", " ... Running $version at $date. Job id = $unique\n", "defgb = $defgb\n", "listvar = $listvar\n", "make_path_info = $make_path_info\n", "parse_path_info = $parse_path_info\n", "temp directory = $tmpdir\n", "indirect temp file = $ind_file\n", "varlist temp file = $varlist_file\n", "timedateparams temp file = $tdparams_file\n", "temp objects' .objects file = $object_file\n", "Input variable names/values:\n", " $inutcflag_inp_var/$inutcflag\n", " $timedisp_inp_var/$timedisp\n", " $timedispzone_inp_var/$timedispzone\n", " $timedispzoneabbrv_inp_var/$timedispzoneabbrv\n", " $timedisphrs_inp_var/$timedisphrs\n", " $timedispmin_inp_var/$timedispmin\n", " $timedispformat_inp_var/$timedispformat\n", " $gyear_inp_var/$gyear\n", " $gcentury_inp_var/$gcentury\n", " $gdecade_inp_var/$gdecade\n", " $gdecade_year_inp_var/$gdecade_year\n", " $jyear_inp_var/$jyear\n", " $jcentury_inp_var/$jcentury\n", " $jdecade_inp_var/$jdecade\n", " $jdecade_year_inp_var/$jdecade_year\n", " $month_inp_var/$month\n", " $monthformat_inp_var/$monthformat\n", " $day_inp_var/$day\n", " $dayformat_inp_var/$dayformat\n", " $timepiecesflag_inp_var/$timepiecesflag\n", " $hour_inp_var/$hour\n", " $minute_inp_var/$minute\n", " $second_inp_var/$second\n", " $hourmin_inp_var/$hourmin\n", " $hourminformat_inp_var/$hourminformat\n", " $hourminsec_inp_var/$hourminsec\n", " $hourminsecformat_inp_var/$hourminsecformat\n", " $injulday1jan_inp_var/$injulday1jan\n", " $maxdaysinyear_inp_var/$maxdaysinyear\n", " $injulianflag_inp_var/$injulianflag\n", " $julian_inp_var/$julian\n", " $oututcflag_inp_var/$oututcflag\n", " $outjulgreg_inp_var/$outjulgreg\n", " $outjulday1jan_inp_var/$outjulday1jan\n", " $outjulianflag_inp_var/$outjulianflag\n", "\n"; } ### # Check or create temporary directory if (-e $tmpdir) { if (! -d $tmpdir) { &CgiDie ($err_header,"$tmpdir is not a directory\n") } if (! -w $tmpdir) { &CgiDie ($err_header, "Cannot create files in directory $tmpdir\n") } } else { mkdir ($tmpdir,0777) || &CgiDie($err_header,"Cannot create directory $tmpdir : $!\n"); } ### # Process input params into various lists, etc # We check a lot, but we don't check a lot. Eg, if a variable is # spec'd without a corresponding format, we probably skip it. # Another example: we don't check that there's any transformation # required at all; we don't even check if there's any input to transform. # defgb is probably the best diagnostic, but we try to catch stuff # here; esp. violations of interface between env vars and this routine. # Flag options invalid due to present (hopefully temporary!) # inadequacies in defgb $errtxt = ""; if ($injulianflag eq "fracyear") { $errtxt = "Sorry-cannot handle input fractional years at present"; } elsif ($outjulgreg eq "julian") { $errtxt = "Sorry-cannot output Julian data at present"; } ($errtxt eq "") || &CgiDie ($err_header,"$errtxt\n"); $ninput_vars = 0; # List of variables that must be in input data (according to env vars) $needed_input_vars = ""; # List of variables to hold output. Usually we must generate these, # but they might be in the object $needed_output_vars = ""; # List of required input that is NOT in object. Presently this is # confined to year and time displacement info. Determined by flag env # var that says data env var is either varname or data. If flag says # "data", we generate a level 0 variable to hold it. Note that this # variable name must NOT be in object $generated_input_vars = ""; $lev0_data = ""; # String of form # intimeconvention = UTC/local # outtimeconvention = UTC/local # invar1name = var1name; invar1format = fmt1_string # invar2name = var2name; invar2format = fmt2_string # . # . # invarNname = varNname; invarNformat = fmtN_string # outmonthvar = varname # . # . # etc. See defgb doc for format of this string, fmt_strings, etc # This stuff is the guts of the whole matter. $tdparams_string = ""; # Input time convention if ($inutcflag eq "") { $in_suffix = ""; } else { if ($inutcflag eq "utc") { $in_suffix = $official_UTC_suffix } elsif ($inutcflag eq "local") { $in_suffix = $official_local_suffix } else { &CgiDie ($err_header, "Unrecognized input utc flag. Value = $inutcflag\n") } $tdparams_string .= "intimeconvention = $inutcflag\n"; } # Input time displacement stuff # This is difference between local and UTC # regardless of whether times are local or UTC if ($timedispformat ne "") { if ($timedisp eq "") { # data from form; generate var name & format # $generated_input_vars .= (some name depending on format. See thesaurus) . " "; $timedisp = "timedispvar"; $generated_input_vars .= "timedispvar "; if ($timedispformat eq "name") { # At least 3 letters/digits. Only 3 defined at moment, but... if ($timedispzoneabbrv =~ /^\w{3,}$/) { $lev0_data .= $timedispzoneabbrv } else { &CgiDie ($err_header, "Unrecognized time zone name format.", "Value = $timedispzoneabbrv\n") } } elsif ($timedispformat eq "zone") { # 0, or +- followed by 1 or 2 digits if ($timedispzone =~ /^(0|[+-]\d{1,2})$/) { $lev0_data .= $timedispzone } else { &CgiDie ($err_header, "Unrecognized time zone format.", "Value = $timedispzone\n") } } elsif ($timedispformat eq "disp") { # 00, or +- followed by 2 digits if ($timedisphrs =~ /^(00|[+-]\d\d)$/) { $lev0_data .= $timedisphrs } else { &CgiDie ($err_header, "Unrecognized time displacement hours format.", "Value = $timedisphrs\n") } if ($timedispmin =~ /^\d\d$/) { $lev0_data .= $timedispmin } else { &CgiDie ($err_header, "Unrecognized time displacement minute format.", "Value = $timedispmin\n") } } $lev0_data .= " "; } else { # data in object &add_needed_var ($timedisp); } $tdparams_string .= "invar" . ++$ninput_vars . "name = $timedisp; " . "invar" . $ninput_vars . "template = "; if ($timedispformat eq "name") { $tdparams_string .= "ZZZZZZ\n" } elsif ($timedispformat eq "zone") { $tdparams_string .= "zzz\n" } elsif ($timedispformat eq "disp") { $tdparams_string .= "RRRRR\n" } else { &CgiDie ($err_header, "Unrecognized time displacement format.", "Value = $timedispformat\n") } } # Date # Julian dates must have a julian variable. Gregorian dates must # have a year. Validate. $gregorian = ( ($gyear ne "") || ($gcentury ne "") || ($gdecade ne "") || ($gdecade_year ne "") ); ($julian eq "") && ! $gregorian && &CgiDie($err_header, "Please select a variable in the Julian date section", " or a year in the Gregorian date section"); ($julian ne "") && $gregorian && &CgiDie($err_header, "Cannot select both a variable in the Julian date section", " and a year in the Gregorian date section"); if ($gregorian) { # Input date is Gregorian $year = $gyear; $century = $gcentury; $decade = $gdecade; $decade_year = $gdecade_year; # Input month if ($month ne "") { ($monthformat eq "") && &CgiDie ($err_header, "Month data but no corresponding format\n"); &add_needed_var ($month); $tdparams_string .= "invar" . ++$ninput_vars . "name = $month; " . "invar" . $ninput_vars . "template = "; if ($monthformat eq "integer") { $tdparams_string .= "mm\n" } elsif ($monthformat eq "alpha") { $tdparams_string .= "bbb\n" } else { &CgiDie ($err_header, "Unrecognized month format.", "Value = $monthformat\n") } } # Input day if ($day ne "") { ($dayformat eq "") && &CgiDie ($err_header, "Day data but no corresponding format\n"); &add_needed_var ($day); $tdparams_string .= "invar" . ++$ninput_vars . "name = $day; " . "invar" . $ninput_vars . "template = "; if ($dayformat eq "DD") { $tdparams_string .= "dd\n" } elsif ($dayformat eq "DD.DDDD") { $tdparams_string .= "dd.ooooo\n" } else { &CgiDie ($err_header, "Unrecognized day format.", "Value = $dayformat\n") } } } else { # Input date is Julian $year = $jyear; $century = $jcentury; $decade = $jdecade; $decade_year = $jdecade_year; &add_needed_var ($julian); # Julian info is asked in 2 parts of the form; date and time # Save its timedateparams info separately, then add to tdparams_string # when all is done. $julian_tdparams_string = "invar" . ++$ninput_vars . "name = $julian; " . "invar" . $ninput_vars . "template = "; if ($injulianflag eq "fracyear") { # Don't know how to do fractional years at moment. Should have bombed above! } elsif ($injulianflag eq "jday") { # Note: do not add trailing \n to julian_td... we might not be done w/it if ($injulday1jan eq "day_0") { if ($maxdaysinyear eq "fixed") { $julian_tdparams_string .= "VVV" } elsif ($maxdaysinyear eq "normal") { $julian_tdparams_string .= "vvv" } else { &CgiDie ($err_header, "Unrecognized value for max days in year.", "Value = $maxdaysinyear\n") } } elsif ($injulday1jan eq "day_1") { if ($maxdaysinyear eq "fixed") { $julian_tdparams_string .= "JJJ" } elsif ($maxdaysinyear eq "normal") { $julian_tdparams_string .= "jjj" } else { &CgiDie ($err_header, "Unrecognized value for max days in year.", "Value = $maxdaysinyear\n") } } else { &CgiDie ($err_header, "Unrecognized julian value for input date of 1 Jan.", "Value = $injulday1jan\n"); } } else { &CgiDie ($err_header, "Unrecognized input julian days/years flag.", "Value = $injulianflag\n"); } } # Input year if (($century ne "") && ($decade ne "") && ($decade_year ne "")) { ($year eq "") || &CgiDie ($err_header,"Year specified as variable and also as value\n"); # data in input vars; generate var name $tdparams_string .= "invar" . ++$ninput_vars . "name = "; $generated_input_vars .= $official_year_var . $in_suffix . " "; $tdparams_string .= $official_year_var . $in_suffix . "; "; $lev0_data .= $century.$decade.$decade_year." "; $tdparams_string .= "invar" . $ninput_vars . "template = yyyy\n"; } else { (($century ne "") || ($decade ne "") || ($decade_year ne "")) && &CgiDie ($err_header, "Year data not completely specified\n"); if ($year ne "") { # data in object $tdparams_string .= "invar" . ++$ninput_vars . "name = "; &add_needed_var ($year); $tdparams_string .= "$year; "; $tdparams_string .= "invar" . $ninput_vars . "template = yyyy\n"; } } # Input time # Recode "combined" time that only specs decimal hours to "separate" # time (this is way originally coded & allows for future decimal minutes) ($timepiecesflag eq "combined") && ($hourminsecformat eq "HH.HHHH") && ($timepiecesflag = "separate") && ($hourformat = "HH.HHHH"); if ($timepiecesflag eq "") { ( ($hour ne "") || ($minute ne "") || ($second ne "") || ($hourmin ne "") || ($hourminsec ne "") ) && &CgiDie ($err_header, "Time pieces specified but flag to interpret them not spec'd\n", "Hour/minute/second/hourmin/hourminsec pieces are: ", "$hour/$minute/$second/$hourmin/$hourminsec\n"); # Time in w/julian date } elsif ($timepiecesflag eq "julian") { $gregorian && &CgiDie($err_header, "Time spec'd as part of Julian date but input is Gregorian"); $julian_tdparams_string .= ".oooooo"; # Hours, mins, and secs } elsif ($timepiecesflag eq "separate") { # Hours (required) ($hour eq "") && &CgiDie ($err_header, "Time pieces flag of separate requires hour data\n"); # If/when form asks for hourformat, next line is ... && die. ($hourformat eq "") && ($hourformat = "hh"); &add_needed_var ($hour); $tdparams_string .= "invar" . ++$ninput_vars . "name = $hour; " . "invar" . $ninput_vars . "template = "; if ($hourformat eq "hh") { $tdparams_string .= "HH\n" } elsif ($hourformat eq "hh.hh") { $tdparams_string .= "HH.OOOOOO\n" } else { &CgiDie ($err_header, "Unrecognized hour format.", "Value = $hourformat\n") } # Minutes (optional) if ($minute ne "") { ($hourformat eq "hh.hh") && &CgiDie ($err_header,"Cannot have minutes and decimal hours"); # If/when form asks for minuteformat, next line is ... && die. ($minuteformat eq "") && ($minuteformat = "mm"); &add_needed_var ($minute); $tdparams_string .= "invar" . ++$ninput_vars . "name = $minute; " . "invar" . $ninput_vars . "template = "; if ($minuteformat eq "mm") { $tdparams_string .= "MM\n" } elsif ($minuteformat eq "mm.mm") { $tdparams_string .= "MM.qqqqqq\n" } else { &CgiDie ($err_header, "Unrecognized minute format.", "Value = $minuteformat\n") } } # Seconds (optional) if ($second ne "") { ($minuteformat eq "mm.mm") && &CgiDie ($err_header,"Cannot have seconds and decimal minutes"); # If/when form asks for secondformat, next line is ... && die. ($secondformat eq "") && ($secondformat = "ss.ss"); &add_needed_var ($second); $tdparams_string .= "invar" . ++$ninput_vars . "name = $second; " . "invar" . $ninput_vars . "template = "; if ($secondformat eq "ss") { $tdparams_string .= "SS\n" } elsif ($secondformat eq "ss.ss") { $tdparams_string .= "SS.QQQQQQ\n" } else { &CgiDie ($err_header, "Unrecognized second format.", "Value = $secondformat\n") } } # HHMM hours & mins, and secs } elsif ($timepiecesflag eq "combo-secs") { # 24 hr time (required) ( ($hourminformat eq "") || ($hourmin eq "") ) && &CgiDie ($err_header, "Time pieces flag of HRMIN requires 24 hour time format and data\n"); &add_needed_var ($hourmin); $tdparams_string .= "invar" . ++$ninput_vars . "name = $hourmin; " . "invar" . $ninput_vars . "template = "; if ($hourminformat eq "HHMM.MMMM") { $tdparams_string .= "NNNN.qqqqqq\n" } elsif ($hourminformat eq "HHMM") { $tdparams_string .= "NNNN\n" } else { &CgiDie ($err_header, "Unrecognized hourmin format.", "Value = $hourminformat\n") } # Seconds (optional) if ($second ne "") { ($hourminformat eq "HHMM.MMMM") && &CgiDie ($err_header,"Cannot have seconds and decimal minutes"); # If/when form asks for secondformat, next line is ... && die. ($secondformat eq "") && ($secondformat = "ss.ss"); &add_needed_var ($second); $tdparams_string .= "invar" . ++$ninput_vars . "name = $second; " . "invar" . $ninput_vars . "template = "; if ($secondformat eq "ss") { $tdparams_string .= "SS\n" } elsif ($secondformat eq "ss.ss") { $tdparams_string .= "SS.QQQQQQ\n" } else { &CgiDie ($err_header, "Unrecognized second format.", "Value = $secondformat\n") } } # HH:MM:SS } elsif ($timepiecesflag eq "combined") { ($hourminsec eq "") && &CgiDie ($err_header,"Time pieces flag of combined requires data\n"); &add_needed_var ($hourminsec); $tdparams_string .= "invar" . ++$ninput_vars . "name = $hourminsec; " . "invar" . $ninput_vars . "template = HH:MM:SS.QQQQQQ\n"; } else { &CgiDie ($err_header, "Unrecognized time pieces flag.", "Value = $timepiecesflag\n"); } # Output time convention if ($oututcflag eq "") { $out_suffix = ""; } else { if ($oututcflag eq "utc") { $out_suffix = $official_UTC_suffix } elsif ($oututcflag eq "local") { $out_suffix = $official_local_suffix } else { &CgiDie ($err_header, "Unrecognized output UTC/local flag.", "Value = $oututcflag\n") } $tdparams_string .= "outtimeconvention = $oututcflag\n"; } if ($outjulgreg eq "julian") { # Don't know how to do output Julian at moment. Should have bombed above! if ($outjulianflag eq "Julian_day") { if ($outjulday1jan eq "day_0") { $tmp = $official_yrday0_var } elsif ($outjulday1jan eq "day_1") { $tmp = $official_yrday_var } else { &CgiDie ($err_header, "Unrecognized julian value for output date of 1 Jan.", "Value = $outjulday1jan\n") } $tmp .= $out_suffix; $needed_output_vars .= "$tmp "; $tdparams_string .= "outjulianname = $tmp\n"; } elsif ($outjulianflag eq "Julian_year") { # Don't know how to do years at moment. Should have bombed above! ; } else { &CgiDie ($err_header, "Unrecognized output Julian days/years flag.", "Value = $outjulianflag\n"); } } elsif ($outjulgreg eq "gregorian") { $tmp = $official_month_var . $out_suffix; $needed_output_vars .= "$tmp "; $tdparams_string .= "outmonthname = $tmp\n"; $tmp = $official_day_var . $out_suffix; $needed_output_vars .= "$tmp "; $tdparams_string .= "outdayname = $tmp\n"; $tmp = $official_time_var . $out_suffix; $needed_output_vars .= "$tmp "; $tdparams_string .= "outtimename = $tmp\n"; } else { &CgiDie ($err_header, "Unrecognized output Julian/Gregorian flag.", "Value = $outjulgreg\n"); } if ($debug) { print "\n", "Needed input variables = $needed_input_vars\n", "Needed output variables = $needed_output_vars\n", "Generating input variables = $generated_input_vars\n", "\n"; } ### # Get PATH_INFO pieces. Need to force methods to output jgofs for # listvar, then restore protocol for final defgb output. Also, # need to be sure that final defgb output includes enough levels. # Forcing done where needed; input done here. %path_info = ( split(/[,=]/,`$parse_path_info $form_input{"path_info"}`) ); ($? == 0) || &CgiDie ($err_header,"$parse_path_info exited w/code $?\n"); if ($debug) { print "\nPieces of PATH_INFO follow:\n"; while ( ($key,$value) = each(%path_info) ) { print "$key<->$value\n" } print "\n"; } ($obj = $path_info{"object"}) || &CgiDie($err_header,"No object information reached this program\n"); ### # Get variable list from object. Convert it into # a b c > # d e f g # format while checking that all variables we're supposed to have # are actually in object # This initialization along with perl -w will protect against # too many levels in input object. Would let defgb do this # except that time_cnv might add the "bad" level, and I'd rather # diagnose that in here. Also, this initialization protects against # variation in $[ - we want to define the range of subscripts foreach (0..$JGOFS_maxlevel) { $levlist[$_] = "" } $maxlevel = 0; $smallest_time_level = 0; # If we already have a file created by listvar, don't go over the # net to get it again if ($listvar_file) { open (FILE,$listvar_file) || &CgiDie ($err_header,"Cannot read $listvar_file : $!\n"); } else { $listvar_commands = "/bin/csh -c " . "\"(" . "unsetenv PATH_INFO" . ";" . $listvar . " " . $path_info{"object"} . " -a " . ")\""; $debug && print "$listvar_commands\n"; open (FILE,"$listvar_commands | ") || &CgiDie ($err_header,"Bad pipe open/read $listvar_commands : $!\n"); } ### defgb 3.1: omit next line $dispwidths_list = ""; while () { $debug && print "$_"; # If record leads off with &x, we have a listvar error, so die if (/^&x/) { close FILE; &CgiDie ($err_header,"listvar died: $_"); } chomp; # listvar puts out 2 leading blanks per level. Count the leading # blanks as we remove them. Add a blank at end for convenience $lev = (tr/ //d)/2; ($lev > $maxlevel) && ($maxlevel = $lev); ### defgb 3.1: next line " " instead of "\n" $_ .= "\n"; ### defgb 3.1: omit next 7 lines # Change var[width=N] to var = N (defgb dispwidths opt file format) # keeping track if we found any [width strings. Assuming no embedded # blanks in var[width=N] string if (s/\[width//) { s/]//; $dispwidths_list .= $_; } # get varname w/o width ### defgb 3.1: next line split on \[ ($varname) = split (/=/); $varname .= " "; ### defgb 3.1: next line $_ instead of $varname $levlist[$lev] .= $varname; # Check for conflicting var names. # Update list of variables we still need, and record level if # we found any such variables. We assume that variables in # object appear from "largest" to "smallest" time value. (If # not, there will be trouble doing time calcs anyway) # Similarly, update list of output variables we might need to add. ($generated_input_vars =~ /$varname/) && &CgiDie ($err_header, "Cannot generate variable $varname for year/timezone data", "since it is already in object\n"); ($needed_input_vars =~ s/$varname//) && ($smallest_time_level = $lev); $needed_output_vars =~ s/$varname//; } close FILE; # Shouldn't be anything but (possibly) blanks left in list of needed variables. ($needed_input_vars =~ /^ *$/) || &CgiDie ($err_header,"Need missing variables $needed_input_vars\n"); ($smallest_time_level == 0) && ($smallest_time_level = $maxlevel); # Add closing > to all levels but last. Adding carriage return # is for convenience in future print command (which must supply return # for last level itself) foreach (0..$maxlevel-1) { $levlist[$_] .= ">\n"; } ################################################ # Build object # 1) Build files for defgb. We'll need indirect & timedateparams files. # Most likely we will also need to create a varlist file, inserting # output variables at the level of the "smallest" input time. If # year or time zone need to be inserted, the varlist file will become # the new level 0 file. # 2) Add entry to .objects file for temporary objects pointing to # defgb(@indirect_file) # 3) Put this object in PATH_INFO for further use # /^ *$/ is my "empty or all blanks" test $new_level_0 = ($generated_input_vars !~ /^ *$/); if ($new_level_0) { ($maxlevel < $JGOFS_maxlevel) || &CgiDie ($err_header, "Cannot add year and/or timezone info", "Too many levels\n"); } $new_varlist = ( $new_level_0 || ($needed_output_vars !~ /^ *$/) ); $id = $ENV{"REMOTE_HOST"}; if ( ! $id) { $id = "eff. UID $>" } # In next line, # is defgb comment indicator $defgb_comment = "# Written for $id $date "; ### # Indirect file open (IND_FILE,">$ind_file") || &CgiDie ($err_header,"Bad open/write $ind_file : $!\n"); # In next line {}s are defgb "where did this comment come from" delims # Next line causes defgb 3.0 to die. Fix in defgb 3.1 # print IND_FILE $defgb_comment,"{$version}\n"; print IND_FILE "$defgb_comment\n"; if ($new_level_0) { print IND_FILE "datafile = $varlist_file\n"; } else { # In next line, {}s are defgb delims indicating object input print IND_FILE "datafile = {$obj}\n"; $new_varlist && print IND_FILE "varlist = $varlist_file\n"; } print IND_FILE "timedateparams = $tdparams_file\n"; ### defgb 3.1: omit next line $dispwidths_list && print IND_FILE "dispwidths = $dispwidths_file\n"; close IND_FILE; ### defgb 3.1: omit dispwidths file ### # dispwidths file if ($dispwidths_list) { open (DISPWIDTHS_FILE,">$dispwidths_file") || &CgiDie ($err_header,"Bad open/write $dispwidths_file : $!\n"); print DISPWIDTHS_FILE "$defgb_comment\n"; print DISPWIDTHS_FILE $dispwidths_list; close DISPWIDTHS_FILE; } ### # Timedateparams file open (TDPARAMS_FILE,">$tdparams_file") || &CgiDie ($err_header,"Bad open/write $tdparams_file : $!\n"); print TDPARAMS_FILE "$defgb_comment\n"; print TDPARAMS_FILE $tdparams_string; (defined($julian_tdparams_string)) && print TDPARAMS_FILE "$julian_tdparams_string\n"; close TDPARAMS_FILE; ### # Varlist file if ($new_varlist) { open (VARLIST_FILE,">$varlist_file") || &CgiDie ($err_header,"Bad open/write $varlist_file : $!\n"); print VARLIST_FILE "$defgb_comment\n"; # In next line, > is def not-last-level indicator $new_level_0 && print VARLIST_FILE "$generated_input_vars>\n"; # Print variable list, inserting needed variables on the same level # as the smallest input time. All levlist entries except last have # concluding ">\n" sequence foreach ( 0..$smallest_time_level-1 ) { print VARLIST_FILE $levlist[$_]; } print VARLIST_FILE $needed_output_vars,$levlist[$smallest_time_level]; foreach ( $smallest_time_level+1..$maxlevel ) { print VARLIST_FILE $levlist[$_]; } print VARLIST_FILE "\n"; # If this is a new level 0 file, put in the level 0 data and pointer to # level 1. {}s are defgb delims indicating object input # Adjust levels to reflect new object structure if ($new_level_0) { print VARLIST_FILE $lev0_data," {$obj}\n"; $smallest_time_level++; $maxlevel++; } close VARLIST_FILE; } ### # Add to .objects file # Don't write duplicate entry (can happen if user goes back and # forth between form and this program - $unique is "in" the form and # does not change. -s suppresses error msg about non-existent file. # Could recode, not grep'ping if file does not exist, but is clumsier if ( ! `grep -s $obj_name $object_file` ) { $open_mode = (-e $object_file) ? ">>" : ">"; open (OBJECT_FILE,"$open_mode$object_file") || &CgiDie ($err_header,"Bad open create/append $object_file : $!\n"); # NB: Cannot put $defgb (containing full file spec) into .objects. The # ability to use this temporary object again depends on $defgb and # defgb in the default methods directory being functionally equivalent. # Further note that the default methods directory is built into # dct.c (in the jgofs.a library) and is not necessarily related to # this program's $JGOFS_ROOT variable print OBJECT_FILE "$obj_name=defgb(\@$ind_file)\n"; close OBJECT_FILE; } ### # We have to build a PATH_INFO since there probably isn't one... # Point it to new object, but get rest of info from %path_info. # It has correct info whether there is an existing PATH_INFO or not. $new_path_info_data = "object=$object_dir/$obj_name" . ",protocol=" . $path_info{"protocol"} . ",level="; # Make sure at least $smallest_time_level levels are asked for (since # that's where we're putting our output!). Empty level string here should # mean "no level in PATH_INFO", which should mean all levels $path_info{"level"} && ($new_path_info_data .= ($path_info{"level"} > $smallest_time_level) ? $path_info{"level"} : $smallest_time_level ); # Add any {}ed options. {}s are JGOFS delimiters of the PATH_INFO # "options" string. $tmp = ""; while ( ($key,$value) = each %path_info ) { ($key =~ /^(object|level|protocol)$/) && next; $tmp .= "$key=$value,"; } chop $tmp; ($tmp eq "") || ($new_path_info_data .= "{$tmp}"); $new_path_info = `$make_path_info $new_path_info_data`; ($? == 0) || &CgiDie ($err_header,"$make_path_info exited w/code $?\n"); chomp ($new_path_info); ($new_query_string = $form_input{"query_string"}) || ($new_query_string = $ENV{"QUERY_STRING"}); $new_query_string && ($new_query_string = "setenv QUERY_STRING $new_query_string; "); ### # Do it! $defgb_cmd = "$defgb \@$ind_file"; $defgb_cmd = "/bin/csh -c " . "\"(" . $new_query_string . "setenv PATH_INFO $new_path_info; " . "$defgb_cmd" . ")\""; $debug && print "$defgb_cmd\n"; system ($defgb_cmd); ###### if ($debug) { $old_flag = $ENV{$pid_file_cleanup_debug_env_var}; $ENV{$pid_file_cleanup_debug_env_var} = 1; } &pid_file_cleanup($unique,@temp_files); if ($debug) { if (defined($old_flag)) { $ENV{$pid_file_cleanup_debug_env_var} = $old_flag } else { undef ($ENV{$pid_file_cleanup_debug_env_var}) } } exit; } sub add_needed_var { my ($var) = @_; $var .= " "; ($needed_input_vars =~ /$var/) && &CgiDie($err_header, "Cannot have 2 pieces of input coming from same variable", "Variable = $var"); $needed_input_vars .= $var; } ######################### # Below is an attempt to cram as much as possible on the command line # to try to get rid of indirect files # Build defgb command that will do work. There is a problem with # special characters defgb wants that shell fools with (and maybe # that the characters used to protect things from the shell are mean- # ingful to perl!). In particular, 1) perl does things with @ # 2) both shell and perl do things with \ 3) shell does things with ; and # {} 4) not sure if perl does things with ' # Args should look to defgb like # @ind_file {object} varlist_file \timedate_opt1;_opt2;_opt3 # a) ind_file must be a defgb indirect file. # b) The timedate_options parameter is a defgb timedate optional file # with its "records" all on one line. At some point, the ind_file and # varlist_file will be able to be expressed this way, eliminating the need # for any files # $defgb_cmd = "$defgb @" . $timecnv_otheropt_indirect . # " '{" . $obj . "}' " . # $varlist_file . # " \\\\invar1name=$year\\;invar1template=yyyy\\;" . # "invar2name=$julian\\;invar2template=jjj.ooooooo\\;" . # "outmonthname=mo\\;outdayname=da\\;outtimename=time_greg";