xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_cmdbuf.c (revision b2a1c4433264b668a6d431670aa823ba41aea68c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*b2a1c443Svb  * Common Development and Distribution License (the "License").
6*b2a1c443Svb  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*b2a1c443Svb  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * The MDB command buffer is a simple structure that keeps track of the
307c478bd9Sstevel@tonic-gate  * command history list, and provides operations to manipulate the current
317c478bd9Sstevel@tonic-gate  * buffer according to the various emacs editing options.  The terminal
327c478bd9Sstevel@tonic-gate  * code uses this code to keep track of the actual contents of the command
337c478bd9Sstevel@tonic-gate  * line, and then uses this content to perform redraw operations.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <stdio.h>
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
417c478bd9Sstevel@tonic-gate #include <mdb/mdb_cmdbuf.h>
427c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
437c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	CMDBUF_LINELEN	BUFSIZ		/* Length of each buffer line */
467c478bd9Sstevel@tonic-gate #define	CMDBUF_TABLEN	8		/* Length of a tab in spaces */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static void
497c478bd9Sstevel@tonic-gate cmdbuf_shiftr(mdb_cmdbuf_t *cmd, size_t nbytes)
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate 	bcopy(&cmd->cmd_buf[cmd->cmd_bufidx],
527c478bd9Sstevel@tonic-gate 	    &cmd->cmd_buf[cmd->cmd_bufidx + nbytes],
537c478bd9Sstevel@tonic-gate 	    cmd->cmd_buflen - cmd->cmd_bufidx);
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate 
56*b2a1c443Svb static void
57*b2a1c443Svb mdb_cmdbuf_allocchunk(mdb_cmdbuf_t *cmd)
58*b2a1c443Svb {
59*b2a1c443Svb 	int i;
60*b2a1c443Svb 	char **newhistory;
61*b2a1c443Svb 	ssize_t newhalloc = cmd->cmd_halloc + MDB_DEF_HISTLEN;
62*b2a1c443Svb 
63*b2a1c443Svb 	if (newhalloc > cmd->cmd_histlen)
64*b2a1c443Svb 		newhalloc = cmd->cmd_histlen;
65*b2a1c443Svb 	newhistory = mdb_alloc(newhalloc * sizeof (char *), UM_SLEEP);
66*b2a1c443Svb 	bcopy(cmd->cmd_history, newhistory, cmd->cmd_halloc * sizeof (char *));
67*b2a1c443Svb 	mdb_free(cmd->cmd_history, cmd->cmd_halloc * sizeof (char *));
68*b2a1c443Svb 	for (i = cmd->cmd_halloc; i < newhalloc; i++)
69*b2a1c443Svb 		newhistory[i] = mdb_alloc(CMDBUF_LINELEN, UM_SLEEP);
70*b2a1c443Svb 	cmd->cmd_history = newhistory;
71*b2a1c443Svb 	cmd->cmd_halloc = newhalloc;
72*b2a1c443Svb }
73*b2a1c443Svb 
747c478bd9Sstevel@tonic-gate void
757c478bd9Sstevel@tonic-gate mdb_cmdbuf_create(mdb_cmdbuf_t *cmd)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate 	size_t i;
787c478bd9Sstevel@tonic-gate 
79*b2a1c443Svb 	cmd->cmd_halloc = MDB_DEF_HISTLEN < mdb.m_histlen ?
80*b2a1c443Svb 	    MDB_DEF_HISTLEN : mdb.m_histlen;
81*b2a1c443Svb 
82*b2a1c443Svb 	cmd->cmd_history = mdb_alloc(cmd->cmd_halloc * sizeof (char *),
83*b2a1c443Svb 	    UM_SLEEP);
847c478bd9Sstevel@tonic-gate 	cmd->cmd_linebuf = mdb_alloc(CMDBUF_LINELEN, UM_SLEEP);
857c478bd9Sstevel@tonic-gate 
86*b2a1c443Svb 	for (i = 0; i < cmd->cmd_halloc; i++)
877c478bd9Sstevel@tonic-gate 		cmd->cmd_history[i] = mdb_alloc(CMDBUF_LINELEN, UM_SLEEP);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	cmd->cmd_buf = cmd->cmd_history[0];
907c478bd9Sstevel@tonic-gate 	cmd->cmd_linelen = CMDBUF_LINELEN;
917c478bd9Sstevel@tonic-gate 	cmd->cmd_histlen = mdb.m_histlen;
927c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = 0;
937c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
947c478bd9Sstevel@tonic-gate 	cmd->cmd_hold = 0;
957c478bd9Sstevel@tonic-gate 	cmd->cmd_hnew = 0;
967c478bd9Sstevel@tonic-gate 	cmd->cmd_hcur = 0;
977c478bd9Sstevel@tonic-gate 	cmd->cmd_hlen = 0;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate void
1017c478bd9Sstevel@tonic-gate mdb_cmdbuf_destroy(mdb_cmdbuf_t *cmd)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	size_t i;
1047c478bd9Sstevel@tonic-gate 
105*b2a1c443Svb 	for (i = 0; i < cmd->cmd_halloc; i++)
1067c478bd9Sstevel@tonic-gate 		mdb_free(cmd->cmd_history[i], CMDBUF_LINELEN);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	mdb_free(cmd->cmd_linebuf, CMDBUF_LINELEN);
109*b2a1c443Svb 	mdb_free(cmd->cmd_history, cmd->cmd_halloc * sizeof (char *));
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate int
1137c478bd9Sstevel@tonic-gate mdb_cmdbuf_caninsert(mdb_cmdbuf_t *cmd, size_t nbytes)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	return (cmd->cmd_buflen + nbytes < cmd->cmd_linelen);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate int
1197c478bd9Sstevel@tonic-gate mdb_cmdbuf_atstart(mdb_cmdbuf_t *cmd)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	return (cmd->cmd_bufidx == 0);
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate int
1257c478bd9Sstevel@tonic-gate mdb_cmdbuf_atend(mdb_cmdbuf_t *cmd)
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate 	return (cmd->cmd_bufidx == cmd->cmd_buflen);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate int
1317c478bd9Sstevel@tonic-gate mdb_cmdbuf_insert(mdb_cmdbuf_t *cmd, int c)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	if (c == '\t') {
1347c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen + CMDBUF_TABLEN < cmd->cmd_linelen) {
1357c478bd9Sstevel@tonic-gate 			int i;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 			if (cmd->cmd_buflen != cmd->cmd_bufidx)
1387c478bd9Sstevel@tonic-gate 				cmdbuf_shiftr(cmd, CMDBUF_TABLEN);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 			for (i = 0; i < CMDBUF_TABLEN; i++)
1417c478bd9Sstevel@tonic-gate 				cmd->cmd_buf[cmd->cmd_bufidx++] = ' ';
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 			cmd->cmd_buflen += CMDBUF_TABLEN;
1447c478bd9Sstevel@tonic-gate 			return (0);
1457c478bd9Sstevel@tonic-gate 		}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 		return (-1);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if (c < ' ' || c > '~')
1517c478bd9Sstevel@tonic-gate 		return (-1);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	if (cmd->cmd_buflen < cmd->cmd_linelen) {
1547c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen != cmd->cmd_bufidx)
1557c478bd9Sstevel@tonic-gate 			cmdbuf_shiftr(cmd, 1);
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 		cmd->cmd_buf[cmd->cmd_bufidx++] = (char)c;
1587c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen++;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 		return (0);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	return (-1);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate const char *
1677c478bd9Sstevel@tonic-gate mdb_cmdbuf_accept(mdb_cmdbuf_t *cmd)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx < cmd->cmd_linelen) {
1707c478bd9Sstevel@tonic-gate 		cmd->cmd_buf[cmd->cmd_buflen++] = '\0';
1717c478bd9Sstevel@tonic-gate 		(void) strcpy(cmd->cmd_linebuf, cmd->cmd_buf);
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 		/*
1747c478bd9Sstevel@tonic-gate 		 * Don't bother inserting empty buffers into the history ring.
1757c478bd9Sstevel@tonic-gate 		 */
1767c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen > 1) {
1777c478bd9Sstevel@tonic-gate 			cmd->cmd_hnew = (cmd->cmd_hnew + 1) % cmd->cmd_histlen;
178*b2a1c443Svb 			if (cmd->cmd_hnew >= cmd->cmd_halloc)
179*b2a1c443Svb 				mdb_cmdbuf_allocchunk(cmd);
180*b2a1c443Svb 
1817c478bd9Sstevel@tonic-gate 			cmd->cmd_buf = cmd->cmd_history[cmd->cmd_hnew];
1827c478bd9Sstevel@tonic-gate 			cmd->cmd_hcur = cmd->cmd_hnew;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 			if (cmd->cmd_hlen + 1 == cmd->cmd_histlen)
1857c478bd9Sstevel@tonic-gate 				cmd->cmd_hold =
1867c478bd9Sstevel@tonic-gate 				    (cmd->cmd_hold + 1) % cmd->cmd_histlen;
1877c478bd9Sstevel@tonic-gate 			else
1887c478bd9Sstevel@tonic-gate 				cmd->cmd_hlen++;
1897c478bd9Sstevel@tonic-gate 		}
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx = 0;
1927c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen = 0;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		return ((const char *)cmd->cmd_linebuf);
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	return (NULL);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2017c478bd9Sstevel@tonic-gate int
2027c478bd9Sstevel@tonic-gate mdb_cmdbuf_backspace(mdb_cmdbuf_t *cmd, int c)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx > 0) {
2057c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen != cmd->cmd_bufidx) {
2067c478bd9Sstevel@tonic-gate 			bcopy(&cmd->cmd_buf[cmd->cmd_bufidx],
2077c478bd9Sstevel@tonic-gate 			    &cmd->cmd_buf[cmd->cmd_bufidx - 1],
2087c478bd9Sstevel@tonic-gate 			    cmd->cmd_buflen - cmd->cmd_bufidx);
2097c478bd9Sstevel@tonic-gate 		}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx--;
2127c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen--;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 		return (0);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	return (-1);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2217c478bd9Sstevel@tonic-gate int
2227c478bd9Sstevel@tonic-gate mdb_cmdbuf_delchar(mdb_cmdbuf_t *cmd, int c)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx < cmd->cmd_buflen) {
2257c478bd9Sstevel@tonic-gate 		if (cmd->cmd_bufidx < --cmd->cmd_buflen) {
2267c478bd9Sstevel@tonic-gate 			bcopy(&cmd->cmd_buf[cmd->cmd_bufidx + 1],
2277c478bd9Sstevel@tonic-gate 			    &cmd->cmd_buf[cmd->cmd_bufidx],
2287c478bd9Sstevel@tonic-gate 			    cmd->cmd_buflen - cmd->cmd_bufidx);
2297c478bd9Sstevel@tonic-gate 		}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 		return (0);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	return (-1);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2387c478bd9Sstevel@tonic-gate int
2397c478bd9Sstevel@tonic-gate mdb_cmdbuf_fwdchar(mdb_cmdbuf_t *cmd, int c)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx < cmd->cmd_buflen) {
2427c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx++;
2437c478bd9Sstevel@tonic-gate 		return (0);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	return (-1);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2507c478bd9Sstevel@tonic-gate int
2517c478bd9Sstevel@tonic-gate mdb_cmdbuf_backchar(mdb_cmdbuf_t *cmd, int c)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx > 0) {
2547c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx--;
2557c478bd9Sstevel@tonic-gate 		return (0);
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	return (-1);
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate int
2627c478bd9Sstevel@tonic-gate mdb_cmdbuf_transpose(mdb_cmdbuf_t *cmd, int c)
2637c478bd9Sstevel@tonic-gate {
2647c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx > 0 && cmd->cmd_buflen > 1) {
2657c478bd9Sstevel@tonic-gate 		c = cmd->cmd_buf[cmd->cmd_bufidx - 1];
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		if (cmd->cmd_bufidx == cmd->cmd_buflen) {
2687c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx - 1] =
2697c478bd9Sstevel@tonic-gate 			    cmd->cmd_buf[cmd->cmd_bufidx - 2];
2707c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx - 2] = (char)c;
2717c478bd9Sstevel@tonic-gate 		} else {
2727c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx - 1] =
2737c478bd9Sstevel@tonic-gate 			    cmd->cmd_buf[cmd->cmd_bufidx];
2747c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx++] = (char)c;
2757c478bd9Sstevel@tonic-gate 		}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 		return (0);
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	return (-1);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2847c478bd9Sstevel@tonic-gate int
2857c478bd9Sstevel@tonic-gate mdb_cmdbuf_home(mdb_cmdbuf_t *cmd, int c)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
2887c478bd9Sstevel@tonic-gate 	return (0);
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2927c478bd9Sstevel@tonic-gate int
2937c478bd9Sstevel@tonic-gate mdb_cmdbuf_end(mdb_cmdbuf_t *cmd, int c)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = cmd->cmd_buflen;
2967c478bd9Sstevel@tonic-gate 	return (0);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate static size_t
3007c478bd9Sstevel@tonic-gate fwdword_index(mdb_cmdbuf_t *cmd)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate 	size_t i = cmd->cmd_bufidx + 1;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	ASSERT(cmd->cmd_bufidx < cmd->cmd_buflen);
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	while (i < cmd->cmd_buflen && isspace(cmd->cmd_buf[i]))
3077c478bd9Sstevel@tonic-gate 		i++;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	while (i < cmd->cmd_buflen && !isspace(cmd->cmd_buf[i]) &&
3107c478bd9Sstevel@tonic-gate 	    !isalnum(cmd->cmd_buf[i]) && cmd->cmd_buf[i] != '_')
3117c478bd9Sstevel@tonic-gate 		i++;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	while (i < cmd->cmd_buflen &&
3147c478bd9Sstevel@tonic-gate 	    (isalnum(cmd->cmd_buf[i]) || cmd->cmd_buf[i] == '_'))
3157c478bd9Sstevel@tonic-gate 		i++;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	return (i);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3217c478bd9Sstevel@tonic-gate int
3227c478bd9Sstevel@tonic-gate mdb_cmdbuf_fwdword(mdb_cmdbuf_t *cmd, int c)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == cmd->cmd_buflen)
3257c478bd9Sstevel@tonic-gate 		return (-1);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = fwdword_index(cmd);
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	return (0);
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3337c478bd9Sstevel@tonic-gate int
3347c478bd9Sstevel@tonic-gate mdb_cmdbuf_killfwdword(mdb_cmdbuf_t *cmd, int c)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate 	size_t i;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == cmd->cmd_buflen)
3397c478bd9Sstevel@tonic-gate 		return (-1);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	i = fwdword_index(cmd);
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	bcopy(&cmd->cmd_buf[i], &cmd->cmd_buf[cmd->cmd_bufidx],
3447c478bd9Sstevel@tonic-gate 	    cmd->cmd_buflen - i);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen -= i - cmd->cmd_bufidx;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	return (0);
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate static size_t
3527c478bd9Sstevel@tonic-gate backword_index(mdb_cmdbuf_t *cmd)
3537c478bd9Sstevel@tonic-gate {
3547c478bd9Sstevel@tonic-gate 	size_t i = cmd->cmd_bufidx - 1;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	ASSERT(cmd->cmd_bufidx != 0);
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	while (i != 0 && isspace(cmd->cmd_buf[i]))
3597c478bd9Sstevel@tonic-gate 		i--;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	while (i != 0 && !isspace(cmd->cmd_buf[i]) &&
3627c478bd9Sstevel@tonic-gate 	    !isalnum(cmd->cmd_buf[i]) && cmd->cmd_buf[i] != '_')
3637c478bd9Sstevel@tonic-gate 		i--;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	while (i != 0 && (isalnum(cmd->cmd_buf[i]) || cmd->cmd_buf[i] == '_'))
3667c478bd9Sstevel@tonic-gate 		i--;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (i != 0)
3697c478bd9Sstevel@tonic-gate 		i++;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	return (i);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3757c478bd9Sstevel@tonic-gate int
3767c478bd9Sstevel@tonic-gate mdb_cmdbuf_backword(mdb_cmdbuf_t *cmd, int c)
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == 0)
3797c478bd9Sstevel@tonic-gate 		return (-1);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = backword_index(cmd);
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	return (0);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3877c478bd9Sstevel@tonic-gate int
3887c478bd9Sstevel@tonic-gate mdb_cmdbuf_killbackword(mdb_cmdbuf_t *cmd, int c)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate 	size_t i;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == 0)
3937c478bd9Sstevel@tonic-gate 		return (-1);
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	i = backword_index(cmd);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	bcopy(&cmd->cmd_buf[cmd->cmd_bufidx], &cmd->cmd_buf[i],
3987c478bd9Sstevel@tonic-gate 	    cmd->cmd_buflen - cmd->cmd_bufidx);
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen -= cmd->cmd_bufidx - i;
4017c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = i;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	return (0);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4077c478bd9Sstevel@tonic-gate int
4087c478bd9Sstevel@tonic-gate mdb_cmdbuf_kill(mdb_cmdbuf_t *cmd, int c)
4097c478bd9Sstevel@tonic-gate {
4107c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = cmd->cmd_bufidx;
4117c478bd9Sstevel@tonic-gate 	return (0);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4157c478bd9Sstevel@tonic-gate int
4167c478bd9Sstevel@tonic-gate mdb_cmdbuf_reset(mdb_cmdbuf_t *cmd, int c)
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = 0;
4197c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
4207c478bd9Sstevel@tonic-gate 	return (0);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4247c478bd9Sstevel@tonic-gate int
4257c478bd9Sstevel@tonic-gate mdb_cmdbuf_prevhist(mdb_cmdbuf_t *cmd, int c)
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate 	if (cmd->cmd_hcur != cmd->cmd_hold) {
4287c478bd9Sstevel@tonic-gate 		if (cmd->cmd_hcur-- == cmd->cmd_hnew) {
4297c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_buflen] = 0;
4307c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_linebuf, cmd->cmd_buf);
4317c478bd9Sstevel@tonic-gate 		}
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 		if (cmd->cmd_hcur < 0)
434*b2a1c443Svb 			cmd->cmd_hcur = cmd->cmd_halloc - 1;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 		(void) strcpy(cmd->cmd_buf, cmd->cmd_history[cmd->cmd_hcur]);
4377c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx = strlen(cmd->cmd_buf);
4387c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen = cmd->cmd_bufidx;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 		return (0);
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	return (-1);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4477c478bd9Sstevel@tonic-gate int
4487c478bd9Sstevel@tonic-gate mdb_cmdbuf_nexthist(mdb_cmdbuf_t *cmd, int c)
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate 	if (cmd->cmd_hcur != cmd->cmd_hnew) {
451*b2a1c443Svb 		cmd->cmd_hcur = (cmd->cmd_hcur + 1) % cmd->cmd_halloc;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 		if (cmd->cmd_hcur == cmd->cmd_hnew) {
4547c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_buf, cmd->cmd_linebuf);
4557c478bd9Sstevel@tonic-gate 		} else {
4567c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_buf,
4577c478bd9Sstevel@tonic-gate 			    cmd->cmd_history[cmd->cmd_hcur]);
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx = strlen(cmd->cmd_buf);
4617c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen = cmd->cmd_bufidx;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		return (0);
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	return (-1);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4707c478bd9Sstevel@tonic-gate int
4717c478bd9Sstevel@tonic-gate mdb_cmdbuf_findhist(mdb_cmdbuf_t *cmd, int c)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate 	ssize_t i, n;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	if (cmd->cmd_buflen != 0) {
4767c478bd9Sstevel@tonic-gate 		cmd->cmd_hcur = cmd->cmd_hnew;
4777c478bd9Sstevel@tonic-gate 		cmd->cmd_buf[cmd->cmd_buflen] = 0;
4787c478bd9Sstevel@tonic-gate 		(void) strcpy(cmd->cmd_linebuf, cmd->cmd_buf);
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	for (i = cmd->cmd_hcur, n = 0; n < cmd->cmd_hlen; n++) {
4827c478bd9Sstevel@tonic-gate 		if (--i < 0)
483*b2a1c443Svb 			i = cmd->cmd_halloc - 1;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 		if (strstr(cmd->cmd_history[i], cmd->cmd_linebuf) != NULL) {
4867c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_buf, cmd->cmd_history[i]);
4877c478bd9Sstevel@tonic-gate 			cmd->cmd_bufidx = strlen(cmd->cmd_buf);
4887c478bd9Sstevel@tonic-gate 			cmd->cmd_buflen = cmd->cmd_bufidx;
4897c478bd9Sstevel@tonic-gate 			cmd->cmd_hcur = i;
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 			return (0);
4927c478bd9Sstevel@tonic-gate 		}
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	cmd->cmd_hcur = cmd->cmd_hnew;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
4987c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = 0;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	return (-1);
5017c478bd9Sstevel@tonic-gate }
502