]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/less/lessecho.c
Merge llvm-project main llvmorg-15-init-17485-ga3e38b4a206b
[FreeBSD/FreeBSD.git] / contrib / less / lessecho.c
1 /*
2  * Copyright (C) 1984-2022  Mark Nudelman
3  *
4  * You may distribute under the terms of either the GNU General Public
5  * License or the Less License, as specified in the README file.
6  *
7  * For more information, see the README file.
8  */
9
10
11 /*
12  * lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ...
13  * Simply echos its filename arguments on standard output.
14  * But any argument containing spaces is enclosed in quotes.
15  *
16  * -ox  Specifies "x" to be the open quote character.
17  * -cx  Specifies "x" to be the close quote character.
18  * -pn  Specifies "n" to be the open quote character, as an integer.
19  * -dn  Specifies "n" to be the close quote character, as an integer.
20  * -mx  Specifies "x" to be a metachar.
21  * -nn  Specifies "n" to be a metachar, as an integer.
22  * -ex  Specifies "x" to be the escape char for metachars.
23  * -fn  Specifies "x" to be the escape char for metachars, as an integer.
24  * -a   Specifies that all arguments are to be quoted.
25  *      The default is that only arguments containing spaces are quoted.
26  */
27
28 #include "less.h"
29
30 static char *version = "$Revision: 1.15 $";
31
32 static int quote_all = 0;
33 static char openquote = '"';
34 static char closequote = '"';
35 static char *meta_escape = "\\";
36 static char meta_escape_buf[2];
37 static char* metachars = NULL;
38 static int num_metachars = 0;
39 static int size_metachars = 0;
40
41         static void
42 pr_usage(VOID_PARAM)
43 {
44         fprintf(stderr,
45                 "usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
46 }
47
48         static void
49 pr_version(VOID_PARAM)
50 {
51         char *p;
52         char buf[10];
53         char *pbuf = buf;
54
55         for (p = version;  *p != ' ';  p++)
56                 if (*p == '\0')
57                         return;
58         for (p++;  *p != '$' && *p != ' ' && *p != '\0';  p++)
59                 *pbuf++ = *p;
60         *pbuf = '\0';
61         printf("%s\n", buf);
62 }
63
64         static void
65 pr_error(s)
66         char *s;
67 {
68         fprintf(stderr, "%s\n", s);
69         exit(1);
70 }
71
72         static long
73 lstrtol(s, radix, pend)
74         char *s;
75         int radix;
76         char **pend;
77 {
78         int v;
79         int neg = 0;
80         long n = 0;
81
82         /* Skip leading white space. */
83         while (*s == ' ' || *s == '\t')
84                 s++;
85
86         /* Check for a leading + or -. */
87         if (*s == '-')
88         {
89                 neg = 1;
90                 s++;
91         } else if (*s == '+')
92         {
93                 s++;
94         }
95
96         /* Determine radix if caller does not specify. */
97         if (radix == 0)
98         {
99                 radix = 10;
100                 if (*s == '0')
101                 {
102                         switch (*++s)
103                         {
104                         case 'x':
105                                 radix = 16;
106                                 s++;
107                                 break;
108                         default:
109                                 radix = 8;
110                                 break;
111                         }
112                 }
113         }
114
115         /* Parse the digits of the number. */
116         for (;;)
117         {
118                 if (*s >= '0' && *s <= '9')
119                         v = *s - '0';
120                 else if (*s >= 'a' && *s <= 'f')
121                         v = *s - 'a' + 10;
122                 else if (*s >= 'A' && *s <= 'F')
123                         v = *s - 'A' + 10;
124                 else
125                         break;
126                 if (v >= radix)
127                         break;
128                 n = n * radix + v;
129                 s++;
130         }
131
132         if (pend != NULL)
133         {
134                 /* Skip trailing white space. */
135                 while (*s == ' ' || *s == '\t')
136                         s++;
137                 *pend = s;
138         }
139         if (neg)
140                 return (-n);
141         return (n);
142 }
143
144         static void
145 add_metachar(ch)
146         int ch;
147 {
148         if (num_metachars+1 >= size_metachars)
149         {
150                 char *p;
151                 size_metachars = (size_metachars > 0) ? size_metachars*2 : 16;
152                 p = (char *) malloc(size_metachars);
153                 if (p == NULL)
154                         pr_error("Cannot allocate memory");
155
156                 if (metachars != NULL)
157                 {
158                         strcpy(p, metachars);
159                         free(metachars);
160                 }
161                 metachars = p;
162         }
163         metachars[num_metachars++] = ch;
164         metachars[num_metachars] = '\0';
165 }
166
167         static int
168 is_metachar(ch)
169         int ch;
170 {
171         return (metachars != NULL && strchr(metachars, ch) != NULL);
172 }
173
174 #if !HAVE_STRCHR
175         char *
176 strchr(s, c)
177         char *s;
178         int c;
179 {
180         for ( ;  *s != '\0';  s++)
181                 if (*s == c)
182                         return (s);
183         if (c == '\0')
184                 return (s);
185         return (NULL);
186 }
187 #endif
188
189         int
190 main(argc, argv)
191         int argc;
192         char *argv[];
193 {
194         char *arg;
195         char *s;
196         int no_more_options;
197
198         no_more_options = 0;
199         while (--argc > 0)
200         {
201                 arg = *++argv;
202                 if (*arg != '-' || no_more_options)
203                         break;
204                 switch (*++arg)
205                 {
206                 case 'a':
207                         quote_all = 1;
208                         break;
209                 case 'c':
210                         closequote = *++arg;
211                         break;
212                 case 'd':
213                         closequote = lstrtol(++arg, 0, &s);
214                         if (s == arg)
215                                 pr_error("Missing number after -d");
216                         break;
217                 case 'e':
218                         if (strcmp(++arg, "-") == 0)
219                                 meta_escape = "";
220                         else
221                                 meta_escape = arg;
222                         break;
223                 case 'f':
224                         meta_escape_buf[0] = lstrtol(++arg, 0, &s);
225                         meta_escape_buf[1] = '\0';
226                         meta_escape = meta_escape_buf;
227                         if (s == arg)
228                                 pr_error("Missing number after -f");
229                         break;
230                 case 'o':
231                         openquote = *++arg;
232                         break;
233                 case 'p':
234                         openquote = lstrtol(++arg, 0, &s);
235                         if (s == arg)
236                                 pr_error("Missing number after -p");
237                         break;
238                 case 'm':
239                         add_metachar(*++arg);
240                         break;
241                 case 'n':
242                         add_metachar(lstrtol(++arg, 0, &s));
243                         if (s == arg)
244                                 pr_error("Missing number after -n");
245                         break;
246                 case '?':
247                         pr_usage();
248                         return (0);
249                 case '-':
250                         if (*++arg == '\0')
251                         {
252                                 no_more_options = 1;
253                                 break;
254                         }
255                         if (strcmp(arg, "version") == 0)
256                         {
257                                 pr_version();
258                                 return (0);
259                         }
260                         if (strcmp(arg, "help") == 0)
261                         {
262                                 pr_usage();
263                                 return (0);
264                         }
265                         pr_error("Invalid option after --");
266                 default:
267                         pr_error("Invalid option letter");
268                 }
269         }
270
271         while (argc-- > 0)
272         {
273                 int has_meta = 0;
274                 arg = *argv++;
275                 for (s = arg;  *s != '\0';  s++)
276                 {
277                         if (is_metachar(*s))
278                         {
279                                 has_meta = 1;
280                                 break;
281                         }
282                 }
283                 if (quote_all || (has_meta && strlen(meta_escape) == 0))
284                         printf("%c%s%c", openquote, arg, closequote);
285                 else 
286                 {
287                         for (s = arg;  *s != '\0';  s++)
288                         {
289                                 if (is_metachar(*s))
290                                         printf("%s", meta_escape);
291                                 printf("%c", *s);
292                         }
293                 }
294                 if (argc > 0)
295                         printf(" ");
296                 else
297                         printf("\n");
298         }
299         return (0);
300 }