/************************************************************************/ /* Make_Blockettes.pc: Generates the SEED tree structure needed by POD. */ /************************************************************************/ /* Author: Stephane Zuzlewski UC Berkeley Seismological Laboratory stephane@seismo.berkeley.edu Purpose: Modification History: Date Ver Who What --------------------------------------------------------------------- 1998/??/?? 1.0 SMZ Initial coding. 2002/09/23 1.1 SMZ Fixed Bug. B052 files were never getting closed. 2003/07/17 2.0 SMZ Abbreviation Dictionary doesn't use the database Id's for the blockette keys. 2003/08/25 2.1 SMZ Supports coalesced time spans. 2004/11/12 2.2 SMZ Fixed bug when channel depth > 1000. 2005/02/09 2.3 SMZ Fixed bug when station.ondate starting before min(channel.ondate). 2006/06/01 2.4 SMZ Database connection string can now be specified in an environment variable. 2012/05/21 2.5 SMZ Handle new Stage 0 polynomial response. 2012/12/03 2.6 SMZ Deprecated USE_ABPOLY env variable. */ /************************************************************************/ #ifndef lint static char sccsid[] = "%W% %G% %U%"; #endif #include #include #include #include #include #include #include #include #include #define VERSION "2.6" #define CONNECT_STRING "user/passwd@db" #define NOMOREROWS 1403 #define info stdout #define LINELEN 255 #define max(a, b) ((a) < (b) ? (b) : (a)) char *syntax[] = { "%s version " VERSION " -- Generates the SEED tree structure needed by POD.", "%s [-p file] [-f date] [-t date] [-S station] [-N network] [-v] [-h]", " where:", " -h Help - prints syntax message.", " -f date Start date. Dates can be in formats:", " yyyy/mm/dd/hh:mm:ss.ffff", " yyyy/mm/dd.hh:mm:ss.ffff", " yyyy/mm/dd,hh:mm:ss.ffff", " yyyy.ddd,hh:mm:ss.ffff", " yyyy,ddd,hh:mm:ss.ffff", " You may leave off any trailing 0 components of the time.", " -t date End date. If ommited then equals start date.", " -S station Specifies a station code.", " -N network Specifies a network code.", " -v Verbose option.", " -p file Specifies a POD request file.", " Environment variable DATA_ROOT specifies the root path and name.", " Environment variable USE_LOOKUP set --> Use blockettes 41 & 60 instead of 61.", " Environment variable DB_CONNECT --> Overwrites default database connection string.", NULL }; /* Structures declaration */ typedef struct { char sta[7]; char net[9]; char cha[4]; char loc[3]; char stime[25]; char etime[25]; } POD_Req_Cha; typedef struct { char sta[7]; char net[9]; char stime[25]; char etime[25]; } POD_Req_Sta; typedef struct { int BlocketteNb; /* Blockette Number (30, 31, 33, 34, 41, 42) */ long DBid; /* Database Id */ int SEEDid; /* SEED Id */ } IdMapping; EXEC SQL INCLUDE sqlca.h; EXEC SQL BEGIN DECLARE SECTION; char user_pwd[80]; int i; int j; int k; int z; short ind; /* Indicator */ char sta[7]; /* Station code */ char sta2[7]; /* Station code */ char sta3[7]; /* Station code */ char usta[7]; /* Station code */ char staname[51]; /* Station name */ char cha[4]; /* Channel code */ char loc[3]; /* Location code */ char net[9]; /* Network code */ char net2[9]; /* Network code */ char net3[9]; /* Network code */ char unet[9]; /* Network code */ int inid; /* Instrument identifier */ int net_id; /* Network identifier */ char seedchan[4]; /* SEED channel name */ char seedchan2[4]; /* SEED channel name */ char seedchan3[4]; /* SEED channel name */ char location[3]; /* SEED location */ char location2[3]; /* SEED location */ char location3[3]; /* SEED location */ double samprate; /* Sampling rate */ double clock_drift; /* Clock drift */ char flags[28]; /* SEED channel flags */ int unit_signal; /* Unit of signal responses identifier */ int unit_calib; /* Unit of calibration identifier */ int record_length; /* Record length */ char remark[31]; /* Optional comment */ double azimuth; /* Azimuth */ double dip; /* Dip */ double lat; /* Sensor latitude */ double lon; /* Sensor longitude */ double elev; /* Sensor elevation */ double slat; /* Station latitude */ double slon; /* Station longitude */ double selev; /* Station elevation */ double edepth; /* Sensor depth */ int word_32; /* Word 32 bits */ int word_16; /* Word 16 bits */ int format_id; /* Format identifier */ char date[20]; /* Date */ char ondate[20]; /* Start date */ char offdate[20]; /* End date */ char condate[20]; /* Start date */ char coffdate[20]; /* End date */ char sondate[20]; /* Start date */ char soffdate[20]; /* End date */ char on_date[20]; /* Start date */ char off_date[20]; /* End date */ char lddate[20]; /* Load date */ int nb_keys; /* Number of decoder keys */ char key_d[81]; /* Decoder keys */ int id; /* Format identifier */ char name[81]; /* Name */ int family; /* Family */ char class; /* Class */ char description[71]; /* Description */ int unit; /* Unit */ int nb_cmt; /* Number of comments */ int comment_id; /* Comment identifier */ int comment_level; /* Comment level */ int nb_stages; /* Number of stages */ int max_pn; int max_c; int max_d; int max_pz; int max_s; int nb_num; /* Number of numerators */ double coeff; /* Coefficient */ double error; /* Error */ int dc_key; /* Coefficients key */ int unit_in; /* Input units */ int unit_out; /* Output units */ char tf_type; /* Response type */ char rname[81]; /* response name */ char symmetry; /* Symmetry code */ int dm_key; /* Decimation key */ int factor; /* Factor */ int offset; /* Offset */ double delay; /* Delay */ double correction; /* Correction */ int pz_key; /* Poles & Zeros identifier */ double AO; double AF; int nb_poles; /* Number of poles */ int nb_zeros; /* Number of zeros */ double r_value; /* Real value */ double r_error; /* Real error */ double i_value; /* Imaginary value */ double i_error; /* Imaginary error */ double sensitivity; /* Sensitivity */ double frequency; /* Frequency */ int pn_key; /* Polynomial identifier */ char polyname[81]; /* Polynomial name */ char poly_type; /* Polynomial type */ double lower_bound; /* Lower bound */ double upper_bound; /* Upper bound */ double upper_freq; /* Upper frequency bound */ double max_error; /* Maximum error */ int nb_coeff; /* Number of coefficients */ double pn_value; /* Coefficient */ char sdate[20]; /* Start date */ char edate[20]; /* End date */ double tsdate; /* Start date */ double tedate; /* End date */ char mindate[20]; /* Minimum date */ char maxdate[20]; /* Maximum date */ double tmindate; /* Minimum date */ double tmaxdate; /* Maximum date */ char SQL_Command[1024]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE sql_stmt STATEMENT; /************************************************************************/ /* External variables and symbols. */ /************************************************************************/ char *cmdname; /* program name from command line. */ long SQLCODE; /* Global variables for the token list */ int tokenc; char **tokenv; POD_Req_Cha podrc[10000]; POD_Req_Sta podrs[10000]; int nb_req_cha = 0; int nb_req_sta = 0; IdMapping idm[16000]; int nb_idm = 0; int idm_30 = 1; int idm_31 = 1; int idm_33 = 1; int idm_34 = 1; int idm_41 = 1; int idm_42 = 5001; /* Function declarations */ int split_inline (char *line, char delim); int split_copy (char *line, char delim); int reset_token (int *pargc, char ***pargv, int dup); int push_token (int *pargc, char ***pargv, char *p, int dup); char *strndup (char *p, int n); void sql_error(); /* Handles unrecoverable errors */ /************************************************************************/ /* Remove_Blank: */ /* */ /* Removes trailing blanks in a string. */ /* Returns new string */ /************************************************************************/ char* Remove_Blank (char *s) { char *p = s + strlen (s); while (--p >= s) if (*p == ' ') *p = '\0'; else break; return (s); } /************************************************************************/ /* Convert_Date: */ /* */ /* Function to convert an Oracle date to a Julian date. */ /************************************************************************/ char* Convert_Date_OJ (char d[20]) { EXEC SQL BEGIN DECLARE SECTION; char nd[20]; int day; EXEC SQL END DECLARE SECTION; static char fd[20]; if (!strcmp (d, "3000/01/01 00:00:00")) return (""); EXEC SQL SELECT TO_CHAR (TO_DATE (:d, 'YYYY/MM/DD HH24:MI:SS'), 'DDD') INTO :nd FROM DUAL; sprintf (fd, "%.4s,%.3s,%.2s:%.2s:%.2s", d, nd, d+11, d+14, d+17); return (fd); } /************************************************************************/ /* Convert_Date_JO: */ /* */ /* Function to convert a Julian date to an Oracle date. */ /************************************************************************/ char* Convert_Date_JO (char d[20]) { static char nd[20]; INT_TIME it, *pt; EXT_TIME et; if ((pt = parse_date (d)) == NULL) { printf ("\n Error: invalid date: %s\n", d); exit (-1); } it = *pt; et = int_to_ext (it); sprintf (nd, "%04d/%02d/%02d %02d:%02d:%02d", et.year, et.month, et.day, et.hour, et.minute, et.second); return (nd); } /************************************************************************/ /* GetID: */ /* */ /* Function that returns the mapped SEED id from a DB Id. */ /************************************************************************/ int GetID (long DBid, int BlocketteNb) { int i; for (i=0;i < nb_idm; i++) { if ((idm[i].DBid == DBid) && (idm[i].BlocketteNb == BlocketteNb)) return (idm[i].SEEDid); } printf ("\n Error: Couldn't map DBid=%d for Blockette #%d.\n\n", DBid, BlocketteNb); } /************************************************************************/ /* Generate_Tree: */ /* */ /* Function to generate the SEED tree structure. */ /************************************************************************/ void Generate_Tree ( char sta2[7], /* Station code */ char net2[9], /* Network code */ char seedchan2[4], /* Channel name */ char location2[3], /* Location code */ char pdate[20], /* Date of interest */ char option, /* a: all, s: station only, c: channel only */ int debug) /* 1: debug info., 0: none */ { int Flag_Sta = 0; int Flag_Poly = 0; int Flag = 0; FILE *f_ad; /* Abbreviation dictionary file descriptor */ FILE *f_st; /* Station file descriptor */ char n_st[255]; /* Station file name */ FILE *f_stc; /* Station comment file descriptor */ char n_stc[255]; /* Station comment file name */ FILE *f_ch; /* Channel file descriptor */ char n_ch[255]; /* Channel file name */ FILE *f_chc; /* Channel comment file descriptor */ char n_chc[255]; /* Channel comment file name */ char s_ad[9999]; /* Generic line */ char rl[5]; /* Record length */ char sys[255]; /* System command */ char stmp[255]; /* Temporary string */ char *data_root2; /* Data root name */ char data_root[1024];/* Data root name */ char ha_name[255]; /* H.A file name */ int Flag_AD = 1; /* Abbreviation Dictionary Flag */ int Flag_AP = 0; /* Abbreviation Polynomial Flag */ char pcha[4]; /* Channel name */ char ploc[3]; /* Location code */ strcpy (pcha, seedchan2); strcpy (ploc, location2); /* Location code */ if ((!strcmp (ploc, "-")) || (!strcmp (ploc, "--"))) strcpy (ploc, " "); /* Retrieving station information */ strcpy (date, pdate); strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate FROM station_data WHERE sta = :sta2 AND net = :net2 AND :date >= ondate AND :date < offdate; if (strlen (lddate) == 0) { printf ("\n No data found for this station at this date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } /* Is 1st channel starting after station? */ if ((option == 's') || (option == 'a')) { EXEC SQL SELECT MIN(ondate) INTO :ondate FROM Channel_Data WHERE sta = :sta2 AND net = :net2; if (strcmp (ondate, date) > 0) strcpy (date, ondate); } /* Decoding environment */ if ((data_root2 = (char *) getenv ("DATA_ROOT")) == NULL) { if (debug) printf ("\n No root path specified, using ./HAR000"); strcpy (data_root, "./HAR000"); } else { if (debug) printf ("\n Using root path %s\n\n", data_root2); strcpy (data_root, data_root2); } if (getenv ("USE_LOOKUP") == NULL) Flag_AD = 0; else Flag_AD = 1; /* if (getenv ("USE_ABPOLY") == NULL) Flag_AP = 0; else Flag_AP = 1; */ Flag_AP = 0; sprintf (SQL_Command, "SELECT sta, net, seedchan, location, inid, remark, unit_signal, unit_calib, lat, lon, elev, edepth, azimuth, dip, format_id, record_length, samprate, clock_drift, flags, ondate, offdate FROM channel_data WHERE sta = '%s' AND net = '%s' AND '%s' >= ondate AND '%s' < offdate", sta2, net2, date, date); EXEC SQL PREPARE sql_stmt FROM :SQL_Command; EXEC SQL DECLARE cha_c CURSOR FOR sql_stmt; EXEC SQL OPEN cha_c; strcpy (remark, ""); EXEC SQL FETCH cha_c INTO :sta, :net, :seedchan, :location, :inid:ind, :remark:ind, :unit_signal, :unit_calib, :lat:ind, :lon:ind, :elev:ind, :edepth:ind, :azimuth:ind, :dip:ind, :format_id, :record_length:ind, :samprate, :clock_drift:ind, :flags:ind, :ondate, :offdate:ind; while (sqlca.sqlcode != NOMOREROWS) { Remove_Blank (sta); Remove_Blank (net); Remove_Blank (seedchan); Remove_Blank (location); Remove_Blank (ondate); Remove_Blank (offdate); Remove_Blank (flags); Remove_Blank (remark); if (strlen (location) == 0) strcpy (location, " "); /* Testing channel/location */ if ((strlen (pcha) == 0) && (strlen (ploc) == 0)) Flag = 0; else if ((strlen (pcha) != 0) && (strlen (ploc) == 0)) { if (strcmp (seedchan, pcha)) Flag = 1; else Flag = 0; } else if ((strlen (ploc) != 0) && (strlen (pcha) == 0)) { if (strcmp (location, ploc)) Flag = 1; else Flag = 0; } else { if ((strcmp (seedchan, pcha)) || (strcmp (location, ploc))) Flag = 1; else Flag = 0; } Remove_Blank (location); if (Flag == 0) { if (Flag_Sta == 0) { Flag_Sta = 1; /* Creating structure root */ mkdir (data_root, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); /* Opening abbreviation dictionary */ sprintf (ha_name, "%s/H.A", data_root); if ((f_ad = fopen (ha_name, "rt")) != NULL) { if (debug) printf ("\n Abbreviation Dictionary already present."); fclose (f_ad); } else { if ((f_ad = fopen (ha_name, "wt")) == NULL) { printf ("\n Error: Couldn't open file %s\n\n", ha_name); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Generating Abbreviation Dictionary */ if (debug) printf ("\n Generating Abbreviation Dictionary ..."); /* Generating blockette 30 */ if (debug) printf ("\n\t Generating Blockettes 30 ..."); EXEC SQL DECLARE c_abf CURSOR FOR SELECT id, name, family FROM D_Format ORDER BY id; EXEC SQL OPEN c_abf; EXEC SQL FETCH c_abf INTO :id, :name, :family; while (sqlca.sqlcode != NOMOREROWS) { EXEC SQL SELECT count(*) INTO :nb_keys FROM D_Format_Data WHERE id = :id; Remove_Blank (name); idm[nb_idm].BlocketteNb = 30; idm[nb_idm].DBid = id; idm[nb_idm].SEEDid = idm_30; sprintf (s_ad, "%.3s%04d%s~%04d%03d%02d", "030", 0, name, idm[nb_idm].SEEDid, family, nb_keys); nb_idm++; idm_30++; for (i=1;i<=nb_keys;i++) { EXEC SQL SELECT key_d INTO :key_d FROM D_Format_Data WHERE id = :id AND row_id = :i; Remove_Blank (key_d); strcat (s_ad, key_d); strcat (s_ad, "~"); } /* Adding record length */ sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ad, "%s\n", s_ad); EXEC SQL FETCH c_abf INTO :id, :name, :family; } EXEC SQL CLOSE c_abf; /* Generating blockette 31 */ if (debug) printf ("\n\t Generating Blockettes 31 ..."); EXEC SQL DECLARE c_abc CURSOR FOR SELECT id, class, description, unit FROM D_Comment ORDER BY id; EXEC SQL OPEN c_abc; EXEC SQL FETCH c_abc INTO :id, :class, :description, :unit; while (sqlca.sqlcode != NOMOREROWS) { Remove_Blank (description); idm[nb_idm].BlocketteNb = 31; idm[nb_idm].DBid = id; idm[nb_idm].SEEDid = idm_31; sprintf (s_ad, "%.3s%04d%04d%c%s~%03d", "031", 0, idm[nb_idm].SEEDid, class, description, unit); nb_idm++; idm_31++; /* Adding record length */ sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ad, "%s\n", s_ad); EXEC SQL FETCH c_abc INTO :id, :class, :description, :unit; } EXEC SQL CLOSE c_abc; /* Generating blockette 33 */ if (debug) printf ("\n\t Generating Blockettes 33 ..."); EXEC SQL DECLARE c_aba CURSOR FOR SELECT id, description FROM D_Abbreviation ORDER BY id; EXEC SQL OPEN c_aba; EXEC SQL FETCH c_aba INTO :id:ind, :description:ind; while (sqlca.sqlcode != NOMOREROWS) { Remove_Blank (description); idm[nb_idm].BlocketteNb = 33; idm[nb_idm].DBid = id; idm[nb_idm].SEEDid = idm_33; sprintf (s_ad, "%.3s%04d%03d%s~", "033", 0, idm[nb_idm].SEEDid, description); nb_idm++; idm_33++; /* Adding record length */ sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ad, "%s\n", s_ad); EXEC SQL FETCH c_aba INTO :id:ind, :description:ind; } EXEC SQL CLOSE c_aba; /* Generating blockette 34 */ if (debug) printf ("\n\t Generating Blockettes 34 ..."); EXEC SQL DECLARE c_abu CURSOR FOR SELECT id, name, description FROM D_Unit ORDER BY id; EXEC SQL OPEN c_abu; EXEC SQL FETCH c_abu INTO :id, :name, :description:ind; while (sqlca.sqlcode != NOMOREROWS) { Remove_Blank (name); for (i=0;i= ondate AND :date < offdate; Remove_Blank (sta); Remove_Blank (net); Remove_Blank (staname); Remove_Blank (ondate); Remove_Blank (offdate); EXEC SQL SELECT count(*) INTO :nb_cmt FROM Station_Comment WHERE sta = :sta2 AND net = :net2 AND :date >= ondate AND :date < offdate; /* Creating directory */ sprintf (sys, "%s/%s.%s/", data_root, sta, net); mkdir (sys, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); /* Opening Station file */ sprintf (n_st, "%s/%s.%s/B050", data_root, sta, net); if ((f_st = fopen (n_st, "a+t")) == NULL) { printf ("\n Error: Couldn't open file %s\n\n", n_st); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Generating Blockette 50 */ if (debug) printf ("\n\n Generating Blockette 50 for %s.%s ....", sta, net); strcpy (on_date, Convert_Date_OJ (ondate)); strcpy (off_date, Convert_Date_OJ (offdate)); sprintf (s_ad, "%.3s%04d%-5s%+10.6f%+11.6f%+7.1f%04d%03d%s~%03d%04d%02d%s~%s~%c%.2s", "050", 0, sta, slat, slon, selev, 0, nb_cmt, staname, GetID (net_id, 33), word_32, word_16, on_date, off_date, 'N', net); /* Adding record length */ sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_st, "%s\n", s_ad); /* Closing Station file */ fclose (f_st); /* Opening Station Comment file */ sprintf (n_stc, "%s/%s.%s/B051", data_root, sta, net); if ((f_stc = fopen (n_stc, "rt")) != NULL) { if (debug) printf ("\n Blockette 51 already present."); fclose (f_stc); } else { if ((f_stc = fopen (n_stc, "wt")) == NULL) { printf ("\n Error: Couldn't open file %s\n\n", n_stc); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Generating Blockette 51 */ if (debug) printf ("\n Generating Blockette 51 for %s.%s ....", sta, net); EXEC SQL DECLARE c_stc CURSOR FOR SELECT ondate, offdate, comment_id, comment_level FROM Station_Comment WHERE sta = :sta2 AND net = :net2; EXEC SQL OPEN c_stc; EXEC SQL FETCH c_stc INTO :sondate, :soffdate, :comment_id, :comment_level; while (sqlca.sqlcode != NOMOREROWS) { strcpy (on_date, Convert_Date_OJ (sondate)); strcpy (off_date, Convert_Date_OJ (soffdate)); sprintf (s_ad, "%.3s%04d%s~%s~%04d%06d", "051", 0, on_date, off_date, GetID (comment_id, 31), comment_level); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_stc, "%s\n", s_ad); EXEC SQL FETCH c_stc INTO :sondate, :soffdate, :comment_id, :comment_level; } EXEC SQL CLOSE c_stc; /* Closing Station comment file */ fclose (f_stc); } if (option == 's') { printf ("\n\n"); return; } } } /* Creating directory */ sprintf (sys, "%s/%s.%s/%s.%s", data_root, sta, net, seedchan, location); mkdir (sys, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); /* Opening Channel file */ sprintf (n_ch, "%s/%s.%s/%s.%s/B052", data_root, sta, net, seedchan, location); if ((f_ch = fopen (n_ch, "a+t")) == NULL) { printf ("\n Error: Couldn't open file %s\n\n", n_ch); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Location */ if (strlen (location) == 0) strcpy (location, " "); /* Generating Blockette 52 */ EXEC SQL SELECT count(*) INTO :nb_cmt FROM Channel_Comment WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate; if (debug) printf ("\n\n Generating Blockette 52 for %s.%s.%s.%s ....", sta, net, seedchan, location); strcpy (on_date, Convert_Date_OJ (ondate)); strcpy (off_date, Convert_Date_OJ (offdate)); if (edepth < 1000.) sprintf (s_ad, "%.3s%04d%.2s%.3s%04d%03d%s~%03d%03d%+10.6f%+11.6f%+7.1f%5.1f%5.1f%+5.1f%04d%02d%10.4E%10.4E%04d%s~%s~%s~%c", "052", 0, location, seedchan, 0, GetID (inid, 33), remark, GetID (unit_signal, 34), GetID (unit_calib, 34), lat, lon, elev, edepth, azimuth, dip, GetID (format_id, 30), record_length, samprate, clock_drift, nb_cmt, flags, on_date, off_date, 'N'); else sprintf (s_ad, "%.3s%04d%.2s%.3s%04d%03d%s~%03d%03d%+10.6f%+11.6f%+7.1f%5.0f%5.1f%+5.1f%04d%02d%10.4E%10.4E%04d%s~%s~%s~%c", "052", 0, location, seedchan, 0, GetID (inid, 33), remark, GetID (unit_signal, 34), GetID (unit_calib, 34), lat, lon, elev, edepth, azimuth, dip, GetID (format_id, 30), record_length, samprate, clock_drift, nb_cmt, flags, on_date, off_date, 'N'); /* Location */ Remove_Blank (location); /* Adding record length */ sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); /* Opening Channel Comment file */ sprintf (n_chc, "%s/%s.%s/%s.%s/B059", data_root, sta, net, seedchan, location); /* Location */ if (strlen (location) == 0) strcpy (location, " "); /* Generating Blockette 59 */ if ((f_chc = fopen (n_chc, "rt")) != NULL) { if (debug) printf ("\n Blockette 59 already present."); fclose (f_chc); } else { if ((f_chc = fopen (n_chc, "wt")) == NULL) { printf ("\n Error: Couldn't open file %s (errno = %d)\n\n", n_chc, errno); EXEC SQL COMMIT WORK RELEASE; exit (0); } if (debug) printf ("\n Generating Blockette 59 for %s.%s.%s.%s ....", sta, net, seedchan, location); EXEC SQL DECLARE c_chc CURSOR FOR SELECT ondate, offdate, comment_id, comment_level FROM Channel_Comment WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location; EXEC SQL OPEN c_chc; EXEC SQL FETCH c_chc INTO :condate, :coffdate, :comment_id, :comment_level; while (sqlca.sqlcode != NOMOREROWS) { strcpy (on_date, Convert_Date_OJ (condate)); strcpy (off_date, Convert_Date_OJ (coffdate)); sprintf (s_ad, "%.3s%04d%s~%s~%04d%06d", "059", 0, on_date, off_date, GetID (comment_id, 31), comment_level); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_chc, "%s\n", s_ad); EXEC SQL FETCH c_chc INTO :condate, :coffdate, :comment_id, :comment_level; } EXEC SQL CLOSE c_chc; /* Closing Channel comment file */ fclose (f_chc); } /* Checking number of Stages */ EXEC SQL SELECT max (stage_seq) INTO :max_pn:ind FROM Polynomial WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate; EXEC SQL SELECT max (stage_seq) INTO :max_c:ind FROM Coefficients WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate; EXEC SQL SELECT max (stage_seq) INTO :max_d:ind FROM Decimation WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate; EXEC SQL SELECT max (stage_seq) INTO :max_pz:ind FROM Poles_Zeros WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate; EXEC SQL SELECT max (stage_seq) INTO :max_s:ind FROM Sensitivity WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate; nb_stages = max (max (max (max (max_pn, max_c), max_d), max_pz), max_s); /* Generating Stages */ Flag_Poly = 0; for (i=1;i<=nb_stages;i++) { /* Polynomial */ strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate:ind FROM Polynomial WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; if (strlen (lddate) != 0) { Flag_Poly = 1; EXEC SQL SELECT pn_key, tf_type, unit_in, unit_out INTO :pn_key, :tf_type, :unit_in, :unit_out FROM Polynomial WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; if (Flag_AP == 1) { /* Generating blockette 60 */ if (debug) printf ("\n\t Generating Blockette 60 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); sprintf (s_ad, "%.3s%04d%02d%02d%02d%04d", "060", 0, 1, i, 1, GetID (pn_key, 42)); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } else { /* Generating blockette 62 */ if (debug) printf ("\n\t Generating Blockette 62 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); EXEC SQL SELECT poly_type, name, lower_bound, upper_bound, max_error INTO :poly_type, :polyname, :lower_bound, :upper_bound, :max_error FROM PN WHERE key = :pn_key; EXEC SQL SELECT count(*) INTO :nb_coeff FROM PN_Data WHERE key = :pn_key; /* Frequency Bounds */ if (strstr (polyname, "LDS") != NULL) upper_freq = .4; else if (strstr (polyname, "LD2") != NULL) upper_freq = .4; else if (strstr (polyname, "LKS") != NULL) upper_freq = .016; else if (strstr (polyname, "UK2") != NULL) upper_freq = .004; else if (strstr (polyname, "LFP") != NULL) upper_freq = .4; else if (strstr (polyname, "LEI") != NULL) upper_freq = .4; else { printf ("\n Error: Frequency bounds for polynomial [%s] not found. Assuming 0.4.\n\n", polyname); upper_freq = .4; } sprintf (s_ad, "%.3s%04d%c%02d%03d%03d%c%c%12.5E%12.5E%12.5E%12.5E%12.5E%03d", "062", 0, tf_type, i, GetID (unit_in, 34), GetID (unit_out, 34), poly_type, 'B', 0., upper_freq, lower_bound, upper_bound, max_error, nb_coeff); for (j=1;j<=nb_coeff;j++) { EXEC SQL SELECT pn_value INTO :pn_value FROM PN_Data WHERE key = :pn_key AND row_key = :j; sprintf (stmp, "%12.5E%12.5E", pn_value, 0.); strcat (s_ad, stmp); } sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } } /* Coefficients */ strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate:ind FROM Coefficients WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; if (strlen (lddate) != 0) { EXEC SQL SELECT dc_key, unit_in, unit_out, tf_type INTO :dc_key:ind, :unit_in, :unit_out, :tf_type FROM Coefficients WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; if (ind != (-1)) { if (Flag_AD) { /* Generating blockette 60 */ if (debug) printf ("\n\t Generating Blockette 60 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); sprintf (s_ad, "%.3s%04d%02d%02d%02d%04d", "060", 0, 1, i, 1, GetID (dc_key, 41)); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } else { /* Generating blockette 61 */ if (debug) printf ("\n\t Generating Blockette 61 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); EXEC SQL SELECT name, symmetry INTO :rname:ind, :symmetry:ind FROM DC WHERE key = :dc_key; Remove_Blank (rname); for (j=0;j= ondate AND :date < offdate AND stage_seq = :i; if (strlen (lddate) != 0) { /* Generating blockette 53 */ if (debug) printf ("\n\t Generating Blockette 53 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); EXEC SQL SELECT pz_key, tf_type, unit_in, unit_out, AO, AF INTO :pz_key, :tf_type, :unit_in, :unit_out, :AO, :AF FROM Poles_Zeros WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; EXEC SQL SELECT count(*) INTO :nb_poles FROM PZ_Data WHERE key = :pz_key AND type = 'P'; EXEC SQL SELECT count(*) INTO :nb_zeros FROM PZ_Data WHERE key = :pz_key AND type = 'Z'; sprintf (s_ad, "%.3s%04d%c%02d%03d%03d%12.5E%12.5E%03d", "053", 0, tf_type, i, GetID (unit_in, 34), GetID (unit_out, 34), AO, AF, nb_zeros); for (j=1;j<=nb_zeros;j++) { EXEC SQL SELECT r_value, r_error, i_value, i_error INTO :r_value, :r_error:ind, :i_value, :i_error:ind FROM PZ_Data WHERE type = 'Z' AND key = :pz_key AND row_key = :j; sprintf (stmp, "%12.5E%12.5E%12.5E%12.5E", r_value, i_value, r_error, i_error); strcat (s_ad, stmp); } sprintf (stmp, "%03d", nb_poles); strcat (s_ad, stmp); for (j=nb_zeros+1;j<=nb_poles+nb_zeros;j++) { EXEC SQL SELECT r_value, r_error, i_value, i_error INTO :r_value, :r_error:ind, :i_value, :i_error:ind FROM PZ_Data WHERE type = 'P' AND key = :pz_key AND row_key = :j; sprintf (stmp, "%12.5E%12.5E%12.5E%12.5E", r_value, i_value, r_error, i_error); strcat (s_ad, stmp); } sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } /* Decimation */ strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate:ind FROM Decimation WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; if (strlen (lddate) != 0) { /* Generating blockette 57 */ if (debug) printf ("\n\t Generating Blockette 57 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); EXEC SQL SELECT dm_key INTO :dm_key FROM Decimation WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; EXEC SQL SELECT samprate, factor, offset, delay, correction INTO samprate, factor, offset, delay, correction FROM DM WHERE key = :dm_key; sprintf (s_ad, "%.3s%04d%02d%10.4E%05d%05d%11.4E%11.4E", "057", 0, i, samprate, factor, offset, delay, correction); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } /* Sensitivity */ strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate:ind FROM Sensitivity WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; if (strlen (lddate) != 0) { /* Generating blockette 58 */ if (debug) printf ("\n\t Generating Blockette 58 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, i); EXEC SQL SELECT sensitivity, frequency INTO :sensitivity, :frequency FROM Sensitivity WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = :i; sprintf (s_ad, "%.3s%04d%02d%12.5E%12.5E%02d", "058", 0, i, sensitivity, frequency, 0); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } } /* Final stage */ strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate:ind FROM Polynomial WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = 0; if (strlen (lddate) != 0) { EXEC SQL SELECT pn_key, tf_type, unit_in, unit_out INTO :pn_key, :tf_type, :unit_in, :unit_out FROM Polynomial WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = 0; if (Flag_AP == 1) { /* Generating blockette 60 */ if (debug) printf ("\n\t Generating Blockette 60 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, 0); sprintf (s_ad, "%.3s%04d%02d%02d%02d%04d", "060", 0, 1, 0, 1, GetID (pn_key, 42)); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } else { /* Generating blockette 62 */ if (debug) printf ("\n\t Generating Blockette 62 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, 0); EXEC SQL SELECT poly_type, name, lower_bound, upper_bound, max_error INTO :poly_type, :polyname, :lower_bound, :upper_bound, :max_error FROM PN WHERE key = :pn_key; EXEC SQL SELECT count(*) INTO :nb_coeff FROM PN_Data WHERE key = :pn_key; /* Frequency Bounds */ if (strstr (polyname, "LDS") != NULL) upper_freq = .4; else if (strstr (polyname, "LD2") != NULL) upper_freq = .4; else if (strstr (polyname, "LKS") != NULL) upper_freq = .016; else if (strstr (polyname, "UK2") != NULL) upper_freq = .004; else if (strstr (polyname, "LFP") != NULL) upper_freq = .4; else if (strstr (polyname, "LEI") != NULL) upper_freq = .4; else { printf ("\n Error: Frequency bounds for polynomial [%s] not found. Assuming 0.4.\n\n", polyname); upper_freq = .4; } sprintf (s_ad, "%.3s%04d%c%02d%03d%03d%c%c%12.5E%12.5E%12.5E%12.5E%12.5E%03d", "062", 0, tf_type, 0, GetID (unit_in, 34), GetID (unit_out, 34), poly_type, 'B', 0., upper_freq, lower_bound, upper_bound, max_error, nb_coeff); for (j=1;j<=nb_coeff;j++) { EXEC SQL SELECT pn_value INTO :pn_value FROM PN_Data WHERE key = :pn_key AND row_key = :j; sprintf (stmp, "%12.5E%12.5E", pn_value, 0.); strcat (s_ad, stmp); } sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } } strcpy (lddate, ""); EXEC SQL SELECT lddate INTO :lddate:ind FROM Sensitivity WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = 0; if (strlen (lddate) != 0) { /* Generating blockette 58 */ if (debug) printf ("\n\t Generating Blockette 58 for %s.%s.%s.%s (Stage %d) ....", sta, net, seedchan, location, 0); EXEC SQL SELECT sensitivity, frequency INTO :sensitivity, :frequency FROM Sensitivity WHERE sta = :sta2 AND net = :net2 AND seedchan = :seedchan AND location = :location AND :date >= ondate AND :date < offdate AND stage_seq = 0; sprintf (s_ad, "%.3s%04d%02d%12.5E%12.5E%02d", "058", 0, 0, sensitivity, frequency, 0); sprintf (rl, "%04d", strlen (s_ad)); memcpy (s_ad+3, rl, 4); fprintf (f_ch, "%s\n", s_ad); } /* Closing Channel file */ fclose (f_ch); } strcpy (remark, ""); EXEC SQL FETCH cha_c INTO :sta, :net, :seedchan, :location, :inid:ind, :remark:ind, :unit_signal, :unit_calib, :lat:ind, :lon:ind, :elev:ind, :edepth:ind, :azimuth:ind, :dip:ind, :format_id, :record_length:ind, :samprate, :clock_drift:ind, :flags:ind, :ondate, :offdate:ind; /* Closing Channel file */ /*fclose (f_ch);*/ } EXEC SQL CLOSE cha_c; return; } /************************************************************************/ /* sql_error: */ /* */ /* Handle errors. Exit on any error. */ /************************************************************************/ void sql_error() { char msg[512]; size_t buf_len, msg_len; EXEC SQL WHENEVER SQLERROR CONTINUE; buf_len = sizeof(msg); sqlglm (msg, &buf_len, &msg_len); printf ("\nORACLE error detected:"); printf ("\n%.*s \n", msg_len, msg); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } /************************************************************************/ /* Main function */ /************************************************************************/ main (int argc, char* argv[]) { int Flag_From = 0; int Flag_To = 0; int Flag_Sta = 0; int Flag_Net = 0; int Flag_Ver = 0; int Flag_Pod = 0; char connect_string[255]; char npod[255]; /* POD request file name */ FILE *fpod; /* POD request file descriptor */ /* Variables needed for getopt. */ extern char *optarg; extern int optind, opterr; int c; char *p; cmdname = ((p = strrchr(*argv,'/')) != NULL) ? ++p : *argv; strcpy (connect_string, CONNECT_STRING); /* Parse command line options. */ while ( (c = getopt(argc,argv,"p:f:t:S:N:vh")) != -1) switch (c) { case '?': case 'h': print_syntax(cmdname,syntax,info); exit(0); break; case 'v': Flag_Ver = 1; break; case 'p': Flag_Pod = 1; strcpy (npod, optarg); break; case 'f': Flag_From = 1; strcpy (sdate, Convert_Date_JO (optarg)); break; case 't': Flag_To = 1; strcpy (edate, Convert_Date_JO (optarg)); break; case 'S': Flag_Sta = 1; strcpy (usta, optarg); break; case 'N': Flag_Net = 1; strcpy (unet, optarg); break; default: fprintf (info, "Unknown option: -%c\n", c); exit(1); } /* Skip over all options and their arguments. */ argv = &(argv[optind]); argc -= optind; /* POD request file */ if (Flag_Pod == 1) { char line[256], *p; int dup = 0; int n; int i; int Flag_POD_Cha; int Flag_POD_Sta; /* Opening POD request file */ if ((fpod = fopen (npod, "rt")) == NULL) { fprintf (stderr, "Error opening file %s\n", npod); exit(1); } /* Connect to ORACLE. */ if ((p = (char *) getenv ("DB_CONNECT")) != NULL) strcpy (connect_string, p); EXEC SQL WHENEVER SQLERROR DO sql_error(); strcpy (user_pwd, connect_string); EXEC SQL CONNECT :user_pwd; while (p = fgets (line, 256, fpod)) { n = strlen(line); /* Remove the newline from the string. */ if (n > 0 && line[n-1] == '\n') line[--n] = '\0'; /* This version splits the original line up into tokens. */ /* It modifies the input line. */ if (dup == 0) n = split_inline (line, '\t'); /* This version splits the original line up into tokens. */ /* It copies the the tokens, leaving the original line unmodified. */ if (dup != 0) n = split_copy (line, '\t'); if (n != 10) { fprintf (stderr, "Error scanning line, expected 10, found %d\n",n); fprintf (stderr, "Line:\t%s",line); exit(1); } /* Removing leap seconds */ if ((!memcmp (tokenv[8]+15, "60", 2)) || (!memcmp (tokenv[8]+16, "61", 2))) { tokenv[8][15] = '5'; tokenv[8][16] = '9'; } if ((!memcmp (tokenv[9]+15, "60", 2)) || (!memcmp (tokenv[9]+16, "61", 2))) { tokenv[9][15] = '5'; tokenv[9][16] = '9'; } if (Flag_Ver == 1) { printf ("station = '%s'\n", tokenv[0]); printf ("network = '%s'\n", tokenv[1]); printf ("channel = '%s'\n", tokenv[2]); printf ("location = '%s'\n", tokenv[3]); printf ("start = '%s'\n", tokenv[8]); printf ("end = '%s'\n", tokenv[9]); printf ("\n"); } /* Populating station array */ Flag_POD_Sta = 0; for (i=0;i 0) strcpy (podrs[i].etime, tokenv[9]); } } if (!Flag_POD_Sta) { strcpy (podrs[nb_req_sta].sta, tokenv[0]); strcpy (podrs[nb_req_sta].net, tokenv[1]); strcpy (podrs[nb_req_sta].stime, tokenv[8]); strcpy (podrs[nb_req_sta].etime, tokenv[9]); nb_req_sta++; } /* Populating channel array */ Flag_POD_Cha = 0; for (i=0;i 0) strcpy (podrc[i].etime, tokenv[9]); } } if (!Flag_POD_Cha) { strcpy (podrc[nb_req_cha].sta, tokenv[0]); strcpy (podrc[nb_req_cha].net, tokenv[1]); strcpy (podrc[nb_req_cha].cha, tokenv[2]); strcpy (podrc[nb_req_cha].loc, tokenv[3]); strcpy (podrc[nb_req_cha].stime, tokenv[8]); strcpy (podrc[nb_req_cha].etime, tokenv[9]); nb_req_cha++; } reset_token (&tokenc, &tokenv, dup); } fclose (fpod); printf ("\n Generating station blockettes:"); for (i=0;i tedate) { printf ("\n End date has to be greater than start date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } if ((tsdate > tmaxdate) || (tedate < tmindate)) { printf ("\n No data found for this station at this date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } strcpy (lddate, ""); EXEC SQL SELECT ondate, lddate INTO :ondate, :lddate FROM station_data WHERE sta = :sta3 AND net = :net3 AND :sdate >= ondate AND :sdate < offdate; if (strlen (lddate) == 0) strcpy (ondate, mindate); strcpy (lddate, ""); EXEC SQL SELECT offdate, lddate INTO :offdate, :lddate FROM station_data WHERE sta = :sta3 AND net = :net3 AND :edate > ondate AND :edate <= offdate; if (strlen (lddate) == 0) strcpy (offdate, maxdate); /* Retrieving time intervals */ EXEC SQL DECLARE date_cursor_sta CURSOR FOR SELECT ondate, offdate FROM station_data WHERE sta = :sta3 AND net = :net3 AND ondate >= :ondate AND ondate < :offdate ORDER BY ondate; EXEC SQL OPEN date_cursor_sta; EXEC SQL FETCH date_cursor_sta INTO :ondate, :offdate; while (sqlca.sqlcode != NOMOREROWS) { printf ("\n Generating response for time interval %.20s --> %.20s", ondate, offdate); if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", podrs[i].sta, podrs[i].net, "", "", ondate, 's', Flag_Ver); Generate_Tree (podrs[i].sta, podrs[i].net, "", "", ondate, 's', Flag_Ver); EXEC SQL FETCH date_cursor_sta INTO :ondate, :offdate; } EXEC SQL CLOSE date_cursor_sta; } printf ("\n\n Generating channel blockettes:"); for (i=0;i tedate) { printf ("\n End date has to be greater than start date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } if ((tsdate > tmaxdate) || (tedate < tmindate)) { printf ("\n No data found for this station at this date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } strcpy (lddate, ""); EXEC SQL SELECT ondate, lddate INTO :ondate, :lddate FROM channel_data WHERE sta = :sta3 AND net = :net3 AND seedchan = :seedchan3 AND location = :location3 AND :sdate >= ondate AND :sdate < offdate; if (strlen (lddate) == 0) strcpy (ondate, mindate); strcpy (lddate, ""); EXEC SQL SELECT offdate, lddate INTO :offdate, :lddate FROM channel_data WHERE sta = :sta3 AND net = :net3 AND seedchan = :seedchan3 AND location = :location3 AND :edate > ondate AND :edate <= offdate; if (strlen (lddate) == 0) strcpy (offdate, maxdate); /* Retrieving time intervals */ EXEC SQL DECLARE date_cursor_cha CURSOR FOR SELECT ondate, offdate FROM channel_data WHERE sta = :sta3 AND net = :net3 AND seedchan = :seedchan3 AND location = :location3 AND ondate >= :ondate AND ondate < :offdate ORDER BY ondate; EXEC SQL OPEN date_cursor_cha; EXEC SQL FETCH date_cursor_cha INTO :ondate, :offdate; while (sqlca.sqlcode != NOMOREROWS) { printf ("\n Generating response for time interval %.20s --> %.20s", ondate, offdate); if (strlen (podrc[i].loc) == 0) { if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", podrc[i].sta, podrc[i].net, podrc[i].cha, "", ondate, 'c', Flag_Ver); Generate_Tree (podrc[i].sta, podrc[i].net, podrc[i].cha, "", ondate, 'c', Flag_Ver); } else { if (!strcmp (podrc[i].loc, " ")) strcpy (podrc[i].loc, "--"); if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", podrc[i].sta, podrc[i].net, podrc[i].cha, podrc[i].loc, ondate, 'c', Flag_Ver); Generate_Tree (podrc[i].sta, podrc[i].net, podrc[i].cha, podrc[i].loc, ondate, 'c', Flag_Ver); } EXEC SQL FETCH date_cursor_cha INTO :ondate, :offdate; } EXEC SQL CLOSE date_cursor_cha; } printf ("\n"); /* Disconnect from the database. */ EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Station/Network in upper case */ if (Flag_Sta) for (i=0;i tedate) { printf ("\n End date has to be greater than start date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } if ((tsdate > tmaxdate) || (tedate < tmindate)) { printf ("\n No data found for this station at this date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } strcpy (lddate, ""); EXEC SQL SELECT ondate, lddate INTO :ondate, :lddate FROM station_data WHERE sta = :usta AND net = :unet AND :sdate >= ondate AND :sdate < offdate; if (strlen (lddate) == 0) strcpy (ondate, mindate); strcpy (lddate, ""); EXEC SQL SELECT offdate, lddate INTO :offdate, :lddate FROM station_data WHERE sta = :usta AND net = :unet AND :edate > ondate AND :edate <= offdate; if (strlen (lddate) == 0) strcpy (offdate, maxdate); /* Retrieving time intervals */ EXEC SQL DECLARE date_cursor CURSOR FOR SELECT ondate, offdate FROM station_data WHERE sta = :usta AND net = :unet AND ondate >= :ondate AND ondate < :offdate ORDER BY ondate; EXEC SQL OPEN date_cursor; EXEC SQL FETCH date_cursor INTO :ondate, :offdate; while (sqlca.sqlcode != NOMOREROWS) { printf ("\n Generating station for time interval %.20s --> %.20s", ondate, offdate); if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", usta, unet, "", "", ondate, 's', Flag_Ver); Generate_Tree (usta, unet, "", "", ondate, 's', Flag_Ver); EXEC SQL FETCH date_cursor INTO :ondate, :offdate; } EXEC SQL CLOSE date_cursor; printf ("\n\n Generating channel blockettes:"); EXEC SQL DECLARE cha_cursor CURSOR FOR SELECT distinct seedchan, location FROM channel_data WHERE sta = :usta AND net = :unet; EXEC SQL OPEN cha_cursor; EXEC SQL FETCH cha_cursor INTO :seedchan3, :location3; while (sqlca.sqlcode != NOMOREROWS) { Remove_Blank (seedchan3); Remove_Blank (location3); if (strlen (location3) == 0) strcpy (location3, " "); /* Converting dates */ EXEC SQL SELECT TRUETIME.STRING2NOMINAL (:sdate) INTO :tsdate FROM DUAL; EXEC SQL SELECT TRUETIME.STRING2NOMINAL (:edate) INTO :tedate FROM DUAL; EXEC SQL SELECT min (ondate) INTO :mindate:ind FROM channel_data WHERE sta = :usta AND net = :unet AND seedchan = :seedchan3 AND location = :location3; EXEC SQL SELECT max (offdate) INTO :maxdate:ind FROM channel_data WHERE sta = :usta AND net = :unet AND seedchan = :seedchan3 AND location = :location3; EXEC SQL SELECT TRUETIME.STRING2NOMINAL (:mindate) INTO :tmindate FROM DUAL; EXEC SQL SELECT TRUETIME.STRING2NOMINAL (:maxdate) INTO :tmaxdate FROM DUAL; if (tsdate > tedate) { printf ("\n End date has to be greater than start date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } if ((tsdate > tmaxdate) || (tedate < tmindate)) { printf ("\n No data found for this station at this date.\n\n"); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } strcpy (lddate, ""); EXEC SQL SELECT ondate, lddate INTO :ondate, :lddate FROM channel_data WHERE sta = :usta AND net = :unet AND seedchan = :seedchan3 AND location = :location3 AND :sdate >= ondate AND :sdate < offdate; if (strlen (lddate) == 0) strcpy (ondate, mindate); strcpy (lddate, ""); EXEC SQL SELECT offdate, lddate INTO :offdate, :lddate FROM channel_data WHERE sta = :usta AND net = :unet AND seedchan = :seedchan3 AND location = :location3 AND :edate > ondate AND :edate <= offdate; if (strlen (lddate) == 0) strcpy (offdate, maxdate); /* Retrieving time intervals */ EXEC SQL DECLARE date_cursor_cha2 CURSOR FOR SELECT ondate, offdate FROM channel_data WHERE sta = :usta AND net = :unet AND seedchan = :seedchan3 AND location = :location3 AND ondate >= :ondate AND ondate < :offdate ORDER BY ondate; EXEC SQL OPEN date_cursor_cha2; EXEC SQL FETCH date_cursor_cha2 INTO :ondate, :offdate; while (sqlca.sqlcode != NOMOREROWS) { printf ("\n Generating response for [%s.%s.%s.%s] time interval %.20s --> %.20s", unet, usta, seedchan3, location3, ondate, offdate); if (strlen (location3) == 0) { if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", usta, unet, seedchan3, "", ondate, 'c', Flag_Ver); Generate_Tree (usta, unet, seedchan3, "", ondate, 'c', Flag_Ver); } else { if (!strcmp (location3, " ")) strcpy (location3, "--"); if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", usta, unet, seedchan3, location3, ondate, 'c', Flag_Ver); Generate_Tree (usta, unet, seedchan3, location3, ondate, 'c', Flag_Ver); } EXEC SQL FETCH date_cursor_cha2 INTO :ondate, :offdate; } EXEC SQL CLOSE date_cursor_cha2; EXEC SQL FETCH cha_cursor INTO :seedchan3, :location3; } EXEC SQL CLOSE cha_cursor; printf ("\n\n"); /* Disconnect from the database. */ EXEC SQL COMMIT WORK RELEASE; exit(0); } /************************************************************************/ /* Split functions: */ /* The split functions will split a line containing 0 or more tokens */ /* into an argc/argv style list of tokens. */ /* Tokens are SEPARATED by the specified delimiter. */ /* If there are NO characters in the line, there are no tokens. */ /* If there are 2 adjacent delimeters (or adjacent delimiter and */ /* string terminator), that represents a 0 length token. */ /************************************************************************/ /************************************************************************/ /* split_inline: */ /* Split line into tokens based on delimiter. */ /* Push token onto list when start of token is seen. */ /* Do not copy token, so token may be modified later. */ /* Original line is modified. */ /************************************************************************/ int split_inline (char *line, char delim) { char *p = line; int start_token = 1; int force_token = 0; for (p=line;;p++) { if (*p == 0) { if (force_token) { push_token (&tokenc, &tokenv, p, 0); } return (tokenc); } if (start_token) { push_token (&tokenc, &tokenv, p, 0); start_token = 0; force_token = 0; } if (*p == delim) { *p = '\0'; start_token = 1; force_token = 1; } } } /************************************************************************/ /* split_copy: */ /* Split line into tokens based on delimiter. */ /* Push token onto list at end of token. */ /* Copy token. Do not modify original line. */ /************************************************************************/ int split_copy (char *line, char delim) { char *p; char *s; char *str; int in_token = 0; for (p=line,s=line;;p++) { if (*p == 0) { if (in_token) { str = strndup(s,p+1-s); str[p-s] = '\0'; push_token (&tokenc, &tokenv, str, 0); } return (tokenc); } in_token = 1; if (*p == delim) { str = strndup(s,p+1-s); str[p-s] = '\0'; push_token (&tokenc, &tokenv, str, 0); s = p+1; } } } /************************************************************************/ /* General token routines. */ /************************************************************************/ /************************************************************************/ /* push_token: */ /* Push a token onto a token list. */ /* Allocate additional space for the expanded token list. */ /* Allocate space for actual token if dup flag is set. */ /************************************************************************/ int push_token (int *pargc, char ***pargv, char *p, int dup) { int n = *pargc; char **argv = *pargv; argv = (n==0) ? (char **)malloc((n+1)*sizeof(char *)) : (char **)realloc(argv,(n+1)*sizeof(char *)); if (argv == NULL) { fprintf (stderr, "Error (re)allocing argv\n"); exit(1); } argv[n++] = (dup) ? strdup(p) : p; *pargv = argv; *pargc = n; return (0); } /************************************************************************/ /* reset_token: */ /* Free the space for the tokenv array list. */ /* Reset the token list variables. */ /* Free actual tokens of dup variable is dup is set. */ /************************************************************************/ int reset_token (int *pargc, char ***pargv, int dup) { if (dup) { int i; int argc = *pargc; char **argv = *pargv; for (i=0; i0) *t++ = *p++; return s; }