parse.c revision 26982
1139804Simp/*-
240711Swollman * Copyright (c) 1992, 1993
340711Swollman *	The Regents of the University of California.  All rights reserved.
440711Swollman *
540711Swollman * This code is derived from software contributed to Berkeley by
640711Swollman * Christos Zoulas of Cornell University.
740711Swollman *
840711Swollman * Redistribution and use in source and binary forms, with or without
940711Swollman * modification, are permitted provided that the following conditions
1040711Swollman * are met:
1140711Swollman * 1. Redistributions of source code must retain the above copyright
1240711Swollman *    notice, this list of conditions and the following disclaimer.
1340711Swollman * 2. Redistributions in binary form must reproduce the above copyright
1440711Swollman *    notice, this list of conditions and the following disclaimer in the
15152543Syongari *    documentation and/or other materials provided with the distribution.
1640711Swollman * 3. All advertising materials mentioning features or use of this software
1740711Swollman *    must display the following acknowledgement:
1840711Swollman *	This product includes software developed by the University of
1940711Swollman *	California, Berkeley and its contributors.
2040711Swollman * 4. Neither the name of the University nor the names of its contributors
2140711Swollman *    may be used to endorse or promote products derived from this software
2240711Swollman *    without specific prior written permission.
2340711Swollman *
2440711Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2540711Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2640711Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2740711Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2840711Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2940711Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3040711Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3140711Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3240711Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3340711Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3440711Swollman * SUCH DAMAGE.
3540711Swollman */
3640711Swollman
3740711Swollman#if !defined(lint) && !defined(SCCSID)
3840711Swollmanstatic char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/4/93";
3940711Swollman#endif /* not lint && not SCCSID */
4040711Swollman
4140711Swollman/*
4240711Swollman * parse.c: parse an editline extended command
4340711Swollman *
4440711Swollman * commands are:
4540711Swollman *
4640711Swollman *	bind
4740711Swollman *	echotc
4840711Swollman *	settc
4940711Swollman *	gettc
5040711Swollman *	history
5140711Swollman *	settc
5240711Swollman *	setty
5340711Swollman */
5440711Swollman#include "sys.h"
5540711Swollman#include "el.h"
5640711Swollman#include "tokenizer.h"
5740711Swollman
58168791Sjhbprivate struct {
59168791Sjhb    char *name;
60116182Sobrien    int (*func) __P((EditLine *, int, char **));
61116182Sobrien} cmds[] = {
62116182Sobrien    {	"bind",		map_bind 	},
6340711Swollman    {	"echotc",	term_echotc 	},
6440711Swollman    {	"history",	hist_list	},
6541304Sbde    {	"telltc",	term_telltc 	},
66164881Sjhb    {	"settc",	term_settc	},
6740711Swollman    {	"setty",	tty_stty	},
6840711Swollman    {	NULL,		NULL		}
6971576Sjasone};
7045720Speter
7145720Speter
7240711Swollman/* parse_line():
73102962Siwasaki *	Parse a line and dispatch it
7440711Swollman */
75168791Sjhbprotected int
76168791Sjhbparse_line(el, line)
77168791Sjhb    EditLine *el;
78168791Sjhb    const char *line;
79151037Sphk{
80151037Sphk    char **argv;
81151037Sphk    int argc;
82151037Sphk    Tokenizer *tok;
83151037Sphk
84151037Sphk    tok = tok_init(NULL);
85151037Sphk    tok_line(tok, line, &argc, &argv);
86151037Sphk    argc = el_parse(el, argc, argv);
87151037Sphk    tok_end(tok);
88151037Sphk    return argc;
89151037Sphk}
90151037Sphk
91151037Sphk/* el_parse():
92151037Sphk *	Command dispatcher
93151037Sphk */
94151037Sphkpublic int
95151037Sphkel_parse(el, argc, argv)
96151037Sphk    EditLine *el;
97151037Sphk    int argc;
98151037Sphk    char *argv[];
99151037Sphk{
100151037Sphk    char *ptr;
101151037Sphk    int i;
102102962Siwasaki
103102962Siwasaki    if (argc < 1)
104102962Siwasaki	return -1;
105102962Siwasaki    ptr = strchr(argv[0], ':');
10659910Spaul    if (ptr != NULL) {
107102962Siwasaki	*ptr++ = '\0';
108102962Siwasaki	if (! el_match(el->el_prog, argv[0]))
10945569Seivind	    return 0;
11040711Swollman    }
11140711Swollman    else
11271576Sjasone	ptr = argv[0];
113150523Sphk
114150523Sphk    for (i = 0; cmds[i].name != NULL; i++)
115150523Sphk	if (strcmp(cmds[i].name, ptr) == 0) {
116150523Sphk	    i = (*cmds[i].func)(el, argc, argv);
11740711Swollman	    return -i;
118150523Sphk	}
119150523Sphk
120150523Sphk    return -1;
121150523Sphk}
122150523Sphk
123150523Sphk
124150523Sphk/* parse__escape():
125150523Sphk *	Parse a string of the form ^<char> \<odigit> \<char> and return
126150523Sphk *	the appropriate character or -1 if the escape is not valid
127150523Sphk */
128150523Sphkprotected int
129150523Sphkparse__escape(ptr)
13040711Swollman    const char  ** const ptr;
13140711Swollman{
13240711Swollman    const char   *p;
133152543Syongari    int   c;
13440711Swollman
13540711Swollman    p = *ptr;
13640711Swollman
13740711Swollman    if (p[1] == 0)
13893818Sjhb	return -1;
13940711Swollman
14040711Swollman    if (*p == '\\') {
14140711Swollman	p++;
14240711Swollman	switch (*p) {
14340711Swollman	case 'a':
14440711Swollman	    c = '\007';		/* Bell */
14540711Swollman	    break;
14668727Smckusick	case 'b':
14784781Sjhb	    c = '\010';		/* Backspace */
148152543Syongari	    break;
14940711Swollman	case 't':
15093818Sjhb	    c = '\011';		/* Horizontal Tab */
15140711Swollman	    break;
15272200Sbmilekic	case 'n':
15340711Swollman	    c = '\012';		/* New Line */
15472200Sbmilekic	    break;
15540711Swollman	case 'v':
15640711Swollman	    c = '\013';		/* Vertical Tab */
15740711Swollman	    break;
15840711Swollman	case 'f':
15940711Swollman	    c = '\014';		/* Form Feed */
16040711Swollman	    break;
161162224Sjhb	case 'r':
16240711Swollman	    c = '\015';		/* Carriage Return */
163134040Snjl	    break;
164134021Snjl	case 'e':
165150523Sphk	    c = '\033';		/* Escape */
166152543Syongari	    break;
16740711Swollman	case '0':
16840711Swollman	case '1':
16940711Swollman	case '2':
17040711Swollman	case '3':
17140711Swollman	case '4':
17272200Sbmilekic	case '5':
173162224Sjhb	case '6':
174162224Sjhb	case '7':
175164881Sjhb	    {
176164881Sjhb		int cnt, ch;
177164881Sjhb
178164881Sjhb		for (cnt = 0, c = 0; cnt < 3; cnt++) {
179164881Sjhb		    ch = *p++;
180164881Sjhb		    if (ch < '0' || ch > '7') {
18140711Swollman			p--;
182162224Sjhb			break;
18368727Smckusick		    }
18468727Smckusick		    c = (c << 3) | (ch - '0');
18540711Swollman		}
186162224Sjhb		if ((c & 0xffffff00) != 0)
187162224Sjhb		    return -1;
188162224Sjhb		--p;
189162224Sjhb	    }
190162224Sjhb	    break;
191162224Sjhb	default:
192162224Sjhb	    c = *p;
193162224Sjhb	    break;
194162224Sjhb	}
195162224Sjhb    }
196162224Sjhb    else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1]))) {
197162224Sjhb	p++;
198162224Sjhb	c = (*p == '?') ? '\177' : (*p & 0237);
199162224Sjhb    }
200162224Sjhb    else
201162224Sjhb	c = *p;
202162224Sjhb    *ptr = ++p;
203162224Sjhb    return (unsigned char)c;
204162224Sjhb}
205162224Sjhb
206162224Sjhb/* parse__string():
207162224Sjhb *	Parse the escapes from in and put the raw string out
208162224Sjhb */
209162224Sjhbprotected char *
210162224Sjhbparse__string(out, in)
211162224Sjhb    char *out;
212162224Sjhb    const char *in;
213162224Sjhb{
214166932Sscottl    char *rv = out;
215166932Sscottl    int n;
216166932Sscottl    for (;;)
217166932Sscottl	switch (*in) {
218166932Sscottl	case '\0':
219166932Sscottl	    *out = '\0';
220162224Sjhb	    return rv;
221166932Sscottl
222162224Sjhb	case '\\':
22340711Swollman	case '^':
22440711Swollman	    if ((n = parse__escape(&in)) == -1)
22572200Sbmilekic		return NULL;
22640711Swollman	    *out++ = n;
22740711Swollman	    break;
22840711Swollman
22940711Swollman	default:
230159536Simp	    *out++ = *in++;
231159536Simp	    break;
232159536Simp	}
233159536Simp}
234159536Simp
235159536Simp/* parse_cmd():
236159536Simp *	Return the command number for the command string given
237159536Simp *	or -1 if one is not found
238159536Simp */
239159536Simpprotected int
24040711Swollmanparse_cmd(el, cmd)
24140711Swollman    EditLine *el;
242150523Sphk    const char *cmd;
24340711Swollman{
24472200Sbmilekic    el_bindings_t *b;
24568727Smckusick
24645720Speter    for (b = el->el_map.help; b->name != NULL; b++)
24772200Sbmilekic	if (strcmp(b->name, cmd) == 0)
24840711Swollman	    return b->func;
24945720Speter    return -1;
25040711Swollman}
25140711Swollman