* Removed the __P macros from lib/
[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  * $DragonFly: src/lib/libedit/parse.c,v 1.4 2003/11/12 20:21:29 eirikn Exp $
38  */
39
40 /*
41  * parse.c: parse an editline extended command
42  *
43  * commands are:
44  *
45  *      bind
46  *      echotc
47  *      settc
48  *      gettc
49  *      history
50  *      settc
51  *      setty
52  */
53 #include "sys.h"
54 #include "el.h"
55 #include "tokenizer.h"
56
57 private struct {
58     char *name;
59     int (*func) (EditLine *, int, char **);
60 } cmds[] = {
61     {   "bind",         map_bind        },
62     {   "echotc",       term_echotc     },
63     {   "history",      hist_list       },
64     {   "telltc",       term_telltc     },
65     {   "settc",        term_settc      },
66     {   "setty",        tty_stty        },
67     {   NULL,           NULL            }
68 };
69
70
71 /* parse_line():
72  *      Parse a line and dispatch it
73  */
74 protected int
75 parse_line(el, line)
76     EditLine *el;
77     const char *line;
78 {
79     char **argv;
80     int argc;
81     Tokenizer *tok;
82
83     tok = tok_init(NULL);
84     tok_line(tok, line, &argc, &argv);
85     argc = el_parse(el, argc, argv);
86     tok_end(tok);
87     return argc;
88 }
89
90 /* el_parse():
91  *      Command dispatcher
92  */
93 public int
94 el_parse(el, argc, argv)
95     EditLine *el;
96     int argc;
97     char *argv[];
98 {
99     char *ptr;
100     int i;
101
102     if (argc < 1)
103         return -1;
104     ptr = strchr(argv[0], ':');
105     if (ptr != NULL) {
106         *ptr++ = '\0';
107         if (! el_match(el->el_prog, argv[0]))
108             return 0;
109     }
110     else
111         ptr = argv[0];
112
113     for (i = 0; cmds[i].name != NULL; i++)
114         if (strcmp(cmds[i].name, ptr) == 0) {
115             i = (*cmds[i].func)(el, argc, argv);
116             return -i;
117         }
118
119     return -1;
120 }
121
122
123 /* parse__escape():
124  *      Parse a string of the form ^<char> \<odigit> \<char> and return
125  *      the appropriate character or -1 if the escape is not valid
126  */
127 protected int
128 parse__escape(ptr)
129     const char  ** const ptr;
130 {
131     const char   *p;
132     int   c;
133
134     p = *ptr;
135
136     if (p[1] == 0)
137         return -1;
138
139     if (*p == '\\') {
140         p++;
141         switch (*p) {
142         case 'a':
143             c = '\007';         /* Bell */
144             break;
145         case 'b':
146             c = '\010';         /* Backspace */
147             break;
148         case 't':
149             c = '\011';         /* Horizontal Tab */
150             break;
151         case 'n':
152             c = '\012';         /* New Line */
153             break;
154         case 'v':
155             c = '\013';         /* Vertical Tab */
156             break;
157         case 'f':
158             c = '\014';         /* Form Feed */
159             break;
160         case 'r':
161             c = '\015';         /* Carriage Return */
162             break;
163         case 'e':
164             c = '\033';         /* Escape */
165             break;
166         case '0':
167         case '1':
168         case '2':
169         case '3':
170         case '4':
171         case '5':
172         case '6':
173         case '7':
174             {
175                 int cnt, ch;
176
177                 for (cnt = 0, c = 0; cnt < 3; cnt++) {
178                     ch = *p++;
179                     if (ch < '0' || ch > '7') {
180                         p--;
181                         break;
182                     }
183                     c = (c << 3) | (ch - '0');
184                 }
185                 if ((c & 0xffffff00) != 0)
186                     return -1;
187                 --p;
188             }
189             break;
190         default:
191             c = *p;
192             break;
193         }
194     }
195     else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1]))) {
196         p++;
197         c = (*p == '?') ? '\177' : (*p & 0237);
198     }
199     else
200         c = *p;
201     *ptr = ++p;
202     return (unsigned char)c;
203 }
204
205 /* parse__string():
206  *      Parse the escapes from in and put the raw string out
207  */
208 protected char *
209 parse__string(out, in)
210     char *out;
211     const char *in;
212 {
213     char *rv = out;
214     int n;
215     for (;;)
216         switch (*in) {
217         case '\0':
218             *out = '\0';
219             return rv;
220
221         case '\\':
222         case '^':
223             if ((n = parse__escape(&in)) == -1)
224                 return NULL;
225             *out++ = n;
226             break;
227
228         default:
229             *out++ = *in++;
230             break;
231         }
232 }
233
234 /* parse_cmd():
235  *      Return the command number for the command string given
236  *      or -1 if one is not found
237  */
238 protected int
239 parse_cmd(el, cmd)
240     EditLine *el;
241     const char *cmd;
242 {
243     el_bindings_t *b;
244
245     for (b = el->el_map.help; b->name != NULL; b++)
246         if (strcmp(b->name, cmd) == 0)
247             return b->func;
248     return -1;
249 }