[m-rev.] for review: MERCURY_OPTIONS-progname

Paul Bone pbone at csse.unimelb.edu.au
Wed May 21 08:26:15 AEST 2008


On Tue, May 20, 2008 at 05:11:06PM +1000, Zoltan Somogyi wrote:
> MERCURY_OPTIONS is a crude way to give options to Mercury programs, since it
> applies to all Mercury programs, even though we often want to give options to
> only one specific Mercury program. (For example, we may want to give it only
> to a test program's executable, and not to the invocation of the compiler
> that generates it.) This diff makes the runtime system, when executing a
> program named "progname", look for and process the environment variable
> whose name is "MERCURY_OPTIONS-progname". This allows options to be given
> at runtime to only one specific program.
> 
> runtime/mercury_wrapper.c:
> 	Make the change described above.
> 
> runtime/mercury_wrapper.h:
> 	Fix some obsolete documentation, and add some up-to-date documentation.
> 
> doc/user_guide.texi:
> 	Document the change.
> 
> util/mkinit.c:
> 	Fix indentation.
> 
> Zoltan.
>
> Index: runtime/mercury_wrapper.c
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
> retrieving revision 1.188
> diff -u -b -r1.188 mercury_wrapper.c
> --- runtime/mercury_wrapper.c	18 Mar 2008 03:09:43 -0000	1.188
> +++ runtime/mercury_wrapper.c	20 May 2008 07:07:46 -0000
> @@ -987,28 +987,67 @@
>  }
>  
>  /*
> -** MR_process_environment_options() is a function to parse the MERCURY_OPTIONS
> -** environment variable.  
> +** MR_process_environment_options() is a function to parse the options put
> +** into MR_runtime_flags by mkinit, the MERCURY_OPTIONS environment variable,
> +** and the MERCURY_OPTIONS-progname environment variable.
>  */ 
>  
> +#define MERCURY_OPTIONS     "MERCURY_OPTIONS"
> +
>  static void
>  MR_process_environment_options(void)
>  {
> -    char    *env_options;
> +    char        *gen_env_options;
> +    char        *prog_env_options;
> +    char        *prog_env_option_name;
> +    int         prog_env_option_name_len;
> +    int         mercury_options_len;
> +    const char  *progname;
> +    const char  *s;
> +
> +    gen_env_options = getenv(MERCURY_OPTIONS);
> +    if (gen_env_options == NULL) {
> +        gen_env_options = (char *) "";
> +    }

Why use a cast here?

I beleive that "" is normaly const char *.  Can gen_env_options be made
const char *?

>  
> -    env_options = getenv("MERCURY_OPTIONS");
> -    if (env_options == NULL) {
> -        env_options = (char *) "";
> +    /* Find out the program's name, stripping off any directory names. */
> +    progname = MR_progname;
> +    for (s = progname; *s != '\0'; s++) {
> +        if (*s == '/') {
> +            progname = s + 1;
>      }
> +    }
> +
> +    /* Build the program-specific option's name: MERCURY_OPTIONS-progname. */
> +    mercury_options_len = strlen(MERCURY_OPTIONS);
> +    prog_env_option_name_len = mercury_options_len + 1 + strlen(progname);
> +    prog_env_option_name = MR_GC_NEW_ARRAY(char, prog_env_option_name_len);
> +    strcpy(prog_env_option_name, MERCURY_OPTIONS);
> +    prog_env_option_name[mercury_options_len] = '-';
> +    strcpy(prog_env_option_name + mercury_options_len + 1, progname);
>  
> -    if (env_options[0] != '\0' || MR_runtime_flags[0] != '\0') {
> -        const char  *cmd;
> -        char        *arg_str, **argv;
> +    prog_env_options = getenv(prog_env_option_name);
> +    if (prog_env_options == NULL) {
> +        prog_env_options = (char *) "";
> +    }

And here.

> @@ -1016,28 +1055,92 @@
>          ** at the start of the options before passing them to MR_make_argv()
>          ** and then to getopt().
>          */
> -        cmd = "mercury_runtime ";
> -        cmd_len = strlen(cmd);
> +
> +        dummy_cmd = "mercury_runtime";
> +        dummy_cmd_len = strlen(dummy_cmd);
>          runtime_flags_len = strlen(MR_runtime_flags);
> -        dummy_command_line = MR_GC_NEW_ARRAY(char,
> -            cmd_len + runtime_flags_len + 1 + strlen(env_options) + 1);
> -        strcpy(dummy_command_line, cmd);
> -        strcpy(dummy_command_line + cmd_len, MR_runtime_flags);
> -        dummy_command_line[cmd_len + runtime_flags_len] = ' ';
> -        strcpy(dummy_command_line + cmd_len + runtime_flags_len + 1,
> -            env_options);
> +        gen_env_options_len = strlen(gen_env_options);
> +        prog_env_options_len = strlen(prog_env_options);
> +        dummy_command_line_len =
> +            dummy_cmd_len + 1 +
> +            runtime_flags_len + 1 +
> +            gen_env_options_len + 1 +
> +            prog_env_options_len + 1;
> +        dummy_command_line = MR_GC_NEW_ARRAY(char, dummy_command_line_len);
> +
> +        next_slot = 0;
> +
> +        strcpy(dummy_command_line + next_slot, dummy_cmd);
> +        next_slot += dummy_cmd_len;
> +        dummy_command_line[next_slot] = ' ';
> +        next_slot += 1;
> +        strcpy(dummy_command_line + next_slot, MR_runtime_flags);
> +        next_slot += runtime_flags_len;
> +        dummy_command_line[next_slot] = ' ';
> +        next_slot += 1;
> +        strcpy(dummy_command_line + next_slot, gen_env_options);
> +        next_slot += gen_env_options_len;
> +        dummy_command_line[next_slot] = ' ';
> +        next_slot += 1;
> +        strcpy(dummy_command_line + next_slot, prog_env_options);
> +        next_slot += prog_env_options_len;
> +        dummy_command_line[next_slot] = '\0';
> +        next_slot += 1;
> +
> +        /* Sanity check. */
> +        if (next_slot != dummy_command_line_len) {
> +            MR_fatal_error("next_slot != dummy_command_line_len");
> +        }
> +
> +#ifdef MR_DEBUG_ARGUMENT_HANDLING
> +        /* Enable this is if you need to debug this code. */
> +        printf("progname = <%s>\n", progname);
> +        printf("MR_runtime_flags = <%s>\n", MR_runtime_flags);
> +        printf("gen_env_options = <%s>\n", gen_env_options);
> +        printf("prog_env_options = <%s>\n", prog_env_options);
> +        printf("dummy_command_line = <%s>\n", dummy_command_line);
> +#endif
>          
> -        error_msg = MR_make_argv(dummy_command_line, &arg_str, &argv, &argc);
> +        error_msg = MR_make_argv(dummy_command_line, &option_arg_str,
> +            &option_argv, &option_argc);
>          if (error_msg != NULL) {
> -            MR_fatal_error("error parsing the MERCURY_OPTIONS "
> -                "environment variable:\n%s\n", error_msg);
> +            char    *where_buf;
> +            int     where_buf_next;
> +
> +            where_buf = MR_GC_NEW_ARRAY(char, 1000);
> +            where_buf[0] = '\0';
> +            where_buf_next = strlen(where_buf);
> +
> +            if (gen_env_options[0] != '\0') {
> +                sprintf(where_buf + where_buf_next,
> +                    "%sthe %s environment variable",
> +                    where_buf_next == 0 ? "" : " and/or ",
> +                    MERCURY_OPTIONS);
> +                where_buf_next = strlen(where_buf);

This could crash when supplied with a large-enough invalid command line
option.  snprintf will not overflow the buffer.

>          }
> -        MR_GC_free(dummy_command_line);
>  
> -        MR_process_options(argc, argv);
> +            if (prog_env_options[0] != '\0') {
> +                sprintf(where_buf + where_buf_next,
> +                    "%sthe %s environment variable",
> +                    where_buf_next == 0 ? "" : " and/or ",
> +                    prog_env_option_name);
> +                where_buf_next = strlen(where_buf);
> +            }
>  
> -        MR_GC_free(arg_str);
> -        MR_GC_free(argv);
> +            if (MR_runtime_flags[0] != '\0') {
> +                sprintf(where_buf + where_buf_next,
> +                    "%sthe runtime options built into the executable",
> +                    where_buf_next == 0 ? "" : " and/or ");
> +                where_buf_next = strlen(where_buf);
> +            }
> +
> +            MR_fatal_error("error parsing %s:\n%s\n", where_buf, error_msg);
> +        }
> +
> +        MR_GC_free(dummy_command_line);
> +        MR_process_options(option_argc, option_argv);
> +        MR_GC_free(option_arg_str);
> +        MR_GC_free(option_argv);
>      }
>  }
>  

Everything else looks good to me.


--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list