00001 00002 /* 00003 * THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE 00004 * CHECKED IT OUT USING THE COMMAND CHECKOUT. 00005 * 00006 * $Id: parse__trig_8c-source.html 2161 2006-05-19 16:55:03Z paulf $ 00007 * 00008 * Revision history: 00009 * $Log$ 00009 * Revision 1.1 2006/05/19 16:55:02 paulf 00009 * first inclusion 00009 * 00010 * Revision 1.7 2002/02/12 04:38:36 davidk 00011 * modded to stop segfault on blank lines 00012 * for trigfiles generated by arc2trig on solaris. 00013 * The strtok appears to be returning NULL on a blank line, 00014 * causing a segfault when evaluated by strcmp, 00015 * so I separated the two calls. 00016 * 00017 * Revision 1.6 2001/04/05 17:56:27 cjbryan 00018 * *** empty log message *** 00019 * 00020 * Revision 1.5 2001/03/22 16:13:28 alex 00021 * *** empty log message *** 00022 * 00023 * Revision 1.4 2001/03/21 18:50:27 alex 00024 * subnet NULL fix as per Pete. 00025 * 00026 * Revision 1.3 2001/03/21 02:20:04 alex 00027 * Alex 3/20/1 added .subnet stuff for CVO 00028 * 00029 * Revision 1.2 2000/03/31 18:26:03 lucky 00030 * *** empty log message *** 00031 * 00032 * Revision 1.1 2000/02/14 18:51:48 lucky 00033 * Initial revision 00034 * 00035 * 00036 */ 00037 00038 /************************************************************ 00039 * parse_trig.c * 00040 * * 00041 * 1/19/00 Alex: changed eventId from being an integer to * 00042 * a string. * 00043 * * 00044 * Mon Nov 2 11:02:23 MST 1998 lucky * 00045 * Y2K compliance: * 00046 * SNIPPET struct has been modified to include 8 digit * 00047 * date (YYYYMMDD), and corresponding changes have been * 00048 * made in parse_Snippet(). * 00049 * * 00050 * t_atodbl() changed to reflect YYYYMMDD. Introduced * 00051 * defines that hold string lengths in case these formats * 00052 * ever need to be changed in the future. Call to * 00053 * epocchsec15() replaced by epochsec17(). * 00054 * * 00055 ************************************************************/ 00056 00057 #include <stdio.h> 00058 #include <stdlib.h> 00059 #include <string.h> 00060 #include <time.h> 00061 00062 #ifndef EARTHWORM_H 00063 #include <earthworm.h> 00064 #endif 00065 #include <parse_trig.h> 00066 00067 00068 #define LINE_LEN 500 00069 #define BAD_TIME_VALUE 5 00070 00071 /* Function declarations */ 00072 extern int epochsec17 (double *, char *); 00073 int getNextLine (char**, char*); 00074 int t_atodbl (char*, char*, double*); 00075 00076 /* 00077 Story: 00078 parseSnippet() parses a trigger message. Inspired by, and uses, 00079 strtok. Therefore, IT IS NOT MULTI-THREAD SAFE. It must be mutex 00080 protected against concurrent calls to strtok. 00081 00082 Arguments: 00083 msg: pointer to the trigger message. 00084 pSnp: pointer to a SNIPPET structure (see parse_trig.h) 00085 nxtLine:running pointer to current line to be parsed. 00086 00087 Usage: 00088 For the first call, set nxtLine to msg. This tells parseSnippet that 00089 we're starting a new message. It will search for, and parse the event 00090 id. It will also parse the first line, and stuff the elements of the 00091 SNIPPET structure. It will then advance nxtLine to point to the next 00092 line to be parsed and return. Subsequent calls, with the adjusted 00093 value of nxtLine, will result in the next line of the message being 00094 parsed. When the last line has been parsed, a EW_FAILURE will be 00095 returned. 00096 */ 00097 00098 00099 /*********************************************************************** 00100 * parseSnippet() parses snippet parameters from next line of trigger * 00101 * message. Returns EW_FAILURE when nothing left. * 00102 * Does its own error logging via logit. * 00103 ***********************************************************************/ 00104 int parseSnippet( char* msg, SNIPPET* pSnp, char** nxtLine) 00105 { 00106 static char terminators[] = " \t\n"; /* we accept space, newline, and tab as terminators */ 00107 char* nxttok; 00108 char line[LINE_LEN]; 00109 static int startFresh=0; 00110 00111 /* if pointer to next line points to start of message, start clean 00112 *****************************************************************/ 00113 if (*nxtLine == msg) startFresh = 1; 00114 else goto GetNextStation; 00115 00116 /* if event id is negative, search for new EVENT ID 00117 **************************************************/ 00118 00119 00120 GetNextEvent: /* we jump to here when we run off the end of an event (below) */ 00121 00122 /* we're looking for a line with the form shown below: 00123 EVENT DETECTED 19970729 03:01:13.22 UTC EVENT ID: 123ABC AUTHOR: Harry SUBNET: redoubt 00124 * 00125 ************************* Y2K ************************/ 00126 00127 if ( startFresh == 1) 00128 { 00129 /* get next non-zero length line from trigger message */ 00130 while ( getNextLine(nxtLine, line) >= 0 ) /* it returns number of chars in line */ 00131 { 00132 /* skip this line if it doesn't start with EVENT */ 00133 /*** MULTI-THREAD WARNING: strtok is not safe (but it is ubiquitus) ***/ 00134 00135 /* modded by DK 013002 to stop segfault on blank lines 00136 for trigfiles generated by arc2trig on solaris. 00137 The strtok appears to be returning NULL on a blank line, 00138 causing a segfault when evaluated by strcmp, so I separated 00139 the two calls. 00140 ******************************************************/ 00141 if(!(nxttok = strtok( line, terminators))) continue; 00142 if(strcmp( nxttok, "EVENT" ) != 0) continue; 00143 /* end DK 013002 mod 00144 ******************************************************/ 00145 00146 /* on this line, find "ID:" which is followed by the event id string */ 00147 while ( (nxttok = strtok( (char*)NULL, terminators)) != NULL ) /* over tokens on this line */ 00148 { 00149 if ( strcmp( nxttok, "ID:" ) != 0) continue; 00150 nxttok = strtok( (char*)NULL, terminators); /* this had better be the event id */ 00151 if (nxttok == NULL) /* oops - there was nothing after ID: */ 00152 { 00153 logit("et", "parse_trig: Bad syntax in trigger message." 00154 " Cant find EVENT ID in:\n.%s.\n", line); 00155 break; 00156 } 00157 strncpy(pSnp->eventId, nxttok, EVENTID_SIZE); 00158 pSnp->eventId[EVENTID_SIZE-1] = '\0'; /* Ensure null termination */ 00159 00160 /* Now search for author id */ 00161 nxttok = strtok( (char*)NULL, terminators); /* this had better be "AUTHOR:" */ 00162 if ( strcmp( nxttok, "AUTHOR:" ) != 0) 00163 { 00164 logit("et", "parse_trig: Bad syntax in trigger message." 00165 " Cant find AUTHOR:\n.%s.\n", line); 00166 break; 00167 } 00168 nxttok = strtok( (char*)NULL, terminators); /* this had better be author's name */ 00169 strncpy(pSnp->author, nxttok, AUTHOR_FIELD_SIZE); 00170 pSnp->author[AUTHOR_FIELD_SIZE-1] = '\0'; /* Ensure null termination */ 00171 00172 /* Now search for optional subnet */ 00173 nxttok = strtok( (char*)NULL, terminators); /* this might be "SUBNET:" */ 00174 if(nxttok == NULL) 00175 { 00176 pSnp->subnet[0] = '\0'; 00177 startFresh = 0; 00178 goto GotNextEvent; 00179 } 00180 if ( strcmp( nxttok, "SUBNET:" ) != 0) 00181 { 00182 pSnp->subnet[0] = '\0'; 00183 startFresh = 0; /* SUBNET is optional; we're happy with the titile line. Ready for rest of message */ 00184 goto GotNextEvent; 00185 } 00186 nxttok = strtok( (char*)NULL, terminators); /* this had better be subnet name */ 00187 if(nxttok != NULL) strncpy(pSnp->subnet, nxttok, MAX_SUBNET_LEN); /* as per Pete: if there's 00188 nothing there, nxttok will be NULL, which is on Solaris fatal for strncpy */ 00189 pSnp->subnet[MAX_SUBNET_LEN-1] = '\0'; /* Ensure null termination */ 00190 00191 startFresh = 0; /* we're happy with the titile line. Ready for rest of message */ 00192 goto GotNextEvent; 00193 } /* end of loop over tokens in this line */ 00194 } /* end of loop over lines in message */ 00195 return(EW_FAILURE); /* no more lines */ 00196 } /* end of search for event id */ 00197 00198 00199 00200 GotNextEvent: 00201 00202 /* So we have an event id. Now parse and return snippet parameters until a blank line 00203 *************************************************************************************/ 00204 getNextLine(nxtLine, line); /* step over the blank line */ 00205 getNextLine(nxtLine, line); /* step over the column titles line */ 00206 getNextLine(nxtLine, line); /* step over the silly dashes line */ 00207 00208 /* Read the next station line 00209 *****************************/ 00210 GetNextStation: 00211 if( getNextLine(nxtLine, line) <= 0 ) /* this should be a station trigger line */ 00212 { 00213 return(EW_FAILURE); /* no more lines */ 00214 } 00215 if ( ( nxttok=strtok(line, terminators) ) == NULL ) /* first token should be station name */ 00216 { 00217 logit("et","parse_trig: Bad syntax in trigger message:" 00218 "Strange station line - no tokens in: \n.&s.\n",line); 00219 goto GetNextEvent; 00220 } 00221 00222 /* Find SCN names 00223 ****************/ 00224 if (nxttok ==NULL) /* oops - should have been the station name */ 00225 { 00226 logit("et", "parse_trig: Bad syntax in trigger message." 00227 " Cant find statio name in:\n.%s.\n", line); 00228 goto GetNextStation; 00229 } 00230 strncpy( pSnp->sta, nxttok, 7); /* Put away the station name */ 00231 pSnp->sta[6] = '\0'; /* Ensure null termination */ 00232 00233 nxttok = strtok( (char*)NULL, terminators); /* should be the component */ 00234 if (nxttok ==NULL) /* oops - there was nothing after station name */ 00235 { 00236 logit("et", "parse_trig: Bad syntax in trigger message." 00237 " Cant find comp name in:\n.%s.\n", line); 00238 goto GetNextStation; 00239 } 00240 strncpy( pSnp->chan, nxttok, 9 ); /* Put away the component */ 00241 pSnp->chan[8] = '\0'; /* Ensure null termination */ 00242 00243 nxttok = strtok( (char*)NULL, terminators); /* should be the net */ 00244 if (nxttok ==NULL) /* oops - there was nothing after component name */ 00245 { 00246 logit("et", "parse_trig: Bad syntax in trigger message." 00247 " Cant find net name in:\n.%s.\n", line); 00248 goto GetNextStation; 00249 } 00250 strncpy( pSnp->net, nxttok, 9 ); /* put away the net */ 00251 pSnp->net[8] = '\0'; /* Ensure null termination */ 00252 00253 /* And now, find "save:" 00254 ***********************/ 00255 while ( (nxttok=strtok((char*)NULL, terminators) ) != NULL ) /* run down the tokens */ 00256 { 00257 if ( strcmp( nxttok, "save:" ) == 0 ) goto FoundSave; /* looking for 'save:' */ 00258 } 00259 logit("et","parse_trig: Bad syntax in trigger message:" 00260 "Bad station line - no save token found: \n.%s.\n",line); 00261 goto GetNextStation; 00262 FoundSave: 00263 00264 /* now find time strings 00265 ***********************/ 00266 nxttok = strtok( (char*)NULL, terminators); /* should be the save start date */ 00267 if (nxttok ==NULL) /* oops - there was nothing after save: */ 00268 { 00269 logit("et", "parse_trig: Bad syntax in trigger message." 00270 " Cant find save date in:\n.%s.\n", line); 00271 goto GetNextStation; 00272 } 00273 strcpy( pSnp->startYYYYMMDD, nxttok ); /* put away the date string */ 00274 00275 nxttok = strtok( (char*)NULL, terminators); /* sould be the save start time-of-day */ 00276 if (nxttok ==NULL) /* oops - there was nothing after save: */ 00277 { 00278 logit("et", "parse_trig: Bad syntax in trigger message." 00279 " Cant find save time of day in:\n.%s.\n", line); 00280 goto GetNextStation; 00281 } 00282 strcpy( pSnp->startHHMMSS, nxttok ); /* put away the time-of-day string */ 00283 00284 /* Convert start time to double 00285 ******************************/ 00286 if( t_atodbl(pSnp->startYYYYMMDD, pSnp->startHHMMSS, &(pSnp->starttime) ) < 0) 00287 { 00288 logit("et", "parse_trig: Bad syntax in trigger message." 00289 " Dont understand start-time in:\n.%s.\n", line); 00290 goto GetNextStation; 00291 } 00292 if ( pSnp->starttime < BAD_TIME_VALUE ) /* unreasonable time value */ 00293 { 00294 logit("et", "parse_trig: Bad syntax in trigger message." 00295 " Bad start time value in:\n.%s.\n", line); 00296 goto GetNextStation; 00297 } 00298 00299 /* find duration to save 00300 ***********************/ 00301 nxttok = strtok( (char*)NULL, terminators); /* should be the duration */ 00302 if (nxttok ==NULL) /* oops - there was nothing after save: */ 00303 { 00304 logit("et", "parse_trig: Bad syntax in trigger message." 00305 " Cant find duration in:\n.%s.\n", line); 00306 goto GetNextStation; 00307 } 00308 pSnp->duration = atol( nxttok ); 00309 if ( pSnp->duration <= 0 ) 00310 { 00311 logit("et", "parse_trig: Bad syntax in trigger message." 00312 " Bad duration value in:\n.%s.\n", line); 00313 goto GetNextStation; 00314 } 00315 00316 return(EW_SUCCESS); 00317 } 00318 /* ----------------------------------- end of parseSnippet() -------------------------------------- */ 00319 00320 /************************************************************************** 00321 * getNextLine(msg, line) moves the next line from 'msg' into 'line * 00322 * returns the number of characters in the line * 00323 * Returns negative if error. * 00324 **************************************************************************/ 00325 int getNextLine ( char** pNxtLine, char* line) 00326 { 00327 int i; 00328 char* nxtLine; 00329 00330 nxtLine=*pNxtLine; 00331 00332 for (i =0; i< LINE_LEN; i++) 00333 { 00334 line[i] = *nxtLine++; 00335 if ( (int)line[i] == 0 ) 00336 { 00337 return(-1); /* Not good */ 00338 } 00339 if (line[i] == '\n') goto normal; 00340 } 00341 logit("","getNextLine error: line too long \n"); 00342 return(-1); 00343 00344 normal: 00345 line[i+1]=0; 00346 *pNxtLine = nxtLine; 00347 return(i); 00348 00349 } 00350 /* ----------------------------------- end of getNextLine() -------------------------------------- */ 00351 00352 00353 /************************************************************************** 00354 * t_atodbl() takes date and time strings, and converts to double * 00355 * seconds since 1970. Note that the time of day string * 00356 * is of the form "hh:mm:ss.ss" * 00357 * Returns negative if error. * 00358 **************************************************************************/ 00359 00361 #define TIMESTR_LEN 17 /* whole string */ 00362 #define YMD_LEN 8 /* date part: YYYYMMDD */ 00363 #define HOUR_LEN 2 /* hours from HH:MM:SS.SS */ 00364 #define MIN_LEN 2 /* minutes from HH:MM:SS.SS */ 00365 #define SEC_LEN 5 /* seconds from HH:MM:SS.SS */ 00366 00367 int t_atodbl(char* YYYYMMDD, char* HHMMSS, double* starttime) 00368 { 00369 char timestr[TIMESTR_LEN+1]; /* need space for the null-terminator */ 00370 int ret; 00371 int tgtind, srcind; /* indices for copying fields into timestr */ 00372 00373 /************************* Y2K ************************ 00374 * 00375 * All instances of YYMMDD have been changed to YYYYMMDD 00376 * 00377 ************************* Y2K ************************/ 00378 00379 /* we want a string of the form yyyymmddhhmmss.ss */ 00380 /* 01234567890123456 */ 00381 00382 tgtind = 0; 00383 srcind = 0; 00384 00385 /* Copy in the date */ 00386 strcpy(timestr,YYYYMMDD); 00387 00388 /* Append the hour */ 00389 tgtind = tgtind + YMD_LEN; 00390 strncpy(×tr[tgtind], HHMMSS, HOUR_LEN); 00391 00392 /* Append the minute */ 00393 tgtind = tgtind + HOUR_LEN; 00394 srcind = srcind + HOUR_LEN + 1; 00395 strncpy(×tr[tgtind] ,&HHMMSS[srcind], MIN_LEN); 00396 00397 /* Append the seconds */ 00398 tgtind = tgtind + MIN_LEN; 00399 srcind = srcind + MIN_LEN + 1; 00400 strncpy(×tr[tgtind], &HHMMSS[srcind], SEC_LEN); 00401 00402 /* Null terminate the string */ 00403 tgtind = tgtind + SEC_LEN; 00404 timestr[tgtind] = '\0'; 00405 00406 00407 /* convert to double seconds */ 00408 ret = epochsec17(starttime, timestr); 00409 if (ret < 0) 00410 { 00411 logit("t","bad return from epochsec17\n"); 00412 return(-1); 00413 } 00414 return(1); 00415 } 00416 /* ----------------------------------- end of t_atodbl() ----------------------------------------- */