/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * */ /* $Id: attribute.c 157 2006-04-26 15:07:55Z ktou $ */ #pragma ident "%Z%%M% %I% %E% SMI" /*LINTLIBRARY*/ #include #include #include #include #include #include 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) { papi_status_t status = PAPI_OK; int i; for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK)); i++) { papi_attribute_t *a = collection[i]; status = papiAttributeListAddValue(&result, PAPI_ATTR_APPEND, a->name, a->type, NULL); if ((status == PAPI_OK) && (a->values != NULL)) { int j; for (j = 0; ((a->values[j] != NULL) && (status == PAPI_OK)); j++) status = papiAttributeListAddValue( &result, PAPI_ATTR_APPEND, a->name, a->type, a->values[j]); } } if (status != PAPI_OK) { papiAttributeListFree(result); result = NULL; } } return (result); } static papi_attribute_value_t * papiAttributeValueDup(papi_attribute_value_type_t type, 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; case PAPI_METADATA: result->metadata = v->metadata; break; default: /* unknown type, fail to duplicate */ free(result); result = NULL; } } return (result); } static papi_attribute_t * papiAttributeAlloc(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 papiAttributeListAppendValue(papi_attribute_value_t ***values, papi_attribute_value_type_t type, 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 papiAttributeListAddValue(papi_attribute_t ***list, int flgs, char *name, papi_attribute_value_type_t type, 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 = papiAttributeListAppendValue(&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, int flags, char *name, char *string) { papi_attribute_value_t v; v.string = (char *)string; return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v)); } papi_status_t papiAttributeListAddInteger(papi_attribute_t ***list, int flags, char *name, int integer) { papi_attribute_value_t v; v.integer = integer; return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v)); } papi_status_t papiAttributeListAddBoolean(papi_attribute_t ***list, int flags, char *name, char boolean) { papi_attribute_value_t v; v.boolean = boolean; return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v)); } papi_status_t papiAttributeListAddRange(papi_attribute_t ***list, int flags, char *name, int lower, int upper) { papi_attribute_value_t v; v.range.lower = lower; v.range.upper = upper; return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v)); } papi_status_t papiAttributeListAddResolution(papi_attribute_t ***list, int flags, char *name, int xres, int yres, papi_resolution_unit_t units) { papi_attribute_value_t v; v.resolution.xres = xres; v.resolution.yres = yres; v.resolution.units = units; return (papiAttributeListAddValue(list, flags, name, PAPI_RESOLUTION, &v)); } papi_status_t papiAttributeListAddDatetime(papi_attribute_t ***list, int flags, char *name, time_t datetime) { papi_attribute_value_t v; v.datetime = datetime; return (papiAttributeListAddValue(list, flags, name, PAPI_DATETIME, &v)); } papi_status_t papiAttributeListAddCollection(papi_attribute_t ***list, int flags, char *name, papi_attribute_t **collection) { papi_attribute_value_t v; v.collection = (papi_attribute_t **)collection; return (papiAttributeListAddValue(list, flags, name, PAPI_COLLECTION, &v)); } papi_status_t papiAttributeListAddMetadata(papi_attribute_t ***list, int flags, char *name, papi_metadata_t metadata) { papi_attribute_value_t v; v.metadata = metadata; return (papiAttributeListAddValue(list, flags, name, PAPI_METADATA, &v)); } papi_status_t papiAttributeListDelete(papi_attribute_t ***list, 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, char *name) { int i; if ((list == NULL) || (name == NULL)) return (NULL); 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, 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, 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, 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, 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, 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, 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, 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, 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); } papi_status_t papiAttributeListGetMetadata(papi_attribute_t **list, void **iter, char *name, papi_metadata_t *vptr) { papi_status_t status; papi_attribute_value_t *value = NULL; if (vptr == NULL) return (PAPI_BAD_ARGUMENT); status = papiAttributeListGetValue(list, iter, name, PAPI_METADATA, &value); if (status == PAPI_OK) *vptr = value->metadata; 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(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 { char value; /* boolean - no value so assume 'true' */ if (strncasecmp(string, "no", 2) == 0) { string += 2; value = PAPI_FALSE; } else value = PAPI_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 = value; attr->values = avalues; } } } } } else { result = PAPI_BAD_ARGUMENT; } return (result); } /* _parseAttributeString() */ papi_status_t papiAttributeListFromString(papi_attribute_t ***attrs, int flags, 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)) { 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 = papiAttributeListAddValue( 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); } static papi_status_t papiAttributeToString(papi_attribute_t *attribute, char *delim, char *buffer, size_t buflen) { papi_attribute_value_t **values = attribute->values; int rc, i; strlcat(buffer, attribute->name, buflen); strlcat(buffer, "=", buflen); if (values == NULL) return (PAPI_OK); for (i = 0; values[i] != NULL; i++) { switch (attribute->type) { case PAPI_STRING: rc = strlcat(buffer, values[i]->string, buflen); break; case PAPI_INTEGER: { char string[24]; snprintf(string, sizeof (string), "%d", values[i]->integer); rc = strlcat(buffer, string, buflen); } break; case PAPI_BOOLEAN: rc = strlcat(buffer, (values[i]->boolean ? "true" : "false"), buflen); break; case PAPI_RANGE: { char string[24]; snprintf(string, sizeof (string), "%d-%d", values[i]->range.lower, values[i]->range.upper); rc = strlcat(buffer, string, buflen); } break; case PAPI_RESOLUTION: { char string[24]; snprintf(string, sizeof (string), "%dx%ddp%c", values[i]->resolution.xres, values[i]->resolution.yres, (values[i]->resolution.units == PAPI_RES_PER_CM ? 'c' : 'i')); rc = strlcat(buffer, string, buflen); } break; case PAPI_DATETIME: { struct tm *tm = localtime(&values[i]->datetime); if (tm != NULL) { char string[64]; strftime(string, sizeof (string), "%C", tm); rc = strlcat(buffer, string, buflen); }} break; case PAPI_COLLECTION: { char *string = alloca(buflen); #ifdef DEBUG char prefix[256]; snprintf(prefix, sizeof (prefix), "%s %s(%d) ", delim, attribute->name, i); papiAttributeListToString(values[i]->collection, prefix, string, buflen); #else papiAttributeListToString(values[i]->collection, delim, string, buflen); #endif rc = strlcat(buffer, string, buflen); } break; default: { char string[32]; snprintf(string, sizeof (string), "unknown-type-0x%x", attribute->type); rc = strlcat(buffer, string, buflen); } } if (values[i+1] != NULL) rc = strlcat(buffer, ",", buflen); if (rc >= buflen) return (PAPI_NOT_POSSIBLE); } return (PAPI_OK); } papi_status_t papiAttributeListToString(papi_attribute_t **attrs, char *delim, char *buffer, size_t buflen) { papi_status_t status = PAPI_OK; int i; if ((attrs == NULL) || (buffer == NULL)) return (PAPI_BAD_ARGUMENT); buffer[0] = '\0'; if (!delim) delim = " "; #ifdef DEBUG strlcat(buffer, delim, buflen); #endif for (i = 0; ((attrs[i] != NULL) && (status == PAPI_OK)); i++) { status = papiAttributeToString(attrs[i], delim, buffer, buflen); if (attrs[i+1] != NULL) strlcat(buffer, delim, buflen); } return (status); } static int is_in_list(char *value, char **list) { if ((list != NULL) && (value != NULL)) { int i; for (i = 0; list[i] != NULL; i++) if (strcasecmp(value, list[i]) == 0) return (0); } return (1); } static papi_status_t copy_attribute(papi_attribute_t ***list, papi_attribute_t *attribute) { papi_status_t status; int i = 0; if ((list == NULL) || (attribute == NULL) || (attribute->values == NULL)) return (PAPI_BAD_ARGUMENT); for (status = papiAttributeListAddValue(list, PAPI_ATTR_EXCL, attribute->name, attribute->type, attribute->values[i]); ((status == PAPI_OK) && (attribute->values[i] != NULL)); status = papiAttributeListAddValue(list, PAPI_ATTR_APPEND, attribute->name, attribute->type, attribute->values[i])) i++; return (status); } void copy_attributes(papi_attribute_t ***result, papi_attribute_t **attributes) { int i; if ((result == NULL) || (attributes == NULL)) return; for (i = 0; attributes[i] != NULL; i++) copy_attribute(result, attributes[i]); } void split_and_copy_attributes(char **list, papi_attribute_t **attributes, papi_attribute_t ***in, papi_attribute_t ***out) { int i; if ((list == NULL) || (attributes == NULL)) return; for (i = 0; attributes[i] != NULL; i++) if (is_in_list(attributes[i]->name, list) == 0) copy_attribute(in, attributes[i]); else copy_attribute(out, attributes[i]); } void papiAttributeListPrint(FILE *fp, papi_attribute_t **attributes, char *prefix_fmt, ...) { char *prefix = NULL; char *buffer = NULL; char *newfmt = NULL; void *mem; ssize_t size = 0; va_list ap; newfmt = malloc(strlen(prefix_fmt) + 2); sprintf(newfmt, "\n%s", prefix_fmt); va_start(ap, prefix_fmt); while (vsnprintf(prefix, size, newfmt, ap) > size) { size += 1024; mem = realloc(prefix, size); if (!mem) goto error; prefix = mem; } va_end(ap); if (attributes) { size = 0; while (papiAttributeListToString(attributes, prefix, buffer, size) != PAPI_OK) { size += 1024; mem = realloc(buffer, size); if (!mem) goto error; buffer = mem; } } fprintf(fp, "%s%s\n", prefix, buffer ? buffer : ""); fflush(fp); error: free(newfmt); free(prefix); free(buffer); }