summaryrefslogtreecommitdiff
path: root/usr/src/lib/print/libpapi-common/common/attribute.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/print/libpapi-common/common/attribute.c')
-rw-r--r--usr/src/lib/print/libpapi-common/common/attribute.c1181
1 files changed, 1181 insertions, 0 deletions
diff --git a/usr/src/lib/print/libpapi-common/common/attribute.c b/usr/src/lib/print/libpapi-common/common/attribute.c
new file mode 100644
index 0000000000..2b2e035cfe
--- /dev/null
+++ b/usr/src/lib/print/libpapi-common/common/attribute.c
@@ -0,0 +1,1181 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <alloca.h>
+#include <papi.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) {
+ 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);
+}