<commit_before>/****************************************************************************
 *
 * Copyright 2016 Samsung Electronics All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 *
 ****************************************************************************/
/// @file   tash_command.c
/// @brief  functions to treate commands

#include <pthread.h>
#include <tinyara/config.h>
#include <tinyara/ascii.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/boardctl.h>
#include <apps/shell/tash.h>
#ifdef CONFIG_BUILTIN_APPS
#include <apps/builtin.h>
#endif
#include "tash_internal.h"

/****************************************************************************
 * Preprocessor Definitions
 ****************************************************************************/

/* Following defines are fixed to avoid many configuration variables for TASH */
#define TASH_CMD_MAXSTRLENGTH		(16) /* example: length of "ifconfig" command is 8 */
#ifdef CONFIG_TASH_MAX_COMMANDS
#define TASH_MAX_COMMANDS			CONFIG_TASH_MAX_COMMANDS
#else
#define TASH_MAX_COMMANDS			(32)
#endif
#ifdef CONFIG_TASH_CMDTASK_STACKSIZE
#define TASH_CMDTASK_STACKSIZE		CONFIG_TASH_CMDTASK_STACKSIZE
#else
#define TASH_CMDTASK_STACKSIZE		(4096)
#endif
#ifdef CONFIG_TASH_CMDTASK_PRIORITY
#define TASH_CMDTASK_PRIORITY		CONFIG_TASH_CMDTASK_PRIORITY
#else
#define TASH_CMDTASK_PRIORITY		(SCHED_PRIORITY_DEFAULT)
#endif
#define TASH_CMDS_PER_LINE			(4)

#if TASH_MAX_STORE > 0
#define CMD_INDEX_UP(x)                                   \
	do {                                                  \
		((x) == TASH_MAX_STORE - 1) ? (x) = 0 : (x)++;    \
	} while (0)

#define CMD_INDEX_DOWN(x)                                 \
	do {                                                  \
		((x) == 0) ? (x) = TASH_MAX_STORE - 1 : (x)--;    \
	} while (0)
#endif
/****************************************************************************
 * Global Variables
 ****************************************************************************/

/****************************************************************************
 * Private Type Declarations
 ****************************************************************************/

/**
 * @brief TASH internal data structure to store command strings & callback function
 * pointers
 */
struct tash_cmd_s {
	char str[TASH_CMD_MAXSTRLENGTH];	/* Command strings- eg, ifconfig */
	TASH_CMD_CALLBACK cb;				/* Function pointer for Callback */
	int exec_type;						/* Execution type of this command */
};

struct tash_cmd_info_s {
	pthread_mutex_t tmutex;						/* Mutex for protection */
	struct tash_cmd_s cmd[TASH_MAX_COMMANDS];
	int count;									/* Number of TASH commands */
};

/********************************************************************************
 * Private Function Prototypes
 ********************************************************************************/

static int tash_help(int argc, char **args);
static int tash_exit(int argc, char **args);
#if defined(CONFIG_BOARDCTL_RESET)
static int tash_reboot(int argc, char **argv);
#endif
#if TASH_MAX_STORE   > 0
static int tash_history(int argc, char **argv);
#endif

/****************************************************************************
 * Private Variables
 ****************************************************************************/

static int is_sorted_list = FALSE;
static struct tash_cmd_info_s tash_cmds_info = {PTHREAD_MUTEX_INITIALIZER};

const static tash_cmdlist_t tash_basic_cmds[] = {
	{"exit",  tash_exit,   TASH_EXECMD_SYNC},
	{"help",  tash_help,   TASH_EXECMD_SYNC},
#ifdef CONFIG_TASH_SCRIPT
	{"sh",    tash_script, TASH_EXECMD_SYNC},
#endif
#ifndef CONFIG_DISABLE_SIGNALS
	{"sleep", tash_sleep,  TASH_EXECMD_SYNC},
#ifdef CONFIG_TASH_USLEEP
	{"usleep", tash_usleep, TASH_EXECMD_SYNC},
#endif
#endif
#if defined(CONFIG_BOARDCTL_RESET)
	{"reboot", tash_reboot, TASH_EXECMD_SYNC},
#endif
#if TASH_MAX_STORE > 0
	{"history", tash_history, TASH_EXECMD_SYNC},
#endif
	{NULL,    NULL,        0}
};

#if TASH_MAX_STORE   > 0
static char cmd_store[TASH_MAX_STORE][TASH_LINEBUFLEN];
static char cmd_line[TASH_LINEBUFLEN];
static int cmd_pos;
static int cmd_head;
static int cmd_tail;
#endif

/****************************************************************************
 * Private Functions
 ****************************************************************************/

