parse.c revision 84334
190792Sgshapiro/*-
294334Sgshapiro * Copyright (c) 1992, 1993
390792Sgshapiro *	The Regents of the University of California.  All rights reserved.
490792Sgshapiro *
590792Sgshapiro * This code is derived from software contributed to Berkeley by
690792Sgshapiro * Christos Zoulas of Cornell University.
790792Sgshapiro *
890792Sgshapiro * Redistribution and use in source and binary forms, with or without
9132943Sgshapiro * modification, are permitted provided that the following conditions
1090792Sgshapiro * are met:
1190792Sgshapiro * 1. Redistributions of source code must retain the above copyright
1290792Sgshapiro *    notice, this list of conditions and the following disclaimer.
1390792Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright
1490792Sgshapiro *    notice, this list of conditions and the following disclaimer in the
1590792Sgshapiro *    documentation and/or other materials provided with the distribution.
1690792Sgshapiro * 3. All advertising materials mentioning features or use of this software
1790792Sgshapiro *    must display the following acknowledgement:
1890792Sgshapiro *	This product includes software developed by the University of
1990792Sgshapiro *	California, Berkeley and its contributors.
2090792Sgshapiro * 4. Neither the name of the University nor the names of its contributors
2190792Sgshapiro *    may be used to endorse or promote products derived from this software
2290792Sgshapiro *    without specific prior written permission.
2390792Sgshapiro *
2490792Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2590792Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2690792Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2790792Sgshapiro * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2890792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2990792Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3090792Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3190792Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3290792Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3390792Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3490792Sgshapiro * SUCH DAMAGE.
3590792Sgshapiro *
3690792Sgshapiro *	$NetBSD: parse.c,v 1.13 2000/09/04 22:06:31 lukem Exp $
3790792Sgshapiro */
3890792Sgshapiro
3990792Sgshapiro#if !defined(lint) && !defined(SCCSID)
4090792Sgshapirostatic char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/4/93";
4190792Sgshapiro#endif /* not lint && not SCCSID */
4290792Sgshapiro#include <sys/cdefs.h>
4390792Sgshapiro__FBSDID("$FreeBSD: head/lib/libedit/parse.c 84334 2001-10-01 23:00:29Z obrien $");
4490792Sgshapiro
4590792Sgshapiro/*
46132943Sgshapiro * parse.c: parse an editline extended command
4790792Sgshapiro *
4890792Sgshapiro * commands are:
4990792Sgshapiro *
5090792Sgshapiro *	bind
5190792Sgshapiro *	echotc
5290792Sgshapiro *	edit
5390792Sgshapiro *	gettc
5490792Sgshapiro *	history
5590792Sgshapiro *	settc
5690792Sgshapiro *	setty
5790792Sgshapiro */
5890792Sgshapiro#include "sys.h"
5990792Sgshapiro#include "el.h"
6090792Sgshapiro#include "tokenizer.h"
61132943Sgshapiro#include <stdlib.h>
62132943Sgshapiro
6390792Sgshapiroprivate const struct {
6490792Sgshapiro	char *name;
6590792Sgshapiro	int (*func)(EditLine *, int, char **);
6690792Sgshapiro} cmds[] = {
6790792Sgshapiro	{ "bind",	map_bind	},
6890792Sgshapiro	{ "echotc",	term_echotc	},
6990792Sgshapiro	{ "edit",	el_editmode	},
7090792Sgshapiro	{ "history",	hist_list	},
7190792Sgshapiro	{ "telltc",	term_telltc	},
7290792Sgshapiro	{ "settc",	term_settc	},
7390792Sgshapiro	{ "setty",	tty_stty	},
7490792Sgshapiro	{ NULL,		NULL		}
7590792Sgshapiro};
7690792Sgshapiro
7790792Sgshapiro
7890792Sgshapiro/* parse_line():
7990792Sgshapiro *	Parse a line and dispatch it
8090792Sgshapiro */
81protected int
82parse_line(EditLine *el, const char *line)
83{
84	char **argv;
85	int argc;
86	Tokenizer *tok;
87
88	tok = tok_init(NULL);
89	tok_line(tok, line, &argc, &argv);
90	argc = el_parse(el, argc, argv);
91	tok_end(tok);
92	return (argc);
93}
94
95
96/* el_parse():
97 *	Command dispatcher
98 */
99public int
100el_parse(EditLine *el, int argc, 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		char *tprog;
110		size_t l;
111
112		if (ptr == argv[0])
113			return (0);
114		l = ptr - argv[0] - 1;
115		tprog = (char *) el_malloc(l + 1);
116		if (tprog == NULL)
117			return (0);
118		(void) strncpy(tprog, argv[0], l);
119		tprog[l] = '\0';
120		ptr++;
121		l = el_match(el->el_prog, tprog);
122		el_free(tprog);
123		if (!l)
124			return (0);
125	} else
126		ptr = argv[0];
127
128	for (i = 0; cmds[i].name != NULL; i++)
129		if (strcmp(cmds[i].name, ptr) == 0) {
130			i = (*cmds[i].func) (el, argc, argv);
131			return (-i);
132		}
133	return (-1);
134}
135
136
137/* parse__escape():
138 *	Parse a string of the form ^<char> \<odigit> \<char> and return
139 *	the appropriate character or -1 if the escape is not valid
140 */
141protected int
142parse__escape(const char **const ptr)
143{
144	const char *p;
145	int c;
146
147	p = *ptr;
148
149	if (p[1] == 0)
150		return (-1);
151
152	if (*p == '\\') {
153		p++;
154		switch (*p) {
155		case 'a':
156			c = '\007';	/* Bell */
157			break;
158		case 'b':
159			c = '\010';	/* Backspace */
160			break;
161		case 't':
162			c = '\011';	/* Horizontal Tab */
163			break;
164		case 'n':
165			c = '\012';	/* New Line */
166			break;
167		case 'v':
168			c = '\013';	/* Vertical Tab */
169			break;
170		case 'f':
171			c = '\014';	/* Form Feed */
172			break;
173		case 'r':
174			c = '\015';	/* Carriage Return */
175			break;
176		case 'e':
177			c = '\033';	/* Escape */
178			break;
179		case '0':
180		case '1':
181		case '2':
182		case '3':
183		case '4':
184		case '5':
185		case '6':
186		case '7':
187		{
188			int cnt, ch;
189
190			for (cnt = 0, c = 0; cnt < 3; cnt++) {
191				ch = *p++;
192				if (ch < '0' || ch > '7') {
193					p--;
194					break;
195				}
196				c = (c << 3) | (ch - '0');
197			}
198			if ((c & 0xffffff00) != 0)
199				return (-1);
200			--p;
201			break;
202		}
203		default:
204			c = *p;
205			break;
206		}
207	} else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1])))  {
208		p++;
209		c = (*p == '?') ? '\177' : (*p & 0237);
210	} else
211		c = *p;
212	*ptr = ++p;
213	return ((unsigned char)c);
214}
215/* parse__string():
216 *	Parse the escapes from in and put the raw string out
217 */
218protected char *
219parse__string(char *out, const char *in)
220{
221	char *rv = out;
222	int n;
223
224	for (;;)
225		switch (*in) {
226		case '\0':
227			*out = '\0';
228			return (rv);
229
230		case '\\':
231		case '^':
232			if ((n = parse__escape(&in)) == -1)
233				return (NULL);
234			*out++ = n;
235			break;
236
237		default:
238			*out++ = *in++;
239			break;
240		}
241}
242
243
244/* parse_cmd():
245 *	Return the command number for the command string given
246 *	or -1 if one is not found
247 */
248protected int
249parse_cmd(EditLine *el, const char *cmd)
250{
251	el_bindings_t *b;
252
253	for (b = el->el_map.help; b->name != NULL; b++)
254		if (strcmp(b->name, cmd) == 0)
255			return (b->func);
256	return (-1);
257}
258