MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
parse.c
1 /* $NetBSD: parse.c,v 1.26 2011/08/16 16:25:15 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1992, 1993
5  * The Regents of the University of California. All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell University.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
39 #else
40 #endif
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  * edit
51  * gettc
52  * history
53  * settc
54  * setty
55  */
56 #include "el.h"
57 #include <stdlib.h>
58 
59 private const struct {
60  const Char *name;
61  int (*func)(EditLine *, int, const Char **);
62 } cmds[] = {
63  { STR("bind"), map_bind },
64  { STR("echotc"), terminal_echotc },
65  { STR("edit"), el_editmode },
66  { STR("history"), hist_command },
67  { STR("telltc"), terminal_telltc },
68  { STR("settc"), terminal_settc },
69  { STR("setty"), tty_stty },
70  { NULL, NULL }
71 };
72 
73 
74 /* parse_line():
75  * Parse a line and dispatch it
76  */
77 protected int
78 parse_line(EditLine *el, const Char *line)
79 {
80  const Char **argv;
81  int argc;
82  TYPE(Tokenizer) *tok;
83 
84  tok = FUN(tok,init)(NULL);
85  FUN(tok,str)(tok, line, &argc, &argv);
86  argc = FUN(el,parse)(el, argc, argv);
87  FUN(tok,end)(tok);
88  return argc;
89 }
90 
91 
92 /* el_parse():
93  * Command dispatcher
94  */
95 public int
96 FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
97 {
98  const Char *ptr;
99  int i;
100 
101  if (argc < 1)
102  return -1;
103  ptr = Strchr(argv[0], ':');
104  if (ptr != NULL) {
105  Char *tprog;
106  size_t l;
107 
108  if (ptr == argv[0])
109  return 0;
110  l = (size_t)(ptr - argv[0] - 1);
111  tprog = el_malloc((l + 1) * sizeof(*tprog));
112  if (tprog == NULL)
113  return 0;
114  (void) Strncpy(tprog, argv[0], l);
115  tprog[l] = '\0';
116  ptr++;
117  l = (size_t)el_match(el->el_prog, tprog);
118  el_free(tprog);
119  if (!l)
120  return 0;
121  } else
122  ptr = argv[0];
123 
124  for (i = 0; cmds[i].name != NULL; i++)
125  if (Strcmp(cmds[i].name, ptr) == 0) {
126  i = (*cmds[i].func) (el, argc, argv);
127  return -i;
128  }
129  return -1;
130 }
131 
132 
133 /* parse__escape():
134  * Parse a string of the form ^<char> <odigit> <char> \U+xxxx and return
135  * the appropriate character or -1 if the escape is not valid
136  */
137 protected int
138 parse__escape(const Char **ptr)
139 {
140  const Char *p;
141  Int c;
142 
143  p = *ptr;
144 
145  if (p[1] == 0)
146  return -1;
147 
148  if (*p == '\\') {
149  p++;
150  switch (*p) {
151  case 'a':
152  c = '\007'; /* Bell */
153  break;
154  case 'b':
155  c = '\010'; /* Backspace */
156  break;
157  case 't':
158  c = '\011'; /* Horizontal Tab */
159  break;
160  case 'n':
161  c = '\012'; /* New Line */
162  break;
163  case 'v':
164  c = '\013'; /* Vertical Tab */
165  break;
166  case 'f':
167  c = '\014'; /* Form Feed */
168  break;
169  case 'r':
170  c = '\015'; /* Carriage Return */
171  break;
172  case 'e':
173  c = '\033'; /* Escape */
174  break;
175  case 'U': /* Unicode \U+xxxx or \U+xxxxx format */
176  {
177  int i;
178  const Char hex[] = STR("0123456789ABCDEF");
179  const Char *h;
180  ++p;
181  if (*p++ != '+')
182  return -1;
183  c = 0;
184  for (i = 0; i < 5; ++i) {
185  h = Strchr(hex, *p++);
186  if (!h && i < 4)
187  return -1;
188  else if (h)
189  c = (c << 4) | ((int)(h - hex));
190  else
191  --p;
192  }
193  if (c > 0x10FFFF) /* outside valid character range */
194  return -1;
195  break;
196  }
197  case '0':
198  case '1':
199  case '2':
200  case '3':
201  case '4':
202  case '5':
203  case '6':
204  case '7':
205  {
206  int cnt, ch;
207 
208  for (cnt = 0, c = 0; cnt < 3; cnt++) {
209  ch = *p++;
210  if (ch < '0' || ch > '7') {
211  p--;
212  break;
213  }
214  c = (c << 3) | (ch - '0');
215  }
216  if ((c & (wint_t)0xffffff00) != (wint_t)0)
217  return -1;
218  --p;
219  break;
220  }
221  default:
222  c = *p;
223  break;
224  }
225  } else if (*p == '^') {
226  p++;
227  c = (*p == '?') ? '\177' : (*p & 0237);
228  } else
229  c = *p;
230  *ptr = ++p;
231  return c;
232 }
233 
234 /* parse__string():
235  * Parse the escapes from in and put the raw string out
236  */
237 protected Char *
238 parse__string(Char *out, const Char *in)
239 {
240  Char *rv = out;
241  int n;
242 
243  for (;;)
244  switch (*in) {
245  case '\0':
246  *out = '\0';
247  return rv;
248 
249  case '\\':
250  case '^':
251  if ((n = parse__escape(&in)) == -1)
252  return NULL;
253  *out++ = n;
254  break;
255 
256  case 'M':
257  if (in[1] == '-' && in[2] != '\0') {
258  *out++ = '\033';
259  in += 2;
260  break;
261  }
262  /*FALLTHROUGH*/
263 
264  default:
265  *out++ = *in++;
266  break;
267  }
268 }
269 
270 
271 /* parse_cmd():
272  * Return the command number for the command string given
273  * or -1 if one is not found
274  */
275 protected int
276 parse_cmd(EditLine *el, const Char *cmd)
277 {
278  el_bindings_t *b;
279 
280  for (b = el->el_map.help; b->name != NULL; b++)
281  if (Strcmp(b->name, cmd) == 0)
282  return b->func;
283  return -1;
284 }