parse.c revision 1.19 1 /* $NetBSD: parse.c,v 1.19 2003/11/02 20:06:57 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
39 #else
40 __RCSID("$NetBSD: parse.c,v 1.19 2003/11/02 20:06:57 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
43
44 /*
45 * parse.c: parse an editline extended command
46 *
47 * commands are:
48 *
49 * bind
50 * echotc
51 * edit
52 * gettc
53 * history
54 * settc
55 * setty
56 */
57 #include "el.h"
58 #include "tokenizer.h"
59 #include <stdlib.h>
60
61 private const struct {
62 const char *name;
63 int (*func)(EditLine *, int, const char **);
64 } cmds[] = {
65 { "bind", map_bind },
66 { "echotc", term_echotc },
67 { "edit", el_editmode },
68 { "history", hist_command },
69 { "telltc", term_telltc },
70 { "settc", term_settc },
71 { "setty", tty_stty },
72 { NULL, NULL }
73 };
74
75
76 /* parse_line():
77 * Parse a line and dispatch it
78 */
79 protected int
80 parse_line(EditLine *el, const char *line)
81 {
82 const char **argv;
83 int argc;
84 Tokenizer *tok;
85
86 tok = tok_init(NULL);
87 tok_line(tok, line, &argc, &argv);
88 argc = el_parse(el, argc, argv);
89 tok_end(tok);
90 return (argc);
91 }
92
93
94 /* el_parse():
95 * Command dispatcher
96 */
97 public int
98 el_parse(EditLine *el, int argc, const char *argv[])
99 {
100 const char *ptr;
101 int i;
102
103 if (argc < 1)
104 return (-1);
105 ptr = strchr(argv[0], ':');
106 if (ptr != NULL) {
107 char *tprog;
108 size_t l;
109
110 if (ptr == argv[0])
111 return (0);
112 l = ptr - argv[0] - 1;
113 tprog = (char *) el_malloc(l + 1);
114 if (tprog == NULL)
115 return (0);
116 (void) strncpy(tprog, argv[0], l);
117 tprog[l] = '\0';
118 ptr++;
119 l = el_match(el->el_prog, tprog);
120 el_free(tprog);
121 if (!l)
122 return (0);
123 } else
124 ptr = argv[0];
125
126 for (i = 0; cmds[i].name != NULL; i++)
127 if (strcmp(cmds[i].name, ptr) == 0) {
128 i = (*cmds[i].func) (el, argc, argv);
129 return (-i);
130 }
131 return (-1);
132 }
133
134
135 /* parse__escape():
136 * Parse a string of the form ^<char> \<odigit> \<char> and return
137 * the appropriate character or -1 if the escape is not valid
138 */
139 protected int
140 parse__escape(const char **const ptr)
141 {
142 const char *p;
143 int c;
144
145 p = *ptr;
146
147 if (p[1] == 0)
148 return (-1);
149
150 if (*p == '\\') {
151 p++;
152 switch (*p) {
153 case 'a':
154 c = '\007'; /* Bell */
155 break;
156 case 'b':
157 c = '\010'; /* Backspace */
158 break;
159 case 't':
160 c = '\011'; /* Horizontal Tab */
161 break;
162 case 'n':
163 c = '\012'; /* New Line */
164 break;
165 case 'v':
166 c = '\013'; /* Vertical Tab */
167 break;
168 case 'f':
169 c = '\014'; /* Form Feed */
170 break;
171 case 'r':
172 c = '\015'; /* Carriage Return */
173 break;
174 case 'e':
175 c = '\033'; /* Escape */
176 break;
177 case '0':
178 case '1':
179 case '2':
180 case '3':
181 case '4':
182 case '5':
183 case '6':
184 case '7':
185 {
186 int cnt, ch;
187
188 for (cnt = 0, c = 0; cnt < 3; cnt++) {
189 ch = *p++;
190 if (ch < '0' || ch > '7') {
191 p--;
192 break;
193 }
194 c = (c << 3) | (ch - '0');
195 }
196 if ((c & 0xffffff00) != 0)
197 return (-1);
198 --p;
199 break;
200 }
201 default:
202 c = *p;
203 break;
204 }
205 } else if (*p == '^') {
206 p++;
207 c = (*p == '?') ? '\177' : (*p & 0237);
208 } else
209 c = *p;
210 *ptr = ++p;
211 return (c);
212 }
213
214 /* parse__string():
215 * Parse the escapes from in and put the raw string out
216 */
217 protected char *
218 parse__string(char *out, const char *in)
219 {
220 char *rv = out;
221 int n;
222
223 for (;;)
224 switch (*in) {
225 case '\0':
226 *out = '\0';
227 return (rv);
228
229 case '\\':
230 case '^':
231 if ((n = parse__escape(&in)) == -1)
232 return (NULL);
233 *out++ = n;
234 break;
235
236 case 'M':
237 if (in[1] == '-' && in[2] != '\0') {
238 *out++ = '\033';
239 in += 2;
240 break;
241 }
242 /*FALLTHROUGH*/
243
244 default:
245 *out++ = *in++;
246 break;
247 }
248 }
249
250
251 /* parse_cmd():
252 * Return the command number for the command string given
253 * or -1 if one is not found
254 */
255 protected int
256 parse_cmd(EditLine *el, const char *cmd)
257 {
258 el_bindings_t *b;
259
260 for (b = el->el_map.help; b->name != NULL; b++)
261 if (strcmp(b->name, cmd) == 0)
262 return (b->func);
263 return (-1);
264 }
265