11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
3184260Sobrien *
32148834Sstefanf *	$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $
331573Srgrimes */
341573Srgrimes
351573Srgrimes#if !defined(lint) && !defined(SCCSID)
361573Srgrimesstatic char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/4/93";
371573Srgrimes#endif /* not lint && not SCCSID */
3884260Sobrien#include <sys/cdefs.h>
3984260Sobrien__FBSDID("$FreeBSD$");
401573Srgrimes
411573Srgrimes/*
421573Srgrimes * parse.c: parse an editline extended command
431573Srgrimes *
441573Srgrimes * commands are:
451573Srgrimes *
461573Srgrimes *	bind
471573Srgrimes *	echotc
4884260Sobrien *	edit
491573Srgrimes *	gettc
5026926Smsmith *	history
5126926Smsmith *	settc
5226926Smsmith *	setty
531573Srgrimes */
541573Srgrimes#include "sys.h"
551573Srgrimes#include "el.h"
5684260Sobrien#include <stdlib.h>
571573Srgrimes
5884260Sobrienprivate const struct {
59148834Sstefanf	const char *name;
60148834Sstefanf	int (*func)(EditLine *, int, const char **);
611573Srgrimes} cmds[] = {
6284260Sobrien	{ "bind",	map_bind	},
6384260Sobrien	{ "echotc",	term_echotc	},
6484260Sobrien	{ "edit",	el_editmode	},
65148834Sstefanf	{ "history",	hist_command	},
6684260Sobrien	{ "telltc",	term_telltc	},
6784260Sobrien	{ "settc",	term_settc	},
6884260Sobrien	{ "setty",	tty_stty	},
6984260Sobrien	{ NULL,		NULL		}
701573Srgrimes};
711573Srgrimes
721573Srgrimes
731573Srgrimes/* parse_line():
741573Srgrimes *	Parse a line and dispatch it
751573Srgrimes */
761573Srgrimesprotected int
7784260Sobrienparse_line(EditLine *el, const char *line)
781573Srgrimes{
79148834Sstefanf	const char **argv;
8084260Sobrien	int argc;
8184260Sobrien	Tokenizer *tok;
821573Srgrimes
8384260Sobrien	tok = tok_init(NULL);
84148834Sstefanf	tok_str(tok, line, &argc, &argv);
8584260Sobrien	argc = el_parse(el, argc, argv);
8684260Sobrien	tok_end(tok);
8784260Sobrien	return (argc);
881573Srgrimes}
891573Srgrimes
9084260Sobrien
911573Srgrimes/* el_parse():
921573Srgrimes *	Command dispatcher
931573Srgrimes */
941573Srgrimespublic int
95148834Sstefanfel_parse(EditLine *el, int argc, const char *argv[])
961573Srgrimes{
97148834Sstefanf	const char *ptr;
9884260Sobrien	int i;
991573Srgrimes
10084260Sobrien	if (argc < 1)
10184260Sobrien		return (-1);
10284260Sobrien	ptr = strchr(argv[0], ':');
10384260Sobrien	if (ptr != NULL) {
10484260Sobrien		char *tprog;
10584260Sobrien		size_t l;
1061573Srgrimes
10784260Sobrien		if (ptr == argv[0])
10884260Sobrien			return (0);
10984260Sobrien		l = ptr - argv[0] - 1;
11084260Sobrien		tprog = (char *) el_malloc(l + 1);
11184260Sobrien		if (tprog == NULL)
11284260Sobrien			return (0);
11384260Sobrien		(void) strncpy(tprog, argv[0], l);
11484260Sobrien		tprog[l] = '\0';
11584260Sobrien		ptr++;
11684260Sobrien		l = el_match(el->el_prog, tprog);
11784260Sobrien		el_free(tprog);
11884260Sobrien		if (!l)
11984260Sobrien			return (0);
12084260Sobrien	} else
12184260Sobrien		ptr = argv[0];
1221573Srgrimes
12384260Sobrien	for (i = 0; cmds[i].name != NULL; i++)
12484260Sobrien		if (strcmp(cmds[i].name, ptr) == 0) {
12584260Sobrien			i = (*cmds[i].func) (el, argc, argv);
12684260Sobrien			return (-i);
12784260Sobrien		}
12884260Sobrien	return (-1);
1291573Srgrimes}
1301573Srgrimes
1311573Srgrimes
1321573Srgrimes/* parse__escape():
1331573Srgrimes *	Parse a string of the form ^<char> \<odigit> \<char> and return
1341573Srgrimes *	the appropriate character or -1 if the escape is not valid
1351573Srgrimes */
1361573Srgrimesprotected int
137148834Sstefanfparse__escape(const char **ptr)
1381573Srgrimes{
13984260Sobrien	const char *p;
14084260Sobrien	int c;
1411573Srgrimes
14284260Sobrien	p = *ptr;
1431573Srgrimes
14484260Sobrien	if (p[1] == 0)
14584260Sobrien		return (-1);
1461573Srgrimes
14784260Sobrien	if (*p == '\\') {
14884260Sobrien		p++;
14984260Sobrien		switch (*p) {
15084260Sobrien		case 'a':
15184260Sobrien			c = '\007';	/* Bell */
15284260Sobrien			break;
15384260Sobrien		case 'b':
15484260Sobrien			c = '\010';	/* Backspace */
15584260Sobrien			break;
15684260Sobrien		case 't':
15784260Sobrien			c = '\011';	/* Horizontal Tab */
15884260Sobrien			break;
15984260Sobrien		case 'n':
16084260Sobrien			c = '\012';	/* New Line */
16184260Sobrien			break;
16284260Sobrien		case 'v':
16384260Sobrien			c = '\013';	/* Vertical Tab */
16484260Sobrien			break;
16584260Sobrien		case 'f':
16684260Sobrien			c = '\014';	/* Form Feed */
16784260Sobrien			break;
16884260Sobrien		case 'r':
16984260Sobrien			c = '\015';	/* Carriage Return */
17084260Sobrien			break;
17184260Sobrien		case 'e':
17284260Sobrien			c = '\033';	/* Escape */
17384260Sobrien			break;
17484260Sobrien		case '0':
17584260Sobrien		case '1':
17684260Sobrien		case '2':
17784260Sobrien		case '3':
17884260Sobrien		case '4':
17984260Sobrien		case '5':
18084260Sobrien		case '6':
18184260Sobrien		case '7':
18284260Sobrien		{
18384260Sobrien			int cnt, ch;
1841573Srgrimes
18584260Sobrien			for (cnt = 0, c = 0; cnt < 3; cnt++) {
18684260Sobrien				ch = *p++;
18784260Sobrien				if (ch < '0' || ch > '7') {
18884260Sobrien					p--;
18984260Sobrien					break;
19084260Sobrien				}
19184260Sobrien				c = (c << 3) | (ch - '0');
19284260Sobrien			}
19384260Sobrien			if ((c & 0xffffff00) != 0)
19484260Sobrien				return (-1);
19584260Sobrien			--p;
1961573Srgrimes			break;
1971573Srgrimes		}
19884260Sobrien		default:
19984260Sobrien			c = *p;
20084260Sobrien			break;
20184260Sobrien		}
202148834Sstefanf	} else if (*p == '^') {
20384260Sobrien		p++;
20484260Sobrien		c = (*p == '?') ? '\177' : (*p & 0237);
20584260Sobrien	} else
20684260Sobrien		c = *p;
20784260Sobrien	*ptr = ++p;
20884260Sobrien	return ((unsigned char)c);
2091573Srgrimes}
210148834Sstefanf
2111573Srgrimes/* parse__string():
2121573Srgrimes *	Parse the escapes from in and put the raw string out
2131573Srgrimes */
2141573Srgrimesprotected char *
21584260Sobrienparse__string(char *out, const char *in)
2161573Srgrimes{
21784260Sobrien	char *rv = out;
21884260Sobrien	int n;
2191573Srgrimes
22084260Sobrien	for (;;)
22184260Sobrien		switch (*in) {
22284260Sobrien		case '\0':
22384260Sobrien			*out = '\0';
22484260Sobrien			return (rv);
2251573Srgrimes
22684260Sobrien		case '\\':
22784260Sobrien		case '^':
22884260Sobrien			if ((n = parse__escape(&in)) == -1)
22984260Sobrien				return (NULL);
23084260Sobrien			*out++ = n;
23184260Sobrien			break;
23284260Sobrien
233148834Sstefanf		case 'M':
234148834Sstefanf			if (in[1] == '-' && in[2] != '\0') {
235148834Sstefanf				*out++ = '\033';
236148834Sstefanf				in += 2;
237148834Sstefanf				break;
238148834Sstefanf			}
239148834Sstefanf			/*FALLTHROUGH*/
240148834Sstefanf
24184260Sobrien		default:
24284260Sobrien			*out++ = *in++;
24384260Sobrien			break;
24484260Sobrien		}
2451573Srgrimes}
2461573Srgrimes
24784260Sobrien
2481573Srgrimes/* parse_cmd():
2491573Srgrimes *	Return the command number for the command string given
2501573Srgrimes *	or -1 if one is not found
2511573Srgrimes */
2521573Srgrimesprotected int
25384260Sobrienparse_cmd(EditLine *el, const char *cmd)
2541573Srgrimes{
255277931Semaste	el_bindings_t *b = el->el_map.help;
256277931Semaste	size_t i;
2571573Srgrimes
258277931Semaste	for (i = 0; i < el->el_map.nfunc; i++)
259277931Semaste		if (strcmp(b[i].name, cmd) == 0)
260277931Semaste			return (b[i].func);
26184260Sobrien	return (-1);
2621573Srgrimes}
263