xref: /freebsd/contrib/diff/lib/prepargs.c (revision 18fd37a72c3a7549d2d4f6c6ea00bdcd2bdaca01)
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