118fd37a7SXin LI /* Parse arguments from a string and prepend them to an argv.
218fd37a7SXin LI
318fd37a7SXin LI Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
418fd37a7SXin LI
518fd37a7SXin LI This program is free software; you can redistribute it and/or modify
618fd37a7SXin LI it under the terms of the GNU General Public License as published by
718fd37a7SXin LI the Free Software Foundation; either version 2, or (at your option)
818fd37a7SXin LI any later version.
918fd37a7SXin LI
1018fd37a7SXin LI This program is distributed in the hope that it will be useful,
1118fd37a7SXin LI but WITHOUT ANY WARRANTY; without even the implied warranty of
1218fd37a7SXin LI MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1318fd37a7SXin LI GNU General Public License for more details.
1418fd37a7SXin LI
1518fd37a7SXin LI You should have received a copy of the GNU General Public License
1618fd37a7SXin LI along with this program; if not, write to the Free Software
1718fd37a7SXin LI Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1818fd37a7SXin LI 02111-1307, USA. */
1918fd37a7SXin LI
2018fd37a7SXin LI /* Written by Paul Eggert <eggert@twinsun.com>. */
2118fd37a7SXin LI
2218fd37a7SXin LI #ifdef HAVE_CONFIG_H
2318fd37a7SXin LI # include <config.h>
2418fd37a7SXin LI #endif
2518fd37a7SXin LI #include "prepargs.h"
2618fd37a7SXin LI #include <string.h>
2718fd37a7SXin LI #include <sys/types.h>
2818fd37a7SXin LI #include <xalloc.h>
2918fd37a7SXin LI
3018fd37a7SXin LI #include <ctype.h>
3118fd37a7SXin LI
3218fd37a7SXin LI /* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
3318fd37a7SXin LI as an argument to <ctype.h> macros like "isspace". */
3418fd37a7SXin LI #ifdef STDC_HEADERS
3518fd37a7SXin LI # define IN_CTYPE_DOMAIN(c) 1
3618fd37a7SXin LI #else
3718fd37a7SXin LI # define IN_CTYPE_DOMAIN(c) ((c) <= 0177)
3818fd37a7SXin LI #endif
3918fd37a7SXin LI
4018fd37a7SXin LI #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
4118fd37a7SXin LI
4218fd37a7SXin LI /* Find the white-space-separated options specified by OPTIONS, and
4318fd37a7SXin LI using BUF to store copies of these options, set ARGV[0], ARGV[1],
4418fd37a7SXin LI etc. to the option copies. Return the number N of options found.
4518fd37a7SXin LI Do not set ARGV[N]. If ARGV is zero, do not store ARGV[0] etc.
4618fd37a7SXin LI Backslash can be used to escape whitespace (and backslashes). */
4718fd37a7SXin LI static int
prepend_args(char const * options,char * buf,char ** argv)4818fd37a7SXin LI prepend_args (char const *options, char *buf, char **argv)
4918fd37a7SXin LI {
5018fd37a7SXin LI char const *o = options;
5118fd37a7SXin LI char *b = buf;
5218fd37a7SXin LI int n = 0;
5318fd37a7SXin LI
5418fd37a7SXin LI for (;;)
5518fd37a7SXin LI {
5618fd37a7SXin LI while (ISSPACE ((unsigned char) *o))
5718fd37a7SXin LI o++;
5818fd37a7SXin LI if (!*o)
5918fd37a7SXin LI return n;
6018fd37a7SXin LI if (argv)
6118fd37a7SXin LI argv[n] = b;
6218fd37a7SXin LI n++;
6318fd37a7SXin LI
6418fd37a7SXin LI do
6518fd37a7SXin LI if ((*b++ = *o++) == '\\' && *o)
6618fd37a7SXin LI b[-1] = *o++;
6718fd37a7SXin LI while (*o && ! ISSPACE ((unsigned char) *o));
6818fd37a7SXin LI
6918fd37a7SXin LI *b++ = '\0';
7018fd37a7SXin LI }
7118fd37a7SXin LI }
7218fd37a7SXin LI
7318fd37a7SXin LI /* Prepend the whitespace-separated options in OPTIONS to the argument
7418fd37a7SXin LI vector of a main program with argument count *PARGC and argument
7518fd37a7SXin LI vector *PARGV. */
7618fd37a7SXin LI void
prepend_default_options(char const * options,int * pargc,char *** pargv)7718fd37a7SXin LI prepend_default_options (char const *options, int *pargc, char ***pargv)
7818fd37a7SXin LI {
7918fd37a7SXin LI if (options)
8018fd37a7SXin LI {
8118fd37a7SXin LI char *buf = xmalloc (strlen (options) + 1);
8218fd37a7SXin LI int prepended = prepend_args (options, buf, (char **) 0);
8318fd37a7SXin LI int argc = *pargc;
8418fd37a7SXin LI char * const *argv = *pargv;
8518fd37a7SXin LI char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
8618fd37a7SXin LI *pargc = prepended + argc;
8718fd37a7SXin LI *pargv = pp;
8818fd37a7SXin LI *pp++ = *argv++;
8918fd37a7SXin LI pp += prepend_args (options, buf, pp);
9018fd37a7SXin LI while ((*pp++ = *argv++))
9118fd37a7SXin LI continue;
9218fd37a7SXin LI }
9318fd37a7SXin LI }
94