1/* $NetBSD: parse.c,v 1.6 2005/06/09 16:48:58 lukem Exp $ */ 2/* from NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp */ 3 4/*- 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Christos Zoulas of Cornell University. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "tnftp.h" 37#include "sys.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 55private 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 */ 73protected int 74parse_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 */ 91public int 92el_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 */ 133protected int 134parse__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 */ 211protected char * 212parse__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 */ 249protected int 250parse_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} 259