parse.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* $NetBSD: parse.c,v 1.15 2002/03/18 16:00:56 christos Exp $ */
  2. /*-
  3. * Copyright (c) 1992, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Christos Zoulas of Cornell University.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the University of
  20. * California, Berkeley and its contributors.
  21. * 4. Neither the name of the University nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. */
  37. #include "config.h"
  38. #if !defined(lint) && !defined(SCCSID)
  39. #if 0
  40. static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
  41. #else
  42. __RCSID("$NetBSD: parse.c,v 1.15 2002/03/18 16:00:56 christos Exp $");
  43. #endif
  44. #endif /* not lint && not SCCSID */
  45. /*
  46. * parse.c: parse an editline extended command
  47. *
  48. * commands are:
  49. *
  50. * bind
  51. * echotc
  52. * edit
  53. * gettc
  54. * history
  55. * settc
  56. * setty
  57. */
  58. #include "el.h"
  59. #include "tokenizer.h"
  60. #include <stdlib.h>
  61. private const struct {
  62. const char *name;
  63. int (*func)(EditLine *, int, const char **);
  64. } cmds[] = {
  65. { "bind", map_bind },
  66. { "echotc", term_echotc },
  67. { "edit", el_editmode },
  68. { "history", hist_list },
  69. { "telltc", term_telltc },
  70. { "settc", term_settc },
  71. { "setty", tty_stty },
  72. { NULL, NULL }
  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. Tokenizer *tok;
  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. /* el_parse():
  90. * Command dispatcher
  91. */
  92. public int
  93. el_parse(EditLine *el, int argc, const char *argv[])
  94. {
  95. const char *ptr;
  96. int i;
  97. if (argc < 1)
  98. return (-1);
  99. ptr = strchr(argv[0], ':');
  100. if (ptr != NULL) {
  101. char *tprog;
  102. size_t l;
  103. if (ptr == argv[0])
  104. return (0);
  105. l = ptr - argv[0] - 1;
  106. tprog = (char *) el_malloc(l + 1);
  107. if (tprog == NULL)
  108. return (0);
  109. (void) strncpy(tprog, argv[0], l);
  110. tprog[l] = '\0';
  111. ptr++;
  112. l = el_match(el->el_prog, tprog);
  113. el_free(tprog);
  114. if (!l)
  115. return (0);
  116. } else
  117. ptr = argv[0];
  118. for (i = 0; cmds[i].name != NULL; i++)
  119. if (strcmp(cmds[i].name, ptr) == 0) {
  120. i = (*cmds[i].func) (el, argc, argv);
  121. return (-i);
  122. }
  123. return (-1);
  124. }
  125. /* parse__escape():
  126. * Parse a string of the form ^<char> \<odigit> \<char> and return
  127. * the appropriate character or -1 if the escape is not valid
  128. */
  129. protected int
  130. parse__escape(const char **const ptr)
  131. {
  132. const char *p;
  133. int c;
  134. p = *ptr;
  135. if (p[1] == 0)
  136. return (-1);
  137. if (*p == '\\') {
  138. p++;
  139. switch (*p) {
  140. case 'a':
  141. c = '\007'; /* Bell */
  142. break;
  143. case 'b':
  144. c = '\010'; /* Backspace */
  145. break;
  146. case 't':
  147. c = '\011'; /* Horizontal Tab */
  148. break;
  149. case 'n':
  150. c = '\012'; /* New Line */
  151. break;
  152. case 'v':
  153. c = '\013'; /* Vertical Tab */
  154. break;
  155. case 'f':
  156. c = '\014'; /* Form Feed */
  157. break;
  158. case 'r':
  159. c = '\015'; /* Carriage Return */
  160. break;
  161. case 'e':
  162. c = '\033'; /* Escape */
  163. break;
  164. case '0':
  165. case '1':
  166. case '2':
  167. case '3':
  168. case '4':
  169. case '5':
  170. case '6':
  171. case '7':
  172. {
  173. int cnt, ch;
  174. for (cnt = 0, c = 0; cnt < 3; cnt++) {
  175. ch = *p++;
  176. if (ch < '0' || ch > '7') {
  177. p--;
  178. break;
  179. }
  180. c = (c << 3) | (ch - '0');
  181. }
  182. if ((c & 0xffffff00) != 0)
  183. return (-1);
  184. --p;
  185. break;
  186. }
  187. default:
  188. c = *p;
  189. break;
  190. }
  191. } else if (*p == '^' && isalpha((unsigned char) p[1])) {
  192. p++;
  193. c = (*p == '?') ? '\177' : (*p & 0237);
  194. } else
  195. c = *p;
  196. *ptr = ++p;
  197. return (c);
  198. }
  199. /* parse__string():
  200. * Parse the escapes from in and put the raw string out
  201. */
  202. protected char *
  203. parse__string(char *out, const char *in)
  204. {
  205. char *rv = out;
  206. int n;
  207. for (;;)
  208. switch (*in) {
  209. case '\0':
  210. *out = '\0';
  211. return (rv);
  212. case '\\':
  213. case '^':
  214. if ((n = parse__escape(&in)) == -1)
  215. return (NULL);
  216. *out++ = n;
  217. break;
  218. default:
  219. *out++ = *in++;
  220. break;
  221. }
  222. }
  223. /* parse_cmd():
  224. * Return the command number for the command string given
  225. * or -1 if one is not found
  226. */
  227. protected int
  228. parse_cmd(EditLine *el, const char *cmd)
  229. {
  230. el_bindings_t *b;
  231. for (b = el->el_map.help; b->name != NULL; b++)
  232. if (strcmp(b->name, cmd) == 0)
  233. return (b->func);
  234. return (-1);
  235. }