Browse Source

Deal with newlines in option values (issue https://trac.osgeo.org/grass/ticket/2139)

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@58339 15284696-431f-4ddb-bdfa-cd5b030d7da7
Glynn Clements 11 years ago
parent
commit
031e5a5fce

+ 8 - 2
general/g.parser/g.parser.html

@@ -22,6 +22,8 @@
 <dd>Print strings for translation</dd>
 <dd>Print strings for translation</dd>
 <dt><b>-s</b></dt>
 <dt><b>-s</b></dt>
 <dd>Write option values to stdout instead of reinvoking script</dd>
 <dd>Write option values to stdout instead of reinvoking script</dd>
+<dt><b>-n</b></dt>
+<dd>Write option values to stdout separated by nulls</dd>
 </dl>
 </dl>
 
 
 <h2>DESCRIPTION</h2>
 <h2>DESCRIPTION</h2>
@@ -34,7 +36,7 @@ script can very quickly be made into a full-fledged GRASS module.
 
 
 <h2>OPTIONS</h2>
 <h2>OPTIONS</h2>
 
 
-Unless the <b>-s</b> switch is used, the arguments are stored in
+Unless the <b>-s</b> or <b>-n</b> switch is used, the arguments are stored in
 environment variables for use in your scripts. These variables are
 environment variables for use in your scripts. These variables are
 named "GIS_FLAG_&lt;NAME&gt;" for flags and "GIS_OPT_&lt;NAME&gt;" for
 named "GIS_FLAG_&lt;NAME&gt;" for flags and "GIS_OPT_&lt;NAME&gt;" for
 options. The names of variables are converted to upper case. For
 options. The names of variables are converted to upper case. For
@@ -47,7 +49,7 @@ and the value of flag with key <b>f</b> will be available in variable
 For flags, the value will be "1" if the flag was given, and "0" otherwise.
 For flags, the value will be "1" if the flag was given, and "0" otherwise.
 
 
 <p>
 <p>
-If the <b>-s</b> switch is used, the options and flags are written to
+If the <b>-s</b> or <b>-n</b> switch is used, the options and flags are written to
 stdout in the form <em>opt_&lt;name&gt;=&lt;value&gt;</em> and
 stdout in the form <em>opt_&lt;name&gt;=&lt;value&gt;</em> and
 <em>flag_&lt;name&gt;=&lt;value&gt;</em>, preceded by the string
 <em>flag_&lt;name&gt;=&lt;value&gt;</em>, preceded by the string
 <b>@ARGS_PARSED@</b>. If this string doesn't appear as the first line
 <b>@ARGS_PARSED@</b>. If this string doesn't appear as the first line
@@ -56,6 +58,10 @@ as <b>--html-description</b>. In this case, the data written by
 <em>g.parser</em> to stdout should be copied to the script's stdout
 <em>g.parser</em> to stdout should be copied to the script's stdout
 verbatim.
 verbatim.
 
 
+If the <b>-s</b> switch is used, the options and flags are separated
+by newlines. If the <b>-n</b> switch is used, the options and flags
+are separated by null characters.
+
 <p>
 <p>
 Typical header definitions are as follows:
 Typical header definitions are as follows:
 
 

+ 11 - 3
general/g.parser/main.c

@@ -32,6 +32,7 @@ int main(int argc, char *argv[])
     struct context ctx;
     struct context ctx;
     const char *filename;
     const char *filename;
     int standard_output;
     int standard_output;
+    int separator_nul;
     
     
     ctx.module = NULL;
     ctx.module = NULL;
     ctx.option = NULL;
     ctx.option = NULL;
@@ -40,8 +41,8 @@ int main(int argc, char *argv[])
     ctx.first_flag = NULL;
     ctx.first_flag = NULL;
     ctx.state = S_TOPLEVEL;
     ctx.state = S_TOPLEVEL;
 
 
-    standard_output = translate_output = FALSE;
-    
+    standard_output = translate_output = separator_nul = FALSE;
+
     /* Detect request to get strings to translate from a file */
     /* Detect request to get strings to translate from a file */
     /* It comes BEFORE the filename to completely avoid confusion with parser.c behaviours */
     /* It comes BEFORE the filename to completely avoid confusion with parser.c behaviours */
     if (argc >= 2 && (strcmp(argv[1], "-t") == 0)) {
     if (argc >= 2 && (strcmp(argv[1], "-t") == 0)) {
@@ -56,6 +57,13 @@ int main(int argc, char *argv[])
 	argv++, argc--;
 	argv++, argc--;
     }
     }
 
 
+    if (argc >= 2 && (strcmp(argv[1], "-n") == 0)) {
+	/* write to stdout with NUL as separator */
+	standard_output = TRUE;
+	separator_nul = TRUE;
+	argv++, argc--;
+    }
+
     if ((argc < 2) || ((strcmp(argv[1], "help") == 0) ||
     if ((argc < 2) || ((strcmp(argv[1], "help") == 0) ||
 		       (strcmp(argv[1], "-help") == 0) ||
 		       (strcmp(argv[1], "-help") == 0) ||
 		       (strcmp(argv[1], "--help") == 0))) {
 		       (strcmp(argv[1], "--help") == 0))) {
@@ -135,6 +143,6 @@ int main(int argc, char *argv[])
 	exit(EXIT_FAILURE);
 	exit(EXIT_FAILURE);
 
 
     return standard_output
     return standard_output
-	? print_options(&ctx)
+	? print_options(&ctx, separator_nul ? '\0' : '\n')
 	: reinvoke_script(&ctx, filename);
 	: reinvoke_script(&ctx, filename);
 }
 }

+ 9 - 7
general/g.parser/parse.c

@@ -228,27 +228,29 @@ void parse_option(struct context *ctx, const char *cmd, const char *arg)
 	    cmd, ctx->line);
 	    cmd, ctx->line);
 }
 }
 
 
