/************************************************************************/ /* 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.0 SMZ Fixed Bug. B052 files were never getting closed. /************************************************************************/ #ifndef lint static char sccsid[] = "%W% %G% %U%"; #endif #include #include #include #include #include #include #include #include #include #define VERSION "2.0" #define CONNECT_STRING2 "netdc/dB2Usr@ncedc" #define CONNECT_STRING "ciresp/dB2Usr@ncedc" #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] [-C channel] [-L location] [-N network] [-m a|s|c] [-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.", " -C channel Specifies a SEED channel name.", " -L location Specifies a SEED location code.", " -m a|s|c Specifies the output mode (all, station, channel).", " -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 USE_ABPOLY set --> Use blockettes 42 & 60 instead of 62.", NULL }; /* Structures declaration */ typedef struct { char sta[7]; char net[3]; char cha[4]; char loc[3]; char stime[32]; char etime[32]; } POD_Req_Cha; typedef struct { char sta[7]; char net[3]; char stime[32]; char etime[32]; } POD_Req_Sta; 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 staname[51]; /* Station name */ char cha[7]; /* Channel code */ char loc[3]; /* Location code */ char net[9]; /* Network code */ char net2[9]; /* Network code */ int inid; /* Instrument identifier */ int net_id; /* Network identifier */ char channel[4]; /* Channel name */ char seedchan[4]; /* SEED channel name */ char channelsrc[9]; /* Channel source */ char location[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[32]; /* Date */ char ondate[32]; /* Start date */ char offdate[32]; /* End date */ char condate[32]; /* Start date */ char coffdate[32]; /* End date */ char sondate[32]; /* Start date */ char soffdate[32]; /* End date */ char on_date[32]; /* Start date */ char off_date[32]; /* End date */ char lddate[32]; /* 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 max_error; /* Maximum error */ int nb_coeff; /* Number of coefficients */ double pn_value; /* Coefficient */ char sdate[32]; /* Start date */ char edate[32]; /* 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 */ EXEC SQL END DECLARE SECTION; /************************************************************************/ /* 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; /* 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 a Oracle date to a Julian date /************************************************************************/ char* Convert_Date_OJ (char d[32]) { EXEC SQL BEGIN DECLARE SECTION; char nd[32]; int day; EXEC SQL END DECLARE SECTION; static char fd[32]; 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: /* /* Function to convert a julian date to a Oracle date /************************************************************************/ char* Convert_Date_JO (char d[32]) { static char nd[32]; 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); } /************************************************************************/ /* Generate_Tree: /* /* Function to generate the SEED tree structure /************************************************************************/ void Generate_Tree ( char sta2[7], /* Station code */ char net2[9], /* Network code */ char cha[7], /* Channel name */ char loc[3], /* Location code */ char pdate[32], /* 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 = 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 */ /* Location code */ if ((!strcmp (loc, "-")) || (!strcmp (loc, "--"))) strcpy (loc, " "); /* 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); } /* 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; EXEC SQL DECLARE chan_cursor CURSOR FOR SELECT sta, net, seedchan, channel, channelsrc, 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 = :sta2 AND net = :net2 AND :date >= ondate AND :date < offdate; EXEC SQL OPEN chan_cursor; strcpy (remark, ""); EXEC SQL FETCH chan_cursor INTO :sta:ind, :net:ind, :seedchan:ind, :channel:ind, :channelsrc:ind, :location:ind, :inid:ind, :remark:ind, :unit_signal:ind, :unit_calib:ind, :lat:ind, :lon:ind, :elev:ind, :edepth:ind, :azimuth:ind, :dip:ind, :format_id:ind, :record_length:ind, :samprate:ind, :clock_drift:ind, :flags:ind, :ondate:ind, :offdate:ind; while (sqlca.sqlcode != NOMOREROWS) { Remove_Blank (sta); Remove_Blank (net); Remove_Blank (seedchan); Remove_Blank (channel); Remove_Blank (channelsrc); /*Remove_Blank (location);*/ Remove_Blank (ondate); Remove_Blank (offdate); Remove_Blank (flags); Remove_Blank (remark); /* Testing channel/location */ if ((strlen (cha) == 0) && (strlen (loc) == 0)) Flag = 0; else if ((strlen (cha) != 0) && (strlen (loc) == 0)) { if (strcmp (seedchan, cha)) Flag = 1; else Flag = 0; } else if ((strlen (loc) != 0) && (strlen (cha) == 0)) { if (strcmp (location, loc)) Flag = 1; else Flag = 0; } else { if ((strcmp (seedchan, cha)) || (strcmp (location, loc))) 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); sprintf (s_ad, "%.3s%04d%s~%04d%03d%02d", "030", 0, name, id, family, nb_keys); 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); sprintf (s_ad, "%.3s%04d%04d%c%s~%03d", "031", 0, id, class, description, unit); /* 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); sprintf (s_ad, "%.3s%04d%03d%s~", "033", 0, id, description); /* 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, net_id, 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, comment_id, 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)); 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, inid, remark, unit_signal, unit_calib, lat, lon, elev, edepth, azimuth, dip, format_id, 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, comment_id, 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 */ 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) { 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, pn_key+5000); 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, lower_bound, upper_bound, max_error INTO :poly_type, :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; 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, unit_in, unit_out, poly_type, 'A', 0., samprate/2., 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, dc_key); 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, unit_in, unit_out, 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 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); } } strcpy (remark, ""); EXEC SQL FETCH chan_cursor INTO :sta:ind, :net:ind, :seedchan:ind, :channel:ind, :channelsrc:ind, :location:ind, :inid:ind, :remark:ind, :unit_signal:ind, :unit_calib:ind, :lat:ind, :lon:ind, :elev:ind, :edepth:ind, :azimuth:ind, :dip:ind, :format_id:ind, :record_length:ind, :samprate:ind, :clock_drift:ind, :flags:ind, :ondate:ind, :offdate:ind; /* Closing Channel file */ fclose (f_ch); } EXEC SQL CLOSE chan_cursor; 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_Cha = 0; int Flag_Loc = 0; int Flag_Mod = 0; int Flag_Ver = 0; int Flag_Pod = 0; char mode; /* Mode: a|s|c */ 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; /* Parse command line options. */ while ( (c = getopt(argc,argv,"p:f:t:S:C:L:N:m: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 (sta2, optarg); break; case 'C': Flag_Cha = 1; strcpy (cha, optarg); break; case 'L': Flag_Loc = 1; strcpy (loc, optarg); break; case 'N': Flag_Net = 1; strcpy (net2, optarg); break; case 'm': Flag_Mod = 1; mode = optarg[0]; if ((mode != 'a') && (mode != 's') && (mode != 'c')) { printf ("\n Error: Mode has to be .\n\n"); exit(0); } 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. */ 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 = :sta2 AND net = :net2 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 = :sta2 AND net = :net2 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 = :sta2 AND net = :net2 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 station_data WHERE sta = :sta2 AND net = :net2 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 = :sta2 AND net = :net2 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 station_data WHERE sta = :sta2 AND net = :net2 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/Channel/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 = :sta2 AND net = :net2 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 = :sta2 AND net = :net2 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 = :sta2 AND net = :net2 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 response for time interval %.20s --> %.20s", ondate, offdate); if (Flag_Ver) printf ("\n Calling Generate_Tree [%s, %s, %s, %s, %.20s, %c, %d]\n", sta2, net2, cha, loc, ondate, mode, Flag_Ver); Generate_Tree (sta2, net2, cha, loc, ondate, mode, Flag_Ver); EXEC SQL FETCH date_cursor INTO :ondate, :offdate; } EXEC SQL CLOSE date_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; }