static void tash_sort_cmds(void)
{
	int i;
	int j;
	int length = tash_cmds_info.count;
	int gap = tash_cmds_info.count;
	struct tash_cmd_s temp;
	int tash_cmd_size = sizeof(struct tash_cmd_s);

	while (gap > 1) {
		/* gap = max(floor(gap * 5 / 11), 1) */

		gap = (gap * 5 / 11) > 1 ? (gap * 5 / 11) : 1;
		for (i = gap; i < length; i++) {
			memcpy(&temp, &tash_cmds_info.cmd[i], tash_cmd_size);
			for (j = i; j >= gap && (strcmp(temp.str, tash_cmds_info.cmd[j - gap].str) < 0); j -= gap) {
				memcpy(&tash_cmds_info.cmd[j], &tash_cmds_info.cmd[j - gap], tash_cmd_size);
			}
			memcpy(&tash_cmds_info.cmd[j], &temp, tash_cmd_size);
		}
	}
}

/** @brief Help function in TASH to list all available commands
 *  @ingroup tash
 */
static int tash_help(int argc, char **args)
{
	int cmd_idx;

	printf("\t TASH command list \n");
	printf("\t --------------------\n");

	if (is_sorted_list == FALSE) {
		tash_sort_cmds();
		is_sorted_list = TRUE;
	}

	for (cmd_idx = 0; cmd_idx < tash_cmds_info.count; cmd_idx++) {
		printf("%-16s ", tash_cmds_info.cmd[cmd_idx].str);
		if (cmd_idx % TASH_CMDS_PER_LINE == (TASH_CMDS_PER_LINE - 1)) {
			printf("\n");
		}
	}
	printf("\n");

	return 0;
}

/** @brief TASH exit function. It cannot be re-launched.
 *  @ingroup tash
 */
static int tash_exit(int argc, char **args)
{
	printf("TASH: Good bye!!\n");
	tash_stop();
	exit(0);
}

/** @brief Help function in TASH to list all available commands
 *  @ingroup tash
 */<commit_msg>apps/shell: Add clear command on TASH<commit_after>/****************************************************************************
 *
 * Copyright 2016 Samsung Electronics All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 *
 ****************************************************************************/
/// @file   tash_command.c
/// @brief  functions to treate commands

#include <pthread.h>
#include <tinyara/config.h>
#include <tinyara/ascii.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/boardctl.h>
#include <apps/shell/tash.h>
#ifdef CONFIG_BUILTIN_APPS
#include <apps/builtin.h>
#endif
#include "tash_internal.h"

/****************************************************************************
 * Preprocessor Definitions
 ****************************************************************************/

/* Following defines are fixed to avoid many configuration variables for TASH */
#define TASH_CMD_MAXSTRLENGTH		(16) /* example: length of "ifconfig" command is 8 */
#ifdef CONFIG_TASH_MAX_COMMANDS
#define TASH_MAX_COMMANDS			CONFIG_TASH_MAX_COMMANDS
#else
#define TASH_MAX_COMMANDS			(32)
#endif
#ifdef CONFIG_TASH_CMDTASK_STACKSIZE
#define TASH_CMDTASK_STACKSIZE		CONFIG_TASH_CMDTASK_STACKSIZE
#else
#define TASH_CMDTASK_STACKSIZE		(4096)
#endif
#ifdef CONFIG_TASH_CMDTASK_PRIORITY
#define TASH_CMDTASK_PRIORITY		CONFIG_TASH_CMDTASK_PRIORITY
#else
#define TASH_CMDTASK_PRIORITY		(SCHED_PRIORITY_DEFAULT)
#endif
#define TASH_CMDS_PER_LINE			(4)

#if TASH_MAX_STORE > 0
#define CMD_INDEX_UP(x)                                   \
	do {                                                  \
		((x) == TASH_MAX_STORE - 1) ? (x) = 0 : (x)++;    \
	} while (0)

#define CMD_INDEX_DOWN(x)                                 \
	do {                                                  \
		((x) == 0) ? (x) = TASH_MAX_STORE - 1 : (x)--;    \
	} while (0)
#endif
/****************************************************************************
 * Global Variables
 ****************************************************************************/

/****************************************************************************
 * Private Type Declarations
 ****************************************************************************/

/**
 * @brief TASH internal data structure to store command strings & callback function
 * pointers
 */
struct tash_cmd_s {
	char str[TASH_CMD_MAXSTRLENGTH];	/* Command strings- eg, ifconfig */
	TASH_CMD_CALLBACK cb;				/* Function pointer for Callback */
	int exec_type;						/* Execution type of this command */
};

