2015-03-01 07:50:13 +00:00
/* Copyright (C) 2014-2015 by Jacob Alexander
2014-01-20 00:40:36 +00:00
*
2011-09-30 05:22:19 +00:00
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
2014-01-20 00:40:36 +00:00
*
2011-09-30 05:22:19 +00:00
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
2014-01-20 00:40:36 +00:00
*
2011-09-30 05:22:19 +00:00
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
// ----- Includes -----
// Compiler Includes
2014-01-20 00:40:36 +00:00
//#include <stdarg.h>
2011-09-30 05:22:19 +00:00
2014-01-20 00:40:36 +00:00
// Project Includes
2014-01-23 10:01:12 +00:00
# include <buildvars.h>
2014-01-20 00:40:36 +00:00
# include "cli.h"
2014-01-23 10:01:12 +00:00
# include <led.h>
2014-01-22 08:38:53 +00:00
# include <print.h>
// ----- Variables -----
// Basic command dictionary
2015-04-02 06:38:26 +00:00
CLIDict_Entry ( clear , " Clear the screen. " ) ;
2014-10-03 05:09:34 +00:00
CLIDict_Entry ( cliDebug , " Enables/Disables hex output of the most recent cli input. " ) ;
CLIDict_Entry ( help , " You're looking at it :P " ) ;
CLIDict_Entry ( led , " Enables/Disables indicator LED. Try a couple times just in case the LED is in an odd state. \r \n \t \t \033 [33mWarning \033 [0m: May adversely affect some modules... " ) ;
CLIDict_Entry ( reload , " Signals microcontroller to reflash/reload. " ) ;
CLIDict_Entry ( reset , " Resets the terminal back to initial settings. " ) ;
CLIDict_Entry ( restart , " Sends a software restart, should be similar to powering on the device. " ) ;
CLIDict_Entry ( version , " Version information about this firmware. " ) ;
CLIDict_Def ( basicCLIDict , " General Commands " ) = {
2015-04-02 06:38:26 +00:00
CLIDict_Item ( clear ) ,
2014-10-03 05:09:34 +00:00
CLIDict_Item ( cliDebug ) ,
CLIDict_Item ( help ) ,
CLIDict_Item ( led ) ,
CLIDict_Item ( reload ) ,
CLIDict_Item ( reset ) ,
CLIDict_Item ( restart ) ,
CLIDict_Item ( version ) ,
2014-01-22 08:38:53 +00:00
{ 0 , 0 , 0 } // Null entry for dictionary end
} ;
2013-01-27 06:47:52 +00:00
2011-09-30 05:22:19 +00:00
// ----- Functions -----
2014-01-22 08:38:53 +00:00
inline void prompt ( )
{
2014-01-24 11:01:09 +00:00
print ( " \033 [2K \r " ) ; // Erases the current line and resets cursor to beginning of line
print ( " \033 [1;34m: \033 [0m " ) ; // Blue bold prompt
2014-01-22 08:38:53 +00:00
}
2014-01-23 10:36:00 +00:00
// Initialize the CLI
2014-04-06 18:49:27 +00:00
inline void CLI_init ( )
2014-01-22 08:38:53 +00:00
{
// Reset the Line Buffer
CLILineBufferCurrent = 0 ;
2015-04-02 07:19:09 +00:00
// History starts empty
CLIHistoryHead = 0 ;
CLIHistoryCurrent = 0 ;
CLIHistoryTail = 0 ;
2014-01-22 08:38:53 +00:00
// Set prompt
prompt ( ) ;
// Register first dictionary
CLIDictionariesUsed = 0 ;
2014-04-06 18:49:27 +00:00
CLI_registerDictionary ( basicCLIDict , basicCLIDictName ) ;
2014-01-23 10:01:12 +00:00
// Initialize main LED
init_errorLED ( ) ;
CLILEDState = 0 ;
2014-01-23 10:36:00 +00:00
// Hex debug mode is off by default
CLIHexDebugMode = 0 ;
2014-01-22 08:38:53 +00:00
}
2014-01-23 10:36:00 +00:00
// Query the serial input buffer for any new characters
2014-04-06 18:49:27 +00:00
void CLI_process ( )
2014-01-22 08:38:53 +00:00
{
// Current buffer position
uint8_t prev_buf_pos = CLILineBufferCurrent ;
// Process each character while available
while ( 1 )
{
// No more characters to process
2014-04-06 18:49:27 +00:00
if ( Output_availablechar ( ) = = 0 )
2014-01-22 08:38:53 +00:00
break ;
2014-03-31 08:07:48 +00:00
// Retrieve from output module
2014-04-06 18:49:27 +00:00
char cur_char = ( char ) Output_getchar ( ) ;
2014-01-22 08:38:53 +00:00
// Make sure buffer isn't full
if ( CLILineBufferCurrent > = CLILineBufferMaxSize )
{
print ( NL ) ;
erro_print ( " Serial line buffer is full, dropping character and resetting... " ) ;
// Clear buffer
CLILineBufferCurrent = 0 ;
// Reset the prompt
prompt ( ) ;
return ;
}
// Place into line buffer
CLILineBuffer [ CLILineBufferCurrent + + ] = cur_char ;
}
2014-01-23 10:36:00 +00:00
// Display Hex Key Input if enabled
if ( CLIHexDebugMode & & CLILineBufferCurrent > prev_buf_pos )
{
print ( " \033 [s \r \n " ) ; // Save cursor position, and move to the next line
print ( " \033 [2K " ) ; // Erases the current line
uint8_t pos = prev_buf_pos ;
while ( CLILineBufferCurrent > pos )
{
printHex ( CLILineBuffer [ pos + + ] ) ;
print ( " " ) ;
}
print ( " \033 [u " ) ; // Restore cursor position
}
2014-01-22 08:38:53 +00:00
// If buffer has changed, output to screen while there are still characters in the buffer not displayed
while ( CLILineBufferCurrent > prev_buf_pos )
{
// Check for control characters
switch ( CLILineBuffer [ prev_buf_pos ] )
{
case 0x0D : // Enter
2014-02-04 08:27:33 +00:00
CLILineBuffer [ CLILineBufferCurrent - 1 ] = ' ' ; // Replace Enter with a space (resolves a bug in args)
// Remove the space if there is no command
if ( CLILineBufferCurrent = = 1 )
CLILineBufferCurrent - - ;
2014-01-22 08:38:53 +00:00
// Process the current line buffer
2014-04-06 18:49:27 +00:00
CLI_commandLookup ( ) ;
2014-01-22 08:38:53 +00:00
2015-04-02 07:19:09 +00:00
// Add the command to the history
2015-04-03 06:53:19 +00:00
cli_saveHistory ( CLILineBuffer ) ;
2015-04-02 07:19:09 +00:00
// Keep the array circular, discarding the older entries
2015-04-03 06:53:19 +00:00
if ( CLIHistoryTail < CLIHistoryHead )
CLIHistoryHead = ( CLIHistoryHead + 1 ) % CLIMaxHistorySize ;
2015-04-02 07:19:09 +00:00
CLIHistoryTail + + ;
2015-04-03 06:53:19 +00:00
if ( CLIHistoryTail = = CLIMaxHistorySize )
2015-04-02 07:19:09 +00:00
{
CLIHistoryTail = 0 ;
CLIHistoryHead = 1 ;
}
CLIHistoryCurrent = CLIHistoryTail ; // 'Up' starts at the last item
2015-04-03 06:53:19 +00:00
cli_saveHistory ( NULL ) ; // delete the old temp buffer
2015-04-02 07:19:09 +00:00
2014-01-22 08:38:53 +00:00
// Reset the buffer
CLILineBufferCurrent = 0 ;
// Reset the prompt after processing has finished
print ( NL ) ;
prompt ( ) ;
// XXX There is a potential bug here when resetting the buffer (losing valid keypresses)
// Doesn't look like it will happen *that* often, so not handling it for now -HaaTa
return ;
case 0x09 : // Tab
// Tab completion for the current command
2014-04-06 18:49:27 +00:00
CLI_tabCompletion ( ) ;
2014-01-24 11:01:09 +00:00
CLILineBufferCurrent - - ; // Remove the Tab
// XXX There is a potential bug here when resetting the buffer (losing valid keypresses)
// Doesn't look like it will happen *that* often, so not handling it for now -HaaTa
2014-01-22 08:38:53 +00:00
return ;
2015-04-02 07:19:09 +00:00
case 0x1B : // Esc / Escape codes
// Check for other escape sequence
// \e[ is an escape code in vt100 compatable terminals
2015-04-03 06:53:19 +00:00
if ( CLILineBufferCurrent > = prev_buf_pos + 3
& & CLILineBuffer [ prev_buf_pos ] = = 0x1B
& & CLILineBuffer [ prev_buf_pos + 1 ] = = 0x5B )
2015-04-02 07:19:09 +00:00
{
// Arrow Keys: A (0x41) = Up, B (0x42) = Down, C (0x43) = Right, D (0x44) = Left
2015-04-03 06:53:19 +00:00
if ( CLILineBuffer [ prev_buf_pos + 2 ] = = 0x41 ) // Hist prev
2015-04-02 07:19:09 +00:00
{
2015-04-03 06:53:19 +00:00
if ( CLIHistoryCurrent = = CLIHistoryTail )
2015-04-02 07:19:09 +00:00
{
// Is first time pressing arrow. Save the current buffer
2015-04-03 06:53:19 +00:00
CLILineBuffer [ prev_buf_pos ] = ' \0 ' ;
cli_saveHistory ( CLILineBuffer ) ;
2015-04-02 07:19:09 +00:00
}
// Grab the previus item from the history if there is one
2015-04-03 06:53:19 +00:00
if ( RING_PREV ( CLIHistoryCurrent ) ! = RING_PREV ( CLIHistoryHead ) )
CLIHistoryCurrent = RING_PREV ( CLIHistoryCurrent ) ;
cli_retreiveHistory ( CLIHistoryCurrent ) ;
2015-04-02 07:19:09 +00:00
}
2015-04-03 06:53:19 +00:00
if ( CLILineBuffer [ prev_buf_pos + 2 ] = = 0x42 ) // Hist next
2015-04-02 07:19:09 +00:00
{
// Grab the next item from the history if it exists
2015-04-03 06:53:19 +00:00
if ( RING_NEXT ( CLIHistoryCurrent ) ! = RING_NEXT ( CLIHistoryTail ) )
CLIHistoryCurrent = RING_NEXT ( CLIHistoryCurrent ) ;
cli_retreiveHistory ( CLIHistoryCurrent ) ;
2015-04-02 07:19:09 +00:00
}
}
2014-01-22 08:38:53 +00:00
return ;
case 0x08 :
case 0x7F : // Backspace
// TODO - Does not handle case for arrow editing (arrows disabled atm)
CLILineBufferCurrent - - ; // Remove the backspace
// If there are characters in the buffer
if ( CLILineBufferCurrent > 0 )
{
// Remove character from current position in the line buffer
CLILineBufferCurrent - - ;
// Remove character from tty
print ( " \b \b " ) ;
}
break ;
default :
// Place a null on the end (to use with string print)
CLILineBuffer [ CLILineBufferCurrent ] = ' \0 ' ;
// Output buffer to screen
dPrint ( & CLILineBuffer [ prev_buf_pos ] ) ;
// Buffer reset
prev_buf_pos + + ;
break ;
}
}
}
2014-01-22 09:58:34 +00:00
// Takes a string, returns two pointers
// One to the first non-space character
// The second to the next argument (first NULL if there isn't an argument). delimited by a space
// Places a NULL at the first space after the first argument
2014-04-06 20:12:31 +00:00
void CLI_argumentIsolation ( char * string , char * * first , char * * second )
2014-01-22 08:38:53 +00:00
{
// Mark out the first argument
// This is done by finding the first space after a list of non-spaces and setting it NULL
2014-01-22 09:58:34 +00:00
char * cmdPtr = string - 1 ;
2014-01-22 08:38:53 +00:00
while ( * + + cmdPtr = = ' ' ) ; // Skips leading spaces, and points to first character of cmd
2014-01-22 09:10:32 +00:00
// Locates first space delimiter
char * argPtr = cmdPtr + 1 ;
while ( * argPtr ! = ' ' & & * argPtr ! = ' \0 ' )
2014-01-22 08:38:53 +00:00
argPtr + + ;
2014-01-22 09:10:32 +00:00
// Point to the first character of args or a NULL (no args) and set the space delimiter as a NULL
( + + argPtr ) [ - 1 ] = ' \0 ' ;
2014-01-22 08:38:53 +00:00
2014-01-22 09:58:34 +00:00
// Set return variables
* first = cmdPtr ;
* second = argPtr ;
}
2014-01-23 10:36:00 +00:00
// Scans the CLILineBuffer for any valid commands
2014-04-06 18:49:27 +00:00
void CLI_commandLookup ( )
2014-01-22 09:58:34 +00:00
{
// Ignore command if buffer is 0 length
if ( CLILineBufferCurrent = = 0 )
return ;
// Set the last+1 character of the buffer to NULL for string processing
CLILineBuffer [ CLILineBufferCurrent ] = ' \0 ' ;
// Retrieve pointers to command and beginning of arguments
// Places a NULL at the first space after the command
char * cmdPtr ;
char * argPtr ;
2014-04-06 18:49:27 +00:00
CLI_argumentIsolation ( CLILineBuffer , & cmdPtr , & argPtr ) ;
2014-01-22 09:58:34 +00:00
2014-01-22 08:38:53 +00:00
// Scan array of dictionaries for a valid command match
for ( uint8_t dict = 0 ; dict < CLIDictionariesUsed ; dict + + )
{
// Parse each cmd until a null command entry is found, or an argument match
for ( uint8_t cmd = 0 ; CLIDict [ dict ] [ cmd ] . name ! = 0 ; cmd + + )
{
// Compare the first argument and each command entry
2014-10-03 05:09:34 +00:00
if ( eqStr ( cmdPtr , ( char * ) CLIDict [ dict ] [ cmd ] . name ) = = - 1 )
2014-01-22 08:38:53 +00:00
{
// Run the specified command function pointer
// argPtr is already pointing at the first character of the arguments
2014-10-03 05:09:34 +00:00
( * ( void ( * ) ( char * ) ) CLIDict [ dict ] [ cmd ] . function ) ( argPtr ) ;
2014-01-22 08:38:53 +00:00
return ;
}
}
}
// No match for the command...
print ( NL ) ;
2014-01-22 09:58:34 +00:00
erro_dPrint ( " \" " , CLILineBuffer , " \" is not a valid command...type \033 [35mhelp \033 [0m " ) ;
2014-01-22 08:38:53 +00:00
}
2014-01-23 10:36:00 +00:00
// Registers a command dictionary with the CLI
2014-08-15 17:42:12 +00:00
void CLI_registerDictionary ( const CLIDictItem * cmdDict , const char * dictName )
2014-01-22 08:38:53 +00:00
{
// Make sure this max limit of dictionaries hasn't been reached
if ( CLIDictionariesUsed > = CLIMaxDictionaries )
{
erro_print ( " Max number of dictionaries defined already... " ) ;
return ;
}
// Add dictionary
2014-08-15 17:42:12 +00:00
CLIDictNames [ CLIDictionariesUsed ] = ( char * ) dictName ;
CLIDict [ CLIDictionariesUsed + + ] = ( CLIDictItem * ) cmdDict ;
2014-01-22 08:38:53 +00:00
}
2014-04-06 18:49:27 +00:00
inline void CLI_tabCompletion ( )
2014-01-24 11:01:09 +00:00
{
// Ignore command if buffer is 0 length
if ( CLILineBufferCurrent = = 0 )
return ;
// Set the last+1 character of the buffer to NULL for string processing
CLILineBuffer [ CLILineBufferCurrent ] = ' \0 ' ;
// Retrieve pointers to command and beginning of arguments
// Places a NULL at the first space after the command
char * cmdPtr ;
char * argPtr ;
2014-04-06 18:49:27 +00:00
CLI_argumentIsolation ( CLILineBuffer , & cmdPtr , & argPtr ) ;
2014-01-24 11:01:09 +00:00
// Tab match pointer
char * tabMatch = 0 ;
uint8_t matches = 0 ;
// Scan array of dictionaries for a valid command match
for ( uint8_t dict = 0 ; dict < CLIDictionariesUsed ; dict + + )
{
// Parse each cmd until a null command entry is found, or an argument match
for ( uint8_t cmd = 0 ; CLIDict [ dict ] [ cmd ] . name ! = 0 ; cmd + + )
{
// Compare the first argument piece to each command entry to see if it is "like"
// NOTE: To save on processing, we only care about the commands and ignore the arguments
// If there are arguments, and a valid tab match is found, buffer is cleared (args lost)
// Also ignores full matches
2014-10-03 05:09:34 +00:00
if ( eqStr ( cmdPtr , ( char * ) CLIDict [ dict ] [ cmd ] . name ) = = 0 )
2014-01-24 11:01:09 +00:00
{
// TODO Make list of commands if multiple matches
matches + + ;
2014-10-03 05:09:34 +00:00
tabMatch = ( char * ) CLIDict [ dict ] [ cmd ] . name ;
2014-01-24 11:01:09 +00:00
}
}
}
// Only tab complete if there was 1 match
if ( matches = = 1 )
{
// Reset the buffer
CLILineBufferCurrent = 0 ;
// Reprint the prompt (automatically clears the line)
prompt ( ) ;
// Display the command
dPrint ( tabMatch ) ;
// There are no index counts, so just copy the whole string to the input buffer
while ( * tabMatch ! = ' \0 ' )
{
CLILineBuffer [ CLILineBufferCurrent + + ] = * tabMatch + + ;
}
}
}
2015-04-03 06:53:19 +00:00
inline int CLI_wrap ( int kX , int const kLowerBound , int const kUpperBound )
2015-04-02 07:19:09 +00:00
{
int range_size = kUpperBound - kLowerBound + 1 ;
2015-04-03 06:53:19 +00:00
if ( kX < kLowerBound )
2015-04-02 07:19:09 +00:00
kX + = range_size * ( ( kLowerBound - kX ) / range_size + 1 ) ;
return kLowerBound + ( kX - kLowerBound ) % range_size ;
}
2015-04-03 06:53:19 +00:00
inline void CLI_saveHistory ( char * buff )
{
if ( buff = = NULL )
{
2015-04-02 07:19:09 +00:00
//clear the item
2015-04-03 06:53:19 +00:00
CLIHistoryBuffer [ CLIHistoryTail ] [ 0 ] = ' \0 ' ;
2015-04-02 07:19:09 +00:00
return ;
}
// Copy the line to the history
int i ;
2015-04-03 06:53:19 +00:00
for ( i = 0 ; i < CLILineBufferCurrent ; i + + )
2015-04-02 07:19:09 +00:00
{
2015-04-03 06:53:19 +00:00
CLIHistoryBuffer [ CLIHistoryTail ] [ i ] = CLILineBuffer [ i ] ;
2015-04-02 07:19:09 +00:00
}
}
2015-04-03 06:53:19 +00:00
void CLI_retreiveHistory ( int index )
{
char * histMatch = CLIHistoryBuffer [ index ] ;
2015-04-02 07:19:09 +00:00
// Reset the buffer
CLILineBufferCurrent = 0 ;
// Reprint the prompt (automatically clears the line)
prompt ( ) ;
// Display the command
dPrint ( histMatch ) ;
// There are no index counts, so just copy the whole string to the input buffe
CLILineBufferCurrent = 0 ;
while ( * histMatch ! = ' \0 ' )
{
2015-04-03 06:53:19 +00:00
CLILineBuffer [ CLILineBufferCurrent + + ] = * histMatch + + ;
2015-04-02 07:19:09 +00:00
}
}
2014-01-22 08:38:53 +00:00
// ----- CLI Command Functions -----
2015-04-02 06:38:26 +00:00
void cliFunc_clear ( char * args )
{
print ( " \033 [2J \033 [H \r " ) ; // Erases the whole screen
}
2014-01-23 10:01:12 +00:00
void cliFunc_cliDebug ( char * args )
{
2014-01-23 10:36:00 +00:00
// Toggle Hex Debug Mode
if ( CLIHexDebugMode )
{
print ( NL ) ;
info_print ( " Hex debug mode disabled... " ) ;
CLIHexDebugMode = 0 ;
}
else
{
print ( NL ) ;
info_print ( " Hex debug mode enabled... " ) ;
CLIHexDebugMode = 1 ;
}
2014-01-23 10:01:12 +00:00
}
2014-01-22 08:38:53 +00:00
void cliFunc_help ( char * args )
{
2014-01-22 09:58:34 +00:00
// Scan array of dictionaries and print every description
// (no alphabetical here, too much processing/memory to sort...)
for ( uint8_t dict = 0 ; dict < CLIDictionariesUsed ; dict + + )
{
2014-01-24 09:56:44 +00:00
// Print the name of each dictionary as a title
2014-10-03 05:09:34 +00:00
print ( NL " \033 [1;32m " ) ;
_print ( CLIDictNames [ dict ] ) ; // This print is requride by AVR (flash)
print ( " \033 [0m " NL ) ;
2014-01-22 09:58:34 +00:00
// Parse each cmd/description until a null command entry is found
for ( uint8_t cmd = 0 ; CLIDict [ dict ] [ cmd ] . name ! = 0 ; cmd + + )
{
2014-01-23 10:01:12 +00:00
dPrintStrs ( " \033 [35m " , CLIDict [ dict ] [ cmd ] . name , " \033 [0m " ) ;
// Determine number of spaces to tab by the length of the command and TabAlign
2014-10-03 05:09:34 +00:00
uint8_t padLength = CLIEntryTabAlign - lenStr ( ( char * ) CLIDict [ dict ] [ cmd ] . name ) ;
2014-01-23 10:01:12 +00:00
while ( padLength - - > 0 )
print ( " " ) ;
2014-10-03 05:09:34 +00:00
_print ( CLIDict [ dict ] [ cmd ] . description ) ; // This print is required by AVR (flash)
print ( NL ) ;
2014-01-22 09:58:34 +00:00
}
}
2014-01-22 08:38:53 +00:00
}
2014-01-23 10:01:12 +00:00
void cliFunc_led ( char * args )
{
CLILEDState ^ = 1 < < 1 ; // Toggle between 0 and 1
errorLED ( CLILEDState ) ; // Enable/Disable error LED
}
void cliFunc_reload ( char * args )
{
// Request to output module to be set into firmware reload mode
2014-04-06 18:49:27 +00:00
Output_firmwareReload ( ) ;
2014-01-23 10:01:12 +00:00
}
void cliFunc_reset ( char * args )
2014-01-23 10:36:00 +00:00
{
print ( " \033 c " ) ; // Resets the terminal
}
void cliFunc_restart ( char * args )
2014-01-23 10:01:12 +00:00
{
// Trigger an overall software reset
2014-04-06 18:49:27 +00:00
Output_softReset ( ) ;
2014-01-23 10:01:12 +00:00
}
2014-01-22 08:38:53 +00:00
void cliFunc_version ( char * args )
2014-01-20 00:40:36 +00:00
{
2014-01-22 08:38:53 +00:00
print ( NL ) ;
2014-01-23 10:01:12 +00:00
print ( " \033 [1mRevision: \033 [0m " CLI_Revision NL ) ;
print ( " \033 [1mBranch: \033 [0m " CLI_Branch NL ) ;
2015-03-01 07:50:13 +00:00
print ( " \033 [1mTree Status: \033 [0m " CLI_ModifiedStatus CLI_ModifiedFiles NL ) ;
2014-01-23 10:01:12 +00:00
print ( " \033 [1mRepo Origin: \033 [0m " CLI_RepoOrigin NL ) ;
print ( " \033 [1mCommit Date: \033 [0m " CLI_CommitDate NL ) ;
print ( " \033 [1mCommit Author: \033 [0m " CLI_CommitAuthor NL ) ;
print ( " \033 [1mBuild Date: \033 [0m " CLI_BuildDate NL ) ;
print ( " \033 [1mBuild OS: \033 [0m " CLI_BuildOS NL ) ;
print ( " \033 [1mArchitecture: \033 [0m " CLI_Arch NL ) ;
print ( " \033 [1mChip: \033 [0m " CLI_Chip NL ) ;
print ( " \033 [1mCPU: \033 [0m " CLI_CPU NL ) ;
print ( " \033 [1mDevice: \033 [0m " CLI_Device NL ) ;
print ( " \033 [1mModules: \033 [0m " CLI_Modules NL ) ;
2014-01-20 00:40:36 +00:00
}
2011-09-30 05:22:19 +00:00