xref: /csrg-svn/lib/libedit/parse.c (revision 61275)
154224Sbostic /*-
2*61275Sbostic  * Copyright (c) 1992, 1993
3*61275Sbostic  *	The Regents of the University of California.  All rights reserved.
454224Sbostic  *
554224Sbostic  * This code is derived from software contributed to Berkeley by
654224Sbostic  * Christos Zoulas of Cornell University.
754224Sbostic  *
854224Sbostic  * %sccs.include.redist.c%
954224Sbostic  */
1054224Sbostic 
1154624Schristos #if !defined(lint) && !defined(SCCSID)
12*61275Sbostic static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 06/04/93";
1354624Schristos #endif /* not lint && not SCCSID */
1454224Sbostic 
1554224Sbostic /*
1654624Schristos  * parse.c: parse an editline extended command
1754224Sbostic  *
1854224Sbostic  * commands are:
1954224Sbostic  *
2054224Sbostic  *	bind
2154224Sbostic  *	echotc
2254224Sbostic  *	settc
2354224Sbostic  *	gettc
2454224Sbostic  */
2554224Sbostic #include "sys.h"
2654224Sbostic #include "el.h"
2754224Sbostic #include "tokenizer.h"
2854224Sbostic 
2954224Sbostic private struct {
3054224Sbostic     char *name;
3154224Sbostic     int (*func) __P((EditLine *, int, char **));
3254224Sbostic } cmds[] = {
3354224Sbostic     {	"bind",		map_bind 	},
3454224Sbostic     {	"echotc",	term_echotc 	},
3554224Sbostic     {	"history",	hist_list	},
3654224Sbostic     {	"telltc",	term_telltc 	},
3754224Sbostic     {	"settc",	term_settc	},
3854224Sbostic     {	"setty",	tty_stty	},
3954224Sbostic     {	NULL,		NULL		}
4054224Sbostic };
4154224Sbostic 
4254224Sbostic 
4354224Sbostic /* parse_line():
4454224Sbostic  *	Parse a line and dispatch it
4554224Sbostic  */
4654224Sbostic protected int
parse_line(el,line)4754224Sbostic parse_line(el, line)
4854224Sbostic     EditLine *el;
4954224Sbostic     const char *line;
5054224Sbostic {
5154224Sbostic     char **argv;
5254224Sbostic     int argc;
5354224Sbostic     Tokenizer *tok;
5454224Sbostic 
5554224Sbostic     tok = tok_init(NULL);
5654224Sbostic     tok_line(tok, line, &argc, &argv);
5754224Sbostic     argc = el_parse(el, argc, argv);
5854224Sbostic     tok_end(tok);
5954224Sbostic     return argc;
6054224Sbostic }
6154224Sbostic 
6254224Sbostic /* el_parse():
6354224Sbostic  *	Command dispatcher
6454224Sbostic  */
6554224Sbostic public int
el_parse(el,argc,argv)6654224Sbostic el_parse(el, argc, argv)
6754224Sbostic     EditLine *el;
6854224Sbostic     int argc;
6954224Sbostic     char *argv[];
7054224Sbostic {
7154224Sbostic     char *ptr;
7254224Sbostic     int i;
7354224Sbostic 
7454224Sbostic     for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++)
7554224Sbostic 	continue;
7654224Sbostic 
7754224Sbostic     if (*ptr == ':') {
7854224Sbostic 	*ptr = '\0';
7954624Schristos 	if (el_match(el->el_prog, ptr))
8054224Sbostic 	    return 0;
8154224Sbostic     }
8254224Sbostic     else
8354224Sbostic 	ptr = argv[0];
8454224Sbostic 
8554224Sbostic     for (i = 0; cmds[i].name != NULL; i++)
8654224Sbostic 	if (strcmp(cmds[i].name, ptr) == 0) {
8754224Sbostic 	    i = (*cmds[i].func)(el, argc, argv);
8854224Sbostic 	    return -i;
8954224Sbostic 	}
9054224Sbostic 
9154224Sbostic     return -1;
9254224Sbostic }
9354224Sbostic 
9454224Sbostic 
9554224Sbostic /* parse__escape():
9654224Sbostic  *	Parse a string of the form ^<char> \<odigit> \<char> and return
9754224Sbostic  *	the appropriate character or -1 if the escape is not valid
9854224Sbostic  */
9954224Sbostic protected int
parse__escape(ptr)10054224Sbostic parse__escape(ptr)
10154224Sbostic     const char  ** const ptr;
10254224Sbostic {
10354224Sbostic     const char   *p;
10454224Sbostic     int   c;
10554224Sbostic 
10654224Sbostic     p = *ptr;
10754224Sbostic 
10854224Sbostic     if (p[1] == 0)
10954224Sbostic 	return -1;
11054224Sbostic 
11154224Sbostic     if (*p == '\\') {
11254224Sbostic 	p++;
11354224Sbostic 	switch (*p) {
11454224Sbostic 	case 'a':
11554224Sbostic 	    c = '\007';		/* Bell */
11654224Sbostic 	    break;
11754224Sbostic 	case 'b':
11854224Sbostic 	    c = '\010';		/* Backspace */
11954224Sbostic 	    break;
12054224Sbostic 	case 't':
12154224Sbostic 	    c = '\011';		/* Horizontal Tab */
12254224Sbostic 	    break;
12354224Sbostic 	case 'n':
12454224Sbostic 	    c = '\012';		/* New Line */
12554224Sbostic 	    break;
12654224Sbostic 	case 'v':
12754224Sbostic 	    c = '\013';		/* Vertical Tab */
12854224Sbostic 	    break;
12954224Sbostic 	case 'f':
13054224Sbostic 	    c = '\014';		/* Form Feed */
13154224Sbostic 	    break;
13254224Sbostic 	case 'r':
13354224Sbostic 	    c = '\015';		/* Carriage Return */
13454224Sbostic 	    break;
13554224Sbostic 	case 'e':
13654224Sbostic 	    c = '\033';		/* Escape */
13754224Sbostic 	    break;
13854224Sbostic 	case '0':
13954224Sbostic 	case '1':
14054224Sbostic 	case '2':
14154224Sbostic 	case '3':
14254224Sbostic 	case '4':
14354224Sbostic 	case '5':
14454224Sbostic 	case '6':
14554224Sbostic 	case '7':
14654224Sbostic 	    {
14754224Sbostic 		int cnt, ch;
14854224Sbostic 
14954224Sbostic 		for (cnt = 0, c = 0; cnt < 3; cnt++) {
15054224Sbostic 		    ch = *p++;
15154224Sbostic 		    if (ch < '0' || ch > '7') {
15254224Sbostic 			p--;
15354224Sbostic 			break;
15454224Sbostic 		    }
15554224Sbostic 		    c = (c << 3) | (ch - '0');
15654224Sbostic 		}
15754224Sbostic 		if ((c & 0xffffff00) != 0)
15854224Sbostic 		    return -1;
15954224Sbostic 		--p;
16054224Sbostic 	    }
16154224Sbostic 	    break;
16254224Sbostic 	default:
16354224Sbostic 	    c = *p;
16454224Sbostic 	    break;
16554224Sbostic 	}
16654224Sbostic     }
16754624Schristos     else if (*p == '^' && isalpha((unsigned char) *p)) {
16854224Sbostic 	p++;
16954224Sbostic 	c = (*p == '?') ? '\177' : (*p & 0237);
17054224Sbostic     }
17154224Sbostic     else
17254224Sbostic 	c = *p;
17354224Sbostic     *ptr = ++p;
17454224Sbostic     return c;
17554224Sbostic }
17654224Sbostic 
17754224Sbostic /* parse__string():
17854224Sbostic  *	Parse the escapes from in and put the raw string out
17954224Sbostic  */
18054224Sbostic protected char *
parse__string(out,in)18154224Sbostic parse__string(out, in)
18254224Sbostic     char *out;
18354224Sbostic     const char *in;
18454224Sbostic {
18554224Sbostic     char *rv = out;
18654224Sbostic     int n;
18754224Sbostic     for (;;)
18854224Sbostic 	switch (*in) {
18954224Sbostic 	case '\0':
19054224Sbostic 	    *out = '\0';
19154224Sbostic 	    return rv;
19254224Sbostic 
19354224Sbostic 	case '\\':
19454224Sbostic 	case '^':
19554224Sbostic 	    if ((n = parse__escape(&in)) == -1)
19654224Sbostic 		return NULL;
19754224Sbostic 	    *out++ = n;
19854224Sbostic 	    break;
19954224Sbostic 
20054224Sbostic 	default:
20154224Sbostic 	    *out++ = *in++;
20254224Sbostic 	    break;
20354224Sbostic 	}
20454224Sbostic }
20554224Sbostic 
20654224Sbostic /* parse_cmd():
20754224Sbostic  *	Return the command number for the command string given
20854224Sbostic  *	or -1 if one is not found
20954224Sbostic  */
21054224Sbostic protected int
parse_cmd(el,cmd)21154224Sbostic parse_cmd(el, cmd)
21254224Sbostic     EditLine *el;
21354224Sbostic     const char *cmd;
21454224Sbostic {
21554224Sbostic     el_bindings_t *b;
21654224Sbostic 
21754224Sbostic     for (b = el->el_map.help; b->name != NULL; b++)
21854224Sbostic 	if (strcmp(b->name, cmd) == 0)
21954224Sbostic 	    return b->func;
22054224Sbostic     return -1;
22154224Sbostic }
222