new libedit: Silence -Wold-style-definition
[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. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * @(#)parse.c  8.1 (Berkeley) 6/4/93
33  * $NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $
34  * $DragonFly: src/lib/libedit/parse.c,v 1.5 2005/11/13 11:58:30 corecode Exp $
35  */
36
37 #include "config.h"
38
39 /*
40  * parse.c: parse an editline extended command
41  *
42  * commands are:
43  *
44  *      bind
45  *      echotc
46  *      edit
47  *      gettc
48  *      history
49  *      settc
50  *      setty
51  */
52 #include "el.h"
53 #include <stdlib.h>
54
55 private const struct {
56         const char *name;
57         int (*func)(EditLine *, int, const char **);
58 } cmds[] = {
59         { "bind",       map_bind        },
60         { "echotc",     term_echotc     },
61         { "edit",       el_editmode     },
62         { "history",    hist_command    },
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(EditLine *el, const char *line)
75 {
76         const char **argv;
77         int argc;
78         Tokenizer *tok;
79
80         tok = tok_init(NULL);
81         tok_str(tok, line, &argc, &argv);
82         argc = el_parse(el, argc, argv);
83         tok_end(tok);
84         return (argc);
85 }
86
87
88 /* el_parse():
89  *      Command dispatcher
90  */
91 public int
92 el_parse(EditLine *el, int argc, const char *argv[])
93 {
94         const char *ptr;
95         int i;
96
97         if (argc < 1)
98                 return (-1);
99         ptr = strchr(argv[0], ':');
100         if (ptr != NULL) {
101                 char *tprog;
102                 size_t l;
103
104                 if (ptr == argv[0])
105                         return (0);
106                 l = ptr - argv[0] - 1;
107                 tprog = (char *) el_malloc(l + 1);
108                 if (tprog == NULL)
109                         return (0);
110                 (void) strncpy(tprog, argv[0], l);
111                 tprog[l] = '\0';
112                 ptr++;
113                 l = el_match(el->el_prog, tprog);
114                 el_free(tprog);
115                 if (!l)
116                         return (0);
117         } else
118                 ptr = argv[0];
119
120         for (i = 0; cmds[i].name != NULL; i++)
121                 if (strcmp(cmds[i].name, ptr) == 0) {
122                         i = (*cmds[i].func) (el, argc, argv);
123                         return (-i);
124                 }
125         return (-1);
126 }
127
128
129 /* parse__escape():
130  *      Parse a string of the form ^<char> \<odigit> \<char> and return
131  *      the appropriate character or -1 if the escape is not valid
132  */
133 protected int
134 parse__escape(const char **ptr)
135 {
136         const char *p;
137         int c;
138
139         p = *ptr;
140
141         if (p[1] == 0)
142                 return (-1);
143
144         if (*p == '\\') {
145                 p++;
146                 switch (*p) {
147                 case 'a':
148                         c = '\007';     /* Bell */
149                         break;
150                 case 'b':
151                         c = '\010';     /* Backspace */
152                         break;
153                 case 't':
154                         c = '\011';     /* Horizontal Tab */
155                         break;
156                 case 'n':
157                         c = '\012';     /* New Line */
158                         break;
159                 case 'v':
160                         c = '\013';     /* Vertical Tab */
161                         break;
162                 case 'f':
163                         c = '\014';     /* Form Feed */
164                         break;
165                 case 'r':
166                         c = '\015';     /* Carriage Return */
167                         break;
168                 case 'e':
169                         c = '\033';     /* Escape */
170                         break;
171                 case '0':
172                 case '1':
173                 case '2':
174                 case '3':
175                 case '4':
176                 case '5':
177                 case '6':
178                 case '7':
179                 {
180                         int cnt, ch;
181
182                         for (cnt = 0, c = 0; cnt < 3; cnt++) {
183                                 ch = *p++;
184                                 if (ch < '0' || ch > '7') {
185                                         p--;
186                                         break;
187                                 }
188                                 c = (c << 3) | (ch - '0');
189                         }
190                         if ((c & 0xffffff00) != 0)
191                                 return (-1);
192                         --p;
193                         break;
194                 }
195                 default:
196                         c = *p;
197                         break;
198                 }
199         } else if (*p == '^') {
200                 p++;
201                 c = (*p == '?') ? '\177' : (*p & 0237);
202         } else
203                 c = *p;
204         *ptr = ++p;
205         return (c);
206 }
207
208 /* parse__string():
209  *      Parse the escapes from in and put the raw string out
210  */
211 protected char *
212 parse__string(char *out, const char *in)
213 {
214         char *rv = out;
215         int n;
216
217         for (;;)
218                 switch (*in) {
219                 case '\0':
220                         *out = '\0';
221                         return (rv);
222
223                 case '\\':
224                 case '^':
225                         if ((n = parse__escape(&in)) == -1)
226                                 return (NULL);
227                         *out++ = n;
228                         break;
229
230                 case 'M':
231                         if (in[1] == '-' && in[2] != '\0') {
232                                 *out++ = '\033';
233                                 in += 2;
234                                 break;
235                         }
236                         /*FALLTHROUGH*/
237
238                 default:
239                         *out++ = *in++;
240                         break;
241                 }
242 }
243
244
245 /* parse_cmd():
246  *      Return the command number for the command string given
247  *      or -1 if one is not found
248  */
249 protected int
250 parse_cmd(EditLine *el, const char *cmd)
251 {
252         el_bindings_t *b;
253
254         for (b = el->el_map.help; b->name != NULL; b++)
255                 if (strcmp(b->name, cmd) == 0)
256                         return (b->func);
257         return (-1);
258 }