struct tash_cmd_info_s {
	pthread_mutex_t tmutex;						/* Mutex for protection */
	struct tash_cmd_s cmd[TASH_MAX_COMMANDS];
	int count;									/* Number of TASH commands */
};

/********************************************************************************
 * Private Function Prototypes
 ********************************************************************************/

static int tash_help(int argc, char **args);
static int tash_clear(int argc, char **args);
static int tash_exit(int argc, char **args);
#if defined(CONFIG_BOARDCTL_RESET)
static int tash_reboot(int argc, char **argv);
#endif
#if TASH_MAX_STORE   > 0
static int tash_history(int argc, char **argv);
#endif

/****************************************************************************
 * Private Variables
 ****************************************************************************/

static int is_sorted_list = FALSE;
static struct tash_cmd_info_s tash_cmds_info = {PTHREAD_MUTEX_INITIALIZER};

const static tash_cmdlist_t tash_basic_cmds[] = {
	{"exit",  tash_exit,   TASH_EXECMD_SYNC},
	{"help",  tash_help,   TASH_EXECMD_SYNC},
	{"clear",  tash_clear,   TASH_EXECMD_SYNC},
#ifdef CONFIG_TASH_SCRIPT
	{"sh",    tash_script, TASH_EXECMD_SYNC},
#endif
#ifndef CONFIG_DISABLE_SIGNALS
	{"sleep", tash_sleep,  TASH_EXECMD_SYNC},
#ifdef CONFIG_TASH_USLEEP
	{"usleep", tash_usleep, TASH_EXECMD_SYNC},
#endif
#endif
#if defined(CONFIG_BOARDCTL_RESET)
	{"reboot", tash_reboot, TASH_EXECMD_SYNC},
#endif
#if TASH_MAX_STORE > 0
	{"history", tash_history, TASH_EXECMD_SYNC},
#endif
	{NULL,    NULL,        0}
};

#if TASH_MAX_STORE   > 0
static char cmd_store[TASH_MAX_STORE][TASH_LINEBUFLEN];
static char cmd_line[TASH_LINEBUFLEN];
static int cmd_pos;
static int cmd_head;
static int cmd_tail;
#endif

/****************************************************************************
 * Private Functions
 ****************************************************************************/

static void tash_sort_cmds(void)
{
	int i;
	int j;
	int length = tash_cmds_info.count;
	int gap = tash_cmds_info.count;
	struct tash_cmd_s temp;
	int tash_cmd_size = sizeof(struct tash_cmd_s);

	while (gap > 1) {
		/* gap = max(floor(gap * 5 / 11), 1) */

		gap = (gap * 5 / 11) > 1 ? (gap * 5 / 11) : 1;
		for (i = gap; i < length; i++) {
			memcpy(&temp, &tash_cmds_info.cmd[i], tash_cmd_size);
			for (j = i; j >= gap && (strcmp(temp.str, tash_cmds_info.cmd[j - gap].str) < 0); j -= gap) {
				memcpy(&tash_cmds_info.cmd[j], &tash_cmds_info.cmd[j - gap], tash_cmd_size);
			}
			memcpy(&tash_cmds_info.cmd[j], &temp, tash_cmd_size);
		}
	}
}

/** @brief Help function in TASH to list all available commands
 *  @ingroup tash
 */
static int tash_help(int argc, char **args)
{
	int cmd_idx;

	printf("\t TASH command list \n");
	printf("\t --------------------\n");

	if (is_sorted_list == FALSE) {
		tash_sort_cmds();
		is_sorted_list = TRUE;
	}

	for (cmd_idx = 0; cmd_idx < tash_cmds_info.count; cmd_idx++) {
		printf("%-16s ", tash_cmds_info.cmd[cmd_idx].str);
		if (cmd_idx % TASH_CMDS_PER_LINE == (TASH_CMDS_PER_LINE - 1)) {
			printf("\n");
		}
	}
	printf("\n");

	return 0;
}

/** @brief Clear the terminal screen and move cursor to top
 *  @ingroup tash
 */
static int tash_clear(int argc, char **args)
{
	printf("\x1b[1;1H\x1b[2J\n");
	return 0;
}

/** @brief TASH exit function. It cannot be re-launched.
 *  @ingroup tash
 */
static int tash_exit(int argc, char **args)
{
	printf("TASH: Good bye!!\n");
	tash_stop();
	exit(0);
}

/** @brief Help function in TASH to list all available commands
 *  @ingroup tash
 */
{'fraction_non_alphanumeric': 0.2671059688912727, 'fraction_numerical': 0.007968738027737338, 'mean_word_length': 4.463373796567602, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4249585', 'n_tokens_mistral': 4412, 'n_tokens_neox': 4131, 'n_words': 1055}