diff options
Diffstat (limited to 'src/mcpp-options.c')
| -rw-r--r-- | src/mcpp-options.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/src/mcpp-options.c b/src/mcpp-options.c new file mode 100644 index 0000000..62fafc6 --- /dev/null +++ b/src/mcpp-options.c @@ -0,0 +1,365 @@ +#include <defs.h> + +static const char * +option_argument( mcpp_options *opts, int argc, char **argv, int *i, + const char *attached, const char *option ) +{ + if( attached != NULL && *attached != 0 ) + return( attached ); + + if( *i + 1 >= argc ) + { + fprintf( stderr, "%s: argument missing after '%s'\n", + opts->progname, option ); + return( NULL ); + } + + ++*i; + return( argv[*i] ); +} + +static int +append_action( mcpp_options *opts, enum mcpp_option_action_kind kind, + const char *option, const char *argument ) +{ + if( opts->action_count >= opts->action_capacity ) + { + errno = EOVERFLOW; + return( -1 ); + } + + opts->actions[opts->action_count].kind = kind; + opts->actions[opts->action_count].option = option; + opts->actions[opts->action_count].argument = argument; + ++opts->action_count; + + return( 0 ); +} + +static int +set_filename( mcpp_options *opts, const char *name ) +{ + if( opts->in_fname == NULL ) + { + opts->in_fname = strcmp(name, "-") == 0 ? "" : name; + return( 0 ); + } + + if( opts->out_fname == NULL ) + { + opts->out_fname = strcmp(name, "-") == 0 ? "" : name; + return( 0 ); + } + + fprintf( stderr, "%s: too many filenames\n", opts->progname ); + return( -1 ); +} + +static int +parse_dump_option( mcpp_options *opts, const char *arg ) +{ + const char *p = arg + 2; + + if( *p == 0 ) + return( -1 ); + + while( *p ) + { + switch( *p++ ) + { + case 'M': + opts->dump_macros = MCPP_DUMP_ONLY; + opts->no_output = 1; + while( *p == 'P' ) + { + opts->dump_only_plus_predefined = 1; + ++p; + } + break; + case 'D': + opts->dump_macros = MCPP_DUMP_DEFINITIONS; + break; + default: + return( -1 ); + } + } + + return( 0 ); +} + +void +mcpp_options_init( mcpp_options *opts, int argc ) +{ + if( opts == NULL ) + return; + + memset( opts, 0, sizeof(*opts) ); + opts->progname = "mcpu-cpp"; + opts->object_suffix = ".o"; + opts->action_capacity = argc > 0 ? (size_t)argc * 2 : 2; + opts->actions = (mcpp_option_action *)calloc( opts->action_capacity, + sizeof(*opts->actions) ); +} + +void +mcpp_options_free( mcpp_options *opts ) +{ + if( opts == NULL ) + return; + + free( opts->actions ); + opts->actions = NULL; + opts->action_count = 0; + opts->action_capacity = 0; +} + +int +mcpp_handle_options( mcpp_options *opts, int argc, char **argv ) +{ + size_t j; + int i; + + if( opts == NULL || argv == NULL ) + { + errno = EINVAL; + return( -1 ); + } + + for( i = 0; i < argc; ++i ) + { + const char *arg = argv[i]; + const char *value; + + if( arg[0] != '-' || arg[1] == 0 ) + { + if( set_filename(opts, arg) != 0 ) return( -1 ); + continue; + } + + if( strcmp(arg, "--help") == 0 ) opts->help = 1; + else if( strcmp(arg, "--version") == 0 ) opts->version = 1; + else if( strcmp(arg, "--no-config") == 0 ) opts->no_config = 1; + else if( strcmp(arg, "--config-file") == 0 ) + { + value = option_argument(opts, argc, argv, &i, NULL, arg); + if( value == NULL ) return( -1 ); + opts->config_fname = value; + } + else if( strcmp(arg, "--object-suffix") == 0 ) + { + value = option_argument(opts, argc, argv, &i, NULL, arg); + if( value == NULL ) return( -1 ); + opts->object_suffix = value; + } + else if( strcmp(arg, "-dconfig") == 0 ) opts->dump_config = 1; + else if( strcmp(arg, "-dsearch-dirs") == 0 ) opts->dump_search_dirs = 1; + else if( arg[0] == '-' && arg[1] == 'd' && arg[2] != 0 ) + { + if( parse_dump_option(opts, arg) != 0 ) goto unknown; + } + else if( strcmp(arg, "-v") == 0 || strcmp(arg, "--verbose") == 0 ) opts->verbose = 1; + else if( strcmp(arg, "-nostdinc") == 0 ) opts->no_standard_includes = 1; + else if( strcmp(arg, "-nostdinc++") == 0 ) opts->no_standard_kplusplus_includes = 1; + else if( strcmp(arg, "-E") == 0 ) { } + else if( strcmp(arg, "-w") == 0 ) opts->inhibit_warnings = 1; + else if( strcmp(arg, "-Wcomment") == 0 || strcmp(arg, "-Wcomments") == 0 ) + { + opts->warn_comments = 1; + opts->warn_comments_explicit = 1; + } + else if( strcmp(arg, "-Wno-comment") == 0 || strcmp(arg, "-Wno-comments") == 0 ) + { + opts->warn_comments = 0; + opts->warn_comments_explicit = 1; + } + else if( strcmp(arg, "-Wall") == 0 ) + { + if( !opts->warn_comments_explicit ) + opts->warn_comments = 1; + } + else if( strcmp(arg, "-Werror") == 0 ) opts->warnings_are_errors = 1; + else if( strcmp(arg, "-Wno-error") == 0 ) opts->warnings_are_errors = 0; + else if( strcmp(arg, "-lint") == 0 ) opts->for_lint = 1; + else if( strcmp(arg, "-M") == 0 ) + { + opts->print_deps = 2; + opts->inhibit_output = 1; + } + else if( strcmp(arg, "-MM") == 0 ) + { + opts->print_deps = 1; + opts->inhibit_output = 1; + } + else if( strcmp(arg, "-MD") == 0 ) + { + opts->print_deps = 2; + opts->inhibit_output = 0; + } + else if( strcmp(arg, "-MMD") == 0 ) + { + opts->print_deps = 1; + opts->inhibit_output = 0; + } + else if( arg[0] == '-' && arg[1] == 'M' && arg[2] == 'F' ) + { + value = option_argument(opts, argc, argv, &i, arg + 3, "-MF"); + if( value == NULL ) return( -1 ); + opts->deps_file = value; + } + else if( arg[0] == '-' && arg[1] == 'M' && + (arg[2] == 'T' || arg[2] == 'Q') ) + { + enum mcpp_option_action_kind kind = arg[2] == 'T' ? + MCPP_ACTION_DEP_TARGET : MCPP_ACTION_DEP_TARGET_QUOTED; + const char *option = arg[2] == 'T' ? "-MT" : "-MQ"; + + value = option_argument(opts, argc, argv, &i, arg + 3, option); + if( value == NULL || append_action(opts, kind, option, value) != 0 ) + return( -1 ); + } + else if( strcmp(arg, "-MG") == 0 ) opts->print_deps_missing_files = 1; + else if( strcmp(arg, "-o") == 0 ) + { + if( opts->out_fname != NULL ) + { + fprintf(stderr, "%s: output filename specified twice\n", opts->progname); + return( -1 ); + } + value = option_argument(opts, argc, argv, &i, NULL, arg); + if( value == NULL ) return( -1 ); + opts->out_fname = strcmp(value, "-") == 0 ? "" : value; + } + else if( arg[1] == 'D' ) + { + value = option_argument(opts, argc, argv, &i, arg + 2, "-D"); + if( value == NULL || append_action(opts, MCPP_ACTION_DEFINE, "-D", value) != 0 ) return( -1 ); + } + else if( arg[1] == 'U' ) + { + value = option_argument(opts, argc, argv, &i, arg + 2, "-U"); + if( value == NULL || append_action(opts, MCPP_ACTION_UNDEF, "-U", value) != 0 ) return( -1 ); + } + else if( arg[1] == 'I' && arg[2] == '-' && arg[3] == 0 ) goto unknown; + else if( arg[1] == 'I' ) + { + value = option_argument(opts, argc, argv, &i, arg + 2, "-I"); + if( value == NULL || append_action(opts, MCPP_ACTION_INCLUDE_USER, "-I", value) != 0 ) return( -1 ); + } + else if( strcmp(arg, "-include") == 0 || strcmp(arg, "-imacros") == 0 || + strcmp(arg, "-isystem") == 0 || strcmp(arg, "-idirafter") == 0 ) + { + enum mcpp_option_action_kind kind = MCPP_ACTION_INCLUDE; + if( strcmp(arg, "-imacros") == 0 ) kind = MCPP_ACTION_IMACROS; + else if( strcmp(arg, "-isystem") == 0 ) kind = MCPP_ACTION_INCLUDE_SYSTEM; + else if( strcmp(arg, "-idirafter") == 0 ) kind = MCPP_ACTION_INCLUDE_AFTER; + value = option_argument(opts, argc, argv, &i, NULL, arg); + if( value == NULL || append_action(opts, kind, arg, value) != 0 ) return( -1 ); + } + else + { +unknown: + fprintf( stderr, "%s: unknown option '%s'\n", opts->progname, arg ); + return( -1 ); + } + } + + if( opts->in_fname == NULL ) opts->in_fname = ""; + if( opts->out_fname == NULL ) opts->out_fname = ""; + + if( opts->deps_file != NULL && opts->print_deps == 0 ) + { + fprintf( stderr, + "%s: -MF requires one of -M, -MM, -MD or -MMD\n", + opts->progname ); + return( -1 ); + } + + if( opts->print_deps == 0 ) + { + for( j = 0; j < opts->action_count; ++j ) + if( opts->actions[j].kind == MCPP_ACTION_DEP_TARGET || + opts->actions[j].kind == MCPP_ACTION_DEP_TARGET_QUOTED ) + { + fprintf( stderr, + "%s: -MT/-MQ require one of -M, -MM, -MD or -MMD\n", + opts->progname ); + return( -1 ); + } + } + + if( opts->print_deps_missing_files && + (opts->print_deps == 0 || !opts->inhibit_output) ) + { + fprintf( stderr, "%s: -MG may only be used with -M or -MM\n", + opts->progname ); + return( -1 ); + } + + return( 0 ); +} + +static const char * +action_name( enum mcpp_option_action_kind kind ) +{ + switch( kind ) + { + case MCPP_ACTION_DEFINE: return( "define" ); + case MCPP_ACTION_UNDEF: return( "undef" ); + case MCPP_ACTION_INCLUDE: return( "include" ); + case MCPP_ACTION_IMACROS: return( "imacros" ); + case MCPP_ACTION_INCLUDE_USER: return( "include-user" ); + case MCPP_ACTION_INCLUDE_SYSTEM: return( "include-system" ); + case MCPP_ACTION_INCLUDE_AFTER: return( "include-after" ); + case MCPP_ACTION_DEP_TARGET: return( "dep-target" ); + case MCPP_ACTION_DEP_TARGET_QUOTED: return( "dep-target-quoted" ); + } + return( "unknown" ); +} + +int +mcpp_options_dump( const mcpp_options *opts, FILE *stream ) +{ + size_t i; + + if( opts == NULL || stream == NULL ) return( -1 ); + + fprintf(stream, "input=%s\n", *opts->in_fname ? opts->in_fname : "<stdin>"); + fprintf(stream, "output=%s\n", *opts->out_fname ? opts->out_fname : "<stdout>"); + fprintf(stream, "verbose=%d\n", opts->verbose); + fprintf(stream, "nostdinc=%d\n", opts->no_standard_includes); + fprintf(stream, "dump_config=%d\n", opts->dump_config); + fprintf(stream, "dump_search_dirs=%d\n", opts->dump_search_dirs); + fprintf(stream, "dump_macros=%d\n", (int)opts->dump_macros); + fprintf(stream, "actions=%lu\n", (unsigned long)opts->action_count); + for( i = 0; i < opts->action_count; ++i ) + fprintf(stream, "action[%lu]=%s:%s\n", (unsigned long)i, + action_name(opts->actions[i].kind), opts->actions[i].argument); + return( 0 ); +} + +int +mcpp_options_has_unimplemented( const mcpp_options *opts ) +{ + size_t i; + if( opts == NULL ) return( 0 ); + if( opts->print_deps && opts->inhibit_output && + opts->dump_macros != MCPP_DUMP_NONE ) + return( 1 ); + if( opts->print_deps && !opts->inhibit_output && + opts->dump_macros == MCPP_DUMP_ONLY ) + return( 1 ); + if( opts->no_standard_kplusplus_includes || opts->for_lint ) + return( 1 ); + for( i = 0; i < opts->action_count; ++i ) + if( opts->actions[i].kind != MCPP_ACTION_DEFINE && + opts->actions[i].kind != MCPP_ACTION_UNDEF && + opts->actions[i].kind != MCPP_ACTION_INCLUDE && + opts->actions[i].kind != MCPP_ACTION_IMACROS && + opts->actions[i].kind != MCPP_ACTION_INCLUDE_USER && + opts->actions[i].kind != MCPP_ACTION_INCLUDE_SYSTEM && + opts->actions[i].kind != MCPP_ACTION_INCLUDE_AFTER && + opts->actions[i].kind != MCPP_ACTION_DEP_TARGET && + opts->actions[i].kind != MCPP_ACTION_DEP_TARGET_QUOTED ) + return( 1 ); + return( 0 ); +} |
