xref: /csrg-svn/lib/libedit/parse.c (revision 54224)
1*54224Sbostic /*-
2*54224Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*54224Sbostic  * All rights reserved.
4*54224Sbostic  *
5*54224Sbostic  * This code is derived from software contributed to Berkeley by
6*54224Sbostic  * Christos Zoulas of Cornell University.
7*54224Sbostic  *
8*54224Sbostic  * %sccs.include.redist.c%
9*54224Sbostic  */
10*54224Sbostic 
11*54224Sbostic #ifndef lint
12*54224Sbostic static char sccsid[] = "@(#)parse.c	5.1 (Berkeley) 06/22/92";
13*54224Sbostic #endif /* not lint */
14*54224Sbostic 
15*54224Sbostic /*
16*54224Sbostic  * el.parse.c: parse an editline extended command
17*54224Sbostic  *
18*54224Sbostic  * commands are:
19*54224Sbostic  *
20*54224Sbostic  *	bind
21*54224Sbostic  *	echotc
22*54224Sbostic  *	settc
23*54224Sbostic  *	gettc
24*54224Sbostic  */
25*54224Sbostic #include "sys.h"
26*54224Sbostic #include "el.h"
27*54224Sbostic #include "tokenizer.h"
28*54224Sbostic 
29*54224Sbostic private struct {
30*54224Sbostic     char *name;
31*54224Sbostic     int (*func) __P((EditLine *, int, char **));
32*54224Sbostic } cmds[] = {
33*54224Sbostic     {	"bind",		map_bind 	},
34*54224Sbostic     {	"echotc",	term_echotc 	},
35*54224Sbostic     {	"history",	hist_list	},
36*54224Sbostic     {	"telltc",	term_telltc 	},
37*54224Sbostic     {	"settc",	term_settc	},
38*54224Sbostic     {	"setty",	tty_stty	},
39*54224Sbostic     {	NULL,		NULL		}
40*54224Sbostic };
41*54224Sbostic 
42*54224Sbostic 
43*54224Sbostic /* parse_line():
44*54224Sbostic  *	Parse a line and dispatch it
45*54224Sbostic  */
46*54224Sbostic protected int
47*54224Sbostic parse_line(el, line)
48*54224Sbostic     EditLine *el;
49*54224Sbostic     const char *line;
50*54224Sbostic {
51*54224Sbostic     char **argv;
52*54224Sbostic     int argc;
53*54224Sbostic     Tokenizer *tok;
54*54224Sbostic 
55*54224Sbostic     tok = tok_init(NULL);
56*54224Sbostic     tok_line(tok, line, &argc, &argv);
57*54224Sbostic     argc = el_parse(el, argc, argv);
58*54224Sbostic     tok_end(tok);
59*54224Sbostic     return argc;
60*54224Sbostic }
61*54224Sbostic 
62*54224Sbostic /* el_parse():
63*54224Sbostic  *	Command dispatcher
64*54224Sbostic  */
65*54224Sbostic public int
66*54224Sbostic el_parse(el, argc, argv)
67*54224Sbostic     EditLine *el;
68*54224Sbostic     int argc;
69*54224Sbostic     char *argv[];
70*54224Sbostic {
71*54224Sbostic     char *ptr;
72*54224Sbostic     int i;
73*54224Sbostic 
74*54224Sbostic     for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++)
75*54224Sbostic 	continue;
76*54224Sbostic 
77*54224Sbostic     if (*ptr == ':') {
78*54224Sbostic 	*ptr = '\0';
79*54224Sbostic 	if (strcmp(ptr, el->el_prog) != 0)
80*54224Sbostic 	    return 0;
81*54224Sbostic     }
82*54224Sbostic     else
83*54224Sbostic 	ptr = argv[0];
84*54224Sbostic 
85*54224Sbostic     for (i = 0; cmds[i].name != NULL; i++)
86*54224Sbostic 	if (strcmp(cmds[i].name, ptr) == 0) {
87*54224Sbostic 	    i = (*cmds[i].func)(el, argc, argv);
88*54224Sbostic 	    return -i;
89*54224Sbostic 	}
90*54224Sbostic 
91*54224Sbostic     return -1;
92*54224Sbostic }
93*54224Sbostic 
94*54224Sbostic 
95*54224Sbostic /* parse__escape():
96*54224Sbostic  *	Parse a string of the form ^<char> \<odigit> \<char> and return
97*54224Sbostic  *	the appropriate character or -1 if the escape is not valid
98*54224Sbostic  */
99*54224Sbostic protected int
100*54224Sbostic parse__escape(ptr)
101*54224Sbostic     const char  ** const ptr;
102*54224Sbostic {
103*54224Sbostic     const char   *p;
104*54224Sbostic     int   c;
105*54224Sbostic 
106*54224Sbostic     p = *ptr;
107*54224Sbostic 
108*54224Sbostic     if (p[1] == 0)
109*54224Sbostic 	return -1;
110*54224Sbostic 
111*54224Sbostic     if (*p == '\\') {
112*54224Sbostic 	p++;
113*54224Sbostic 	switch (*p) {
114*54224Sbostic 	case 'a':
115*54224Sbostic 	    c = '\007';		/* Bell */
116*54224Sbostic 	    break;
117*54224Sbostic 	case 'b':
118*54224Sbostic 	    c = '\010';		/* Backspace */
119*54224Sbostic 	    break;
120*54224Sbostic 	case 't':
121*54224Sbostic 	    c = '\011';		/* Horizontal Tab */
122*54224Sbostic 	    break;
123*54224Sbostic 	case 'n':
124*54224Sbostic 	    c = '\012';		/* New Line */
125*54224Sbostic 	    break;
126*54224Sbostic 	case 'v':
127*54224Sbostic 	    c = '\013';		/* Vertical Tab */
128*54224Sbostic 	    break;
129*54224Sbostic 	case 'f':
130*54224Sbostic 	    c = '\014';		/* Form Feed */
131*54224Sbostic 	    break;
132*54224Sbostic 	case 'r':
133*54224Sbostic 	    c = '\015';		/* Carriage Return */
134*54224Sbostic 	    break;
135*54224Sbostic 	case 'e':
136*54224Sbostic 	    c = '\033';		/* Escape */
137*54224Sbostic 	    break;
138*54224Sbostic 	case '0':
139*54224Sbostic 	case '1':
140*54224Sbostic 	case '2':
141*54224Sbostic 	case '3':
142*54224Sbostic 	case '4':
143*54224Sbostic 	case '5':
144*54224Sbostic 	case '6':
145*54224Sbostic 	case '7':
146*54224Sbostic 	    {
147*54224Sbostic 		int cnt, ch;
148*54224Sbostic 
149*54224Sbostic 		for (cnt = 0, c = 0; cnt < 3; cnt++) {
150*54224Sbostic 		    ch = *p++;
151*54224Sbostic 		    if (ch < '0' || ch > '7') {
152*54224Sbostic 			p--;
153*54224Sbostic 			break;
154*54224Sbostic 		    }
155*54224Sbostic 		    c = (c << 3) | (ch - '0');
156*54224Sbostic 		}
157*54224Sbostic 		if ((c & 0xffffff00) != 0)
158*54224Sbostic 		    return -1;
159*54224Sbostic 		--p;
160*54224Sbostic 	    }
161*54224Sbostic 	    break;
162*54224Sbostic 	default:
163*54224Sbostic 	    c = *p;
164*54224Sbostic 	    break;
165*54224Sbostic 	}
166*54224Sbostic     }
167*54224Sbostic     else if (*p == '^') {
168*54224Sbostic 	p++;
169*54224Sbostic 	c = (*p == '?') ? '\177' : (*p & 0237);
170*54224Sbostic     }
171*54224Sbostic     else
172*54224Sbostic 	c = *p;
173*54224Sbostic     *ptr = ++p;
174*54224Sbostic     return c;
175*54224Sbostic }
176*54224Sbostic 
177*54224Sbostic /* parse__string():
178*54224Sbostic  *	Parse the escapes from in and put the raw string out
179*54224Sbostic  */
180*54224Sbostic protected char *
181*54224Sbostic parse__string(out, in)
182*54224Sbostic     char *out;
183*54224Sbostic     const char *in;
184*54224Sbostic {
185*54224Sbostic     char *rv = out;
186*54224Sbostic     int n;
187*54224Sbostic     for (;;)
188*54224Sbostic 	switch (*in) {
189*54224Sbostic 	case '\0':
190*54224Sbostic 	    *out = '\0';
191*54224Sbostic 	    return rv;
192*54224Sbostic 
193*54224Sbostic 	case '\\':
194*54224Sbostic 	case '^':
195*54224Sbostic 	    if ((n = parse__escape(&in)) == -1)
196*54224Sbostic 		return NULL;
197*54224Sbostic 	    *out++ = n;
198*54224Sbostic 	    break;
199*54224Sbostic 
200*54224Sbostic 	default:
201*54224Sbostic 	    *out++ = *in++;
202*54224Sbostic 	    break;
203*54224Sbostic 	}
204*54224Sbostic }
205*54224Sbostic 
206*54224Sbostic /* parse_cmd():
207*54224Sbostic  *	Return the command number for the command string given
208*54224Sbostic  *	or -1 if one is not found
209*54224Sbostic  */
210*54224Sbostic protected int
211*54224Sbostic parse_cmd(el, cmd)
212*54224Sbostic     EditLine *el;
213*54224Sbostic     const char *cmd;
214*54224Sbostic {
215*54224Sbostic     el_bindings_t *b;
216*54224Sbostic 
217*54224Sbostic     for (b = el->el_map.help; b->name != NULL; b++)
218*54224Sbostic 	if (strcmp(b->name, cmd) == 0)
219*54224Sbostic 	    return b->func;
220*54224Sbostic     return -1;
221*54224Sbostic }
222