int RFG_Filter_readDefFile( RFG_Filter* filter, int rank, uint8_t* r_isRankOff ) { char* line; uint32_t lineno = 0; size_t pos = 0; uint8_t parse_err = 0; uint8_t l_is_rank_off = 0; uint8_t includes_current_rank = 1; if( !filter || !filter->file_name ) return 0; /* reset filter rules */ if( !RFG_Filter_reset( filter ) ) return 0; /* get filter file content, if necessary */ if( !filter->file_content ) { if( !get_file_content( filter ) ) { fprintf( stderr, "RFG_Filter_readDefFile(): Error: Could not read file '%s'\n", filter->file_name ); return 0; } } /* allocate memory for line */ line = ( char* )malloc( MAX_LINE_LEN * sizeof( char ) ); if( !line ) return 0; /* read lines */ while( !l_is_rank_off && !parse_err && get_file_content_line( filter, line, MAX_LINE_LEN, &pos ) ) { char* p; char* q; /* increment line number */ lineno++; /* remove newline */ if( strlen(line) > 0 && line[strlen(line)-1] == '\n' ) line[strlen(line)-1] = '\0'; /* remove leading and trailing spaces from line */ vt_strtrim( line ); /* cut possible comment from line */ p = strchr( line, '#' ); if( p ) *p = '\0'; /* continue if line is empty */ if( strlen( line ) == 0 ) continue; if( line[0] == '@' ) { int a = -1; int b = -1; uint8_t is_rank_off_rule = 0; /* check whether selected ranks shall be disabled */ if( ( p = strstr( line, "--" ) ) ) { /* cut "-- OFF" from line */ *p = '\0'; p += 2; while( *p == ' ' || *p == '\t' ) p++; q = p; while( *q != '\0' ) { *q = tolower( *q ); q++; } if( strcmp( p, "off" ) == 0 ) { is_rank_off_rule = 1; } else { parse_err = 1; break; } } /* no specific rank given? */ if( rank == -1 ) { /* continue reading, if selected ranks shall be disabled (non-rank-specific filter rules can follow) */ if( is_rank_off_rule ) continue; /* otherwise, stop reading (all the following filter rules are rank-specific which will be read later) */ else break; } /* parse rank selection If current rank is included, then read the following filter rules. Otherwise, jump to next @ clause. */ p = line + 1; includes_current_rank = 0; while( 1 ) { while( *p == ' ' || *p == '\t' ) p++; if( *p >= '0' && *p <= '9' ) { errno = 0; a = strtol( p, &q, 10 ); p = q; if( errno != 0 ) { parse_err = 1; break; } } else if( *p == '-' && *(p+1) != '\0' && a != -1 ) { p++; errno = 0; b = strtol( p, &q, 10 ); p = q; if( errno != 0 ) { parse_err = 1; break; } } else if( (*p == ';' || *p == ',') && a != -1 ) { p++; if( a == rank || (a < rank && rank <= b ) ) { includes_current_rank = 1; if( is_rank_off_rule ) { l_is_rank_off = 1; /* deactivate this rank completely */ break; } } else if( is_rank_off_rule ) { includes_current_rank = 1; } a = b = -1; } else if( *p == '\0' && a != -1 ) { if( a == rank || (a < rank && rank <= b ) ) { includes_current_rank = 1; if( is_rank_off_rule ) l_is_rank_off = 1; /* deactivate this rank completely */ } else if( is_rank_off_rule ) { includes_current_rank = 1; } break; } else { parse_err = 1; break; } } } else { int32_t climit; uint32_t sbounds[2] = { 1, (uint32_t)-1 }; uint8_t flags = 0; uint8_t is_cpath_rule = 0; uint32_t num_cpath_regions = 0; char* cpath_regions[RFG_FILTER_MAX_CPATH_SIZE]; /* search for '--' e.g. "func1;func2;func3 -- 1000 S:5-10 R" p */ if( !( p = strstr( line, "--" ) ) ) { parse_err = 1; break; } /* cut call limit, stack level bounds, and flags from line e.g. "func1;func2;func3 -- 1000 S:5-10 R" => "func1;func2;func3" */ *p = '\0'; /* split remaining line at ' ' to get call limit, stack level bounds, and flags */ if( !( p = strtok( p+2, " " ) ) ) { parse_err = 1; break; } /* parse call limit */ { long l_climit; l_climit = strtol( p, &q, 10 ); if( p == q || l_climit == LONG_MIN || l_climit == LONG_MAX || l_climit < -1 ) { parse_err = 1; break; } climit = (int32_t)l_climit; } /* parse stack level bounds and flags */ while( !parse_err && ( p = strtok( NULL, " " ) ) ) { /* stack level bounds */ if( strlen( p ) > 2 && tolower( *p ) == 's' && *(p+1) == ':' ) { long l_bounds[2] = { 1 }; p = p+2; /* parse maximum (or minimum) stack level bound */ l_bounds[1] = strtol( p, &q, 10 ); if( p == q || l_bounds[1] == LONG_MIN || l_bounds[1] == LONG_MAX || l_bounds[1] < 1 ) { parse_err = 1; break; } p = q; /* minimum stack level bound specified? */ if( *p == '-' ) { p++; l_bounds[0] = l_bounds[1]; /* parse maximum stack level bound */ l_bounds[1] = strtol( p, &q, 10 ); if( p == q || l_bounds[1] == LONG_MIN || l_bounds[1] == LONG_MAX || l_bounds[1] < l_bounds[0] ) { parse_err = 1; break; } p = q; } if( strlen( p ) > 1 || ( *p != '\0' && *p != '\t' ) ) { parse_err = 1; break; } sbounds[0] = (uint32_t)l_bounds[0]; sbounds[1] = (uint32_t)l_bounds[1]; } /* group flag */ else if( strlen( p ) == 1 && tolower( *p ) == 'g' ) { flags |= RFG_FILTER_FLAG_GROUP; } /* recursiveness flag */ else if( strlen( p ) == 1 && tolower( *p ) == 'r' ) { flags |= RFG_FILTER_FLAG_RECURSIVE; } /* call-path flag */ else if( strlen( p ) == 1 && tolower( *p ) == 'c' ) { is_cpath_rule = 1; } else { parse_err = 1; break; } } /* call-path flag must not be mixed with other flags (except recursiveness) or stack level bounds */ parse_err = ( parse_err || ( is_cpath_rule && ( ( flags != 0 && flags != RFG_FILTER_FLAG_RECURSIVE ) || sbounds[0] != 1 || sbounds[1] != (uint32_t)-1 ) ) ); if( parse_err ) break; /* split line at ';' to get pattern/region names */ p = strtok( line, ";" ); do { char* pattern_or_rname; if( !p ) { parse_err = 1; break; } pattern_or_rname = strdup( p ); vt_strtrim( pattern_or_rname ); if( *pattern_or_rname != '\0' && includes_current_rank ) { if( is_cpath_rule ) { /* max. number of regions in a call path exceeded? */ if( num_cpath_regions + 1 > RFG_FILTER_MAX_CPATH_SIZE ) { free( pattern_or_rname ); parse_err = 1; break; } /* add region to array of call-path region names */ cpath_regions[num_cpath_regions++] = pattern_or_rname; } else { /* add region filter rules */ RFG_Filter_addRegionRules( filter, pattern_or_rname, climit, sbounds, flags ); free( pattern_or_rname ); } } else { free( pattern_or_rname ); } } while( ( p = strtok( 0, ";" ) ) ); if( is_cpath_rule ) { if( !parse_err ) { /* add call-path filter rules */ RFG_Filter_addCallPathRules( filter, num_cpath_regions, (const char**)cpath_regions, climit, NULL, NULL ); } /* free array of call-path region names */ do free( cpath_regions[--num_cpath_regions] ); while( num_cpath_regions > 0 ); } } } free( line ); if( parse_err ) { fprintf( stderr, "%s:%u: Could not be parsed\n", filter->file_name, lineno ); return 0; } if( r_isRankOff ) *r_isRankOff = l_is_rank_off; return 1; }
int RFG_Groups_readDefFile( RFG_Groups* groups ) { FILE* f; char* line; uint32_t lineno = 0; uint8_t parse_err = 0; if( !groups ) return 0; if( !groups->file_name ) return 1; /* open group definition file */ f = fopen( groups->file_name, "r" ); if( !f ) { fprintf( stderr, "RFG_Groups_readDefFile(): Error: Could not open file '%s'\n", groups->file_name ); return 0; } line = ( char* )malloc( MAX_LINE_LEN * sizeof( char ) ); if( !line ) { fclose( f ); return 0; } /* read lines */ while( !parse_err && fgets( line, MAX_LINE_LEN, f ) ) { char* group; char* p; /* increment line number */ lineno++; /* remove newline */ if( strlen( line ) > 0 && line[strlen(line)-1] == '\n' ) line[strlen(line)-1] = '\0'; /* remove leading and trailing spaces from line */ vt_strtrim( line ); /* cut possible comment from line */ p = strchr( line, '#' ); if( p ) *p = '\0'; /* continue if line is empty */ if( strlen( line ) == 0 ) continue; /* search for '=' e.g. "GROUP=func1;func2;func3" p */ p = strchr( line, '=' ); if( !p ) { parse_err = 1; break; } /* cut group name from line e.g. "GROUP=func1;func2;func3" => "GROUP" */ *p = '\0'; group = strdup( line ); vt_strtrim( group ); /* split remaining line at ';' to get pattern */ p = strtok( p+1, ";" ); do { char* pattern; if( !p ) { parse_err = 1; break; } pattern = strdup( p ); vt_strtrim( pattern ); /* add group assignment */ if( strlen( pattern ) > 0 ) RFG_Groups_addAssign( groups, group, pattern ); free( pattern ); } while( ( p = strtok( 0, ";" ) ) ); free( group ); } if( parse_err ) { fprintf( stderr, "%s:%u: Could not be parsed\n", groups->file_name, lineno ); } free( line ); fclose( f ); return parse_err ? 0 : 1; }