xref: /freebsd/contrib/diff/lib/prepargs.c (revision f57be329fc1b1c9227029ea39166de2b9ab5df20)
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).  */
47  static int
48  prepend_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.  */
76  void
77  prepend_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