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