00001 /* 00002 * THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE 00003 * CHECKED IT OUT USING THE COMMAND CHECKOUT. 00004 * 00005 * $Id: rw__mag_8c-source.html 2161 2006-05-19 16:55:03Z paulf $ 00006 * 00007 * Revision history: 00008 * $Log$ 00008 * Revision 1.1 2006/05/19 16:55:02 paulf 00008 * first inclusion 00008 * 00009 * Revision 1.11 2002/06/28 21:03:57 lucky 00010 * Fixed reading of mag phases -- it would not properly read float 00011 * values for amplitude and period 00012 * 00013 * Revision 1.10 2001/08/07 16:54:17 lucky 00014 * Pre v6.0 checkin 00015 * 00016 * Revision 1.9 2001/06/07 20:51:49 lucky 00017 * Modified wr_mag so that it checks for NULL strings. Before, if qid was null, 00018 * wr_mag would produce an invalid TYPE_MAGNITUDE message which could not 00019 * be parsed by rd_mag. This is not good, given that the qid is not known 00020 * in the review system. 00021 * 00022 * Revision 1.8 2001/06/07 19:48:28 lucky 00023 * rd_chan_mag_lucky renamed to rd_chan_mag. The old rd_chan_mag is still 00024 * available as rd_chan_mag_Pete. 00025 * 00026 * Revision 1.7 2001/05/31 21:09:02 lucky 00027 * Addedd rd_chan_mag_lucky; I don't think that rd_chan_mag in its original form 00028 * works. There are numerical comparisons of pointers, and other visible problems. 00029 * 00030 * Revision 1.6 2001/05/26 21:04:59 lombard 00031 * Changed ML_INFO struct to MAG_CHAN_INFO struct to make it more 00032 * generic; now this struct should work with most mag types. 00033 * Fixed a number of obvious bugs and cleaned up the code. 00034 * But the parsers still have not been tested and this may not work. 00035 * 00036 * Revision 1.5 2001/05/02 20:58:45 alex 00037 * *** empty log message *** 00038 * 00039 * Revision 1.4 2001/05/01 22:38:48 davidk 00040 * moved the MagNames table out of the header file and into rw_mag.c 00041 * 00042 * Revision 1.3 2001/05/01 20:26:02 davidk 00043 * Modified several new functions added by Alex, so that they compile and do not impede the 00044 * release. The new functions have been added, but have not properly been tested and debugged, 00045 * at all. 00046 * 00047 * Revision 1.2 2001/04/29 00:15:29 alex 00048 * Alex: changes for mag type int and string, and added alternate parsing routines. 00049 * 00050 * Revision 1.1 2001/03/31 00:44:58 lombard 00051 * Initial revision 00052 * 00053 * 00054 * 00055 */ 00056 00057 /* rw_mag.c 00058 * 00059 * Contains functions in that convert from a 00060 * TYPE_MAGNITUDE message to a structure and visa versa. 00061 * 00062 * written by Pete Lombard February, 2001 00063 */ 00064 00065 #include <stdio.h> 00066 #include <string.h> 00067 #include <earthworm.h> 00068 #include <rw_mag.h> 00069 00070 /* Internal Function Prototypes */ 00071 static int strappend( char *s1, int s1max, char *s2 ); 00072 static int tokenlength( char *begtok, char c ); 00073 00074 /******************************************************************** 00075 * rd_mag() * 00076 * Reads an ascii TYPE_MAGNITUDE message and fills in a MAG_INFO * 00077 * structure which must be allocated by the caller * 00078 * If, in addition, the caller allocates space for auxiliary * 00079 * structures at pMag->pMagAux (number of bytes in pMag->size_aux), * 00080 * then rd_mag will call the appropriate function to decode the * 00081 * remainder of the message into appropriate structures. * 00082 * Currently supported magnitude types are: Ml * 00083 * Returns 0 on success * 00084 * -1 on parsing errors * 00085 * -2 on insufficient space in pMagAux * 00086 ********************************************************************/ 00087 int rd_mag( char *msg, int msgLen, MAG_INFO *pMag) 00088 { 00089 size_t size_aux; 00090 char *pMagAux; 00091 00092 size_aux = pMag->size_aux; 00093 pMagAux = (char *)pMag->pMagAux; 00094 memset(pMag, 0, sizeof(MAG_INFO)); 00095 00096 switch ( sscanf( msg 00097 , "%s MAG %d %s %lf %s %d %d %lf %lf %lf %d %s %d %d" 00098 , pMag->qid 00099 , &pMag->imagtype 00100 , pMag->szmagtype 00101 , &pMag->mag 00102 , pMag->algorithm 00103 , &pMag->nstations 00104 , &pMag->nchannels 00105 , &pMag->error 00106 , &pMag->quality 00107 , &pMag->mindist 00108 , &pMag->azimuth 00109 , pMag->qauthor 00110 , &pMag->origin_version 00111 , &pMag->qdds_version 00112 ) ) 00113 { 00114 case 12: /* old-style, no origin version, qdds version numbers */ 00115 pMag->origin_version = 0; 00116 pMag->qdds_version = 0; 00117 break; 00118 case 13: /* new-style, with origin version, no qdds version */ 00119 pMag->qdds_version = 0; 00120 break; 00121 case 14: /* new-style, with both number */ 00122 break; 00123 default: 00124 return( -1 ); 00125 } 00126 00127 if (pMagAux && size_aux > 0) 00128 { 00129 pMag->size_aux = size_aux; 00130 pMag->pMagAux = pMagAux; 00131 00132 /* Read the rest of a Mag message */ 00133 if (pMag->pMagAux != NULL) 00134 { 00135 return( rd_chan_mag(msg, msgLen, (MAG_CHAN_INFO *)pMag->pMagAux, 00136 pMag->size_aux) ); 00137 } 00138 } 00139 00140 return( 0 ); 00141 } 00142 00143 /***************************************************************** 00144 * rd_chan_mag() * 00145 * Reads an ascii TYPE_MAGNITUDE Ml message and fills in * 00146 * MAG_CHAN_INFO structures. * 00147 * This function can be called by rd_mag if sufficient space is * 00148 * allocated by its caller. Or it may be called after rd_mag * 00149 * when the caller has allocated space for `nchannels' of * 00150 * MAG_CHAN_INFO structures. * 00151 * Returns 0 on success * 00152 * -1 on parsing errors * 00153 * -2 on insufficient space in pMagAux * 00154 *****************************************************************/ 00155 int rd_chan_mag ( char *msg, int msglen, MAG_CHAN_INFO *pMci, int size_ml) 00156 { 00157 char *line; 00158 char *begtok; 00159 char *tmpMsg; /* local copy of msg */ 00160 int len; /* length (bytes) of the next token */ 00161 int nchan; /* number of channels read from msg so far */ 00162 int nML; /* number of MAG_CHAN_INFO structures we can use */ 00163 int rc; 00164 int index; 00165 00166 memset(pMci, 0, size_ml); 00167 nML = size_ml / sizeof(MAG_CHAN_INFO); 00168 00169 tmpMsg = (char *) malloc (msglen); 00170 strcpy (tmpMsg, msg); 00171 00172 nchan = 0; 00173 00174 /* Skip the first line */ 00175 len = tokenlength (tmpMsg, '\n'); 00176 00177 index = len + 1; 00178 00179 /* Read next line from the message into working buffer */ 00180 while(index < (msglen-1)) 00181 { 00182 /* Process next line */ 00183 line = tmpMsg + index; 00184 len = tokenlength(line, '\n' ); 00185 line[len] = '\0'; 00186 index = index + len + 1; 00187 00188 begtok = line; 00189 while( begtok[0] == ' ' && begtok[0] != '\0') begtok++; /* go to 1st non-blank char */ 00190 if( begtok[0] == '\0' ) return( -1 ); 00191 len = tokenlength( begtok, '.' ); 00192 if( len >= TRACE_STA_LEN ) return( -1 ); 00193 strncpy( pMci[nchan].sta, begtok, len ); 00194 pMci[nchan].sta[len] = '\0'; 00195 begtok += len + 1; 00196 00197 len = tokenlength( begtok, '.' ); 00198 if( len >= TRACE_CHAN_LEN ) return( -1 ); 00199 strncpy( pMci[nchan].comp, begtok, len ); 00200 pMci[nchan].comp[len] = '\0'; 00201 begtok += len + 1; 00202 00203 len = tokenlength( begtok, ' ' ); 00204 if( len >= TRACE_NET_LEN ) return( -1 ); 00205 strncpy( pMci[nchan].net, begtok, len ); 00206 pMci[nchan].net[len] = '\0'; 00207 begtok += len + 1; 00208 00209 while( begtok[0] == ' ' && begtok[0] != '\0' ) begtok++; /* go to next non-blank char */ 00210 if ( (rc = sscanf(begtok, "%lf %lf %lf %E %lf %f %E %lf %f", 00211 &(pMci[nchan].mag), &(pMci[nchan].dist), &(pMci[nchan].corr), 00212 &(pMci[nchan].Amp1), &(pMci[nchan].Time1), &(pMci[nchan].Period1), 00213 &(pMci[nchan].Amp2), &(pMci[nchan].Time2), 00214 &(pMci[nchan].Period2))) != 9) 00215 { 00216 if (rc == 6) 00217 { 00218 pMci[nchan].Amp2 = pMci[nchan].Time2 = pMci[nchan].Period2 = -1.0; 00219 continue; 00220 } 00221 return( -1 ); 00222 } 00223 00224 nchan = nchan + 1; 00225 00226 } 00227 00228 return 0; 00229 } 00230 00231 00232 00233 /******************************************************************* 00234 * wr_mag() * 00235 * Reads a MAG_INFO structure and writes an ascii TYPE_MAGNITUDE * 00236 * message (null terminated) * 00237 * Returns 0 on success, -1 on failure (potential buffer overflow) * 00238 *******************************************************************/ 00239 int wr_mag( MAG_INFO *pMag, char *buf, int buflen ) 00240 { 00241 char tmp[256]; /* working buffer */ 00242 char qid[256]; 00243 char szmagtype[256]; 00244 char algorithm[256]; 00245 char qauthor[256]; 00246 00247 memset( buf, 0, (size_t)buflen ); /* zero output buffer */ 00248 00249 /* 00250 * We should check for null strings, if for nothing else than to 00251 * avoid mis-formatted message trickling down the system. LV 6/2001 00252 */ 00253 if (strlen (pMag->qid) == 0) 00254 strcpy (qid, "UNKNOWN"); 00255 else 00256 strcpy (qid, pMag->qid); 00257 00258 if (strlen (pMag->szmagtype) == 0) 00259 strcpy (szmagtype, "UNKNOWN"); 00260 else 00261 strcpy (szmagtype, pMag->szmagtype); 00262 00263 if (strlen (pMag->algorithm) == 0) 00264 strcpy (algorithm, "UNKNOWN"); 00265 else 00266 strcpy (algorithm, pMag->algorithm); 00267 00268 if (strlen (pMag->qauthor) == 0) 00269 strcpy (qauthor, "UNKNOWN"); 00270 else 00271 strcpy (qauthor, pMag->qauthor); 00272 00273 sprintf(tmp, "%s MAG %d %s %0.2f %s %d %d %0.2f %0.2f %0.2f %d %s %d %d\n", 00274 qid, pMag->imagtype, szmagtype, pMag->mag, algorithm, 00275 pMag->nstations, pMag->nchannels, pMag->error, pMag->quality, 00276 pMag->mindist, pMag->azimuth, qauthor, pMag->origin_version 00277 , pMag->qdds_version 00278 ); 00279 00280 if ( strappend( buf, buflen, tmp ) ) return( -1 ); 00281 00282 if (pMag->pMagAux != NULL) 00283 { 00284 return( wr_chan_mag( (MAG_CHAN_INFO *)pMag->pMagAux, pMag->nchannels, 00285 buf, buflen) ); 00286 } 00287 00288 return( 0 ); 00289 } 00290 00291 /******************************************************************* 00292 * wr_chan_mag() * 00293 * Reads MAG_CHAN_INFO structures and appends to an ascii * 00294 * TYPE_MAGNITUDE message (null terminated) * 00295 * Normally this would be called by wr_mag(). * 00296 * Returns 0 on success, -1 on failure (potential buffer overflow) * 00297 *******************************************************************/ 00298 int wr_chan_mag( MAG_CHAN_INFO *pMci, int nchannels, char *buf, int buflen ) 00299 { 00300 int i; 00301 char line[256]; 00302 00303 for (i = 0; i < nchannels; i++) 00304 { 00305 sprintf(line, 00306 "%s.%s.%s %.2f %.2f %.2f %9.2E %9.2f %9.2f %9.2E %9.2f %9.2f\n", 00307 /*s c n mag dist corr Amp1 Time1 Period1 Amp2 Time2 Period2 */ 00308 pMci[i].sta, pMci[i].comp, pMci[i].net, 00309 pMci[i].mag, pMci[i].dist, pMci[i].corr, 00310 pMci[i].Amp1, 00311 ( (pMci[i].Time1 < 0.0) ? -1.0 : pMci[i].Time1), 00312 ( (pMci[i].Period1 < 0.0) ? -1.0 : pMci[i].Period1), 00313 pMci[i].Amp2, 00314 ( (pMci[i].Time2 < 0.0) ? -1.0 : pMci[i].Time2), 00315 ( (pMci[i].Period2 < 0.0) ? -1.0 : pMci[i].Period2)); 00316 00317 if ( strappend(buf, buflen, line)) 00318 return( -1 ); 00319 } 00320 return( 0 ); 00321 } 00322 00323 00324 /******************************************************************** 00325 * strappend() append second null-terminated character string to * 00326 * the first as long as there's enough room in the target buffer * 00327 * for both strings an the null-byte * 00328 ********************************************************************/ 00329 static int strappend( char *s1, int s1max, char *s2 ) 00330 { 00331 if( (int)strlen(s1)+(int)strlen(s2)+1 > s1max ) return( -1 ); 00332 strcat( s1, s2 ); 00333 return( 0 ); 00334 } 00335 00336 /******************************************************************** 00337 * tokenlength() given a null-terminated character string and a * 00338 * character that delimits the end of a token, tokenlength returns * 00339 * the length (in bytes) of the next token. If the character wasn't * 00340 * found, tokenlength returns the length of the string. * 00341 ********************************************************************/ 00342 static int tokenlength( char *begtok, char c ) 00343 { 00344 char *endtok; /* points to the end of this token */ 00345 00346 endtok = strchr( begtok, c ); 00347 if( endtok == NULL ) return( (int)strlen(begtok) ); 00348 return( (int)(endtok-begtok) ); 00349 }