Blame src/papi_preset.c

Packit 577717
/* 
Packit 577717
* File:    papi_preset.c
Packit 577717
* Author:  Haihang You
Packit 577717
*          you@cs.utk.edu
Packit 577717
* Mods:    Brian Sheely
Packit 577717
*          bsheely@eecs.utk.edu
Packit 577717
* Author:  Vince Weaver
Packit 577717
*          vweaver1 @ eecs.utk.edu
Packit 577717
*          Merge of the libpfm3/libpfm4/pmapi-ppc64_events preset code
Packit 577717
*/
Packit 577717
Packit 577717
Packit 577717
#include <string.h>
Packit 577717
#include <ctype.h>
Packit 577717
#include <errno.h>
Packit 577717
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_vector.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
#include "papi_preset.h"
Packit 577717
#include "extras.h"
Packit 577717
Packit 577717
Packit 577717
// A place to put user defined events
Packit 577717
extern hwi_presets_t user_defined_events[];
Packit 577717
extern int user_defined_events_count;
Packit 577717
Packit 577717
static int papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag);
Packit 577717
Packit 577717
Packit 577717
/* This routine copies values from a dense 'findem' array of events
Packit 577717
   into the sparse global _papi_hwi_presets array, which is assumed
Packit 577717
   to be empty at initialization.
Packit 577717
Packit 577717
   Multiple dense arrays can be copied into the sparse array, allowing
Packit 577717
   event overloading at run-time, or allowing a baseline table to be
Packit 577717
   augmented by a model specific table at init time.
Packit 577717
Packit 577717
   This method supports adding new events; overriding existing events, or
Packit 577717
   deleting deprecated events.
Packit 577717
*/
Packit 577717
int
Packit 577717
_papi_hwi_setup_all_presets( hwi_search_t * findem, int cidx )
Packit 577717
{
Packit 577717
    int i, pnum, did_something = 0;
Packit 577717
    unsigned int preset_index, j, k;
Packit 577717
Packit 577717
    /* dense array of events is terminated with a 0 preset.
Packit 577717
       don't do anything if NULL pointer. This allows just notes to be loaded.
Packit 577717
       It's also good defensive programming.
Packit 577717
     */
Packit 577717
    if ( findem != NULL ) {
Packit 577717
       for ( pnum = 0; ( pnum < PAPI_MAX_PRESET_EVENTS ) &&
Packit 577717
			  ( findem[pnum].event_code != 0 ); pnum++ ) {
Packit 577717
	   /* find the index for the event to be initialized */
Packit 577717
	   preset_index = ( findem[pnum].event_code & PAPI_PRESET_AND_MASK );
Packit 577717
	   /* count and set the number of native terms in this event, 
Packit 577717
              these items are contiguous.
Packit 577717
Packit 577717
	      PAPI_EVENTS_IN_DERIVED_EVENT is arbitrarily defined in the high 
Packit 577717
              level to be a reasonable number of terms to use in a derived 
Packit 577717
              event linear expression, currently 8.
Packit 577717
Packit 577717
	      This wastes space for components with less than 8 counters, 
Packit 577717
              but keeps the framework independent of the components.
Packit 577717
Packit 577717
	      The 'native' field below is an arbitrary opaque identifier 
Packit 577717
              that points to information on an actual native event. 
Packit 577717
              It is not an event code itself (whatever that might mean).
Packit 577717
	      By definition, this value can never == PAPI_NULL.
Packit 577717
	      - dkt */
Packit 577717
Packit 577717
	   INTDBG( "Counting number of terms for preset index %d, "
Packit 577717
                   "search map index %d.\n", preset_index, pnum );
Packit 577717
	   i = 0;
Packit 577717
	   j = 0;
Packit 577717
	   while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
Packit 577717
	      if ( findem[pnum].native[i] != PAPI_NULL ) {
Packit 577717
		 j++;
Packit 577717
	      }
Packit 577717
	      else if ( j ) {
Packit 577717
		 break;
Packit 577717
	      }
Packit 577717
	      i++;
Packit 577717
	   }
Packit 577717
Packit 577717
	   INTDBG( "This preset has %d terms.\n", j );
Packit 577717
	   _papi_hwi_presets[preset_index].count = j;
Packit 577717
 
Packit 577717
           _papi_hwi_presets[preset_index].derived_int = findem[pnum].derived;
Packit 577717
	   for(k=0;k
Packit 577717
              _papi_hwi_presets[preset_index].code[k] =
Packit 577717
                     findem[pnum].native[k];
Packit 577717
	   }
Packit 577717
	   /* preset code list must be PAPI_NULL terminated */
Packit 577717
	   if (k
Packit 577717
              _papi_hwi_presets[preset_index].code[k] = PAPI_NULL;
Packit 577717
	   }
Packit 577717
Packit 577717
	   _papi_hwi_presets[preset_index].postfix=
Packit 577717
	                                   papi_strdup(findem[pnum].operation);
Packit 577717
Packit 577717
	   did_something++;
Packit 577717
       }
Packit 577717
    }
Packit 577717
Packit 577717
    _papi_hwd[cidx]->cmp_info.num_preset_events += did_something;
Packit 577717
Packit 577717
    return ( did_something ? PAPI_OK : PAPI_ENOEVNT );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_papi_hwi_cleanup_all_presets( void )
