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 /*
236725Sjacobs * Copyright 2008 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>
386725Sjacobs #include <ctype.h>
392264Sjacobs #include <alloca.h>
402264Sjacobs #include <papi.h>
416725Sjacobs #include <regex.h>
422264Sjacobs
43*7154Ssg223391 #define MAX_PAGES 32767
44*7154Ssg223391 /*
45*7154Ssg223391 * Assuming the maximum number of pages in
46*7154Ssg223391 * a document to be 32767
47*7154Ssg223391 */
48*7154Ssg223391
492264Sjacobs static void papiAttributeFree(papi_attribute_t *attribute);
502264Sjacobs
512264Sjacobs static void
papiAttributeValueFree(papi_attribute_value_type_t type,papi_attribute_value_t * value)522264Sjacobs papiAttributeValueFree(papi_attribute_value_type_t type,
532264Sjacobs papi_attribute_value_t *value)
542264Sjacobs {
552264Sjacobs if (value != NULL) {
562264Sjacobs switch (type) {
572264Sjacobs case PAPI_STRING:
582264Sjacobs if (value->string != NULL)
592264Sjacobs free(value->string);
602264Sjacobs break;
612264Sjacobs case PAPI_COLLECTION:
622264Sjacobs if (value->collection != NULL) {
632264Sjacobs int i;
642264Sjacobs
652264Sjacobs for (i = 0; value->collection[i] != NULL; i++)
662264Sjacobs papiAttributeFree(value->collection[i]);
672264Sjacobs
682264Sjacobs free(value->collection);
692264Sjacobs }
702264Sjacobs break;
712264Sjacobs default: /* don't need to free anything extra */
722264Sjacobs break;
732264Sjacobs }
742264Sjacobs
752264Sjacobs free(value);
762264Sjacobs }
772264Sjacobs }
782264Sjacobs
792264Sjacobs static void
papiAttributeValuesFree(papi_attribute_value_type_t type,papi_attribute_value_t ** values)802264Sjacobs papiAttributeValuesFree(papi_attribute_value_type_t type,
812264Sjacobs papi_attribute_value_t **values)
822264Sjacobs {
832264Sjacobs if (values != NULL) {
842264Sjacobs int i;
852264Sjacobs
862264Sjacobs for (i = 0; values[i] != NULL; i++)
872264Sjacobs papiAttributeValueFree(type, values[i]);
882264Sjacobs
892264Sjacobs free(values);
902264Sjacobs }
912264Sjacobs }
922264Sjacobs
932264Sjacobs static void
papiAttributeFree(papi_attribute_t * attribute)942264Sjacobs papiAttributeFree(papi_attribute_t *attribute)
952264Sjacobs {
962264Sjacobs if (attribute != NULL) {
972264Sjacobs if (attribute->name != NULL)
982264Sjacobs free(attribute->name);
992264Sjacobs if (attribute->values != NULL)
1002264Sjacobs papiAttributeValuesFree(attribute->type,
1012264Sjacobs attribute->values);
1022264Sjacobs free(attribute);
1032264Sjacobs }
1042264Sjacobs }
1052264Sjacobs
1062264Sjacobs void
papiAttributeListFree(papi_attribute_t ** list)1072264Sjacobs papiAttributeListFree(papi_attribute_t **list)
1082264Sjacobs {
1092264Sjacobs if (list != NULL) {
1102264Sjacobs int i;
1112264Sjacobs
1122264Sjacobs for (i = 0; list[i] != NULL; i++)
1132264Sjacobs papiAttributeFree(list[i]);
1142264Sjacobs
1152264Sjacobs free(list);
1162264Sjacobs }
1172264Sjacobs }
1182264Sjacobs
1192264Sjacobs static papi_attribute_t **
collection_dup(papi_attribute_t ** collection)1202264Sjacobs collection_dup(papi_attribute_t **collection)
1212264Sjacobs {
1222264Sjacobs papi_attribute_t **result = NULL;
1232264Sjacobs
1242264Sjacobs /* allows a NULL collection that is "empty" or "no value" */
1252264Sjacobs if (collection != NULL) {
1262264Sjacobs papi_status_t status = PAPI_OK;
1272264Sjacobs int i;
1282264Sjacobs
1292264Sjacobs for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK));
1302264Sjacobs i++) {
1312264Sjacobs papi_attribute_t *a = collection[i];
1322264Sjacobs
1332264Sjacobs status = papiAttributeListAddValue(&result,
1342264Sjacobs PAPI_ATTR_APPEND, a->name, a->type,
1352264Sjacobs NULL);
1362264Sjacobs if ((status == PAPI_OK) && (a->values != NULL)) {
1372264Sjacobs int j;
1382264Sjacobs
1392264Sjacobs for (j = 0; ((a->values[j] != NULL) &&
1402264Sjacobs (status == PAPI_OK)); j++)
1412264Sjacobs status = papiAttributeListAddValue(
1422264Sjacobs &result,
1432264Sjacobs PAPI_ATTR_APPEND,
1442264Sjacobs a->name, a->type,
1452264Sjacobs a->values[j]);
1462264Sjacobs }
1472264Sjacobs }
1482264Sjacobs if (status != PAPI_OK) {
1492264Sjacobs papiAttributeListFree(result);
1502264Sjacobs result = NULL;
1512264Sjacobs }
1522264Sjacobs }
1532264Sjacobs
1542264Sjacobs return (result);
1552264Sjacobs }
1562264Sjacobs
1572264Sjacobs static papi_attribute_value_t *
papiAttributeValueDup(papi_attribute_value_type_t type,papi_attribute_value_t * v)1582264Sjacobs papiAttributeValueDup(papi_attribute_value_type_t type,
1592264Sjacobs papi_attribute_value_t *v)
1602264Sjacobs {
1612264Sjacobs papi_attribute_value_t *result = NULL;
1622264Sjacobs
1632264Sjacobs if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) {
1642264Sjacobs switch (type) {
1652264Sjacobs case PAPI_STRING:
1662264Sjacobs if (v->string == NULL) {
1672264Sjacobs free(result);
1682264Sjacobs result = NULL;
1692264Sjacobs } else
1702264Sjacobs result->string = strdup(v->string);
1712264Sjacobs break;
1722264Sjacobs case PAPI_INTEGER:
1732264Sjacobs result->integer = v->integer;
1742264Sjacobs break;
1752264Sjacobs case PAPI_BOOLEAN:
1762264Sjacobs result->boolean = v->boolean;
1772264Sjacobs break;
1782264Sjacobs case PAPI_RANGE:
1792264Sjacobs result->range.lower = v->range.lower;
1802264Sjacobs result->range.upper = v->range.upper;
1812264Sjacobs break;
1822264Sjacobs case PAPI_RESOLUTION:
1832264Sjacobs result->resolution.xres = v->resolution.xres;
1842264Sjacobs result->resolution.yres = v->resolution.yres;
1852264Sjacobs result->resolution.units = v->resolution.units;
1862264Sjacobs break;
1872264Sjacobs case PAPI_DATETIME:
1882264Sjacobs result->datetime = v->datetime;
1892264Sjacobs break;
1902264Sjacobs case PAPI_COLLECTION:
1912264Sjacobs result->collection = collection_dup(v->collection);
1922264Sjacobs break;
1932264Sjacobs case PAPI_METADATA:
1942264Sjacobs result->metadata = v->metadata;
1952264Sjacobs break;
1962264Sjacobs default: /* unknown type, fail to duplicate */
1972264Sjacobs free(result);
1982264Sjacobs result = NULL;
1992264Sjacobs }
2002264Sjacobs }
2012264Sjacobs
2022264Sjacobs return (result);
2032264Sjacobs }
2042264Sjacobs
2052264Sjacobs static papi_attribute_t *
papiAttributeAlloc(char * name,papi_attribute_value_type_t type)2062264Sjacobs papiAttributeAlloc(char *name, papi_attribute_value_type_t type)
2072264Sjacobs {
2082264Sjacobs papi_attribute_t *result = NULL;
2092264Sjacobs
2102264Sjacobs if ((result = calloc(1, sizeof (*result))) != NULL) {
2112264Sjacobs result->name = strdup(name);
2122264Sjacobs result->type = type;
2132264Sjacobs }
2142264Sjacobs
2152264Sjacobs return (result);
2162264Sjacobs }
2172264Sjacobs
2182264Sjacobs static papi_status_t
papiAttributeListAppendValue(papi_attribute_value_t *** values,papi_attribute_value_type_t type,papi_attribute_value_t * value)2192264Sjacobs papiAttributeListAppendValue(papi_attribute_value_t ***values,
2202264Sjacobs papi_attribute_value_type_t type,
2212264Sjacobs papi_attribute_value_t *value)
2222264Sjacobs {
2232264Sjacobs
2242264Sjacobs if (values == NULL)
2252264Sjacobs return (PAPI_BAD_ARGUMENT);
2262264Sjacobs
2272264Sjacobs if (value != NULL) { /* this allows "empty" attributes */
2282264Sjacobs papi_attribute_value_t *tmp = NULL;
2292264Sjacobs
2302264Sjacobs if ((tmp = papiAttributeValueDup(type, value)) == NULL)
2312264Sjacobs return (PAPI_TEMPORARY_ERROR);
2322264Sjacobs
2332264Sjacobs list_append(values, tmp);
2342264Sjacobs }
2352264Sjacobs
2362264Sjacobs return (PAPI_OK);
2372264Sjacobs }
2382264Sjacobs
2392264Sjacobs papi_status_t
papiAttributeListAddValue(papi_attribute_t *** list,int flgs,char * name,papi_attribute_value_type_t type,papi_attribute_value_t * value)2402264Sjacobs papiAttributeListAddValue(papi_attribute_t ***list, int flgs,
2412264Sjacobs char *name, papi_attribute_value_type_t type,
2422264Sjacobs papi_attribute_value_t *value)
2432264Sjacobs {
2442264Sjacobs papi_status_t result;
2452264Sjacobs int flags = flgs;
2462264Sjacobs papi_attribute_t *attribute = NULL;
2472264Sjacobs papi_attribute_value_t **values = NULL;
2482264Sjacobs
2492264Sjacobs if ((list == NULL) || (name == NULL))
2502264Sjacobs return (PAPI_BAD_ARGUMENT);
2512264Sjacobs
2522264Sjacobs if ((type == PAPI_RANGE) && (value != NULL) &&
2532264Sjacobs (value->range.lower > value->range.upper))
2542264Sjacobs return (PAPI_BAD_ARGUMENT); /* RANGE must have min <= max */
2552264Sjacobs
2562264Sjacobs if (flags == 0) /* if it wasn't set, set a default behaviour */
2572264Sjacobs flags = PAPI_ATTR_APPEND;
2582264Sjacobs
2592264Sjacobs /* look for an existing one */
2602264Sjacobs attribute = papiAttributeListFind(*list, name);
2612264Sjacobs
2622264Sjacobs if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL))
2632264Sjacobs return (PAPI_CONFLICT); /* EXISTS */
2642264Sjacobs
2652264Sjacobs if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) &&
2662264Sjacobs (attribute->type != type))
2672264Sjacobs return (PAPI_CONFLICT); /* TYPE CONFLICT */
2682264Sjacobs
2692264Sjacobs /* if we don't have one, create it and add it to the list */
2702264Sjacobs if ((attribute == NULL) &&
2712264Sjacobs ((attribute = papiAttributeAlloc(name, type)) != NULL))
2722264Sjacobs list_append(list, attribute);
2732264Sjacobs
2742264Sjacobs /* if we don't have one by now, it's most likely an alloc fail */
2752264Sjacobs if (attribute == NULL)
2762264Sjacobs return (PAPI_TEMPORARY_ERROR);
2772264Sjacobs
2782264Sjacobs /*
2792264Sjacobs * if we are replacing, clear any existing values, but don't free
2802264Sjacobs * until after we have replaced the values, in case we are replacing
2812264Sjacobs * a collection with a relocated version of the original collection.
2822264Sjacobs */
2832264Sjacobs if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) {
2842264Sjacobs values = attribute->values;
2852264Sjacobs attribute->values = NULL;
2862264Sjacobs }
2872264Sjacobs
2882264Sjacobs attribute->type = type;
2892264Sjacobs
2902264Sjacobs result = papiAttributeListAppendValue(&attribute->values, type, value);
2912264Sjacobs
2922264Sjacobs /* free old values if we replaced them */
2932264Sjacobs if (values != NULL)
2942264Sjacobs papiAttributeValuesFree(type, values);
2952264Sjacobs
2962264Sjacobs return (result);
2972264Sjacobs }
2982264Sjacobs
2992264Sjacobs papi_status_t
papiAttributeListAddString(papi_attribute_t *** list,int flags,char * name,char * string)3002264Sjacobs papiAttributeListAddString(papi_attribute_t ***list, int flags,
3012264Sjacobs char *name, char *string)
3022264Sjacobs {
3032264Sjacobs papi_attribute_value_t v;
3042264Sjacobs
3052264Sjacobs v.string = (char *)string;
3062264Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v));
3072264Sjacobs }
3082264Sjacobs
3092264Sjacobs papi_status_t
papiAttributeListAddInteger(papi_attribute_t *** list,int flags,char * name,int integer)3102264Sjacobs papiAttributeListAddInteger(papi_attribute_t ***list, int flags,
3112264Sjacobs char *name, int integer)
3122264Sjacobs {
3132264Sjacobs papi_attribute_value_t v;
3142264Sjacobs
3152264Sjacobs v.integer = integer;
3162264Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v));
3172264Sjacobs }
3182264Sjacobs
3192264Sjacobs papi_status_t
papiAttributeListAddBoolean(papi_attribute_t *** list,int flags,char * name,char boolean)3202264Sjacobs papiAttributeListAddBoolean(papi_attribute_t ***list, int flags,
3212264Sjacobs char *name, char boolean)
3222264Sjacobs {
3232264Sjacobs papi_attribute_value_t v;
3242264Sjacobs
3252264Sjacobs v.boolean = boolean;
3262264Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v));
3272264Sjacobs }
3282264Sjacobs
3292264Sjacobs papi_status_t
papiAttributeListAddRange(papi_attribute_t *** list,int flags,char * name,int lower,int upper)3302264Sjacobs papiAttributeListAddRange(papi_attribute_t ***list, int flags,
3312264Sjacobs char *name, int lower, int upper)
3322264Sjacobs {
3332264Sjacobs papi_attribute_value_t v;
3342264Sjacobs
3352264Sjacobs v.range.lower = lower;
3362264Sjacobs v.range.upper = upper;
3372264Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v));
3382264Sjacobs }
3392264Sjacobs
3402264Sjacobs papi_status_t
papiAttributeListAddResolution(papi_attribute_t *** list,int flags,char * name,int xres,int yres,papi_resolution_unit_t units)3412264Sjacobs papiAttributeListAddResolution(papi_attribute_t ***list, int flags,
3422264Sjacobs char *name, int xres, int yres,
3432264Sjacobs papi_resolution_unit_t units)
3442264Sjacobs {
3452264Sjacobs papi_attribute_value_t v;
3462264Sjacobs
3472264Sjacobs v.resolution.xres = xres;
3482264Sjacobs v.resolution.yres = yres;
3492264Sjacobs v.resolution.units = units;
3502264Sjacobs return (papiAttributeListAddValue(list, flags, name,
3512264Sjacobs PAPI_RESOLUTION, &v));
3522264Sjacobs }
3532264Sjacobs
3542264Sjacobs papi_status_t
papiAttributeListAddDatetime(papi_attribute_t *** list,int flags,char * name,time_t datetime)3552264Sjacobs papiAttributeListAddDatetime(papi_attribute_t ***list, int flags,
3562264Sjacobs char *name, time_t datetime)
3572264Sjacobs {
3582264Sjacobs papi_attribute_value_t v;
3592264Sjacobs
3602264Sjacobs v.datetime = datetime;
3612264Sjacobs return (papiAttributeListAddValue(list, flags, name,
3622264Sjacobs PAPI_DATETIME, &v));
3632264Sjacobs }
3642264Sjacobs
3652264Sjacobs papi_status_t
papiAttributeListAddCollection(papi_attribute_t *** list,int flags,char * name,papi_attribute_t ** collection)3662264Sjacobs papiAttributeListAddCollection(papi_attribute_t ***list, int flags,
3672264Sjacobs char *name, papi_attribute_t **collection)
3682264Sjacobs {
3692264Sjacobs papi_attribute_value_t v;
3702264Sjacobs
3712264Sjacobs v.collection = (papi_attribute_t **)collection;
3722264Sjacobs return (papiAttributeListAddValue(list, flags, name,
3732264Sjacobs PAPI_COLLECTION, &v));
3742264Sjacobs }
3752264Sjacobs
3762264Sjacobs papi_status_t
papiAttributeListAddMetadata(papi_attribute_t *** list,int flags,char * name,papi_metadata_t metadata)3772264Sjacobs papiAttributeListAddMetadata(papi_attribute_t ***list, int flags,
3782264Sjacobs char *name, papi_metadata_t metadata)
3792264Sjacobs {
3802264Sjacobs papi_attribute_value_t v;
3812264Sjacobs
3822264Sjacobs v.metadata = metadata;
3832264Sjacobs return (papiAttributeListAddValue(list, flags, name,
3842264Sjacobs PAPI_METADATA, &v));
3852264Sjacobs }
3862264Sjacobs
3872264Sjacobs papi_status_t
papiAttributeListDelete(papi_attribute_t *** list,char * name)3882264Sjacobs papiAttributeListDelete(papi_attribute_t ***list, char *name)
3892264Sjacobs {
3902264Sjacobs papi_attribute_t *attribute;
3912264Sjacobs
3922264Sjacobs if ((list == NULL) || (name == NULL))
3932264Sjacobs return (PAPI_BAD_ARGUMENT);
3942264Sjacobs
3952264Sjacobs if ((attribute = papiAttributeListFind(*list, name)) == NULL)
3962264Sjacobs return (PAPI_NOT_FOUND);
3972264Sjacobs
3983125Sjacobs list_remove(list, attribute);
3992264Sjacobs papiAttributeFree(attribute);
4002264Sjacobs
4012264Sjacobs return (PAPI_OK);
4022264Sjacobs }
4032264Sjacobs
4042264Sjacobs papi_attribute_t *
papiAttributeListFind(papi_attribute_t ** list,char * name)4052264Sjacobs papiAttributeListFind(papi_attribute_t **list, char *name)
4062264Sjacobs {
4072264Sjacobs int i;
4082264Sjacobs if ((list == NULL) || (name == NULL))
4092264Sjacobs return (NULL);
4102264Sjacobs
4112264Sjacobs for (i = 0; list[i] != NULL; i++)
4122264Sjacobs if (strcasecmp(list[i]->name, name) == 0)
4132264Sjacobs return ((papi_attribute_t *)list[i]);
4142264Sjacobs
4152264Sjacobs return (NULL);
4162264Sjacobs }
4172264Sjacobs
4182264Sjacobs papi_attribute_t *
papiAttributeListGetNext(papi_attribute_t ** list,void ** iter)4192264Sjacobs papiAttributeListGetNext(papi_attribute_t **list, void **iter)
4202264Sjacobs {
4212264Sjacobs papi_attribute_t **tmp, *result;
4222264Sjacobs
4232264Sjacobs if ((list == NULL) && (iter == NULL))
4242264Sjacobs return (NULL);
4252264Sjacobs
4262264Sjacobs if (*iter == NULL)
4272264Sjacobs *iter = list;
4282264Sjacobs
4292264Sjacobs tmp = *iter;
4302264Sjacobs result = *tmp;
4312264Sjacobs *iter = ++tmp;
4322264Sjacobs
4332264Sjacobs return (result);
4342264Sjacobs }
4352264Sjacobs
4362264Sjacobs papi_status_t
papiAttributeListGetValue(papi_attribute_t ** list,void ** iter,char * name,papi_attribute_value_type_t type,papi_attribute_value_t ** value)4372264Sjacobs papiAttributeListGetValue(papi_attribute_t **list, void **iter,
4382264Sjacobs char *name, papi_attribute_value_type_t type,
4392264Sjacobs papi_attribute_value_t **value)
4402264Sjacobs {
4412264Sjacobs papi_attribute_value_t **tmp;
4422264Sjacobs void *fodder = NULL;
4432264Sjacobs
4442264Sjacobs if ((list == NULL) || ((name == NULL) && (iter == NULL)) ||
4452264Sjacobs (value == NULL))
4462264Sjacobs return (PAPI_BAD_ARGUMENT);
4472264Sjacobs
4482264Sjacobs if (iter == NULL)
4492264Sjacobs iter = &fodder;
4502264Sjacobs
4512264Sjacobs if ((iter == NULL) || (*iter == NULL)) {
4522264Sjacobs papi_attribute_t *attr = papiAttributeListFind(list, name);
4532264Sjacobs
4542264Sjacobs if (attr == NULL)
4552264Sjacobs return (PAPI_NOT_FOUND);
4562264Sjacobs
4572264Sjacobs if (attr->type != type)
4582264Sjacobs return (PAPI_NOT_POSSIBLE);
4592264Sjacobs
4602264Sjacobs tmp = attr->values;
4612264Sjacobs } else
4622264Sjacobs tmp = *iter;
4632264Sjacobs
4642264Sjacobs if (tmp == NULL)
4652264Sjacobs return (PAPI_NOT_FOUND);
4662264Sjacobs
4672264Sjacobs *value = *tmp;
4682264Sjacobs *iter = ++tmp;
4692264Sjacobs
4702264Sjacobs if (*value == NULL)
4712264Sjacobs return (PAPI_GONE);
4722264Sjacobs
4732264Sjacobs return (PAPI_OK);
4742264Sjacobs }
4752264Sjacobs
4762264Sjacobs papi_status_t
papiAttributeListGetString(papi_attribute_t ** list,void ** iter,char * name,char ** vptr)4772264Sjacobs papiAttributeListGetString(papi_attribute_t **list, void **iter,
4782264Sjacobs char *name, char **vptr)
4792264Sjacobs {
4802264Sjacobs papi_status_t status;
4812264Sjacobs papi_attribute_value_t *value = NULL;
4822264Sjacobs
4832264Sjacobs if (vptr == NULL)
4842264Sjacobs return (PAPI_BAD_ARGUMENT);
4852264Sjacobs
4862264Sjacobs status = papiAttributeListGetValue(list, iter, name,
4872264Sjacobs PAPI_STRING, &value);
4882264Sjacobs if (status == PAPI_OK)
4892264Sjacobs *vptr = value->string;
4902264Sjacobs
4912264Sjacobs return (status);
4922264Sjacobs }
4932264Sjacobs
4942264Sjacobs papi_status_t
papiAttributeListGetInteger(papi_attribute_t ** list,void ** iter,char * name,int * vptr)4952264Sjacobs papiAttributeListGetInteger(papi_attribute_t **list, void **iter,
4962264Sjacobs char *name, int *vptr)
4972264Sjacobs {
4982264Sjacobs papi_status_t status;
4992264Sjacobs papi_attribute_value_t *value = NULL;
5002264Sjacobs
5012264Sjacobs if (vptr == NULL)
5022264Sjacobs return (PAPI_BAD_ARGUMENT);
5032264Sjacobs
5042264Sjacobs status = papiAttributeListGetValue(list, iter, name,
5052264Sjacobs PAPI_INTEGER, &value);
5062264Sjacobs if (status == PAPI_OK)
5072264Sjacobs *vptr = value->integer;
5082264Sjacobs
5092264Sjacobs return (status);
5102264Sjacobs }
5112264Sjacobs
5122264Sjacobs papi_status_t
papiAttributeListGetBoolean(papi_attribute_t ** list,void ** iter,char * name,char * vptr)5132264Sjacobs papiAttributeListGetBoolean(papi_attribute_t **list, void **iter,
5142264Sjacobs char *name, char *vptr)
5152264Sjacobs {
5162264Sjacobs papi_status_t status;
5172264Sjacobs papi_attribute_value_t *value = NULL;
5182264Sjacobs
5192264Sjacobs if (vptr == NULL)
5202264Sjacobs return (PAPI_BAD_ARGUMENT);
5212264Sjacobs
5222264Sjacobs status = papiAttributeListGetValue(list, iter, name,
5232264Sjacobs PAPI_BOOLEAN, &value);
5242264Sjacobs if (status == PAPI_OK)
5252264Sjacobs *vptr = value->boolean;
5262264Sjacobs
5272264Sjacobs return (status);
5282264Sjacobs }
5292264Sjacobs
5302264Sjacobs papi_status_t
papiAttributeListGetRange(papi_attribute_t ** list,void ** iter,char * name,int * min,int * max)5312264Sjacobs papiAttributeListGetRange(papi_attribute_t **list, void **iter,
5322264Sjacobs char *name, int *min, int *max)
5332264Sjacobs {
5342264Sjacobs papi_status_t status;
5352264Sjacobs papi_attribute_value_t *value = NULL;
5362264Sjacobs
5372264Sjacobs if ((min == NULL) || (max == NULL))
5382264Sjacobs return (PAPI_BAD_ARGUMENT);
5392264Sjacobs
5402264Sjacobs status = papiAttributeListGetValue(list, iter, name,
5412264Sjacobs PAPI_RANGE, &value);
5422264Sjacobs if (status == PAPI_OK) {
5432264Sjacobs *min = value->range.lower;
5442264Sjacobs *max = value->range.upper;
5452264Sjacobs }
5462264Sjacobs
5472264Sjacobs return (status);
5482264Sjacobs }
5492264Sjacobs
5502264Sjacobs papi_status_t
papiAttributeListGetResolution(papi_attribute_t ** list,void ** iter,char * name,int * x,int * y,papi_resolution_unit_t * units)5512264Sjacobs papiAttributeListGetResolution(papi_attribute_t **list, void **iter,
5522264Sjacobs char *name, int *x, int *y,
5532264Sjacobs papi_resolution_unit_t *units)
5542264Sjacobs {
5552264Sjacobs papi_status_t status;
5562264Sjacobs papi_attribute_value_t *value = NULL;
5572264Sjacobs
5582264Sjacobs if ((x == NULL) || (y == NULL) || (units == NULL))
5592264Sjacobs return (PAPI_BAD_ARGUMENT);
5602264Sjacobs
5612264Sjacobs status = papiAttributeListGetValue(list, iter, name,
5622264Sjacobs PAPI_RESOLUTION, &value);
5632264Sjacobs if (status == PAPI_OK) {
5642264Sjacobs *x = value->resolution.xres;
5652264Sjacobs *y = value->resolution.yres;
5662264Sjacobs *units = value->resolution.units;
5672264Sjacobs }
5682264Sjacobs
5692264Sjacobs return (status);
5702264Sjacobs }
5712264Sjacobs
5722264Sjacobs papi_status_t
papiAttributeListGetDatetime(papi_attribute_t ** list,void ** iter,char * name,time_t * dt)5732264Sjacobs papiAttributeListGetDatetime(papi_attribute_t **list, void **iter,
5742264Sjacobs char *name, time_t *dt)
5752264Sjacobs {
5762264Sjacobs papi_status_t status;
5772264Sjacobs papi_attribute_value_t *value = NULL;
5782264Sjacobs
5792264Sjacobs if (dt == NULL)
5802264Sjacobs return (PAPI_BAD_ARGUMENT);
5812264Sjacobs
5822264Sjacobs status = papiAttributeListGetValue(list, iter, name,
5832264Sjacobs PAPI_DATETIME, &value);
5842264Sjacobs if (status == PAPI_OK) {
5852264Sjacobs *dt = value->datetime;
5862264Sjacobs }
5872264Sjacobs
5882264Sjacobs return (status);
5892264Sjacobs }
5902264Sjacobs
5912264Sjacobs papi_status_t
papiAttributeListGetCollection(papi_attribute_t ** list,void ** iter,char * name,papi_attribute_t *** collection)5922264Sjacobs papiAttributeListGetCollection(papi_attribute_t **list, void **iter,
5932264Sjacobs char *name, papi_attribute_t ***collection)
5942264Sjacobs {
5952264Sjacobs papi_status_t status;
5962264Sjacobs papi_attribute_value_t *value = NULL;
5972264Sjacobs
5982264Sjacobs if (collection == NULL)
5992264Sjacobs return (PAPI_BAD_ARGUMENT);
6002264Sjacobs
6012264Sjacobs status = papiAttributeListGetValue(list, iter, name,
6022264Sjacobs PAPI_COLLECTION, &value);
6032264Sjacobs if (status == PAPI_OK) {
6042264Sjacobs *collection = value->collection;
6052264Sjacobs }
6062264Sjacobs
6072264Sjacobs return (status);
6082264Sjacobs }
6092264Sjacobs
6102264Sjacobs papi_status_t
papiAttributeListGetMetadata(papi_attribute_t ** list,void ** iter,char * name,papi_metadata_t * vptr)6112264Sjacobs papiAttributeListGetMetadata(papi_attribute_t **list, void **iter,
6122264Sjacobs char *name, papi_metadata_t *vptr)
6132264Sjacobs {
6142264Sjacobs papi_status_t status;
6152264Sjacobs papi_attribute_value_t *value = NULL;
6162264Sjacobs
6172264Sjacobs if (vptr == NULL)
6182264Sjacobs return (PAPI_BAD_ARGUMENT);
6192264Sjacobs
6202264Sjacobs status = papiAttributeListGetValue(list, iter, name,
6212264Sjacobs PAPI_METADATA, &value);
6222264Sjacobs if (status == PAPI_OK)
6232264Sjacobs *vptr = value->metadata;
6242264Sjacobs
6252264Sjacobs return (status);
6262264Sjacobs }
6272264Sjacobs
6282264Sjacobs
6296725Sjacobs /* The string is modified by this call */
6302264Sjacobs static char *
regvalue(regmatch_t match,char * string)6316725Sjacobs regvalue(regmatch_t match, char *string)
6322264Sjacobs {
6332264Sjacobs char *result = NULL;
6346725Sjacobs if (match.rm_so != match.rm_eo) {
6356725Sjacobs result = string + match.rm_so;
6366725Sjacobs *(result + (match.rm_eo - match.rm_so)) = '\0';
6376725Sjacobs }
6386725Sjacobs return (result);
6396725Sjacobs }
6402264Sjacobs
6416725Sjacobs static papi_attribute_value_type_t
_process_value(char * string,char *** parts)6426725Sjacobs _process_value(char *string, char ***parts)
6436725Sjacobs {
6446725Sjacobs int i;
6456725Sjacobs static struct {
6466725Sjacobs papi_attribute_value_type_t type;
6476725Sjacobs size_t vals;
6486725Sjacobs char *expression;
6496725Sjacobs int compiled;
6506725Sjacobs regex_t re;
6516725Sjacobs } types[] = {
6526725Sjacobs { PAPI_BOOLEAN, 1, "^(true|false|yes|no)$", 0 },
6536725Sjacobs { PAPI_COLLECTION, 1, "^\\{(.+)\\}$", 0 },
6546725Sjacobs /* PAPI_DATETIME is unsupported, too much like an integer */
6556725Sjacobs { PAPI_INTEGER, 1, "^([+-]{0,1}[[:digit:]]+)$", 0 },
656*7154Ssg223391 { PAPI_RANGE, 3, "^([[:digit:]]*)-([[:digit:]]*)$", 0 },
6576725Sjacobs { PAPI_RESOLUTION, 4, "^([[:digit:]]+)x([[:digit:]]+)dp(i|c)$",
6586725Sjacobs 0 },
6596725Sjacobs NULL
6606725Sjacobs };
6616725Sjacobs regmatch_t matches[4];
6626725Sjacobs
6636725Sjacobs for (i = 0; i < 5; i++) {
6646725Sjacobs int j;
6656725Sjacobs
6666725Sjacobs if (types[i].compiled == 0) {
6676725Sjacobs (void) regcomp(&(types[i].re), types[i].expression,
6686725Sjacobs REG_EXTENDED|REG_ICASE);
6696725Sjacobs types[i].compiled = 1;
6702264Sjacobs }
6716725Sjacobs if (regexec(&(types[i].re), string, (size_t)types[i].vals,
6726725Sjacobs matches, 0) == REG_NOMATCH)
6736725Sjacobs continue;
6746725Sjacobs
6756725Sjacobs for (j = 0 ; j < types[i].vals; j++)
6766725Sjacobs list_append(parts, regvalue(matches[j], string));
6776725Sjacobs return (types[i].type);
6786725Sjacobs }
6792264Sjacobs
6806725Sjacobs list_append(parts, string);
6816725Sjacobs return (PAPI_STRING);
6826725Sjacobs }
6836725Sjacobs
6846725Sjacobs static void
_add_attribute_value(papi_attribute_value_t *** list,papi_attribute_value_type_t type,papi_attribute_value_type_t dtype,char ** parts)6856725Sjacobs _add_attribute_value(papi_attribute_value_t ***list,
6866725Sjacobs papi_attribute_value_type_t type,
6876725Sjacobs papi_attribute_value_type_t dtype, char **parts)
6886725Sjacobs {
6896725Sjacobs papi_attribute_value_t *value = calloc(1, sizeof (*value));
6902264Sjacobs
6916725Sjacobs switch(type) {
6926725Sjacobs case PAPI_STRING:
6936725Sjacobs value->string = strdup(parts[0]);
6946725Sjacobs list_append(list, value);
6956725Sjacobs break;
6966725Sjacobs case PAPI_BOOLEAN:
6976725Sjacobs value->boolean = PAPI_TRUE;
6986725Sjacobs if ((strcasecmp(parts[0], "false") == 0) ||
6996725Sjacobs (strcasecmp(parts[0], "no") == 0))
7006725Sjacobs value->boolean = PAPI_FALSE;
7016725Sjacobs list_append(list, value);
7026725Sjacobs break;
7036725Sjacobs case PAPI_INTEGER:
7046725Sjacobs value->integer = atoi(parts[0]);
7056725Sjacobs list_append(list, value);
7066725Sjacobs break;
7076725Sjacobs case PAPI_RANGE:
708*7154Ssg223391 if (dtype == PAPI_INTEGER) {
709*7154Ssg223391 if (atoi(parts[0]) < 0) {
710*7154Ssg223391 /*
711*7154Ssg223391 * Handles -P -x case
712*7154Ssg223391 * which prints from page number 1
713*7154Ssg223391 * till page number x
714*7154Ssg223391 */
715*7154Ssg223391 value->range.lower = 1;
716*7154Ssg223391 value->range.upper = 0 - (atoi(parts[0]));
717*7154Ssg223391 } else {
718*7154Ssg223391 value->range.lower = value->range.upper
719*7154Ssg223391 = atoi(parts[0]);
720*7154Ssg223391 }
721*7154Ssg223391 } else if (dtype == PAPI_RANGE) {
722*7154Ssg223391 if (parts[2] == NULL) {
723*7154Ssg223391 value->range.lower = atoi(parts[1]);
724*7154Ssg223391 /*
725*7154Ssg223391 * Imposing an artificial limit on
726*7154Ssg223391 * the upper bound for page range.
727*7154Ssg223391 */
728*7154Ssg223391 value->range.upper = MAX_PAGES;
729*7154Ssg223391 } else if ((parts[1] != NULL) && (parts[2] != NULL)) {
730*7154Ssg223391 value->range.lower = atoi(parts[1]);
731*7154Ssg223391 value->range.upper = atoi(parts[2]);
732*7154Ssg223391 }
7332264Sjacobs }
7346725Sjacobs list_append(list, value);
7356725Sjacobs break;
7366725Sjacobs case PAPI_RESOLUTION:
7376725Sjacobs value->resolution.xres = atoi(parts[1]);
7386725Sjacobs value->resolution.yres = atoi(parts[2]);
7396725Sjacobs if (parts[3][0] == 'i')
7406725Sjacobs value->resolution.units = PAPI_RES_PER_INCH;
7416725Sjacobs else
7426725Sjacobs value->resolution.units = PAPI_RES_PER_CM;
7436725Sjacobs list_append(list, value);
7446725Sjacobs break;
7456725Sjacobs case PAPI_COLLECTION:
7466725Sjacobs papiAttributeListFromString(&(value->collection), 0, parts[0]);
7476725Sjacobs list_append(list, value);
7486725Sjacobs break;
7496725Sjacobs }
7506725Sjacobs }
7512264Sjacobs
7526725Sjacobs static papi_status_t
_papiAttributeFromStrings(papi_attribute_t *** list,int flags,char * key,char ** values)7536725Sjacobs _papiAttributeFromStrings(papi_attribute_t ***list, int flags,
7546725Sjacobs char *key, char **values)
7556725Sjacobs {
7566725Sjacobs int i;
7576725Sjacobs papi_status_t result = PAPI_OK;
7586725Sjacobs papi_attribute_t *attr = calloc(1, sizeof (*attr));
7596725Sjacobs
7606725Sjacobs /* these are specified in the papi spec as ranges */
7616725Sjacobs char *ranges[] = { "copies-supported", "job-impressions-supported",
7626725Sjacobs "job-k-octets-supported",
7636725Sjacobs "job-media-sheets-supported", "page-ranges",
7646725Sjacobs NULL };
7656725Sjacobs
7666725Sjacobs if ((attr == NULL) || ((attr->name = strdup(key)) == NULL))
7676725Sjacobs return (PAPI_TEMPORARY_ERROR);
7686725Sjacobs
7696725Sjacobs attr->type = PAPI_METADATA;
7706725Sjacobs /* these are known ranges */
7716725Sjacobs for (i = 0; ranges[i] != NULL; i++)
7726725Sjacobs if (strcasecmp(attr->name, ranges[i]) == 0) {
7736725Sjacobs attr->type = PAPI_RANGE;
7746725Sjacobs break;
7756725Sjacobs }
7766725Sjacobs
7776725Sjacobs if (values != NULL) {
7786725Sjacobs papi_attribute_value_t **vals = NULL;
7796725Sjacobs
7806725Sjacobs for (i = 0; values[i] != NULL; i++) {
7816725Sjacobs papi_attribute_value_type_t dtype;
7826725Sjacobs char **parts = NULL;
7836725Sjacobs
7846725Sjacobs dtype = _process_value(values[i], &parts);
7856725Sjacobs if (attr->type == PAPI_METADATA)
7866725Sjacobs attr->type = dtype;
7876725Sjacobs _add_attribute_value(&vals, attr->type, dtype, parts);
7886725Sjacobs free(parts);
7892264Sjacobs }
7906725Sjacobs attr->values = vals;
7916725Sjacobs }
7926725Sjacobs
7936725Sjacobs list_append(list, attr);
7946725Sjacobs
7956725Sjacobs return (result);
7966725Sjacobs }
7972264Sjacobs
7986725Sjacobs static papi_status_t
_parse_attribute_list(papi_attribute_t *** list,int flags,char * string)7996725Sjacobs _parse_attribute_list(papi_attribute_t ***list, int flags, char *string)
8006725Sjacobs {
8016725Sjacobs papi_status_t result = PAPI_OK;
8026725Sjacobs char *ptr;
8036725Sjacobs
8046725Sjacobs if ((list == NULL) || (string == NULL))
8056725Sjacobs return (PAPI_BAD_ARGUMENT);
8066725Sjacobs
8076725Sjacobs if ((ptr = strdup(string)) == NULL)
8086725Sjacobs return (PAPI_TEMPORARY_ERROR);
8096725Sjacobs
8106725Sjacobs while ((*ptr != '\0') && (result == PAPI_OK)) {
8116725Sjacobs char *key, **values = NULL;
8126725Sjacobs
8136725Sjacobs /* strip any leading whitespace */
8146725Sjacobs while (isspace(*ptr) != 0)
8156725Sjacobs ptr++;
8166725Sjacobs
8176725Sjacobs /* Get the name: name[=value] */
8186725Sjacobs key = ptr;
8196725Sjacobs while ((*ptr != '\0') && (*ptr != '=') && (isspace(*ptr) == 0))
8206725Sjacobs ptr++;
8216725Sjacobs
8226725Sjacobs if (*ptr == '=') {
8236725Sjacobs *ptr++ = '\0';
8246725Sjacobs
8256725Sjacobs while ((*ptr != '\0') && (isspace(*ptr) == 0)) {
8266725Sjacobs char *value = ptr;
8276725Sjacobs
8286725Sjacobs if ((*ptr == '\'') || (*ptr == '"')) {
8296725Sjacobs char q = *ptr++;
8302264Sjacobs
8316725Sjacobs /* quoted string value */
8326725Sjacobs while ((*ptr != '\0') && (*ptr != q))
8336725Sjacobs ptr++;
8346725Sjacobs if (*ptr == q)
8356725Sjacobs ptr++;
8366725Sjacobs } else if (*ptr == '{') {
8376725Sjacobs /* collection */
8386725Sjacobs while ((*ptr != '\0') && (*ptr != '}'))
8396725Sjacobs ptr++;
8406725Sjacobs if (*ptr == '}')
8416725Sjacobs ptr++;
8426725Sjacobs } else {
8436725Sjacobs /* value */
8446725Sjacobs while ((*ptr != '\0') &&
8456725Sjacobs (*ptr != ',') &&
8466725Sjacobs (isspace(*ptr) == 0))
8476725Sjacobs ptr++;
8486725Sjacobs }
8496725Sjacobs if (*ptr == ',')
8506725Sjacobs *ptr++ = '\0';
8516725Sjacobs list_append(&values, value);
8522264Sjacobs }
8536725Sjacobs } else { /* boolean "[no]key" */
8546725Sjacobs char *value = "true";
8556725Sjacobs
8566725Sjacobs if (strncasecmp(key, "no", 2) == 0) {
8576725Sjacobs key += 2;
8586725Sjacobs value = "false";
8596725Sjacobs }
8606725Sjacobs list_append(&values, value);
8612264Sjacobs }
8626725Sjacobs if (*ptr != '\0')
8636725Sjacobs *ptr++ = '\0';
8646725Sjacobs
8656725Sjacobs result = _papiAttributeFromStrings(list, flags, key, values);
8666725Sjacobs free(values);
8672264Sjacobs }
8682264Sjacobs
8692264Sjacobs return (result);
8706725Sjacobs }
8712264Sjacobs
8722264Sjacobs papi_status_t
papiAttributeListFromString(papi_attribute_t *** attrs,int flags,char * string)8732264Sjacobs papiAttributeListFromString(papi_attribute_t ***attrs,
8742264Sjacobs int flags, char *string)
8752264Sjacobs {
8762264Sjacobs papi_status_t result = PAPI_OK;
8772264Sjacobs
8782264Sjacobs if ((attrs != NULL) && (string != NULL) &&
8792264Sjacobs ((flags & ~(PAPI_ATTR_APPEND+PAPI_ATTR_REPLACE+PAPI_ATTR_EXCL))
8802264Sjacobs == 0)) {
8816725Sjacobs result = _parse_attribute_list(attrs, flags, string);
8826725Sjacobs } else {
8832264Sjacobs result = PAPI_BAD_ARGUMENT;
8842264Sjacobs }
8852264Sjacobs
8862264Sjacobs return (result);
8872264Sjacobs }
8882264Sjacobs
8892264Sjacobs static papi_status_t
papiAttributeToString(papi_attribute_t * attribute,char * delim,char * buffer,size_t buflen)8902264Sjacobs papiAttributeToString(papi_attribute_t *attribute, char *delim,
8912264Sjacobs char *buffer, size_t buflen)
8922264Sjacobs {
8932264Sjacobs papi_attribute_value_t **values = attribute->values;
8942264Sjacobs int rc, i;
8952264Sjacobs
8966725Sjacobs if ((attribute->type == PAPI_BOOLEAN) && (values[1] == NULL)) {
8976725Sjacobs if (values[0]->boolean == PAPI_FALSE) {
8986725Sjacobs if (isupper(attribute->name[0]) == 0)
8996725Sjacobs strlcat(buffer, "no", buflen);
9006725Sjacobs else
9016725Sjacobs strlcat(buffer, "No", buflen);
9026725Sjacobs }
9036725Sjacobs rc = strlcat(buffer, attribute->name, buflen);
9046725Sjacobs } else {
9056725Sjacobs strlcat(buffer, attribute->name, buflen);
9066725Sjacobs rc = strlcat(buffer, "=", buflen);
9076725Sjacobs }
9082264Sjacobs
9092264Sjacobs if (values == NULL)
9102264Sjacobs return (PAPI_OK);
9112264Sjacobs
9122264Sjacobs for (i = 0; values[i] != NULL; i++) {
9132264Sjacobs switch (attribute->type) {
9142264Sjacobs case PAPI_STRING:
9152264Sjacobs rc = strlcat(buffer, values[i]->string, buflen);
9162264Sjacobs break;
9172264Sjacobs case PAPI_INTEGER: {
9182264Sjacobs char string[24];
9192264Sjacobs
9202264Sjacobs snprintf(string, sizeof (string), "%d",
9212264Sjacobs values[i]->integer);
9222264Sjacobs rc = strlcat(buffer, string, buflen);
9232264Sjacobs }
9242264Sjacobs break;
9252264Sjacobs case PAPI_BOOLEAN:
9266725Sjacobs if (values[1] != NULL)
9276725Sjacobs rc = strlcat(buffer, (values[i]->boolean ?
9286725Sjacobs "true" : "false"), buflen);
9292264Sjacobs break;
9302264Sjacobs case PAPI_RANGE: {
9312264Sjacobs char string[24];
9322264Sjacobs
9336725Sjacobs if (values[i]->range.lower == values[i]->range.upper)
9346725Sjacobs snprintf(string, sizeof (string), "%d",
9356725Sjacobs values[i]->range.lower);
9366725Sjacobs else
9376725Sjacobs snprintf(string, sizeof (string), "%d-%d",
9386725Sjacobs values[i]->range.lower,
9396725Sjacobs values[i]->range.upper);
9402264Sjacobs rc = strlcat(buffer, string, buflen);
9412264Sjacobs }
9422264Sjacobs break;
9432264Sjacobs case PAPI_RESOLUTION: {
9442264Sjacobs char string[24];
9452264Sjacobs
9462264Sjacobs snprintf(string, sizeof (string), "%dx%ddp%c",
9472264Sjacobs values[i]->resolution.xres,
9482264Sjacobs values[i]->resolution.yres,
9492264Sjacobs (values[i]->resolution.units == PAPI_RES_PER_CM
9502264Sjacobs ? 'c' : 'i'));
9512264Sjacobs rc = strlcat(buffer, string, buflen);
9522264Sjacobs }
9532264Sjacobs break;
9542264Sjacobs case PAPI_DATETIME: {
9552264Sjacobs struct tm *tm = localtime(&values[i]->datetime);
9562264Sjacobs
9572264Sjacobs if (tm != NULL) {
9582264Sjacobs char string[64];
9592264Sjacobs
9602264Sjacobs strftime(string, sizeof (string), "%C", tm);
9612264Sjacobs rc = strlcat(buffer, string, buflen);
9622264Sjacobs }}
9632264Sjacobs break;
9642264Sjacobs case PAPI_COLLECTION: {
9652264Sjacobs char *string = alloca(buflen);
9662264Sjacobs
9672264Sjacobs papiAttributeListToString(values[i]->collection,
9682264Sjacobs delim, string, buflen);
9692264Sjacobs rc = strlcat(buffer, string, buflen);
9702264Sjacobs }
9712264Sjacobs break;
9722264Sjacobs default: {
9732264Sjacobs char string[32];
9742264Sjacobs
9752264Sjacobs snprintf(string, sizeof (string), "unknown-type-0x%x",
9762264Sjacobs attribute->type);
9772264Sjacobs rc = strlcat(buffer, string, buflen);
9782264Sjacobs }
9792264Sjacobs }
9802264Sjacobs if (values[i+1] != NULL)
9812264Sjacobs rc = strlcat(buffer, ",", buflen);
9822264Sjacobs
9832264Sjacobs if (rc >= buflen)
9842264Sjacobs return (PAPI_NOT_POSSIBLE);
9852264Sjacobs
9862264Sjacobs }
9872264Sjacobs
9882264Sjacobs return (PAPI_OK);
9892264Sjacobs }
9902264Sjacobs
9912264Sjacobs papi_status_t
papiAttributeListToString(papi_attribute_t ** attrs,char * delim,char * buffer,size_t buflen)9922264Sjacobs papiAttributeListToString(papi_attribute_t **attrs,
9932264Sjacobs char *delim, char *buffer, size_t buflen)
9942264Sjacobs {
9952264Sjacobs papi_status_t status = PAPI_OK;
9962264Sjacobs int i;
9972264Sjacobs
9982264Sjacobs if ((attrs == NULL) || (buffer == NULL))
9992264Sjacobs return (PAPI_BAD_ARGUMENT);
10002264Sjacobs
10012264Sjacobs buffer[0] = '\0';
10022264Sjacobs if (!delim)
10032264Sjacobs delim = " ";
10042264Sjacobs
10052264Sjacobs for (i = 0; ((attrs[i] != NULL) && (status == PAPI_OK)); i++) {
10062264Sjacobs status = papiAttributeToString(attrs[i], delim, buffer, buflen);
10072264Sjacobs if (attrs[i+1] != NULL)
10082264Sjacobs strlcat(buffer, delim, buflen);
10092264Sjacobs }
10102264Sjacobs
10112264Sjacobs return (status);
10122264Sjacobs }
10132264Sjacobs
10142264Sjacobs static int
is_in_list(char * value,char ** list)10152264Sjacobs is_in_list(char *value, char **list)
10162264Sjacobs {
10172264Sjacobs if ((list != NULL) && (value != NULL)) {
10182264Sjacobs int i;
10192264Sjacobs
10202264Sjacobs for (i = 0; list[i] != NULL; i++)
10212264Sjacobs if (strcasecmp(value, list[i]) == 0)
10222264Sjacobs return (0);
10232264Sjacobs }
10242264Sjacobs
10252264Sjacobs return (1);
10262264Sjacobs }
10272264Sjacobs
10282264Sjacobs static papi_status_t
copy_attribute(papi_attribute_t *** list,papi_attribute_t * attribute)10292264Sjacobs copy_attribute(papi_attribute_t ***list, papi_attribute_t *attribute)
10302264Sjacobs {
10312264Sjacobs papi_status_t status;
10322264Sjacobs int i = 0;
10332264Sjacobs
10342264Sjacobs if ((list == NULL) || (attribute == NULL) ||
10352264Sjacobs (attribute->values == NULL))
10362264Sjacobs return (PAPI_BAD_ARGUMENT);
10372264Sjacobs
10382264Sjacobs for (status = papiAttributeListAddValue(list, PAPI_ATTR_EXCL,
10392264Sjacobs attribute->name, attribute->type,
10402264Sjacobs attribute->values[i]);
10412264Sjacobs ((status == PAPI_OK) && (attribute->values[i] != NULL));
10422264Sjacobs status = papiAttributeListAddValue(list, PAPI_ATTR_APPEND,
10432264Sjacobs attribute->name, attribute->type,
10442264Sjacobs attribute->values[i]))
10452264Sjacobs i++;
10462264Sjacobs
10472264Sjacobs return (status);
10482264Sjacobs }
10492264Sjacobs
10502264Sjacobs void
copy_attributes(papi_attribute_t *** result,papi_attribute_t ** attributes)10512264Sjacobs copy_attributes(papi_attribute_t ***result, papi_attribute_t **attributes)
10522264Sjacobs {
10532264Sjacobs int i;
10542264Sjacobs
10552264Sjacobs if ((result == NULL) || (attributes == NULL))
10562264Sjacobs return;
10572264Sjacobs
10582264Sjacobs for (i = 0; attributes[i] != NULL; i++)
10592264Sjacobs copy_attribute(result, attributes[i]);
10602264Sjacobs }
10612264Sjacobs
10622264Sjacobs void
split_and_copy_attributes(char ** list,papi_attribute_t ** attributes,papi_attribute_t *** in,papi_attribute_t *** out)10632264Sjacobs split_and_copy_attributes(char **list, papi_attribute_t **attributes,
10642264Sjacobs papi_attribute_t ***in, papi_attribute_t ***out)
10652264Sjacobs {
10662264Sjacobs int i;
10672264Sjacobs
10682264Sjacobs if ((list == NULL) || (attributes == NULL))
10692264Sjacobs return;
10702264Sjacobs
10712264Sjacobs for (i = 0; attributes[i] != NULL; i++)
10722264Sjacobs if (is_in_list(attributes[i]->name, list) == 0)
10732264Sjacobs copy_attribute(in, attributes[i]);
10742264Sjacobs else
10752264Sjacobs copy_attribute(out, attributes[i]);
10762264Sjacobs }
10772264Sjacobs
10782264Sjacobs void
papiAttributeListPrint(FILE * fp,papi_attribute_t ** attributes,char * prefix_fmt,...)10792264Sjacobs papiAttributeListPrint(FILE *fp, papi_attribute_t **attributes,
10802264Sjacobs char *prefix_fmt, ...)
10812264Sjacobs {
10822264Sjacobs char *prefix = NULL;
10832264Sjacobs char *buffer = NULL;
10842264Sjacobs char *newfmt = NULL;
10852264Sjacobs void *mem;
10862264Sjacobs ssize_t size = 0;
10872264Sjacobs va_list ap;
10882264Sjacobs
10892264Sjacobs newfmt = malloc(strlen(prefix_fmt) + 2);
10902264Sjacobs sprintf(newfmt, "\n%s", prefix_fmt);
10912264Sjacobs
10922264Sjacobs va_start(ap, prefix_fmt);
10932264Sjacobs while (vsnprintf(prefix, size, newfmt, ap) > size) {
10942264Sjacobs size += 1024;
10952264Sjacobs mem = realloc(prefix, size);
10962264Sjacobs if (!mem) goto error;
10972264Sjacobs prefix = mem;
10982264Sjacobs }
10992264Sjacobs va_end(ap);
11002264Sjacobs
11012264Sjacobs if (attributes) {
11022264Sjacobs size = 0;
11032264Sjacobs while (papiAttributeListToString(attributes, prefix, buffer,
11042264Sjacobs size) != PAPI_OK) {
11052264Sjacobs size += 1024;
11062264Sjacobs mem = realloc(buffer, size);
11072264Sjacobs if (!mem) goto error;
11082264Sjacobs buffer = mem;
11092264Sjacobs }
11102264Sjacobs }
11112264Sjacobs
11122264Sjacobs fprintf(fp, "%s%s\n", prefix, buffer ? buffer : "");
11132264Sjacobs fflush(fp);
11142264Sjacobs
11152264Sjacobs error:
11162264Sjacobs free(newfmt);
11172264Sjacobs free(prefix);
11182264Sjacobs free(buffer);
11192264Sjacobs }
1120