attribute.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*LINTLIBRARY*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <papi_impl.h>
static void papiAttributeFree(papi_attribute_t *attribute);
static void
papiAttributeValueFree(papi_attribute_value_type_t type,
papi_attribute_value_t *value)
{
if (value != NULL) {
switch (type) {
case PAPI_STRING:
if (value->string != NULL)
free(value->string);
break;
case PAPI_COLLECTION:
if (value->collection != NULL) {
int i;
for (i = 0; value->collection[i] != NULL; i++)
papiAttributeFree(value->collection[i]);
free(value->collection);
}
break;
default: /* don't need to free anything extra */
break;
}
free(value);
}
}
static void
papiAttributeValuesFree(papi_attribute_value_type_t type,
papi_attribute_value_t **values)
{
if (values != NULL) {
int i;
for (i = 0; values[i] != NULL; i++)
papiAttributeValueFree(type, values[i]);
free(values);
}
}
static void
papiAttributeFree(papi_attribute_t *attribute)
{
if (attribute != NULL) {
if (attribute->name != NULL)
free(attribute->name);
if (attribute->values != NULL)
papiAttributeValuesFree(attribute->type,
attribute->values);
free(attribute);
}
}
void
papiAttributeListFree(papi_attribute_t **list)
{
if (list != NULL) {
int i;
for (i = 0; list[i] != NULL; i++)
papiAttributeFree(list[i]);
free(list);
}
}
static papi_attribute_t **
collection_dup(papi_attribute_t **collection)
{
papi_attribute_t **result = NULL;
/* allows a NULL collection that is "empty" or "no value" */
if (collection != NULL) {
int i;
for (i = 0; collection[i] != NULL; i++) {
papi_attribute_t *a = collection[i];
papiAttributeListAdd(&result, PAPI_ATTR_APPEND, a->name,
a->type, NULL);
if (a->values != NULL) {
int j;
for (j = 0; a->values[j] != NULL; j++)
papiAttributeListAdd(&result,
PAPI_ATTR_APPEND,
a->name, a->type,
a->values[j]);
}
}
}
return (result);
}
static papi_attribute_value_t *
papiAttributeValueDup(const papi_attribute_value_type_t type,
const papi_attribute_value_t *v)
{
papi_attribute_value_t *result = NULL;
if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) {
switch (type) {
case PAPI_STRING:
if (v->string == NULL) {
free(result);
result = NULL;
} else
result->string = strdup(v->string);
break;
case PAPI_INTEGER:
result->integer = v->integer;
break;
case PAPI_BOOLEAN:
result->boolean = v->boolean;
break;
case PAPI_RANGE:
result->range.lower = v->range.lower;
result->range.upper = v->range.upper;
break;
case PAPI_RESOLUTION:
result->resolution.xres = v->resolution.xres;
result->resolution.yres = v->resolution.yres;
result->resolution.units = v->resolution.units;
break;
case PAPI_DATETIME:
result->datetime = v->datetime;
break;
case PAPI_COLLECTION:
result->collection = collection_dup(v->collection);
break;
default: /* unknown type, fail to duplicate */
free(result);
result = NULL;
}
}
return (result);
}
static papi_attribute_t *
papiAttributeAlloc(const char *name, papi_attribute_value_type_t type)
{
papi_attribute_t *result = NULL;
if ((result = calloc(1, sizeof (*result))) != NULL) {
result->name = strdup(name);
result->type = type;
}
return (result);
}
static papi_status_t
papiAttributeListAddValue(papi_attribute_value_t ***values,
const papi_attribute_value_type_t type,
const papi_attribute_value_t *value)
{
if (values == NULL)
return (PAPI_BAD_ARGUMENT);
if (value != NULL) { /* this allows "empty" attributes */
papi_attribute_value_t *tmp = NULL;
if ((tmp = papiAttributeValueDup(type, value)) == NULL)
return (PAPI_TEMPORARY_ERROR);
list_append(values, tmp);
}
return (PAPI_OK);
}
papi_status_t
papiAttributeListAdd(papi_attribute_t ***list, const int flgs,
const char *name, const papi_attribute_value_type_t type,
const papi_attribute_value_t *value)
{
papi_status_t result;
int flags = flgs;
papi_attribute_t *attribute = NULL;
papi_attribute_value_t **values = NULL;
if ((list == NULL) || (name == NULL))
return (PAPI_BAD_ARGUMENT);
if ((type == PAPI_RANGE) && (value != NULL) &&
(value->range.lower > value->range.upper))
return (PAPI_BAD_ARGUMENT); /* RANGE must have min <= max */
if (flags == 0) /* if it wasn't set, set a default behaviour */
flags = PAPI_ATTR_APPEND;
/* look for an existing one */
attribute = papiAttributeListFind(*list, name);
if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL))
return (PAPI_CONFLICT); /* EXISTS */
if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) &&
(attribute->type != type))
return (PAPI_CONFLICT); /* TYPE CONFLICT */
/* if we don't have one, create it and add it to the list */
if ((attribute == NULL) &&
((attribute = papiAttributeAlloc(name, type)) != NULL))
list_append(list, attribute);
/* if we don't have one by now, it's most likely an alloc fail */
if (attribute == NULL)
return (PAPI_TEMPORARY_ERROR);
/*
* if we are replacing, clear any existing values, but don't free
* until after we have replaced the values, in case we are replacing
* a collection with a relocated version of the original collection.
*/
if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) {
values = attribute->values;
attribute->values = NULL;
}
attribute->type = type;
result = papiAttributeListAddValue(&attribute->values, type, value);
/* free old values if we replaced them */
if (values != NULL)
papiAttributeValuesFree(type, values);
return (result);
}
papi_status_t
papiAttributeListAddString(papi_attribute_t ***list, const int flags,
const char *name, const char *string)
{
papi_attribute_value_t v;
v.string = (char *)string;
return (papiAttributeListAdd(list, flags, name, PAPI_STRING, &v));
}
papi_status_t
papiAttributeListAddInteger(papi_attribute_t ***list, const int flags,
const char *name, const int integer)
{
papi_attribute_value_t v;
v.integer = integer;
return (papiAttributeListAdd(list, flags, name, PAPI_INTEGER, &v));
}
papi_status_t
papiAttributeListAddBoolean(papi_attribute_t ***list, const int flags,
const char *name, const char boolean)
{
papi_attribute_value_t v;
v.boolean = boolean;
return (papiAttributeListAdd(list, flags, name, PAPI_BOOLEAN, &v));
}
papi_status_t
papiAttributeListAddRange(papi_attribute_t ***list, const int flags,
const char *name, const int lower, const int upper)
{
papi_attribute_value_t v;
v.range.lower = lower;
v.range.upper = upper;
return (papiAttributeListAdd(list, flags, name, PAPI_RANGE, &v));
}
papi_status_t
papiAttributeListAddResolution(papi_attribute_t ***list, const int flags,
const char *name, const int xres, const int yres,
const papi_resolution_unit_t units)
{
papi_attribute_value_t v;
v.resolution.xres = xres;
v.resolution.yres = yres;
v.resolution.units = units;
return (papiAttributeListAdd(list, flags, name, PAPI_RESOLUTION, &v));
}
papi_status_t
papiAttributeListAddDatetime(papi_attribute_t ***list, const int flags,
const char *name, const time_t datetime)
{
papi_attribute_value_t v;
v.datetime = datetime;
return (papiAttributeListAdd(list, flags, name, PAPI_DATETIME, &v));
}
papi_status_t
papiAttributeListAddCollection(papi_attribute_t ***list, const int flags,
const char *name, const papi_attribute_t **collection)
{
papi_attribute_value_t v;
v.collection = (papi_attribute_t **)collection;
return (papiAttributeListAdd(list, flags, name, PAPI_COLLECTION, &v));
}
papi_status_t
papiAttributeListDelete(papi_attribute_t ***list, const char *name)
{
papi_attribute_t *attribute;
if ((list == NULL) || (name == NULL))
return (PAPI_BAD_ARGUMENT);
if ((attribute = papiAttributeListFind(*list, name)) == NULL)
return (PAPI_NOT_FOUND);
list_remove(*list, attribute);
papiAttributeFree(attribute);
return (PAPI_OK);
}
papi_attribute_t *
papiAttributeListFind(papi_attribute_t **list, const char *name)
{
if (list != NULL) {
int i;
for (i = 0; list[i] != NULL; i++)
if (strcasecmp(list[i]->name, name) == 0)
return ((papi_attribute_t *)list[i]);
}
return (NULL);
}
papi_attribute_t *
papiAttributeListGetNext(papi_attribute_t **list, void **iter)
{
papi_attribute_t **tmp, *result;
if ((list == NULL) && (iter == NULL))
return (NULL);
if (*iter == NULL)
*iter = list;
tmp = *iter;
result = *tmp;
*iter = ++tmp;
return (result);
}
papi_status_t
papiAttributeListGetValue(papi_attribute_t **list, void **iter,
const char *name, papi_attribute_value_type_t type,
papi_attribute_value_t **value)
{
papi_attribute_value_t **tmp;
void *fodder = NULL;
if ((list == NULL) || ((name == NULL) && (iter == NULL)) ||
(value == NULL))
return (PAPI_BAD_ARGUMENT);
if (iter == NULL)
iter = &fodder;
if ((iter == NULL) || (*iter == NULL)) {
papi_attribute_t *attr = papiAttributeListFind(list, name);
if (attr == NULL)
return (PAPI_NOT_FOUND);
if (attr->type != type)
return (PAPI_NOT_POSSIBLE);
tmp = attr->values;
} else
tmp = *iter;
if (tmp == NULL)
return (PAPI_NOT_FOUND);
*value = *tmp;
*iter = ++tmp;
if (*value == NULL)
return (PAPI_GONE);
return (PAPI_OK);
}
papi_status_t
papiAttributeListGetString(papi_attribute_t **list, void **iter,
const char *name, char **vptr)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if (vptr == NULL)
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_STRING, &value);
if (status == PAPI_OK)
*vptr = value->string;
return (status);
}
papi_status_t
papiAttributeListGetInteger(papi_attribute_t **list, void **iter,
const char *name, int *vptr)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if (vptr == NULL)
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_INTEGER, &value);
if (status == PAPI_OK)
*vptr = value->integer;
return (status);
}
papi_status_t
papiAttributeListGetBoolean(papi_attribute_t **list, void **iter,
const char *name, char *vptr)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if (vptr == NULL)
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_BOOLEAN, &value);
if (status == PAPI_OK)
*vptr = value->boolean;
return (status);
}
papi_status_t
papiAttributeListGetRange(papi_attribute_t **list, void **iter,
const char *name, int *min, int *max)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if ((min == NULL) || (max == NULL))
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_RANGE, &value);
if (status == PAPI_OK) {
*min = value->range.lower;
*max = value->range.upper;
}
return (status);
}
papi_status_t
papiAttributeListGetResolution(papi_attribute_t **list, void **iter,
const char *name, int *x, int *y,
papi_resolution_unit_t *units)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if ((x == NULL) || (y == NULL) || (units == NULL))
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_RESOLUTION, &value);
if (status == PAPI_OK) {
*x = value->resolution.xres;
*y = value->resolution.yres;
*units = value->resolution.units;
}
return (status);
}
papi_status_t
papiAttributeListGetDatetime(papi_attribute_t **list, void **iter,
const char *name, time_t *dt)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if (dt == NULL)
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_DATETIME, &value);
if (status == PAPI_OK) {
*dt = value->datetime;
}
return (status);
}
papi_status_t
papiAttributeListGetCollection(papi_attribute_t **list, void **iter,
const char *name, papi_attribute_t ***collection)
{
papi_status_t status;
papi_attribute_value_t *value = NULL;
if (collection == NULL)
return (PAPI_BAD_ARGUMENT);
status = papiAttributeListGetValue(list, iter, name,
PAPI_COLLECTION, &value);
if (status == PAPI_OK) {
*collection = value->collection;
}
return (status);
}
/*
* *****************************************************************************
*
* Description: The given string contains one or more attributes, in the
* following form:
* "aaaa=true bbbbb=1 ccccc=abcd"
* extract the next attribute from that string; the 'next'
* parameter should be set to zero to extract the first attribute
* in the string.
*
* *****************************************************************************
*/
static char *
_getNextAttr(const char *string, int *next)
{
char *result = NULL;
char *start = (char *)string + *next;
char *nl = NULL;
char *sp = NULL;
char *tab = NULL;
char *val = NULL;
int len = 0;
if ((string != NULL) && (*start != '\0'))
{
while ((*start == ' ') || (*start == '\t') || (*start == '\n'))
{
start++;
}
nl = strchr(start, '\n');
sp = strchr(start, ' ');
tab = strchr(start, '\t');
val = strchr(start, '=');
if ((val != NULL) && ((val[1] == '"') || (val[1] == '\'')))
{
val = strchr(&val[2], val[1]);
if (val != NULL)
{
nl = strchr(&val[1], '\n');
sp = strchr(&val[1], ' ');
tab = strchr(&val[1], '\t');
}
}
if ((nl != NULL) &&
((sp == NULL) || ((sp != NULL) && (nl < sp))) &&
((tab == NULL) || ((tab != NULL) && (nl < tab))))
{
len = nl-start;
}
else
if ((sp != NULL) && (tab != NULL) && (sp > tab))
{
len = tab-start;
}
else
if ((sp != NULL) && (sp != NULL))
{
len = sp-start;
}
else
if ((tab != NULL) && (tab != NULL))
{
len = tab-start;
}
if (len == 0)
{
len = strlen(start);
}
if (len > 0)
{
result = (char *)malloc(len+1);
if (result != NULL)
{
strncpy(result, start, len);
result[len] = '\0';
*next = (start-string)+len;
}
}
}
return (result);
} /* _getNextAttr() */
/*
* *****************************************************************************
*
* Description: Parse the given attribute string value and transform it into
* the papi_attribute_value_t in the papi_attribute_t structure.
*
* *****************************************************************************
*/
static papi_status_t
_parseAttrValue(char *value, papi_attribute_t *attr)
{
papi_status_t result = PAPI_OK;
int len = 0;
int i = 0;
char *papiString = NULL;
char *tmp1 = NULL;
char *tmp2 = NULL;
char *tmp3 = NULL;
papi_attribute_value_t **avalues = NULL;
avalues = malloc(sizeof (papi_attribute_value_t *) * 2);
if (avalues == NULL)
{
result = PAPI_TEMPORARY_ERROR;
return (result);
}
avalues[0] = malloc(sizeof (papi_attribute_value_t));
avalues[1] = NULL;
if (avalues[0] == NULL)
{
free(avalues);
result = PAPI_TEMPORARY_ERROR;
return (result);
}
/*
* TODO - need to sort out 'resolution', 'dateandtime' & 'collection' values
*/
if ((value != NULL) && (strlen(value) > 0) && (attr != NULL))
{
len = strlen(value);
if ((len >= 2) &&
(((value[0] == '"') && (value[len-1] == '"')) ||
((value[0] == '\'') && (value[len-1] == '\''))))
{
/* string value */
attr->type = PAPI_STRING;
papiString = strdup(value+1);
if (papiString != NULL)
{
papiString[strlen(papiString)-1] = '\0';
avalues[0]->string = papiString;
}
else
{
result = PAPI_TEMPORARY_ERROR;
}
}
else
if ((strcasecmp(value, "true") == 0) ||
(strcasecmp(value, "YES") == 0))
{
/* boolean = true */
attr->type = PAPI_BOOLEAN;
avalues[0]->boolean = PAPI_TRUE;
}
else
if ((strcasecmp(value, "false") == 0) ||
(strcasecmp(value, "NO") == 0))
{
/* boolean = false */
attr->type = PAPI_BOOLEAN;
avalues[0]->boolean = PAPI_FALSE;
}
else
{
/* is value an integer or a range? */
i = 0;
attr->type = PAPI_INTEGER;
tmp1 = strdup(value);
while (((value[i] >= '0') && (value[i] <= '9')) ||
(value[i] == '-'))
{
if (value[i] == '-')
{
tmp1[i] = '\0';
tmp2 = &tmp1[i+1];
attr->type = PAPI_RANGE;
}
i++;
}
if (strlen(value) == i)
{
if (attr->type == PAPI_RANGE)
{
avalues[0]->range.lower = atoi(tmp1);
avalues[0]->range.upper = atoi(tmp2);
}
else
{
avalues[0]->integer = atoi(value);
}
}
else
{
/* is value a resolution? */
i = 0;
attr->type = PAPI_INTEGER;
tmp1 = strdup(value);
while (((value[i] >= '0') &&
(value[i] <= '9')) ||
(value[i] == 'x'))
{
if (value[i] == 'x')
{
tmp1[i] = '\0';
if (attr->type == PAPI_INTEGER)
{
tmp2 = &tmp1[i+1];
attr->type =
PAPI_RESOLUTION;
}
else
{
tmp3 = &tmp1[i+1];
}
}
i++;
}
if (strlen(value) == i)
{
if (attr->type == PAPI_RESOLUTION)
{
avalues[0]->resolution.xres =
atoi(tmp1);
avalues[0]->resolution.yres =
atoi(tmp2);
if (tmp3 != NULL)
{
avalues[0]->
resolution.units =
atoi(tmp3);
}
else
{
avalues[0]->
resolution.units =
0;
}
}
}
if (attr->type != PAPI_RESOLUTION)
{
attr->type = PAPI_STRING;
avalues[0]->string = strdup(value);
if (avalues[0]->string == NULL)
{
result = PAPI_TEMPORARY_ERROR;
}
}
}
free(tmp1);
}
}
else
{
result = PAPI_BAD_ARGUMENT;
}
if (result != PAPI_OK)
{
i = 0;
while (avalues[i] != NULL)
{
free(avalues[i]);
i++;
}
free(avalues);
}
else
{
attr->values = avalues;
}
return (result);
} /* _parseAttrValue() */
/*
* *****************************************************************************
*
* Description: Parse the given attribute string and transform it into the
* papi_attribute_t structure.
*
* *****************************************************************************
*/
static papi_status_t
_parseAttributeString(char *attrString, papi_attribute_t *attr)
{
papi_status_t result = PAPI_OK;
char *string = NULL;
char *p = NULL;
papi_attribute_value_t **avalues = NULL;
if ((attrString != NULL) && (strlen(attrString) >= 3) && (attr != NULL))
{
attr->name = NULL;
string = strdup(attrString);
if (string != NULL)
{
p = strchr(string, '=');
if (p != NULL)
{
*p = '\0';
attr->name = string;
p++; /* pointer to value */
result = _parseAttrValue(p, attr);
}
else
{
/* boolean - no value so assume 'true' */
attr->name = string;
attr->type = PAPI_BOOLEAN;
avalues =
malloc(
sizeof (papi_attribute_value_t *) * 2);
if (avalues == NULL)
{
result = PAPI_TEMPORARY_ERROR;
}
else
{
avalues[0] =
malloc(
sizeof (papi_attribute_value_t));
avalues[1] = NULL;
if (avalues[0] == NULL)
{
free(avalues);
result = PAPI_TEMPORARY_ERROR;
}
else
{
avalues[0]->boolean =
PAPI_TRUE;
attr->values = avalues;
}
}
}
}
}
else
{
result = PAPI_BAD_ARGUMENT;
}
return (result);
} /* _parseAttributeString() */
papi_status_t
papiAttributeListFromString(papi_attribute_t ***attrs,
const int flags, const char *string)
{
papi_status_t result = PAPI_OK;
int next = 0;
char *attrString = NULL;
papi_attribute_t attr;
if ((attrs != NULL) && (string != NULL) &&
((flags &
~(PAPI_ATTR_APPEND+PAPI_ATTR_REPLACE+PAPI_ATTR_EXCL)) == 0)) {
attrString = _getNextAttr(string, &next);
while ((result == PAPI_OK) && (attrString != NULL)) {
printf("papiAttributeListFromString() attr='%s'\n", attrString);
result = _parseAttributeString(attrString, &attr);
if ((result == PAPI_OK) && (attr.name != NULL)) {
/* add this attribute to the list */
if ((attr.values != NULL) &&
(attr.values[0] != NULL)) {
result = papiAttributeListAdd(
attrs, PAPI_ATTR_APPEND,
attr.name, attr.type,
attr.values[0]);
free(attr.values[0]);
free(attr.values);
} else {
result = PAPI_TEMPORARY_ERROR;
}
}
free(attrString);
attrString = _getNextAttr(string, &next);
}
}
else
{
result = PAPI_BAD_ARGUMENT;
}
return (result);
}
papi_status_t
papiAttributeListToString(const papi_attribute_t **attrs,
const char *delim, char *buffer, const size_t buflen)
{
return (PAPI_OPERATION_NOT_SUPPORTED);
}
/* for debugging, not part of the public API */
static char *
typeString(papi_attribute_value_type_t type)
{
switch (type) {
case PAPI_STRING:
return ("string");
case PAPI_INTEGER:
return ("integer");
case PAPI_BOOLEAN:
return ("boolean");
case PAPI_RANGE:
return ("range");
case PAPI_RESOLUTION:
return ("resolution");
case PAPI_DATETIME:
return ("datetime");
case PAPI_COLLECTION:
return ("collection");
}
return ("unknown");
}
void papiAttributeListPrint(FILE *fp, char *prefix, papi_attribute_t **list);
void
papiAttributePrint(FILE *fp, char *prefix, papi_attribute_t *attribute)
{
if (attribute != NULL) {
char *name = attribute->name;
if (prefix == NULL)
prefix = "";
/*
* fprintf(fp, "%s'%s' (%s) =\n", prefix, (name ? name : "(NULL)"),
* typeString(attribute->type));
*/
if (attribute->values != NULL) {
papi_attribute_value_t **values = attribute->values;
int i;
for (i = 0; values[i] != NULL; i++) {
fprintf(fp, "%s=", (name ? name : "(NULL)"));
/*
* if (attribute->type != PAPI_COLLECTION)
* fprintf(fp, "%s\t", prefix);
*/
switch (attribute->type) {
case PAPI_STRING:
if ((strchr(values[i]->string, ' ')
!= NULL) ||
(strchr(values[i]->string, '\t')
!= NULL)) {
/* quote the string */
fprintf(fp, "\"%s\"",
values[i]->string);
} else {
fprintf(fp, "%s",
values[i]->string);
}
break;
case PAPI_INTEGER:
fprintf(fp, "%d", values[i]->integer);
break;
case PAPI_BOOLEAN:
fprintf(fp, "%s", (values[i]->boolean ?
"true" : "false"));
break;
case PAPI_RANGE:
fprintf(fp, "%d-%d",
values[i]->range.lower,
values[i]->range.upper);
break;
case PAPI_RESOLUTION:
fprintf(fp, "%dx%d",
values[i]->resolution.xres,
values[i]->resolution.yres);
break;
case PAPI_DATETIME: {
struct tm *tm;
tm = localtime(&values[i]->datetime);
if (tm != NULL) {
char buf[64];
strftime(buf, sizeof (buf),
"%C", tm);
fprintf(fp, "%s", buf);
}}
break;
case PAPI_COLLECTION: {
char s[64];
snprintf(s, sizeof (s), "%s\t", prefix);
papiAttributeListPrint(fp, s,
values[i]->collection);
}
break;
default:
fprintf(fp, "unknown");
}
if (attribute->type != PAPI_COLLECTION)
fprintf(fp, "\n");
}
}
}
}
void
papiAttributeListPrint(FILE *fp, char *prefix, papi_attribute_t **list)
{
if (list != NULL) {
int i;
for (i = 0; list[i] != NULL; i++)
papiAttributePrint(fp, prefix, list[i]);
}
}