1238730Sdelphij/*
2369759Sgit2svn * Copyright (C) 1984-2021  Mark Nudelman
3238730Sdelphij *
4238730Sdelphij * You may distribute under the terms of either the GNU General Public
5238730Sdelphij * License or the Less License, as specified in the README file.
6238730Sdelphij *
7238730Sdelphij * For more information, see the README file.
8238730Sdelphij */
960786Sps
1060786Sps
1160786Sps/*
1260786Sps * lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ...
1360786Sps * Simply echos its filename arguments on standard output.
1460786Sps * But any argument containing spaces is enclosed in quotes.
1560786Sps *
16369759Sgit2svn * -ox  Specifies "x" to be the open quote character.
17369759Sgit2svn * -cx  Specifies "x" to be the close quote character.
18369759Sgit2svn * -pn  Specifies "n" to be the open quote character, as an integer.
19369759Sgit2svn * -dn  Specifies "n" to be the close quote character, as an integer.
20128345Stjr * -mx  Specifies "x" to be a metachar.
21128345Stjr * -nn  Specifies "n" to be a metachar, as an integer.
22128345Stjr * -ex  Specifies "x" to be the escape char for metachars.
23128345Stjr * -fn  Specifies "x" to be the escape char for metachars, as an integer.
24369759Sgit2svn * -a   Specifies that all arguments are to be quoted.
25369759Sgit2svn *      The default is that only arguments containing spaces are quoted.
2660786Sps */
2760786Sps
2860786Sps#include "less.h"
2960786Sps
30237613Sdelphijstatic char *version = "$Revision: 1.15 $";
3160786Sps
3260786Spsstatic int quote_all = 0;
3360786Spsstatic char openquote = '"';
3460786Spsstatic char closequote = '"';
35128345Stjrstatic char *meta_escape = "\\";
36128345Stjrstatic char meta_escape_buf[2];
37128345Stjrstatic char metachars[64] = "";
38128345Stjrstatic int num_metachars = 0;
3960786Sps
4060786Sps	static void
41355504Sdelphijpr_usage(VOID_PARAM)
4260786Sps{
4360786Sps	fprintf(stderr,
44128345Stjr		"usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
4560786Sps}
4660786Sps
4760786Sps	static void
48355504Sdelphijpr_version(VOID_PARAM)
4960786Sps{
5060786Sps	char *p;
5160786Sps	char buf[10];
5260786Sps	char *pbuf = buf;
5360786Sps
5460786Sps	for (p = version;  *p != ' ';  p++)
5560786Sps		if (*p == '\0')
5660786Sps			return;
5760786Sps	for (p++;  *p != '$' && *p != ' ' && *p != '\0';  p++)
5860786Sps		*pbuf++ = *p;
5960786Sps	*pbuf = '\0';
6060786Sps	printf("%s\n", buf);
6160786Sps}
6260786Sps
6360786Sps	static void
6460786Spspr_error(s)
6560786Sps	char *s;
6660786Sps{
6760786Sps	fprintf(stderr, "%s\n", s);
6860786Sps	exit(1);
6960786Sps}
7060786Sps
7160786Sps	static long
7260786Spslstrtol(s, radix, pend)
7360786Sps	char *s;
7460786Sps	int radix;
7560786Sps	char **pend;
7660786Sps{
7760786Sps	int v;
7860786Sps	int neg = 0;
7960786Sps	long n = 0;
8060786Sps
8160786Sps	/* Skip leading white space. */
8260786Sps	while (*s == ' ' || *s == '\t')
8360786Sps		s++;
8460786Sps
8560786Sps	/* Check for a leading + or -. */
8660786Sps	if (*s == '-')
8760786Sps	{
8860786Sps		neg = 1;
8960786Sps		s++;
9060786Sps	} else if (*s == '+')
9160786Sps	{
9260786Sps		s++;
9360786Sps	}
9460786Sps
9560786Sps	/* Determine radix if caller does not specify. */
9660786Sps	if (radix == 0)
9760786Sps	{
9860786Sps		radix = 10;
9960786Sps		if (*s == '0')
10060786Sps		{
10160786Sps			switch (*++s)
10260786Sps			{
10360786Sps			case 'x':
10460786Sps				radix = 16;
10560786Sps				s++;
10660786Sps				break;
10760786Sps			default:
10860786Sps				radix = 8;
10960786Sps				break;
11060786Sps			}
11160786Sps		}
11260786Sps	}
11360786Sps
11460786Sps	/* Parse the digits of the number. */
11560786Sps	for (;;)
11660786Sps	{
11760786Sps		if (*s >= '0' && *s <= '9')
11860786Sps			v = *s - '0';
11960786Sps		else if (*s >= 'a' && *s <= 'f')
12060786Sps			v = *s - 'a' + 10;
12160786Sps		else if (*s >= 'A' && *s <= 'F')
12260786Sps			v = *s - 'A' + 10;
12360786Sps		else
12460786Sps			break;
12560786Sps		if (v >= radix)
12660786Sps			break;
12760786Sps		n = n * radix + v;
12860786Sps		s++;
12960786Sps	}
13060786Sps
13160786Sps	if (pend != NULL)
13260786Sps	{
13360786Sps		/* Skip trailing white space. */
13460786Sps		while (*s == ' ' || *s == '\t')
13560786Sps			s++;
13660786Sps		*pend = s;
13760786Sps	}
13860786Sps	if (neg)
13960786Sps		return (-n);
14060786Sps	return (n);
14160786Sps}
14260786Sps
14360786Sps
14460786Sps#if !HAVE_STRCHR
14560786Sps	char *
14660786Spsstrchr(s, c)
14760786Sps	char *s;
14860786Sps	int c;
14960786Sps{
15060786Sps	for ( ;  *s != '\0';  s++)
15160786Sps		if (*s == c)
15260786Sps			return (s);
15360786Sps	if (c == '\0')
15460786Sps		return (s);
15560786Sps	return (NULL);
15660786Sps}
15760786Sps#endif
15860786Sps
15960786Sps	int
16060786Spsmain(argc, argv)
16160786Sps	int argc;
16260786Sps	char *argv[];
16360786Sps{
16460786Sps	char *arg;
16560786Sps	char *s;
16660786Sps	int no_more_options;
16760786Sps
16860786Sps	no_more_options = 0;
16960786Sps	while (--argc > 0)
17060786Sps	{
17160786Sps		arg = *++argv;
17260786Sps		if (*arg != '-' || no_more_options)
17360786Sps			break;
17460786Sps		switch (*++arg)
17560786Sps		{
17660786Sps		case 'a':
17760786Sps			quote_all = 1;
17860786Sps			break;
179128345Stjr		case 'c':
180128345Stjr			closequote = *++arg;
181128345Stjr			break;
182128345Stjr		case 'd':
183128345Stjr			closequote = lstrtol(++arg, 0, &s);
184128345Stjr			if (s == arg)
185128345Stjr				pr_error("Missing number after -d");
186128345Stjr			break;
187128345Stjr		case 'e':
188128345Stjr			if (strcmp(++arg, "-") == 0)
189128345Stjr				meta_escape = "";
190128345Stjr			else
191128345Stjr				meta_escape = arg;
192128345Stjr			break;
193128345Stjr		case 'f':
194128345Stjr			meta_escape_buf[0] = lstrtol(++arg, 0, &s);
195128345Stjr			meta_escape = meta_escape_buf;
196128345Stjr			if (s == arg)
197128345Stjr				pr_error("Missing number after -f");
198128345Stjr			break;
19960786Sps		case 'o':
20060786Sps			openquote = *++arg;
20160786Sps			break;
20260786Sps		case 'p':
20360786Sps			openquote = lstrtol(++arg, 0, &s);
20460786Sps			if (s == arg)
205128345Stjr				pr_error("Missing number after -p");
20660786Sps			break;
207128345Stjr		case 'm':
208128345Stjr			metachars[num_metachars++] = *++arg;
209128345Stjr			metachars[num_metachars] = '\0';
210128345Stjr			break;
211128345Stjr		case 'n':
212128345Stjr			metachars[num_metachars++] = lstrtol(++arg, 0, &s);
21360786Sps			if (s == arg)
214128345Stjr				pr_error("Missing number after -n");
215128345Stjr			metachars[num_metachars] = '\0';
21660786Sps			break;
21760786Sps		case '?':
21860786Sps			pr_usage();
21960786Sps			return (0);
22060786Sps		case '-':
22160786Sps			if (*++arg == '\0')
22260786Sps			{
22360786Sps				no_more_options = 1;
22460786Sps				break;
22560786Sps			}
22660786Sps			if (strcmp(arg, "version") == 0)
22760786Sps			{
22860786Sps				pr_version();
22960786Sps				return (0);
23060786Sps			}
23160786Sps			if (strcmp(arg, "help") == 0)
23260786Sps			{
23360786Sps				pr_usage();
23460786Sps				return (0);
23560786Sps			}
23660786Sps			pr_error("Invalid option after --");
23760786Sps		default:
23860786Sps			pr_error("Invalid option letter");
23960786Sps		}
24060786Sps	}
24160786Sps
24260786Sps	while (argc-- > 0)
24360786Sps	{
244128345Stjr		int has_meta = 0;
24560786Sps		arg = *argv++;
246128345Stjr		for (s = arg;  *s != '\0';  s++)
247128345Stjr		{
248128345Stjr			if (strchr(metachars, *s) != NULL)
249128345Stjr			{
250128345Stjr				has_meta = 1;
251128345Stjr				break;
252128345Stjr			}
253128345Stjr		}
254128345Stjr		if (quote_all || (has_meta && strlen(meta_escape) == 0))
25560786Sps			printf("%c%s%c", openquote, arg, closequote);
256128345Stjr		else
257128345Stjr		{
258128345Stjr			for (s = arg;  *s != '\0';  s++)
259128345Stjr			{
260128345Stjr				if (strchr(metachars, *s) != NULL)
261128345Stjr					printf("%s", meta_escape);
262128345Stjr				printf("%c", *s);
263128345Stjr			}
264128345Stjr		}
26560786Sps		if (argc > 0)
26660786Sps			printf(" ");
26760786Sps		else
26860786Sps			printf("\n");
26960786Sps	}
27060786Sps	return (0);
27160786Sps}
272