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