[GRASS-dev] using G_parser() --script in the wild

Glynn Clements glynn at gclements.plus.com
Tue Feb 27 14:46:29 EST 2007


Hamish wrote:

> WRT d.path bug #302, d.path from GIS.m runs without a backdrop map.
>  http://wald.intevation.org/tracker/index.php?func=detail&aid=302
> 
> 
> After coding a solution in the d.path C code using D_get_dig_list() to
> check if the target map was already drawn, and if not draw it by closing
> the driver, running G_system(d.vect), and then opening the driver again,
> I decided that that solution was fragile and not so good.
> 
> So I decided to to it with a wrapper shell script instead using the new
> --script parser option. (see attached)
> 
> 
> Problem:
> the template script calls g.parser (which resets "$@" command line
> options to "@ARGS_PARSED@") before I can get my hands on it, and I'd
> rather not have to code all the command line options by hand.
> 
> Can we add a line in G_script() before the g.parser call like:
> 
> GRASS_CL_OPTS="$@"
> 
> if [ "$1" != "@ARGS_PARSED@" ] ; then
>   exec g.parser "$0" "$@"
> fi

If you want such a line, add it to the resulting script manually. The
--script option is meant to create an initial "draft", not a complete
script.

Note that the assignment would have to be performed when the script is
initially run, not when it is invoked by g.parser (otherwise
$GRASS_CL_OPTS would also be equal to @ARGS_PARSED@). It would have to
be exported, so that its value is present when the script is invoked
by g.parser.

Also, note that such a solution is fragile; it won't work if any of
the arguments contain spaces (or possibly other shell metacharacters). 
Essentially, there's no way to mimic the behaviour of "$@". If you
enclose a variable substitution in quotes, it will be treated as a
single word; if you don't use quotes, it will be split at each space
character. There's no way to make a copy of the argument list such
that you can split it back into words at the original boundaries, in
the way that "$@" works.

Ultimately, if you want to pass a list of strings between processes,
you have to find some way to encode that list as a single string, and
to decode it back into a list.

> Portability: currently I have it creating a temp file and then making
> it executable with chmod.

Ah. So you're writing a script which uses --script to create another
script which it then executes? That isn't the intended purpose of
--script. And it's potentially fragile; e.g. will it work if the
script is on a partition mounted with the "noexec" option (which may
well be the case for any partition to which you have write
permission)?.

I suggest simply writing a d.path.sh script which runs d.vect followed
by d.path, using the output from "d.path --script" as a template.

Writing the d.path command isn't *that* much work:

	if [ "$GIS_FLAG_G" = "1" ] ; then
	    gflag=-g
	else
	    gflag=
	fi

	if [ "$GIS_OPT_AFCOL" = "" ] ; then
	    afcol=
	else
	    afcol="afcol=$GIS_OPT_AFCOL"
	fi

	if [ "$GIS_OPT_ABCOL" = "" ] ; then
	    abcol=
	else
	    abcol="abcol=$GIS_OPT_ABCOL"
	fi

	if [ "$GIS_OPT_NCOL" = "" ] ; then
	    ncol=
	else
	    ncol="ncol=$GIS_OPT_NCOL"
	fi

	exec d.path $gflag $afcol $abcol $ncol \
		"map=$GIS_OPT_MAP" \
		"type=$GIS_OPT_TYPE" \
		"alayer=$GIS_OPT_ALAYER" \
		"nlayer=$GIS_OPT_NLAYER" \
		"color=$GIS_OPT_COLOR" \
		"hcolor=$GIS_OPT_HCOLOR" \
		"bgcolor=$GIS_OPT_BGCOLOR"

Hmm. I'm wondering whether it would be feasible to make G_parser() set
opt->answer = NULL if the value is an empty string (although that's
problematic if any module allows an empty string to be used where it
isn't the default value). Or provide some other mechanism for passing
NULL as an option value.

Most modules could be written to treat an empty string the same as
null, but re-writing modules involves a lot of work, and having to
remember to catch this case is error-prone.

-- 
Glynn Clements <glynn at gclements.plus.com>




More information about the grass-dev mailing list