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