12264Sjacobs /*
22264Sjacobs  * CDDL HEADER START
32264Sjacobs  *
42264Sjacobs  * The contents of this file are subject to the terms of the
52264Sjacobs  * Common Development and Distribution License (the "License").
62264Sjacobs  * You may not use this file except in compliance with the License.
72264Sjacobs  *
82264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs  * or http://www.opensolaris.org/os/licensing.
102264Sjacobs  * See the License for the specific language governing permissions
112264Sjacobs  * and limitations under the License.
122264Sjacobs  *
132264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs  *
192264Sjacobs  * CDDL HEADER END
202264Sjacobs  */
212264Sjacobs 
222264Sjacobs /*
232264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
242264Sjacobs  * Use is subject to license terms.
252264Sjacobs  *
262264Sjacobs  */
272264Sjacobs 
282264Sjacobs /* $Id: attribute.c 157 2006-04-26 15:07:55Z ktou $ */
292264Sjacobs 
302264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
312264Sjacobs 
322264Sjacobs /*LINTLIBRARY*/
332264Sjacobs 
342264Sjacobs #include <stdio.h>
352264Sjacobs #include <stdlib.h>
362264Sjacobs #include <stdarg.h>
372264Sjacobs #include <string.h>
382264Sjacobs #include <alloca.h>
392264Sjacobs #include <papi.h>
402264Sjacobs 
412264Sjacobs static void papiAttributeFree(papi_attribute_t *attribute);
422264Sjacobs 
432264Sjacobs static void
442264Sjacobs papiAttributeValueFree(papi_attribute_value_type_t type,
452264Sjacobs 		    papi_attribute_value_t *value)
462264Sjacobs {
472264Sjacobs 	if (value != NULL) {
482264Sjacobs 		switch (type) {
492264Sjacobs 		case PAPI_STRING:
502264Sjacobs 			if (value->string != NULL)
512264Sjacobs 				free(value->string);
522264Sjacobs 			break;
532264Sjacobs 		case PAPI_COLLECTION:
542264Sjacobs 			if (value->collection != NULL) {
552264Sjacobs 				int i;
562264Sjacobs 
572264Sjacobs 				for (i = 0; value->collection[i] != NULL; i++)
582264Sjacobs 					papiAttributeFree(value->collection[i]);
592264Sjacobs 
602264Sjacobs 				free(value->collection);
612264Sjacobs 			}
622264Sjacobs 			break;
632264Sjacobs 		default: /* don't need to free anything extra */
642264Sjacobs 			break;
652264Sjacobs 		}
662264Sjacobs 
672264Sjacobs 		free(value);
682264Sjacobs 	}
692264Sjacobs }
702264Sjacobs 
712264Sjacobs static void
722264Sjacobs papiAttributeValuesFree(papi_attribute_value_type_t type,
732264Sjacobs 		    papi_attribute_value_t **values)
742264Sjacobs {
752264Sjacobs 	if (values != NULL) {
762264Sjacobs 		int i;
772264Sjacobs 
782264Sjacobs 		for (i = 0; values[i] != NULL; i++)
792264Sjacobs 			papiAttributeValueFree(type, values[i]);
802264Sjacobs 
812264Sjacobs 		free(values);
822264Sjacobs 	}
832264Sjacobs }
842264Sjacobs 
852264Sjacobs static void
862264Sjacobs papiAttributeFree(papi_attribute_t *attribute)
872264Sjacobs {
882264Sjacobs 	if (attribute != NULL) {
892264Sjacobs 		if (attribute->name != NULL)
902264Sjacobs 			free(attribute->name);
912264Sjacobs 		if (attribute->values != NULL)
922264Sjacobs 			papiAttributeValuesFree(attribute->type,
932264Sjacobs 						attribute->values);
942264Sjacobs 			free(attribute);
952264Sjacobs 	}
962264Sjacobs }
972264Sjacobs 
982264Sjacobs void
992264Sjacobs papiAttributeListFree(papi_attribute_t **list)
1002264Sjacobs {
1012264Sjacobs 	if (list != NULL) {
1022264Sjacobs 		int i;
1032264Sjacobs 
1042264Sjacobs 		for (i = 0; list[i] != NULL; i++)
1052264Sjacobs 			papiAttributeFree(list[i]);
1062264Sjacobs 
1072264Sjacobs 		free(list);
1082264Sjacobs 	}
1092264Sjacobs }
1102264Sjacobs 
1112264Sjacobs static papi_attribute_t **
1122264Sjacobs collection_dup(papi_attribute_t **collection)
1132264Sjacobs {
1142264Sjacobs 	papi_attribute_t **result = NULL;
1152264Sjacobs 
1162264Sjacobs 	/* allows a NULL collection that is "empty" or "no value" */
1172264Sjacobs 	if (collection != NULL) {
1182264Sjacobs 		papi_status_t status = PAPI_OK;
1192264Sjacobs 		int i;
1202264Sjacobs 
1212264Sjacobs 		for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK));
1222264Sjacobs 		     i++) {
1232264Sjacobs 			papi_attribute_t *a = collection[i];
1242264Sjacobs 
1252264Sjacobs 			status = papiAttributeListAddValue(&result,
1262264Sjacobs 					PAPI_ATTR_APPEND, a->name, a->type,
1272264Sjacobs 					NULL);
1282264Sjacobs 			if ((status == PAPI_OK) && (a->values != NULL)) {
1292264Sjacobs 				int j;
1302264Sjacobs 
1312264Sjacobs 				for (j = 0; ((a->values[j] != NULL) &&
1322264Sjacobs 					     (status == PAPI_OK)); j++)
1332264Sjacobs 					status = papiAttributeListAddValue(
1342264Sjacobs 							&result,
1352264Sjacobs 							PAPI_ATTR_APPEND,
1362264Sjacobs 							a->name, a->type,
1372264Sjacobs 							a->values[j]);
1382264Sjacobs 			}
1392264Sjacobs 		}
1402264Sjacobs 		if (status != PAPI_OK) {
1412264Sjacobs 			papiAttributeListFree(result);
1422264Sjacobs 			result = NULL;
1432264Sjacobs 		}
1442264Sjacobs 	}
1452264Sjacobs 
1462264Sjacobs 	return (result);
1472264Sjacobs }
1482264Sjacobs 
1492264Sjacobs static papi_attribute_value_t *
1502264Sjacobs papiAttributeValueDup(papi_attribute_value_type_t type,
1512264Sjacobs 		papi_attribute_value_t *v)
1522264Sjacobs {
1532264Sjacobs 	papi_attribute_value_t *result = NULL;
1542264Sjacobs 
1552264Sjacobs 	if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) {
1562264Sjacobs 		switch (type) {
1572264Sjacobs 		case PAPI_STRING:
1582264Sjacobs 			if (v->string == NULL) {
1592264Sjacobs 				free(result);
1602264Sjacobs 				result = NULL;
1612264Sjacobs 			} else
1622264Sjacobs 				result->string = strdup(v->string);
1632264Sjacobs 			break;
1642264Sjacobs 		case PAPI_INTEGER:
1652264Sjacobs 			result->integer = v->integer;
1662264Sjacobs 			break;
1672264Sjacobs 		case PAPI_BOOLEAN:
1682264Sjacobs 			result->boolean = v->boolean;
1692264Sjacobs 			break;
1702264Sjacobs 		case PAPI_RANGE:
1712264Sjacobs 			result->range.lower = v->range.lower;
1722264Sjacobs 			result->range.upper = v->range.upper;
1732264Sjacobs 			break;
1742264Sjacobs 		case PAPI_RESOLUTION:
1752264Sjacobs 			result->resolution.xres = v->resolution.xres;
1762264Sjacobs 			result->resolution.yres = v->resolution.yres;
1772264Sjacobs 			result->resolution.units = v->resolution.units;
1782264Sjacobs 			break;
1792264Sjacobs 		case PAPI_DATETIME:
1802264Sjacobs 			result->datetime = v->datetime;
1812264Sjacobs 			break;
1822264Sjacobs 		case PAPI_COLLECTION:
1832264Sjacobs 			result->collection = collection_dup(v->collection);
1842264Sjacobs 			break;
1852264Sjacobs 		case PAPI_METADATA:
1862264Sjacobs 			result->metadata = v->metadata;
1872264Sjacobs 			break;
1882264Sjacobs 		default:	/* unknown type, fail to duplicate */
1892264Sjacobs 			free(result);
1902264Sjacobs 			result = NULL;
1912264Sjacobs 		}
1922264Sjacobs 	}
1932264Sjacobs 
1942264Sjacobs 	return (result);
1952264Sjacobs }
1962264Sjacobs 
1972264Sjacobs static papi_attribute_t *
1982264Sjacobs papiAttributeAlloc(char *name, papi_attribute_value_type_t type)
1992264Sjacobs {
2002264Sjacobs 	papi_attribute_t *result = NULL;
2012264Sjacobs 
2022264Sjacobs 	if ((result = calloc(1, sizeof (*result))) != NULL) {
2032264Sjacobs 		result->name = strdup(name);
2042264Sjacobs 		result->type = type;
2052264Sjacobs 	}
2062264Sjacobs 
2072264Sjacobs 	return (result);
2082264Sjacobs }
2092264Sjacobs 
2102264Sjacobs static papi_status_t
2112264Sjacobs papiAttributeListAppendValue(papi_attribute_value_t ***values,
2122264Sjacobs 		papi_attribute_value_type_t type,
2132264Sjacobs 		papi_attribute_value_t *value)
2142264Sjacobs {
2152264Sjacobs 
2162264Sjacobs 	if (values == NULL)
2172264Sjacobs 		return (PAPI_BAD_ARGUMENT);
2182264Sjacobs 
2192264Sjacobs 	if (value != NULL) {	/* this allows "empty" attributes */
2202264Sjacobs 		papi_attribute_value_t *tmp = NULL;
2212264Sjacobs 
2222264Sjacobs 		if ((tmp = papiAttributeValueDup(type, value)) == NULL)
2232264Sjacobs 			return (PAPI_TEMPORARY_ERROR);
2242264Sjacobs 
2252264Sjacobs 		list_append(values, tmp);
2262264Sjacobs 	}
2272264Sjacobs 
2282264Sjacobs 	return (PAPI_OK);
2292264Sjacobs }
2302264Sjacobs 
2312264Sjacobs papi_status_t
2322264Sjacobs papiAttributeListAddValue(papi_attribute_t ***list, int flgs,
2332264Sjacobs 		char *name, papi_attribute_value_type_t type,
2342264Sjacobs 		papi_attribute_value_t *value)
2352264Sjacobs {
2362264Sjacobs 	papi_status_t result;
2372264Sjacobs 	int flags = flgs;
2382264Sjacobs 	papi_attribute_t *attribute = NULL;
2392264Sjacobs 	papi_attribute_value_t **values = NULL;
2402264Sjacobs 
2412264Sjacobs 	if ((list == NULL) || (name == NULL))
2422264Sjacobs 		return (PAPI_BAD_ARGUMENT);
2432264Sjacobs 
2442264Sjacobs 	if ((type == PAPI_RANGE) && (value != NULL) &&
2452264Sjacobs 	    (value->range.lower > value->range.upper))
2462264Sjacobs 		return (PAPI_BAD_ARGUMENT);	/* RANGE must have min <= max */
2472264Sjacobs 
2482264Sjacobs 	if (flags == 0) /* if it wasn't set, set a default behaviour */
2492264Sjacobs 		flags = PAPI_ATTR_APPEND;
2502264Sjacobs 
2512264Sjacobs 	/* look for an existing one */
2522264Sjacobs 	attribute = papiAttributeListFind(*list, name);
2532264Sjacobs 
2542264Sjacobs 	if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL))
2552264Sjacobs 		return (PAPI_CONFLICT); /* EXISTS */
2562264Sjacobs 
2572264Sjacobs 	if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) &&
2582264Sjacobs 	    (attribute->type != type))
2592264Sjacobs 		return (PAPI_CONFLICT); /* TYPE CONFLICT */
2602264Sjacobs 
2612264Sjacobs 	/* if we don't have one, create it and add it to the list */
2622264Sjacobs 	if ((attribute == NULL) &&
2632264Sjacobs 	    ((attribute = papiAttributeAlloc(name, type)) != NULL))
2642264Sjacobs 		list_append(list, attribute);
2652264Sjacobs 
2662264Sjacobs 	/* if we don't have one by now, it's most likely an alloc fail */
2672264Sjacobs 	if (attribute == NULL)
2682264Sjacobs 		return (PAPI_TEMPORARY_ERROR);
2692264Sjacobs 
2702264Sjacobs 	/*
2712264Sjacobs 	 * if we are replacing, clear any existing values, but don't free
2722264Sjacobs 	 * until after we have replaced the values, in case we are replacing
2732264Sjacobs 	 * a collection with a relocated version of the original collection.
2742264Sjacobs 	 */
2752264Sjacobs 	if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) {
2762264Sjacobs 		values = attribute->values;
2772264Sjacobs 		attribute->values = NULL;
2782264Sjacobs 	}
2792264Sjacobs 
2802264Sjacobs 	attribute->type = type;
2812264Sjacobs 
2822264Sjacobs 	result = papiAttributeListAppendValue(&attribute->values, type, value);
2832264Sjacobs 
2842264Sjacobs 	/* free old values if we replaced them */
2852264Sjacobs 	if (values != NULL)
2862264Sjacobs 		papiAttributeValuesFree(type, values);
2872264Sjacobs 
2882264Sjacobs 	return (result);
2892264Sjacobs }
2902264Sjacobs 
2912264Sjacobs papi_status_t
2922264Sjacobs papiAttributeListAddString(papi_attribute_t ***list, int flags,
2932264Sjacobs 			char *name, char *string)
2942264Sjacobs {
2952264Sjacobs 	papi_attribute_value_t v;
2962264Sjacobs 
2972264Sjacobs 	v.string = (char *)string;
2982264Sjacobs 	return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v));
2992264Sjacobs }
3002264Sjacobs 
3012264Sjacobs papi_status_t
3022264Sjacobs papiAttributeListAddInteger(papi_attribute_t ***list, int flags,
3032264Sjacobs 			char *name, int integer)
3042264Sjacobs {
3052264Sjacobs 	papi_attribute_value_t v;
3062264Sjacobs 
3072264Sjacobs 	v.integer = integer;
3082264Sjacobs 	return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v));
3092264Sjacobs }
3102264Sjacobs 
3112264Sjacobs papi_status_t
3122264Sjacobs papiAttributeListAddBoolean(papi_attribute_t ***list, int flags,
3132264Sjacobs 			char *name, char boolean)
3142264Sjacobs {
3152264Sjacobs 	papi_attribute_value_t v;
3162264Sjacobs 
3172264Sjacobs 	v.boolean = boolean;
3182264Sjacobs 	return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v));
3192264Sjacobs }
3202264Sjacobs 
3212264Sjacobs papi_status_t
3222264Sjacobs papiAttributeListAddRange(papi_attribute_t ***list, int flags,
3232264Sjacobs 			char *name, int lower, int upper)
3242264Sjacobs {
3252264Sjacobs 	papi_attribute_value_t v;
3262264Sjacobs 
3272264Sjacobs 	v.range.lower = lower;
3282264Sjacobs 	v.range.upper = upper;
3292264Sjacobs 	return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v));
3302264Sjacobs }
3312264Sjacobs 
3322264Sjacobs papi_status_t
3332264Sjacobs papiAttributeListAddResolution(papi_attribute_t ***list, int flags,
3342264Sjacobs 			char *name, int xres, int yres,
3352264Sjacobs 			papi_resolution_unit_t units)
3362264Sjacobs {
3372264Sjacobs 	papi_attribute_value_t v;
3382264Sjacobs 
3392264Sjacobs 	v.resolution.xres = xres;
3402264Sjacobs 	v.resolution.yres = yres;
3412264Sjacobs 	v.resolution.units = units;
3422264Sjacobs 	return (papiAttributeListAddValue(list, flags, name,
3432264Sjacobs 				PAPI_RESOLUTION, &v));
3442264Sjacobs }
3452264Sjacobs 
3462264Sjacobs papi_status_t
3472264Sjacobs papiAttributeListAddDatetime(papi_attribute_t ***list, int flags,
3482264Sjacobs 			char *name, time_t datetime)
3492264Sjacobs {
3502264Sjacobs 	papi_attribute_value_t v;
3512264Sjacobs 
3522264Sjacobs 	v.datetime = datetime;
3532264Sjacobs 	return (papiAttributeListAddValue(list, flags, name,
3542264Sjacobs 				PAPI_DATETIME, &v));
3552264Sjacobs }
3562264Sjacobs 
3572264Sjacobs papi_status_t
3582264Sjacobs papiAttributeListAddCollection(papi_attribute_t ***list, int flags,
3592264Sjacobs 			char *name, papi_attribute_t **collection)
3602264Sjacobs {
3612264Sjacobs 	papi_attribute_value_t v;
3622264Sjacobs 
3632264Sjacobs 	v.collection = (papi_attribute_t **)collection;
3642264Sjacobs 	return (papiAttributeListAddValue(list, flags, name,
3652264Sjacobs 				PAPI_COLLECTION, &v));
3662264Sjacobs }
3672264Sjacobs 
3682264Sjacobs papi_status_t
3692264Sjacobs papiAttributeListAddMetadata(papi_attribute_t ***list, int flags,
3702264Sjacobs 			char *name, papi_metadata_t metadata)
3712264Sjacobs {
3722264Sjacobs 	papi_attribute_value_t v;
3732264Sjacobs 
3742264Sjacobs 	v.metadata = metadata;
3752264Sjacobs 	return (papiAttributeListAddValue(list, flags, name,
3762264Sjacobs 				PAPI_METADATA, &v));
3772264Sjacobs }
3782264Sjacobs 
3792264Sjacobs papi_status_t
3802264Sjacobs papiAttributeListDelete(papi_attribute_t ***list, char *name)
3812264Sjacobs {
3822264Sjacobs 	papi_attribute_t *attribute;
3832264Sjacobs 
3842264Sjacobs 	if ((list == NULL) || (name == NULL))
3852264Sjacobs 		return (PAPI_BAD_ARGUMENT);
3862264Sjacobs 
3872264Sjacobs 	if ((attribute = papiAttributeListFind(*list, name)) == NULL)
3882264Sjacobs 		return (PAPI_NOT_FOUND);
3892264Sjacobs 
390*3125Sjacobs 	list_remove(list, attribute);
3912264Sjacobs 	papiAttributeFree(attribute);
3922264Sjacobs 
3932264Sjacobs 	return (PAPI_OK);
3942264Sjacobs }
3952264Sjacobs 
3962264Sjacobs papi_attribute_t *
3972264Sjacobs papiAttributeListFind(papi_attribute_t **list, char *name)
3982264Sjacobs {
3992264Sjacobs 	int i;
4002264Sjacobs 	if ((list == NULL) || (name == NULL))
4012264Sjacobs 		return (NULL);
4022264Sjacobs 
4032264Sjacobs 	for (i = 0; list[i] != NULL; i++)
4042264Sjacobs 		if (strcasecmp(list[i]->name, name) == 0)
4052264Sjacobs 			return ((papi_attribute_t *)list[i]);
4062264Sjacobs 
4072264Sjacobs 	return (NULL);
4082264Sjacobs }
4092264Sjacobs 
4102264Sjacobs papi_attribute_t *
4112264Sjacobs papiAttributeListGetNext(papi_attribute_t **list, void **iter)
4122264Sjacobs {
4132264Sjacobs 	papi_attribute_t **tmp, *result;
4142264Sjacobs 
4152264Sjacobs 	if ((list == NULL) && (iter == NULL))
4162264Sjacobs 		return (NULL);
4172264Sjacobs 
4182264Sjacobs 	if (*iter == NULL)
4192264Sjacobs 		*iter = list;
4202264Sjacobs 
4212264Sjacobs 	tmp = *iter;
4222264Sjacobs 	result = *tmp;
4232264Sjacobs 	*iter = ++tmp;
4242264Sjacobs 
4252264Sjacobs 	return (result);
4262264Sjacobs }
4272264Sjacobs 
4282264Sjacobs papi_status_t
4292264Sjacobs papiAttributeListGetValue(papi_attribute_t **list, void **iter,
4302264Sjacobs 			char *name, papi_attribute_value_type_t type,
4312264Sjacobs 			papi_attribute_value_t **value)
4322264Sjacobs {
4332264Sjacobs 	papi_attribute_value_t **tmp;
4342264Sjacobs 	void *fodder = NULL;
4352264Sjacobs 
4362264Sjacobs 	if ((list == NULL) || ((name == NULL) && (iter == NULL)) ||
4372264Sjacobs 	    (value == NULL))
4382264Sjacobs 		return (PAPI_BAD_ARGUMENT);
4392264Sjacobs 
4402264Sjacobs 	if (iter == NULL)
4412264Sjacobs 		iter = &fodder;
4422264Sjacobs 
4432264Sjacobs 	if ((iter == NULL) || (*iter == NULL)) {
4442264Sjacobs 		papi_attribute_t *attr = papiAttributeListFind(list, name);
4452264Sjacobs 
4462264Sjacobs 		if (attr == NULL)
4472264Sjacobs 			return (PAPI_NOT_FOUND);
4482264Sjacobs 
4492264Sjacobs 		if (attr->type != type)
4502264Sjacobs 			return (PAPI_NOT_POSSIBLE);
4512264Sjacobs 
4522264Sjacobs 		tmp = attr->values;
4532264Sjacobs 	} else
4542264Sjacobs 		tmp = *iter;
4552264Sjacobs 
4562264Sjacobs 	if (tmp == NULL)
4572264Sjacobs 		return (PAPI_NOT_FOUND);
4582264Sjacobs 
4592264Sjacobs 	*value = *tmp;
4602264Sjacobs 	*iter =  ++tmp;
4612264Sjacobs 
4622264Sjacobs 	if (*value == NULL)
4632264Sjacobs 		return (PAPI_GONE);
4642264Sjacobs 
4652264Sjacobs 	return (PAPI_OK);
4662264Sjacobs }
4672264Sjacobs 
4682264Sjacobs papi_status_t
4692264Sjacobs papiAttributeListGetString(papi_attribute_t **list, void **iter,
4702264Sjacobs 			char *name, char **vptr)
4712264Sjacobs {
4722264Sjacobs 	papi_status_t status;
4732264Sjacobs 	papi_attribute_value_t *value = NULL;
4742264Sjacobs 
4752264Sjacobs 	if (vptr == NULL)
4762264Sjacobs 		return (PAPI_BAD_ARGUMENT);
4772264Sjacobs 
4782264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
4792264Sjacobs 				PAPI_STRING, &value);
4802264Sjacobs 	if (status == PAPI_OK)
4812264Sjacobs 		*vptr = value->string;
4822264Sjacobs 
4832264Sjacobs 	return (status);
4842264Sjacobs }
4852264Sjacobs 
4862264Sjacobs papi_status_t
4872264Sjacobs papiAttributeListGetInteger(papi_attribute_t **list, void **iter,
4882264Sjacobs 			char *name, int *vptr)
4892264Sjacobs {
4902264Sjacobs 	papi_status_t status;
4912264Sjacobs 	papi_attribute_value_t *value = NULL;
4922264Sjacobs 
4932264Sjacobs 	if (vptr == NULL)
4942264Sjacobs 		return (PAPI_BAD_ARGUMENT);
4952264Sjacobs 
4962264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
4972264Sjacobs 				PAPI_INTEGER, &value);
4982264Sjacobs 	if (status == PAPI_OK)
4992264Sjacobs 		*vptr = value->integer;
5002264Sjacobs 
5012264Sjacobs 	return (status);
5022264Sjacobs }
5032264Sjacobs 
5042264Sjacobs papi_status_t
5052264Sjacobs papiAttributeListGetBoolean(papi_attribute_t **list, void **iter,
5062264Sjacobs 			char *name, char *vptr)
5072264Sjacobs {
5082264Sjacobs 	papi_status_t status;
5092264Sjacobs 	papi_attribute_value_t *value = NULL;
5102264Sjacobs 
5112264Sjacobs 	if (vptr == NULL)
5122264Sjacobs 		return (PAPI_BAD_ARGUMENT);
5132264Sjacobs 
5142264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
5152264Sjacobs 				PAPI_BOOLEAN, &value);
5162264Sjacobs 	if (status == PAPI_OK)
5172264Sjacobs 		*vptr = value->boolean;
5182264Sjacobs 
5192264Sjacobs 	return (status);
5202264Sjacobs }
5212264Sjacobs 
5222264Sjacobs papi_status_t
5232264Sjacobs papiAttributeListGetRange(papi_attribute_t **list, void **iter,
5242264Sjacobs 			char *name, int *min, int *max)
5252264Sjacobs {
5262264Sjacobs 	papi_status_t status;
5272264Sjacobs 	papi_attribute_value_t *value = NULL;
5282264Sjacobs 
5292264Sjacobs 	if ((min == NULL) || (max == NULL))
5302264Sjacobs 		return (PAPI_BAD_ARGUMENT);
5312264Sjacobs 
5322264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
5332264Sjacobs 				PAPI_RANGE, &value);
5342264Sjacobs 	if (status == PAPI_OK) {
5352264Sjacobs 		*min = value->range.lower;
5362264Sjacobs 		*max = value->range.upper;
5372264Sjacobs 	}
5382264Sjacobs 
5392264Sjacobs 	return (status);
5402264Sjacobs }
5412264Sjacobs 
5422264Sjacobs papi_status_t
5432264Sjacobs papiAttributeListGetResolution(papi_attribute_t **list, void **iter,
5442264Sjacobs 			char *name, int *x, int *y,
5452264Sjacobs 			papi_resolution_unit_t *units)
5462264Sjacobs {
5472264Sjacobs 	papi_status_t status;
5482264Sjacobs 	papi_attribute_value_t *value = NULL;
5492264Sjacobs 
5502264Sjacobs 	if ((x == NULL) || (y == NULL) || (units == NULL))
5512264Sjacobs 		return (PAPI_BAD_ARGUMENT);
5522264Sjacobs 
5532264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
5542264Sjacobs 				PAPI_RESOLUTION, &value);
5552264Sjacobs 	if (status == PAPI_OK) {
5562264Sjacobs 		*x = value->resolution.xres;
5572264Sjacobs 		*y = value->resolution.yres;
5582264Sjacobs 		*units = value->resolution.units;
5592264Sjacobs 	}
5602264Sjacobs 
5612264Sjacobs 	return (status);
5622264Sjacobs }
5632264Sjacobs 
5642264Sjacobs papi_status_t
5652264Sjacobs papiAttributeListGetDatetime(papi_attribute_t **list, void **iter,
5662264Sjacobs 			char *name, time_t *dt)
5672264Sjacobs {
5682264Sjacobs 	papi_status_t status;
5692264Sjacobs 	papi_attribute_value_t *value = NULL;
5702264Sjacobs 
5712264Sjacobs 	if (dt == NULL)
5722264Sjacobs 		return (PAPI_BAD_ARGUMENT);
5732264Sjacobs 
5742264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
5752264Sjacobs 				PAPI_DATETIME, &value);
5762264Sjacobs 	if (status == PAPI_OK) {
5772264Sjacobs 		*dt = value->datetime;
5782264Sjacobs 	}
5792264Sjacobs 
5802264Sjacobs 	return (status);
5812264Sjacobs }
5822264Sjacobs 
5832264Sjacobs papi_status_t
5842264Sjacobs papiAttributeListGetCollection(papi_attribute_t **list, void **iter,
5852264Sjacobs 			char *name, papi_attribute_t ***collection)
5862264Sjacobs {
5872264Sjacobs 	papi_status_t status;
5882264Sjacobs 	papi_attribute_value_t *value = NULL;
5892264Sjacobs 
5902264Sjacobs 	if (collection == NULL)
5912264Sjacobs 		return (PAPI_BAD_ARGUMENT);
5922264Sjacobs 
5932264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
5942264Sjacobs 				PAPI_COLLECTION, &value);
5952264Sjacobs 	if (status == PAPI_OK) {
5962264Sjacobs 		*collection = value->collection;
5972264Sjacobs 	}
5982264Sjacobs 
5992264Sjacobs 	return (status);
6002264Sjacobs }
6012264Sjacobs 
6022264Sjacobs papi_status_t
6032264Sjacobs papiAttributeListGetMetadata(papi_attribute_t **list, void **iter,
6042264Sjacobs 			char *name, papi_metadata_t *vptr)
6052264Sjacobs {
6062264Sjacobs 	papi_status_t status;
6072264Sjacobs 	papi_attribute_value_t *value = NULL;
6082264Sjacobs 
6092264Sjacobs 	if (vptr == NULL)
6102264Sjacobs 		return (PAPI_BAD_ARGUMENT);
6112264Sjacobs 
6122264Sjacobs 	status = papiAttributeListGetValue(list, iter, name,
6132264Sjacobs 				PAPI_METADATA, &value);
6142264Sjacobs 	if (status == PAPI_OK)
6152264Sjacobs 		*vptr = value->metadata;
6162264Sjacobs 
6172264Sjacobs 	return (status);
6182264Sjacobs }
6192264Sjacobs 
6202264Sjacobs /*
6212264Sjacobs  * Description: The given string contains one or more attributes, in the
6222264Sjacobs  *	      following form:
6232264Sjacobs  *		  "aaaa=true bbbbb=1 ccccc=abcd"
6242264Sjacobs  *	      extract the next attribute from that string; the 'next'
6252264Sjacobs  *	      parameter should be set to zero to extract the first attribute
6262264Sjacobs  *	      in the string.
6272264Sjacobs  *
6282264Sjacobs  */
6292264Sjacobs 
6302264Sjacobs static char *
6312264Sjacobs _getNextAttr(char *string, int *next)
6322264Sjacobs 
6332264Sjacobs {
6342264Sjacobs 	char *result = NULL;
6352264Sjacobs 	char *start = (char *)string + *next;
6362264Sjacobs 	char *nl = NULL;
6372264Sjacobs 	char *sp = NULL;
6382264Sjacobs 	char *tab = NULL;
6392264Sjacobs 	char *val = NULL;
6402264Sjacobs 	int len = 0;
6412264Sjacobs 
6422264Sjacobs 	if ((string != NULL) && (*start != '\0')) {
6432264Sjacobs 		while ((*start == ' ') || (*start == '\t') || (*start == '\n'))
6442264Sjacobs 		{
6452264Sjacobs 			start++;
6462264Sjacobs 		}
6472264Sjacobs 		nl = strchr(start, '\n');
6482264Sjacobs 		sp = strchr(start, ' ');
6492264Sjacobs 		tab = strchr(start, '\t');
6502264Sjacobs 
6512264Sjacobs 		val = strchr(start, '=');
6522264Sjacobs 
6532264Sjacobs 		if ((val != NULL) && ((val[1] == '"') || (val[1] == '\''))) {
6542264Sjacobs 			val = strchr(&val[2], val[1]);
6552264Sjacobs 			if (val != NULL) {
6562264Sjacobs 				nl = strchr(&val[1], '\n');
6572264Sjacobs 				sp = strchr(&val[1], ' ');
6582264Sjacobs 				tab = strchr(&val[1], '\t');
6592264Sjacobs 			}
6602264Sjacobs 		}
6612264Sjacobs 
6622264Sjacobs 		if ((nl != NULL) &&
6632264Sjacobs 		    ((sp == NULL) || ((sp != NULL) && (nl < sp))) &&
6642264Sjacobs 		    ((tab == NULL) || ((tab != NULL) && (nl < tab)))) {
6652264Sjacobs 			len = nl-start;
6662264Sjacobs 		} else if ((sp != NULL) && (tab != NULL) && (sp > tab)) {
6672264Sjacobs 			len = tab-start;
6682264Sjacobs 		} else if ((sp != NULL) && (sp != NULL)) {
6692264Sjacobs 			len = sp-start;
6702264Sjacobs 		} else if ((tab != NULL) && (tab != NULL)) {
6712264Sjacobs 			len = tab-start;
6722264Sjacobs 		}
6732264Sjacobs 
6742264Sjacobs 		if (len == 0) {
6752264Sjacobs 			len = strlen(start);
6762264Sjacobs 		}
6772264Sjacobs 
6782264Sjacobs 		if (len > 0) {
6792264Sjacobs 			result = (char *)malloc(len+1);
6802264Sjacobs 			if (result != NULL) {
6812264Sjacobs 				strncpy(result, start, len);
6822264Sjacobs 				result[len] = '\0';
6832264Sjacobs 				*next = (start-string)+len;
6842264Sjacobs 			}
6852264Sjacobs 		}
6862264Sjacobs 	}
6872264Sjacobs 
6882264Sjacobs 	return (result);
6892264Sjacobs } /* _getNextAttr() */
6902264Sjacobs 
6912264Sjacobs 
6922264Sjacobs /*
6932264Sjacobs  * Description: Parse the given attribute string value and transform it into
6942264Sjacobs  *	      the papi_attribute_value_t in the papi_attribute_t structure.
6952264Sjacobs  *
6962264Sjacobs  */
6972264Sjacobs 
6982264Sjacobs static papi_status_t
6992264Sjacobs _parseAttrValue(char *value, papi_attribute_t *attr)
7002264Sjacobs 
7012264Sjacobs {
7022264Sjacobs 	papi_status_t result = PAPI_OK;
7032264Sjacobs 	int len = 0;
7042264Sjacobs 	int i = 0;
7052264Sjacobs 	char *papiString = NULL;
7062264Sjacobs 	char *tmp1 = NULL;
7072264Sjacobs 	char *tmp2 = NULL;
7082264Sjacobs 	char *tmp3 = NULL;
7092264Sjacobs 	papi_attribute_value_t **avalues = NULL;
7102264Sjacobs 
7112264Sjacobs 	avalues = malloc(sizeof (papi_attribute_value_t *) * 2);
7122264Sjacobs 	if (avalues == NULL) {
7132264Sjacobs 		result = PAPI_TEMPORARY_ERROR;
7142264Sjacobs 		return (result);
7152264Sjacobs 	}
7162264Sjacobs 	avalues[0] = malloc(sizeof (papi_attribute_value_t));
7172264Sjacobs 	avalues[1] = NULL;
7182264Sjacobs 	if (avalues[0] == NULL) {
7192264Sjacobs 		free(avalues);
7202264Sjacobs 		result = PAPI_TEMPORARY_ERROR;
7212264Sjacobs 		return (result);
7222264Sjacobs 	}
7232264Sjacobs 
7242264Sjacobs 
7252264Sjacobs /*
7262264Sjacobs  * TODO - need to sort out 'resolution', 'dateandtime' & 'collection' values
7272264Sjacobs  */
7282264Sjacobs 	if ((value != NULL) && (strlen(value) > 0) && (attr != NULL)) {
7292264Sjacobs 
7302264Sjacobs 		len = strlen(value);
7312264Sjacobs 		if ((len >= 2) && (((value[0] == '"') &&
7322264Sjacobs 				(value[len-1] == '"')) || ((value[0] == '\'') &&
7332264Sjacobs 				(value[len-1] == '\'')))) {
7342264Sjacobs 			/* string value */
7352264Sjacobs 			attr->type = PAPI_STRING;
7362264Sjacobs 
7372264Sjacobs 			papiString = strdup(value+1);
7382264Sjacobs 			if (papiString != NULL) {
7392264Sjacobs 				papiString[strlen(papiString)-1] = '\0';
7402264Sjacobs 				avalues[0]->string = papiString;
7412264Sjacobs 			} else {
7422264Sjacobs 				result = PAPI_TEMPORARY_ERROR;
7432264Sjacobs 			}
7442264Sjacobs 		} else if ((strcasecmp(value, "true") == 0) ||
7452264Sjacobs 		    (strcasecmp(value, "YES") == 0)) {
7462264Sjacobs 			/* boolean = true */
7472264Sjacobs 			attr->type = PAPI_BOOLEAN;
7482264Sjacobs 			avalues[0]->boolean = PAPI_TRUE;
7492264Sjacobs 		} else if ((strcasecmp(value, "false") == 0) ||
7502264Sjacobs 		    (strcasecmp(value, "NO") == 0)) {
7512264Sjacobs 			/* boolean = false */
7522264Sjacobs 			attr->type = PAPI_BOOLEAN;
7532264Sjacobs 			avalues[0]->boolean = PAPI_FALSE;
7542264Sjacobs 		} else {
7552264Sjacobs 			/* is value an integer or a range ? */
7562264Sjacobs 
7572264Sjacobs 			i = 0;
7582264Sjacobs 			attr->type = PAPI_INTEGER;
7592264Sjacobs 			tmp1 = strdup(value);
7602264Sjacobs 			while (((value[i] >= '0') && (value[i] <= '9')) ||
7612264Sjacobs 					(value[i] == '-')) {
7622264Sjacobs 				if (value[i] == '-') {
7632264Sjacobs 					tmp1[i] = '\0';
7642264Sjacobs 					tmp2 = &tmp1[i+1];
7652264Sjacobs 					attr->type = PAPI_RANGE;
7662264Sjacobs 				}
7672264Sjacobs 
7682264Sjacobs 				i++;
7692264Sjacobs 			}
7702264Sjacobs 
7712264Sjacobs 			if (strlen(value) == i) {
7722264Sjacobs 				if (attr->type == PAPI_RANGE) {
7732264Sjacobs 					avalues[0]->range.lower = atoi(tmp1);
7742264Sjacobs 					avalues[0]->range.upper = atoi(tmp2);
7752264Sjacobs 				} else {
7762264Sjacobs 					avalues[0]->integer = atoi(value);
7772264Sjacobs 				}
7782264Sjacobs 			} else {
7792264Sjacobs 				/* is value a resolution ? */
7802264Sjacobs 				i = 0;
7812264Sjacobs 				attr->type = PAPI_INTEGER;
7822264Sjacobs 				tmp1 = strdup(value);
7832264Sjacobs 				while (((value[i] >= '0') &&
7842264Sjacobs 					(value[i] <= '9')) ||
7852264Sjacobs 					(value[i] == 'x')) {
7862264Sjacobs 					if (value[i] == 'x') {
7872264Sjacobs 						tmp1[i] = '\0';
7882264Sjacobs 						if (attr->type == PAPI_INTEGER)
7892264Sjacobs 						{
7902264Sjacobs 							tmp2 = &tmp1[i+1];
7912264Sjacobs 							attr->type =
7922264Sjacobs 								PAPI_RESOLUTION;
7932264Sjacobs 						} else {
7942264Sjacobs 							tmp3 = &tmp1[i+1];
7952264Sjacobs 						}
7962264Sjacobs 					}
7972264Sjacobs 
7982264Sjacobs 					i++;
7992264Sjacobs 				}
8002264Sjacobs 
8012264Sjacobs 				if (strlen(value) == i) {
8022264Sjacobs 					if (attr->type == PAPI_RESOLUTION) {
8032264Sjacobs 						avalues[0]->resolution.xres =
8042264Sjacobs 								atoi(tmp1);
8052264Sjacobs 						avalues[0]->resolution.yres =
8062264Sjacobs 								atoi(tmp2);
8072264Sjacobs 						if (tmp3 != NULL) {
8082264Sjacobs 							avalues[0]->
8092264Sjacobs 							resolution.units =
8102264Sjacobs 								atoi(tmp3);
8112264Sjacobs 						} else {
8122264Sjacobs 							avalues[0]->
8132264Sjacobs 							resolution.units = 0;
8142264Sjacobs 						}
8152264Sjacobs 					}
8162264Sjacobs 				}
8172264Sjacobs 
8182264Sjacobs 				if (attr->type != PAPI_RESOLUTION) {
8192264Sjacobs 					attr->type = PAPI_STRING;
8202264Sjacobs 					avalues[0]->string = strdup(value);
8212264Sjacobs 					if (avalues[0]->string == NULL) {
8222264Sjacobs 						result = PAPI_TEMPORARY_ERROR;
8232264Sjacobs 					}
8242264Sjacobs 				}
8252264Sjacobs 			}
8262264Sjacobs 			free(tmp1);
8272264Sjacobs 		}
8282264Sjacobs 
8292264Sjacobs 	} else {
8302264Sjacobs 		result = PAPI_BAD_ARGUMENT;
8312264Sjacobs 	}
8322264Sjacobs 
8332264Sjacobs 	if (result != PAPI_OK) {
8342264Sjacobs 		i = 0;
8352264Sjacobs 		while (avalues[i] != NULL) {
8362264Sjacobs 			free(avalues[i]);
8372264Sjacobs 			i++;
8382264Sjacobs 		}
8392264Sjacobs 		free(avalues);
8402264Sjacobs 	} else {
8412264Sjacobs 		attr->values = avalues;
8422264Sjacobs 	}
8432264Sjacobs 
8442264Sjacobs 	return (result);
8452264Sjacobs } /* _parseAttrValue() */
8462264Sjacobs 
8472264Sjacobs 
8482264Sjacobs /*
8492264Sjacobs  * Description: Parse the given attribute string and transform it into the
8502264Sjacobs  *	      papi_attribute_t structure.
8512264Sjacobs  *
8522264Sjacobs  */
8532264Sjacobs 
8542264Sjacobs static papi_status_t
8552264Sjacobs _parseAttributeString(char *attrString, papi_attribute_t *attr)
8562264Sjacobs 
8572264Sjacobs {
8582264Sjacobs 	papi_status_t result = PAPI_OK;
8592264Sjacobs 	char *string = NULL;
8602264Sjacobs 	char *p = NULL;
8612264Sjacobs 	papi_attribute_value_t **avalues = NULL;
8622264Sjacobs 
8632264Sjacobs 	if ((attrString != NULL) && (strlen(attrString) >= 3) &&
8642264Sjacobs 	    (attr != NULL)) {
8652264Sjacobs 		attr->name = NULL;
8662264Sjacobs 		string = strdup(attrString);
8672264Sjacobs 		if (string != NULL) {
8682264Sjacobs 			p = strchr(string, '=');
8692264Sjacobs 			if (p != NULL) {
8702264Sjacobs 				*p = '\0';
8712264Sjacobs 				attr->name = string;
8722264Sjacobs 				p++;  /* pointer to value */
8732264Sjacobs 
8742264Sjacobs 				result = _parseAttrValue(p, attr);
8752264Sjacobs 			} else {
8762264Sjacobs 				char value;
8772264Sjacobs 				/* boolean - no value so assume 'true' */
8782264Sjacobs 				if (strncasecmp(string, "no", 2) == 0) {
8792264Sjacobs 					string += 2;
8802264Sjacobs 					value = PAPI_FALSE;
8812264Sjacobs 				} else
8822264Sjacobs 					value = PAPI_TRUE;
8832264Sjacobs 
8842264Sjacobs 				attr->name = string;
8852264Sjacobs 				attr->type = PAPI_BOOLEAN;
8862264Sjacobs 
8872264Sjacobs 				avalues = malloc(
8882264Sjacobs 					sizeof (papi_attribute_value_t *) * 2);
8892264Sjacobs 				if (avalues == NULL) {
8902264Sjacobs 					result = PAPI_TEMPORARY_ERROR;
8912264Sjacobs 				} else {
8922264Sjacobs 					avalues[0] = malloc(
8932264Sjacobs 					sizeof (papi_attribute_value_t));
8942264Sjacobs 					avalues[1] = NULL;
8952264Sjacobs 					if (avalues[0] == NULL) {
8962264Sjacobs 						free(avalues);
8972264Sjacobs 						result = PAPI_TEMPORARY_ERROR;
8982264Sjacobs 					} else {
8992264Sjacobs 						avalues[0]->boolean = value;
9002264Sjacobs 						attr->values = avalues;
9012264Sjacobs 					}
9022264Sjacobs 				}
9032264Sjacobs 			}
9042264Sjacobs 		}
9052264Sjacobs 	} else {
9062264Sjacobs 		result = PAPI_BAD_ARGUMENT;
9072264Sjacobs 	}
9082264Sjacobs 
9092264Sjacobs 	return (result);
9102264Sjacobs } /* _parseAttributeString() */
9112264Sjacobs 
9122264Sjacobs 
9132264Sjacobs papi_status_t
9142264Sjacobs papiAttributeListFromString(papi_attribute_t ***attrs,
9152264Sjacobs 		int flags, char *string)
9162264Sjacobs {
9172264Sjacobs 	papi_status_t result = PAPI_OK;
9182264Sjacobs 	int	   next = 0;
9192264Sjacobs 	char	 *attrString = NULL;
9202264Sjacobs 	papi_attribute_t attr;
9212264Sjacobs 
9222264Sjacobs 	if ((attrs != NULL) && (string != NULL) &&
9232264Sjacobs 	    ((flags & ~(PAPI_ATTR_APPEND+PAPI_ATTR_REPLACE+PAPI_ATTR_EXCL))
9242264Sjacobs 			== 0)) {
9252264Sjacobs 		attrString = _getNextAttr(string, &next);
9262264Sjacobs 		while ((result == PAPI_OK) && (attrString != NULL)) {
9272264Sjacobs 			result = _parseAttributeString(attrString, &attr);
9282264Sjacobs 			if ((result == PAPI_OK) && (attr.name != NULL)) {
9292264Sjacobs 				/* add this attribute to the list */
9302264Sjacobs 				if ((attr.values != NULL) &&
9312264Sjacobs 				    (attr.values[0] != NULL)) {
9322264Sjacobs 					result = papiAttributeListAddValue(
9332264Sjacobs 							attrs, PAPI_ATTR_APPEND,
9342264Sjacobs 							attr.name, attr.type,
9352264Sjacobs 							attr.values[0]);
9362264Sjacobs 					free(attr.values[0]);
9372264Sjacobs 					free(attr.values);
9382264Sjacobs 				} else {
9392264Sjacobs 					result = PAPI_TEMPORARY_ERROR;
9402264Sjacobs 				}
9412264Sjacobs 			}
9422264Sjacobs 			free(attrString);
9432264Sjacobs 
9442264Sjacobs 			attrString = _getNextAttr(string, &next);
9452264Sjacobs 		}
9462264Sjacobs 	}
9472264Sjacobs 	else
9482264Sjacobs 	{
9492264Sjacobs 		result = PAPI_BAD_ARGUMENT;
9502264Sjacobs 	}
9512264Sjacobs 
9522264Sjacobs 	return (result);
9532264Sjacobs }
9542264Sjacobs 
9552264Sjacobs static papi_status_t
9562264Sjacobs papiAttributeToString(papi_attribute_t *attribute, char *delim,
9572264Sjacobs 		char *buffer, size_t buflen)
9582264Sjacobs {
9592264Sjacobs 	papi_attribute_value_t **values = attribute->values;
9602264Sjacobs 	int rc, i;
9612264Sjacobs 
9622264Sjacobs 	strlcat(buffer, attribute->name, buflen);
9632264Sjacobs 	strlcat(buffer, "=", buflen);
9642264Sjacobs 
9652264Sjacobs 	if (values == NULL)
9662264Sjacobs 		return (PAPI_OK);
9672264Sjacobs 
9682264Sjacobs 	for (i = 0; values[i] != NULL; i++) {
9692264Sjacobs 		switch (attribute->type) {
9702264Sjacobs 		case PAPI_STRING:
9712264Sjacobs 			rc = strlcat(buffer, values[i]->string, buflen);
9722264Sjacobs 			break;
9732264Sjacobs 		case PAPI_INTEGER: {
9742264Sjacobs 			char string[24];
9752264Sjacobs 
9762264Sjacobs 			snprintf(string, sizeof (string), "%d",
9772264Sjacobs 				values[i]->integer);
9782264Sjacobs 			rc = strlcat(buffer, string, buflen);
9792264Sjacobs 			}
9802264Sjacobs 			break;
9812264Sjacobs 		case PAPI_BOOLEAN:
9822264Sjacobs 			rc = strlcat(buffer, (values[i]->boolean ? "true" :
9832264Sjacobs 							"false"), buflen);
9842264Sjacobs 			break;
9852264Sjacobs 		case PAPI_RANGE: {
9862264Sjacobs 			char string[24];
9872264Sjacobs 
9882264Sjacobs 			snprintf(string, sizeof (string), "%d-%d",
9892264Sjacobs 				values[i]->range.lower, values[i]->range.upper);
9902264Sjacobs 			rc = strlcat(buffer, string, buflen);
9912264Sjacobs 			}
9922264Sjacobs 			break;
9932264Sjacobs 		case PAPI_RESOLUTION: {
9942264Sjacobs 			char string[24];
9952264Sjacobs 
9962264Sjacobs 			snprintf(string, sizeof (string), "%dx%ddp%c",
9972264Sjacobs 				values[i]->resolution.xres,
9982264Sjacobs 				values[i]->resolution.yres,
9992264Sjacobs 				(values[i]->resolution.units == PAPI_RES_PER_CM
10002264Sjacobs 							? 'c' : 'i'));
10012264Sjacobs 			rc = strlcat(buffer, string, buflen);
10022264Sjacobs 			}
10032264Sjacobs 			break;
10042264Sjacobs 		case PAPI_DATETIME: {
10052264Sjacobs 			struct tm *tm = localtime(&values[i]->datetime);
10062264Sjacobs 
10072264Sjacobs 			if (tm != NULL) {
10082264Sjacobs 				char string[64];
10092264Sjacobs 
10102264Sjacobs 				strftime(string, sizeof (string), "%C", tm);
10112264Sjacobs 				rc = strlcat(buffer, string, buflen);
10122264Sjacobs 			}}
10132264Sjacobs 			break;
10142264Sjacobs 		case PAPI_COLLECTION: {
10152264Sjacobs 			char *string = alloca(buflen);
10162264Sjacobs #ifdef DEBUG
10172264Sjacobs 			char prefix[256];
10182264Sjacobs 
10192264Sjacobs 			snprintf(prefix, sizeof (prefix), "%s  %s(%d)  ", delim,
10202264Sjacobs 					attribute->name, i);
10212264Sjacobs 
10222264Sjacobs 			papiAttributeListToString(values[i]->collection,
10232264Sjacobs 					prefix, string, buflen);
10242264Sjacobs #else
10252264Sjacobs 			papiAttributeListToString(values[i]->collection,
10262264Sjacobs 					delim, string, buflen);
10272264Sjacobs #endif
10282264Sjacobs 			rc = strlcat(buffer, string, buflen);
10292264Sjacobs 			}
10302264Sjacobs 			break;
10312264Sjacobs 		default: {
10322264Sjacobs 			char string[32];
10332264Sjacobs 
10342264Sjacobs 			snprintf(string, sizeof (string), "unknown-type-0x%x",
10352264Sjacobs 				attribute->type);
10362264Sjacobs 			rc = strlcat(buffer, string, buflen);
10372264Sjacobs 			}
10382264Sjacobs 		}
10392264Sjacobs 		if (values[i+1] != NULL)
10402264Sjacobs 			rc = strlcat(buffer, ",", buflen);
10412264Sjacobs 
10422264Sjacobs 		if (rc >= buflen)
10432264Sjacobs 			return (PAPI_NOT_POSSIBLE);
10442264Sjacobs 
10452264Sjacobs 	}
10462264Sjacobs 
10472264Sjacobs 	return (PAPI_OK);
10482264Sjacobs }
10492264Sjacobs 
10502264Sjacobs papi_status_t
10512264Sjacobs papiAttributeListToString(papi_attribute_t **attrs,
10522264Sjacobs 		char *delim, char *buffer, size_t buflen)
10532264Sjacobs {
10542264Sjacobs 	papi_status_t status = PAPI_OK;
10552264Sjacobs 	int i;
10562264Sjacobs 
10572264Sjacobs 	if ((attrs == NULL) || (buffer == NULL))
10582264Sjacobs 		return (PAPI_BAD_ARGUMENT);
10592264Sjacobs 
10602264Sjacobs 	buffer[0] = '\0';
10612264Sjacobs 	if (!delim)
10622264Sjacobs 		delim = " ";
10632264Sjacobs 
10642264Sjacobs #ifdef DEBUG
10652264Sjacobs 	strlcat(buffer, delim, buflen);
10662264Sjacobs #endif
10672264Sjacobs 	for (i = 0; ((attrs[i] != NULL) && (status == PAPI_OK)); i++) {
10682264Sjacobs 		status = papiAttributeToString(attrs[i], delim, buffer, buflen);
10692264Sjacobs 		if (attrs[i+1] != NULL)
10702264Sjacobs 			strlcat(buffer, delim, buflen);
10712264Sjacobs 	}
10722264Sjacobs 
10732264Sjacobs 	return (status);
10742264Sjacobs }
10752264Sjacobs 
10762264Sjacobs static int
10772264Sjacobs is_in_list(char *value, char **list)
10782264Sjacobs {
10792264Sjacobs 	if ((list != NULL) && (value != NULL)) {
10802264Sjacobs 		int i;
10812264Sjacobs 
10822264Sjacobs 		for (i = 0; list[i] != NULL; i++)
10832264Sjacobs 			if (strcasecmp(value, list[i]) == 0)
10842264Sjacobs 				return (0);
10852264Sjacobs 	}
10862264Sjacobs 
10872264Sjacobs 	return (1);
10882264Sjacobs }
10892264Sjacobs 
10902264Sjacobs static papi_status_t
10912264Sjacobs copy_attribute(papi_attribute_t ***list, papi_attribute_t *attribute)
10922264Sjacobs {
10932264Sjacobs 	papi_status_t status;
10942264Sjacobs 	int i = 0;
10952264Sjacobs 
10962264Sjacobs 	if ((list == NULL) || (attribute == NULL) ||
10972264Sjacobs 	    (attribute->values == NULL))
10982264Sjacobs 		return (PAPI_BAD_ARGUMENT);
10992264Sjacobs 
11002264Sjacobs 	for (status = papiAttributeListAddValue(list, PAPI_ATTR_EXCL,
11012264Sjacobs 					attribute->name, attribute->type,
11022264Sjacobs 					attribute->values[i]);
11032264Sjacobs 	     ((status == PAPI_OK) && (attribute->values[i] != NULL));
11042264Sjacobs 	     status = papiAttributeListAddValue(list, PAPI_ATTR_APPEND,
11052264Sjacobs 					attribute->name, attribute->type,
11062264Sjacobs 					attribute->values[i]))
11072264Sjacobs 		i++;
11082264Sjacobs 
11092264Sjacobs 	return (status);
11102264Sjacobs }
11112264Sjacobs 
11122264Sjacobs void
11132264Sjacobs copy_attributes(papi_attribute_t ***result, papi_attribute_t **attributes)
11142264Sjacobs {
11152264Sjacobs 	int i;
11162264Sjacobs 
11172264Sjacobs 	if ((result == NULL) || (attributes == NULL))
11182264Sjacobs 		return;
11192264Sjacobs 
11202264Sjacobs 	for (i = 0; attributes[i] != NULL; i++)
11212264Sjacobs 		copy_attribute(result, attributes[i]);
11222264Sjacobs }
11232264Sjacobs 
11242264Sjacobs void
11252264Sjacobs split_and_copy_attributes(char **list, papi_attribute_t **attributes,
11262264Sjacobs 		papi_attribute_t ***in, papi_attribute_t ***out)
11272264Sjacobs {
11282264Sjacobs 	int i;
11292264Sjacobs 
11302264Sjacobs 	if ((list == NULL) || (attributes == NULL))
11312264Sjacobs 		return;
11322264Sjacobs 
11332264Sjacobs 	for (i = 0; attributes[i] != NULL; i++)
11342264Sjacobs 		if (is_in_list(attributes[i]->name, list) == 0)
11352264Sjacobs 			copy_attribute(in, attributes[i]);
11362264Sjacobs 		else
11372264Sjacobs 			copy_attribute(out, attributes[i]);
11382264Sjacobs }
11392264Sjacobs 
11402264Sjacobs void
11412264Sjacobs papiAttributeListPrint(FILE *fp, papi_attribute_t **attributes,
11422264Sjacobs 		char *prefix_fmt, ...)
11432264Sjacobs {
11442264Sjacobs 	char *prefix = NULL;
11452264Sjacobs 	char *buffer = NULL;
11462264Sjacobs 	char *newfmt = NULL;
11472264Sjacobs 	void *mem;
11482264Sjacobs 	ssize_t size = 0;
11492264Sjacobs 	va_list ap;
11502264Sjacobs 
11512264Sjacobs 	newfmt = malloc(strlen(prefix_fmt) + 2);
11522264Sjacobs 	sprintf(newfmt, "\n%s", prefix_fmt);
11532264Sjacobs 
11542264Sjacobs 	va_start(ap, prefix_fmt);
11552264Sjacobs 	while (vsnprintf(prefix, size, newfmt, ap) > size) {
11562264Sjacobs 		size += 1024;
11572264Sjacobs 		mem = realloc(prefix, size);
11582264Sjacobs 		if (!mem) goto error;
11592264Sjacobs 		prefix = mem;
11602264Sjacobs 	}
11612264Sjacobs 	va_end(ap);
11622264Sjacobs 
11632264Sjacobs 	if (attributes) {
11642264Sjacobs 		size = 0;
11652264Sjacobs 		while (papiAttributeListToString(attributes, prefix, buffer,
11662264Sjacobs 						size) != PAPI_OK) {
11672264Sjacobs 			size += 1024;
11682264Sjacobs 			mem = realloc(buffer, size);
11692264Sjacobs 			if (!mem) goto error;
11702264Sjacobs 			buffer = mem;
11712264Sjacobs 		}
11722264Sjacobs 	}
11732264Sjacobs 
11742264Sjacobs 	fprintf(fp, "%s%s\n", prefix, buffer ? buffer : "");
11752264Sjacobs 	fflush(fp);
11762264Sjacobs 
11772264Sjacobs  error:
11782264Sjacobs 	free(newfmt);
11792264Sjacobs 	free(prefix);
11802264Sjacobs 	free(buffer);
11812264Sjacobs }
1182