static int load_preset_table(char *pmu_name, int pmu_type, pfm_preset_search_entry_t *here)
{
  char line[LINE_MAX];
  char name[PATH_MAX] = "builtin papi_events_table";
  char *tmp_papi_events_table = NULL;
  char *tmpn;
  FILE *table;
  int line_no = 1, derived = 0, insert = 0, preset = 0;
  int get_presets = 0;   /* only get PRESETS after CPU is identified */
  int found_presets = 0; /* only terminate search after PRESETS are found */
						 /* this allows support for synonyms for CPU names */

#ifdef SHOW_LOADS
  SUBDBG("%p\n",here);
#endif

/*  here[0].preset = PAPI_TOT_CYC;
  here[0].derived = NOT_DERIVED;
  here[1].preset = PAPI_TOT_INS;
  here[1].derived = NOT_DERIVED;
*/
  /* try the environment variable first */
  if ((tmpn = getenv("PAPI_PERFMON_EVENT_FILE")) && (strlen(tmpn) != 0)) {
    sprintf(name,"%s",tmpn);
    table = fopen(name,"r");
  }
  /* if no valid environment variable, look for built-in table */
  else if (papi_events_table) {
	  tmp_papi_events_table = papi_events_table;
	  table = NULL;
  }
  /* if no env var and no built-in, search for default file */
  else {
#ifdef PAPI_DATADIR
    sprintf(name,"%s/%s",PAPI_DATADIR,PAPI_EVENT_FILE);
#else
    sprintf(name,"%s",PAPI_EVENT_FILE);
#endif
	table = open_event_table(name);
  }
  /* if no valid file or built-in table, bail */
  if (table == NULL && tmp_papi_events_table == NULL) {
    PAPIERROR("fopen(%s): %s, please set the PAPI_PERFMON_EVENT_FILE env. variable",name,strerror(errno));
    return(PAPI_ESYS);
  }

  /* at this point either a valid file pointer or built-in table pointer */
  while (get_event_line(line, table, &tmp_papi_events_table)) {
      char *t;
	  int i;
      t = trim_string(strtok(line,","));
      if ((t == NULL) || (strlen(t) == 0))
	continue;
      if (t[0] == '#')
	{
/*	  SUBDBG("Comment found on line %d\n",line_no); */
	  goto nextline;
	}
      else if (strcasecmp(t,"CPU") == 0)
	{
#ifdef SHOW_LOADS
	  SUBDBG("CPU token found on line %d\n",line_no);
#endif
	  if (get_presets != 0 && found_presets != 0)
	    {
#ifdef SHOW_LOADS
	      SUBDBG("Ending preset scanning at line %d of %s.\n",line_no,name);
#endif
	      goto done;
	    }
	  t = trim_string(strtok(NULL,","));
	  if ((t == NULL) || (strlen(t) == 0))
	    {
	      PAPIERROR("Expected name after CPU token at line %d of %s -- ignoring",line_no,name);
	      goto nextline;
	    }
#ifdef SHOW_LOADS
	  SUBDBG("Examining CPU (%s) vs. (%s)\n",t,pmu_name);
#endif
	  if (strcasecmp(t, pmu_name) == 0)
	    {
	      int type;

#ifdef SHOW_LOADS
	      SUBDBG("Found CPU %s at line %d of %s.\n",t,line_no,name);
#endif
	      t = trim_string(strtok(NULL,","));
	      if ((t == NULL) || (strlen(t) == 0))
		{
#ifdef SHOW_LOADS
		  SUBDBG("No additional qualifier found, matching on string.\n");
#endif
		  get_presets = 1;
		}
	      else if ((sscanf(t,"%d",&type) == 1) && (type == pmu_type))
		{
#ifdef SHOW_LOADS
		  SUBDBG("Found CPU %s type %d at line %d of %s.\n",pmu_name,type,line_no,name);
#endif
		  get_presets = 1;
		}
	      else
#ifdef SHOW_LOADS
		SUBDBG("Additional qualifier match failed %d vs %d.\n",pmu_type,type)
#endif
	      ;
	    }
	}
      else if (strcasecmp(t,"PRESET") == 0)
	{
#ifdef SHOW_LOADS
	  SUBDBG("PRESET token found on line %d\n",line_no);
#endif
	  if (get_presets == 0)
	    goto nextline;
	  found_presets = 1;
	  t = trim_string(strtok(NULL,","));
	  if ((t == NULL) || (strlen(t) == 0))
	    {
	      printf("Expected name after PRESET token at line %d of %s -- ignoring",line_no,name);
	      goto nextline;
	    }
#ifdef SHOW_LOADS
	  SUBDBG("Examining preset %s\n",t);
#endif
	  if (find_preset_code(t,&preset) != PAPI_OK)
	    {
	      PAPIERROR("Invalid preset name %s after PRESET token at line %d of %s -- ignoring",t,line_no,name);
	      goto nextline;
	    }
#ifdef SHOW_LOADS
	  SUBDBG("Found 0x%08x for %s\n",preset,t);
#endif
	  t = trim_string(strtok(NULL,","));
	  if ((t == NULL) || (strlen(t) == 0))
	    {
	      PAPIERROR("Expected derived type after PRESET token at line %d of %s -- ignoring",line_no,name);
	      goto nextline;
	    }
#ifdef SHOW_LOADS
	  SUBDBG("Examining derived %s\n",t);
#endif
	  if (_papi_hwi_derived_type(t,&derived) != PAPI_OK)
	    {
	      PAPIERROR("Invalid derived name %s after PRESET token at line %d of %s -- ignoring",t,line_no,name);
	      goto nextline;
	    }
#ifdef SHOW_LOADS
	  SUBDBG("Found %d for %s\n",derived,t);
	  SUBDBG("Adding 0x%x,%d to preset search table.\n",preset,derived);
#endif
	  here[insert].preset = preset;
	  here[insert].derived = derived;
#ifdef SHOW_LOADS
	  SUBDBG("%d Adding 0x%x,%d to preset search table.\n",insert, here[insert].preset,here[insert].derived);
#endif

	  /* Derived support starts here */
	  /* Special handling for postfix */
	  if (derived == DERIVED_POSTFIX) {
	    t = trim_string(strtok(NULL,","));
	    if ((t == NULL) || (strlen(t) == 0)) {
	      PAPIERROR("Expected Operation string after derived type DERIVED_POSTFIX at line %d of %s -- ignoring",line_no,name);
	      goto nextline;
	    }
#ifdef SHOW_LOADS
	    SUBDBG("Saving PostFix operations %s\n",t);
#endif
	    here[insert].operation = strdup(t);
	  }
	  /* All derived terms collected here */
	  i = 0;
	  do {
	    t = trim_string(strtok(NULL,","));
	    if ((t == NULL) || (strlen(t) == 0)) break;
	    if (strcasecmp(t,"NOTE") == 0) break;
	    here[insert].findme[i] = strdup(t);
#ifdef SHOW_LOADS
	    SUBDBG("Adding term (%d) %s to preset event 0x%x.\n",i,t,preset);
#endif
	  } while (++i < MAX_COUNTER_TERMS);
	  /* End of derived support */

	  if (i == 0) {
	    PAPIERROR("Expected PFM event after DERIVED token at line %d of %s -- ignoring",line_no,name);
	    goto nextline;
	  }
	  if (i == MAX_COUNTER_TERMS)
	    t = trim_string(strtok(NULL,","));

	  /* Handle optional NOTEs */
	  if (t && (strcasecmp(t,"NOTE") == 0)) {
#ifdef SHOW_LOADS
	    SUBDBG("%s found on line %d\n",t,line_no);
#endif
	    t = trim_note(strtok(NULL,"")); /* read the rest of the line */
	    if ((t == NULL) || (strlen(t) == 0))
	      PAPIERROR("Expected Note string at line %d of %s\n",line_no,name);
	    else {
	      here[insert].note = strdup(t);
#ifdef SHOW_LOADS
	      SUBDBG("NOTE: --%s-- found on line %d\n",t,line_no);
#endif
	    }
	  }

	  insert++;
	}
      else
	{
	  PAPIERROR("Unrecognized token %s at line %d of %s -- ignoring",t,line_no,name);
	  goto nextline;
	}
    nextline:
      line_no++;
    }
 done:
  if (table)
    fclose(table);
  return(insert);
}
Esempio n. 2
0
int
_papi_load_preset_table( char *pmu_str, int pmu_type, int cidx)
{

  (void) cidx;  /* We'll use this later */

    char pmu_name[PAPI_MIN_STR_LEN];
    char line[LINE_MAX];
    char name[PATH_MAX] = "builtin papi_events_table";
    char *tmp_papi_events_table = NULL;
    char *tmpn;
    FILE *table;
    int ret;
    unsigned int event_idx;
    int invalid_event;
    int line_no = 1, derived = 0, insert = 0, preset = 0;
    int get_presets = 0;   /* only get PRESETS after CPU is identified      */
    int found_presets = 0; /* only terminate search after PRESETS are found */
	                   /* this allows support for synonyms for CPU names*/

    SUBDBG("ENTER\n");

    /* copy the pmu identifier, stripping commas if found */
    tmpn = pmu_name;
    while ( *pmu_str ) {
       if ( *pmu_str != ',' ) *tmpn++ = *pmu_str;
       pmu_str++;
    }
    *tmpn = '\0';

    /* try the environment variable first */
    if ( ( tmpn = getenv( "PAPI_CSV_EVENT_FILE" ) ) && 
         ( strlen( tmpn ) != 0 ) ) {
       sprintf( name, "%s", tmpn );
       table = fopen( name, "r" );
    }
    /* if no valid environment variable, look for built-in table */
    else if ( papi_events_table ) {
       tmp_papi_events_table = papi_events_table;
       table = NULL;
    }
    /* if no env var and no built-in, search for default file */
    else {
#ifdef PAPI_DATADIR
       sprintf( name, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE );
#else
       sprintf( name, "%s", PAPI_EVENT_FILE );
#endif
       table = open_event_table( name );
    }

    /* if no valid file or built-in table, bail */
    if ( table == NULL && tmp_papi_events_table == NULL ) {
       PAPIERROR( "fopen(%s): %s, please set the PAPI_CSV_EVENT_FILE "
                  "env. variable", name, strerror( errno ) );
       return PAPI_ESYS;
    }

    /* at this point either a valid file pointer or built-in table pointer */
    while ( get_event_line( line, table, &tmp_papi_events_table ) ) {
       char *t;
       int i;

       t = trim_string( strtok( line, "," ) );

       /* Skip blank lines */
       if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) continue;

       /* Skip comments */
       if ( t[0] == '#' ) {
	  goto nextline;
       } 

       if ( strcasecmp( t, "CPU" ) == 0 ) {
	  SUBDBG( "CPU token found on line %d\n", line_no );

	  if ( get_presets != 0 && found_presets != 0 ) {
	     SUBDBG( "Ending preset scanning at line %d of %s.\n", 
                     line_no, name );

	     get_presets=0; found_presets=0;
				
	  }
			
	  t = trim_string( strtok( NULL, "," ) );
	  if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) {
	     PAPIERROR( "Expected name after CPU token at line %d of %s "
			"-- ignoring", line_no, name );
	     goto nextline;
	  }

	  SUBDBG( "Examining CPU (%s) vs. (%s)\n", t, pmu_name );

	  if ( strcasecmp( t, pmu_name ) == 0 ) {
	     int type;

	     SUBDBG( "Found CPU %s at line %d of %s.\n", t, line_no, name );

	     t = trim_string( strtok( NULL, "," ) );
	     if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) {
		SUBDBG("No additional qualifier found, matching on string.\n");

		get_presets = 1;
	     } else if ( ( sscanf( t,"%d",&type )==1) && (type==pmu_type) ) {
                SUBDBG( "Found CPU %s type %d at line %d of %s.\n",
			pmu_name, type, line_no, name );
		get_presets = 1;
	     } else {
		SUBDBG( "Additional qualifier match failed %d vs %d.\n",
			pmu_type, type );

	     }
	  }
       } else if ( strcasecmp( t, "PRESET" ) == 0 ) {

          if ( get_presets == 0 ) goto nextline;

	  found_presets = 1;
	  t = trim_string( strtok( NULL, "," ) );

	  if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) {
			       
             PAPIERROR( "Expected name after PRESET token at line %d of %s "
			"-- ignoring", line_no, name );
	     goto nextline;
	  }

	  SUBDBG( "Examining preset %s\n", t );

	  if ( find_preset_code( t, &preset ) != PAPI_OK ) {
	     PAPIERROR ( "Invalid preset name %s after PRESET token "
			 "at line %d of %s -- ignoring",
			 t, line_no, name );
	     goto nextline;
	  }

	  SUBDBG( "Found 0x%08x for %s\n", preset, t );

	  t = trim_string( strtok( NULL, "," ) );
	  if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) {
	     PAPIERROR( "Expected derived type after PRESET token at "
                        "line %d of %s -- ignoring", line_no, name );
	     goto nextline;
	  }

	  if ( _papi_hwi_derived_type( t, &derived ) != PAPI_OK ) {
	     PAPIERROR( "Invalid derived name %s after PRESET token at "
			"line %d of %s -- ignoring",
			t, line_no, name );
	     goto nextline;
	  }

	  /****************************************/
	  /* Have a preset, let's start assigning */
	  /****************************************/

	  SUBDBG( "Found %d for %s\n", derived, t );
	  SUBDBG( "Adding 0x%x,%d to preset search table.\n", 
		  preset, derived );
	  
	  insert=preset&PAPI_PRESET_AND_MASK;

	  /* _papi_hwi_presets[insert].event_code = preset; */
	  _papi_hwi_presets[insert].derived_int = derived;

	  /* Derived support starts here */
	  /* Special handling for postfix */
	  if ( derived == DERIVED_POSTFIX ) {
	     t = trim_string( strtok( NULL, "," ) );
	     if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) {
		PAPIERROR( "Expected Operation string after derived type "
			   "DERIVED_POSTFIX at line %d of %s -- ignoring",
			   line_no, name );
		goto nextline;
	     }

	     SUBDBG( "Saving PostFix operations %s\n", t );

	     _papi_hwi_presets[insert].postfix=strdup(t);
	  }
			
	  /* All derived terms collected here */
	  i = 0;
	  invalid_event=0;
	  do {
	     t = trim_string( strtok( NULL, "," ) );
	     if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) break;
	     if ( strcasecmp( t, "NOTE" ) == 0 ) break;
	     _papi_hwi_presets[insert].name[i]=strdup(t);

	     SUBDBG( "Adding term (%d) %s to preset event 0x%x.\n", 
		     i, t, preset );

	     SUBDBG("Looking up: %s\n",t);

	     ret=_papi_hwd[cidx]->ntv_name_to_code(t, &event_idx);

	     if (ret==PAPI_OK) {
		SUBDBG("Found %x\n",event_idx);
		_papi_hwi_presets[insert].code[i]=event_idx;
	     }
	     else {
		PAPIERROR("papi_preset: Error finding event %s",t);
		invalid_event=1;
	     }

	  } while ( ++i < PAPI_MAX_COUNTER_TERMS );

	  if (invalid_event) {
	    /* We signify a valid preset if count > 0 */
	     _papi_hwi_presets[insert].count=0;
	  } else {
	     _papi_hwi_presets[insert].count=i;
	  }

	  /* End of derived support */

	  if ( i == 0 ) {
	     PAPIERROR( "Expected PFM event after DERIVED token at "
			"line %d of %s -- ignoring", line_no, name );
	     goto nextline;
	  }
	  if ( i == PAPI_MAX_COUNTER_TERMS ) {
	     t = trim_string( strtok( NULL, "," ) );
	  }
			
	  /* Handle optional NOTEs */
	  if ( t && ( strcasecmp( t, "NOTE" ) == 0 ) ) {
	     SUBDBG( "%s found on line %d\n", t, line_no );

	     /* read the rest of the line */
	     t = trim_note( strtok( NULL, "" ) );
	
	     if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) {
		PAPIERROR( "Expected Note string at line %d of %s\n",
			   line_no, name );
	     }
	     else {
	        _papi_hwi_presets[insert].note = strdup( t );
		SUBDBG( "NOTE: --%s-- found on line %d\n", t, line_no );
	     }
	  }

       } else {
	  PAPIERROR( "Unrecognized token %s at line %d of %s -- ignoring", 
		     t, line_no, name );
	  goto nextline;
       }
