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