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