db_input.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /* $OpenBSD: db_input.c,v 1.14 2015/03/14 03:38:46 jsg Exp $ */
  2. /* $NetBSD: db_input.c,v 1.7 1996/02/05 01:57:02 christos Exp $ */
  3. /*
  4. * Mach Operating System
  5. * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
  6. * All Rights Reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  15. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  16. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  17. *
  18. * Carnegie Mellon requests users of this software to return to
  19. *
  20. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  21. * School of Computer Science
  22. * Carnegie Mellon University
  23. * Pittsburgh PA 15213-3890
  24. *
  25. * any improvements or extensions that they make and grant Carnegie Mellon
  26. * the rights to redistribute these changes.
  27. *
  28. * Author: David B. Golub, Carnegie Mellon University
  29. * Date: 7/90
  30. */
  31. #include <sys/param.h>
  32. #include <sys/systm.h>
  33. #include <machine/db_machdep.h>
  34. #include <ddb/db_var.h>
  35. #include <ddb/db_output.h>
  36. #include <ddb/db_sym.h>
  37. #include <ddb/db_extern.h>
  38. #include <dev/cons.h>
  39. /*
  40. * Character input and editing.
  41. */
  42. /*
  43. * We don't track output position while editing input,
  44. * since input always ends with a new-line. We just
  45. * reset the line position at the end.
  46. */
  47. char * db_lbuf_start; /* start of input line buffer */
  48. char * db_lbuf_end; /* end of input line buffer */
  49. char * db_lc; /* current character */
  50. char * db_le; /* one past last character */
  51. #if DB_HISTORY_SIZE != 0
  52. char db_history[DB_HISTORY_SIZE]; /* start of history buffer */
  53. int db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
  54. char * db_history_curr = db_history; /* start of current line */
  55. char * db_history_last = db_history; /* start of last line */
  56. char * db_history_prev = (char *) 0; /* start of previous line */
  57. #endif
  58. #define CTRL(c) ((c) & 0x1f)
  59. #define isspace(c) ((c) == ' ' || (c) == '\t')
  60. #define BLANK ' '
  61. #define BACKUP '\b'
  62. void
  63. db_putstring(char *s, int count)
  64. {
  65. while (--count >= 0)
  66. cnputc(*s++);
  67. }
  68. void
  69. db_putnchars(int c, int count)
  70. {
  71. while (--count >= 0)
  72. cnputc(c);
  73. }
  74. /*
  75. * Delete N characters, forward or backward
  76. */
  77. #define DEL_FWD 0
  78. #define DEL_BWD 1
  79. void
  80. db_delete(int n, int bwd)
  81. {
  82. char *p;
  83. if (bwd) {
  84. db_lc -= n;
  85. db_putnchars(BACKUP, n);
  86. }
  87. for (p = db_lc; p < db_le-n; p++) {
  88. *p = *(p+n);
  89. cnputc(*p);
  90. }
  91. db_putnchars(BLANK, n);
  92. db_putnchars(BACKUP, db_le - db_lc);
  93. db_le -= n;
  94. }
  95. void
  96. db_delete_line(void)
  97. {
  98. db_delete(db_le - db_lc, DEL_FWD);
  99. db_delete(db_lc - db_lbuf_start, DEL_BWD);
  100. db_le = db_lc = db_lbuf_start;
  101. }
  102. #if DB_HISTORY_SIZE != 0
  103. #define INC_DB_CURR() \
  104. do { \
  105. db_history_curr++; \
  106. if (db_history_curr > \
  107. db_history + db_history_size - 1) \
  108. db_history_curr = db_history; \
  109. } while (0)
  110. #define DEC_DB_CURR() \
  111. do { \
  112. db_history_curr--; \
  113. if (db_history_curr < db_history) \
  114. db_history_curr = db_history + \
  115. db_history_size - 1; \
  116. } while (0)
  117. #endif
  118. /* returns TRUE at end-of-line */
  119. int
  120. db_inputchar(int c)
  121. {
  122. switch (c) {
  123. case CTRL('b'):
  124. /* back up one character */
  125. if (db_lc > db_lbuf_start) {
  126. cnputc(BACKUP);
  127. db_lc--;
  128. }
  129. break;
  130. case CTRL('f'):
  131. /* forward one character */
  132. if (db_lc < db_le) {
  133. cnputc(*db_lc);
  134. db_lc++;
  135. }
  136. break;
  137. case CTRL('a'):
  138. /* beginning of line */
  139. while (db_lc > db_lbuf_start) {
  140. cnputc(BACKUP);
  141. db_lc--;
  142. }
  143. break;
  144. case CTRL('e'):
  145. /* end of line */
  146. while (db_lc < db_le) {
  147. cnputc(*db_lc);
  148. db_lc++;
  149. }
  150. break;
  151. case CTRL('w'):
  152. /* erase word back */
  153. while (db_lc > db_lbuf_start && db_lc[-1] != BLANK)
  154. db_delete(1, DEL_BWD);
  155. break;
  156. case CTRL('h'):
  157. case 0177:
  158. /* erase previous character */
  159. if (db_lc > db_lbuf_start)
  160. db_delete(1, DEL_BWD);
  161. break;
  162. case CTRL('d'):
  163. /* erase next character */
  164. if (db_lc < db_le)
  165. db_delete(1, DEL_FWD);
  166. break;
  167. case CTRL('k'):
  168. /* delete to end of line */
  169. if (db_lc < db_le)
  170. db_delete(db_le - db_lc, DEL_FWD);
  171. break;
  172. case CTRL('u'):
  173. /* delete line */
  174. db_delete_line();
  175. break;
  176. case CTRL('t'):
  177. /* twiddle last 2 characters */
  178. if (db_lc >= db_lbuf_start + 2) {
  179. c = db_lc[-2];
  180. db_lc[-2] = db_lc[-1];
  181. db_lc[-1] = c;
  182. cnputc(BACKUP);
  183. cnputc(BACKUP);
  184. cnputc(db_lc[-2]);
  185. cnputc(db_lc[-1]);
  186. }
  187. break;
  188. #if DB_HISTORY_SIZE != 0
  189. case CTRL('p'):
  190. DEC_DB_CURR();
  191. while (db_history_curr != db_history_last) {
  192. DEC_DB_CURR();
  193. if (*db_history_curr == '\0')
  194. break;
  195. }
  196. db_delete_line();
  197. if (db_history_curr == db_history_last) {
  198. INC_DB_CURR();
  199. db_le = db_lc = db_lbuf_start;
  200. } else {
  201. char *p;
  202. INC_DB_CURR();
  203. for (p = db_history_curr, db_le = db_lbuf_start;*p; ) {
  204. *db_le++ = *p++;
  205. if (p == db_history + db_history_size)
  206. p = db_history;
  207. }
  208. db_lc = db_le;
  209. }
  210. db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  211. break;
  212. case CTRL('n'):
  213. while (db_history_curr != db_history_last) {
  214. if (*db_history_curr == '\0')
  215. break;
  216. INC_DB_CURR();
  217. }
  218. if (db_history_curr != db_history_last) {
  219. INC_DB_CURR();
  220. db_delete_line();
  221. if (db_history_curr != db_history_last) {
  222. char *p;
  223. for (p = db_history_curr,
  224. db_le = db_lbuf_start; *p;) {
  225. *db_le++ = *p++;
  226. if (p == db_history + db_history_size)
  227. p = db_history;
  228. }
  229. db_lc = db_le;
  230. }
  231. db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  232. }
  233. break;
  234. #endif
  235. case CTRL('r'):
  236. db_putstring("^R\n", 3);
  237. if (db_le > db_lbuf_start) {
  238. db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  239. db_putnchars(BACKUP, db_le - db_lc);
  240. }
  241. break;
  242. case '\n':
  243. case '\r':
  244. #if DB_HISTORY_SIZE != 0
  245. /*
  246. * Check whether current line is the same
  247. * as previous saved line. If it is, don`t
  248. * save it.
  249. */
  250. if (db_history_curr == db_history_prev) {
  251. char *pp, *pc;
  252. /*
  253. * Is it the same?
  254. */
  255. for (pp = db_history_prev, pc = db_lbuf_start;
  256. pc != db_le && *pp; ) {
  257. if (*pp != *pc)
  258. break;
  259. if (++pp == db_history + db_history_size)
  260. pp = db_history;
  261. pc++;
  262. }
  263. if (!*pp && pc == db_le) {
  264. /*
  265. * Repeated previous line. Don`t save.
  266. */
  267. db_history_curr = db_history_last;
  268. *db_le++ = c;
  269. return TRUE;
  270. }
  271. }
  272. if (db_le != db_lbuf_start) {
  273. char *p;
  274. db_history_prev = db_history_last;
  275. for (p = db_lbuf_start; p != db_le; p++) {
  276. *db_history_last++ = *p;
  277. if (db_history_last ==
  278. db_history + db_history_size)
  279. db_history_last = db_history;
  280. }
  281. *db_history_last++ = '\0';
  282. }
  283. db_history_curr = db_history_last;
  284. #endif
  285. *db_le++ = c;
  286. return TRUE;
  287. default:
  288. if (db_le == db_lbuf_end) {
  289. cnputc('\007');
  290. }
  291. else if (c >= ' ' && c <= '~') {
  292. char *p;
  293. for (p = db_le; p > db_lc; p--)
  294. *p = *(p-1);
  295. *db_lc++ = c;
  296. db_le++;
  297. cnputc(c);
  298. db_putstring(db_lc, db_le - db_lc);
  299. db_putnchars(BACKUP, db_le - db_lc);
  300. }
  301. break;
  302. }
  303. return FALSE;
  304. }
  305. int
  306. db_readline(char *lstart, int lsize)
  307. {
  308. db_force_whitespace(); /* synch output position */
  309. db_lbuf_start = lstart;
  310. db_lbuf_end = lstart + lsize - 1;
  311. db_lc = lstart;
  312. db_le = lstart;
  313. while (!db_inputchar(cngetc()))
  314. continue;
  315. db_putchar('\n'); /* synch output position */
  316. *db_le = 0;
  317. return (db_le - db_lbuf_start);
  318. }