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