summaryrefslogtreecommitdiff
path: root/src/mcpp-options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mcpp-options.c')
-rw-r--r--src/mcpp-options.c365
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 );
+}