-int print_options(const struct context *ctx)
+int print_options(const struct context *ctx, int sep)
 {
 {
     struct Option *option;
     struct Option *option;
     struct Flag *flag;
     struct Flag *flag;
     const char *overwrite = getenv("GRASS_OVERWRITE");
     const char *overwrite = getenv("GRASS_OVERWRITE");
     const char *verbose = getenv("GRASS_VERBOSE");
     const char *verbose = getenv("GRASS_VERBOSE");
 
 
-    printf("@ARGS_PARSED@\n");
+    printf("@ARGS_PARSED@%c", sep);
 
 
     if (overwrite)
     if (overwrite)
-	printf("GRASS_OVERWRITE=%s\n", overwrite);
+	printf("GRASS_OVERWRITE=%s%c", overwrite, sep);
 
 
     if (verbose)
     if (verbose)
-	printf("GRASS_VERBOSE=%s\n", verbose);
+	printf("GRASS_VERBOSE=%s%c", verbose, sep);
 
 
     for (flag = ctx->first_flag; flag; flag = flag->next_flag)
     for (flag = ctx->first_flag; flag; flag = flag->next_flag)
-	printf("flag_%c=%d\n", flag->key, flag->answer ? 1 : 0);
+	printf("flag_%c=%d%c", flag->key, flag->answer ? 1 : 0, sep);
 
 
     for (option = ctx->first_option; option; option = option->next_opt)
     for (option = ctx->first_option; option; option = option->next_opt)
-	printf("opt_%s=%s\n", option->key,
-	       option->answer ? option->answer : "");
+	printf("opt_%s=%s%c", option->key,
+	       option->answer ? option->answer : "", sep);
+
+    fflush(stdout);
 
 
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
 }
 }

+ 1 - 1
general/g.parser/proto.h

@@ -7,7 +7,7 @@ void parse_module(struct context *, const char *, const char *);
 void parse_flag(struct context *, const char *, const char *);
 void parse_flag(struct context *, const char *, const char *);
 int parse_type(struct context *, const char *);
 int parse_type(struct context *, const char *);
 void parse_option(struct context *, const char *, const char *);
 void parse_option(struct context *, const char *, const char *);
-int print_options(const struct context *);
+int print_options(const struct context *, int);
 
 
 /* revoke.c */
 /* revoke.c */
 int reinvoke_script(const struct context *, const char *);
 int reinvoke_script(const struct context *, const char *);

+ 3 - 4
lib/python/script/core.py

@@ -595,7 +595,6 @@ def _parse_opts(lines):
     options = {}
     options = {}
     flags = {}
     flags = {}
     for line in lines:
     for line in lines:
-        line = line.rstrip('\r\n')
         if not line:
         if not line:
             break
             break
         try:
         try:
@@ -645,11 +644,11 @@ def parser():
         else:
         else:
             argv[0] = os.path.join(sys.path[0], name)
             argv[0] = os.path.join(sys.path[0], name)
 
 
-    p = Popen(['g.parser', '-s'] + argv, stdout=PIPE)
+    p = Popen(['g.parser', '-n'] + argv, stdout=PIPE)
     s = p.communicate()[0]
     s = p.communicate()[0]
-    lines = s.splitlines()
+    lines = s.split('\0')
 
 
-    if not lines or lines[0].rstrip('\r\n') != "@ARGS_PARSED@":
+    if not lines or lines[0] != "@ARGS_PARSED@":
         sys.stdout.write(s)
         sys.stdout.write(s)
         sys.exit(p.returncode)
         sys.exit(p.returncode)