@@ -75,6 +75,7 @@ static void _show_help(void) {
7575 pizza_io_printf ("{cyan} sort Sort tests by specified criteria{reset}\n" );
7676 pizza_io_printf ("{cyan} shuffle Shuffle tests with optional parameters{reset}\n" );
7777 pizza_io_printf ("{cyan} color=<mode> Set color mode (enable, disable, auto){reset}\n" );
78+ pizza_io_printf ("{cyan} config=<file> Specify a configuration file (must be pizza_test.ini){reset}\n" );
7879 pizza_io_printf ("{cyan} theme=<name> Set the theme (fossil, catch, doctest, etc.){reset}\n" );
7980 pizza_io_printf ("{cyan} verbose=<level> Set verbosity level (plain, ci, doge){reset}\n" );
8081 exit (EXIT_SUCCESS );
@@ -320,6 +321,19 @@ fossil_pizza_pallet_t fossil_pizza_pallet_create(int argc, char** argv) {
320321 if (i + 1 < argc && pizza_io_cstr_compare (argv [i + 1 ], "--help" ) == 0 ) {
321322 _show_subhelp_color ();
322323 }
324+ } else if (strncmp (argv [i ], "config=" , 7 ) == 0 ) {
325+ const char * config_file = argv [i ] + 7 ;
326+ if (pizza_io_cstr_compare (config_file , "pizza_test.ini" ) == 0 ) {
327+ pallet .config_file = config_file ;
328+ } else {
329+ pizza_io_printf ("{red}Error: Invalid configuration file name. Must be 'pizza_test.ini'.{reset}\n" );
330+ exit (EXIT_FAILURE );
331+ }
332+ } else if (pizza_io_cstr_compare (argv [i ], "config" ) == 0 ) {
333+ if (i + 1 < argc && pizza_io_cstr_compare (argv [i + 1 ], "--help" ) == 0 ) {
334+ _show_help ();
335+ }
336+
323337 } else if (strncmp (argv [i ], "theme=" , 6 ) == 0 ) {
324338 const char * theme_str = argv [i ] + 6 ;
325339 if (pizza_io_cstr_compare (theme_str , "fossil" ) == 0 ) {
@@ -371,6 +385,161 @@ fossil_pizza_pallet_t fossil_pizza_pallet_create(int argc, char** argv) {
371385 return pallet ;
372386}
373387
388+ // *****************************************************************************
389+ // INI Parser
390+ // *****************************************************************************
391+
392+ int fossil_pizza_ini_parse (const char * filename , fossil_pizza_pallet_t * pallet ) {
393+ if (pizza_io_cstr_compare (filename , "pizza_test.ini" ) != 0 ) {
394+ fprintf (stderr , "Error: INI file must be named 'pizza_test.ini'.\n" );
395+ return -1 ;
396+ }
397+
398+ FILE * file = fopen (filename , "r" );
399+ if (!file ) {
400+ fprintf (stderr , "Error: Unable to open INI file: %s\n" , filename );
401+ return -1 ;
402+ }
403+
404+ char line [256 ];
405+ char section [64 ] = "" ;
406+ while (fgets (line , sizeof (line ), file )) {
407+ // Trim whitespace
408+ char * start = line ;
409+ while (isspace ((unsigned char )* start )) start ++ ;
410+ char * end = start + strlen (start ) - 1 ;
411+ while (end > start && isspace ((unsigned char )* end )) * end -- = '\0' ;
412+
413+ // Skip comments and empty lines
414+ if (* start == ';' || * start == '#' || * start == '\0' ) continue ;
415+
416+ // Handle section headers
417+ if (* start == '[' ) {
418+ char * close = strchr (start , ']' );
419+ if (close ) {
420+ * close = '\0' ;
421+ strncpy (section , start + 1 , sizeof (section ) - 1 );
422+ section [sizeof (section ) - 1 ] = '\0' ;
423+ }
424+ continue ;
425+ }
426+
427+ // Handle key-value pairs
428+ char * equals = strchr (start , '=' );
429+ if (equals ) {
430+ * equals = '\0' ;
431+ char * key = start ;
432+ char * value = equals + 1 ;
433+
434+ // Trim whitespace around key and value
435+ while (isspace ((unsigned char )* key )) key ++ ;
436+ end = key + strlen (key ) - 1 ;
437+ while (end > key && isspace ((unsigned char )* end )) * end -- = '\0' ;
438+
439+ while (isspace ((unsigned char )* value )) value ++ ;
440+ end = value + strlen (value ) - 1 ;
441+ while (end > value && isspace ((unsigned char )* end )) * end -- = '\0' ;
442+
443+ // Handle inline comments
444+ char * comment = strchr (value , ';' );
445+ if (!comment ) comment = strchr (value , '#' );
446+ if (comment ) * comment = '\0' ;
447+
448+ // Trim whitespace again after removing comments
449+ end = value + strlen (value ) - 1 ;
450+ while (end > value && isspace ((unsigned char )* end )) * end -- = '\0' ;
451+
452+ // Populate the pallet structure based on the section and key
453+ if (pizza_io_cstr_compare (section , "general" ) == 0 ) {
454+ if (pizza_io_cstr_compare (key , "theme" ) == 0 ) {
455+ if (pizza_io_cstr_compare (value , "fossil" ) == 0 ) {
456+ pallet -> theme = PIZZA_THEME_FOSSIL ;
457+ } else if (pizza_io_cstr_compare (value , "catch" ) == 0 ) {
458+ pallet -> theme = PIZZA_THEME_CATCH ;
459+ } else if (pizza_io_cstr_compare (value , "doctest" ) == 0 ) {
460+ pallet -> theme = PIZZA_THEME_DOCTEST ;
461+ } else if (pizza_io_cstr_compare (value , "cpputest" ) == 0 ) {
462+ pallet -> theme = PIZZA_THEME_CPPUTEST ;
463+ } else if (pizza_io_cstr_compare (value , "tap" ) == 0 ) {
464+ pallet -> theme = PIZZA_THEME_TAP ;
465+ } else if (pizza_io_cstr_compare (value , "gtest" ) == 0 ) {
466+ pallet -> theme = PIZZA_THEME_GOOGLETEST ;
467+ } else if (pizza_io_cstr_compare (value , "unity" ) == 0 ) {
468+ pallet -> theme = PIZZA_THEME_UNITY ;
469+ }
470+ } else if (pizza_io_cstr_compare (key , "verbose" ) == 0 ) {
471+ if (pizza_io_cstr_compare (value , "plain" ) == 0 ) {
472+ pallet -> verbose = PIZZA_VERBOSE_PLAIN ;
473+ } else if (pizza_io_cstr_compare (value , "ci" ) == 0 ) {
474+ pallet -> verbose = PIZZA_VERBOSE_CI ;
475+ } else if (pizza_io_cstr_compare (value , "doge" ) == 0 ) {
476+ pallet -> verbose = PIZZA_VERBOSE_DOGE ;
477+ }
478+ }
479+ } else if (pizza_io_cstr_compare (section , "test" ) == 0 ) {
480+ if (pizza_io_cstr_compare (key , "run.fail_fast" ) == 0 ) {
481+ pallet -> run .fail_fast = atoi (value );
482+ } else if (pizza_io_cstr_compare (key , "run.only" ) == 0 ) {
483+ pallet -> run .only = pizza_io_cstr_dup (value );
484+ } else if (pizza_io_cstr_compare (key , "run.repeat" ) == 0 ) {
485+ pallet -> run .repeat = atoi (value );
486+ } else if (pizza_io_cstr_compare (key , "filter.test_name" ) == 0 ) {
487+ pallet -> filter .test_name = pizza_io_cstr_dup (value );
488+ } else if (pizza_io_cstr_compare (key , "filter.suite_name" ) == 0 ) {
489+ pallet -> filter .suite_name = pizza_io_cstr_dup (value );
490+ } else if (pizza_io_cstr_compare (key , "filter.tag" ) == 0 ) {
491+ int is_valid_tag = 0 ;
492+ for (int i = 0 ; VALID_TAGS [i ] != null ; i ++ ) {
493+ if (pizza_io_cstr_compare (value , VALID_TAGS [i ]) == 0 ) {
494+ is_valid_tag = 1 ;
495+ break ;
496+ }
497+ }
498+ if (is_valid_tag ) {
499+ pallet -> filter .tag = pizza_io_cstr_dup (value );
500+ } else {
501+ fprintf (stderr , "Error: Invalid tag '%s'.\n" , value );
502+ fclose (file );
503+ return -1 ;
504+ }
505+ } else if (pizza_io_cstr_compare (key , "sort.by" ) == 0 ) {
506+ int is_valid_criteria = 0 ;
507+ for (int i = 0 ; VALID_CRITERIA [i ] != null ; i ++ ) {
508+ if (pizza_io_cstr_compare (value , VALID_CRITERIA [i ]) == 0 ) {
509+ is_valid_criteria = 1 ;
510+ break ;
511+ }
512+ }
513+ if (is_valid_criteria ) {
514+ pallet -> sort .by = pizza_io_cstr_dup (value );
515+ } else {
516+ fprintf (stderr , "Error: Invalid sort criteria '%s'.\n" , value );
517+ fclose (file );
518+ return -1 ;
519+ }
520+ } else if (pizza_io_cstr_compare (key , "sort.order" ) == 0 ) {
521+ pallet -> sort .order = pizza_io_cstr_dup (value );
522+ } else if (pizza_io_cstr_compare (key , "shuffle.seed" ) == 0 ) {
523+ pallet -> shuffle .seed = pizza_io_cstr_dup (value );
524+ } else if (pizza_io_cstr_compare (key , "shuffle.count" ) == 0 ) {
525+ pallet -> shuffle .count = atoi (value );
526+ } else if (pizza_io_cstr_compare (key , "shuffle.by" ) == 0 ) {
527+ pallet -> shuffle .by = pizza_io_cstr_dup (value );
528+ }
529+ } else if (pizza_io_cstr_compare (section , "mock" ) == 0 ) {
530+ // Add mock-related parsing logic here
531+ } else if (pizza_io_cstr_compare (section , "mark" ) == 0 ) {
532+ // Add mark-related parsing logic here
533+ } else if (pizza_io_cstr_compare (section , "sanity" ) == 0 ) {
534+ // Add sanity-related parsing logic here
535+ }
536+ }
537+ }
538+
539+ fclose (file );
540+ return 0 ;
541+ }
542+
374543// *****************************************************************************
375544// Host information
376545// *****************************************************************************
0 commit comments