lessecho.c revision 225736
1/*
2 * Copyright (C) 1984-2011  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 about less, or for information on how to
8 * contact the author, see the README file.
9 */
10
11
12/*
13 * lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ...
14 * Simply echos its filename arguments on standard output.
15 * But any argument containing spaces is enclosed in quotes.
16 *
17 * -ox	Specifies "x" to be the open quote character.
18 * -cx	Specifies "x" to be the close quote character.
19 * -pn	Specifies "n" to be the open quote character, as an integer.
20 * -dn	Specifies "n" to be the close quote character, as an integer.
21 * -mx  Specifies "x" to be a metachar.
22 * -nn  Specifies "n" to be a metachar, as an integer.
23 * -ex  Specifies "x" to be the escape char for metachars.
24 * -fn  Specifies "x" to be the escape char for metachars, as an integer.
25 * -a	Specifies that all arguments are to be quoted.
26 *	The default is that only arguments containing spaces are quoted.
27 */
28
29#include "less.h"
30
31static char *version = "$Revision: 1.14 $";
32
33static int quote_all = 0;
34static char openquote = '"';
35static char closequote = '"';
36static char *meta_escape = "\\";
37static char meta_escape_buf[2];
38static char metachars[64] = "";
39static int num_metachars = 0;
40
41	static void
42pr_usage()
43{
44	fprintf(stderr,
45		"usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
46}
47
48	static void
49pr_version()
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
65pr_error(s)
66	char *s;
67{
68	fprintf(stderr, "%s\n", s);
69	exit(1);
70}
71
72	static long
73lstrtol(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
145#if !HAVE_STRCHR
146	char *
147strchr(s, c)
148	char *s;
149	int c;
150{
151	for ( ;  *s != '\0';  s++)
152		if (*s == c)
153			return (s);
154	if (c == '\0')
155		return (s);
156	return (NULL);
157}
158#endif
159
160	int
161main(argc, argv)
162	int argc;
163	char *argv[];
164{
165	char *arg;
166	char *s;
167	int no_more_options;
168
169	no_more_options = 0;
170	while (--argc > 0)
171	{
172		arg = *++argv;
173		if (*arg != '-' || no_more_options)
174			break;
175		switch (*++arg)
176		{
177		case 'a':
178			quote_all = 1;
179			break;
180		case 'c':
181			closequote = *++arg;
182			break;
183		case 'd':
184			closequote = lstrtol(++arg, 0, &s);
185			if (s == arg)
186				pr_error("Missing number after -d");
187			break;
188		case 'e':
189			if (strcmp(++arg, "-") == 0)
190				meta_escape = "";
191			else
192				meta_escape = arg;
193			break;
194		case 'f':
195			meta_escape_buf[0] = lstrtol(++arg, 0, &s);
196			meta_escape = meta_escape_buf;
197			if (s == arg)
198				pr_error("Missing number after -f");
199			break;
200		case 'o':
201			openquote = *++arg;
202			break;
203		case 'p':
204			openquote = lstrtol(++arg, 0, &s);
205			if (s == arg)
206				pr_error("Missing number after -p");
207			break;
208		case 'm':
209			metachars[num_metachars++] = *++arg;
210			metachars[num_metachars] = '\0';
211			break;
212		case 'n':
213			metachars[num_metachars++] = lstrtol(++arg, 0, &s);
214			if (s == arg)
215				pr_error("Missing number after -n");
216			metachars[num_metachars] = '\0';
217			break;
218		case '?':
219			pr_usage();
220			return (0);
221		case '-':
222			if (*++arg == '\0')
223			{
224				no_more_options = 1;
225				break;
226			}
227			if (strcmp(arg, "version") == 0)
228			{
229				pr_version();
230				return (0);
231			}
232			if (strcmp(arg, "help") == 0)
233			{
234				pr_usage();
235				return (0);
236			}
237			pr_error("Invalid option after --");
238		default:
239			pr_error("Invalid option letter");
240		}
241	}
242
243	while (argc-- > 0)
244	{
245		int has_meta = 0;
246		arg = *argv++;
247		for (s = arg;  *s != '\0';  s++)
248		{
249			if (strchr(metachars, *s) != NULL)
250			{
251				has_meta = 1;
252				break;
253			}
254		}
255		if (quote_all || (has_meta && strlen(meta_escape) == 0))
256			printf("%c%s%c", openquote, arg, closequote);
257		else
258		{
259			for (s = arg;  *s != '\0';  s++)
260			{
261				if (strchr(metachars, *s) != NULL)
262					printf("%s", meta_escape);
263				printf("%c", *s);
264			}
265		}
266		if (argc > 0)
267			printf(" ");
268		else
269			printf("\n");
270	}
271	return (0);
272}
273