Packit 577717
{
Packit 577717
        int preset_index,cidx;
Packit 577717
	unsigned int j;
Packit 577717
Packit 577717
	for ( preset_index = 0; preset_index < PAPI_MAX_PRESET_EVENTS;
Packit 577717
		  preset_index++ ) {
Packit 577717
	    if ( _papi_hwi_presets[preset_index].postfix != NULL ) {
Packit 577717
	       papi_free( _papi_hwi_presets[preset_index].postfix );
Packit 577717
	       _papi_hwi_presets[preset_index].postfix = NULL;
Packit 577717
	    }
Packit 577717
	    if ( _papi_hwi_presets[preset_index].note != NULL ) {
Packit 577717
	       papi_free( _papi_hwi_presets[preset_index].note );
Packit 577717
	       _papi_hwi_presets[preset_index].note = NULL;
Packit 577717
	    }
Packit 577717
	    for(j=0; j<_papi_hwi_presets[preset_index].count;j++) {
Packit 577717
	       papi_free(_papi_hwi_presets[preset_index].name[j]);
Packit 577717
	    }
Packit 577717
	}
Packit 577717
Packit 577717
	for(cidx=0;cidx
Packit 577717
	   _papi_hwd[cidx]->cmp_info.num_preset_events = 0;
Packit 577717
	}
Packit 577717
Packit 577717
#if defined(ITANIUM2) || defined(ITANIUM3)
Packit 577717
	/* NOTE: This memory may need to be freed for BG/P builds as well */
Packit 577717
	if ( preset_search_map != NULL ) {
Packit 577717
		papi_free( preset_search_map );
Packit 577717
		preset_search_map = NULL;
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
#define PAPI_EVENT_FILE "papi_events.csv"
Packit 577717
Packit 577717
Packit 577717
/*  Trims blank space from both ends of a string (in place).
Packit 577717
    Returns pointer to new start address */
Packit 577717
static inline char *
Packit 577717
trim_string( char *in )
Packit 577717
{
Packit 577717
	int len, i = 0;
Packit 577717
	char *start = in;
Packit 577717
Packit 577717
	if ( in == NULL )
Packit 577717
		return ( in );
Packit 577717
	len = ( int ) strlen( in );
Packit 577717
	if ( len == 0 )
Packit 577717
		return ( in );
Packit 577717
Packit 577717
	/* Trim left */
Packit 577717
	while ( i < len ) {
Packit 577717
		if ( isblank( in[i] ) ) {
Packit 577717
			in[i] = '\0';
Packit 577717
			start++;
Packit 577717
		} else
Packit 577717
			break;
Packit 577717
		i++;
Packit 577717
	}
Packit 577717
Packit 577717
	/* Trim right */
Packit 577717
	i = ( int ) strlen( start ) - 1;
Packit 577717
	while ( i >= 0 ) {
Packit 577717
		if ( isblank( start[i] ) )
Packit 577717
			start[i] = '\0';
Packit 577717
		else
Packit 577717
			break;
Packit 577717
		i--;
Packit 577717
	}
Packit 577717
	return ( start );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*  Calls trim_string to remove blank space;
Packit 577717
    Removes paired punctuation delimiters from
Packit 577717
    beginning and end of string. If the same punctuation
Packit 577717
    appears first and last (quotes, slashes) they are trimmed;
Packit 577717
    Also checks for the following pairs: () <> {} [] */
Packit 577717
static inline char *
Packit 577717
trim_note( char *in )
Packit 577717
{
Packit 577717
	int len;
Packit 577717
	char *note, start, end;
Packit 577717
Packit 577717
	note = trim_string( in );
Packit 577717
	if ( note != NULL ) {
Packit 577717
                len = ( int ) strlen( note );
Packit 577717
		if ( len > 0 ) {
Packit 577717
			if ( ispunct( *note ) ) {
Packit 577717
				start = *note;
Packit 577717
				end = note[len - 1];
Packit 577717
				if ( ( start == end )
Packit 577717
					 || ( ( start == '(' ) && ( end == ')' ) )
Packit 577717
					 || ( ( start == '<' ) && ( end == '>' ) )
Packit 577717
					 || ( ( start == '{' ) && ( end == '}' ) )
Packit 577717
					 || ( ( start == '[' ) && ( end == ']' ) ) ) {
Packit 577717
					note[len - 1] = '\0';
Packit 577717
					*note = '\0';
Packit 577717
					note++;
Packit 577717
				}
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
	return note;
Packit 577717
}
Packit 577717
Packit 577717
static inline int
Packit 577717
find_event_index(hwi_presets_t *array, int size, char *tmp) {
Packit 577717
	SUBDBG("ENTER: array: %p, size: %d, tmp: %s\n", array, size, tmp);
Packit 577717
	int i;
Packit 577717
	for (i = 0; i < size; i++) {
Packit 577717
		if (array[i].symbol == NULL) {
Packit 577717
			array[i].symbol = papi_strdup(tmp);
Packit 577717
			SUBDBG("EXIT: i: %d\n", i);
Packit 577717
			return i;
Packit 577717
		}
Packit 577717
		if (strcasecmp(tmp, array[i].symbol) == 0) {
Packit 577717
			SUBDBG("EXIT: i: %d\n", i);
Packit 577717
			return i;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	SUBDBG("EXIT: PAPI_EINVAL\n");
Packit 577717
	return PAPI_EINVAL;
Packit 577717
}
Packit 577717
Packit 577717
/* Look for an event file 'name' in a couple common locations.
Packit 577717
   Return a valid file handle if found */
Packit 577717
static FILE *
Packit 577717
open_event_table( char *name )
Packit 577717
{
Packit 577717
	FILE *table;
Packit 577717
Packit 577717
	SUBDBG( "Opening %s\n", name );
Packit 577717
	table = fopen( name, "r" );
Packit 577717
	if ( table == NULL ) {
Packit 577717
		SUBDBG( "Open %s failed, trying ./%s.\n", 
Packit 577717
			name, PAPI_EVENT_FILE );
Packit 577717
		sprintf( name, "%s", PAPI_EVENT_FILE );
Packit 577717
		table = fopen( name, "r" );
Packit 577717
	}
Packit 577717
	if ( table == NULL ) {
Packit 577717
		SUBDBG( "Open ./%s failed, trying ../%s.\n", 
Packit 577717
			name, PAPI_EVENT_FILE );
Packit 577717
		sprintf( name, "../%s", PAPI_EVENT_FILE );
Packit 577717
		table = fopen( name, "r" );
Packit 577717
	}
Packit 577717
	if ( table ) {
Packit 577717
		SUBDBG( "Open %s succeeded.\n", name );
Packit 577717
	}
Packit 577717
	return table;
Packit 577717
}
Packit 577717
Packit 577717
/* parse a single line from either a file or character table
Packit 577717
   Strip trailing <cr>; return 0 if empty */
Packit 577717
static int
Packit 577717
get_event_line( char *line, FILE * table, char **tmp_perfmon_events_table )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	if ( table ) {
Packit 577717
	    if ( fgets( line, LINE_MAX, table ) == NULL)
Packit 577717
		return 0;
Packit 577717
Packit 577717
	    i = ( int ) strlen( line );
Packit 577717
	    if (i == 0)
Packit 577717
		return 0;
Packit 577717
	    if ( line[i-1] == '\n' )
Packit 577717
		line[i-1] = '\0';
Packit 577717
	    return 1;
Packit 577717
	} else {
Packit 577717
		for ( i = 0;
Packit 577717
			  **tmp_perfmon_events_table && **tmp_perfmon_events_table != '\n';
Packit 577717
			  i++, ( *tmp_perfmon_events_table )++ )
Packit 577717
			line[i] = **tmp_perfmon_events_table;
Packit 577717
		if (i == 0)
Packit 577717
		    return 0;
Packit 577717
		if ( **tmp_perfmon_events_table && **tmp_perfmon_events_table == '\n' ) {
Packit 577717
		    ( *tmp_perfmon_events_table )++;
Packit 577717
		}
Packit 577717
		line[i] = '\0';
Packit 577717
		return 1;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
// update tokens in formula referring to index "old_index" with tokens referring to index "new_index".
Packit 577717
static void
Packit 577717
update_ops_string(char **formula, int old_index, int new_index) {
Packit 577717
	INTDBG("ENTER:   *formula: %s, old_index: %d, new_index: %d\n", *formula?*formula:"NULL", old_index, new_index);
Packit 577717
Packit 577717
	int cur_index;
Packit 577717
	char *newFormula;
Packit 577717
	char *subtoken;
Packit 577717
	char *tok_save_ptr=NULL;
Packit 577717
Packit 577717
	// if formula is null just return
Packit 577717
	if (*formula == NULL) {
Packit 577717
		INTDBG("EXIT: Null pointer to formula passed in\n");
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
	// get some space for the new formula we are going to create
Packit 577717
	newFormula = papi_calloc(strlen(*formula) + 20, 1);
Packit 577717
Packit 577717
	// replace the specified "replace" tokens in the new original formula with the new insertion formula
Packit 577717
	newFormula[0] = '\0';
Packit 577717
	subtoken = strtok_r(*formula, "|", &tok_save_ptr);
Packit 577717
	while ( subtoken != NULL) {
Packit 577717
//		INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
Packit 577717
		char work[10];
Packit 577717
		// if this is the token we want to replace with the new token index, do it now
Packit 577717
		if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
Packit 577717
			cur_index = atoi(&subtoken[1]);
Packit 577717
			// if matches old index, use the new one
Packit 577717
			if (cur_index == old_index) {
Packit 577717
				sprintf (work, "N%d", new_index);
Packit 577717
				strcat (newFormula, work);
Packit 577717
			} else if (cur_index > old_index) {
Packit 577717
				// current token greater than old index, make it one less than what it was
Packit 577717
				sprintf (work, "N%d", cur_index-1);
Packit 577717
				strcat (newFormula, work);
Packit 577717
			} else {
Packit 577717
				// current token less than old index, copy this part of the original formula into the new formula
Packit 577717
				strcat(newFormula, subtoken);
Packit 577717
			}
Packit 577717
		} else {
Packit 577717
			// copy this part of the original formula into the new formula
Packit 577717
			strcat(newFormula, subtoken);
Packit 577717
		}
Packit 577717
		strcat (newFormula, "|");
Packit 577717
		subtoken = strtok_r(NULL, "|", &tok_save_ptr);
Packit 577717
	}
Packit 577717
	papi_free (*formula);
Packit 577717
	*formula = newFormula;
Packit 577717
Packit 577717
	INTDBG("EXIT: newFormula: %s\n", newFormula);
Packit 577717
	return;
Packit 577717
}
Packit 577717
Packit 577717
//
Packit 577717
// Handle creating a new derived event of type DERIVED_ADD.  This may create a new formula
Packit 577717
// which can be used to compute the results of the new event from the events it depends on.
Packit 577717
// This code is also responsible for making sure that all the needed native events are in the
Packit 577717
// new events native event list and that the formula's referenced to this array are correct.
Packit 577717
//
Packit 577717
static void
Packit 577717
ops_string_append(hwi_presets_t *results, hwi_presets_t *depends_on, int addition) {
Packit 577717
	INTDBG("ENTER: results: %p, depends_on: %p, addition %d\n", results, depends_on, addition);
Packit 577717
Packit 577717
	int i;
Packit 577717
	int second_event = 0;
Packit 577717
	char newFormula[PAPI_MIN_STR_LEN] = "";
Packit 577717
	char work[20];
Packit 577717
Packit 577717
	// if our results already have a formula, start with what was collected so far
Packit 577717
	// this should only happens when processing the second event of a new derived add
Packit 577717
	if (results->postfix != NULL) {
Packit 577717
		INTDBG("Event %s has existing formula %s\n", results->symbol, results->postfix);
Packit 577717
		// get the existing formula
Packit 577717
		strncat(newFormula, results->postfix, sizeof(newFormula)-1);
Packit 577717
		newFormula[sizeof(newFormula)-1] = '\0';
Packit 577717
		second_event = 1;
Packit 577717
	}
Packit 577717
Packit 577717
	// process based on what kind of event the one we depend on is
Packit 577717
	switch (depends_on->derived_int) {
Packit 577717
		case DERIVED_POSTFIX: {
Packit 577717
			// the event we depend on has a formula, append it our new events formula
Packit 577717
Packit 577717
			// if event we depend on does not have a formula, report error
Packit 577717
			if (depends_on->postfix == NULL) {
Packit 577717
				INTDBG("Event %s is of type DERIVED_POSTFIX but is missing operation string\n", depends_on->symbol);
Packit 577717
				return;
Packit 577717
			}
Packit 577717
Packit 577717
			// may need to renumber the native event index values in the depends on event formula before putting it into new derived event
Packit 577717
			char *temp = papi_strdup(depends_on->postfix);
Packit 577717
Packit 577717
			// If this is not the first event of the new derived add, need to adjust native event index values in formula.
Packit 577717
			// At this time we assume that all the native events in the second events formula are unique for the new event
Packit 577717
			// and just bump the indexes by the number of events already known to the new event.  Later when we add the events
Packit 577717
			// to the native event list for this new derived event, we will check to see if the native events are already known
Packit 577717
			// to the new derived event and if so adjust the indexes again.
Packit 577717
			if (second_event) {
Packit 577717
				for ( i=depends_on->count-1 ; i>=0 ; i--) {
Packit 577717
					update_ops_string(&temp, i, results->count + i);
Packit 577717
				}
Packit 577717
			}
Packit 577717
Packit 577717
			// append the existing formula from the event we depend on (but get rid of last '|' character)
Packit 577717
			strncat(newFormula, temp, sizeof(newFormula)-1);
Packit 577717
			newFormula[sizeof(newFormula)-1] = '\0';
Packit 577717
			papi_free (temp);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		case DERIVED_ADD: {
Packit 577717
			// the event we depend on has no formula, create a formula for our new event to add together the depends_on native event values
Packit 577717
Packit 577717
			// build a formula for this add event
Packit 577717
			sprintf(work, "N%d|N%d|+|", results->count, results->count + 1);
Packit 577717
			strcat(newFormula, work);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		case DERIVED_SUB: {
Packit 577717
			// the event we depend on has no formula, create a formula for our new event to subtract the depends_on native event values
Packit 577717
Packit 577717
			// build a formula for this subtract event
Packit 577717
			sprintf(work, "N%d|N%d|-|", results->count, results->count + 1);
Packit 577717
			strcat(newFormula, work);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		case NOT_DERIVED: {
Packit 577717
			// the event we depend on has no formula and is itself only based on one native event, create a formula for our new event to include this native event
Packit 577717
Packit 577717
			// build a formula for this subtract event
Packit 577717
			sprintf(work, "N%d|", results->count);
Packit 577717
			strcat(newFormula, work);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		default: {
Packit 577717
			// the event we depend on has unsupported derived type, put out some debug and give up
Packit 577717
			INTDBG("Event %s depends on event %s which has an unsupported derived type of %d\n", results->symbol, depends_on->symbol, depends_on->derived_int);
Packit 577717
			return;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	// if this was the second event, append to the formula an operation to add or subtract the results of the two events
Packit 577717
	if (second_event) {
Packit 577717
		if (addition != 0) {
Packit 577717
			strcat(newFormula, "+|");
Packit 577717
		} else {
Packit 577717
			strcat(newFormula, "-|");
Packit 577717
		}
Packit 577717
		// also change the new derived events type to show it has a formula now
Packit 577717
		results->derived_int = DERIVED_POSTFIX;
Packit 577717
	}
Packit 577717
Packit 577717
	// we need to free the existing space (created by malloc and we need to create a new one)
Packit 577717
	papi_free (results->postfix);
Packit 577717
	results->postfix = papi_strdup(newFormula);
Packit 577717
	INTDBG("EXIT: newFormula: %s\n", newFormula);
Packit 577717
	return;
Packit 577717
}
Packit 577717
Packit 577717
// merge the 'insertion' formula into the 'original' formula replacing the
Packit 577717
// 'replaces' token in the 'original' formula.
Packit 577717
static void
Packit 577717
ops_string_merge(char **original, char *insertion, int replaces, int start_index) {
Packit 577717
	INTDBG("ENTER: original: %p, *original: %s, insertion: %s, replaces: %d, start_index: %d\n", original, *original, insertion, replaces, start_index);
Packit 577717
Packit 577717
	int orig_len=0;
Packit 577717
	int ins_len=0;
Packit 577717
	char *subtoken;
Packit 577717
	char *workBuf;
Packit 577717
	char *workPtr;
Packit 577717
	char *tok_save_ptr=NULL;
Packit 577717
	char *newOriginal;
Packit 577717
	char *newInsertion;
Packit 577717
	char *newFormula;
Packit 577717
	int insert_events;
Packit 577717
Packit 577717
	if (*original != NULL) {
Packit 577717
		orig_len = strlen(*original);
Packit 577717
	}
Packit 577717
	if (insertion != NULL) {
Packit 577717
		ins_len = strlen(insertion);
Packit 577717
	}
Packit 577717
	newFormula = papi_calloc (orig_len + ins_len + 40, 1);
Packit 577717
Packit 577717
	// if insertion formula is not provided, then the original formula remains basically unchanged.
Packit 577717
	if (insertion == NULL) {
Packit 577717
		// if the original formula has a leading '|' then get rid of it
Packit 577717
		workPtr = *original;
Packit 577717
		if (workPtr[0] == '|') {
Packit 577717
			strcpy(newFormula, &workPtr[1]);
Packit 577717
		} else {
Packit 577717
			strcpy(newFormula, workPtr);
Packit 577717
		}
Packit 577717
		// formula fields are always malloced space so free the previous one
Packit 577717
		papi_free (*original);
Packit 577717
		*original = newFormula;
Packit 577717
		INTDBG("EXIT: newFormula: %s\n", *original);
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
	// renumber the token numbers in the insertion formula
Packit 577717
	// also count how many native events are used in this formula
Packit 577717
	insert_events = 0;
Packit 577717
	newInsertion = papi_calloc(ins_len+20, 1);
Packit 577717
	workBuf = papi_calloc(ins_len+10, 1);
Packit 577717
	workPtr = papi_strdup(insertion);
Packit 577717
	subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
Packit 577717
	while ( subtoken != NULL) {
Packit 577717
//		INTDBG("subtoken: %s, newInsertion: %s\n", subtoken, newInsertion);
Packit 577717
		if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
Packit 577717
			insert_events++;
Packit 577717
			int val = atoi(&subtoken[1]);
Packit 577717
			val += start_index;
Packit 577717
			subtoken[1] = '\0';
Packit 577717
			sprintf (workBuf, "N%d", val);
Packit 577717
		} else {
Packit 577717
			strcpy(workBuf, subtoken);
Packit 577717
		}
Packit 577717
		strcat (newInsertion, workBuf);
Packit 577717
		strcat (newInsertion, "|");
Packit 577717
		subtoken = strtok_r(NULL, "|", &tok_save_ptr);
Packit 577717
	}
Packit 577717
	papi_free (workBuf);
Packit 577717
	papi_free (workPtr);
Packit 577717
	INTDBG("newInsertion: %s\n", newInsertion);
Packit 577717
Packit 577717
	// if original formula is not provided, then the updated insertion formula becomes the new formula
Packit 577717
	// but we still had to renumber the native event tokens in case another native event was put into the list first
Packit 577717
	if (*original == NULL) {
Packit 577717
		*original = papi_strdup(newInsertion);
Packit 577717
		INTDBG("EXIT: newFormula: %s\n", newInsertion);
Packit 577717
		papi_free (newInsertion);
Packit 577717
		papi_free (newFormula);
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
	// if token to replace not valid, return null  (do we also need to check an upper bound ???)
Packit 577717
	if ((replaces < 0)) {
Packit 577717
		papi_free (newInsertion);
Packit 577717
		papi_free (newFormula);
Packit 577717
		INTDBG("EXIT: Invalid value for token in original formula to be replaced\n");
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
	// renumber the token numbers in the original formula
Packit 577717
	// tokens with an index greater than the replaces token need to be incremented by number of events in insertion formula-1
Packit 577717
	newOriginal = papi_calloc (orig_len+20, 1);
Packit 577717
	workBuf = papi_calloc(orig_len+10, 1);
Packit 577717
	workPtr = papi_strdup(*original);
Packit 577717
Packit 577717
	subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
Packit 577717
	while ( subtoken != NULL) {
Packit 577717
//		INTDBG("subtoken: %s, newOriginal: %s\n", subtoken, newOriginal);
Packit 577717
		// prime the work area with the next token, then see if we need to change it
Packit 577717
		strcpy(workBuf, subtoken);
Packit 577717
		if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
Packit 577717
			int val = atoi(&subtoken[1]);
Packit 577717
			if (val > replaces) {
Packit 577717
				val += insert_events-1;
Packit 577717
				subtoken[1] = '\0';
Packit 577717
				sprintf (workBuf, "N%d", val);
Packit 577717
			}
Packit 577717
		}
Packit 577717
		// put the work buffer into the new original formula
Packit 577717
		strcat (newOriginal, workBuf);
Packit 577717
		strcat (newOriginal, "|");
Packit 577717
		subtoken = strtok_r(NULL, "|", &tok_save_ptr);
Packit 577717
	}
Packit 577717
	papi_free (workBuf);
Packit 577717
	papi_free (workPtr);
Packit 577717
	INTDBG("newOriginal: %s\n", newOriginal);
Packit 577717
Packit 577717
	// replace the specified "replace" tokens in the new original formula with the new insertion formula
Packit 577717
	newFormula[0] = '\0';
Packit 577717
	workPtr = newOriginal;
Packit 577717
	subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
Packit 577717
	while ( subtoken != NULL) {
Packit 577717
//		INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
Packit 577717
		// if this is the token we want to replace with the insertion string, do it now
Packit 577717
		if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))  &&  (replaces == atoi(&subtoken[1]))) {
Packit 577717
			// copy updated insertion string into the original string (replacing this token)
Packit 577717
			strcat(newFormula, newInsertion);
Packit 577717
		} else {
Packit 577717
			// copy this part of the original formula into the new formula
Packit 577717
			strcat(newFormula, subtoken);
Packit 577717
			strcat(newFormula, "|");
Packit 577717
		}
Packit 577717
		subtoken = strtok_r(NULL, "|", &tok_save_ptr);
Packit 577717
	}
Packit 577717
	papi_free (newInsertion);
Packit 577717
	papi_free (workPtr);
Packit 577717
Packit 577717
	// formula fields are always malloced space so free the previous one
Packit 577717
	papi_free (*original);
Packit 577717
	*original = newFormula;
Packit 577717
	INTDBG("EXIT: newFormula: %s\n", newFormula);
Packit 577717
	return;
Packit 577717
}
Packit 577717
Packit 577717
//
Packit 577717
//  Check to see if an event the new derived event being created depends on is known.  We check both preset and user defined derived events here.
Packit 577717
//  If it is a known derived event then we set the new event being defined to include the necessary native events and formula to compute its
Packit 577717
//  derived value and use it in the correct context of the new derived event being created.  Depending on the inputs, the operations strings (formulas)
Packit 577717
//  to be used by the new derived event may need to be created and/or adjusted to reference the correct native event indexes for the new derived event.
Packit 577717
//  The formulas processed by this code must be reverse polish notation (RPN) or postfix format and they must contain place holders (like N0, N1) which
Packit 577717
//  identify indexes into the native event array used to compute the new derived events final value.
Packit 577717
//
Packit 577717
//  Arguments:
Packit 577717
//    target:  event we are looking for
Packit 577717
//    derived_type:  type of derived event being created (add, subtract, postfix)
Packit 577717
//    results:  where to build the new preset event being defined.
Packit 577717
//    search: table of known existing preset or user events the new derived event is allowed to use (points to a table of either preset or user events).
Packit 577717
//    search_size:  number of entries in the search table.
Packit 577717
//
Packit 577717
static int
Packit 577717
check_derived_events(char *target, int derived_type, hwi_presets_t* results, hwi_presets_t * search, int search_size, int token_index)
Packit 577717
{
Packit 577717
	INTDBG("ENTER: target: %p (%s), results: %p, search: %p, search_size: %d, token_index: %d\n", target, target, results, search, search_size, token_index);
Packit 577717
	unsigned int i;
Packit 577717
	int j;
Packit 577717
	int k;
Packit 577717
	int found = 0;
Packit 577717
Packit 577717
	for (j=0; j < search_size; j++) {
Packit 577717
		//	INTDBG("search[%d].symbol: %s, looking for: %s\n", j, search[j].symbol, target);
Packit 577717
		if (search[j].symbol == NULL) {
Packit 577717
			INTDBG("EXIT: returned: 0\n");
Packit 577717
			return 0;
Packit 577717
		}
Packit 577717
Packit 577717
		// if not the event we depend on, just look at next
Packit 577717
		if ( strcasecmp( target, search[j].symbol) != 0 ) {
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
Packit 577717
		INTDBG("Found a match\n");
Packit 577717
Packit 577717
		// derived formulas need to be adjusted based on what kind of derived event we are processing
Packit 577717
		// the derived type passed to this function is the type of the new event being defined (not the events it is based on)
Packit 577717
		// when we get here the formula must be in reverse polish notation (RPN) format
Packit 577717
		switch (derived_type) {
Packit 577717
			case DERIVED_POSTFIX: {
Packit 577717
				// go create a formula to merge the second formula into a spot identified by one of the tokens in
Packit 577717
				// the first formula.
Packit 577717
				ops_string_merge(&(results->postfix), search[j].postfix, token_index, results->count);
Packit 577717
				break;
Packit 577717
			}
Packit 577717
			case DERIVED_ADD: {
Packit 577717
				// the new derived event adds two things together, go handle this target events role in the add
Packit 577717
				ops_string_append(results, &search[j], 1);
Packit 577717
				break;
Packit 577717
			}
Packit 577717
			case DERIVED_SUB: {
Packit 577717
				// go create a formula to subtract the value generated by the second formula from the value generated by the first formula.
Packit 577717
				ops_string_append(results, &search[j], 0);
Packit 577717
				break;
Packit 577717
			}
Packit 577717
				default: {
Packit 577717
				INTDBG("Derived type: %d, not currently handled\n", derived_type);
Packit 577717
				break;
Packit 577717
			}
Packit 577717
		}
Packit 577717
Packit 577717
		// copy event name and code used by the derived event into the results table (place where new derived event is getting created)
Packit 577717
		for ( k = 0; k < (int)search[j].count; k++ ) {
Packit 577717
//			INTDBG("search[%d]: %p, name[%d]: %s, code[%d]: %#x\n", j, &search[j], k, search[j].name[k], k, search[j].code[k]);
Packit 577717
			// if this event is already in the list, just update the formula so that references to this event point to the existing one
Packit 577717
			for (i=0 ; i < results->count ; i++) {
Packit 577717
				if (results->code[i] == search[j].code[k]) {
Packit 577717
					INTDBG("event: %s, code: %#x, already in results at index: %d\n", search[j].name[k], search[j].code[k], i);
Packit 577717
					// replace all tokens in the formula that refer to index "results->count + found" with a token that refers to index "i".
Packit 577717
					// the index "results->count + found" identifies the index used in the formula for the event we just determined is a duplicate
Packit 577717
					update_ops_string(&(results->postfix), results->count + found, i);
Packit 577717
					found++;
Packit 577717
					break;
Packit 577717
				}
Packit 577717
			}
Packit 577717
Packit 577717
			// if we did not find a match, copy native event info into results array
Packit 577717
			if (found == 0) {
Packit 577717
				// not a duplicate, go ahead and copy into results and bump number of native events in results
Packit 577717
				if (search[j].name[k]) {
Packit 577717
					results->name[results->count] = papi_strdup(search[j].name[k]);
Packit 577717
				} else {
Packit 577717
					results->name[results->count] = papi_strdup(target);
Packit 577717
				}
Packit 577717
				results->code[results->count] = search[j].code[k];
Packit 577717
				INTDBG("results: %p, name[%d]: %s, code[%d]: %#x\n", results, results->count, results->name[results->count], results->count, results->code[results->count]);
Packit 577717
Packit 577717
				results->count++;
Packit 577717
			}
Packit 577717
		}
Packit 577717
Packit 577717
		INTDBG("EXIT: returned: 1\n");
Packit 577717
		return 1;
Packit 577717
	}
Packit 577717
Packit 577717
	INTDBG("EXIT: returned: 0\n");
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
check_native_events(char *target, hwi_presets_t* results)
Packit 577717
{
Packit 577717
	INTDBG("ENTER: target: %p (%s), results: %p\n", target, target, results);
Packit 577717
	int ret;
Packit 577717
Packit 577717
	// find this native events code
Packit 577717
	if ( ( ret = _papi_hwi_native_name_to_code( target, (int *)(&results->code[results->count])) ) != PAPI_OK ) {
Packit 577717
		INTDBG("EXIT: returned: 0, call to convert name to event code failed with ret: %d\n", ret);
Packit 577717
		return 0;
Packit 577717
	}
Packit 577717
Packit 577717
	// if the code returned was 0, return to show it is not a valid native event
Packit 577717
	if ( results->code[results->count] == 0 ) {
Packit 577717
		INTDBG( "EXIT: returned: 0, event code not found\n");
Packit 577717
		return 0;
Packit 577717
	}
Packit 577717
Packit 577717
	// if this native event is not for component 0, return to show it can not be used in derived events
Packit 577717
	// it should be possible to create derived events for other components as long as all events in the derived event are associated with the same component
Packit 577717
	if ( _papi_hwi_component_index(results->code[results->count]) != 0 ) {
Packit 577717
		INTDBG( "EXIT: returned: 0, new event not associated with component 0 (current limitation with derived events)\n");
Packit 577717
		return 0;
Packit 577717
	}
Packit 577717
Packit 577717
	//	  found = 1;
Packit 577717
	INTDBG("\tFound a native event %s\n", target);
Packit 577717
	results->name[results->count++] = papi_strdup(target);
Packit 577717
Packit 577717
	INTDBG( "EXIT: returned: 1\n");
Packit 577717
	return 1;
Packit 577717
}
Packit 577717
Packit 577717
// see if the event_name string passed in matches a known event name
Packit 577717
// if it does these calls also updates information in event definition tables to remember the event
Packit 577717
static int
Packit 577717
is_event(char *event_name, int derived_type, hwi_presets_t* results, int token_index) {
Packit 577717
	INTDBG("ENTER: event_name: %p (%s), derived_type: %d, results: %p, token_index: %d\n", event_name, event_name, derived_type, results, token_index);
Packit 577717
Packit 577717
	/* check if its a preset event */
Packit 577717
	if ( check_derived_events(event_name, derived_type, results, &_papi_hwi_presets[0], PAPI_MAX_PRESET_EVENTS, token_index) ) {
Packit 577717
		INTDBG("EXIT: found preset event\n");
Packit 577717
		return 1;
Packit 577717
	}
Packit 577717
Packit 577717
	/* check if its a user defined event */
Packit 577717
	if ( check_derived_events(event_name, derived_type, results, user_defined_events, user_defined_events_count, token_index) ) {
Packit 577717
		INTDBG("EXIT: found user event\n");
Packit 577717
		return 1;
Packit 577717
	}
Packit 577717
Packit 577717
	/* check if its a native event */
Packit 577717
	if ( check_native_events(event_name, results) ) {
Packit 577717
		INTDBG("EXIT: found native event\n");
Packit 577717
		return 1;
Packit 577717
	}
Packit 577717
Packit 577717
	INTDBG("EXIT: event not found\n");
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
/* Static version of the events file. */
Packit 577717
#if defined(STATIC_PAPI_EVENTS_TABLE)
Packit 577717
#include "papi_events_table.h"
Packit 577717
#else
Packit 577717
static char *papi_events_table = NULL;
Packit 577717
#endif
Packit 577717
Packit 577717
int _papi_load_preset_table(char *pmu_str, int pmu_type, int cidx) {
Packit 577717
	SUBDBG("ENTER: pmu_str: %s, pmu_type: %d, cidx: %d\n", pmu_str, pmu_type, cidx);
Packit 577717
Packit 577717
	int retval;
Packit 577717
Packit 577717
	// go load papi preset events (last argument tells function if we are loading presets or user events)
Packit 577717
	retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 1);
Packit 577717
	if (retval != PAPI_OK) {
Packit 577717
		SUBDBG("EXIT: retval: %d\n", retval);
Packit 577717
		return retval;
Packit 577717
	}
Packit 577717
Packit 577717
	// go load the user defined event definitions if any are defined
Packit 577717
	retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 0);
Packit 577717
Packit 577717
	SUBDBG("EXIT: retval: %d\n", retval);
Packit 577717
	return retval;
Packit 577717
}
Packit 577717
Packit 577717
// global variables
Packit 577717
static char stack[2*PAPI_HUGE_STR_LEN]; // stack
Packit 577717
static int stacktop = -1; // stack length
Packit 577717
Packit 577717
// priority: This function returns the priority of the operator
Packit 577717
static
Packit 577717
int priority( char symbol ) {
Packit 577717
        switch( symbol ) {
Packit 577717
        case '@':
Packit 577717
                return -1;
Packit 577717
        case '(':
Packit 577717
                return 0;
Packit 577717
	case '+':
Packit 577717
	case '-':
Packit 577717
                return 1;
Packit 577717
	case '*':
Packit 577717
	case '/':
Packit 577717
	case '%':
Packit 577717
		return 2;
Packit 577717
	default :
Packit 577717
		return 0;
Packit 577717
	} // end switch symbol
Packit 577717
} // end priority
Packit 577717
Packit 577717
static
Packit 577717
int push( char symbol ) {
Packit 577717
  if (stacktop >= 2*PAPI_HUGE_STR_LEN - 1) {
Packit 577717
    INTDBG("stack overflow converting algebraic expression (%d,%c)\n", stacktop,symbol );
Packit 577717
    return -1;  //***TODO: Figure out how to exit gracefully
Packit 577717
  } // end if stacktop>MAX
Packit 577717
  stack[++stacktop] = symbol;
Packit 577717
  return 0;
Packit 577717
} // end push
Packit 577717
Packit 577717
// pop from stack
Packit 577717
static
Packit 577717
char pop() {
Packit 577717
  if( stacktop < 0 ) {
Packit 577717
    INTDBG("stack underflow converting algebraic expression\n" );
Packit 577717
    return '\0';  //***TODO: Figure out how to exit gracefully
Packit 577717
  } // end if empty
Packit 577717
  return( stack[stacktop--] );
Packit 577717
} // end pop
Packit 577717
Packit 577717
/* infix_to_postfix:
Packit 577717
   routine that will be called with parameter:
Packit 577717
   char *in characters of infix notation (algebraic formula)
Packit 577717
   returns: char * pointer to string of returned postfix */
Packit 577717
static char *
Packit 577717
infix_to_postfix( char *infix ) {
Packit 577717
	INTDBG("ENTER: in: %s, size: %zu\n", infix, strlen(infix));
Packit 577717
	static char postfix[2*PAPI_HUGE_STR_LEN];	// output
Packit 577717
        unsigned int index;
Packit 577717
        int postfixlen;
Packit 577717
        char token;
Packit 577717
        if ( strlen(infix) > PAPI_HUGE_STR_LEN ) 
Packit 577717
            PAPIERROR("A infix string (probably in user-defined presets) is too big (max allowed %d): %s", PAPI_HUGE_STR_LEN, infix );
Packit 577717
Packit 577717
        // initialize stack
Packit 577717
	memset(stack, 0, 2*PAPI_HUGE_STR_LEN);
Packit 577717
	stacktop = -1; 
Packit 577717
	push('#'); 
Packit 577717
        stacktop = 0; // after initialization of stack to #
Packit 577717
        /* initialize output string */
Packit 577717
	memset(postfix,0,2*PAPI_HUGE_STR_LEN);
Packit 577717
        postfixlen = 0;
Packit 577717
Packit 577717
	for( index=0; index
Packit 577717
                token = infix[index];
Packit 577717
                INTDBG("INTDBG: in: %s, length: %zu, index: %d token %c\n", infix, strlen( infix ), index, token);
Packit 577717
		switch( token ) {
Packit 577717
		case '(':
Packit 577717
			push( token );
Packit 577717
			break;
Packit 577717
		case ')':
Packit 577717
                        if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
Packit 577717
                        while ( stack[stacktop] != '(' ) {
Packit 577717
                                postfix[postfixlen++] = pop();
Packit 577717
                                postfix[postfixlen++] = '|';
Packit 577717
                        }
Packit 577717
                        token = pop();  /* pop the '(' character */
Packit 577717
			break;
Packit 577717
		case '+':
Packit 577717
		case '-':
Packit 577717
		case '*':
Packit 577717
		case '/':
Packit 577717
		case '%':
Packit 577717
		case '^':       /* if an operator */
Packit 577717
                        if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
Packit 577717
                        while ( priority(stack[stacktop]) > priority(token) ) {
Packit 577717
                                postfix[postfixlen++] = pop();
Packit 577717
                                postfix[postfixlen++] = '|';
Packit 577717
                        }
Packit 577717
                        push( token ); /* save current operator */
Packit 577717
                        break;
Packit 577717
		default: // if alphanumeric character which is not parenthesis or an operator
Packit 577717
                        postfix[postfixlen++] = token;
Packit 577717
			break;
Packit 577717
		} // end switch symbol
Packit 577717
	} // end while
Packit 577717
Packit 577717
        /* Write any remaining operators */
Packit 577717
        if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
Packit 577717
        while ( stacktop>0 ) {
Packit 577717
                postfix[postfixlen++] = pop();
Packit 577717
                postfix[postfixlen++] = '|';
Packit 577717
        }
Packit 577717
        postfix[postfixlen++] = '\0';
Packit 577717
	stacktop = -1; 
Packit 577717
Packit 577717
	INTDBG("EXIT: postfix: %s, size: %zu\n", postfix, strlen(postfix));
Packit 577717
	return (postfix);
Packit 577717
} // end infix_to_postfix
Packit 577717
Packit 577717
/*
Packit 577717
 * This function will load event definitions from either a file or an in memory table.  It is used to load both preset events
Packit 577717
 * which are defined by the PAPI development team and delivered with the product and user defined events which can be defined
Packit 577717
 * by papi users and provided to papi to be processed at library initialization.  Both the preset events and user defined events
Packit 577717
 * support the same event definition syntax.
Packit 577717
 *
Packit 577717
 * Event definition file syntax:
Packit 577717
 * see PAPI_derived_event_files(1) man page.
Packit 577717
 *
Packit 577717
 * Blank lines are ignored
Packit 577717
 * Lines that begin with '#' are comments.
Packit 577717
 * Lines that begin with 'CPU' identify a pmu name and have the following effect.
Packit 577717
 *      If this pmu name does not match the pmu_str passed in, it is ignored and we get the next input line.
Packit 577717
 *      If this pmu name matches the pmu_str passed in, we set a 'process events' flag.
Packit 577717
 *      Multiple consecutive 'CPU' lines may be provided and if any of them match the pmu_str passed in, we set a 'process events' flag.
Packit 577717
 *      When a 'CPU' line is found following event definition lines, it turns off the 'process events' flag and then does the above checks.
Packit 577717
 * Lines that begin with 'PRESET' or 'EVENT' specify an event definition and are processed as follows.
Packit 577717
 *      If the 'process events' flag is not set, the line is ignored and we get the next input line.
Packit 577717
 *      If the 'process events' flag is set, the event is processed and the event information is put into the next slot in the results array.
Packit 577717
 *
Packit 577717
 * There are three possible sources of input for preset event definitions.  The code will first look for the environment variable
Packit 577717
 * "PAPI_CSV_EVENT_FILE".  If found its value will be used as the pathname of where to get the preset information.  If not found,
Packit 577717
 * the code will look for a built in table containing preset events.  If the built in table was not created during the build of
Packit 577717
 * PAPI then the code will build a pathname of the form "PAPI_DATADIR/PAPI_EVENT_FILE".  Each of these are build variables, the
Packit 577717
 * PAPI_DATADIR variable can be given a value during the configure of PAPI at build time, and the PAPI_EVENT_FILE variable has a
Packit 577717
 * hard coded value of "papi_events.csv".
Packit 577717
 *
Packit 577717
 * There is only one way to define user events.  The code will look for an environment variable "PAPI_USER_EVENTS_FILE".  If found
Packit 577717
 * its value will be used as the pathname of a file which contains user event definitions.  The events defined in this file will be
Packit 577717
 * added to the ones known by PAPI when the call to PAPI_library_init is done.
Packit 577717
 *
Packit 577717
 * TODO:
Packit 577717
 * Look into restoring the ability to specify a user defined event file with a call to PAPI_set_opt(PAPI_USER_EVENTS_FILE).
Packit 577717
 * This needs to figure out how to pass a pmu name (could use default pmu from component 0) to this function.
Packit 577717
 *
Packit 577717
 * Currently code elsewhere in PAPI limits the events which preset and user events can depend on to those events which are known to component 0.  This possibly could
Packit 577717
 * be relaxed to allow events from different components.  But since all the events used by any derived event must be added to the same eventset, it will always be a
Packit 577717
 * requirement that all events used by a given derived event must be from the same component.
Packit 577717
 *
Packit 577717
 */
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag) {
Packit 577717
	SUBDBG( "ENTER: pmu_str: %s, pmu_type: %d, cidx: %d, preset_flag: %d\n", pmu_str, pmu_type, cidx, preset_flag);
Packit 577717
Packit 577717
	char pmu_name[PAPI_MIN_STR_LEN];
Packit 577717
	char line[LINE_MAX];
Packit 577717
	char name[PATH_MAX] = "builtin papi_events_table";
Packit 577717
	char *event_file_path=NULL;
Packit 577717
	char *event_table_ptr=NULL;
Packit 577717
	int event_type_bits = 0;
Packit 577717
	char *tmpn;
Packit 577717
	char *tok_save_ptr=NULL;
Packit 577717
	FILE *event_file = NULL;
Packit 577717
	hwi_presets_t *results=NULL;
Packit 577717
	int result_size = 0;
Packit 577717
	int *event_count = NULL;
Packit 577717
	int invalid_event;
Packit 577717
	int line_no = 0;  /* count of lines read from event definition input */
Packit 577717
	int derived = 0;
Packit 577717
	int res_idx = 0;  /* index into results array for where to store next event */
Packit 577717
	int preset = 0;
Packit 577717
	int get_events = 0; /* only process derived events after CPU type they apply to is identified      */
Packit 577717
	int found_events = 0; /* flag to track if event definitions (PRESETS) are found since last CPU declaration */
Packit 577717
#ifdef PAPI_DATADIR
Packit 577717
		char path[PATH_MAX];
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
	if (preset_flag) {
Packit 577717
		/* try the environment variable first */
Packit 577717
		if ((tmpn = getenv("PAPI_CSV_EVENT_FILE")) && (strlen(tmpn) > 0)) {
Packit 577717
			event_file_path = tmpn;
Packit 577717
		}
Packit 577717
		/* if no valid environment variable, look for built-in table */
Packit 577717
		else if (papi_events_table) {
Packit 577717
			event_table_ptr = papi_events_table;
Packit 577717
		}
Packit 577717
		/* if no env var and no built-in, search for default file */
Packit 577717
		else {
Packit 577717
#ifdef PAPI_DATADIR
Packit 577717
			sprintf( path, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE );
Packit 577717
			event_file_path = path;
Packit 577717
#else
Packit 577717
			event_file_path = PAPI_EVENT_FILE;
Packit 577717
#endif
Packit 577717
		}
Packit 577717
		event_type_bits = PAPI_PRESET_MASK;
Packit 577717
		results = &_papi_hwi_presets[0];
Packit 577717
		result_size = PAPI_MAX_PRESET_EVENTS;
Packit 577717
		event_count = &_papi_hwd[cidx]->cmp_info.num_preset_events;
Packit 577717
	} else {
Packit 577717
		if ((event_file_path = getenv( "PAPI_USER_EVENTS_FILE" )) == NULL ) {
Packit 577717
			SUBDBG("EXIT: User event definition file not provided.\n");
Packit 577717
			return PAPI_OK;
Packit 577717
		}
Packit 577717
Packit 577717
		event_type_bits = PAPI_UE_MASK;
Packit 577717
		results = &user_defined_events[0];
Packit 577717
		result_size = PAPI_MAX_USER_EVENTS;
Packit 577717
		event_count = &user_defined_events_count;
Packit 577717
	}
Packit 577717
Packit 577717
	// if we have an event file pathname, open it and read event definitions from the file
Packit 577717
	if (event_file_path != NULL) {
Packit 577717
		if ((event_file = open_event_table(event_file_path)) == NULL) {
Packit 577717
			// if file open fails, return an error
Packit 577717
			SUBDBG("EXIT: Event file open failed.\n");
Packit 577717
			return PAPI_ESYS;
Packit 577717
		}
Packit 577717
		strncpy(name, event_file_path, sizeof(name)-1);
Packit 577717
		name[sizeof(name)-1] = '\0';
Packit 577717
	} else if (event_table_ptr == NULL) {
Packit 577717
		// if we do not have a path name or table pointer, return an error
Packit 577717
		SUBDBG("EXIT: Both event_file_path and event_table_ptr are NULL.\n");
Packit 577717
		return PAPI_ESYS;
Packit 577717
	}
Packit 577717
Packit 577717
	/* copy the pmu identifier, stripping commas if found */
Packit 577717
	tmpn = pmu_name;
Packit 577717
	while (*pmu_str) {
Packit 577717
		if (*pmu_str != ',')
Packit 577717
			*tmpn++ = *pmu_str;
Packit 577717
		pmu_str++;
Packit 577717
	}
Packit 577717
	*tmpn = '\0';
Packit 577717
Packit 577717
	/* at this point we have either a valid file pointer or built-in table pointer */
Packit 577717
	while (get_event_line(line, event_file, &event_table_ptr)) {
Packit 577717
		char *t;
Packit 577717
		int i;
Packit 577717
Packit 577717
		// increment number of lines we have read
Packit 577717
		line_no++;
Packit 577717
Packit 577717
		t = trim_string(strtok_r(line, ",", &tok_save_ptr));
Packit 577717
Packit 577717
		/* Skip blank lines */
Packit 577717
		if ((t == NULL) || (strlen(t) == 0))
Packit 577717
			continue;
Packit 577717
Packit 577717
		/* Skip comments */
Packit 577717
		if (t[0] == '#') {
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
Packit 577717
		if (strcasecmp(t, "CPU") == 0) {
Packit 577717
			if (get_events != 0 && found_events != 0) {
Packit 577717
				SUBDBG( "Ending event scanning at line %d of %s.\n", line_no, name);
Packit 577717
				get_events = 0;
Packit 577717
				found_events = 0;
Packit 577717
			}
Packit 577717
Packit 577717
			t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
			if ((t == NULL) || (strlen(t) == 0)) {
Packit 577717
				PAPIERROR("Expected name after CPU token at line %d of %s -- ignoring", line_no, name);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			if (strcasecmp(t, pmu_name) == 0) {
Packit 577717
				int type;
Packit 577717
Packit 577717
				SUBDBG( "Process events for PMU %s found at line %d of %s.\n", t, line_no, name);
Packit 577717
Packit 577717
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
				if ((t == NULL) || (strlen(t) == 0)) {
Packit 577717
					SUBDBG("No additional qualifier found, matching on string.\n");
Packit 577717
					get_events = 1;
Packit 577717
				} else if ((sscanf(t, "%d", &type) == 1) && (type == pmu_type)) {
Packit 577717
					SUBDBG( "Found CPU %s type %d at line %d of %s.\n", pmu_name, type, line_no, name);
Packit 577717
					get_events = 1;
Packit 577717
				} else {
Packit 577717
					SUBDBG( "Additional qualifier match failed %d vs %d.\n", pmu_type, type);
Packit 577717
				}
Packit 577717
			}
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
Packit 577717
		if ((strcasecmp(t, "PRESET") == 0)  || (strcasecmp(t, "EVENT") == 0)) {
Packit 577717
Packit 577717
			if (get_events == 0)
Packit 577717
				continue;
Packit 577717
Packit 577717
			found_events = 1;
Packit 577717
			t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
Packit 577717
			if ((t == NULL) || (strlen(t) == 0)) {
Packit 577717
				PAPIERROR("Expected name after PRESET token at line %d of %s -- ignoring", line_no, name);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			SUBDBG( "Examining event %s\n", t);
Packit 577717
Packit 577717
			// see if this event already exists in the results array, if not already known it sets up event in unused entry
Packit 577717
			if ((res_idx = find_event_index (results, result_size, t)) < 0) {
Packit 577717
				PAPIERROR("No room left for event %s -- ignoring", t);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			// add the proper event bits (preset or user defined bits)
Packit 577717
			preset = res_idx | event_type_bits;
Packit 577717
			(void) preset;
Packit 577717
Packit 577717
			SUBDBG( "Use event code: %#x for %s\n", preset, t);
Packit 577717
Packit 577717
			t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
			if ((t == NULL) || (strlen(t) == 0)) {
Packit 577717
				// got an error, make this entry unused
Packit 577717
				papi_free (results[res_idx].symbol);
Packit 577717
				results[res_idx].symbol = NULL;
Packit 577717
				PAPIERROR("Expected derived type after PRESET token at line %d of %s -- ignoring", line_no, name);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			if (_papi_hwi_derived_type(t, &derived) != PAPI_OK) {
Packit 577717
				// got an error, make this entry unused
Packit 577717
				papi_free (results[res_idx].symbol);
Packit 577717
				results[res_idx].symbol = NULL;
Packit 577717
				PAPIERROR("Invalid derived name %s after PRESET token at line %d of %s -- ignoring", t, line_no, name);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			/****************************************/
Packit 577717
			/* Have an event, let's start assigning */
Packit 577717
			/****************************************/
Packit 577717
Packit 577717
			SUBDBG( "Adding event: %s, code: %#x, derived: %d results[%d]: %p.\n", t, preset, derived, res_idx, &results[res_idx]);
Packit 577717
Packit 577717
			/* results[res_idx].event_code = preset; */
Packit 577717
			results[res_idx].derived_int = derived;
Packit 577717
Packit 577717
			/* Derived support starts here */
Packit 577717
			/* Special handling for postfix and infix */
Packit 577717
			if ((derived == DERIVED_POSTFIX)  || (derived == DERIVED_INFIX)) {
Packit 577717
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
				if ((t == NULL) || (strlen(t) == 0)) {
Packit 577717
					// got an error, make this entry unused
Packit 577717
					papi_free (results[res_idx].symbol);
Packit 577717
					results[res_idx].symbol = NULL;
Packit 577717
					PAPIERROR("Expected Operation string after derived type DERIVED_POSTFIX or DERIVED_INFIX at line %d of %s -- ignoring", line_no, name);
Packit 577717
					continue;
Packit 577717
				}
Packit 577717
Packit 577717
				// if it is an algebraic formula, we need to convert it to postfix
Packit 577717
				if (derived == DERIVED_INFIX) {
Packit 577717
					SUBDBG( "Converting InFix operations %s\n", t);
Packit 577717
					t = infix_to_postfix( t );
Packit 577717
					results[res_idx].derived_int = DERIVED_POSTFIX;
Packit 577717
				}
Packit 577717
Packit 577717
				SUBDBG( "Saving PostFix operations %s\n", t);
Packit 577717
				results[res_idx].postfix = papi_strdup(t);
Packit 577717
			}
Packit 577717
Packit 577717
			/* All derived terms collected here */
Packit 577717
			i = 0;
Packit 577717
			invalid_event = 0;
Packit 577717
			results[res_idx].count = 0;
Packit 577717
			do {
Packit 577717
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
				if ((t == NULL) || (strlen(t) == 0))
Packit 577717
					break;
Packit 577717
				if (strcasecmp(t, "NOTE") == 0)
Packit 577717
					break;
Packit 577717
				if (strcasecmp(t, "LDESC") == 0)
Packit 577717
					break;
Packit 577717
				if (strcasecmp(t, "SDESC") == 0)
Packit 577717
					break;
Packit 577717
Packit 577717
				SUBDBG( "Adding term (%d) %s to derived event %#x, current native event count: %d.\n", i, t, preset, results[res_idx].count);
Packit 577717
Packit 577717
				// show that we do not have an event code yet (the component may create one and update this info)
Packit 577717
				// this also clears any values left over from a previous call
Packit 577717
				_papi_hwi_set_papi_event_code(-1, -1);
Packit 577717
Packit 577717
				// make sure that this term in the derived event is a valid event name
Packit 577717
				// this call replaces preset and user event names with the equivalent native events in our results table
Packit 577717
				// it also updates formulas for derived events so that they refer to the correct native event index
Packit 577717
				if (is_event(t, results[res_idx].derived_int, &results[res_idx], i) == 0) {
Packit 577717
					invalid_event = 1;
Packit 577717
					PAPIERROR("Missing event %s, used in derived event %s", t, results[res_idx].symbol);
Packit 577717
					break;
Packit 577717
				}
Packit 577717
Packit 577717
				i++;
Packit 577717
			} while (results[res_idx].count < PAPI_EVENTS_IN_DERIVED_EVENT);
Packit 577717
Packit 577717
			/* preset code list must be PAPI_NULL terminated */
Packit 577717
			if (i < PAPI_EVENTS_IN_DERIVED_EVENT) {
Packit 577717
				results[res_idx].code[results[res_idx].count] = PAPI_NULL;
Packit 577717
			}
Packit 577717
Packit 577717
			if (invalid_event) {
Packit 577717
				// got an error, make this entry unused
Packit 577717
			        // preset table is statically allocated, user defined is dynamic
Packit 577717
			        if (!preset_flag) papi_free (results[res_idx].symbol);
Packit 577717
				results[res_idx].symbol = NULL;
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			/* End of derived support */
Packit 577717
Packit 577717
			// if we did not find any terms to base this derived event on, report error
Packit 577717
			if (i == 0) {
Packit 577717
				// got an error, make this entry unused
Packit 577717
			  if (!preset_flag) papi_free (results[res_idx].symbol);
Packit 577717
				results[res_idx].symbol = NULL;
Packit 577717
				PAPIERROR("Expected PFM event after DERIVED token at line %d of %s -- ignoring", line_no, name);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			if (i == PAPI_EVENTS_IN_DERIVED_EVENT) {
Packit 577717
				t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
			}
Packit 577717
Packit 577717
			// if something was provided following the list of events to be used by the operation, process it
Packit 577717
			if ( t!= NULL  && strlen(t) > 0 ) {
Packit 577717
				do {
Packit 577717
					// save the field name
Packit 577717
					char *fptr = papi_strdup(t);
Packit 577717
Packit 577717
					// get the value to be used with this field
Packit 577717
					t = trim_note(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
					if ( t== NULL  || strlen(t) == 0 ) {
Packit 577717
						papi_free(fptr);
Packit 577717
						break;
Packit 577717
					}
Packit 577717
Packit 577717
					// Handle optional short descriptions, long descriptions and notes
Packit 577717
					if (strcasecmp(fptr, "SDESC") == 0) {
Packit 577717
						results[res_idx].short_descr = papi_strdup(t);
Packit 577717
					}
Packit 577717
					if (strcasecmp(fptr, "LDESC") == 0) {
Packit 577717
						results[res_idx].long_descr = papi_strdup(t);
Packit 577717
					}
Packit 577717
					if (strcasecmp(fptr, "NOTE") == 0) {
Packit 577717
						results[res_idx].note = papi_strdup(t);
Packit 577717
					}
Packit 577717
Packit 577717
					SUBDBG( "Found %s (%s) on line %d\n", fptr, t, line_no);
Packit 577717
					papi_free (fptr);
Packit 577717
Packit 577717
					// look for another field name
Packit 577717
					t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
Packit 577717
					if ( t== NULL  || strlen(t) == 0 ) {
Packit 577717
						break;
Packit 577717
					}
Packit 577717
				} while (t != NULL);
Packit 577717
			}
Packit 577717
			(*event_count)++;
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
Packit 577717
		PAPIERROR("Unrecognized token %s at line %d of %s -- ignoring", t, line_no, name);
Packit 577717
	}
Packit 577717
Packit 577717
	if (event_file) {
Packit 577717
		fclose(event_file);
Packit 577717
	}
Packit 577717
Packit 577717
	SUBDBG("EXIT: Done processing derived event file.\n");
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/* The following code is proof of principle for reading preset events from an
Packit 577717
   xml file. It has been tested and works for pentium3. It relys on the expat
Packit 577717
   library and is invoked by adding
Packit 577717
   XMLFLAG		= -DXML
Packit 577717
   to the Makefile. It is presently hardcoded to look for "./papi_events.xml"
Packit 577717
*/
Packit 577717
#ifdef XML
Packit 577717
Packit 577717
#define BUFFSIZE 8192
Packit 577717
#define SPARSE_BEGIN 0
Packit 577717
#define SPARSE_EVENT_SEARCH 1
Packit 577717
#define SPARSE_EVENT 2
Packit 577717
#define SPARSE_DESC 3
Packit 577717
#define ARCH_SEARCH 4
Packit 577717
#define DENSE_EVENT_SEARCH 5
Packit 577717
#define DENSE_NATIVE_SEARCH 6
Packit 577717
#define DENSE_NATIVE_DESC 7
Packit 577717
#define FINISHED 8
Packit 577717
Packit 577717
char buffer[BUFFSIZE], *xml_arch;
Packit 577717
int location = SPARSE_BEGIN, sparse_index = 0, native_index, error = 0;
Packit 577717
Packit 577717
/* The function below, _xml_start(), is a hook into expat's XML
Packit 577717
 * parser.  _xml_start() defines how the parser handles the
Packit 577717
 * opening tags in PAPI's XML file.  This function can be understood
Packit 577717
 * more easily if you follow along with its logic while looking at
Packit 577717
 * papi_events.xml.  The location variable is a global telling us
Packit 577717
 * where we are in the XML file.  Have we found our architecture's
Packit 577717
 * events yet?  Are we looking at an event definition?...etc.
Packit 577717
 */
Packit 577717
static void
Packit 577717
_xml_start( void *data, const char *el, const char **attr )
Packit 577717
{
Packit 577717
	int native_encoding;
Packit 577717
Packit 577717
	if ( location == SPARSE_BEGIN && !strcmp( "papistdevents", el ) ) {
Packit 577717
		location = SPARSE_EVENT_SEARCH;
Packit 577717
	} else if ( location == SPARSE_EVENT_SEARCH && !strcmp( "papievent", el ) ) {
Packit 577717
		_papi_hwi_presets[sparse_index].info.symbol = papi_strdup( attr[1] );
Packit 577717
//      strcpy(_papi_hwi_presets.info[sparse_index].symbol, attr[1]);
Packit 577717
		location = SPARSE_EVENT;
Packit 577717
	} else if ( location == SPARSE_EVENT && !strcmp( "desc", el ) ) {
Packit 577717
		location = SPARSE_DESC;
Packit 577717
	} else if ( location == ARCH_SEARCH && !strcmp( "availevents", el ) &&
Packit 577717
				!strcmp( xml_arch, attr[1] ) ) {
Packit 577717
		location = DENSE_EVENT_SEARCH;
Packit 577717
	} else if ( location == DENSE_EVENT_SEARCH && !strcmp( "papievent", el ) ) {
Packit 577717
		if ( !strcmp( "PAPI_NULL", attr[1] ) ) {
Packit 577717
			location = FINISHED;
Packit 577717
			return;
Packit 577717
		} else if ( PAPI_event_name_to_code( ( char * ) attr[1], &sparse_index )
Packit 577717
					!= PAPI_OK ) {
Packit 577717
			PAPIERROR( "Improper Preset name given in XML file for %s.",
Packit 577717
					   attr[1] );
Packit 577717
			error = 1;
Packit 577717
		}
Packit 577717
		sparse_index &= PAPI_PRESET_AND_MASK;
Packit 577717
Packit 577717
		/* allocate and initialize data space for this event */
Packit 577717
		papi_valid_free( _papi_hwi_presets[sparse_index].data );
Packit 577717
		_papi_hwi_presets[sparse_index].data =
Packit 577717
			papi_malloc( sizeof ( hwi_preset_data_t ) );
Packit 577717
		native_index = 0;
Packit 577717
		_papi_hwi_presets[sparse_index].data->native[native_index] = PAPI_NULL;
Packit 577717
		_papi_hwi_presets[sparse_index].data->operation[0] = '\0';
Packit 577717
Packit 577717
Packit 577717
		if ( attr[2] ) {	 /* derived event */
Packit 577717
			_papi_hwi_presets[sparse_index].data->derived =
Packit 577717
				_papi_hwi_derived_type( ( char * ) attr[3] );
Packit 577717
			/* where does DERIVED POSTSCRIPT get encoded?? */
Packit 577717
			if ( _papi_hwi_presets[sparse_index].data->derived == -1 ) {
Packit 577717
				PAPIERROR( "No derived type match for %s in Preset XML file.",
Packit 577717
						   attr[3] );
Packit 577717
				error = 1;
Packit 577717
			}
Packit 577717
Packit 577717
			if ( attr[5] ) {
Packit 577717
				_papi_hwi_presets[sparse_index].count = atoi( attr[5] );
Packit 577717
			} else {
Packit 577717
				PAPIERROR( "No count given for %s in Preset XML file.",
Packit 577717
						   attr[1] );
Packit 577717
				error = 1;
Packit 577717
			}
Packit 577717
		} else {
Packit 577717
			_papi_hwi_presets[sparse_index].data->derived = NOT_DERIVED;
Packit 577717
			_papi_hwi_presets[sparse_index].count = 1;
Packit 577717
		}
Packit 577717
		location = DENSE_NATIVE_SEARCH;
Packit 577717
	} else if ( location == DENSE_NATIVE_SEARCH && !strcmp( "native", el ) ) {
Packit 577717
		location = DENSE_NATIVE_DESC;
Packit 577717
	} else if ( location == DENSE_NATIVE_DESC && !strcmp( "event", el ) ) {
Packit 577717
		if ( _papi_hwi_native_name_to_code( attr[1], &native_encoding ) !=
Packit 577717
			 PAPI_OK ) {
Packit 577717
			printf( "Improper Native name given in XML file for %s\n",
Packit 577717
					attr[1] );
Packit 577717
			PAPIERROR( "Improper Native name given in XML file for %s",
Packit 577717
					   attr[1] );
Packit 577717
			error = 1;
Packit 577717
		}
Packit 577717
		_papi_hwi_presets[sparse_index].data->native[native_index] =
Packit 577717
			native_encoding;
Packit 577717
		native_index++;
Packit 577717
		_papi_hwi_presets[sparse_index].data->native[native_index] = PAPI_NULL;
Packit 577717
	} else if ( location && location != ARCH_SEARCH && location != FINISHED ) {
Packit 577717
		PAPIERROR( "Poorly-formed Preset XML document." );
Packit 577717
		error = 1;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/* The function below, _xml_end(), is a hook into expat's XML
Packit 577717
 * parser.  _xml_end() defines how the parser handles the
Packit 577717
 * end tags in PAPI's XML file.
Packit 577717
 */
Packit 577717
static void
Packit 577717
_xml_end( void *data, const char *el )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	if ( location == SPARSE_EVENT_SEARCH && !strcmp( "papistdevents", el ) ) {
Packit 577717
		for ( i = sparse_index; i < PAPI_MAX_PRESET_EVENTS; i++ ) {
Packit 577717
			_papi_hwi_presets[i].info.symbol = NULL;
Packit 577717
			_papi_hwi_presets[i].info.long_descr = NULL;
Packit 577717
			_papi_hwi_presets[i].info.short_descr = NULL;
Packit 577717
		}
Packit 577717
		location = ARCH_SEARCH;
Packit 577717
	} else if ( location == DENSE_NATIVE_DESC && !strcmp( "native", el ) ) {
Packit 577717
		location = DENSE_EVENT_SEARCH;
Packit 577717
	} else if ( location == DENSE_EVENT_SEARCH && !strcmp( "availevents", el ) ) {
Packit 577717
		location = FINISHED;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/* The function below, _xml_content(), is a hook into expat's XML
Packit 577717
 * parser.  _xml_content() defines how the parser handles the
Packit 577717
 * text between tags in PAPI's XML file.  The information between
Packit 577717
 * tags is usally text for event descriptions.
Packit 577717
 */
Packit 577717
static void
Packit 577717
_xml_content( void *data, const char *el, const int len )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
	if ( location == SPARSE_DESC ) {
Packit 577717
		_papi_hwi_presets[sparse_index].info.long_descr =
Packit 577717
			papi_malloc( len + 1 );
Packit 577717
		for ( i = 0; i < len; i++ )
Packit 577717
			_papi_hwi_presets[sparse_index].info.long_descr[i] = el[i];
Packit 577717
		_papi_hwi_presets[sparse_index].info.long_descr[len] = '\0';
Packit 577717
		/* the XML data currently doesn't contain a short description */
Packit 577717
		_papi_hwi_presets[sparse_index].info.short_descr = NULL;
Packit 577717
		sparse_index++;
Packit 577717
		_papi_hwi_presets[sparse_index].data = NULL;
Packit 577717
		location = SPARSE_EVENT_SEARCH;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_xml_papi_hwi_setup_all_presets( char *arch, hwi_dev_notes_t * notes )
Packit 577717
{
Packit 577717
	int done = 0;
Packit 577717
	FILE *fp = fopen( "./papi_events.xml", "r" );
Packit 577717
	XML_Parser p = XML_ParserCreate( NULL );
Packit 577717
Packit 577717
	if ( !p ) {
Packit 577717
		PAPIERROR( "Couldn't allocate memory for XML parser." );
Packit 577717
		fclose(fp);
Packit 577717
		return ( PAPI_ESYS );
Packit 577717
	}
Packit 577717
	XML_SetElementHandler( p, _xml_start, _xml_end );
Packit 577717
	XML_SetCharacterDataHandler( p, _xml_content );
Packit 577717
	if ( fp == NULL ) {
Packit 577717
		PAPIERROR( "Error opening Preset XML file." );
Packit 577717
		fclose(fp);
Packit 577717
		return ( PAPI_ESYS );
Packit 577717
	}
Packit 577717
Packit 577717
	xml_arch = arch;
Packit 577717
Packit 577717
	do {
Packit 577717
		int len;
Packit 577717
		void *buffer = XML_GetBuffer( p, BUFFSIZE );
Packit 577717
Packit 577717
		if ( buffer == NULL ) {
Packit 577717
			PAPIERROR( "Couldn't allocate memory for XML buffer." );
Packit 577717
			fclose(fp);
Packit 577717
			return ( PAPI_ESYS );
Packit 577717
		}
Packit 577717
		len = fread( buffer, 1, BUFFSIZE, fp );
Packit 577717
		if ( ferror( fp ) ) {
Packit 577717
			PAPIERROR( "XML read error." );
Packit 577717
			fclose(fp);
Packit 577717
			return ( PAPI_ESYS );
Packit 577717
		}
Packit 577717
		done = feof( fp );
Packit 577717
		if ( !XML_ParseBuffer( p, len, len == 0 ) ) {
Packit 577717
			PAPIERROR( "Parse error at line %d:\n%s",
Packit 577717
					   XML_GetCurrentLineNumber( p ),
Packit 577717
					   XML_ErrorString( XML_GetErrorCode( p ) ) );
Packit 577717
			fclose(fp);
Packit 577717
			return ( PAPI_ESYS );
Packit 577717
		}
Packit 577717
		if ( error ) {
Packit 577717
			fclose(fp);
Packit 577717
			return ( PAPI_ESYS );
Packit 577717
		}
Packit 577717
	} while ( !done );
Packit 577717
	XML_ParserFree( p );
Packit 577717
	fclose( fp );
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
#endif