tools

various tools
git clone git://deadbeef.fr/tools.git
Log | Files | Refs | README | LICENSE

optparser.cpp (3512B)


      1 // Copyright (c) 2020 Morel BĂ©renger
      2 // 
      3 // This software is provided 'as-is', without any express or implied
      4 // warranty. In no event will the authors be held liable for any damages
      5 // arising from the use of this software.
      6 // 
      7 // Permission is granted to anyone to use this software for any purpose,
      8 // including commercial applications, and to alter it and redistribute it
      9 // freely, subject to the following restrictions:
     10 // 
     11 // 1. The origin of this software must not be misrepresented; you must not
     12 //    claim that you wrote the original software. If you use this software
     13 //    in a product, an acknowledgment in the product documentation would be
     14 //    appreciated but is not required.
     15 // 2. Altered source versions must be plainly marked as such, and must not be
     16 //    misrepresented as being the original software.
     17 // 3. This notice may not be removed or altered from any source distribution.
     18 
     19 // option parser: implementation
     20 
     21 #include <string.h>
     22 #include <assert.h>
     23 #include <stdlib.h>
     24 #include <stdio.h>
     25 #include <stdint.h>
     26 #include <errno.h>
     27 #include <limits.h>
     28 
     29 #include "optparser.hpp"
     30 #include "utils.hpp"
     31 
     32 // those strings must be defined in same order than the enum
     33 // Trick: use vim's block insertion to check them
     34 char const *parse_error_msgs[] =
     35 {
     36 	/*NONE       */"no error",
     37 	/*IGNORED    */"not an option",
     38 	/*MAX_COUNT  */"count overflow",
     39 	/*SET_NO_VAL */"this option needs a value",
     40 	/*SET_VAL_IGN*/"this option does not needs a value",
     41 	/*SET_FAIL   */"failed to parse the value",
     42 	/*BAD_ARGS   */"application bug: bad arguments to call",
     43 	/*BAD_SETTER */"application bug: bad values in option",
     44 };
     45 
     46 parse_error_t parse_cmd_opt( char * arg, opt_desc_t* start, opt_desc_t const* end )
     47 {
     48 	BUG_CHECK( !( arg && start && end && end > start ), BAD_ARGS );
     49 
     50 	if( arg[0] != '-' || arg[1] == 0 )
     51 	{
     52 		return IGNORED;
     53 	}
     54 
     55 	opt_desc_t* opt = start;
     56 	char* argv = arg + 2;
     57 
     58 	//search for option (stores in opt)
     59 	if( arg[1] == '-' ) //long
     60 	{
     61 		char* name = argv;
     62 		size_t name_sz;
     63 		argv = strchr( name, '=' );
     64 		if( argv )
     65 		{
     66 			assert( argv > name );
     67 			name_sz = static_cast<size_t>( argv - name );
     68 			++argv;
     69 		}
     70 		else
     71 		{
     72 			name_sz = strlen( name );
     73 		}
     74 
     75 		for( ; true
     76 				&& opt != end
     77 				&& 0 != strncmp( name, opt->option, name_sz )
     78 				&& name_sz != strlen( opt->option ); ++opt )
     79 		{
     80 		}
     81 	}
     82 	else //short
     83 	{
     84 		uint32_t name = static_cast<uint8_t>( arg[1] );
     85 		if( name & 0x80 )
     86 		{
     87 			assert( !( name & 0x80 ) && "TODO: utf-8 support" );
     88 			abort();
     89 		}
     90 		for( ; opt != end && opt->short_option != name; ++opt )
     91 		{
     92 		}
     93 	}
     94 
     95 	//BUG_CHECK( ( opt->set && !opt->value ) || ( !opt->set && opt->value ), BAD_SETTER );
     96 
     97 	if( opt == end )
     98 	{
     99 		return IGNORED;
    100 	}
    101 
    102 	if( opt->value && empty_array( argv ) )
    103 	{
    104 		return SET_NO_VAL;
    105 	}
    106 
    107 	if( !opt->value && !empty_array( argv ) )
    108 	{
    109 		return SET_VAL_IGN;
    110 	}
    111 
    112 	if( opt->set && opt->set( opt->value, argv ) )
    113 	{
    114 		return SET_FAIL;
    115 	}
    116 
    117 	if( opt->count < UINT32_MAX )
    118 	{
    119 		++opt->count;
    120 	}
    121 	return opt->count == UINT32_MAX ? MAX_COUNT : NONE;
    122 }
    123 
    124 void print_opts( FILE_PTR target, opt_desc_t const* start, opt_desc_t const* end )
    125 {
    126 	char short_name[] = ",-????";
    127 	for( ; start != end; ++start )
    128 	{
    129 		memcpy( short_name + 2, &start->short_option, sizeof( start->short_option ) );
    130 		fprintf( target, "\t* --%s%s: %s",
    131 				start->option,
    132 				start->short_option ? short_name : "",
    133 				start->description
    134 				);
    135 		//fail to show current val
    136 		if( start->show && start->show( start->value, target ) )
    137 		{
    138 			abort();
    139 		}
    140 		fputc( '\n', target );
    141 	}
    142 }