1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 */ 27 28 /* $Id: attribute.c 157 2006-04-26 15:07:55Z ktou $ */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /*LINTLIBRARY*/ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <stdarg.h> 37 #include <string.h> 38 #include <alloca.h> 39 #include <papi.h> 40 41 static void papiAttributeFree(papi_attribute_t *attribute); 42 43 static void 44 papiAttributeValueFree(papi_attribute_value_type_t type, 45 papi_attribute_value_t *value) 46 { 47 if (value != NULL) { 48 switch (type) { 49 case PAPI_STRING: 50 if (value->string != NULL) 51 free(value->string); 52 break; 53 case PAPI_COLLECTION: 54 if (value->collection != NULL) { 55 int i; 56 57 for (i = 0; value->collection[i] != NULL; i++) 58 papiAttributeFree(value->collection[i]); 59 60 free(value->collection); 61 } 62 break; 63 default: /* don't need to free anything extra */ 64 break; 65 } 66 67 free(value); 68 } 69 } 70 71 static void 72 papiAttributeValuesFree(papi_attribute_value_type_t type, 73 papi_attribute_value_t **values) 74 { 75 if (values != NULL) { 76 int i; 77 78 for (i = 0; values[i] != NULL; i++) 79 papiAttributeValueFree(type, values[i]); 80 81 free(values); 82 } 83 } 84 85 static void 86 papiAttributeFree(papi_attribute_t *attribute) 87 { 88 if (attribute != NULL) { 89 if (attribute->name != NULL) 90 free(attribute->name); 91 if (attribute->values != NULL) 92 papiAttributeValuesFree(attribute->type, 93 attribute->values); 94 free(attribute); 95 } 96 } 97 98 void 99 papiAttributeListFree(papi_attribute_t **list) 100 { 101 if (list != NULL) { 102 int i; 103 104 for (i = 0; list[i] != NULL; i++) 105 papiAttributeFree(list[i]); 106 107 free(list); 108 } 109 } 110 111 static papi_attribute_t ** 112 collection_dup(papi_attribute_t **collection) 113 { 114 papi_attribute_t **result = NULL; 115 116 /* allows a NULL collection that is "empty" or "no value" */ 117 if (collection != NULL) { 118 papi_status_t status = PAPI_OK; 119 int i; 120 121 for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK)); 122 i++) { 123 papi_attribute_t *a = collection[i]; 124 125 status = papiAttributeListAddValue(&result, 126 PAPI_ATTR_APPEND, a->name, a->type, 127 NULL); 128 if ((status == PAPI_OK) && (a->values != NULL)) { 129 int j; 130 131 for (j = 0; ((a->values[j] != NULL) && 132 (status == PAPI_OK)); j++) 133 status = papiAttributeListAddValue( 134 &result, 135 PAPI_ATTR_APPEND, 136 a->name, a->type, 137 a->values[j]); 138 } 139 } 140 if (status != PAPI_OK) { 141 papiAttributeListFree(result); 142 result = NULL; 143 } 144 } 145 146 return (result); 147 } 148 149 static papi_attribute_value_t * 150 papiAttributeValueDup(papi_attribute_value_type_t type, 151 papi_attribute_value_t *v) 152 { 153 papi_attribute_value_t *result = NULL; 154 155 if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) { 156 switch (type) { 157 case PAPI_STRING: 158 if (v->string == NULL) { 159 free(result); 160 result = NULL; 161 } else 162 result->string = strdup(v->string); 163 break; 164 case PAPI_INTEGER: 165 result->integer = v->integer; 166 break; 167 case PAPI_BOOLEAN: 168 result->boolean = v->boolean; 169 break; 170 case PAPI_RANGE: 171 result->range.lower = v->range.lower; 172 result->range.upper = v->range.upper; 173 break; 174 case PAPI_RESOLUTION: 175 result->resolution.xres = v->resolution.xres; 176 result->resolution.yres = v->resolution.yres; 177 result->resolution.units = v->resolution.units; 178 break; 179 case PAPI_DATETIME: 180 result->datetime = v->datetime; 181 break; 182 case PAPI_COLLECTION: 183 result->collection = collection_dup(v->collection); 184 break; 185 case PAPI_METADATA: 186 result->metadata = v->metadata; 187 break; 188 default: /* unknown type, fail to duplicate */ 189 free(result); 190 result = NULL; 191 } 192 } 193 194 return (result); 195 } 196 197 static papi_attribute_t * 198 papiAttributeAlloc(char *name, papi_attribute_value_type_t type) 199 { 200 papi_attribute_t *result = NULL; 201 202 if ((result = calloc(1, sizeof (*result))) != NULL) { 203 result->name = strdup(name); 204 result->type = type; 205 } 206 207 return (result); 208 } 209 210 static papi_status_t 211 papiAttributeListAppendValue(papi_attribute_value_t ***values, 212 papi_attribute_value_type_t type, 213 papi_attribute_value_t *value) 214 { 215 216 if (values == NULL) 217 return (PAPI_BAD_ARGUMENT); 218 219 if (value != NULL) { /* this allows "empty" attributes */ 220 papi_attribute_value_t *tmp = NULL; 221 222 if ((tmp = papiAttributeValueDup(type, value)) == NULL) 223 return (PAPI_TEMPORARY_ERROR); 224 225 list_append(values, tmp); 226 } 227 228 return (PAPI_OK); 229 } 230 231 papi_status_t 232 papiAttributeListAddValue(papi_attribute_t ***list, int flgs, 233 char *name, papi_attribute_value_type_t type, 234 papi_attribute_value_t *value) 235 { 236 papi_status_t result; 237 int flags = flgs; 238 papi_attribute_t *attribute = NULL; 239 papi_attribute_value_t **values = NULL; 240 241 if ((list == NULL) || (name == NULL)) 242 return (PAPI_BAD_ARGUMENT); 243 244 if ((type == PAPI_RANGE) && (value != NULL) && 245 (value->range.lower > value->range.upper)) 246 return (PAPI_BAD_ARGUMENT); /* RANGE must have min <= max */ 247 248 if (flags == 0) /* if it wasn't set, set a default behaviour */ 249 flags = PAPI_ATTR_APPEND; 250 251 /* look for an existing one */ 252 attribute = papiAttributeListFind(*list, name); 253 254 if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL)) 255 return (PAPI_CONFLICT); /* EXISTS */ 256 257 if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) && 258 (attribute->type != type)) 259 return (PAPI_CONFLICT); /* TYPE CONFLICT */ 260 261 /* if we don't have one, create it and add it to the list */ 262 if ((attribute == NULL) && 263 ((attribute = papiAttributeAlloc(name, type)) != NULL)) 264 list_append(list, attribute); 265 266 /* if we don't have one by now, it's most likely an alloc fail */ 267 if (attribute == NULL) 268 return (PAPI_TEMPORARY_ERROR); 269 270 /* 271 * if we are replacing, clear any existing values, but don't free 272 * until after we have replaced the values, in case we are replacing 273 * a collection with a relocated version of the original collection. 274 */ 275 if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) { 276 values = attribute->values; 277 attribute->values = NULL; 278 } 279 280 attribute->type = type; 281 282 result = papiAttributeListAppendValue(&attribute->values, type, value); 283 284 /* free old values if we replaced them */ 285 if (values != NULL) 286 papiAttributeValuesFree(type, values); 287 288 return (result); 289 } 290 291 papi_status_t 292 papiAttributeListAddString(papi_attribute_t ***list, int flags, 293 char *name, char *string) 294 { 295 papi_attribute_value_t v; 296 297 v.string = (char *)string; 298 return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v)); 299 } 300 301 papi_status_t 302 papiAttributeListAddInteger(papi_attribute_t ***list, int flags, 303 char *name, int integer) 304 { 305 papi_attribute_value_t v; 306 307 v.integer = integer; 308 return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v)); 309 } 310 311 papi_status_t 312 papiAttributeListAddBoolean(papi_attribute_t ***list, int flags, 313 char *name, char boolean) 314 { 315 papi_attribute_value_t v; 316 317 v.boolean = boolean; 318 return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v)); 319 } 320 321 papi_status_t 322 papiAttributeListAddRange(papi_attribute_t ***list, int flags, 323 char *name, int lower, int upper) 324 { 325 papi_attribute_value_t v; 326 327 v.range.lower = lower; 328 v.range.upper = upper; 329 return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v)); 330 } 331 332 papi_status_t 333 papiAttributeListAddResolution(papi_attribute_t ***list, int flags, 334 char *name, int xres, int yres, 335 papi_resolution_unit_t units) 336 { 337 papi_attribute_value_t v; 338 339 v.resolution.xres = xres; 340 v.resolution.yres = yres; 341 v.resolution.units = units; 342 return (papiAttributeListAddValue(list, flags, name, 343 PAPI_RESOLUTION, &v)); 344 } 345 346 papi_status_t 347 papiAttributeListAddDatetime(papi_attribute_t ***list, int flags, 348 char *name, time_t datetime) 349 { 350 papi_attribute_value_t v; 351 352 v.datetime = datetime; 353 return (papiAttributeListAddValue(list, flags, name, 354 PAPI_DATETIME, &v)); 355 } 356 357 papi_status_t 358 papiAttributeListAddCollection(papi_attribute_t ***list, int flags, 359 char *name, papi_attribute_t **collection) 360 { 361 papi_attribute_value_t v; 362 363 v.collection = (papi_attribute_t **)collection; 364 return (papiAttributeListAddValue(list, flags, name, 365 PAPI_COLLECTION, &v)); 366 } 367 368 papi_status_t 369 papiAttributeListAddMetadata(papi_attribute_t ***list, int flags, 370 char *name, papi_metadata_t metadata) 371 { 372 papi_attribute_value_t v; 373 374 v.metadata = metadata; 375 return (papiAttributeListAddValue(list, flags, name, 376 PAPI_METADATA, &v)); 377 } 378 379 papi_status_t 380 papiAttributeListDelete(papi_attribute_t ***list, char *name) 381 { 382 papi_attribute_t *attribute; 383 384 if ((list == NULL) || (name == NULL)) 385 return (PAPI_BAD_ARGUMENT); 386 387 if ((attribute = papiAttributeListFind(*list, name)) == NULL) 388 return (PAPI_NOT_FOUND); 389 390 list_remove(list, attribute); 391 papiAttributeFree(attribute); 392 393 return (PAPI_OK); 394 } 395 396 papi_attribute_t * 397 papiAttributeListFind(papi_attribute_t **list, char *name) 398 { 399 int i; 400 if ((list == NULL) || (name == NULL)) 401 return (NULL); 402 403 for (i = 0; list[i] != NULL; i++) 404 if (strcasecmp(list[i]->name, name) == 0) 405 return ((papi_attribute_t *)list[i]); 406 407 return (NULL); 408 } 409 410 papi_attribute_t * 411 papiAttributeListGetNext(papi_attribute_t **list, void **iter) 412 { 413 papi_attribute_t **tmp, *result; 414 415 if ((list == NULL) && (iter == NULL)) 416 return (NULL); 417 418 if (*iter == NULL) 419 *iter = list; 420 421 tmp = *iter; 422 result = *tmp; 423 *iter = ++tmp; 424 425 return (result); 426 } 427 428 papi_status_t 429 papiAttributeListGetValue(papi_attribute_t **list, void **iter, 430 char *name, papi_attribute_value_type_t type, 431 papi_attribute_value_t **value) 432 { 433 papi_attribute_value_t **tmp; 434 void *fodder = NULL; 435 436 if ((list == NULL) || ((name == NULL) && (iter == NULL)) || 437 (value == NULL)) 438 return (PAPI_BAD_ARGUMENT); 439 440 if (iter == NULL) 441 iter = &fodder; 442 443 if ((iter == NULL) || (*iter == NULL)) { 444 papi_attribute_t *attr = papiAttributeListFind(list, name); 445 446 if (attr == NULL) 447 return (PAPI_NOT_FOUND); 448 449 if (attr->type != type) 450 return (PAPI_NOT_POSSIBLE); 451 452 tmp = attr->values; 453 } else 454 tmp = *iter; 455 456 if (tmp == NULL) 457 return (PAPI_NOT_FOUND); 458 459 *value = *tmp; 460 *iter = ++tmp; 461 462 if (*value == NULL) 463 return (PAPI_GONE); 464 465 return (PAPI_OK); 466 } 467 468 papi_status_t 469 papiAttributeListGetString(papi_attribute_t **list, void **iter, 470 char *name, char **vptr) 471 { 472 papi_status_t status; 473 papi_attribute_value_t *value = NULL; 474 475 if (vptr == NULL) 476 return (PAPI_BAD_ARGUMENT); 477 478 status = papiAttributeListGetValue(list, iter, name, 479 PAPI_STRING, &value); 480 if (status == PAPI_OK) 481 *vptr = value->string; 482 483 return (status); 484 } 485 486 papi_status_t 487 papiAttributeListGetInteger(papi_attribute_t **list, void **iter, 488 char *name, int *vptr) 489 { 490 papi_status_t status; 491 papi_attribute_value_t *value = NULL; 492 493 if (vptr == NULL) 494 return (PAPI_BAD_ARGUMENT); 495 496 status = papiAttributeListGetValue(list, iter, name, 497 PAPI_INTEGER, &value); 498 if (status == PAPI_OK) 499 *vptr = value->integer; 500 501 return (status); 502 } 503 504 papi_status_t 505 papiAttributeListGetBoolean(papi_attribute_t **list, void **iter, 506 char *name, char *vptr) 507 { 508 papi_status_t status; 509 papi_attribute_value_t *value = NULL; 510 511 if (vptr == NULL) 512 return (PAPI_BAD_ARGUMENT); 513 514 status = papiAttributeListGetValue(list, iter, name, 515 PAPI_BOOLEAN, &value); 516 if (status == PAPI_OK) 517 *vptr = value->boolean; 518 519 return (status); 520 } 521 522 papi_status_t 523 papiAttributeListGetRange(papi_attribute_t **list, void **iter, 524 char *name, int *min, int *max) 525 { 526 papi_status_t status; 527 papi_attribute_value_t *value = NULL; 528 529 if ((min == NULL) || (max == NULL)) 530 return (PAPI_BAD_ARGUMENT); 531 532 status = papiAttributeListGetValue(list, iter, name, 533 PAPI_RANGE, &value); 534 if (status == PAPI_OK) { 535 *min = value->range.lower; 536 *max = value->range.upper; 537 } 538 539 return (status); 540 } 541 542 papi_status_t 543 papiAttributeListGetResolution(papi_attribute_t **list, void **iter, 544 char *name, int *x, int *y, 545 papi_resolution_unit_t *units) 546 { 547 papi_status_t status; 548 papi_attribute_value_t *value = NULL; 549 550 if ((x == NULL) || (y == NULL) || (units == NULL)) 551 return (PAPI_BAD_ARGUMENT); 552 553 status = papiAttributeListGetValue(list, iter, name, 554 PAPI_RESOLUTION, &value); 555 if (status == PAPI_OK) { 556 *x = value->resolution.xres; 557 *y = value->resolution.yres; 558 *units = value->resolution.units; 559 } 560 561 return (status); 562 } 563 564 papi_status_t 565 papiAttributeListGetDatetime(papi_attribute_t **list, void **iter, 566 char *name, time_t *dt) 567 { 568 papi_status_t status; 569 papi_attribute_value_t *value = NULL; 570 571 if (dt == NULL) 572 return (PAPI_BAD_ARGUMENT); 573 574 status = papiAttributeListGetValue(list, iter, name, 575 PAPI_DATETIME, &value); 576 if (status == PAPI_OK) { 577 *dt = value->datetime; 578 } 579 580 return (status); 581 } 582 583 papi_status_t 584 papiAttributeListGetCollection(papi_attribute_t **list, void **iter, 585 char *name, papi_attribute_t ***collection) 586 { 587 papi_status_t status; 588 papi_attribute_value_t *value = NULL; 589 590 if (collection == NULL) 591 return (PAPI_BAD_ARGUMENT); 592 593 status = papiAttributeListGetValue(list, iter, name, 594 PAPI_COLLECTION, &value); 595 if (status == PAPI_OK) { 596 *collection = value->collection; 597 } 598 599 return (status); 600 } 601 602 papi_status_t 603 papiAttributeListGetMetadata(papi_attribute_t **list, void **iter, 604 char *name, papi_metadata_t *vptr) 605 { 606 papi_status_t status; 607 papi_attribute_value_t *value = NULL; 608 609 if (vptr == NULL) 610 return (PAPI_BAD_ARGUMENT); 611 612 status = papiAttributeListGetValue(list, iter, name, 613 PAPI_METADATA, &value); 614 if (status == PAPI_OK) 615 *vptr = value->metadata; 616 617 return (status); 618 } 619 620 /* 621 * Description: The given string contains one or more attributes, in the 622 * following form: 623 * "aaaa=true bbbbb=1 ccccc=abcd" 624 * extract the next attribute from that string; the 'next' 625 * parameter should be set to zero to extract the first attribute 626 * in the string. 627 * 628 */ 629 630 static char * 631 _getNextAttr(char *string, int *next) 632 633 { 634 char *result = NULL; 635 char *start = (char *)string + *next; 636 char *nl = NULL; 637 char *sp = NULL; 638 char *tab = NULL; 639 char *val = NULL; 640 int len = 0; 641 642 if ((string != NULL) && (*start != '\0')) { 643 while ((*start == ' ') || (*start == '\t') || (*start == '\n')) 644 { 645 start++; 646 } 647 nl = strchr(start, '\n'); 648 sp = strchr(start, ' '); 649 tab = strchr(start, '\t'); 650 651 val = strchr(start, '='); 652 653 if ((val != NULL) && ((val[1] == '"') || (val[1] == '\''))) { 654 val = strchr(&val[2], val[1]); 655 if (val != NULL) { 656 nl = strchr(&val[1], '\n'); 657 sp = strchr(&val[1], ' '); 658 tab = strchr(&val[1], '\t'); 659 } 660 } 661 662 if ((nl != NULL) && 663 ((sp == NULL) || ((sp != NULL) && (nl < sp))) && 664 ((tab == NULL) || ((tab != NULL) && (nl < tab)))) { 665 len = nl-start; 666 } else if ((sp != NULL) && (tab != NULL) && (sp > tab)) { 667 len = tab-start; 668 } else if ((sp != NULL) && (sp != NULL)) { 669 len = sp-start; 670 } else if ((tab != NULL) && (tab != NULL)) { 671 len = tab-start; 672 } 673 674 if (len == 0) { 675 len = strlen(start); 676 } 677 678 if (len > 0) { 679 result = (char *)malloc(len+1); 680 if (result != NULL) { 681 strncpy(result, start, len); 682 result[len] = '\0'; 683 *next = (start-string)+len; 684 } 685 } 686 } 687 688 return (result); 689 } /* _getNextAttr() */ 690 691 692 /* 693 * Description: Parse the given attribute string value and transform it into 694 * the papi_attribute_value_t in the papi_attribute_t structure. 695 * 696 */ 697 698 static papi_status_t 699 _parseAttrValue(char *value, papi_attribute_t *attr) 700 701 { 702 papi_status_t result = PAPI_OK; 703 int len = 0; 704 int i = 0; 705 char *papiString = NULL; 706 char *tmp1 = NULL; 707 char *tmp2 = NULL; 708 char *tmp3 = NULL; 709 papi_attribute_value_t **avalues = NULL; 710 711 avalues = malloc(sizeof (papi_attribute_value_t *) * 2); 712 if (avalues == NULL) { 713 result = PAPI_TEMPORARY_ERROR; 714 return (result); 715 } 716 avalues[0] = malloc(sizeof (papi_attribute_value_t)); 717 avalues[1] = NULL; 718 if (avalues[0] == NULL) { 719 free(avalues); 720 result = PAPI_TEMPORARY_ERROR; 721 return (result); 722 } 723 724 725 /* 726 * TODO - need to sort out 'resolution', 'dateandtime' & 'collection' values 727 */ 728 if ((value != NULL) && (strlen(value) > 0) && (attr != NULL)) { 729 730 len = strlen(value); 731 if ((len >= 2) && (((value[0] == '"') && 732 (value[len-1] == '"')) || ((value[0] == '\'') && 733 (value[len-1] == '\'')))) { 734 /* string value */ 735 attr->type = PAPI_STRING; 736 737 papiString = strdup(value+1); 738 if (papiString != NULL) { 739 papiString[strlen(papiString)-1] = '\0'; 740 avalues[0]->string = papiString; 741 } else { 742 result = PAPI_TEMPORARY_ERROR; 743 } 744 } else if ((strcasecmp(value, "true") == 0) || 745 (strcasecmp(value, "YES") == 0)) { 746 /* boolean = true */ 747 attr->type = PAPI_BOOLEAN; 748 avalues[0]->boolean = PAPI_TRUE; 749 } else if ((strcasecmp(value, "false") == 0) || 750 (strcasecmp(value, "NO") == 0)) { 751 /* boolean = false */ 752 attr->type = PAPI_BOOLEAN; 753 avalues[0]->boolean = PAPI_FALSE; 754 } else { 755 /* is value an integer or a range ? */ 756 757 i = 0; 758 attr->type = PAPI_INTEGER; 759 tmp1 = strdup(value); 760 while (((value[i] >= '0') && (value[i] <= '9')) || 761 (value[i] == '-')) { 762 if (value[i] == '-') { 763 tmp1[i] = '\0'; 764 tmp2 = &tmp1[i+1]; 765 attr->type = PAPI_RANGE; 766 } 767 768 i++; 769 } 770 771 if (strlen(value) == i) { 772 if (attr->type == PAPI_RANGE) { 773 avalues[0]->range.lower = atoi(tmp1); 774 avalues[0]->range.upper = atoi(tmp2); 775 } else { 776 avalues[0]->integer = atoi(value); 777 } 778 } else { 779 /* is value a resolution ? */ 780 i = 0; 781 attr->type = PAPI_INTEGER; 782 tmp1 = strdup(value); 783 while (((value[i] >= '0') && 784 (value[i] <= '9')) || 785 (value[i] == 'x')) { 786 if (value[i] == 'x') { 787 tmp1[i] = '\0'; 788 if (attr->type == PAPI_INTEGER) 789 { 790 tmp2 = &tmp1[i+1]; 791 attr->type = 792 PAPI_RESOLUTION; 793 } else { 794 tmp3 = &tmp1[i+1]; 795 } 796 } 797 798 i++; 799 } 800 801 if (strlen(value) == i) { 802 if (attr->type == PAPI_RESOLUTION) { 803 avalues[0]->resolution.xres = 804 atoi(tmp1); 805 avalues[0]->resolution.yres = 806 atoi(tmp2); 807 if (tmp3 != NULL) { 808 avalues[0]-> 809 resolution.units = 810 atoi(tmp3); 811 } else { 812 avalues[0]-> 813 resolution.units = 0; 814 } 815 } 816 } 817 818 if (attr->type != PAPI_RESOLUTION) { 819 attr->type = PAPI_STRING; 820 avalues[0]->string = strdup(value); 821 if (avalues[0]->string == NULL) { 822 result = PAPI_TEMPORARY_ERROR; 823 } 824 } 825 } 826 free(tmp1); 827 } 828 829 } else { 830 result = PAPI_BAD_ARGUMENT; 831 } 832 833 if (result != PAPI_OK) { 834 i = 0; 835 while (avalues[i] != NULL) { 836 free(avalues[i]); 837 i++; 838 } 839 free(avalues); 840 } else { 841 attr->values = avalues; 842 } 843 844 return (result); 845 } /* _parseAttrValue() */ 846 847 848 /* 849 * Description: Parse the given attribute string and transform it into the 850 * papi_attribute_t structure. 851 * 852 */ 853 854 static papi_status_t 855 _parseAttributeString(char *attrString, papi_attribute_t *attr) 856 857 { 858 papi_status_t result = PAPI_OK; 859 char *string = NULL; 860 char *p = NULL; 861 papi_attribute_value_t **avalues = NULL; 862 863 if ((attrString != NULL) && (strlen(attrString) >= 3) && 864 (attr != NULL)) { 865 attr->name = NULL; 866 string = strdup(attrString); 867 if (string != NULL) { 868 p = strchr(string, '='); 869 if (p != NULL) { 870 *p = '\0'; 871 attr->name = string; 872 p++; /* pointer to value */ 873 874 result = _parseAttrValue(p, attr); 875 } else { 876 char value; 877 /* boolean - no value so assume 'true' */ 878 if (strncasecmp(string, "no", 2) == 0) { 879 string += 2; 880 value = PAPI_FALSE; 881 } else 882 value = PAPI_TRUE; 883 884 attr->name = string; 885 attr->type = PAPI_BOOLEAN; 886 887 avalues = malloc( 888 sizeof (papi_attribute_value_t *) * 2); 889 if (avalues == NULL) { 890 result = PAPI_TEMPORARY_ERROR; 891 } else { 892 avalues[0] = malloc( 893 sizeof (papi_attribute_value_t)); 894 avalues[1] = NULL; 895 if (avalues[0] == NULL) { 896 free(avalues); 897 result = PAPI_TEMPORARY_ERROR; 898 } else { 899 avalues[0]->boolean = value; 900 attr->values = avalues; 901 } 902 } 903 } 904 } 905 } else { 906 result = PAPI_BAD_ARGUMENT; 907 } 908 909 return (result); 910 } /* _parseAttributeString() */ 911 912 913 papi_status_t 914 papiAttributeListFromString(papi_attribute_t ***attrs, 915 int flags, char *string) 916 { 917 papi_status_t result = PAPI_OK; 918 int next = 0; 919 char *attrString = NULL; 920 papi_attribute_t attr; 921 922 if ((attrs != NULL) && (string != NULL) && 923 ((flags & ~(PAPI_ATTR_APPEND+PAPI_ATTR_REPLACE+PAPI_ATTR_EXCL)) 924 == 0)) { 925 attrString = _getNextAttr(string, &next); 926 while ((result == PAPI_OK) && (attrString != NULL)) { 927 result = _parseAttributeString(attrString, &attr); 928 if ((result == PAPI_OK) && (attr.name != NULL)) { 929 /* add this attribute to the list */ 930 if ((attr.values != NULL) && 931 (attr.values[0] != NULL)) { 932 result = papiAttributeListAddValue( 933 attrs, PAPI_ATTR_APPEND, 934 attr.name, attr.type, 935 attr.values[0]); 936 free(attr.values[0]); 937 free(attr.values); 938 } else { 939 result = PAPI_TEMPORARY_ERROR; 940 } 941 } 942 free(attrString); 943 944 attrString = _getNextAttr(string, &next); 945 } 946 } 947 else 948 { 949 result = PAPI_BAD_ARGUMENT; 950 } 951 952 return (result); 953 } 954 955 static papi_status_t 956 papiAttributeToString(papi_attribute_t *attribute, char *delim, 957 char *buffer, size_t buflen) 958 { 959 papi_attribute_value_t **values = attribute->values; 960 int rc, i; 961 962 strlcat(buffer, attribute->name, buflen); 963 strlcat(buffer, "=", buflen); 964 965 if (values == NULL) 966 return (PAPI_OK); 967 968 for (i = 0; values[i] != NULL; i++) { 969 switch (attribute->type) { 970 case PAPI_STRING: 971 rc = strlcat(buffer, values[i]->string, buflen); 972 break; 973 case PAPI_INTEGER: { 974 char string[24]; 975 976 snprintf(string, sizeof (string), "%d", 977 values[i]->integer); 978 rc = strlcat(buffer, string, buflen); 979 } 980 break; 981 case PAPI_BOOLEAN: 982 rc = strlcat(buffer, (values[i]->boolean ? "true" : 983 "false"), buflen); 984 break; 985 case PAPI_RANGE: { 986 char string[24]; 987 988 snprintf(string, sizeof (string), "%d-%d", 989 values[i]->range.lower, values[i]->range.upper); 990 rc = strlcat(buffer, string, buflen); 991 } 992 break; 993 case PAPI_RESOLUTION: { 994 char string[24]; 995 996 snprintf(string, sizeof (string), "%dx%ddp%c", 997 values[i]->resolution.xres, 998 values[i]->resolution.yres, 999 (values[i]->resolution.units == PAPI_RES_PER_CM 1000 ? 'c' : 'i')); 1001 rc = strlcat(buffer, string, buflen); 1002 } 1003 break; 1004 case PAPI_DATETIME: { 1005 struct tm *tm = localtime(&values[i]->datetime); 1006 1007 if (tm != NULL) { 1008 char string[64]; 1009 1010 strftime(string, sizeof (string), "%C", tm); 1011 rc = strlcat(buffer, string, buflen); 1012 }} 1013 break; 1014 case PAPI_COLLECTION: { 1015 char *string = alloca(buflen); 1016 #ifdef DEBUG 1017 char prefix[256]; 1018 1019 snprintf(prefix, sizeof (prefix), "%s %s(%d) ", delim, 1020 attribute->name, i); 1021 1022 papiAttributeListToString(values[i]->collection, 1023 prefix, string, buflen); 1024 #else 1025 papiAttributeListToString(values[i]->collection, 1026 delim, string, buflen); 1027 #endif 1028 rc = strlcat(buffer, string, buflen); 1029 } 1030 break; 1031 default: { 1032 char string[32]; 1033 1034 snprintf(string, sizeof (string), "unknown-type-0x%x", 1035 attribute->type); 1036 rc = strlcat(buffer, string, buflen); 1037 } 1038 } 1039 if (values[i+1] != NULL) 1040 rc = strlcat(buffer, ",", buflen); 1041 1042 if (rc >= buflen) 1043 return (PAPI_NOT_POSSIBLE); 1044 1045 } 1046 1047 return (PAPI_OK); 1048 } 1049 1050 papi_status_t 1051 papiAttributeListToString(papi_attribute_t **attrs, 1052 char *delim, char *buffer, size_t buflen) 1053 { 1054 papi_status_t status = PAPI_OK; 1055 int i; 1056 1057 if ((attrs == NULL) || (buffer == NULL)) 1058 return (PAPI_BAD_ARGUMENT); 1059 1060 buffer[0] = '\0'; 1061 if (!delim) 1062 delim = " "; 1063 1064 #ifdef DEBUG 1065 strlcat(buffer, delim, buflen); 1066 #endif 1067 for (i = 0; ((attrs[i] != NULL) && (status == PAPI_OK)); i++) { 1068 status = papiAttributeToString(attrs[i], delim, buffer, buflen); 1069 if (attrs[i+1] != NULL) 1070 strlcat(buffer, delim, buflen); 1071 } 1072 1073 return (status); 1074 } 1075 1076 static int 1077 is_in_list(char *value, char **list) 1078 { 1079 if ((list != NULL) && (value != NULL)) { 1080 int i; 1081 1082 for (i = 0; list[i] != NULL; i++) 1083 if (strcasecmp(value, list[i]) == 0) 1084 return (0); 1085 } 1086 1087 return (1); 1088 } 1089 1090 static papi_status_t 1091 copy_attribute(papi_attribute_t ***list, papi_attribute_t *attribute) 1092 { 1093 papi_status_t status; 1094 int i = 0; 1095 1096 if ((list == NULL) || (attribute == NULL) || 1097 (attribute->values == NULL)) 1098 return (PAPI_BAD_ARGUMENT); 1099 1100 for (status = papiAttributeListAddValue(list, PAPI_ATTR_EXCL, 1101 attribute->name, attribute->type, 1102 attribute->values[i]); 1103 ((status == PAPI_OK) && (attribute->values[i] != NULL)); 1104 status = papiAttributeListAddValue(list, PAPI_ATTR_APPEND, 1105 attribute->name, attribute->type, 1106 attribute->values[i])) 1107 i++; 1108 1109 return (status); 1110 } 1111 1112 void 1113 copy_attributes(papi_attribute_t ***result, papi_attribute_t **attributes) 1114 { 1115 int i; 1116 1117 if ((result == NULL) || (attributes == NULL)) 1118 return; 1119 1120 for (i = 0; attributes[i] != NULL; i++) 1121 copy_attribute(result, attributes[i]); 1122 } 1123 1124 void 1125 split_and_copy_attributes(char **list, papi_attribute_t **attributes, 1126 papi_attribute_t ***in, papi_attribute_t ***out) 1127 { 1128 int i; 1129 1130 if ((list == NULL) || (attributes == NULL)) 1131 return; 1132 1133 for (i = 0; attributes[i] != NULL; i++) 1134 if (is_in_list(attributes[i]->name, list) == 0) 1135 copy_attribute(in, attributes[i]); 1136 else 1137 copy_attribute(out, attributes[i]); 1138 } 1139 1140 void 1141 papiAttributeListPrint(FILE *fp, papi_attribute_t **attributes, 1142 char *prefix_fmt, ...) 1143 { 1144 char *prefix = NULL; 1145 char *buffer = NULL; 1146 char *newfmt = NULL; 1147 void *mem; 1148 ssize_t size = 0; 1149 va_list ap; 1150 1151 newfmt = malloc(strlen(prefix_fmt) + 2); 1152 sprintf(newfmt, "\n%s", prefix_fmt); 1153 1154 va_start(ap, prefix_fmt); 1155 while (vsnprintf(prefix, size, newfmt, ap) > size) { 1156 size += 1024; 1157 mem = realloc(prefix, size); 1158 if (!mem) goto error; 1159 prefix = mem; 1160 } 1161 va_end(ap); 1162 1163 if (attributes) { 1164 size = 0; 1165 while (papiAttributeListToString(attributes, prefix, buffer, 1166 size) != PAPI_OK) { 1167 size += 1024; 1168 mem = realloc(buffer, size); 1169 if (!mem) goto error; 1170 buffer = mem; 1171 } 1172 } 1173 1174 fprintf(fp, "%s%s\n", prefix, buffer ? buffer : ""); 1175 fflush(fp); 1176 1177 error: 1178 free(newfmt); 1179 free(prefix); 1180 free(buffer); 1181 } 1182