@@ -245,12 +245,21 @@ void show_usage(const char *command_name, const fossil_io_parser_palette_t *pale
245245 case FOSSIL_IO_PARSER_INT :
246246 fossil_io_printf ("{cyan}<int>{reset}" );
247247 break ;
248+ case FOSSIL_IO_PARSER_UINT :
249+ fossil_io_printf ("{cyan}<uint>{reset}" );
250+ break ;
248251 case FOSSIL_IO_PARSER_BOOL :
249252 fossil_io_printf ("{cyan}<true/false>{reset}" );
250253 break ;
251254 case FOSSIL_IO_PARSER_FLOAT :
252255 fossil_io_printf ("{cyan}<float>{reset}" );
253256 break ;
257+ case FOSSIL_IO_PARSER_HEX :
258+ fossil_io_printf ("{cyan}<0xHEX>{reset}" );
259+ break ;
260+ case FOSSIL_IO_PARSER_OCT :
261+ fossil_io_printf ("{cyan}<0OCT>{reset}" );
262+ break ;
254263 case FOSSIL_IO_PARSER_DATE :
255264 fossil_io_printf ("{cyan}<YYYY-MM-DD>{reset}" );
256265 break ;
@@ -310,7 +319,7 @@ fossil_io_parser_palette_t *fossil_io_parser_create_palette(const char *name, co
310319 return palette ;
311320}
312321
313- fossil_io_parser_command_t * fossil_io_parser_add_command (fossil_io_parser_palette_t * palette , const char * command_name , const char * description ) {
322+ fossil_io_parser_command_t * fossil_io_parser_add_command (fossil_io_parser_palette_t * palette , const char * command_name , const char * short_name , const char * description ) {
314323 if (!palette || !command_name || !description ) {
315324 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Palette, command name, and description cannot be NULL.{reset}\n" );
316325 return NULL ;
@@ -321,13 +330,17 @@ fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palett
321330 return NULL ;
322331 }
323332
324- // Check for duplicate command name
333+ // Check for duplicate command name or short name
325334 fossil_io_parser_command_t * current = palette -> commands ;
326335 while (current ) {
327336 if (strcmp (current -> name , command_name ) == 0 ) {
328337 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Command with name '%s' already exists.{reset}\n" , command_name );
329338 return NULL ;
330339 }
340+ if (short_name && current -> short_name && strcmp (current -> short_name , short_name ) == 0 ) {
341+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Command with short name '%s' already exists.{reset}\n" , short_name );
342+ return NULL ;
343+ }
331344 current = current -> next ;
332345 }
333346
@@ -336,8 +349,10 @@ fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palett
336349 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for command.{reset}\n" );
337350 return NULL ;
338351 }
352+
339353 // Initialize all fields to zero/NULL
340354 command -> name = NULL ;
355+ command -> short_name = NULL ;
341356 command -> description = NULL ;
342357 command -> arguments = NULL ;
343358 command -> prev = NULL ;
@@ -350,10 +365,21 @@ fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palett
350365 return NULL ;
351366 }
352367
368+ if (short_name ) {
369+ command -> short_name = _custom_strdup (short_name );
370+ if (!command -> short_name ) {
371+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for command short name.{reset}\n" );
372+ free (command -> name );
373+ free (command );
374+ return NULL ;
375+ }
376+ }
377+
353378 command -> description = _custom_strdup (description );
354379 if (!command -> description ) {
355380 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for command description.{reset}\n" );
356381 free (command -> name );
382+ if (command -> short_name ) free (command -> short_name );
357383 free (command );
358384 return NULL ;
359385 }
@@ -368,31 +394,71 @@ fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palett
368394 return command ;
369395}
370396
371- fossil_io_parser_argument_t * fossil_io_parser_add_argument (fossil_io_parser_command_t * command , const char * arg_name , fossil_io_parser_arg_type_t arg_type , char * * combo_options , int combo_count ) {
397+ fossil_io_parser_argument_t * fossil_io_parser_add_argument (fossil_io_parser_command_t * command , const char * arg_name , const char * short_name , fossil_io_parser_arg_type_t arg_type , char * * combo_options , int combo_count ) {
372398 if (!command || !arg_name ) {
373399 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Command and argument name cannot be NULL.{reset}\n" );
374400 return NULL ;
375401 }
376402
403+ if (strlen (arg_name ) == 0 ) {
404+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Argument name cannot be empty.{reset}\n" );
405+ return NULL ;
406+ }
407+
408+ // Check for duplicate argument name or short name
409+ fossil_io_parser_argument_t * current = command -> arguments ;
410+ while (current ) {
411+ if (strcmp (current -> name , arg_name ) == 0 ) {
412+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Argument with name '%s' already exists.{reset}\n" , arg_name );
413+ return NULL ;
414+ }
415+ if (short_name && current -> short_name && strcmp (current -> short_name , short_name ) == 0 ) {
416+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Argument with short name '%s' already exists.{reset}\n" , short_name );
417+ return NULL ;
418+ }
419+ current = current -> next ;
420+ }
421+
377422 fossil_io_parser_argument_t * argument = malloc (sizeof (fossil_io_parser_argument_t ));
378423 if (!argument ) {
379424 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for argument.{reset}\n" );
380425 return NULL ;
381426 }
382427
428+ // Initialize all fields to zero/NULL
429+ argument -> name = NULL ;
430+ argument -> short_name = NULL ;
431+ argument -> type = FOSSIL_IO_PARSER_BOOL ;
432+ argument -> value = NULL ;
433+ argument -> combo_options = NULL ;
434+ argument -> combo_count = 0 ;
435+ argument -> next = NULL ;
436+
383437 argument -> name = _custom_strdup (arg_name );
384438 if (!argument -> name ) {
385439 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for argument name.{reset}\n" );
386440 free (argument );
387441 return NULL ;
388442 }
389443
390- if (arg_type < FOSSIL_IO_PARSER_BOOL || arg_type > FOSSIL_IO_PARSER_FEATURE ) {
444+ if (short_name ) {
445+ argument -> short_name = _custom_strdup (short_name );
446+ if (!argument -> short_name ) {
447+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for argument short name.{reset}\n" );
448+ free (argument -> name );
449+ free (argument );
450+ return NULL ;
451+ }
452+ }
453+
454+ if (arg_type < FOSSIL_IO_PARSER_BOOL || arg_type >= FOSSIL_IO_PARSER_INVALID ) {
391455 fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Invalid argument type for '%s'.{reset}\n" , arg_name );
392456 free (argument -> name );
457+ if (argument -> short_name ) free (argument -> short_name );
393458 free (argument );
394459 return NULL ;
395460 }
461+
396462 argument -> type = arg_type ;
397463 argument -> value = NULL ;
398464 argument -> combo_options = combo_options ;
@@ -576,6 +642,18 @@ void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char
576642 fossil_io_fprintf (FOSSIL_STDERR , "{red}Missing value for integer argument: %s{reset}\n" , arg_value );
577643 }
578644 break ;
645+ case FOSSIL_IO_PARSER_UINT :
646+ if (i + 1 < argc ) {
647+ argument -> value = malloc (sizeof (unsigned int ));
648+ if (!argument -> value ) {
649+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for unsigned integer argument.{reset}\n" );
650+ return ;
651+ }
652+ * (unsigned int * )argument -> value = (unsigned int )atol (argv [++ i ]);
653+ } else {
654+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Missing value for unsigned integer argument: %s{reset}\n" , arg_value );
655+ }
656+ break ;
579657 case FOSSIL_IO_PARSER_FLOAT :
580658 if (i + 1 < argc ) {
581659 argument -> value = malloc (sizeof (float ));
@@ -588,6 +666,30 @@ void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char
588666 fossil_io_fprintf (FOSSIL_STDERR , "{red}Missing value for float argument: %s{reset}\n" , arg_value );
589667 }
590668 break ;
669+ case FOSSIL_IO_PARSER_HEX :
670+ if (i + 1 < argc ) {
671+ argument -> value = malloc (sizeof (unsigned int ));
672+ if (!argument -> value ) {
673+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for hex argument.{reset}\n" );
674+ return ;
675+ }
676+ * (unsigned int * )argument -> value = (unsigned int )strtol (argv [++ i ], NULL , 16 );
677+ } else {
678+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Missing value for hex argument: %s{reset}\n" , arg_value );
679+ }
680+ break ;
681+ case FOSSIL_IO_PARSER_OCT :
682+ if (i + 1 < argc ) {
683+ argument -> value = malloc (sizeof (unsigned int ));
684+ if (!argument -> value ) {
685+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Error: Memory allocation failed for octal argument.{reset}\n" );
686+ return ;
687+ }
688+ * (unsigned int * )argument -> value = (unsigned int )strtol (argv [++ i ], NULL , 8 );
689+ } else {
690+ fossil_io_fprintf (FOSSIL_STDERR , "{red}Missing value for octal argument: %s{reset}\n" , arg_value );
691+ }
692+ break ;
591693 case FOSSIL_IO_PARSER_DATE :
592694 if (i + 1 < argc ) {
593695 argument -> value = _custom_strdup (argv [++ i ]);
@@ -670,21 +772,47 @@ void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char
670772}
671773
672774void fossil_io_parser_free (fossil_io_parser_palette_t * palette ) {
775+ if (!palette ) return ;
776+
673777 fossil_io_parser_command_t * command = palette -> commands ;
674778 while (command ) {
779+ fossil_io_parser_command_t * next_command = command -> next ;
780+
781+ // Free all arguments for this command
675782 fossil_io_parser_argument_t * argument = command -> arguments ;
676783 while (argument ) {
677- free (argument -> name );
678- if (argument -> value && argument -> value != (char * )argument -> combo_options ) {
784+ fossil_io_parser_argument_t * next_argument = argument -> next ;
785+
786+ if (argument -> name ) free (argument -> name );
787+ if (argument -> short_name ) free (argument -> short_name );
788+
789+ // Handle different value types
790+ if (argument -> value ) {
791+ if (argument -> type == FOSSIL_IO_PARSER_ARRAY ) {
792+ // For arrays, we need to free each string in the array
793+ char * * array_values = (char * * )argument -> value ;
794+ if (array_values ) {
795+ for (int i = 0 ; array_values [i ] != NULL ; i ++ ) {
796+ free (array_values [i ]);
797+ }
798+ }
799+ }
679800 free (argument -> value );
680801 }
681- argument = argument -> next ;
802+
803+ free (argument );
804+ argument = next_argument ;
682805 }
683- free (command -> name );
684- free (command -> description );
685- command = command -> next ;
806+
807+ if (command -> name ) free (command -> name );
808+ if (command -> short_name ) free (command -> short_name );
809+ if (command -> description ) free (command -> description );
810+
811+ free (command );
812+ command = next_command ;
686813 }
687- free (palette -> name );
688- free (palette -> description );
814+
815+ if (palette -> name ) free (palette -> name );
816+ if (palette -> description ) free (palette -> description );
689817 free (palette );
690818}
0 commit comments