17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * 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. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21355b4669Sjacobs 227c478bd9Sstevel@tonic-gate /* 23*ee169c7eSGary Mills * Copyright (c) 2014 Gary Mills 24*ee169c7eSGary Mills * 2543b9c050Sjacobs * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate * Use is subject to license terms. 27355b4669Sjacobs * 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 30355b4669Sjacobs /* $Id: attribute.c 157 2006-04-26 15:07:55Z ktou $ */ 31355b4669Sjacobs 327c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 36355b4669Sjacobs #include <stdarg.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 3843b9c050Sjacobs #include <ctype.h> 39355b4669Sjacobs #include <alloca.h> 40355b4669Sjacobs #include <papi.h> 4143b9c050Sjacobs #include <regex.h> 427c478bd9Sstevel@tonic-gate 43fa9d6f9fSsg #define MAX_PAGES 32767 44fa9d6f9fSsg /* 45fa9d6f9fSsg * Assuming the maximum number of pages in 46fa9d6f9fSsg * a document to be 32767 47fa9d6f9fSsg */ 48fa9d6f9fSsg 497c478bd9Sstevel@tonic-gate static void papiAttributeFree(papi_attribute_t *attribute); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static void 527c478bd9Sstevel@tonic-gate papiAttributeValueFree(papi_attribute_value_type_t type, 537c478bd9Sstevel@tonic-gate papi_attribute_value_t *value) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate if (value != NULL) { 567c478bd9Sstevel@tonic-gate switch (type) { 577c478bd9Sstevel@tonic-gate case PAPI_STRING: 587c478bd9Sstevel@tonic-gate if (value->string != NULL) 597c478bd9Sstevel@tonic-gate free(value->string); 607c478bd9Sstevel@tonic-gate break; 617c478bd9Sstevel@tonic-gate case PAPI_COLLECTION: 627c478bd9Sstevel@tonic-gate if (value->collection != NULL) { 637c478bd9Sstevel@tonic-gate int i; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate for (i = 0; value->collection[i] != NULL; i++) 667c478bd9Sstevel@tonic-gate papiAttributeFree(value->collection[i]); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate free(value->collection); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate break; 717c478bd9Sstevel@tonic-gate default: /* don't need to free anything extra */ 727c478bd9Sstevel@tonic-gate break; 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate free(value); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static void 807c478bd9Sstevel@tonic-gate papiAttributeValuesFree(papi_attribute_value_type_t type, 817c478bd9Sstevel@tonic-gate papi_attribute_value_t **values) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate if (values != NULL) { 847c478bd9Sstevel@tonic-gate int i; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate for (i = 0; values[i] != NULL; i++) 877c478bd9Sstevel@tonic-gate papiAttributeValueFree(type, values[i]); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate free(values); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static void 947c478bd9Sstevel@tonic-gate papiAttributeFree(papi_attribute_t *attribute) 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate if (attribute != NULL) { 977c478bd9Sstevel@tonic-gate if (attribute->name != NULL) 987c478bd9Sstevel@tonic-gate free(attribute->name); 997c478bd9Sstevel@tonic-gate if (attribute->values != NULL) 1007c478bd9Sstevel@tonic-gate papiAttributeValuesFree(attribute->type, 1017c478bd9Sstevel@tonic-gate attribute->values); 1027c478bd9Sstevel@tonic-gate free(attribute); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate void 1077c478bd9Sstevel@tonic-gate papiAttributeListFree(papi_attribute_t **list) 1087c478bd9Sstevel@tonic-gate { 1097c478bd9Sstevel@tonic-gate if (list != NULL) { 1107c478bd9Sstevel@tonic-gate int i; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate for (i = 0; list[i] != NULL; i++) 1137c478bd9Sstevel@tonic-gate papiAttributeFree(list[i]); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate free(list); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate static papi_attribute_t ** 1207c478bd9Sstevel@tonic-gate collection_dup(papi_attribute_t **collection) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate papi_attribute_t **result = NULL; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* allows a NULL collection that is "empty" or "no value" */ 1257c478bd9Sstevel@tonic-gate if (collection != NULL) { 126355b4669Sjacobs papi_status_t status = PAPI_OK; 1277c478bd9Sstevel@tonic-gate int i; 1287c478bd9Sstevel@tonic-gate 129355b4669Sjacobs for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK)); 130355b4669Sjacobs i++) { 1317c478bd9Sstevel@tonic-gate papi_attribute_t *a = collection[i]; 1327c478bd9Sstevel@tonic-gate 133355b4669Sjacobs status = papiAttributeListAddValue(&result, 134355b4669Sjacobs PAPI_ATTR_APPEND, a->name, a->type, 135355b4669Sjacobs NULL); 136355b4669Sjacobs if ((status == PAPI_OK) && (a->values != NULL)) { 1377c478bd9Sstevel@tonic-gate int j; 1387c478bd9Sstevel@tonic-gate 139355b4669Sjacobs for (j = 0; ((a->values[j] != NULL) && 140355b4669Sjacobs (status == PAPI_OK)); j++) 141355b4669Sjacobs status = papiAttributeListAddValue( 142355b4669Sjacobs &result, 1437c478bd9Sstevel@tonic-gate PAPI_ATTR_APPEND, 1447c478bd9Sstevel@tonic-gate a->name, a->type, 1457c478bd9Sstevel@tonic-gate a->values[j]); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate } 148355b4669Sjacobs if (status != PAPI_OK) { 149355b4669Sjacobs papiAttributeListFree(result); 150355b4669Sjacobs result = NULL; 151355b4669Sjacobs } 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate return (result); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate static papi_attribute_value_t * 158355b4669Sjacobs papiAttributeValueDup(papi_attribute_value_type_t type, 159355b4669Sjacobs papi_attribute_value_t *v) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate papi_attribute_value_t *result = NULL; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) { 1647c478bd9Sstevel@tonic-gate switch (type) { 1657c478bd9Sstevel@tonic-gate case PAPI_STRING: 1667c478bd9Sstevel@tonic-gate if (v->string == NULL) { 1677c478bd9Sstevel@tonic-gate free(result); 1687c478bd9Sstevel@tonic-gate result = NULL; 1697c478bd9Sstevel@tonic-gate } else 1707c478bd9Sstevel@tonic-gate result->string = strdup(v->string); 1717c478bd9Sstevel@tonic-gate break; 1727c478bd9Sstevel@tonic-gate case PAPI_INTEGER: 1737c478bd9Sstevel@tonic-gate result->integer = v->integer; 1747c478bd9Sstevel@tonic-gate break; 1757c478bd9Sstevel@tonic-gate case PAPI_BOOLEAN: 1767c478bd9Sstevel@tonic-gate result->boolean = v->boolean; 1777c478bd9Sstevel@tonic-gate break; 1787c478bd9Sstevel@tonic-gate case PAPI_RANGE: 1797c478bd9Sstevel@tonic-gate result->range.lower = v->range.lower; 1807c478bd9Sstevel@tonic-gate result->range.upper = v->range.upper; 1817c478bd9Sstevel@tonic-gate break; 1827c478bd9Sstevel@tonic-gate case PAPI_RESOLUTION: 1837c478bd9Sstevel@tonic-gate result->resolution.xres = v->resolution.xres; 1847c478bd9Sstevel@tonic-gate result->resolution.yres = v->resolution.yres; 1857c478bd9Sstevel@tonic-gate result->resolution.units = v->resolution.units; 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate case PAPI_DATETIME: 1887c478bd9Sstevel@tonic-gate result->datetime = v->datetime; 1897c478bd9Sstevel@tonic-gate break; 1907c478bd9Sstevel@tonic-gate case PAPI_COLLECTION: 1917c478bd9Sstevel@tonic-gate result->collection = collection_dup(v->collection); 1927c478bd9Sstevel@tonic-gate break; 193355b4669Sjacobs case PAPI_METADATA: 194355b4669Sjacobs result->metadata = v->metadata; 195355b4669Sjacobs break; 1967c478bd9Sstevel@tonic-gate default: /* unknown type, fail to duplicate */ 1977c478bd9Sstevel@tonic-gate free(result); 1987c478bd9Sstevel@tonic-gate result = NULL; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate return (result); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate static papi_attribute_t * 206355b4669Sjacobs papiAttributeAlloc(char *name, papi_attribute_value_type_t type) 2077c478bd9Sstevel@tonic-gate { 2087c478bd9Sstevel@tonic-gate papi_attribute_t *result = NULL; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if ((result = calloc(1, sizeof (*result))) != NULL) { 2117c478bd9Sstevel@tonic-gate result->name = strdup(name); 2127c478bd9Sstevel@tonic-gate result->type = type; 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate return (result); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate static papi_status_t 219355b4669Sjacobs papiAttributeListAppendValue(papi_attribute_value_t ***values, 220355b4669Sjacobs papi_attribute_value_type_t type, 221355b4669Sjacobs papi_attribute_value_t *value) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if (values == NULL) 2257c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (value != NULL) { /* this allows "empty" attributes */ 2287c478bd9Sstevel@tonic-gate papi_attribute_value_t *tmp = NULL; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if ((tmp = papiAttributeValueDup(type, value)) == NULL) 2317c478bd9Sstevel@tonic-gate return (PAPI_TEMPORARY_ERROR); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate list_append(values, tmp); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate return (PAPI_OK); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate 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) 2437c478bd9Sstevel@tonic-gate { 2447c478bd9Sstevel@tonic-gate papi_status_t result; 2457c478bd9Sstevel@tonic-gate int flags = flgs; 2467c478bd9Sstevel@tonic-gate papi_attribute_t *attribute = NULL; 2477c478bd9Sstevel@tonic-gate papi_attribute_value_t **values = NULL; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if ((list == NULL) || (name == NULL)) 2507c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if ((type == PAPI_RANGE) && (value != NULL) && 2537c478bd9Sstevel@tonic-gate (value->range.lower > value->range.upper)) 2547c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); /* RANGE must have min <= max */ 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if (flags == 0) /* if it wasn't set, set a default behaviour */ 2577c478bd9Sstevel@tonic-gate flags = PAPI_ATTR_APPEND; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* look for an existing one */ 2607c478bd9Sstevel@tonic-gate attribute = papiAttributeListFind(*list, name); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL)) 2637c478bd9Sstevel@tonic-gate return (PAPI_CONFLICT); /* EXISTS */ 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) && 2667c478bd9Sstevel@tonic-gate (attribute->type != type)) 2677c478bd9Sstevel@tonic-gate return (PAPI_CONFLICT); /* TYPE CONFLICT */ 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* if we don't have one, create it and add it to the list */ 2707c478bd9Sstevel@tonic-gate if ((attribute == NULL) && 2717c478bd9Sstevel@tonic-gate ((attribute = papiAttributeAlloc(name, type)) != NULL)) 2727c478bd9Sstevel@tonic-gate list_append(list, attribute); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* if we don't have one by now, it's most likely an alloc fail */ 2757c478bd9Sstevel@tonic-gate if (attribute == NULL) 2767c478bd9Sstevel@tonic-gate return (PAPI_TEMPORARY_ERROR); 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * if we are replacing, clear any existing values, but don't free 2807c478bd9Sstevel@tonic-gate * until after we have replaced the values, in case we are replacing 2817c478bd9Sstevel@tonic-gate * a collection with a relocated version of the original collection. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) { 2847c478bd9Sstevel@tonic-gate values = attribute->values; 2857c478bd9Sstevel@tonic-gate attribute->values = NULL; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate attribute->type = type; 2897c478bd9Sstevel@tonic-gate 290355b4669Sjacobs result = papiAttributeListAppendValue(&attribute->values, type, value); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* free old values if we replaced them */ 2937c478bd9Sstevel@tonic-gate if (values != NULL) 2947c478bd9Sstevel@tonic-gate papiAttributeValuesFree(type, values); 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate return (result); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate papi_status_t 300355b4669Sjacobs papiAttributeListAddString(papi_attribute_t ***list, int flags, 301355b4669Sjacobs char *name, char *string) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate v.string = (char *)string; 306355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v)); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate papi_status_t 310355b4669Sjacobs papiAttributeListAddInteger(papi_attribute_t ***list, int flags, 311355b4669Sjacobs char *name, int integer) 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate v.integer = integer; 316355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v)); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate papi_status_t 320355b4669Sjacobs papiAttributeListAddBoolean(papi_attribute_t ***list, int flags, 321355b4669Sjacobs char *name, char boolean) 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate v.boolean = boolean; 326355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v)); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate papi_status_t 330355b4669Sjacobs papiAttributeListAddRange(papi_attribute_t ***list, int flags, 331355b4669Sjacobs char *name, int lower, int upper) 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate v.range.lower = lower; 3367c478bd9Sstevel@tonic-gate v.range.upper = upper; 337355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v)); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate papi_status_t 341355b4669Sjacobs papiAttributeListAddResolution(papi_attribute_t ***list, int flags, 342355b4669Sjacobs char *name, int xres, int yres, 343355b4669Sjacobs papi_resolution_unit_t units) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate v.resolution.xres = xres; 3487c478bd9Sstevel@tonic-gate v.resolution.yres = yres; 3497c478bd9Sstevel@tonic-gate v.resolution.units = units; 350355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, 351355b4669Sjacobs PAPI_RESOLUTION, &v)); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate papi_status_t 355355b4669Sjacobs papiAttributeListAddDatetime(papi_attribute_t ***list, int flags, 356355b4669Sjacobs char *name, time_t datetime) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate v.datetime = datetime; 361355b4669Sjacobs return (papiAttributeListAddValue(list, flags, name, 362355b4669Sjacobs PAPI_DATETIME, &v)); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate papi_status_t 366355b4669Sjacobs papiAttributeListAddCollection(papi_attribute_t ***list, int flags, 367355b4669Sjacobs char *name, papi_attribute_t **collection) 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate papi_attribute_value_t v; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate 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)); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate papi_status_t 388355b4669Sjacobs papiAttributeListDelete(papi_attribute_t ***list, char *name) 3897c478bd9Sstevel@tonic-gate { 3907c478bd9Sstevel@tonic-gate papi_attribute_t *attribute; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate if ((list == NULL) || (name == NULL)) 3937c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate if ((attribute = papiAttributeListFind(*list, name)) == NULL) 3967c478bd9Sstevel@tonic-gate return (PAPI_NOT_FOUND); 3977c478bd9Sstevel@tonic-gate 3980a44ef6dSjacobs list_remove(list, attribute); 3997c478bd9Sstevel@tonic-gate papiAttributeFree(attribute); 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate return (PAPI_OK); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate papi_attribute_t * 405355b4669Sjacobs papiAttributeListFind(papi_attribute_t **list, char *name) 4067c478bd9Sstevel@tonic-gate { 407355b4669Sjacobs int i; 408355b4669Sjacobs if ((list == NULL) || (name == NULL)) 409355b4669Sjacobs return (NULL); 4107c478bd9Sstevel@tonic-gate 411355b4669Sjacobs for (i = 0; list[i] != NULL; i++) 412355b4669Sjacobs if (strcasecmp(list[i]->name, name) == 0) 413355b4669Sjacobs return ((papi_attribute_t *)list[i]); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate return (NULL); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate papi_attribute_t * 4197c478bd9Sstevel@tonic-gate papiAttributeListGetNext(papi_attribute_t **list, void **iter) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate papi_attribute_t **tmp, *result; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if ((list == NULL) && (iter == NULL)) 4247c478bd9Sstevel@tonic-gate return (NULL); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate if (*iter == NULL) 4277c478bd9Sstevel@tonic-gate *iter = list; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate tmp = *iter; 4307c478bd9Sstevel@tonic-gate result = *tmp; 4317c478bd9Sstevel@tonic-gate *iter = ++tmp; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate return (result); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate papi_status_t 4377c478bd9Sstevel@tonic-gate papiAttributeListGetValue(papi_attribute_t **list, void **iter, 438355b4669Sjacobs char *name, papi_attribute_value_type_t type, 4397c478bd9Sstevel@tonic-gate papi_attribute_value_t **value) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate papi_attribute_value_t **tmp; 4427c478bd9Sstevel@tonic-gate void *fodder = NULL; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate if ((list == NULL) || ((name == NULL) && (iter == NULL)) || 4457c478bd9Sstevel@tonic-gate (value == NULL)) 4467c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate if (iter == NULL) 4497c478bd9Sstevel@tonic-gate iter = &fodder; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate if ((iter == NULL) || (*iter == NULL)) { 4527c478bd9Sstevel@tonic-gate papi_attribute_t *attr = papiAttributeListFind(list, name); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if (attr == NULL) 4557c478bd9Sstevel@tonic-gate return (PAPI_NOT_FOUND); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (attr->type != type) 4587c478bd9Sstevel@tonic-gate return (PAPI_NOT_POSSIBLE); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate tmp = attr->values; 4617c478bd9Sstevel@tonic-gate } else 4627c478bd9Sstevel@tonic-gate tmp = *iter; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate if (tmp == NULL) 4657c478bd9Sstevel@tonic-gate return (PAPI_NOT_FOUND); 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate *value = *tmp; 4687c478bd9Sstevel@tonic-gate *iter = ++tmp; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if (*value == NULL) 4717c478bd9Sstevel@tonic-gate return (PAPI_GONE); 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate return (PAPI_OK); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate papi_status_t 4777c478bd9Sstevel@tonic-gate papiAttributeListGetString(papi_attribute_t **list, void **iter, 478355b4669Sjacobs char *name, char **vptr) 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate papi_status_t status; 4817c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate if (vptr == NULL) 4847c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 4877c478bd9Sstevel@tonic-gate PAPI_STRING, &value); 4887c478bd9Sstevel@tonic-gate if (status == PAPI_OK) 4897c478bd9Sstevel@tonic-gate *vptr = value->string; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate return (status); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate papi_status_t 4957c478bd9Sstevel@tonic-gate papiAttributeListGetInteger(papi_attribute_t **list, void **iter, 496355b4669Sjacobs char *name, int *vptr) 4977c478bd9Sstevel@tonic-gate { 4987c478bd9Sstevel@tonic-gate papi_status_t status; 4997c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate if (vptr == NULL) 5027c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 5057c478bd9Sstevel@tonic-gate PAPI_INTEGER, &value); 5067c478bd9Sstevel@tonic-gate if (status == PAPI_OK) 5077c478bd9Sstevel@tonic-gate *vptr = value->integer; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate return (status); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate papi_status_t 5137c478bd9Sstevel@tonic-gate papiAttributeListGetBoolean(papi_attribute_t **list, void **iter, 514355b4669Sjacobs char *name, char *vptr) 5157c478bd9Sstevel@tonic-gate { 5167c478bd9Sstevel@tonic-gate papi_status_t status; 5177c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (vptr == NULL) 5207c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 5237c478bd9Sstevel@tonic-gate PAPI_BOOLEAN, &value); 5247c478bd9Sstevel@tonic-gate if (status == PAPI_OK) 5257c478bd9Sstevel@tonic-gate *vptr = value->boolean; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate return (status); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate papi_status_t 5317c478bd9Sstevel@tonic-gate papiAttributeListGetRange(papi_attribute_t **list, void **iter, 532355b4669Sjacobs char *name, int *min, int *max) 5337c478bd9Sstevel@tonic-gate { 5347c478bd9Sstevel@tonic-gate papi_status_t status; 5357c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate if ((min == NULL) || (max == NULL)) 5387c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 5417c478bd9Sstevel@tonic-gate PAPI_RANGE, &value); 5427c478bd9Sstevel@tonic-gate if (status == PAPI_OK) { 5437c478bd9Sstevel@tonic-gate *min = value->range.lower; 5447c478bd9Sstevel@tonic-gate *max = value->range.upper; 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate return (status); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate papi_status_t 5517c478bd9Sstevel@tonic-gate papiAttributeListGetResolution(papi_attribute_t **list, void **iter, 552355b4669Sjacobs char *name, int *x, int *y, 5537c478bd9Sstevel@tonic-gate papi_resolution_unit_t *units) 5547c478bd9Sstevel@tonic-gate { 5557c478bd9Sstevel@tonic-gate papi_status_t status; 5567c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if ((x == NULL) || (y == NULL) || (units == NULL)) 5597c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 5627c478bd9Sstevel@tonic-gate PAPI_RESOLUTION, &value); 5637c478bd9Sstevel@tonic-gate if (status == PAPI_OK) { 5647c478bd9Sstevel@tonic-gate *x = value->resolution.xres; 5657c478bd9Sstevel@tonic-gate *y = value->resolution.yres; 5667c478bd9Sstevel@tonic-gate *units = value->resolution.units; 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate return (status); 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate papi_status_t 5737c478bd9Sstevel@tonic-gate papiAttributeListGetDatetime(papi_attribute_t **list, void **iter, 574355b4669Sjacobs char *name, time_t *dt) 5757c478bd9Sstevel@tonic-gate { 5767c478bd9Sstevel@tonic-gate papi_status_t status; 5777c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (dt == NULL) 5807c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 5837c478bd9Sstevel@tonic-gate PAPI_DATETIME, &value); 5847c478bd9Sstevel@tonic-gate if (status == PAPI_OK) { 5857c478bd9Sstevel@tonic-gate *dt = value->datetime; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate return (status); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate papi_status_t 5927c478bd9Sstevel@tonic-gate papiAttributeListGetCollection(papi_attribute_t **list, void **iter, 593355b4669Sjacobs char *name, papi_attribute_t ***collection) 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate papi_status_t status; 5967c478bd9Sstevel@tonic-gate papi_attribute_value_t *value = NULL; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate if (collection == NULL) 5997c478bd9Sstevel@tonic-gate return (PAPI_BAD_ARGUMENT); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate status = papiAttributeListGetValue(list, iter, name, 6027c478bd9Sstevel@tonic-gate PAPI_COLLECTION, &value); 6037c478bd9Sstevel@tonic-gate if (status == PAPI_OK) { 6047c478bd9Sstevel@tonic-gate *collection = value->collection; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate return (status); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 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 } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate 62943b9c050Sjacobs /* The string is modified by this call */ 6307c478bd9Sstevel@tonic-gate static char * 63143b9c050Sjacobs regvalue(regmatch_t match, char *string) 6327c478bd9Sstevel@tonic-gate { 6337c478bd9Sstevel@tonic-gate 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'; 63743b9c050Sjacobs } 63843b9c050Sjacobs return (result); 63943b9c050Sjacobs } 6407c478bd9Sstevel@tonic-gate 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 }, 656fa9d6f9fSsg { 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]; 66243b9c050Sjacobs 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; 6707c478bd9Sstevel@tonic-gate } 67143b9c050Sjacobs if (regexec(&(types[i].re), string, (size_t)types[i].vals, 67243b9c050Sjacobs matches, 0) == REG_NOMATCH) 67343b9c050Sjacobs continue; 6747c478bd9Sstevel@tonic-gate 67543b9c050Sjacobs for (j = 0 ; j < types[i].vals; j++) 67643b9c050Sjacobs list_append(parts, regvalue(matches[j], string)); 67743b9c050Sjacobs return (types[i].type); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate 68043b9c050Sjacobs list_append(parts, string); 68143b9c050Sjacobs return (PAPI_STRING); 68243b9c050Sjacobs } 6837c478bd9Sstevel@tonic-gate 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: 708fa9d6f9fSsg if (dtype == PAPI_INTEGER) { 709fa9d6f9fSsg if (atoi(parts[0]) < 0) { 710fa9d6f9fSsg /* 711fa9d6f9fSsg * Handles -P -x case 712fa9d6f9fSsg * which prints from page number 1 713fa9d6f9fSsg * till page number x 714fa9d6f9fSsg */ 715fa9d6f9fSsg value->range.lower = 1; 716fa9d6f9fSsg value->range.upper = 0 - (atoi(parts[0])); 717fa9d6f9fSsg } else { 718fa9d6f9fSsg value->range.lower = value->range.upper 719fa9d6f9fSsg = atoi(parts[0]); 720fa9d6f9fSsg } 721fa9d6f9fSsg } else if (dtype == PAPI_RANGE) { 722fa9d6f9fSsg if (parts[2] == NULL) { 723fa9d6f9fSsg value->range.lower = atoi(parts[1]); 724fa9d6f9fSsg /* 725fa9d6f9fSsg * Imposing an artificial limit on 726fa9d6f9fSsg * the upper bound for page range. 727fa9d6f9fSsg */ 728fa9d6f9fSsg value->range.upper = MAX_PAGES; 729fa9d6f9fSsg } else if ((parts[1] != NULL) && (parts[2] != NULL)) { 730fa9d6f9fSsg value->range.lower = atoi(parts[1]); 731fa9d6f9fSsg value->range.upper = atoi(parts[2]); 732fa9d6f9fSsg } 73343b9c050Sjacobs } 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 } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate static papi_status_t 75343b9c050Sjacobs _papiAttributeFromStrings(papi_attribute_t ***list, int flags, 75443b9c050Sjacobs char *key, char **values) 7557c478bd9Sstevel@tonic-gate { 75643b9c050Sjacobs int i; 7577c478bd9Sstevel@tonic-gate papi_status_t result = PAPI_OK; 75843b9c050Sjacobs papi_attribute_t *attr = calloc(1, sizeof (*attr)); 7597c478bd9Sstevel@tonic-gate 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 }; 7657c478bd9Sstevel@tonic-gate 76643b9c050Sjacobs if ((attr == NULL) || ((attr->name = strdup(key)) == NULL)) 76743b9c050Sjacobs return (PAPI_TEMPORARY_ERROR); 7687c478bd9Sstevel@tonic-gate 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) { 77343b9c050Sjacobs attr->type = PAPI_RANGE; 77443b9c050Sjacobs break; 77543b9c050Sjacobs } 7767c478bd9Sstevel@tonic-gate 77743b9c050Sjacobs if (values != NULL) { 77843b9c050Sjacobs papi_attribute_value_t **vals = NULL; 7797c478bd9Sstevel@tonic-gate 78043b9c050Sjacobs for (i = 0; values[i] != NULL; i++) { 78143b9c050Sjacobs papi_attribute_value_type_t dtype; 78243b9c050Sjacobs char **parts = NULL; 7837c478bd9Sstevel@tonic-gate 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); 7897c478bd9Sstevel@tonic-gate } 79043b9c050Sjacobs attr->values = vals; 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 79343b9c050Sjacobs list_append(list, attr); 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate return (result); 79643b9c050Sjacobs } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate static papi_status_t 79943b9c050Sjacobs _parse_attribute_list(papi_attribute_t ***list, int flags, char *string) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate papi_status_t result = PAPI_OK; 80243b9c050Sjacobs char *ptr; 80343b9c050Sjacobs 80443b9c050Sjacobs if ((list == NULL) || (string == NULL)) 80543b9c050Sjacobs return (PAPI_BAD_ARGUMENT); 80643b9c050Sjacobs 80743b9c050Sjacobs if ((ptr = strdup(string)) == NULL) 80843b9c050Sjacobs return (PAPI_TEMPORARY_ERROR); 80943b9c050Sjacobs 81043b9c050Sjacobs while ((*ptr != '\0') && (result == PAPI_OK)) { 81143b9c050Sjacobs char *key, **values = NULL; 81243b9c050Sjacobs 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++; 8487c478bd9Sstevel@tonic-gate } 84943b9c050Sjacobs if (*ptr == ',') 85043b9c050Sjacobs *ptr++ = '\0'; 85143b9c050Sjacobs list_append(&values, value); 8527c478bd9Sstevel@tonic-gate } 85343b9c050Sjacobs } else { /* boolean "[no]key" */ 85443b9c050Sjacobs char *value = "true"; 85543b9c050Sjacobs 85643b9c050Sjacobs if (strncasecmp(key, "no", 2) == 0) { 85743b9c050Sjacobs key += 2; 85843b9c050Sjacobs value = "false"; 85943b9c050Sjacobs } 86043b9c050Sjacobs list_append(&values, value); 8617c478bd9Sstevel@tonic-gate } 86243b9c050Sjacobs if (*ptr != '\0') 86343b9c050Sjacobs *ptr++ = '\0'; 86443b9c050Sjacobs 86543b9c050Sjacobs result = _papiAttributeFromStrings(list, flags, key, values); 86643b9c050Sjacobs free(values); 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate return (result); 87043b9c050Sjacobs } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate papi_status_t 8737c478bd9Sstevel@tonic-gate papiAttributeListFromString(papi_attribute_t ***attrs, 874355b4669Sjacobs int flags, char *string) 8757c478bd9Sstevel@tonic-gate { 8767c478bd9Sstevel@tonic-gate papi_status_t result = PAPI_OK; 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate 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); 88243b9c050Sjacobs } else { 8837c478bd9Sstevel@tonic-gate result = PAPI_BAD_ARGUMENT; 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate return (result); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 889355b4669Sjacobs static papi_status_t 890355b4669Sjacobs papiAttributeToString(papi_attribute_t *attribute, char *delim, 891355b4669Sjacobs char *buffer, size_t buflen) 8927c478bd9Sstevel@tonic-gate { 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 { 90543b9c050Sjacobs 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 93743b9c050Sjacobs 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); 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate 991355b4669Sjacobs papi_status_t 992355b4669Sjacobs papiAttributeListToString(papi_attribute_t **attrs, 993355b4669Sjacobs char *delim, char *buffer, size_t buflen) 9947c478bd9Sstevel@tonic-gate { 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); 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 1011355b4669Sjacobs return (status); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 1014355b4669Sjacobs static int 1015355b4669Sjacobs is_in_list(char *value, char **list) 1016355b4669Sjacobs { 1017355b4669Sjacobs if ((list != NULL) && (value != NULL)) { 1018355b4669Sjacobs int i; 10197c478bd9Sstevel@tonic-gate 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) 10307c478bd9Sstevel@tonic-gate { 1031355b4669Sjacobs papi_status_t status; 1032355b4669Sjacobs int i = 0; 10337c478bd9Sstevel@tonic-gate 1034355b4669Sjacobs if ((list == NULL) || (attribute == NULL) || 1035355b4669Sjacobs (attribute->values == NULL)) 1036355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 10377c478bd9Sstevel@tonic-gate 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++; 10467c478bd9Sstevel@tonic-gate 1047355b4669Sjacobs return (status); 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 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 } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate void 1063355b4669Sjacobs split_and_copy_attributes(char **list, papi_attribute_t **attributes, 1064355b4669Sjacobs papi_attribute_t ***in, papi_attribute_t ***out) 10657c478bd9Sstevel@tonic-gate { 1066355b4669Sjacobs int i; 10677c478bd9Sstevel@tonic-gate 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 } 11107c478bd9Sstevel@tonic-gate } 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); 11197c478bd9Sstevel@tonic-gate } 1120