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
5b2a1c443Svb  * Common Development and Distribution License (the "License").
6b2a1c443Svb  * 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*cd31838bSvb  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * The MDB command buffer is a simple structure that keeps track of the
287c478bd9Sstevel@tonic-gate  * command history list, and provides operations to manipulate the current
297c478bd9Sstevel@tonic-gate  * buffer according to the various emacs editing options.  The terminal
307c478bd9Sstevel@tonic-gate  * code uses this code to keep track of the actual contents of the command
317c478bd9Sstevel@tonic-gate  * line, and then uses this content to perform redraw operations.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <strings.h>
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <ctype.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
397c478bd9Sstevel@tonic-gate #include <mdb/mdb_cmdbuf.h>
407c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
417c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #define	CMDBUF_LINELEN	BUFSIZ		/* Length of each buffer line */
447c478bd9Sstevel@tonic-gate #define	CMDBUF_TABLEN	8		/* Length of a tab in spaces */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate static void
cmdbuf_shiftr(mdb_cmdbuf_t * cmd,size_t nbytes)477c478bd9Sstevel@tonic-gate cmdbuf_shiftr(mdb_cmdbuf_t *cmd, size_t nbytes)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	bcopy(&cmd->cmd_buf[cmd->cmd_bufidx],
507c478bd9Sstevel@tonic-gate 	    &cmd->cmd_buf[cmd->cmd_bufidx + nbytes],
517c478bd9Sstevel@tonic-gate 	    cmd->cmd_buflen - cmd->cmd_bufidx);
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate 
54b2a1c443Svb static void
mdb_cmdbuf_allocchunk(mdb_cmdbuf_t * cmd)55b2a1c443Svb mdb_cmdbuf_allocchunk(mdb_cmdbuf_t *cmd)
56b2a1c443Svb {
57b2a1c443Svb 	int i;
58b2a1c443Svb 	char **newhistory;
59b2a1c443Svb 	ssize_t newhalloc = cmd->cmd_halloc + MDB_DEF_HISTLEN;
60b2a1c443Svb 
61b2a1c443Svb 	if (newhalloc > cmd->cmd_histlen)
62b2a1c443Svb 		newhalloc = cmd->cmd_histlen;
63b2a1c443Svb 	newhistory = mdb_alloc(newhalloc * sizeof (char *), UM_SLEEP);
64b2a1c443Svb 	bcopy(cmd->cmd_history, newhistory, cmd->cmd_halloc * sizeof (char *));
65b2a1c443Svb 	mdb_free(cmd->cmd_history, cmd->cmd_halloc * sizeof (char *));
66b2a1c443Svb 	for (i = cmd->cmd_halloc; i < newhalloc; i++)
67b2a1c443Svb 		newhistory[i] = mdb_alloc(CMDBUF_LINELEN, UM_SLEEP);
68b2a1c443Svb 	cmd->cmd_history = newhistory;
69b2a1c443Svb 	cmd->cmd_halloc = newhalloc;
70b2a1c443Svb }
71b2a1c443Svb 
727c478bd9Sstevel@tonic-gate void
mdb_cmdbuf_create(mdb_cmdbuf_t * cmd)737c478bd9Sstevel@tonic-gate mdb_cmdbuf_create(mdb_cmdbuf_t *cmd)
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate 	size_t i;
767c478bd9Sstevel@tonic-gate 
77b2a1c443Svb 	cmd->cmd_halloc = MDB_DEF_HISTLEN < mdb.m_histlen ?
78b2a1c443Svb 	    MDB_DEF_HISTLEN : mdb.m_histlen;
79b2a1c443Svb 
80b2a1c443Svb 	cmd->cmd_history = mdb_alloc(cmd->cmd_halloc * sizeof (char *),
81b2a1c443Svb 	    UM_SLEEP);
827c478bd9Sstevel@tonic-gate 	cmd->cmd_linebuf = mdb_alloc(CMDBUF_LINELEN, UM_SLEEP);
837c478bd9Sstevel@tonic-gate 
84b2a1c443Svb 	for (i = 0; i < cmd->cmd_halloc; i++)
857c478bd9Sstevel@tonic-gate 		cmd->cmd_history[i] = mdb_alloc(CMDBUF_LINELEN, UM_SLEEP);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	cmd->cmd_buf = cmd->cmd_history[0];
887c478bd9Sstevel@tonic-gate 	cmd->cmd_linelen = CMDBUF_LINELEN;
897c478bd9Sstevel@tonic-gate 	cmd->cmd_histlen = mdb.m_histlen;
907c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = 0;
917c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
927c478bd9Sstevel@tonic-gate 	cmd->cmd_hold = 0;
937c478bd9Sstevel@tonic-gate 	cmd->cmd_hnew = 0;
947c478bd9Sstevel@tonic-gate 	cmd->cmd_hcur = 0;
957c478bd9Sstevel@tonic-gate 	cmd->cmd_hlen = 0;
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate void
mdb_cmdbuf_destroy(mdb_cmdbuf_t * cmd)997c478bd9Sstevel@tonic-gate mdb_cmdbuf_destroy(mdb_cmdbuf_t *cmd)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	size_t i;
1027c478bd9Sstevel@tonic-gate 
103b2a1c443Svb 	for (i = 0; i < cmd->cmd_halloc; i++)
1047c478bd9Sstevel@tonic-gate 		mdb_free(cmd->cmd_history[i], CMDBUF_LINELEN);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	mdb_free(cmd->cmd_linebuf, CMDBUF_LINELEN);
107b2a1c443Svb 	mdb_free(cmd->cmd_history, cmd->cmd_halloc * sizeof (char *));
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_caninsert(mdb_cmdbuf_t * cmd,size_t nbytes)1117c478bd9Sstevel@tonic-gate mdb_cmdbuf_caninsert(mdb_cmdbuf_t *cmd, size_t nbytes)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	return (cmd->cmd_buflen + nbytes < cmd->cmd_linelen);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_atstart(mdb_cmdbuf_t * cmd)1177c478bd9Sstevel@tonic-gate mdb_cmdbuf_atstart(mdb_cmdbuf_t *cmd)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	return (cmd->cmd_bufidx == 0);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_atend(mdb_cmdbuf_t * cmd)1237c478bd9Sstevel@tonic-gate mdb_cmdbuf_atend(mdb_cmdbuf_t *cmd)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	return (cmd->cmd_bufidx == cmd->cmd_buflen);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_insert(mdb_cmdbuf_t * cmd,int c)1297c478bd9Sstevel@tonic-gate mdb_cmdbuf_insert(mdb_cmdbuf_t *cmd, int c)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	if (c == '\t') {
1327c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen + CMDBUF_TABLEN < cmd->cmd_linelen) {
1337c478bd9Sstevel@tonic-gate 			int i;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 			if (cmd->cmd_buflen != cmd->cmd_bufidx)
1367c478bd9Sstevel@tonic-gate 				cmdbuf_shiftr(cmd, CMDBUF_TABLEN);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 			for (i = 0; i < CMDBUF_TABLEN; i++)
1397c478bd9Sstevel@tonic-gate 				cmd->cmd_buf[cmd->cmd_bufidx++] = ' ';
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 			cmd->cmd_buflen += CMDBUF_TABLEN;
1427c478bd9Sstevel@tonic-gate 			return (0);
1437c478bd9Sstevel@tonic-gate 		}
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 		return (-1);
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (c < ' ' || c > '~')
1497c478bd9Sstevel@tonic-gate 		return (-1);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	if (cmd->cmd_buflen < cmd->cmd_linelen) {
1527c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen != cmd->cmd_bufidx)
1537c478bd9Sstevel@tonic-gate 			cmdbuf_shiftr(cmd, 1);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 		cmd->cmd_buf[cmd->cmd_bufidx++] = (char)c;
1567c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen++;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 		return (0);
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	return (-1);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate const char *
mdb_cmdbuf_accept(mdb_cmdbuf_t * cmd)1657c478bd9Sstevel@tonic-gate mdb_cmdbuf_accept(mdb_cmdbuf_t *cmd)
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx < cmd->cmd_linelen) {
168*cd31838bSvb 		int is_repeating = 0;
169*cd31838bSvb 
1707c478bd9Sstevel@tonic-gate 		cmd->cmd_buf[cmd->cmd_buflen++] = '\0';
1717c478bd9Sstevel@tonic-gate 		(void) strcpy(cmd->cmd_linebuf, cmd->cmd_buf);
1727c478bd9Sstevel@tonic-gate 
173*cd31838bSvb 		if (cmd->cmd_hold != cmd->cmd_hnew) {
174*cd31838bSvb 			int lastidx = cmd->cmd_hnew == 0 ? cmd->cmd_halloc - 1 :
175*cd31838bSvb 			    cmd->cmd_hnew - 1;
176*cd31838bSvb 
177*cd31838bSvb 			is_repeating = strcmp(cmd->cmd_buf,
178*cd31838bSvb 			    cmd->cmd_history[lastidx]) == 0;
179*cd31838bSvb 		}
180*cd31838bSvb 
1817c478bd9Sstevel@tonic-gate 		/*
182*cd31838bSvb 		 * Don't bother inserting empty or repeating buffers into the
183*cd31838bSvb 		 * history ring.
1847c478bd9Sstevel@tonic-gate 		 */
185*cd31838bSvb 		if (cmd->cmd_buflen > 1 && !is_repeating) {
1867c478bd9Sstevel@tonic-gate 			cmd->cmd_hnew = (cmd->cmd_hnew + 1) % cmd->cmd_histlen;
187b2a1c443Svb 			if (cmd->cmd_hnew >= cmd->cmd_halloc)
188b2a1c443Svb 				mdb_cmdbuf_allocchunk(cmd);
189b2a1c443Svb 
1907c478bd9Sstevel@tonic-gate 			cmd->cmd_buf = cmd->cmd_history[cmd->cmd_hnew];
1917c478bd9Sstevel@tonic-gate 			cmd->cmd_hcur = cmd->cmd_hnew;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 			if (cmd->cmd_hlen + 1 == cmd->cmd_histlen)
1947c478bd9Sstevel@tonic-gate 				cmd->cmd_hold =
1957c478bd9Sstevel@tonic-gate 				    (cmd->cmd_hold + 1) % cmd->cmd_histlen;
1967c478bd9Sstevel@tonic-gate 			else
1977c478bd9Sstevel@tonic-gate 				cmd->cmd_hlen++;
198*cd31838bSvb 		} else if (is_repeating) {
199*cd31838bSvb 			cmd->cmd_hcur = cmd->cmd_hnew;
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx = 0;
2037c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen = 0;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 		return ((const char *)cmd->cmd_linebuf);
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	return (NULL);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2127c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_backspace(mdb_cmdbuf_t * cmd,int c)2137c478bd9Sstevel@tonic-gate mdb_cmdbuf_backspace(mdb_cmdbuf_t *cmd, int c)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx > 0) {
2167c478bd9Sstevel@tonic-gate 		if (cmd->cmd_buflen != cmd->cmd_bufidx) {
2177c478bd9Sstevel@tonic-gate 			bcopy(&cmd->cmd_buf[cmd->cmd_bufidx],
2187c478bd9Sstevel@tonic-gate 			    &cmd->cmd_buf[cmd->cmd_bufidx - 1],
2197c478bd9Sstevel@tonic-gate 			    cmd->cmd_buflen - cmd->cmd_bufidx);
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx--;
2237c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen--;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 		return (0);
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	return (-1);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2327c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_delchar(mdb_cmdbuf_t * cmd,int c)2337c478bd9Sstevel@tonic-gate mdb_cmdbuf_delchar(mdb_cmdbuf_t *cmd, int c)
2347c478bd9Sstevel@tonic-gate {
2357c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx < cmd->cmd_buflen) {
2367c478bd9Sstevel@tonic-gate 		if (cmd->cmd_bufidx < --cmd->cmd_buflen) {
2377c478bd9Sstevel@tonic-gate 			bcopy(&cmd->cmd_buf[cmd->cmd_bufidx + 1],
2387c478bd9Sstevel@tonic-gate 			    &cmd->cmd_buf[cmd->cmd_bufidx],
2397c478bd9Sstevel@tonic-gate 			    cmd->cmd_buflen - cmd->cmd_bufidx);
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		return (0);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	return (-1);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2497c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_fwdchar(mdb_cmdbuf_t * cmd,int c)2507c478bd9Sstevel@tonic-gate mdb_cmdbuf_fwdchar(mdb_cmdbuf_t *cmd, int c)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx < cmd->cmd_buflen) {
2537c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx++;
2547c478bd9Sstevel@tonic-gate 		return (0);
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	return (-1);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2617c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_backchar(mdb_cmdbuf_t * cmd,int c)2627c478bd9Sstevel@tonic-gate mdb_cmdbuf_backchar(mdb_cmdbuf_t *cmd, int c)
2637c478bd9Sstevel@tonic-gate {
2647c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx > 0) {
2657c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx--;
2667c478bd9Sstevel@tonic-gate 		return (0);
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	return (-1);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_transpose(mdb_cmdbuf_t * cmd,int c)2737c478bd9Sstevel@tonic-gate mdb_cmdbuf_transpose(mdb_cmdbuf_t *cmd, int c)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx > 0 && cmd->cmd_buflen > 1) {
2767c478bd9Sstevel@tonic-gate 		c = cmd->cmd_buf[cmd->cmd_bufidx - 1];
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 		if (cmd->cmd_bufidx == cmd->cmd_buflen) {
2797c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx - 1] =
2807c478bd9Sstevel@tonic-gate 			    cmd->cmd_buf[cmd->cmd_bufidx - 2];
2817c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx - 2] = (char)c;
2827c478bd9Sstevel@tonic-gate 		} else {
2837c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx - 1] =
2847c478bd9Sstevel@tonic-gate 			    cmd->cmd_buf[cmd->cmd_bufidx];
2857c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_bufidx++] = (char)c;
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 		return (0);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	return (-1);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2957c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_home(mdb_cmdbuf_t * cmd,int c)2967c478bd9Sstevel@tonic-gate mdb_cmdbuf_home(mdb_cmdbuf_t *cmd, int c)
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
2997c478bd9Sstevel@tonic-gate 	return (0);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3037c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_end(mdb_cmdbuf_t * cmd,int c)3047c478bd9Sstevel@tonic-gate mdb_cmdbuf_end(mdb_cmdbuf_t *cmd, int c)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = cmd->cmd_buflen;
3077c478bd9Sstevel@tonic-gate 	return (0);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate static size_t
fwdword_index(mdb_cmdbuf_t * cmd)3117c478bd9Sstevel@tonic-gate fwdword_index(mdb_cmdbuf_t *cmd)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	size_t i = cmd->cmd_bufidx + 1;
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	ASSERT(cmd->cmd_bufidx < cmd->cmd_buflen);
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	while (i < cmd->cmd_buflen && isspace(cmd->cmd_buf[i]))
3187c478bd9Sstevel@tonic-gate 		i++;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	while (i < cmd->cmd_buflen && !isspace(cmd->cmd_buf[i]) &&
3217c478bd9Sstevel@tonic-gate 	    !isalnum(cmd->cmd_buf[i]) && cmd->cmd_buf[i] != '_')
3227c478bd9Sstevel@tonic-gate 		i++;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	while (i < cmd->cmd_buflen &&
3257c478bd9Sstevel@tonic-gate 	    (isalnum(cmd->cmd_buf[i]) || cmd->cmd_buf[i] == '_'))
3267c478bd9Sstevel@tonic-gate 		i++;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	return (i);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3327c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_fwdword(mdb_cmdbuf_t * cmd,int c)3337c478bd9Sstevel@tonic-gate mdb_cmdbuf_fwdword(mdb_cmdbuf_t *cmd, int c)
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == cmd->cmd_buflen)
3367c478bd9Sstevel@tonic-gate 		return (-1);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = fwdword_index(cmd);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	return (0);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3447c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_killfwdword(mdb_cmdbuf_t * cmd,int c)3457c478bd9Sstevel@tonic-gate mdb_cmdbuf_killfwdword(mdb_cmdbuf_t *cmd, int c)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 	size_t i;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == cmd->cmd_buflen)
3507c478bd9Sstevel@tonic-gate 		return (-1);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	i = fwdword_index(cmd);
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	bcopy(&cmd->cmd_buf[i], &cmd->cmd_buf[cmd->cmd_bufidx],
3557c478bd9Sstevel@tonic-gate 	    cmd->cmd_buflen - i);
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen -= i - cmd->cmd_bufidx;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	return (0);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate static size_t
backword_index(mdb_cmdbuf_t * cmd)3637c478bd9Sstevel@tonic-gate backword_index(mdb_cmdbuf_t *cmd)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate 	size_t i = cmd->cmd_bufidx - 1;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	ASSERT(cmd->cmd_bufidx != 0);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	while (i != 0 && isspace(cmd->cmd_buf[i]))
3707c478bd9Sstevel@tonic-gate 		i--;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	while (i != 0 && !isspace(cmd->cmd_buf[i]) &&
3737c478bd9Sstevel@tonic-gate 	    !isalnum(cmd->cmd_buf[i]) && cmd->cmd_buf[i] != '_')
3747c478bd9Sstevel@tonic-gate 		i--;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	while (i != 0 && (isalnum(cmd->cmd_buf[i]) || cmd->cmd_buf[i] == '_'))
3777c478bd9Sstevel@tonic-gate 		i--;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (i != 0)
3807c478bd9Sstevel@tonic-gate 		i++;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	return (i);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3867c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_backword(mdb_cmdbuf_t * cmd,int c)3877c478bd9Sstevel@tonic-gate mdb_cmdbuf_backword(mdb_cmdbuf_t *cmd, int c)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == 0)
3907c478bd9Sstevel@tonic-gate 		return (-1);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = backword_index(cmd);
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	return (0);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3987c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_killbackword(mdb_cmdbuf_t * cmd,int c)3997c478bd9Sstevel@tonic-gate mdb_cmdbuf_killbackword(mdb_cmdbuf_t *cmd, int c)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate 	size_t i;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	if (cmd->cmd_bufidx == 0)
4047c478bd9Sstevel@tonic-gate 		return (-1);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	i = backword_index(cmd);
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	bcopy(&cmd->cmd_buf[cmd->cmd_bufidx], &cmd->cmd_buf[i],
4097c478bd9Sstevel@tonic-gate 	    cmd->cmd_buflen - cmd->cmd_bufidx);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen -= cmd->cmd_bufidx - i;
4127c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = i;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	return (0);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4187c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_kill(mdb_cmdbuf_t * cmd,int c)4197c478bd9Sstevel@tonic-gate mdb_cmdbuf_kill(mdb_cmdbuf_t *cmd, int c)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = cmd->cmd_bufidx;
4227c478bd9Sstevel@tonic-gate 	return (0);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4267c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_reset(mdb_cmdbuf_t * cmd,int c)4277c478bd9Sstevel@tonic-gate mdb_cmdbuf_reset(mdb_cmdbuf_t *cmd, int c)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = 0;
4307c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
4317c478bd9Sstevel@tonic-gate 	return (0);
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4357c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_prevhist(mdb_cmdbuf_t * cmd,int c)4367c478bd9Sstevel@tonic-gate mdb_cmdbuf_prevhist(mdb_cmdbuf_t *cmd, int c)
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate 	if (cmd->cmd_hcur != cmd->cmd_hold) {
4397c478bd9Sstevel@tonic-gate 		if (cmd->cmd_hcur-- == cmd->cmd_hnew) {
4407c478bd9Sstevel@tonic-gate 			cmd->cmd_buf[cmd->cmd_buflen] = 0;
4417c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_linebuf, cmd->cmd_buf);
4427c478bd9Sstevel@tonic-gate 		}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 		if (cmd->cmd_hcur < 0)
445b2a1c443Svb 			cmd->cmd_hcur = cmd->cmd_halloc - 1;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 		(void) strcpy(cmd->cmd_buf, cmd->cmd_history[cmd->cmd_hcur]);
4487c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx = strlen(cmd->cmd_buf);
4497c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen = cmd->cmd_bufidx;
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 		return (0);
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	return (-1);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4587c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_nexthist(mdb_cmdbuf_t * cmd,int c)4597c478bd9Sstevel@tonic-gate mdb_cmdbuf_nexthist(mdb_cmdbuf_t *cmd, int c)
4607c478bd9Sstevel@tonic-gate {
4617c478bd9Sstevel@tonic-gate 	if (cmd->cmd_hcur != cmd->cmd_hnew) {
462b2a1c443Svb 		cmd->cmd_hcur = (cmd->cmd_hcur + 1) % cmd->cmd_halloc;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		if (cmd->cmd_hcur == cmd->cmd_hnew) {
4657c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_buf, cmd->cmd_linebuf);
4667c478bd9Sstevel@tonic-gate 		} else {
4677c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_buf,
4687c478bd9Sstevel@tonic-gate 			    cmd->cmd_history[cmd->cmd_hcur]);
4697c478bd9Sstevel@tonic-gate 		}
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		cmd->cmd_bufidx = strlen(cmd->cmd_buf);
4727c478bd9Sstevel@tonic-gate 		cmd->cmd_buflen = cmd->cmd_bufidx;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 		return (0);
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	return (-1);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4817c478bd9Sstevel@tonic-gate int
mdb_cmdbuf_findhist(mdb_cmdbuf_t * cmd,int c)4827c478bd9Sstevel@tonic-gate mdb_cmdbuf_findhist(mdb_cmdbuf_t *cmd, int c)
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate 	ssize_t i, n;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	if (cmd->cmd_buflen != 0) {
4877c478bd9Sstevel@tonic-gate 		cmd->cmd_hcur = cmd->cmd_hnew;
4887c478bd9Sstevel@tonic-gate 		cmd->cmd_buf[cmd->cmd_buflen] = 0;
4897c478bd9Sstevel@tonic-gate 		(void) strcpy(cmd->cmd_linebuf, cmd->cmd_buf);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	for (i = cmd->cmd_hcur, n = 0; n < cmd->cmd_hlen; n++) {
4937c478bd9Sstevel@tonic-gate 		if (--i < 0)
494b2a1c443Svb 			i = cmd->cmd_halloc - 1;
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 		if (strstr(cmd->cmd_history[i], cmd->cmd_linebuf) != NULL) {
4977c478bd9Sstevel@tonic-gate 			(void) strcpy(cmd->cmd_buf, cmd->cmd_history[i]);
4987c478bd9Sstevel@tonic-gate 			cmd->cmd_bufidx = strlen(cmd->cmd_buf);
4997c478bd9Sstevel@tonic-gate 			cmd->cmd_buflen = cmd->cmd_bufidx;
5007c478bd9Sstevel@tonic-gate 			cmd->cmd_hcur = i;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 			return (0);
5037c478bd9Sstevel@tonic-gate 		}
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	cmd->cmd_hcur = cmd->cmd_hnew;
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	cmd->cmd_bufidx = 0;
5097c478bd9Sstevel@tonic-gate 	cmd->cmd_buflen = 0;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	return (-1);
5127c478bd9Sstevel@tonic-gate }
513