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