lessecho.c revision 1.1.1.1 1 /* $NetBSD */
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.1.1.1 $";
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
44 pr_usage()
45 {
46 fprintf(stderr,
47 "usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
48 }
49
50 static void
51 pr_version()
52 {
53 char *p;
54 char buf[10];
55 char *pbuf = buf;
56
57 for (p = version; *p != ' '; p++)
58 if (*p == '\0')
59 return;
60 for (p++; *p != '$' && *p != ' ' && *p != '\0'; p++)
61 *pbuf++ = *p;
62 *pbuf = '\0';
63 printf("%s\n", buf);
64 }
65
66 static void
67 pr_error(s)
68 char *s;
69 {
70 fprintf(stderr, "%s\n", s);
71 exit(1);
72 }
73
74 static long
75 lstrtol(s, radix, pend)
76 char *s;
77 int radix;
78 char **pend;
79 {
80 int v;
81 int neg = 0;
82 long n = 0;
83
84 /* Skip leading white space. */
85 while (*s == ' ' || *s == '\t')
86 s++;
87
88 /* Check for a leading + or -. */
89 if (*s == '-')
90 {
91 neg = 1;
92 s++;
93 } else if (*s == '+')
94 {
95 s++;
96 }
97
98 /* Determine radix if caller does not specify. */
99 if (radix == 0)
100 {
101 radix = 10;
102 if (*s == '0')
103 {
104 switch (*++s)
105 {
106 case 'x':
107 radix = 16;
108 s++;
109 break;
110 default:
111 radix = 8;
112 break;
113 }
114 }
115 }
116
117 /* Parse the digits of the number. */
118 for (;;)
119 {
120 if (*s >= '0' && *s <= '9')
121 v = *s - '0';
122 else if (*s >= 'a' && *s <= 'f')
123 v = *s - 'a' + 10;
124 else if (*s >= 'A' && *s <= 'F')
125 v = *s - 'A' + 10;
126 else
127 break;
128 if (v >= radix)
129 break;
130 n = n * radix + v;
131 s++;
132 }
133
134 if (pend != NULL)
135 {
136 /* Skip trailing white space. */
137 while (*s == ' ' || *s == '\t')
138 s++;
139 *pend = s;
140 }
141 if (neg)
142 return (-n);
143 return (n);
144 }
145
146
147 #if !HAVE_STRCHR
148 char *
149 strchr(s, c)
150 char *s;
151 int c;
152 {
153 for ( ; *s != '\0'; s++)
154 if (*s == c)
155 return (s);
156 if (c == '\0')
157 return (s);
158 return (NULL);
159 }
160 #endif
161
162 int
163 main(argc, argv)
164 int argc;
165 char *argv[];
166 {
167 char *arg;
168 char *s;
169 int no_more_options;
170
171 no_more_options = 0;
172 while (--argc > 0)
173 {
174 arg = *++argv;
175 if (*arg != '-' || no_more_options)
176 break;
177 switch (*++arg)
178 {
179 case 'a':
180 quote_all = 1;
181 break;
182 case 'c':
183 closequote = *++arg;
184 break;
185 case 'd':
186 closequote = lstrtol(++arg, 0, &s);
187 if (s == arg)
188 pr_error("Missing number after -d");
189 break;
190 case 'e':
191 if (strcmp(++arg, "-") == 0)
192 meta_escape = "";
193 else
194 meta_escape = arg;
195 break;
196 case 'f':
197 meta_escape_buf[0] = lstrtol(++arg, 0, &s);
198 meta_escape = meta_escape_buf;
199 if (s == arg)
200 pr_error("Missing number after -f");
201 break;
202 case 'o':
203 openquote = *++arg;
204 break;
205 case 'p':
206 openquote = lstrtol(++arg, 0, &s);
207 if (s == arg)
208 pr_error("Missing number after -p");
209 break;
210 case 'm':
211 metachars[num_metachars++] = *++arg;
212 metachars[num_metachars] = '\0';
213 break;
214 case 'n':
215 metachars[num_metachars++] = lstrtol(++arg, 0, &s);
216 if (s == arg)
217 pr_error("Missing number after -n");
218 metachars[num_metachars] = '\0';
219 break;
220 case '?':
221 pr_usage();
222 return (0);
223 case '-':
224 if (*++arg == '\0')
225 {
226 no_more_options = 1;
227 break;
228 }
229 if (strcmp(arg, "version") == 0)
230 {
231 pr_version();
232 return (0);
233 }
234 if (strcmp(arg, "help") == 0)
235 {
236 pr_usage();
237 return (0);
238 }
239 pr_error("Invalid option after --");
240 default:
241 pr_error("Invalid option letter");
242 }
243 }
244
245 while (argc-- > 0)
246 {
247 int has_meta = 0;
248 arg = *argv++;
249 for (s = arg; *s != '\0'; s++)
250 {
251 if (strchr(metachars, *s) != NULL)
252 {
253 has_meta = 1;
254 break;
255 }
256 }
257 if (quote_all || (has_meta && strlen(meta_escape) == 0))
258 printf("%c%s%c", openquote, arg, closequote);
259 else
260 {
261 for (s = arg; *s != '\0'; s++)
262 {
263 if (strchr(metachars, *s) != NULL)
264 printf("%s", meta_escape);
265 printf("%c", *s);
266 }
267 }
268 if (argc > 0)
269 printf(" ");
270 else
271 printf("\n");
272 }
273 return (0);
274 }
275