2424
2525#include "opal/mca/base/mca_base_var_enum.h"
2626#include "opal/mca/base/base.h"
27+ #include "opal/util/argv.h"
2728
2829#include <stdio.h>
2930#include <string.h>
@@ -34,6 +35,11 @@ static void mca_base_var_enum_destructor (mca_base_var_enum_t *enumerator);
3435OBJ_CLASS_INSTANCE (mca_base_var_enum_t , opal_object_t , mca_base_var_enum_constructor ,
3536 mca_base_var_enum_destructor );
3637
38+ static void mca_base_var_enum_flag_constructor (mca_base_var_enum_flag_t * enumerator );
39+ static void mca_base_var_enum_flag_destructor (mca_base_var_enum_flag_t * enumerator );
40+ OBJ_CLASS_INSTANCE (mca_base_var_enum_flag_t , opal_object_t , mca_base_var_enum_flag_constructor ,
41+ mca_base_var_enum_flag_destructor );
42+
3743static int enum_dump (mca_base_var_enum_t * self , char * * out );
3844static int enum_get_count (mca_base_var_enum_t * self , int * count );
3945static int enum_get_value (mca_base_var_enum_t * self , int index , int * value , const char * * string_value );
@@ -85,10 +91,10 @@ static int mca_base_var_enum_bool_vfs (mca_base_var_enum_t *self, const char *st
8591}
8692
8793static int mca_base_var_enum_bool_sfv (mca_base_var_enum_t * self , const int value ,
88- const char * * string_value )
94+ char * * string_value )
8995{
9096 if (string_value ) {
91- * string_value = value ? "true" : "false" ;
97+ * string_value = strdup ( value ? "true" : "false" ) ;
9298 }
9399
94100 return OPAL_SUCCESS ;
@@ -155,24 +161,26 @@ static int mca_base_var_enum_verbose_vfs (mca_base_var_enum_t *self, const char
155161}
156162
157163static int mca_base_var_enum_verbose_sfv (mca_base_var_enum_t * self , const int value ,
158- const char * * string_value )
164+ char * * string_value )
159165{
160- static char buffer [ 4 ] ;
166+ int ret ;
161167
162168 if (value < 0 || value > 100 ) {
163169 return OPAL_ERR_VALUE_OUT_OF_BOUNDS ;
164170 }
165171
166172 for (int i = 0 ; verbose_values [i ].string ; ++ i ) {
167173 if (verbose_values [i ].value == value ) {
168- * string_value = verbose_values [i ].string ;
174+ * string_value = strdup ( verbose_values [i ].string ) ;
169175 return OPAL_SUCCESS ;
170176 }
171177 }
172178
173- snprintf (buffer , 4 , "%d" , value );
174179 if (string_value ) {
175- * string_value = buffer ;
180+ ret = asprintf (string_value , "%d" , value );
181+ if (0 > ret ) {
182+ return OPAL_ERR_OUT_OF_RESOURCE ;
183+ }
176184 }
177185
178186 return OPAL_SUCCESS ;
@@ -251,6 +259,52 @@ int mca_base_var_enum_create (const char *name, const mca_base_var_enum_value_t
251259 return OPAL_SUCCESS ;
252260}
253261
262+ int mca_base_var_enum_create_flag (const char * name , const mca_base_var_enum_value_flag_t * flags , mca_base_var_enum_flag_t * * enumerator )
263+ {
264+ mca_base_var_enum_flag_t * new_enum ;
265+ int i ;
266+
267+ * enumerator = NULL ;
268+
269+ new_enum = OBJ_NEW (mca_base_var_enum_flag_t );
270+ if (NULL == new_enum ) {
271+ return OPAL_ERR_OUT_OF_RESOURCE ;
272+ }
273+
274+ new_enum -> super .enum_name = strdup (name );
275+ if (NULL == new_enum -> super .enum_name ) {
276+ return OPAL_ERR_OUT_OF_RESOURCE ;
277+ }
278+
279+ for (i = 0 ; flags [i ].string ; ++ i );
280+ new_enum -> super .enum_value_count = i ;
281+
282+ /* make a copy of the values */
283+ new_enum -> enum_flags = calloc (new_enum -> super .enum_value_count + 1 , sizeof (* new_enum -> enum_flags ));
284+ if (NULL == new_enum -> enum_flags ) {
285+ OBJ_RELEASE (new_enum );
286+ return OPAL_ERR_OUT_OF_RESOURCE ;
287+ }
288+
289+ int all_flags = 0 ;
290+ for (i = 0 ; i < new_enum -> super .enum_value_count ; ++ i ) {
291+ new_enum -> enum_flags [i ].flag = flags [i ].flag ;
292+ new_enum -> enum_flags [i ].string = strdup (flags [i ].string );
293+ new_enum -> enum_flags [i ].conflicting_flag = flags [i ].conflicting_flag ;
294+ /* ensure flags are only set a single bit, doesn't conflict with itself, and
295+ * hasn't already been specified. */
296+ assert (!(flags [i ].flag & (flags [i ].flag - 1 )));
297+ assert (!(flags [i ].flag & flags [i ].conflicting_flag ));
298+ assert (!(all_flags & flags [i ].flag ));
299+ assert (flags [i ].flag );
300+ all_flags |= flags [i ].flag ;
301+ }
302+
303+ * enumerator = new_enum ;
304+
305+ return OPAL_SUCCESS ;
306+ }
307+
254308static int enum_dump (mca_base_var_enum_t * self , char * * out )
255309{
256310 int i ;
@@ -301,7 +355,7 @@ static int enum_get_value (mca_base_var_enum_t *self, int index, int *value, con
301355 }
302356
303357 if (string_value ) {
304- * string_value = self -> enum_values [index ].string ;
358+ * string_value = strdup ( self -> enum_values [index ].string ) ;
305359 }
306360
307361 return OPAL_SUCCESS ;
@@ -338,7 +392,7 @@ static int enum_value_from_string(mca_base_var_enum_t *self, const char *string_
338392 return OPAL_SUCCESS ;
339393}
340394
341- static int enum_string_from_value (mca_base_var_enum_t * self , const int value , const char * * string_value ) {
395+ static int enum_string_from_value (mca_base_var_enum_t * self , const int value , char * * string_value ) {
342396 int count , ret , i ;
343397
344398 ret = self -> get_count (self , & count );
@@ -357,7 +411,7 @@ static int enum_string_from_value(mca_base_var_enum_t *self, const int value, co
357411 }
358412
359413 if (string_value ) {
360- * string_value = self -> enum_values [i ].string ;
414+ * string_value = strdup ( self -> enum_values [i ].string ) ;
361415 }
362416
363417 return OPAL_SUCCESS ;
@@ -389,3 +443,178 @@ static void mca_base_var_enum_destructor (mca_base_var_enum_t *enumerator)
389443 free (enumerator -> enum_values );
390444 }
391445}
446+
447+ static int enum_get_value_flag (mca_base_var_enum_t * self , int index , int * value , const char * * string_value )
448+ {
449+ mca_base_var_enum_flag_t * flag_enum = (mca_base_var_enum_flag_t * ) self ;
450+ int count , ret ;
451+
452+ ret = self -> get_count (self , & count );
453+ if (OPAL_SUCCESS != ret ) {
454+ return ret ;
455+ }
456+
457+ if (index >= count ) {
458+ return OPAL_ERR_VALUE_OUT_OF_BOUNDS ;
459+ }
460+
461+ if (value ) {
462+ * value = flag_enum -> enum_flags [index ].flag ;
463+ }
464+
465+ if (string_value ) {
466+ * string_value = strdup (flag_enum -> enum_flags [index ].string );
467+ }
468+
469+ return OPAL_SUCCESS ;
470+ }
471+
472+ static int enum_value_from_string_flag (mca_base_var_enum_t * self , const char * string_value , int * value_out ) {
473+ mca_base_var_enum_flag_t * flag_enum = (mca_base_var_enum_flag_t * ) self ;
474+ int value , count , ret , flag ;
475+ char * * flags ;
476+ bool is_int ;
477+ char * tmp ;
478+
479+ ret = self -> get_count (self , & count );
480+ if (OPAL_SUCCESS != ret ) {
481+ return ret ;
482+ }
483+
484+ flags = opal_argv_split (string_value , ',' );
485+ if (NULL == flags ) {
486+ return OPAL_ERR_BAD_PARAM ;
487+ }
488+
489+ flag = 0 ;
490+
491+ for (int i = 0 ; flags [i ] ; ++ i ) {
492+ value = strtol (flags [i ], & tmp , 0 );
493+ is_int = tmp [0 ] == '\0' ;
494+
495+ bool found = false, conflict = false;
496+ for (int j = 0 ; j < count ; ++ j ) {
497+ if ((is_int && (value == flag_enum -> enum_flags [i ].flag )) ||
498+ 0 == strcasecmp (flags [i ], flag_enum -> enum_flags [i ].string )) {
499+ found = true;
500+
501+ if (flag & flag_enum -> enum_flags [i ].conflicting_flag ) {
502+ conflict = true;
503+ } else {
504+ flag |= flag_enum -> enum_flags [i ].flag ;
505+ }
506+
507+ break ;
508+ }
509+ }
510+
511+ if (!found || conflict ) {
512+ opal_argv_free (flags );
513+ return !found ? OPAL_ERR_VALUE_OUT_OF_BOUNDS : OPAL_ERR_BAD_PARAM ;
514+ }
515+ }
516+
517+ * value_out = flag ;
518+
519+ return OPAL_SUCCESS ;
520+ }
521+
522+ static int enum_string_from_value_flag (mca_base_var_enum_t * self , const int value , char * * string_value ) {
523+ mca_base_var_enum_flag_t * flag_enum = (mca_base_var_enum_flag_t * ) self ;
524+ int count , ret , current ;
525+ char * out = NULL , * tmp ;
526+
527+ ret = self -> get_count (self , & count );
528+ if (OPAL_SUCCESS != ret ) {
529+ return ret ;
530+ }
531+
532+ current = value ;
533+ for (int i = 0 ; i < count ; ++ i ) {
534+ if (!(flag_enum -> enum_flags [i ].flag & current )) {
535+ continue ;
536+ }
537+
538+ tmp = out ;
539+
540+ ret = asprintf (& out , "%s%s%s" , tmp ? tmp : "" , tmp ? "," : "" , flag_enum -> enum_flags [i ].string );
541+ free (tmp );
542+
543+ if (0 > ret ) {
544+ return OPAL_ERR_OUT_OF_RESOURCE ;
545+ }
546+
547+ if (value & flag_enum -> enum_flags [i ].conflicting_flag ) {
548+ free (out );
549+ return OPAL_ERR_BAD_PARAM ;
550+ }
551+
552+ current &= ~flag_enum -> enum_flags [i ].flag ;
553+ }
554+
555+ if (current ) {
556+ free (out );
557+ return OPAL_ERR_VALUE_OUT_OF_BOUNDS ;
558+ }
559+
560+ if (string_value ) {
561+ * string_value = out ? out : strdup ("" );
562+ } else {
563+ free (out );
564+ }
565+
566+ return OPAL_SUCCESS ;
567+ }
568+
569+ static int enum_dump_flag (mca_base_var_enum_t * self , char * * out )
570+ {
571+ mca_base_var_enum_flag_t * flag_enum = (mca_base_var_enum_flag_t * ) self ;
572+ char * tmp ;
573+ int ret ;
574+
575+ * out = NULL ;
576+
577+ if (NULL == self ) {
578+ return OPAL_ERROR ;
579+ }
580+
581+ * out = strdup ("Comma-delimited list of: " );
582+ if (NULL == * out ) {
583+ return OPAL_ERR_OUT_OF_RESOURCE ;
584+ }
585+
586+ for (int i = 0 ; i < self -> enum_value_count ; ++ i ) {
587+ tmp = * out ;
588+
589+ ret = asprintf (out , "%s%s0x%x:\"%s\"" , tmp , i ? ", " : " " , flag_enum -> enum_flags [i ].flag ,
590+ flag_enum -> enum_flags [i ].string );
591+ free (tmp );
592+ if (0 > ret ) {
593+ return OPAL_ERR_OUT_OF_RESOURCE ;
594+ }
595+ }
596+
597+ return OPAL_SUCCESS ;
598+ }
599+
600+ static void mca_base_var_enum_flag_constructor (mca_base_var_enum_flag_t * enumerator )
601+ {
602+ enumerator -> enum_flags = NULL ;
603+ enumerator -> super .get_value = enum_get_value_flag ;
604+ enumerator -> super .get_count = enum_get_count ;
605+ enumerator -> super .value_from_string = enum_value_from_string_flag ;
606+ enumerator -> super .string_from_value = enum_string_from_value_flag ;
607+ enumerator -> super .dump = enum_dump_flag ;
608+ enumerator -> super .enum_is_static = false;
609+ }
610+
611+ static void mca_base_var_enum_flag_destructor (mca_base_var_enum_flag_t * enumerator )
612+ {
613+ /* release the copy of the values */
614+ if (enumerator -> enum_flags ) {
615+ for (int i = 0 ; i < enumerator -> super .enum_value_count ; ++ i ) {
616+ free ((void * ) enumerator -> enum_flags [i ].string );
617+ }
618+ free (enumerator -> enum_flags );
619+ }
620+ }
0 commit comments