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