3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * CDDL HEADER START
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * The contents of this file are subject to the terms of the
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Common Development and Distribution License (the "License").
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * You may not use this file except in compliance with the License.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * or http://www.opensolaris.org/os/licensing.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * See the License for the specific language governing permissions
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * and limitations under the License.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * When distributing Covered Code, include this CDDL HEADER in each
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * If applicable, add the following below this CDDL HEADER, with the
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * fields enclosed by brackets "[]" replaced with your own identifying
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * information: Portions Copyright [yyyy] [name of copyright owner]
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * CDDL HEADER END
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson * Copyright (c) 2013 by Delphix. All rights reserved.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Copyright (c) 2012 Joyent, Inc. All rights reserved.
065c692a88e4dcdd0c6eadc2476c046d6ee9dd1cJosef 'Jeff' Sipek * Copyright (c) 2013 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * This file contains all of the interfaces for mdb's tab completion engine.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Currently some interfaces are private to mdb and its internal implementation,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * those are in mdb_tab.h. Other pieces are public interfaces. Those are in
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * mdb_modapi.h.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Memory allocations in tab completion context have to be done very carefully.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * We need to think of ourselves as the same as any other command that is being
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * executed by the user, which means we must use UM_GC to handle being
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * interrupted.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_modapi.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_ctf.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_ctf_impl.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_string.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_module.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_debug.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_print.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_nv.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb_tab.h>
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson#include <mdb/mdb_target.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <mdb/mdb.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#include <ctype.h>
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * There may be another way to do this, but this works well enough.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur#define COMMAND_SEPARATOR "::"
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * find_command_start --
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Given a buffer find the start of the last command.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic char *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_find_command_start(char *buf)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *offset = strstr(buf, COMMAND_SEPARATOR);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (offset == NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (NULL);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur for (;;) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *next = strstr(offset + strlen(COMMAND_SEPARATOR),
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur COMMAND_SEPARATOR);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (next == NULL) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (offset);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur offset = next;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * get_dcmd --
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Given a buffer containing a command and its argument return
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * the name of the command and the offset in the buffer where
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * the command arguments start.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Note: This will modify the buffer.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurchar *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_get_dcmd(char *buf, char **args, uint_t *flags)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *start = buf + strlen(COMMAND_SEPARATOR);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *separator = start;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur const char *end = buf + strlen(buf);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur uint_t space = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (separator < end && !isspace(*separator))
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur separator++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (separator == end) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *args = NULL;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur } else {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (isspace(*separator))
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur space = 1;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *separator++ = '\0';
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *args = separator;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (space)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *flags |= DCMD_TAB_SPACE;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (start);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * count_args --
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Given a buffer containing dmcd arguments return the total number
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * of arguments.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * While parsing arguments we need to keep track of whether or not the last
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * arguments ends with a trailing space.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_count_args(const char *input, uint_t *flags)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur const char *index;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int argc = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur uint_t space = *flags & DCMD_TAB_SPACE;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index = input;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (*index != '\0') {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (*index != '\0' && isspace(*index)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur space = 1;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (*index != '\0' && !isspace(*index)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argc++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur space = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (*index != '\0' && !isspace (*index)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (space)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *flags |= DCMD_TAB_SPACE;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur else
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *flags &= ~DCMD_TAB_SPACE;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (argc);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * copy_args --
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Given a buffer containing dcmd arguments and an array of mdb_arg_t's
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * initialize the string value of each mdb_arg_t.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Note: This will modify the buffer.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_copy_args(char *input, int argc, mdb_arg_t *argv)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int i = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *index;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index = input;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (*index) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (*index && isspace(*index)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (*index && !isspace(*index)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *end = index;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (*end && !isspace(*end)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur end++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (*end) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *end++ = '\0';
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argv[i].a_type = MDB_TYPE_STRING;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argv[i].a_un.a_str = index;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index = end;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur i++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (i != argc)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (-1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * parse-buf --
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Parse the given buffer and return the specified dcmd, the number
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * of arguments, and array of mdb_arg_t containing the argument
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * values.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Note: this will modify the specified buffer. Caller is responisble
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * for freeing argvp.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_parse_buf(char *buf, char **dcmdp, int *argcp, mdb_arg_t **argvp,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur uint_t *flags)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *data = tab_find_command_start(buf);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *args_data = NULL;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *dcmd = NULL;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int argc = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_arg_t *argv = NULL;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (data == NULL) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (-1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur dcmd = tab_get_dcmd(data, &args_data, flags);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (dcmd == NULL) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (-1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (args_data != NULL) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argc = tab_count_args(args_data, flags);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc != 0) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argv = mdb_alloc(sizeof (mdb_arg_t) * argc,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur UM_SLEEP | UM_GC);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (tab_copy_args(args_data, argc, argv) == -1)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (-1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *dcmdp = dcmd;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *argcp = argc;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *argvp = argv;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * tab_command --
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * This function is executed anytime a tab is entered. It checks
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * the current buffer to determine if there is a valid dmcd,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * if that dcmd has a tab completion handler it will invoke it.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * This function returns the string (if any) that should be added to the
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * existing buffer to complete it.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_command(mdb_tab_cookie_t *mcp, const char *buf)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *data;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char *dcmd = NULL;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int argc = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_arg_t *argv = NULL;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int ret = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_idcmd_t *cp;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur uint_t flags = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Parsing the command and arguments will modify the buffer
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * (replacing spaces with \0), so make a copy of the specified
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * buffer first.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur data = mdb_alloc(strlen(buf) + 1, UM_SLEEP | UM_GC);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) strcpy(data, buf);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Get the specified dcmd and arguments from the buffer.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur ret = tab_parse_buf(data, &dcmd, &argc, &argv, &flags);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson /*
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson * Match against global symbols if the input is not a dcmd
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (ret != 0) {
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson (void) mdb_tab_complete_global(mcp, buf);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur goto out;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Check to see if the buffer contains a valid dcmd
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur cp = mdb_dcmd_lookup(dcmd);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * When argc is zero it indicates that we are trying to tab complete
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson * a dcmd or a global symbol. Note, that if there isn't the start of
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson * a dcmd, i.e. ::, then we will have already bailed in the call to
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson * tab_parse_buf.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (cp == NULL && argc != 0) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur goto out;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Invoke the command specific tab completion handler or the built in
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * dcmd one if there is no dcmd.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (cp == NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_tab_complete_dcmd(mcp, dcmd);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur else
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_call_tab(cp, mcp, flags, argc, argv);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurout:
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_tab_size(mcp));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_complete_dcmd(mdb_var_t *v, void *arg)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_idcmd_t *idcp = mdb_nv_get_cookie(mdb_nv_get_cookie(v));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_cookie_t *mcp = (mdb_tab_cookie_t *)arg;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * The way that mdb is implemented, even commands like $C will show up
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * here. As such, we don't want to match anything that doesn't start
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * with an alpha or number. While nothing currently appears (via a
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * cursory search with mdb -k) to start with a capital letter or a
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * number, we'll support them anyways.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (!isalnum(idcp->idc_name[0]))
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_insert(mcp, idcp->idc_name);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_dcmd(mdb_tab_cookie_t *mcp, const char *dcmd)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
2f045fd6af922f819146b314d143b660b58b20b7Robert Mustacchi if (dcmd != NULL)
2f045fd6af922f819146b314d143b660b58b20b7Robert Mustacchi mdb_tab_setmbase(mcp, dcmd);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_nv_sort_iter(&mdb.m_dcmds, tab_complete_dcmd, mcp,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur UM_GC | UM_SLEEP);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_complete_walker(mdb_var_t *v, void *arg)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_iwalker_t *iwp = mdb_nv_get_cookie(mdb_nv_get_cookie(v));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_cookie_t *mcp = arg;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_insert(mcp, iwp->iwlk_name);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_walker(mdb_tab_cookie_t *mcp, const char *walker)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (walker != NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_setmbase(mcp, walker);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_nv_sort_iter(&mdb.m_walkers, tab_complete_walker, mcp,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur UM_GC | UM_SLEEP);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_cookie_t *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_init(void)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_cookie_t *mcp;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mcp = mdb_zalloc(sizeof (mdb_tab_cookie_t), UM_SLEEP | UM_GC);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_nv_create(&mcp->mtc_nv, UM_SLEEP | UM_GC);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mcp);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdursize_t
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_size(mdb_tab_cookie_t *mcp)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_nv_size(&mcp->mtc_nv));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * Determine whether the specified name is a valid tab completion for
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * the given command. If the name is a valid tab completion then
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * it will be saved in the mdb_tab_cookie_t.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurvoid
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_insert(mdb_tab_cookie_t *mcp, const char *name)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
065c692a88e4dcdd0c6eadc2476c046d6ee9dd1cJosef 'Jeff' Sipek size_t matches, index;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_var_t *v;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * If we have a match set, then we want to verify that we actually match
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * it.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (mcp->mtc_base != NULL &&
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur strncmp(name, mcp->mtc_base, strlen(mcp->mtc_base)) != 0)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur v = mdb_nv_lookup(&mcp->mtc_nv, name);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (v != NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
065c692a88e4dcdd0c6eadc2476c046d6ee9dd1cJosef 'Jeff' Sipek (void) mdb_nv_insert(&mcp->mtc_nv, name, NULL, 0, MDB_NV_RDONLY);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur matches = mdb_tab_size(mcp);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (matches == 1) {
065c692a88e4dcdd0c6eadc2476c046d6ee9dd1cJosef 'Jeff' Sipek (void) strlcpy(mcp->mtc_match, name, MDB_SYM_NAMLEN);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur } else {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur while (mcp->mtc_match[index] &&
065c692a88e4dcdd0c6eadc2476c046d6ee9dd1cJosef 'Jeff' Sipek mcp->mtc_match[index] == name[index])
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur index++;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mcp->mtc_match[index] = '\0';
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*ARGSUSED*/
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_print_cb(mdb_var_t *v, void *ignored)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_printf("%s\n", mdb_nv_get_name(v));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurvoid
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_print(mdb_tab_cookie_t *mcp)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_nv_sort_iter(&mcp->mtc_nv, tab_print_cb, NULL, UM_SLEEP | UM_GC);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurconst char *
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_match(mdb_tab_cookie_t *mcp)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur size_t blen;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (mcp->mtc_base == NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur blen = 0;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur else
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur blen = strlen(mcp->mtc_base);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mcp->mtc_match + blen);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurvoid
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_setmbase(mdb_tab_cookie_t *mcp, const char *base)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) strlcpy(mcp->mtc_base, base, MDB_SYM_NAMLEN);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * This function is currently a no-op due to the fact that we have to GC because
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * we're in command context.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*ARGSUSED*/
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurvoid
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_fini(mdb_tab_cookie_t *mcp)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson/*ARGSUSED*/
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattssonstatic int
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattssontab_complete_global(void *arg, const GElf_Sym *sym, const char *name,
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson const mdb_syminfo_t *sip, const char *obj)
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson{
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson mdb_tab_cookie_t *mcp = arg;
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson mdb_tab_insert(mcp, name);
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson return (0);
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson}
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson/*
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson * This function tab completes against all loaded global symbols.
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson */
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattssonint
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattssonmdb_tab_complete_global(mdb_tab_cookie_t *mcp, const char *name)
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson{
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson mdb_tab_setmbase(mcp, name);
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson (void) mdb_tgt_symbol_iter(mdb.m_target, MDB_TGT_OBJ_EVERY,
22ce014825a14b6ce90123db2834a13e343d6cafMatthew Ahrens MDB_TGT_SYMTAB, MDB_TGT_BIND_ANY | MDB_TGT_TYPE_OBJECT |
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson MDB_TGT_TYPE_FUNC, tab_complete_global, mcp);
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson return (0);
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson}
72a1114bccf02392ab254b9615412236f3b63256Henrik Mattsson
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * This function takes a ctf id and determines whether or not the associated
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * type should be considered as a potential match for the given tab
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * completion command. We verify that the type itself is valid
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * for completion given the current context of the command, resolve
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * its actual name, and then pass it off to mdb_tab_insert to determine
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * if it's an actual match.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_complete_type(mdb_ctf_id_t id, void *arg)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int rkind;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char buf[MDB_SYM_NAMLEN];
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_ctf_id_t rid;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_cookie_t *mcp = arg;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur uint_t flags = (uint_t)(uintptr_t)mcp->mtc_cba;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur /*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * CTF data includes types that mdb commands don't understand. Before
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * we resolve the actual type prune any entry that is a type we
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * don't care about.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur switch (mdb_ctf_type_kind(id)) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur case CTF_K_CONST:
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur case CTF_K_RESTRICT:
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur case CTF_K_VOLATILE:
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (mdb_ctf_type_resolve(id, &rid) != 0)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur rkind = mdb_ctf_type_kind(rid);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if ((flags & MDB_TABC_MEMBERS) && rkind != CTF_K_STRUCT &&
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur rkind != CTF_K_UNION)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if ((flags & MDB_TABC_NOPOINT) && rkind == CTF_K_POINTER)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if ((flags & MDB_TABC_NOARRAY) && rkind == CTF_K_ARRAY)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_ctf_type_name(id, buf, sizeof (buf));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_insert(mcp, buf);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*ARGSUSED*/
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_module(void *data, const mdb_map_t *mp, const char *name)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_ctf_type_iter(name, tab_complete_type, data);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_type(mdb_tab_cookie_t *mcp, const char *name, uint_t flags)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tgt_t *t = mdb.m_target;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mcp->mtc_cba = (void *)(uintptr_t)flags;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (name != NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_setmbase(mcp, name);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_tgt_object_iter(t, mdb_tab_complete_module, mcp);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, tab_complete_type,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mcp);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*ARGSUSED*/
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurstatic int
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurtab_complete_member(const char *name, mdb_ctf_id_t id, ulong_t off, void *arg)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_cookie_t *mcp = arg;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_insert(mcp, name);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_member_by_id(mdb_tab_cookie_t *mcp, mdb_ctf_id_t id,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur const char *member)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (member != NULL)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_tab_setmbase(mcp, member);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_ctf_member_iter(id, tab_complete_member, mcp);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_member(mdb_tab_cookie_t *mcp, const char *type,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur const char *member)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur mdb_ctf_id_t id;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (mdb_ctf_lookup_by_name(type, &id) != 0)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (-1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_tab_complete_member_by_id(mcp, id, member));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_complete_mt(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur const mdb_arg_t *argv)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur char tn[MDB_SYM_NAMLEN];
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int ret;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc == 0 && !(flags & DCMD_TAB_SPACE))
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc == 0)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_tab_complete_type(mcp, NULL, MDB_TABC_MEMBERS));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if ((ret = mdb_tab_typename(&argc, &argv, tn, sizeof (tn))) < 0)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (ret);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc == 1 && (!(flags & DCMD_TAB_SPACE) || ret == 1))
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_tab_complete_type(mcp, tn, MDB_TABC_MEMBERS));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc == 1 && (flags & DCMD_TAB_SPACE))
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_tab_complete_member(mcp, tn, NULL));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc == 2)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (mdb_tab_complete_member(mcp, tn, argv[1].a_un.a_str));
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur/*
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * This is similar to mdb_print.c's args_to_typename, but it has subtle
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * differences surrounding how the strings of one element are handled that have
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * 'struct', 'enum', or 'union' in them and instead works with them for tab
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur * completion purposes.
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur */
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurint
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdurmdb_tab_typename(int *argcp, const mdb_arg_t **argvp, char *buf, size_t len)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur{
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur int argc = *argcp;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur const mdb_arg_t *argv = *argvp;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc < 1 || argv->a_type != MDB_TYPE_STRING)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (DCMD_USAGE);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (strcmp(argv->a_un.a_str, "struct") == 0 ||
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur strcmp(argv->a_un.a_str, "enum") == 0 ||
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur strcmp(argv->a_un.a_str, "union") == 0) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argc == 1) {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_snprintf(buf, len, "%s ",
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argv[0].a_un.a_str);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (1);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur if (argv[1].a_type != MDB_TYPE_STRING)
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (DCMD_USAGE);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_snprintf(buf, len, "%s %s",
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur argv[0].a_un.a_str, argv[1].a_un.a_str);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *argcp = argc - 1;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur *argvp = argv + 1;
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur } else {
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur (void) mdb_snprintf(buf, len, "%s", argv[0].a_un.a_str);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur }
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur return (0);
3b6e0a598869dfc84461624e8699bf51738f68b3Matt Amdur}