1355b4669Sjacobs /* 2355b4669Sjacobs * CDDL HEADER START 3355b4669Sjacobs * 4355b4669Sjacobs * The contents of this file are subject to the terms of the 5355b4669Sjacobs * Common Development and Distribution License (the "License"). 6355b4669Sjacobs * You may not use this file except in compliance with the License. 7355b4669Sjacobs * 8355b4669Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9355b4669Sjacobs * or http://www.opensolaris.org/os/licensing. 10355b4669Sjacobs * See the License for the specific language governing permissions 11355b4669Sjacobs * and limitations under the License. 12355b4669Sjacobs * 13355b4669Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 14355b4669Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15355b4669Sjacobs * If applicable, add the following below this CDDL HEADER, with the 16355b4669Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 17355b4669Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 18355b4669Sjacobs * 19355b4669Sjacobs * CDDL HEADER END 20355b4669Sjacobs */ 21355b4669Sjacobs 22355b4669Sjacobs /* 23*ee169c7eSGary Mills * Copyright (c) 2014 Gary Mills 24*ee169c7eSGary Mills * 2543b9c050Sjacobs * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26355b4669Sjacobs * Use is subject to license terms. 27355b4669Sjacobs * 28355b4669Sjacobs */ 29355b4669Sjacobs 30355b4669Sjacobs /* $Id: attribute.c 157 2006-04-26 15:07:55Z ktou $ */ 31355b4669Sjacobs 32355b4669Sjacobs /*LINTLIBRARY*/ 33355b4669Sjacobs 34355b4669Sjacobs #include <stdio.h> 35355b4669Sjacobs #include <stdlib.h> 36355b4669Sjacobs #include <stdarg.h> 37355b4669Sjacobs #include <string.h> 3843b9c050Sjacobs #include <ctype.h> 39355b4669Sjacobs #include <alloca.h> 40355b4669Sjacobs #include <papi.h> 4143b9c050Sjacobs #include <regex.h> 42355b4669Sjacobs 43fa9d6f9fSsg223391 #define MAX_PAGES 32767 44fa9d6f9fSsg223391 /* 45fa9d6f9fSsg223391 * Assuming the maximum number of pages in 46fa9d6f9fSsg223391 * a document to be 32767 47fa9d6f9fSsg223391 */ 48fa9d6f9fSsg223391 49355b4669Sjacobs static void papiAttributeFree(papi_attribute_t *attribute); 50355b4669Sjacobs 51355b4669Sjacobs static void 52355b4669Sjacobs papiAttributeValueFree(papi_attribute_value_type_t type, 53355b4669Sjacobs papi_attribute_value_t *value) 54355b4669Sjacobs { 55355b4669Sjacobs if (value != NULL) { 56355b4669Sjacobs switch (type) { 57355b4669Sjacobs case PAPI_STRING: 58355b4669Sjacobs if (value->string != NULL) 59355b4669Sjacobs free(value->string); 60355b4669Sjacobs break; 61355b4669Sjacobs case PAPI_COLLECTION: 62355b4669Sjacobs if (value->collection != NULL) { 63355b4669Sjacobs int i; 64355b4669Sjacobs 65355b4669Sjacobs for (i = 0; value->collection[i] != NULL; i++) 66355b4669Sjacobs papiAttributeFree(value->collection[i]); 67355b4669Sjacobs 68355b4669Sjacobs free(value->collection); 69355b4669Sjacobs } 70355b4669Sjacobs break; 71355b4669Sjacobs default: /* don't need to free anything extra */ 72355b4669Sjacobs break; 73355b4669Sjacobs } 74355b4669Sjacobs 75355b4669Sjacobs free(value); 76355b4669Sjacobs } 77355b4669Sjacobs } 78355b4669Sjacobs 79355b4669Sjacobs static void 80355b4669Sjacobs papiAttributeValuesFree(papi_attribute_value_type_t type, 81355b4669Sjacobs papi_attribute_value_t **values) 82355b4669Sjacobs { 83355b4669Sjacobs if (values != NULL) { 84355b4669Sjacobs int i; 85355b4669Sjacobs 86355b4669Sjacobs for (i = 0; values[i] != NULL; i++) 87355b4669Sjacobs papiAttributeValueFree(type, values[i]); 88355b4669Sjacobs 89355b4669Sjacobs free(values); 90355b4669Sjacobs } 91355b4669Sjacobs } 92355b4669Sjacobs 93355b4669Sjacobs static void 94355b4669Sjacobs papiAttributeFree(papi_attribute_t *attribute) 95355b4669Sjacobs { 96355b4669Sjacobs if (attribute != NULL) { 97355b4669Sjacobs if (attribute->name != NULL) 98355b4669Sjacobs free(attribute->name); 99355b4669Sjacobs if (attribute->values != NULL) 100355b4669Sjacobs papiAttributeValuesFree(attribute->type, 101355b4669Sjacobs attribute->values); 102355b4669Sjacobs free(attribute); 103355b4669Sjacobs } 104355b4669Sjacobs } 105355b4669Sjacobs 106355b4669Sjacobs void 107355b4669Sjacobs papiAttributeListFree(papi_attribute_t **list) 108355b4669Sjacobs { 109355b4669Sjacobs if (list != NULL) { 110355b4669Sjacobs int i; 111355b4669Sjacobs 112355b4669Sjacobs for (i = 0; list[i] != NULL; i++) 113355b4669Sjacobs papiAttributeFree(list[i]); 114355b4669Sjacobs 115355b4669Sjacobs free(list); 116355b4669Sjacobs } 117355b4669Sjacobs } 118355b4669Sjacobs 119355b4669Sjacobs static papi_attribute_t ** 120355b4669Sjacobs collection_dup(papi_attribute_t **collection) 121355b4669Sjacobs { 122355b4669Sjacobs papi_attribute_t **result = NULL; 123355b4669Sjacobs 124355b4669Sjacobs /* allows a NULL collection that is "empty" or "no value" */ 125355b4669Sjacobs if (collection != NULL) { 126355b4669Sjacobs papi_status_t status = PAPI_OK; 127355b4669Sjacobs int i; 128355b4669Sjacobs 129355b4669Sjacobs for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK)); 130355b4669Sjacobs i++) { 131355b4669Sjacobs papi_attribute_t *a = collection[i]; 132355b4669Sjacobs 133355b4669Sjacobs status = papiAttributeListAddValue(&result, 134355b4669Sjacobs PAPI_ATTR_APPEND, a->name, a->type, 135355b4669Sjacobs NULL); 136355b4669Sjacobs if ((status == PAPI_OK) && (a->values != NULL)) { 137355b4669Sjacobs int j; 138355b4669Sjacobs 139355b4669Sjacobs for (j = 0; ((a->values[j] != NULL) && 140355b4669Sjacobs (status == PAPI_OK)); j++) 141355b4669Sjacobs status = papiAttributeListAddValue( 142355b4669Sjacobs &result, 143355b4669Sjacobs PAPI_ATTR_APPEND, 144355b4669Sjacobs a->name, a->type, 145355b4669Sjacobs a->values[j]); 146355b4669Sjacobs } 147355b4669Sjacobs } 148355b4669Sjacobs if (status != PAPI_OK) { 149355b4669Sjacobs papiAttributeListFree(result); 150355b4669Sjacobs result = NULL; 151355b4669Sjacobs } 152355b4669Sjacobs } 153355b4669Sjacobs 154355b4669Sjacobs return (result); 155355b4669Sjacobs } 156355b4669Sjacobs 157355b4669Sjacobs static papi_attribute_value_t * 158355b4669Sjacobs papiAttributeValueDup(papi_attribute_value_type_t type, 159355b4669Sjacobs papi_attribute_value_t *v) 160355b4669Sjacobs { 161355b4669Sjacobs papi_attribute_value_t *result = NULL; 162355b4669Sjacobs 163355b4669Sjacobs if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) { 164355b4669Sjacobs switch (type) { 165355b4669Sjacobs case PAPI_STRING: 166355b4669Sjacobs if (v->string == NULL) { 167355b4669Sjacobs free(result); 168355b4669Sjacobs result = NULL; 169355b4669Sjacobs } else 170355b4669Sjacobs result->string = strdup(v->string); 171355b4669Sjacobs break; 172355b4669Sjacobs case PAPI_INTEGER: 173355b4669Sjacobs result->integer = v->integer; 174355b4669Sjacobs break; 175355b4669Sjacobs case PAPI_BOOLEAN: 176355b4669Sjacobs result->boolean = v->boolean; 177355b4669Sjacobs break; 178355b4669Sjacobs case PAPI_RANGE: 179355b4669Sjacobs result->range.lower = v->range.lower; 180355b4669Sjacobs result->range.upper = v->range.upper; 181355b4669Sjacobs break; 182355b4669Sjacobs case PAPI_RESOLUTION: 183355b4669Sjacobs result->resolution.xres = v->resolution.xres; 184355b4669Sjacobs result->resolution.yres = v->resolution.yres; 185355b4669Sjacobs result->resolution.units = v->resolution.units; 186355b4669Sjacobs break; 187355b4669Sjacobs case PAPI_DATETIME: 188355b4669Sjacobs result->datetime = v->datetime; 189355b4669Sjacobs break; 190355b4669Sjacobs case PAPI_COLLECTION: 191355b4669Sjacobs result->collection = collection_dup(v->collection); 192355b4669Sjacobs break; 193355b4669Sjacobs case PAPI_METADATA: 194355b4669Sjacobs result->metadata = v->metadata; 195355b4669Sjacobs break; 196355b4669Sjacobs default: /* unknown type, fail to duplicate */ 197355b4669Sjacobs free(result); 198355b4669Sjacobs result = NULL; 199355b4669Sjacobs } 200355b4669Sjacobs } 201355b4669Sjacobs 202355b4669Sjacobs return (result); 203355b4669Sjacobs } 204355b4669Sjacobs 205355b4669Sjacobs static papi_attribute_t * 206355b4669Sjacobs papiAttributeAlloc(char *name, papi_attribute_value_type_t type) 207355b4669Sjacobs { 208355b4669Sjacobs papi_attribute_t *result = NULL; 209355b4669Sjacobs 210355b4669Sjacobs if ((result = calloc(1, sizeof (*result))) != NULL) { 211355b4669Sjacobs result->name = strdup(name); 212355b4669Sjacobs result->type = type; 213355b4669Sjacobs } 214355b4669Sjacobs 215355b4669Sjacobs return (result); 216355b4669Sjacobs } 217355b4669Sjacobs 218355b4669Sjacobs static papi_status_t 219355b4669Sjacobs papiAttributeListAppendValue(papi_attribute_value_t ***values, 220355b4669Sjacobs papi_attribute_value_type_t type, 221355b4669Sjacobs papi_attribute_value_t *value) 222355b4669Sjacobs { 223355b4669Sjacobs 224355b4669Sjacobs if (values == NULL) 225355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 226355b4669Sjacobs 227355b4669Sjacobs if (value != NULL) { /* this allows "empty" attributes */ 228355b4669Sjacobs papi_attribute_value_t *tmp = NULL; 229355b4669Sjacobs 230355b4669Sjacobs if ((tmp = papiAttributeValueDup(type, value)) == NULL) 231355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 232355b4669Sjacobs 233355b4669Sjacobs list_append(values, tmp); 234355b4669Sjacobs } 235355b4669Sjacobs 236355b4669Sjacobs return (PAPI_OK); 237355b4669Sjacobs } 238355b4669Sjacobs 239355b4669Sjacobs papi_status_t 240355b4669Sjacobs papiAttributeListAddValue(papi_attribute_t ***list, int flgs, 241355b4669Sjacobs char *name, papi_attribute_value_type_t type, 242355b4669Sjacobs papi_attribute_value_t *value) 243355b4669Sjacobs { 244355b4669Sjacobs papi_status_t result; 245355b4669Sjacobs int flags = flgs; 246355b4669Sjacobs papi_attribute_t *attribute = NULL; 247355b4669Sjacobs papi_attribute_value_t **values = NULL; 248355b4669Sjacobs 249355b4669Sjacobs if ((list == NULL) || (name == NULL)) 250355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 251355b4669Sjacobs 252355b4669Sjacobs if ((type == PAPI_RANGE) && (value != NULL) && 253355b4669Sjacobs (value->range.lower > value->range.upper)) 254355b4669Sjacobs return (PAPI_BAD_ARGUMENT); /* RANGE must have min <= max */ 255355b4669Sjacobs 256355b4669Sjacobs if (flags == 0) /* if it wasn't set, set a default behaviour */ 257355b4669Sjacobs flags = PAPI_ATTR_APPEND; 258355b4669Sjacobs 259355b4669Sjacobs /* look for an existing one */ 260355b4669Sjacobs attribute = papiAttributeListFind(*list, name); 261355b4669Sjacobs 262355b4669Sjacobs if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL)) 263355b4669Sjacobs return (PAPI_CONFLICT); /* EXISTS */ 264355b4669Sjacobs 265355b4669Sjacobs if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) && 266355b4669Sjacobs (attribute->type != type)) 267355b4669Sjacobs return (PAPI_CONFLICT); /* TYPE CONFLICT */ 268355b4669Sjacobs 269355b4669Sjacobs /* if we don't have one, create it and add it to the list */ 270355b4669Sjacobs if ((attribute == NULL) && 271355b4669Sjacobs ((attribute = papiAttributeAlloc(name, type)) != NULL)) 272355b4669Sjacobs list_append(list, attribute); 273355b4669Sjacobs 274355b4669Sjacobs /* if we don't have one by now, it's most likely an alloc fail */ 275355b4669Sjacobs if (attribute == NULL) 276355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 277355b4669Sjacobs 278355b4669Sjacobs /* 279355b4669Sjacobs * if we are replacing, clear any existing values, but don't free 280355b4669Sjacobs * until after we have replaced the values, in case we are replacing 281355b4669Sjacobs * a collection with a relocated version of the original collection. 282355b4669Sjacobs */ 283355b4669Sjacobs if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) { 284355b4669Sjacobs values = attribute->values; 285355b4669Sjacobs attribute->values = NULL; 286355b4669Sjacobs } 287355b4669Sjacobs 288355b4669Sjacobs attribute->type = type; 289355b4669Sjacobs 290355b4669Sjacobs result = papiAttributeListAppendValue(&attribute->values, type, value); 291355b4669Sjacobs 292355b4669Sjacobs /* free old values if we replaced them */ 293355b4669Sjacobs if (values != NULL) 294355b4669Sjacobs papiAttributeValuesFree(type, values); 295355b4669Sjacobs 296355b4669Sjacobs return (result); 297355b4669Sjacobs } 298355b4669Sjacobs 299355b4669Sjacobs papi_status_t 300355b4669Sjacobs papiAttributeListAddString(papi_attribute_t ***list, int flags, 301355b4669Sjacobs char *name, char *string) 302355b4669Sjacobs { 303355b4669Sjacobs papi_attribute_value_t v; 304355b4669Sjacobs 305355b4669Sjacobs v.string = (char *)string; 306355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v)); 307355b4669Sjacobs } 308355b4669Sjacobs 309355b4669Sjacobs papi_status_t 310355b4669Sjacobs papiAttributeListAddInteger(papi_attribute_t ***list, int flags, 311355b4669Sjacobs char *name, int integer) 312355b4669Sjacobs { 313355b4669Sjacobs papi_attribute_value_t v; 314355b4669Sjacobs 315355b4669Sjacobs v.integer = integer; 316355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v)); 317355b4669Sjacobs } 318355b4669Sjacobs 319355b4669Sjacobs papi_status_t 320355b4669Sjacobs papiAttributeListAddBoolean(papi_attribute_t ***list, int flags, 321355b4669Sjacobs char *name, char boolean) 322355b4669Sjacobs { 323355b4669Sjacobs papi_attribute_value_t v; 324355b4669Sjacobs 325355b4669Sjacobs v.boolean = boolean; 326355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v)); 327355b4669Sjacobs } 328355b4669Sjacobs 329355b4669Sjacobs papi_status_t 330355b4669Sjacobs papiAttributeListAddRange(papi_attribute_t ***list, int flags, 331355b4669Sjacobs char *name, int lower, int upper) 332355b4669Sjacobs { 333355b4669Sjacobs papi_attribute_value_t v; 334355b4669Sjacobs 335355b4669Sjacobs v.range.lower = lower; 336355b4669Sjacobs v.range.upper = upper; 337355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v)); 338355b4669Sjacobs } 339355b4669Sjacobs 340355b4669Sjacobs papi_status_t 341355b4669Sjacobs papiAttributeListAddResolution(papi_attribute_t ***list, int flags, 342355b4669Sjacobs char *name, int xres, int yres, 343355b4669Sjacobs papi_resolution_unit_t units) 344355b4669Sjacobs { 345355b4669Sjacobs papi_attribute_value_t v; 346355b4669Sjacobs 347355b4669Sjacobs v.resolution.xres = xres; 348355b4669Sjacobs v.resolution.yres = yres; 349355b4669Sjacobs v.resolution.units = units; 350355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, 351355b4669Sjacobs PAPI_RESOLUTION, &v)); 352355b4669Sjacobs } 353355b4669Sjacobs 354355b4669Sjacobs papi_status_t 355355b4669Sjacobs papiAttributeListAddDatetime(papi_attribute_t ***list, int flags, 356355b4669Sjacobs char *name, time_t datetime) 357355b4669Sjacobs { 358355b4669Sjacobs papi_attribute_value_t v; 359355b4669Sjacobs 360355b4669Sjacobs v.datetime = datetime; 361355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, 362355b4669Sjacobs PAPI_DATETIME, &v)); 363355b4669Sjacobs } 364355b4669Sjacobs 365355b4669Sjacobs papi_status_t 366355b4669Sjacobs papiAttributeListAddCollection(papi_attribute_t ***list, int flags, 367355b4669Sjacobs char *name, papi_attribute_t **collection) 368355b4669Sjacobs { 369355b4669Sjacobs papi_attribute_value_t v; 370355b4669Sjacobs 371355b4669Sjacobs v.collection = (papi_attribute_t **)collection; 372355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, 373355b4669Sjacobs PAPI_COLLECTION, &v)); 374355b4669Sjacobs } 375355b4669Sjacobs 376355b4669Sjacobs papi_status_t 377355b4669Sjacobs papiAttributeListAddMetadata(papi_attribute_t ***list, int flags, 378355b4669Sjacobs char *name, papi_metadata_t metadata) 379355b4669Sjacobs { 380355b4669Sjacobs papi_attribute_value_t v; 381355b4669Sjacobs 382355b4669Sjacobs v.metadata = metadata; 383355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, 384355b4669Sjacobs PAPI_METADATA, &v)); 385355b4669Sjacobs } 386355b4669Sjacobs 387355b4669Sjacobs papi_status_t 388355b4669Sjacobs papiAttributeListDelete(papi_attribute_t ***list, char *name) 389355b4669Sjacobs { 390355b4669Sjacobs papi_attribute_t *attribute; 391355b4669Sjacobs 392355b4669Sjacobs if ((list == NULL) || (name == NULL)) 393355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 394355b4669Sjacobs 395355b4669Sjacobs if ((attribute = papiAttributeListFind(*list, name)) == NULL) 396355b4669Sjacobs return (PAPI_NOT_FOUND); 397355b4669Sjacobs 3980a44ef6dSjacobs list_remove(list, attribute); 399355b4669Sjacobs papiAttributeFree(attribute); 400355b4669Sjacobs 401355b4669Sjacobs return (PAPI_OK); 402355b4669Sjacobs } 403355b4669Sjacobs 404355b4669Sjacobs papi_attribute_t * 405355b4669Sjacobs papiAttributeListFind(papi_attribute_t **list, char *name) 406355b4669Sjacobs { 407355b4669Sjacobs int i; 408355b4669Sjacobs if ((list == NULL) || (name == NULL)) 409355b4669Sjacobs return (NULL); 410355b4669Sjacobs 411355b4669Sjacobs for (i = 0; list[i] != NULL; i++) 412355b4669Sjacobs if (strcasecmp(list[i]->name, name) == 0) 413355b4669Sjacobs return ((papi_attribute_t *)list[i]); 414355b4669Sjacobs 415355b4669Sjacobs return (NULL); 416355b4669Sjacobs } 417355b4669Sjacobs 418355b4669Sjacobs papi_attribute_t * 419355b4669Sjacobs papiAttributeListGetNext(papi_attribute_t **list, void **iter) 420355b4669Sjacobs { 421355b4669Sjacobs papi_attribute_t **tmp, *result; 422355b4669Sjacobs 423355b4669Sjacobs if ((list == NULL) && (iter == NULL)) 424355b4669Sjacobs return (NULL); 425355b4669Sjacobs 426355b4669Sjacobs if (*iter == NULL) 427355b4669Sjacobs *iter = list; 428355b4669Sjacobs 429355b4669Sjacobs tmp = *iter; 430355b4669Sjacobs result = *tmp; 431355b4669Sjacobs *iter = ++tmp; 432355b4669Sjacobs 433355b4669Sjacobs return (result); 434355b4669Sjacobs } 435355b4669Sjacobs 436355b4669Sjacobs papi_status_t 437355b4669Sjacobs papiAttributeListGetValue(papi_attribute_t **list, void **iter, 438355b4669Sjacobs char *name, papi_attribute_value_type_t type, 439355b4669Sjacobs papi_attribute_value_t **value) 440355b4669Sjacobs { 441355b4669Sjacobs papi_attribute_value_t **tmp; 442355b4669Sjacobs void *fodder = NULL; 443355b4669Sjacobs 444355b4669Sjacobs if ((list == NULL) || ((name == NULL) && (iter == NULL)) || 445355b4669Sjacobs (value == NULL)) 446355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 447355b4669Sjacobs 448355b4669Sjacobs if (iter == NULL) 449355b4669Sjacobs iter = &fodder; 450355b4669Sjacobs 451355b4669Sjacobs if ((iter == NULL) || (*iter == NULL)) { 452355b4669Sjacobs papi_attribute_t *attr = papiAttributeListFind(list, name); 453355b4669Sjacobs 454355b4669Sjacobs if (attr == NULL) 455355b4669Sjacobs return (PAPI_NOT_FOUND); 456355b4669Sjacobs 457355b4669Sjacobs if (attr->type != type) 458355b4669Sjacobs return (PAPI_NOT_POSSIBLE); 459355b4669Sjacobs 460355b4669Sjacobs tmp = attr->values; 461355b4669Sjacobs } else 462355b4669Sjacobs tmp = *iter; 463355b4669Sjacobs 464355b4669Sjacobs if (tmp == NULL) 465355b4669Sjacobs return (PAPI_NOT_FOUND); 466355b4669Sjacobs 467355b4669Sjacobs *value = *tmp; 468355b4669Sjacobs *iter = ++tmp; 469355b4669Sjacobs 470355b4669Sjacobs if (*value == NULL) 471355b4669Sjacobs return (PAPI_GONE); 472355b4669Sjacobs 473355b4669Sjacobs return (PAPI_OK); 474355b4669Sjacobs } 475355b4669Sjacobs 476355b4669Sjacobs papi_status_t 477355b4669Sjacobs papiAttributeListGetString(papi_attribute_t **list, void **iter, 478355b4669Sjacobs char *name, char **vptr) 479355b4669Sjacobs { 480355b4669Sjacobs papi_status_t status; 481355b4669Sjacobs papi_attribute_value_t *value = NULL; 482355b4669Sjacobs 483355b4669Sjacobs if (vptr == NULL) 484355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 485355b4669Sjacobs 486355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 487355b4669Sjacobs PAPI_STRING, &value); 488355b4669Sjacobs if (status == PAPI_OK) 489355b4669Sjacobs *vptr = value->string; 490355b4669Sjacobs 491355b4669Sjacobs return (status); 492355b4669Sjacobs } 493355b4669Sjacobs 494355b4669Sjacobs papi_status_t 495355b4669Sjacobs papiAttributeListGetInteger(papi_attribute_t **list, void **iter, 496355b4669Sjacobs char *name, int *vptr) 497355b4669Sjacobs { 498355b4669Sjacobs papi_status_t status; 499355b4669Sjacobs papi_attribute_value_t *value = NULL; 500355b4669Sjacobs 501355b4669Sjacobs if (vptr == NULL) 502355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 503355b4669Sjacobs 504355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 505355b4669Sjacobs PAPI_INTEGER, &value); 506355b4669Sjacobs if (status == PAPI_OK) 507355b4669Sjacobs *vptr = value->integer; 508355b4669Sjacobs 509355b4669Sjacobs return (status); 510355b4669Sjacobs } 511355b4669Sjacobs 512355b4669Sjacobs papi_status_t 513355b4669Sjacobs papiAttributeListGetBoolean(papi_attribute_t **list, void **iter, 514355b4669Sjacobs char *name, char *vptr) 515355b4669Sjacobs { 516355b4669Sjacobs papi_status_t status; 517355b4669Sjacobs papi_attribute_value_t *value = NULL; 518355b4669Sjacobs 519355b4669Sjacobs if (vptr == NULL) 520355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 521355b4669Sjacobs 522355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 523355b4669Sjacobs PAPI_BOOLEAN, &value); 524355b4669Sjacobs if (status == PAPI_OK) 525355b4669Sjacobs *vptr = value->boolean; 526355b4669Sjacobs 527355b4669Sjacobs return (status); 528355b4669Sjacobs } 529355b4669Sjacobs 530355b4669Sjacobs papi_status_t 531355b4669Sjacobs papiAttributeListGetRange(papi_attribute_t **list, void **iter, 532355b4669Sjacobs char *name, int *min, int *max) 533355b4669Sjacobs { 534355b4669Sjacobs papi_status_t status; 535355b4669Sjacobs papi_attribute_value_t *value = NULL; 536355b4669Sjacobs 537355b4669Sjacobs if ((min == NULL) || (max == NULL)) 538355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 539355b4669Sjacobs 540355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 541355b4669Sjacobs PAPI_RANGE, &value); 542355b4669Sjacobs if (status == PAPI_OK) { 543355b4669Sjacobs *min = value->range.lower; 544355b4669Sjacobs *max = value->range.upper; 545355b4669Sjacobs } 546355b4669Sjacobs 547355b4669Sjacobs return (status); 548355b4669Sjacobs } 549355b4669Sjacobs 550355b4669Sjacobs papi_status_t 551355b4669Sjacobs papiAttributeListGetResolution(papi_attribute_t **list, void **iter, 552355b4669Sjacobs char *name, int *x, int *y, 553355b4669Sjacobs papi_resolution_unit_t *units) 554355b4669Sjacobs { 555355b4669Sjacobs papi_status_t status; 556355b4669Sjacobs papi_attribute_value_t *value = NULL; 557355b4669Sjacobs 558355b4669Sjacobs if ((x == NULL) || (y == NULL) || (units == NULL)) 559355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 560355b4669Sjacobs 561355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 562355b4669Sjacobs PAPI_RESOLUTION, &value); 563355b4669Sjacobs if (status == PAPI_OK) { 564355b4669Sjacobs *x = value->resolution.xres; 565355b4669Sjacobs *y = value->resolution.yres; 566355b4669Sjacobs *units = value->resolution.units; 567355b4669Sjacobs } 568355b4669Sjacobs 569355b4669Sjacobs return (status); 570355b4669Sjacobs } 571355b4669Sjacobs 572355b4669Sjacobs papi_status_t 573355b4669Sjacobs papiAttributeListGetDatetime(papi_attribute_t **list, void **iter, 574355b4669Sjacobs char *name, time_t *dt) 575355b4669Sjacobs { 576355b4669Sjacobs papi_status_t status; 577355b4669Sjacobs papi_attribute_value_t *value = NULL; 578355b4669Sjacobs 579355b4669Sjacobs if (dt == NULL) 580355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 581355b4669Sjacobs 582355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 583355b4669Sjacobs PAPI_DATETIME, &value); 584355b4669Sjacobs if (status == PAPI_OK) { 585355b4669Sjacobs *dt = value->datetime; 586355b4669Sjacobs } 587355b4669Sjacobs 588355b4669Sjacobs return (status); 589355b4669Sjacobs } 590355b4669Sjacobs 591355b4669Sjacobs papi_status_t 592355b4669Sjacobs papiAttributeListGetCollection(papi_attribute_t **list, void **iter, 593355b4669Sjacobs char *name, papi_attribute_t ***collection) 594355b4669Sjacobs { 595355b4669Sjacobs papi_status_t status; 596355b4669Sjacobs papi_attribute_value_t *value = NULL; 597355b4669Sjacobs 598355b4669Sjacobs if (collection == NULL) 599355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 600355b4669Sjacobs 601355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 602355b4669Sjacobs PAPI_COLLECTION, &value); 603355b4669Sjacobs if (status == PAPI_OK) { 604355b4669Sjacobs *collection = value->collection; 605355b4669Sjacobs } 606355b4669Sjacobs 607355b4669Sjacobs return (status); 608355b4669Sjacobs } 609355b4669Sjacobs 610355b4669Sjacobs papi_status_t 611355b4669Sjacobs papiAttributeListGetMetadata(papi_attribute_t **list, void **iter, 612355b4669Sjacobs char *name, papi_metadata_t *vptr) 613355b4669Sjacobs { 614355b4669Sjacobs papi_status_t status; 615355b4669Sjacobs papi_attribute_value_t *value = NULL; 616355b4669Sjacobs 617355b4669Sjacobs if (vptr == NULL) 618355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 619355b4669Sjacobs 620355b4669Sjacobs status = papiAttributeListGetValue(list, iter, name, 621355b4669Sjacobs PAPI_METADATA, &value); 622355b4669Sjacobs if (status == PAPI_OK) 623355b4669Sjacobs *vptr = value->metadata; 624355b4669Sjacobs 625355b4669Sjacobs return (status); 626355b4669Sjacobs } 627355b4669Sjacobs 628355b4669Sjacobs 62943b9c050Sjacobs /* The string is modified by this call */ 630355b4669Sjacobs static char * 63143b9c050Sjacobs regvalue(regmatch_t match, char *string) 632355b4669Sjacobs { 633355b4669Sjacobs char *result = NULL; 63443b9c050Sjacobs if (match.rm_so != match.rm_eo) { 63543b9c050Sjacobs result = string + match.rm_so; 63643b9c050Sjacobs *(result + (match.rm_eo - match.rm_so)) = '\0'; 637355b4669Sjacobs } 638355b4669Sjacobs return (result); 63943b9c050Sjacobs } 640355b4669Sjacobs 64143b9c050Sjacobs static papi_attribute_value_type_t 64243b9c050Sjacobs _process_value(char *string, char ***parts) 64343b9c050Sjacobs { 64443b9c050Sjacobs int i; 64543b9c050Sjacobs static struct { 64643b9c050Sjacobs papi_attribute_value_type_t type; 64743b9c050Sjacobs size_t vals; 64843b9c050Sjacobs char *expression; 64943b9c050Sjacobs int compiled; 65043b9c050Sjacobs regex_t re; 65143b9c050Sjacobs } types[] = { 65243b9c050Sjacobs { PAPI_BOOLEAN, 1, "^(true|false|yes|no)$", 0 }, 65343b9c050Sjacobs { PAPI_COLLECTION, 1, "^\\{(.+)\\}$", 0 }, 65443b9c050Sjacobs /* PAPI_DATETIME is unsupported, too much like an integer */ 65543b9c050Sjacobs { PAPI_INTEGER, 1, "^([+-]{0,1}[[:digit:]]+)$", 0 }, 656fa9d6f9fSsg223391 { PAPI_RANGE, 3, "^([[:digit:]]*)-([[:digit:]]*)$", 0 }, 65743b9c050Sjacobs { PAPI_RESOLUTION, 4, "^([[:digit:]]+)x([[:digit:]]+)dp(i|c)$", 65843b9c050Sjacobs 0 }, 65943b9c050Sjacobs NULL 66043b9c050Sjacobs }; 66143b9c050Sjacobs regmatch_t matches[4]; 662355b4669Sjacobs 66343b9c050Sjacobs for (i = 0; i < 5; i++) { 66443b9c050Sjacobs int j; 66543b9c050Sjacobs 66643b9c050Sjacobs if (types[i].compiled == 0) { 66743b9c050Sjacobs (void) regcomp(&(types[i].re), types[i].expression, 66843b9c050Sjacobs REG_EXTENDED|REG_ICASE); 66943b9c050Sjacobs types[i].compiled = 1; 67043b9c050Sjacobs } 67143b9c050Sjacobs if (regexec(&(types[i].re), string, (size_t)types[i].vals, 67243b9c050Sjacobs matches, 0) == REG_NOMATCH) 67343b9c050Sjacobs continue; 67443b9c050Sjacobs 67543b9c050Sjacobs for (j = 0 ; j < types[i].vals; j++) 67643b9c050Sjacobs list_append(parts, regvalue(matches[j], string)); 67743b9c050Sjacobs return (types[i].type); 67843b9c050Sjacobs } 67943b9c050Sjacobs 68043b9c050Sjacobs list_append(parts, string); 68143b9c050Sjacobs return (PAPI_STRING); 68243b9c050Sjacobs } 68343b9c050Sjacobs 68443b9c050Sjacobs static void 68543b9c050Sjacobs _add_attribute_value(papi_attribute_value_t ***list, 68643b9c050Sjacobs papi_attribute_value_type_t type, 68743b9c050Sjacobs papi_attribute_value_type_t dtype, char **parts) 68843b9c050Sjacobs { 68943b9c050Sjacobs papi_attribute_value_t *value = calloc(1, sizeof (*value)); 69043b9c050Sjacobs 69143b9c050Sjacobs switch(type) { 69243b9c050Sjacobs case PAPI_STRING: 69343b9c050Sjacobs value->string = strdup(parts[0]); 69443b9c050Sjacobs list_append(list, value); 69543b9c050Sjacobs break; 69643b9c050Sjacobs case PAPI_BOOLEAN: 69743b9c050Sjacobs value->boolean = PAPI_TRUE; 69843b9c050Sjacobs if ((strcasecmp(parts[0], "false") == 0) || 69943b9c050Sjacobs (strcasecmp(parts[0], "no") == 0)) 70043b9c050Sjacobs value->boolean = PAPI_FALSE; 70143b9c050Sjacobs list_append(list, value); 70243b9c050Sjacobs break; 70343b9c050Sjacobs case PAPI_INTEGER: 70443b9c050Sjacobs value->integer = atoi(parts[0]); 70543b9c050Sjacobs list_append(list, value); 70643b9c050Sjacobs break; 70743b9c050Sjacobs case PAPI_RANGE: 708fa9d6f9fSsg223391 if (dtype == PAPI_INTEGER) { 709fa9d6f9fSsg223391 if (atoi(parts[0]) < 0) { 710fa9d6f9fSsg223391 /* 711fa9d6f9fSsg223391 * Handles -P -x case 712fa9d6f9fSsg223391 * which prints from page number 1 713fa9d6f9fSsg223391 * till page number x 714fa9d6f9fSsg223391 */ 715fa9d6f9fSsg223391 value->range.lower = 1; 716fa9d6f9fSsg223391 value->range.upper = 0 - (atoi(parts[0])); 717fa9d6f9fSsg223391 } else { 71843b9c050Sjacobs value->range.lower = value->range.upper 71943b9c050Sjacobs = atoi(parts[0]); 720fa9d6f9fSsg223391 } 721fa9d6f9fSsg223391 } else if (dtype == PAPI_RANGE) { 722fa9d6f9fSsg223391 if (parts[2] == NULL) { 723fa9d6f9fSsg223391 value->range.lower = atoi(parts[1]); 724fa9d6f9fSsg223391 /* 725fa9d6f9fSsg223391 * Imposing an artificial limit on 726fa9d6f9fSsg223391 * the upper bound for page range. 727fa9d6f9fSsg223391 */ 728fa9d6f9fSsg223391 value->range.upper = MAX_PAGES; 729fa9d6f9fSsg223391 } else if ((parts[1] != NULL) && (parts[2] != NULL)) { 73043b9c050Sjacobs value->range.lower = atoi(parts[1]); 73143b9c050Sjacobs value->range.upper = atoi(parts[2]); 73243b9c050Sjacobs } 733fa9d6f9fSsg223391 } 73443b9c050Sjacobs list_append(list, value); 73543b9c050Sjacobs break; 73643b9c050Sjacobs case PAPI_RESOLUTION: 73743b9c050Sjacobs value->resolution.xres = atoi(parts[1]); 73843b9c050Sjacobs value->resolution.yres = atoi(parts[2]); 73943b9c050Sjacobs if (parts[3][0] == 'i') 74043b9c050Sjacobs value->resolution.units = PAPI_RES_PER_INCH; 74143b9c050Sjacobs else 74243b9c050Sjacobs value->resolution.units = PAPI_RES_PER_CM; 74343b9c050Sjacobs list_append(list, value); 74443b9c050Sjacobs break; 74543b9c050Sjacobs case PAPI_COLLECTION: 74643b9c050Sjacobs papiAttributeListFromString(&(value->collection), 0, parts[0]); 74743b9c050Sjacobs list_append(list, value); 74843b9c050Sjacobs break; 74943b9c050Sjacobs } 75043b9c050Sjacobs } 751355b4669Sjacobs 752355b4669Sjacobs static papi_status_t 75343b9c050Sjacobs _papiAttributeFromStrings(papi_attribute_t ***list, int flags, 75443b9c050Sjacobs char *key, char **values) 755355b4669Sjacobs { 75643b9c050Sjacobs int i; 757355b4669Sjacobs papi_status_t result = PAPI_OK; 75843b9c050Sjacobs papi_attribute_t *attr = calloc(1, sizeof (*attr)); 759355b4669Sjacobs 76043b9c050Sjacobs /* these are specified in the papi spec as ranges */ 76143b9c050Sjacobs char *ranges[] = { "copies-supported", "job-impressions-supported", 76243b9c050Sjacobs "job-k-octets-supported", 76343b9c050Sjacobs "job-media-sheets-supported", "page-ranges", 76443b9c050Sjacobs NULL }; 765355b4669Sjacobs 76643b9c050Sjacobs if ((attr == NULL) || ((attr->name = strdup(key)) == NULL)) 76743b9c050Sjacobs return (PAPI_TEMPORARY_ERROR); 768355b4669Sjacobs 76943b9c050Sjacobs attr->type = PAPI_METADATA; 77043b9c050Sjacobs /* these are known ranges */ 77143b9c050Sjacobs for (i = 0; ranges[i] != NULL; i++) 77243b9c050Sjacobs if (strcasecmp(attr->name, ranges[i]) == 0) { 773355b4669Sjacobs attr->type = PAPI_RANGE; 77443b9c050Sjacobs break; 775355b4669Sjacobs } 776355b4669Sjacobs 77743b9c050Sjacobs if (values != NULL) { 77843b9c050Sjacobs papi_attribute_value_t **vals = NULL; 77943b9c050Sjacobs 78043b9c050Sjacobs for (i = 0; values[i] != NULL; i++) { 78143b9c050Sjacobs papi_attribute_value_type_t dtype; 78243b9c050Sjacobs char **parts = NULL; 78343b9c050Sjacobs 78443b9c050Sjacobs dtype = _process_value(values[i], &parts); 78543b9c050Sjacobs if (attr->type == PAPI_METADATA) 78643b9c050Sjacobs attr->type = dtype; 78743b9c050Sjacobs _add_attribute_value(&vals, attr->type, dtype, parts); 78843b9c050Sjacobs free(parts); 78943b9c050Sjacobs } 79043b9c050Sjacobs attr->values = vals; 791355b4669Sjacobs } 792355b4669Sjacobs 79343b9c050Sjacobs list_append(list, attr); 794355b4669Sjacobs 795355b4669Sjacobs return (result); 79643b9c050Sjacobs } 797355b4669Sjacobs 798355b4669Sjacobs static papi_status_t 79943b9c050Sjacobs _parse_attribute_list(papi_attribute_t ***list, int flags, char *string) 800355b4669Sjacobs { 801355b4669Sjacobs papi_status_t result = PAPI_OK; 80243b9c050Sjacobs char *ptr; 803355b4669Sjacobs 80443b9c050Sjacobs if ((list == NULL) || (string == NULL)) 80543b9c050Sjacobs return (PAPI_BAD_ARGUMENT); 806355b4669Sjacobs 80743b9c050Sjacobs if ((ptr = strdup(string)) == NULL) 80843b9c050Sjacobs return (PAPI_TEMPORARY_ERROR); 809355b4669Sjacobs 81043b9c050Sjacobs while ((*ptr != '\0') && (result == PAPI_OK)) { 81143b9c050Sjacobs char *key, **values = NULL; 812355b4669Sjacobs 81343b9c050Sjacobs /* strip any leading whitespace */ 81443b9c050Sjacobs while (isspace(*ptr) != 0) 81543b9c050Sjacobs ptr++; 81643b9c050Sjacobs 81743b9c050Sjacobs /* Get the name: name[=value] */ 81843b9c050Sjacobs key = ptr; 81943b9c050Sjacobs while ((*ptr != '\0') && (*ptr != '=') && (isspace(*ptr) == 0)) 82043b9c050Sjacobs ptr++; 82143b9c050Sjacobs 82243b9c050Sjacobs if (*ptr == '=') { 82343b9c050Sjacobs *ptr++ = '\0'; 82443b9c050Sjacobs 82543b9c050Sjacobs while ((*ptr != '\0') && (isspace(*ptr) == 0)) { 82643b9c050Sjacobs char *value = ptr; 82743b9c050Sjacobs 82843b9c050Sjacobs if ((*ptr == '\'') || (*ptr == '"')) { 82943b9c050Sjacobs char q = *ptr++; 83043b9c050Sjacobs 83143b9c050Sjacobs /* quoted string value */ 83243b9c050Sjacobs while ((*ptr != '\0') && (*ptr != q)) 83343b9c050Sjacobs ptr++; 83443b9c050Sjacobs if (*ptr == q) 83543b9c050Sjacobs ptr++; 83643b9c050Sjacobs } else if (*ptr == '{') { 83743b9c050Sjacobs /* collection */ 83843b9c050Sjacobs while ((*ptr != '\0') && (*ptr != '}')) 83943b9c050Sjacobs ptr++; 84043b9c050Sjacobs if (*ptr == '}') 84143b9c050Sjacobs ptr++; 842355b4669Sjacobs } else { 84343b9c050Sjacobs /* value */ 84443b9c050Sjacobs while ((*ptr != '\0') && 84543b9c050Sjacobs (*ptr != ',') && 84643b9c050Sjacobs (isspace(*ptr) == 0)) 84743b9c050Sjacobs ptr++; 848355b4669Sjacobs } 84943b9c050Sjacobs if (*ptr == ',') 85043b9c050Sjacobs *ptr++ = '\0'; 85143b9c050Sjacobs list_append(&values, value); 852355b4669Sjacobs } 85343b9c050Sjacobs } else { /* boolean "[no]key" */ 85443b9c050Sjacobs char *value = "true"; 85543b9c050Sjacobs 85643b9c050Sjacobs if (strncasecmp(key, "no", 2) == 0) { 85743b9c050Sjacobs key += 2; 85843b9c050Sjacobs value = "false"; 859355b4669Sjacobs } 86043b9c050Sjacobs list_append(&values, value); 861355b4669Sjacobs } 86243b9c050Sjacobs if (*ptr != '\0') 86343b9c050Sjacobs *ptr++ = '\0'; 86443b9c050Sjacobs 86543b9c050Sjacobs result = _papiAttributeFromStrings(list, flags, key, values); 86643b9c050Sjacobs free(values); 867355b4669Sjacobs } 868355b4669Sjacobs 869355b4669Sjacobs return (result); 87043b9c050Sjacobs } 871355b4669Sjacobs 872355b4669Sjacobs papi_status_t 873355b4669Sjacobs papiAttributeListFromString(papi_attribute_t ***attrs, 874355b4669Sjacobs int flags, char *string) 875355b4669Sjacobs { 876355b4669Sjacobs papi_status_t result = PAPI_OK; 877355b4669Sjacobs 878355b4669Sjacobs if ((attrs != NULL) && (string != NULL) && 879355b4669Sjacobs ((flags & ~(PAPI_ATTR_APPEND+PAPI_ATTR_REPLACE+PAPI_ATTR_EXCL)) 880355b4669Sjacobs == 0)) { 88143b9c050Sjacobs result = _parse_attribute_list(attrs, flags, string); 882355b4669Sjacobs } else { 883355b4669Sjacobs result = PAPI_BAD_ARGUMENT; 884355b4669Sjacobs } 885355b4669Sjacobs 886355b4669Sjacobs return (result); 887355b4669Sjacobs } 888355b4669Sjacobs 889355b4669Sjacobs static papi_status_t 890355b4669Sjacobs papiAttributeToString(papi_attribute_t *attribute, char *delim, 891355b4669Sjacobs char *buffer, size_t buflen) 892355b4669Sjacobs { 893355b4669Sjacobs papi_attribute_value_t **values = attribute->values; 894355b4669Sjacobs int rc, i; 895355b4669Sjacobs 89643b9c050Sjacobs if ((attribute->type == PAPI_BOOLEAN) && (values[1] == NULL)) { 89743b9c050Sjacobs if (values[0]->boolean == PAPI_FALSE) { 89843b9c050Sjacobs if (isupper(attribute->name[0]) == 0) 89943b9c050Sjacobs strlcat(buffer, "no", buflen); 90043b9c050Sjacobs else 90143b9c050Sjacobs strlcat(buffer, "No", buflen); 90243b9c050Sjacobs } 90343b9c050Sjacobs rc = strlcat(buffer, attribute->name, buflen); 90443b9c050Sjacobs } else { 905355b4669Sjacobs strlcat(buffer, attribute->name, buflen); 90643b9c050Sjacobs rc = strlcat(buffer, "=", buflen); 90743b9c050Sjacobs } 908355b4669Sjacobs 909355b4669Sjacobs if (values == NULL) 910355b4669Sjacobs return (PAPI_OK); 911355b4669Sjacobs 912355b4669Sjacobs for (i = 0; values[i] != NULL; i++) { 913355b4669Sjacobs switch (attribute->type) { 914355b4669Sjacobs case PAPI_STRING: 915355b4669Sjacobs rc = strlcat(buffer, values[i]->string, buflen); 916355b4669Sjacobs break; 917355b4669Sjacobs case PAPI_INTEGER: { 918355b4669Sjacobs char string[24]; 919355b4669Sjacobs 920355b4669Sjacobs snprintf(string, sizeof (string), "%d", 921355b4669Sjacobs values[i]->integer); 922355b4669Sjacobs rc = strlcat(buffer, string, buflen); 923355b4669Sjacobs } 924355b4669Sjacobs break; 925355b4669Sjacobs case PAPI_BOOLEAN: 92643b9c050Sjacobs if (values[1] != NULL) 92743b9c050Sjacobs rc = strlcat(buffer, (values[i]->boolean ? 92843b9c050Sjacobs "true" : "false"), buflen); 929355b4669Sjacobs break; 930355b4669Sjacobs case PAPI_RANGE: { 931355b4669Sjacobs char string[24]; 932355b4669Sjacobs 93343b9c050Sjacobs if (values[i]->range.lower == values[i]->range.upper) 93443b9c050Sjacobs snprintf(string, sizeof (string), "%d", 93543b9c050Sjacobs values[i]->range.lower); 93643b9c050Sjacobs else 937355b4669Sjacobs snprintf(string, sizeof (string), "%d-%d", 93843b9c050Sjacobs values[i]->range.lower, 93943b9c050Sjacobs values[i]->range.upper); 940355b4669Sjacobs rc = strlcat(buffer, string, buflen); 941355b4669Sjacobs } 942355b4669Sjacobs break; 943355b4669Sjacobs case PAPI_RESOLUTION: { 944355b4669Sjacobs char string[24]; 945355b4669Sjacobs 946355b4669Sjacobs snprintf(string, sizeof (string), "%dx%ddp%c", 947355b4669Sjacobs values[i]->resolution.xres, 948355b4669Sjacobs values[i]->resolution.yres, 949355b4669Sjacobs (values[i]->resolution.units == PAPI_RES_PER_CM 950355b4669Sjacobs ? 'c' : 'i')); 951355b4669Sjacobs rc = strlcat(buffer, string, buflen); 952355b4669Sjacobs } 953355b4669Sjacobs break; 954355b4669Sjacobs case PAPI_DATETIME: { 955355b4669Sjacobs struct tm *tm = localtime(&values[i]->datetime); 956355b4669Sjacobs 957355b4669Sjacobs if (tm != NULL) { 958355b4669Sjacobs char string[64]; 959355b4669Sjacobs 960*ee169c7eSGary Mills strftime(string, sizeof (string), "%c", tm); 961355b4669Sjacobs rc = strlcat(buffer, string, buflen); 962355b4669Sjacobs }} 963355b4669Sjacobs break; 964355b4669Sjacobs case PAPI_COLLECTION: { 965355b4669Sjacobs char *string = alloca(buflen); 966355b4669Sjacobs 967355b4669Sjacobs papiAttributeListToString(values[i]->collection, 968355b4669Sjacobs delim, string, buflen); 969355b4669Sjacobs rc = strlcat(buffer, string, buflen); 970355b4669Sjacobs } 971355b4669Sjacobs break; 972355b4669Sjacobs default: { 973355b4669Sjacobs char string[32]; 974355b4669Sjacobs 975355b4669Sjacobs snprintf(string, sizeof (string), "unknown-type-0x%x", 976355b4669Sjacobs attribute->type); 977355b4669Sjacobs rc = strlcat(buffer, string, buflen); 978355b4669Sjacobs } 979355b4669Sjacobs } 980355b4669Sjacobs if (values[i+1] != NULL) 981355b4669Sjacobs rc = strlcat(buffer, ",", buflen); 982355b4669Sjacobs 983355b4669Sjacobs if (rc >= buflen) 984355b4669Sjacobs return (PAPI_NOT_POSSIBLE); 985355b4669Sjacobs 986355b4669Sjacobs } 987355b4669Sjacobs 988355b4669Sjacobs return (PAPI_OK); 989355b4669Sjacobs } 990355b4669Sjacobs 991355b4669Sjacobs papi_status_t 992355b4669Sjacobs papiAttributeListToString(papi_attribute_t **attrs, 993355b4669Sjacobs char *delim, char *buffer, size_t buflen) 994355b4669Sjacobs { 995355b4669Sjacobs papi_status_t status = PAPI_OK; 996355b4669Sjacobs int i; 997355b4669Sjacobs 998355b4669Sjacobs if ((attrs == NULL) || (buffer == NULL)) 999355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 1000355b4669Sjacobs 1001355b4669Sjacobs buffer[0] = '\0'; 1002355b4669Sjacobs if (!delim) 1003355b4669Sjacobs delim = " "; 1004355b4669Sjacobs 1005355b4669Sjacobs for (i = 0; ((attrs[i] != NULL) && (status == PAPI_OK)); i++) { 1006355b4669Sjacobs status = papiAttributeToString(attrs[i], delim, buffer, buflen); 1007355b4669Sjacobs if (attrs[i+1] != NULL) 1008355b4669Sjacobs strlcat(buffer, delim, buflen); 1009355b4669Sjacobs } 1010355b4669Sjacobs 1011355b4669Sjacobs return (status); 1012355b4669Sjacobs } 1013355b4669Sjacobs 1014355b4669Sjacobs static int 1015355b4669Sjacobs is_in_list(char *value, char **list) 1016355b4669Sjacobs { 1017355b4669Sjacobs if ((list != NULL) && (value != NULL)) { 1018355b4669Sjacobs int i; 1019355b4669Sjacobs 1020355b4669Sjacobs for (i = 0; list[i] != NULL; i++) 1021355b4669Sjacobs if (strcasecmp(value, list[i]) == 0) 1022355b4669Sjacobs return (0); 1023355b4669Sjacobs } 1024355b4669Sjacobs 1025355b4669Sjacobs return (1); 1026355b4669Sjacobs } 1027355b4669Sjacobs 1028355b4669Sjacobs static papi_status_t 1029355b4669Sjacobs copy_attribute(papi_attribute_t ***list, papi_attribute_t *attribute) 1030355b4669Sjacobs { 1031355b4669Sjacobs papi_status_t status; 1032355b4669Sjacobs int i = 0; 1033355b4669Sjacobs 1034355b4669Sjacobs if ((list == NULL) || (attribute == NULL) || 1035355b4669Sjacobs (attribute->values == NULL)) 1036355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 1037355b4669Sjacobs 1038355b4669Sjacobs for (status = papiAttributeListAddValue(list, PAPI_ATTR_EXCL, 1039355b4669Sjacobs attribute->name, attribute->type, 1040355b4669Sjacobs attribute->values[i]); 1041355b4669Sjacobs ((status == PAPI_OK) && (attribute->values[i] != NULL)); 1042355b4669Sjacobs status = papiAttributeListAddValue(list, PAPI_ATTR_APPEND, 1043355b4669Sjacobs attribute->name, attribute->type, 1044355b4669Sjacobs attribute->values[i])) 1045355b4669Sjacobs i++; 1046355b4669Sjacobs 1047355b4669Sjacobs return (status); 1048355b4669Sjacobs } 1049355b4669Sjacobs 1050355b4669Sjacobs void 1051355b4669Sjacobs copy_attributes(papi_attribute_t ***result, papi_attribute_t **attributes) 1052355b4669Sjacobs { 1053355b4669Sjacobs int i; 1054355b4669Sjacobs 1055355b4669Sjacobs if ((result == NULL) || (attributes == NULL)) 1056355b4669Sjacobs return; 1057355b4669Sjacobs 1058355b4669Sjacobs for (i = 0; attributes[i] != NULL; i++) 1059355b4669Sjacobs copy_attribute(result, attributes[i]); 1060355b4669Sjacobs } 1061355b4669Sjacobs 1062355b4669Sjacobs void 1063355b4669Sjacobs split_and_copy_attributes(char **list, papi_attribute_t **attributes, 1064355b4669Sjacobs papi_attribute_t ***in, papi_attribute_t ***out) 1065355b4669Sjacobs { 1066355b4669Sjacobs int i; 1067355b4669Sjacobs 1068355b4669Sjacobs if ((list == NULL) || (attributes == NULL)) 1069355b4669Sjacobs return; 1070355b4669Sjacobs 1071355b4669Sjacobs for (i = 0; attributes[i] != NULL; i++) 1072355b4669Sjacobs if (is_in_list(attributes[i]->name, list) == 0) 1073355b4669Sjacobs copy_attribute(in, attributes[i]); 1074355b4669Sjacobs else 1075355b4669Sjacobs copy_attribute(out, attributes[i]); 1076355b4669Sjacobs } 1077355b4669Sjacobs 1078355b4669Sjacobs void 1079355b4669Sjacobs papiAttributeListPrint(FILE *fp, papi_attribute_t **attributes, 1080355b4669Sjacobs char *prefix_fmt, ...) 1081355b4669Sjacobs { 1082355b4669Sjacobs char *prefix = NULL; 1083355b4669Sjacobs char *buffer = NULL; 1084355b4669Sjacobs char *newfmt = NULL; 1085355b4669Sjacobs void *mem; 1086355b4669Sjacobs ssize_t size = 0; 1087355b4669Sjacobs va_list ap; 1088355b4669Sjacobs 1089355b4669Sjacobs newfmt = malloc(strlen(prefix_fmt) + 2); 1090355b4669Sjacobs sprintf(newfmt, "\n%s", prefix_fmt); 1091355b4669Sjacobs 1092355b4669Sjacobs va_start(ap, prefix_fmt); 1093355b4669Sjacobs while (vsnprintf(prefix, size, newfmt, ap) > size) { 1094355b4669Sjacobs size += 1024; 1095355b4669Sjacobs mem = realloc(prefix, size); 1096355b4669Sjacobs if (!mem) goto error; 1097355b4669Sjacobs prefix = mem; 1098355b4669Sjacobs } 1099355b4669Sjacobs va_end(ap); 1100355b4669Sjacobs 1101355b4669Sjacobs if (attributes) { 1102355b4669Sjacobs size = 0; 1103355b4669Sjacobs while (papiAttributeListToString(attributes, prefix, buffer, 1104355b4669Sjacobs size) != PAPI_OK) { 1105355b4669Sjacobs size += 1024; 1106355b4669Sjacobs mem = realloc(buffer, size); 1107355b4669Sjacobs if (!mem) goto error; 1108355b4669Sjacobs buffer = mem; 1109355b4669Sjacobs } 1110355b4669Sjacobs } 1111355b4669Sjacobs 1112355b4669Sjacobs fprintf(fp, "%s%s\n", prefix, buffer ? buffer : ""); 1113355b4669Sjacobs fflush(fp); 1114355b4669Sjacobs 1115355b4669Sjacobs error: 1116355b4669Sjacobs free(newfmt); 1117355b4669Sjacobs free(prefix); 1118355b4669Sjacobs free(buffer); 1119355b4669Sjacobs } 1120