Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / lib / libedit / parse.c
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)parse.c  8.1 (Berkeley) 6/4/93
37  */
38
39 /*
40  * parse.c: parse an editline extended command
41  *
42  * commands are:
43  *
44  *      bind
45  *      echotc
46  *      settc
47  *      gettc
48  *      history
49  *      settc
50  *      setty
51  */
52 #include "sys.h"
53 #include "el.h"
54 #include "tokenizer.h"
55
56 private struct {
57     char *name;
58     int (*func) __P((EditLine *, int, char **));
59 } cmds[] = {
60     {   "bind",         map_bind        },
61     {   "echotc",       term_echotc     },
62     {   "history",      hist_list       },
63     {   "telltc",       term_telltc     },
64     {   "settc",        term_settc      },
65     {   "setty",        tty_stty        },
66     {   NULL,           NULL            }
67 };
68
69
70 /* parse_line():
71  *      Parse a line and dispatch it
72  */
73 protected int
74 parse_line(el, line)
75     EditLine *el;
76     const char *line;
77 {
78     char **argv;
79     int argc;
80     Tokenizer *tok;
81
82     tok = tok_init(NULL);
83     tok_line(tok, line, &argc, &argv);
84     argc = el_parse(el, argc, argv);
85     tok_end(tok);
86     return argc;
87 }
88
89 /* el_parse():
90  *      Command dispatcher
91  */
92 public int
93 el_parse(el, argc, argv)
94     EditLine *el;
95     int argc;
96     char *argv[];
97 {
98     char *ptr;
99     int i;
100
101     if (argc < 1)
102         return -1;
103     ptr = strchr(argv[0], ':');
104     if (ptr != NULL) {
105         *ptr++ = '\0';
106         if (! el_match(el->el_prog, argv[0]))
107             return 0;
108     }
109     else
110         ptr = argv[0];
111
112     for (i = 0; cmds[i].name != NULL; i++)
113         if (strcmp(cmds[i].name, ptr) == 0) {
114             i = (*cmds[i].func)(el, argc, argv);
115             return -i;
116         }
117
118     return -1;
119 }
120
121
122 /* parse__escape():
123  *      Parse a string of the form ^<char> \<odigit> \<char> and return
124  *      the appropriate character or -1 if the escape is not valid
125  */
126 protected int
127 parse__escape(ptr)
128     const char  ** const ptr;
129 {
130     const char   *p;
131     int   c;
132
133     p = *ptr;
134
135     if (p[1] == 0)
136         return -1;
137
138     if (*p == '\\') {
139         p++;
140         switch (*p) {
141         case 'a':
142             c = '\007';         /* Bell */
143             break;
144         case 'b':
145             c = '\010';         /* Backspace */
146             break;
147         case 't':
148             c = '\011';         /* Horizontal Tab */
149             break;
150         case 'n':
151             c = '\012';         /* New Line */
152             break;
153         case 'v':
154             c = '\013';         /* Vertical Tab */
155             break;
156         case 'f':
157             c = '\014';         /* Form Feed */
158             break;
159         case 'r':
160             c = '\015';         /* Carriage Return */
161             break;
162         case 'e':
163             c = '\033';         /* Escape */
164             break;
165         case '0':
166         case '1':
167         case '2':
168         case '3':
169         case '4':
170         case '5':
171         case '6':
172         case '7':
173             {
174                 int cnt, ch;
175
176                 for (cnt = 0, c = 0; cnt < 3; cnt++) {
177                     ch = *p++;
178                     if (ch < '0' || ch > '7') {
179                         p--;
180                         break;
181                     }
182                     c = (c << 3) | (ch - '0');
183                 }
184                 if ((c & 0xffffff00) != 0)
185                     return -1;
186                 --p;
187             }
188             break;
189         default:
190             c = *p;
191             break;
192         }
193     }
194     else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1]))) {
195         p++;
196         c = (*p == '?') ? '\177' : (*p & 0237);
197     }
198     else
199         c = *p;
200     *ptr = ++p;
201     return (unsigned char)c;
202 }
203
204 /* parse__string():
205  *      Parse the escapes from in and put the raw string out
206  */
207 protected char *
208 parse__string(out, in)
209     char *out;
210     const char *in;
211 {
212     char *rv = out;
213     int n;
214     for (;;)
215         switch (*in) {
216         case '\0':
217             *out = '\0';
218             return rv;
219
220         case '\\':
221         case '^':
222             if ((n = parse__escape(&in)) == -1)
223                 return NULL;
224             *out++ = n;
225             break;
226
227         default:
228             *out++ = *in++;
229             break;
230         }
231 }
232
233 /* parse_cmd():
234  *      Return the command number for the command string given
235  *      or -1 if one is not found
236  */
237 protected int
238 parse_cmd(el, cmd)
239     EditLine *el;
240     const char *cmd;
241 {
242     el_bindings_t *b;
243
244     for (b = el->el_map.help; b->name != NULL; b++)
245         if (strcmp(b->name, cmd) == 0)
246             return b->func;
247     return -1;
248 }