nextline:
       line_no++;
    }

    if ( table ) {
       fclose( table );
    }
	
    return PAPI_OK;
}
Esempio n. 3
0
static int
papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag) {
	SUBDBG( "ENTER: pmu_str: %s, pmu_type: %d, cidx: %d, preset_flag: %d\n", pmu_str, pmu_type, cidx, preset_flag);

	char pmu_name[PAPI_MIN_STR_LEN];
	char line[LINE_MAX];
	char name[PATH_MAX] = "builtin papi_events_table";
	char *event_file_path=NULL;
	char *event_table_ptr=NULL;
	int event_type_bits = 0;
	char *tmpn;
	char *tok_save_ptr=NULL;
	FILE *event_file = NULL;
	hwi_presets_t *results=NULL;
	int result_size = 0;
	int *event_count = NULL;
	int invalid_event;
	int line_no = 0;  /* count of lines read from event definition input */
	int derived = 0;
	int res_idx = 0;  /* index into results array for where to store next event */
	int preset = 0;
	int get_events = 0; /* only process derived events after CPU type they apply to is identified      */
	int found_events = 0; /* flag to track if event definitions (PRESETS) are found since last CPU declaration */
#ifdef PAPI_DATADIR
		char path[PATH_MAX];
#endif


	if (preset_flag) {
		/* try the environment variable first */
		if ((tmpn = getenv("PAPI_CSV_EVENT_FILE")) && (strlen(tmpn) > 0)) {
			event_file_path = tmpn;
		}
		/* if no valid environment variable, look for built-in table */
		else if (papi_events_table) {
			event_table_ptr = papi_events_table;
		}
		/* if no env var and no built-in, search for default file */
		else {
#ifdef PAPI_DATADIR
			sprintf( path, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE );
			event_file_path = path;
#else
			event_file_path = PAPI_EVENT_FILE;
#endif
		}
		event_type_bits = PAPI_PRESET_MASK;
		results = &_papi_hwi_presets[0];
		result_size = PAPI_MAX_PRESET_EVENTS;
		event_count = &_papi_hwd[cidx]->cmp_info.num_preset_events;
	} else {
		if ((event_file_path = getenv( "PAPI_USER_EVENTS_FILE" )) == NULL ) {
			SUBDBG("EXIT: User event definition file not provided.\n");
			return PAPI_OK;
		}

		event_type_bits = PAPI_UE_MASK;
		results = &user_defined_events[0];
		result_size = PAPI_MAX_USER_EVENTS;
		event_count = &user_defined_events_count;
	}

	// if we have an event file pathname, open it and read event definitions from the file
	if (event_file_path != NULL) {
		if ((event_file = open_event_table(event_file_path)) == NULL) {
			// if file open fails, return an error
			SUBDBG("EXIT: Event file open failed.\n");
			return PAPI_ESYS;
		}
		strncpy(name, event_file_path, sizeof(name)-1);
		name[sizeof(name)-1] = '\0';
	} else if (event_table_ptr == NULL) {
		// if we do not have a path name or table pointer, return an error
		SUBDBG("EXIT: Both event_file_path and event_table_ptr are NULL.\n");
		return PAPI_ESYS;
	}

	/* copy the pmu identifier, stripping commas if found */
	tmpn = pmu_name;
	while (*pmu_str) {
		if (*pmu_str != ',')
			*tmpn++ = *pmu_str;
		pmu_str++;
	}
	*tmpn = '\0';

	/* at this point we have either a valid file pointer or built-in table pointer */
	while (get_event_line(line, event_file, &event_table_ptr)) {
		char *t;
		int i;

		// increment number of lines we have read
		line_no++;

		t = trim_string(strtok_r(line, ",", &tok_save_ptr));

		/* Skip blank lines */
		if ((t == NULL) || (strlen(t) == 0))
			continue;

		/* Skip comments */
		if (t[0] == '#') {
			continue;
		}

		if (strcasecmp(t, "CPU") == 0) {
			if (get_events != 0 && found_events != 0) {
				SUBDBG( "Ending event scanning at line %d of %s.\n", line_no, name);
				get_events = 0;
				found_events = 0;
			}

			t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
			if ((t == NULL) || (strlen(t) == 0)) {
				PAPIERROR("Expected name after CPU token at line %d of %s -- ignoring", line_no, name);
				continue;
			}

			if (strcasecmp(t, pmu_name) == 0) {
				int type;

				SUBDBG( "Process events for PMU %s found at line %d of %s.\n", t, line_no, name);

				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
				if ((t == NULL) || (strlen(t) == 0)) {
					SUBDBG("No additional qualifier found, matching on string.\n");
					get_events = 1;
				} else if ((sscanf(t, "%d", &type) == 1) && (type == pmu_type)) {
					SUBDBG( "Found CPU %s type %d at line %d of %s.\n", pmu_name, type, line_no, name);
					get_events = 1;
				} else {
					SUBDBG( "Additional qualifier match failed %d vs %d.\n", pmu_type, type);
				}
			}
			continue;
		}

		if ((strcasecmp(t, "PRESET") == 0)  || (strcasecmp(t, "EVENT") == 0)) {

			if (get_events == 0)
				continue;

			found_events = 1;
			t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));

			if ((t == NULL) || (strlen(t) == 0)) {
				PAPIERROR("Expected name after PRESET token at line %d of %s -- ignoring", line_no, name);
				continue;
			}

			SUBDBG( "Examining event %s\n", t);

			// see if this event already exists in the results array, if not already known it sets up event in unused entry
			if ((res_idx = find_event_index (results, result_size, t)) < 0) {
				PAPIERROR("No room left for event %s -- ignoring", t);
				continue;
			}

			// add the proper event bits (preset or user defined bits)
			preset = res_idx | event_type_bits;

			SUBDBG( "Use event code: %#x for %s\n", preset, t);

			t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
			if ((t == NULL) || (strlen(t) == 0)) {
				// got an error, make this entry unused
				papi_free (results[res_idx].symbol);
				results[res_idx].symbol = NULL;
				PAPIERROR("Expected derived type after PRESET token at line %d of %s -- ignoring", line_no, name);
				continue;
			}

			if (_papi_hwi_derived_type(t, &derived) != PAPI_OK) {
				// got an error, make this entry unused
				papi_free (results[res_idx].symbol);
				results[res_idx].symbol = NULL;
				PAPIERROR("Invalid derived name %s after PRESET token at line %d of %s -- ignoring", t, line_no, name);
				continue;
			}

			/****************************************/
			/* Have an event, let's start assigning */
			/****************************************/

			SUBDBG( "Adding event: %s, code: %#x, derived: %d results[%d]: %p.\n", t, preset, derived, res_idx, &results[res_idx]);

			/* results[res_idx].event_code = preset; */
			results[res_idx].derived_int = derived;

			/* Derived support starts here */
			/* Special handling for postfix and infix */
			if ((derived == DERIVED_POSTFIX)  || (derived == DERIVED_INFIX)) {
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
				if ((t == NULL) || (strlen(t) == 0)) {
					// got an error, make this entry unused
					papi_free (results[res_idx].symbol);
					results[res_idx].symbol = NULL;
					PAPIERROR("Expected Operation string after derived type DERIVED_POSTFIX or DERIVED_INFIX at line %d of %s -- ignoring", line_no, name);
					continue;
				}

				// if it is an algebraic formula, we need to convert it to postfix
				if (derived == DERIVED_INFIX) {
					SUBDBG( "Converting InFix operations %s\n", t);
					t = infix_to_postfix( t );
					results[res_idx].derived_int = DERIVED_POSTFIX;
				}

				SUBDBG( "Saving PostFix operations %s\n", t);
				results[res_idx].postfix = papi_strdup(t);
			}

			/* All derived terms collected here */
			i = 0;
			invalid_event = 0;
			results[res_idx].count = 0;
			do {
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
				if ((t == NULL) || (strlen(t) == 0))
					break;
				if (strcasecmp(t, "NOTE") == 0)
					break;
				if (strcasecmp(t, "LDESC") == 0)
					break;
				if (strcasecmp(t, "SDESC") == 0)
					break;

				SUBDBG( "Adding term (%d) %s to derived event %#x, current native event count: %d.\n", i, t, preset, results[res_idx].count);

				// show that we do not have an event code yet (the component may create one and update this info)
				// this also clears any values left over from a previous call
				_papi_hwi_set_papi_event_code(-1, -1);

				// make sure that this term in the derived event is a valid event name
				// this call replaces preset and user event names with the equivalent native events in our results table
				// it also updates formulas for derived events so that they refer to the correct native event index
				if (is_event(t, results[res_idx].derived_int, &results[res_idx], i) == 0) {
					invalid_event = 1;
					PAPIERROR("Error finding event %s, it is used in derived event %s", t, results[res_idx].symbol);
					break;
				}

				i++;
			} while (results[res_idx].count < PAPI_EVENTS_IN_DERIVED_EVENT);

			/* preset code list must be PAPI_NULL terminated */
			if (i < PAPI_EVENTS_IN_DERIVED_EVENT) {
				results[res_idx].code[results[res_idx].count] = PAPI_NULL;
			}

			if (invalid_event) {
				// got an error, make this entry unused
				papi_free (results[res_idx].symbol);
				results[res_idx].symbol = NULL;
				continue;
			}

			/* End of derived support */

			// if we did not find any terms to base this derived event on, report error
			if (i == 0) {
				// got an error, make this entry unused
				papi_free (results[res_idx].symbol);
				results[res_idx].symbol = NULL;
				PAPIERROR("Expected PFM event after DERIVED token at line %d of %s -- ignoring", line_no, name);
				continue;
			}

			if (i == PAPI_EVENTS_IN_DERIVED_EVENT) {
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
			}

			// if something was provided following the list of events to be used by the operation, process it
			if ( t!= NULL  && strlen(t) > 0 ) {
				do {
					// save the field name
					char *fptr = papi_strdup(t);

					// get the value to be used with this field
					t = trim_note(strtok_r(NULL, ",", &tok_save_ptr));
					if ( t== NULL  || strlen(t) == 0 ) {
						papi_free(fptr);
						break;
					}

					// Handle optional short descriptions, long descriptions and notes
					if (strcasecmp(fptr, "SDESC") == 0) {
						results[res_idx].short_descr = papi_strdup(t);
					}
					if (strcasecmp(fptr, "LDESC") == 0) {
						results[res_idx].long_descr = papi_strdup(t);
					}
					if (strcasecmp(fptr, "NOTE") == 0) {
						results[res_idx].note = papi_strdup(t);
					}

					SUBDBG( "Found %s (%s) on line %d\n", fptr, t, line_no);
					papi_free (fptr);

					// look for another field name
					t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
					if ( t== NULL  || strlen(t) == 0 ) {
						break;
					}
				} while (t != NULL);
			}
			(*event_count)++;
			continue;
		}

		PAPIERROR("Unrecognized token %s at line %d of %s -- ignoring", t, line_no, name);
	}

	if (event_file) {
		fclose(event_file);
	}

	SUBDBG("EXIT: Done processing derived event file.\n");
	return PAPI_OK;
}