Merge from vendor branch GCC:
[dragonfly.git] / contrib / patch / quotearg.c
1 /* Shell command argument quoting.
2    Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; see the file COPYING.
16    If not, write to the Free Software Foundation,
17    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19 /* Written by Paul Eggert <eggert@twinsun.com> */
20
21 #if HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <sys/types.h>
26 #include <quotearg.h>
27
28 /* Place into QUOTED a quoted version of ARG suitable for `system'.
29    Return the length of the resulting string (which is not null-terminated).
30    If QUOTED is null, return the length without any side effects.  */
31
32 size_t
33 quote_system_arg (quoted, arg)
34      char *quoted;
35      char const *arg;
36 {
37   char const *a;
38   size_t len = 0;
39
40   /* Scan ARG, copying it to QUOTED if QUOTED is not null,
41      looking for shell metacharacters.  */
42
43   for (a = arg; ; a++)
44     {
45       char c = *a;
46       switch (c)
47         {
48         case 0:
49           /* ARG has no shell metacharacters.  */
50           return len;
51
52         case '=':
53           if (*arg == '-')
54             break;
55           /* Fall through.  */
56         case '\t': case '\n': case ' ':
57         case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
58         case '(': case ')': case '*': case ';':
59         case '<': case '>': case '?': case '[': case '\\':
60         case '^': case '`': case '|': case '~':
61           {
62             /* ARG has a shell metacharacter.
63                Start over, quoting it this time.  */
64
65             len = 0;
66             c = *arg++;
67
68             /* If ARG is an option, quote just its argument.
69                This is not necessary, but it looks nicer.  */
70             if (c == '-'  &&  arg < a)
71               {
72                 c = *arg++;
73
74                 if (quoted)
75                   {
76                     quoted[len] = '-';
77                     quoted[len + 1] = c;
78                   }
79                 len += 2;
80
81                 if (c == '-')
82                   while (arg < a)
83                     {
84                       c = *arg++;
85                       if (quoted)
86                         quoted[len] = c;
87                       len++;
88                       if (c == '=')
89                         break;
90                     }
91                 c = *arg++;
92               }
93
94             if (quoted)
95               quoted[len] = '\'';
96             len++;
97
98             for (;  c;  c = *arg++)
99               {
100                 if (c == '\'')
101                   {
102                     if (quoted)
103                       {
104                         quoted[len] = '\'';
105                         quoted[len + 1] = '\\';
106                         quoted[len + 2] = '\'';
107                       }
108                     len += 3;
109                   }
110                 if (quoted)
111                   quoted[len] = c;
112                 len++;
113               }
114
115             if (quoted)
116               quoted[len] = '\'';
117             return len + 1;
118           }
119         }
120
121       if (quoted)
122         quoted[len] = c;
123       len++;
124     }
125 }