1/* Parse arguments from a string and prepend them to an argv.
2
3   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2, or (at your option)
8   any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18   02111-1307, USA.  */
19
20/* Written by Paul Eggert <eggert@twinsun.com>.  */
21
22#ifdef HAVE_CONFIG_H
23# include <config.h>
24#endif
25#include "prepargs.h"
26#include <string.h>
27#include <sys/types.h>
28#include <xalloc.h>
29
30#include <ctype.h>
31
32/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
33   as an argument to <ctype.h> macros like "isspace".  */
34#ifdef STDC_HEADERS
35# define IN_CTYPE_DOMAIN(c) 1
36#else
37# define IN_CTYPE_DOMAIN(c) ((c) <= 0177)
38#endif
39
40#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
41
42/* Find the white-space-separated options specified by OPTIONS, and
43   using BUF to store copies of these options, set ARGV[0], ARGV[1],
44   etc. to the option copies.  Return the number N of options found.
45   Do not set ARGV[N].  If ARGV is zero, do not store ARGV[0] etc.
46   Backslash can be used to escape whitespace (and backslashes).  */
47static int
48prepend_args (char const *options, char *buf, char **argv)
49{
50  char const *o = options;
51  char *b = buf;
52  int n = 0;
53
54  for (;;)
55    {
56      while (ISSPACE ((unsigned char) *o))
57	o++;
58      if (!*o)
59	return n;
60      if (argv)
61	argv[n] = b;
62      n++;
63
64      do
65	if ((*b++ = *o++) == '\\' && *o)
66	  b[-1] = *o++;
67      while (*o && ! ISSPACE ((unsigned char) *o));
68
69      *b++ = '\0';
70    }
71}
72
73/* Prepend the whitespace-separated options in OPTIONS to the argument
74   vector of a main program with argument count *PARGC and argument
75   vector *PARGV.  */
76void
77prepend_default_options (char const *options, int *pargc, char ***pargv)
78{
79  if (options)
80    {
81      char *buf = xmalloc (strlen (options) + 1);
82      int prepended = prepend_args (options, buf, (char **) 0);
83      int argc = *pargc;
84      char * const *argv = *pargv;
85      char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
86      *pargc = prepended + argc;
87      *pargv = pp;
88      *pp++ = *argv++;
89      pp += prepend_args (options, buf, pp);
90      while ((*pp++ = *argv++))
91	continue;
92    }
93}
94