//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2015 Authors and OPENCORES.ORG ////
|
//// Copyright (C) 2015 Authors and OPENCORES.ORG ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
|
|
#include "sys_cmd.h"
|
#include "sys_cmd.h"
|
#include "sys_error.h"
|
#include "sys_error.h"
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
void clear_screen(void)
|
void clear_screen(void)
|
{
|
{
|
PRINTF_MACRO("\033[H\033[J");
|
PRINTF_MACRO("\033[H\033[J");
|
}
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
#ifdef ANSI_ESCAPE_CODE
|
#ifdef ANSI_ESCAPE_CODE
|
#define ASCII_ESC '\x1b'
|
#define ASCII_ESC '\x1b'
|
|
|
static void send_csi(char c)
|
static void send_csi(char c)
|
{
|
{
|
putchar(ASCII_ESC);
|
putchar(ASCII_ESC);
|
putchar('[');
|
putchar('[');
|
putchar(c);
|
putchar(c);
|
}
|
}
|
#else
|
#else
|
static void send_csi(char c) {};
|
static void send_csi(char c) {};
|
#endif
|
#endif
|
|
|
|
|
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
static char *cli_edit_buffer(char *in_buffer, char *out_buffer, unsigned int line_length)
|
static char *cli_edit_buffer(char *in_buffer, char *out_buffer, unsigned int line_length)
|
{
|
{
|
static char *out_ptr;
|
static char *out_ptr;
|
static char *begin_ptr;
|
static char *begin_ptr;
|
static char *end_ptr;
|
static char *end_ptr;
|
|
|
#ifdef ANSI_ESCAPE_CODE
|
#ifdef ANSI_ESCAPE_CODE
|
static char prev_char;
|
static char prev_char;
|
static unsigned int csi;
|
static unsigned int csi;
|
#endif
|
#endif
|
|
|
|
#ifdef CLI_ECHO_UART
|
|
fwrite(in_buffer,1,line_length,stdout);
|
|
#endif
|
|
|
unsigned int i;
|
unsigned int i;
|
|
|
if(out_buffer != NULL)
|
if(out_buffer != NULL)
|
{
|
{
|
out_ptr = out_buffer;
|
out_ptr = out_buffer;
|
begin_ptr = out_buffer;
|
begin_ptr = out_buffer;
|
end_ptr = out_buffer + INPUT_LINE_LENGTH;
|
end_ptr = out_buffer + INPUT_LINE_LENGTH;
|
|
|
#ifdef ANSI_ESCAPE_CODE
|
#ifdef ANSI_ESCAPE_CODE
|
prev_char = 0;
|
prev_char = 0;
|
csi = 0;
|
csi = 0;
|
#endif
|
#endif
|
}
|
}
|
|
|
for(i = 0 ; i < line_length ; i++)
|
for(i = 0 ; i < line_length ; i++)
|
{
|
{
|
|
|
if(out_ptr >= end_ptr)
|
if(out_ptr >= end_ptr)
|
{
|
{
|
*end_ptr = '\0';
|
*end_ptr = '\0';
|
return(NULL);
|
return(NULL);
|
}
|
}
|
|
|
if(out_ptr < begin_ptr)
|
if(out_ptr < begin_ptr)
|
sys_error_fatal(FATAL_ERROR_CLI);
|
sys_error_fatal(FATAL_ERROR_CLI);
|
|
|
switch(in_buffer[i])
|
switch(in_buffer[i])
|
{
|
{
|
case '\0':
|
case '\0':
|
return(NULL);
|
return(NULL);
|
break;
|
break;
|
|
|
case '\n':
|
case '\n':
|
*out_ptr = '\0';
|
*out_ptr = '\0';
|
return(NULL);
|
return(NULL);
|
break;
|
break;
|
|
|
case '\r':
|
case '\r':
|
*out_ptr = '\0';
|
*out_ptr = '\0';
|
return(NULL);
|
return(NULL);
|
break;
|
break;
|
|
|
case '\b':
|
case '\b':
|
if(out_ptr != begin_ptr)
|
if(out_ptr != begin_ptr)
|
{
|
{
|
send_csi('P');
|
send_csi('P');
|
out_ptr--;
|
out_ptr--;
|
} else
|
} else
|
{
|
{
|
putchar(' ');
|
putchar(' ');
|
send_csi('\a');
|
send_csi('\a');
|
}
|
}
|
break;
|
break;
|
|
|
#ifdef ANSI_ESCAPE_CODE
|
#ifdef ANSI_ESCAPE_CODE
|
case ASCII_ESC:
|
case ASCII_ESC:
|
break;
|
break;
|
|
|
case '[':
|
case '[':
|
if(prev_char == ASCII_ESC)
|
if(prev_char == ASCII_ESC)
|
{
|
{
|
csi = 1;
|
csi = 1;
|
} else
|
} else
|
{
|
{
|
*out_ptr = in_buffer[i];
|
*out_ptr = in_buffer[i];
|
out_ptr++;
|
out_ptr++;
|
}
|
}
|
break;
|
break;
|
|
|
case 'A':
|
case 'A':
|
if(csi)
|
if(csi)
|
{
|
{
|
send_csi('B');
|
send_csi('B');
|
send_csi('\a');
|
send_csi('\a');
|
|
|
csi = 0;
|
csi = 0;
|
} else
|
} else
|
{
|
{
|
*out_ptr = in_buffer[i];
|
*out_ptr = in_buffer[i];
|
out_ptr++;
|
out_ptr++;
|
}
|
}
|
break;
|
break;
|
|
|
case 'B':
|
case 'B':
|
if(csi == 0)
|
if(csi == 0)
|
{
|
{
|
*out_ptr = in_buffer[i];
|
*out_ptr = in_buffer[i];
|
out_ptr++;
|
out_ptr++;
|
}
|
}
|
break;
|
break;
|
|
|
case 'C':
|
case 'C':
|
if(csi)
|
if(csi)
|
{
|
{
|
send_csi('D');
|
send_csi('D');
|
send_csi('\a');
|
send_csi('\a');
|
|
|
csi = 0;
|
csi = 0;
|
} else
|
} else
|
{
|
{
|
*out_ptr = in_buffer[i];
|
*out_ptr = in_buffer[i];
|
out_ptr++;
|
out_ptr++;
|
}
|
}
|
break;
|
break;
|
|
|
case 'D':
|
case 'D':
|
if(csi)
|
if(csi)
|
{
|
{
|
send_csi('C');
|
send_csi('C');
|
send_csi('\a');
|
send_csi('\a');
|
|
|
csi = 0;
|
csi = 0;
|
} else
|
} else
|
{
|
{
|
*out_ptr = in_buffer[i];
|
*out_ptr = in_buffer[i];
|
out_ptr++;
|
out_ptr++;
|
}
|
}
|
break;
|
break;
|
#endif
|
#endif
|
|
|
default:
|
default:
|
*out_ptr = in_buffer[i];
|
*out_ptr = in_buffer[i];
|
out_ptr++;
|
out_ptr++;
|
break;
|
break;
|
}
|
}
|
|
|
#ifdef ANSI_ESCAPE_CODE
|
#ifdef ANSI_ESCAPE_CODE
|
prev_char = in_buffer[i];
|
prev_char = in_buffer[i];
|
#endif
|
#endif
|
}
|
}
|
|
|
return(out_ptr);
|
return(out_ptr);
|
}
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
void sys_cli_task(void)
|
void sys_cli_task(void)
|
{
|
{
|
char last_return_value = EXIT_SUCCESS;
|
char last_return_value = EXIT_SUCCESS;
|
char in_buffer[INPUT_LINE_LENGTH + 1];
|
char in_buffer[INPUT_LINE_LENGTH + 1];
|
char out_buffer[INPUT_LINE_LENGTH + 1];
|
char out_buffer[INPUT_LINE_LENGTH + 1];
|
char *cli_ptr;
|
char *cli_ptr;
|
struct cli_cmd_tab_t cmd_to_check = { "", NULL, NULL };
|
struct cli_cmd_tab_t cmd_to_check = { "", NULL, NULL };
|
unsigned char cli_argc;
|
unsigned char cli_argc;
|
char *cli_argv[MAX_CLI_ARGC];
|
char *cli_argv[MAX_CLI_ARGC];
|
struct cli_cmd_tab_t *cli_cmd;
|
struct cli_cmd_tab_t *cli_cmd;
|
unsigned int bytes_read;
|
unsigned int bytes_read;
|
|
|
cli_init();
|
cli_init();
|
|
|
// PRINTF_MACRO("\r\n");
|
|
|
|
for(;;)
|
for(;;)
|
{
|
{
|
// PRINTF_MACRO("%d > ", last_return_value);
|
|
PRINTF_MACRO("\r\n# > ");
|
PRINTF_MACRO("\r\n# > ");
|
|
|
cli_argc = 0;
|
cli_argc = 0;
|
last_return_value = EXIT_SUCCESS;
|
last_return_value = EXIT_SUCCESS;
|
|
|
bytes_read = (unsigned int)read(STDIN_FILENO, (void *)in_buffer, sizeof(in_buffer));
|
bytes_read = (unsigned int)read(STDIN_FILENO, (void *)in_buffer, sizeof(in_buffer));
|
cli_ptr = cli_edit_buffer(in_buffer, out_buffer, bytes_read);
|
cli_ptr = cli_edit_buffer(in_buffer, out_buffer, bytes_read);
|
|
|
while(cli_ptr != NULL)
|
while(cli_ptr != NULL)
|
{
|
{
|
bytes_read = (unsigned int)read(STDIN_FILENO, (void *)in_buffer, sizeof(in_buffer));
|
bytes_read = (unsigned int)read(STDIN_FILENO, (void *)in_buffer, sizeof(in_buffer));
|
cli_ptr = cli_edit_buffer(in_buffer, NULL, bytes_read);
|
cli_ptr = cli_edit_buffer(in_buffer, NULL, bytes_read);
|
}
|
}
|
|
|
if(out_buffer[0] == '\0')
|
if(out_buffer[0] == '\0')
|
last_return_value = EXIT_FAILURE;
|
last_return_value = EXIT_FAILURE;
|
|
|
while(last_return_value != EXIT_FAILURE)
|
while(last_return_value != EXIT_FAILURE)
|
{
|
{
|
cli_ptr = strtok(out_buffer, " \t");
|
cli_ptr = strtok(out_buffer, " \t");
|
|
|
strncpy(cmd_to_check.cmd, out_buffer, MAX_CMD_LENGTH);
|
strncpy(cmd_to_check.cmd, out_buffer, MAX_CMD_LENGTH);
|
cli_cmd = cli_find_command(&cmd_to_check);
|
cli_cmd = cli_find_command(&cmd_to_check);
|
|
|
if (cli_cmd == NULL)
|
if (cli_cmd == NULL)
|
{
|
{
|
PRINTF_MACRO("\r\n! > Command not found!!!");
|
PRINTF_MACRO("\r\n! > Command not found!!!");
|
last_return_value = EXIT_FAILURE;
|
last_return_value = EXIT_FAILURE;
|
break;
|
break;
|
}
|
}
|
|
|
if(cli_ptr == NULL)
|
if(cli_ptr == NULL)
|
{
|
{
|
cli_argv[cli_argc] = out_buffer;
|
cli_argv[cli_argc] = out_buffer;
|
cli_argc++;
|
cli_argc++;
|
} else
|
} else
|
{
|
{
|
while(cli_ptr != NULL)
|
while(cli_ptr != NULL)
|
{
|
{
|
cli_argv[cli_argc] = cli_ptr;
|
cli_argv[cli_argc] = cli_ptr;
|
cli_argc++;
|
cli_argc++;
|
|
|
cli_ptr = strtok(NULL, " \t");
|
cli_ptr = strtok(NULL, " \t");
|
}
|
}
|
}
|
}
|
|
|
// PRINTF_MACRO("\r\n");
|
|
|
|
last_return_value = cli_cmd->func(cli_argc, (const char **)cli_argv);
|
last_return_value = cli_cmd->func(cli_argc, (const char **)cli_argv);
|
break;
|
break;
|
}
|
}
|
|
|
}
|
}
|
}
|
}
|
|
|
|
|