Coding

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

In the preceding chapter, I built a clean system reset for MicroMonitor with warmstart, exception

handlers, and serial interface functions. In this chapter, I will implement a user interface through
the console port. Over the last few years, I’ve probably rewritten this command line interface
(CLI) half of a dozen times. I haven’t had any need to change it for quite some time now, so
maybe this version is a keeper.

The design goal of this CLI is to provide a good amount of flexibility without excess complexity.
This CLI provides shell variables and symbols, command line editing and history, command
output redirection, user levels, and password protection. If you don’t want all of these features,
most of this functionality can be optionally removed from the code at build time by setting a few
macros in the main MicroMonitor configuration file. To support this configurability without
being forced to scatter #ifdefs throughout the code, I have modularized the functionality and
accepted a few limitations. The end result is a fairly robust but not very complex CLI handler.

CLI Features
The CLI I develop in this chapter provides MicroMonitor with the following features:

 Functional Command Execution — All of the command line processing, except for
history and editing, is provided by a single function: docommand(). The docommand() is
passed a string from the command line and a verbosity level. Other modules in
MicroMonitor (not just the console connection) can also use docommand() to invoke
commands from within the code.
 Command Line Tokenization — Each command in the system has the standard
cmdfunc(int argc, char *argv[]) prototype. The CLI parses a string of characters into
individual white-space delimited tokens to form the argument count (argc) and argument
list (argv), which is then passed to a command-specific function.
 Shell Variables and Symbols — The command line processor makes substitutions for
shell variables and symbols. Shell variables are seen on the command line as strings
prefixed with $. The CLI looks to the string following the dollar sign to see if it matches
any of the currently stored shell variable names in MicroMonitor’s environment. If the
string matches a shell variable name, then a substitution is made; if not, the string is left
untouched. A very similar capability is provided for symbols or strings prefixed with %.
 CLI Editing and History — As each line is typed, the CLI provides the ability to modify
the already-typed characters in a way that is much more efficient than simply
backspacing to the point of the error and retyping from that point. History allows the user
to retrieve a command string that was entered earlier and either execute it again or
modify it to form a new command.
 Command Output Redirection — When the CLI passes control to a command function,
that function can use printf() and putchar() to transfer command-specific information to
the user. Redirection at the CLI means that all data printed by the command can be
redirected to RAM and eventually transferred from RAM to a file in the flash file system.
 User Levels and Password Protection — The CLI accesses each command by first
determining the current user level of the system and the user level required for the
command to execute. If the user level of the system is higher than the required user level
for the command, then the command is allowed; otherwise, the command is rejected by
the CLI.
 Fall Through to FFS for Script Execution — If the command is not found in the
command table, then as a last resort, the CLI passes the string to TFS to process as an
executable script (if a script with the same name as the command exists).
 Leading Underscore Processing — MicroMonitor can have an application running on
top of it just as can DOS. The application is likely to have its own command set, but there
are times when a command in the monitor is useful to the application (the monitor’s API
allows the application’s CLI to access commands in the monitor’s CLI). To support the
situation where the application and MicroMonitor both recognize the same command
string (“help” is the most common example), the monitor’s CLI throws away a leading
underscore. Thus the the string _help can be passed to an application where it will fall
through to the monitor’s CLI and be processed as help.

In the preceding chapter, I built a clean system reset for MicroMonitor with warmstart, exception
handlers, and serial interface functions. In this chapter, I will implement a user interface through
the console port. Over the last few years, I’ve probably rewritten this command line interface
(CLI) half of a dozen times. I haven’t had any need to change it for quite some time now, so
maybe this version is a keeper.

The design goal of this CLI is to provide a good amount of flexibility without excess complexity.
This CLI provides shell variables and symbols, command line editing and history, command
output redirection, user levels, and password protection. If you don’t want all of these features,
most of this functionality can be optionally removed from the code at build time by setting a few
macros in the main MicroMonitor configuration file. To support this configurability without
being forced to scatter #ifdefs throughout the code, I have modularized the functionality and
accepted a few limitations. The end result is a fairly robust but not very complex CLI handler.

CLI Features
The CLI I develop in this chapter provides MicroMonitor with the following features:

 Functional Command Execution — All of the command line processing, except for
history and editing, is provided by a single function: docommand(). The docommand() is
passed a string from the command line and a verbosity level. Other modules in
MicroMonitor (not just the console connection) can also use docommand() to invoke
commands from within the code.
 Command Line Tokenization — Each command in the system has the standard
cmdfunc(int argc, char *argv[]) prototype. The CLI parses a string of characters into
individual white-space delimited tokens to form the argument count (argc) and argument
list (argv), which is then passed to a command-specific function.
 Shell Variables and Symbols — The command line processor makes substitutions for
shell variables and symbols. Shell variables are seen on the command line as strings
prefixed with $. The CLI looks to the string following the dollar sign to see if it matches
any of the currently stored shell variable names in MicroMonitor’s environment. If the
string matches a shell variable name, then a substitution is made; if not, the string is left
untouched. A very similar capability is provided for symbols or strings prefixed with %.
 CLI Editing and History — As each line is typed, the CLI provides the ability to modify
the already-typed characters in a way that is much more efficient than simply
backspacing to the point of the error and retyping from that point. History allows the user
to retrieve a command string that was entered earlier and either execute it again or
modify it to form a new command.
 Command Output Redirection — When the CLI passes control to a command function,
that function can use printf() and putchar() to transfer command-specific information to
the user. Redirection at the CLI means that all data printed by the command can be
redirected to RAM and eventually transferred from RAM to a file in the flash file system.
 User Levels and Password Protection — The CLI accesses each command by first
determining the current user level of the system and the user level required for the
command to execute. If the user level of the system is higher than the required user level
for the command, then the command is allowed; otherwise, the command is rejected by
the CLI.
 Fall Through to FFS for Script Execution — If the command is not found in the
command table, then as a last resort, the CLI passes the string to TFS to process as an
executable script (if a script with the same name as the command exists).
 Leading Underscore Processing — MicroMonitor can have an application running on
top of it just as can DOS. The application is likely to have its own command set, but there
are times when a command in the monitor is useful to the application (the monitor’s API
allows the application’s CLI to access commands in the monitor’s CLI). To support the
situation where the application and MicroMonitor both recognize the same command
string (“help” is the most common example), the monitor’s CLI throws away a leading
underscore. Thus the the string _help can be passed to an application where it will fall
through to the monitor’s CLI and be processed as help.

In the preceding chapter, I built a clean system reset for MicroMonitor with warmstart, exception
handlers, and serial interface functions. In this chapter, I will implement a user interface through
the console port. Over the last few years, I’ve probably rewritten this command line interface
(CLI) half of a dozen times. I haven’t had any need to change it for quite some time now, so
maybe this version is a keeper.

The design goal of this CLI is to provide a good amount of flexibility without excess complexity.
This CLI provides shell variables and symbols, command line editing and history, command
output redirection, user levels, and password protection. If you don’t want all of these features,
most of this functionality can be optionally removed from the code at build time by setting a few
macros in the main MicroMonitor configuration file. To support this configurability without
being forced to scatter #ifdefs throughout the code, I have modularized the functionality and
accepted a few limitations. The end result is a fairly robust but not very complex CLI handler.

CLI Features
The CLI I develop in this chapter provides MicroMonitor with the following features:
 Functional Command Execution — All of the command line processing, except for
history and editing, is provided by a single function: docommand(). The docommand() is
passed a string from the command line and a verbosity level. Other modules in
MicroMonitor (not just the console connection) can also use docommand() to invoke
commands from within the code.
 Command Line Tokenization — Each command in the system has the standard
cmdfunc(int argc, char *argv[]) prototype. The CLI parses a string of characters into
individual white-space delimited tokens to form the argument count (argc) and argument
list (argv), which is then passed to a command-specific function.
 Shell Variables and Symbols — The command line processor makes substitutions for
shell variables and symbols. Shell variables are seen on the command line as strings
prefixed with $. The CLI looks to the string following the dollar sign to see if it matches
any of the currently stored shell variable names in MicroMonitor’s environment. If the
string matches a shell variable name, then a substitution is made; if not, the string is left
untouched. A very similar capability is provided for symbols or strings prefixed with %.
 CLI Editing and History — As each line is typed, the CLI provides the ability to modify
the already-typed characters in a way that is much more efficient than simply
backspacing to the point of the error and retyping from that point. History allows the user
to retrieve a command string that was entered earlier and either execute it again or
modify it to form a new command.
 Command Output Redirection — When the CLI passes control to a command function,
that function can use printf() and putchar() to transfer command-specific information to
the user. Redirection at the CLI means that all data printed by the command can be
redirected to RAM and eventually transferred from RAM to a file in the flash file system.
 User Levels and Password Protection — The CLI accesses each command by first
determining the current user level of the system and the user level required for the
command to execute. If the user level of the system is higher than the required user level
for the command, then the command is allowed; otherwise, the command is rejected by
the CLI.
 Fall Through to FFS for Script Execution — If the command is not found in the
command table, then as a last resort, the CLI passes the string to TFS to process as an
executable script (if a script with the same name as the command exists).
 Leading Underscore Processing — MicroMonitor can have an application running on
top of it just as can DOS. The application is likely to have its own command set, but there
are times when a command in the monitor is useful to the application (the monitor’s API
allows the application’s CLI to access commands in the monitor’s CLI). To support the
situation where the application and MicroMonitor both recognize the same command
string (“help” is the most common example), the monitor’s CLI throws away a leading
underscore. Thus the the string _help can be passed to an application where it will fall
through to the monitor’s CLI and be processed as help.

In the preceding chapter, I built a clean system reset for MicroMonitor with warmstart, exception
handlers, and serial interface functions. In this chapter, I will implement a user interface through
the console port. Over the last few years, I’ve probably rewritten this command line interface
(CLI) half of a dozen times. I haven’t had any need to change it for quite some time now, so
maybe this version is a keeper.
The design goal of this CLI is to provide a good amount of flexibility without excess complexity.
This CLI provides shell variables and symbols, command line editing and history, command
output redirection, user levels, and password protection. If you don’t want all of these features,
most of this functionality can be optionally removed from the code at build time by setting a few
macros in the main MicroMonitor configuration file. To support this configurability without
being forced to scatter #ifdefs throughout the code, I have modularized the functionality and
accepted a few limitations. The end result is a fairly robust but not very complex CLI handler.

CLI Features
The CLI I develop in this chapter provides MicroMonitor with the following features:

 Functional Command Execution — All of the command line processing, except for
history and editing, is provided by a single function: docommand(). The docommand() is
passed a string from the command line and a verbosity level. Other modules in
MicroMonitor (not just the console connection) can also use docommand() to invoke
commands from within the code.
 Command Line Tokenization — Each command in the system has the standard
cmdfunc(int argc, char *argv[]) prototype. The CLI parses a string of characters into
individual white-space delimited tokens to form the argument count (argc) and argument
list (argv), which is then passed to a command-specific function.
 Shell Variables and Symbols — The command line processor makes substitutions for
shell variables and symbols. Shell variables are seen on the command line as strings
prefixed with $. The CLI looks to the string following the dollar sign to see if it matches
any of the currently stored shell variable names in MicroMonitor’s environment. If the
string matches a shell variable name, then a substitution is made; if not, the string is left
untouched. A very similar capability is provided for symbols or strings prefixed with %.
 CLI Editing and History — As each line is typed, the CLI provides the ability to modify
the already-typed characters in a way that is much more efficient than simply
backspacing to the point of the error and retyping from that point. History allows the user
to retrieve a command string that was entered earlier and either execute it again or
modify it to form a new command.
 Command Output Redirection — When the CLI passes control to a command function,
that function can use printf() and putchar() to transfer command-specific information to
the user. Redirection at the CLI means that all data printed by the command can be
redirected to RAM and eventually transferred from RAM to a file in the flash file system.
 User Levels and Password Protection — The CLI accesses each command by first
determining the current user level of the system and the user level required for the
command to execute. If the user level of the system is higher than the required user level
for the command, then the command is allowed; otherwise, the command is rejected by
the CLI.
 Fall Through to FFS for Script Execution — If the command is not found in the
command table, then as a last resort, the CLI passes the string to TFS to process as an
executable script (if a script with the same name as the command exists).
 Leading Underscore Processing — MicroMonitor can have an application running on
top of it just as can DOS. The application is likely to have its own command set, but there
are times when a command in the monitor is useful to the application (the monitor’s API
allows the application’s CLI to access commands in the monitor’s CLI). To support the
situation where the application and MicroMonitor both recognize the same command
string (“help” is the most common example), the monitor’s CLI throws away a leading
underscore. Thus the the string _help can be passed to an application where it will fall
through to the monitor’s CLI and be processed as help.

In the preceding chapter, I built a clean system reset for MicroMonitor with warmstart, exception
handlers, and serial interface functions. In this chapter, I will implement a user interface through
the console port. Over the last few years, I’ve probably rewritten this command line interface
(CLI) half of a dozen times. I haven’t had any need to change it for quite some time now, so
maybe this version is a keeper.

The design goal of this CLI is to provide a good amount of flexibility without excess complexity.
This CLI provides shell variables and symbols, command line editing and history, command
output redirection, user levels, and password protection. If you don’t want all of these features,
most of this functionality can be optionally removed from the code at build time by setting a few
macros in the main MicroMonitor configuration file. To support this configurability without
being forced to scatter #ifdefs throughout the code, I have modularized the functionality and
accepted a few limitations. The end result is a fairly robust but not very complex CLI handler.

CLI Features
The CLI I develop in this chapter provides MicroMonitor with the following features:

 Functional Command Execution — All of the command line processing, except for
history and editing, is provided by a single function: docommand(). The docommand() is
passed a string from the command line and a verbosity level. Other modules in
MicroMonitor (not just the console connection) can also use docommand() to invoke
commands from within the code.
 Command Line Tokenization — Each command in the system has the standard
cmdfunc(int argc, char *argv[]) prototype. The CLI parses a string of characters into
individual white-space delimited tokens to form the argument count (argc) and argument
list (argv), which is then passed to a command-specific function.
 Shell Variables and Symbols — The command line processor makes substitutions for
shell variables and symbols. Shell variables are seen on the command line as strings
prefixed with $. The CLI looks to the string following the dollar sign to see if it matches
any of the currently stored shell variable names in MicroMonitor’s environment. If the
string matches a shell variable name, then a substitution is made; if not, the string is left
untouched. A very similar capability is provided for symbols or strings prefixed with %.
 CLI Editing and History — As each line is typed, the CLI provides the ability to modify
the already-typed characters in a way that is much more efficient than simply
backspacing to the point of the error and retyping from that point. History allows the user
to retrieve a command string that was entered earlier and either execute it again or
modify it to form a new command.
 Command Output Redirection — When the CLI passes control to a command function,
that function can use printf() and putchar() to transfer command-specific information to
the user. Redirection at the CLI means that all data printed by the command can be
redirected to RAM and eventually transferred from RAM to a file in the flash file system.
 User Levels and Password Protection — The CLI accesses each command by first
determining the current user level of the system and the user level required for the
command to execute. If the user level of the system is higher than the required user level
for the command, then the command is allowed; otherwise, the command is rejected by
the CLI.
 Fall Through to FFS for Script Execution — If the command is not found in the
command table, then as a last resort, the CLI passes the string to TFS to process as an
executable script (if a script with the same name as the command exists).
 Leading Underscore Processing — MicroMonitor can have an application running on
top of it just as can DOS. The application is likely to have its own command set, but there
are times when a command in the monitor is useful to the application (the monitor’s API
allows the application’s CLI to access commands in the monitor’s CLI). To support the
situation where the application and MicroMonitor both recognize the same command
string (“help” is the most common example), the monitor’s CLI throws away a leading
underscore. Thus the the string _help can be passed to an application where it will fall
through to the monitor’s CLI and be processed as help.

In the preceding chapter, I built a clean system reset for MicroMonitor with warmstart, exception
handlers, and serial interface functions. In this chapter, I will implement a user interface through
the console port. Over the last few years, I’ve probably rewritten this command line interface
(CLI) half of a dozen times. I haven’t had any need to change it for quite some time now, so
maybe this version is a keeper.

The design goal of this CLI is to provide a good amount of flexibility without excess complexity.
This CLI provides shell variables and symbols, command line editing and history, command
output redirection, user levels, and password protection. If you don’t want all of these features,
most of this functionality can be optionally removed from the code at build time by setting a few
macros in the main MicroMonitor configuration file. To support this configurability without
being forced to scatter #ifdefs throughout the code, I have modularized the functionality and
accepted a few limitations. The end result is a fairly robust but not very complex CLI handler.

CLI Features
The CLI I develop in this chapter provides MicroMonitor with the following features:

 Functional Command Execution — All of the command line processing, except for
history and editing, is provided by a single function: docommand(). The docommand() is
passed a string from the command line and a verbosity level. Other modules in
MicroMonitor (not just the console connection) can also use docommand() to invoke
commands from within the code.
 Command Line Tokenization — Each command in the system has the standard
cmdfunc(int argc, char *argv[]) prototype. The CLI parses a string of characters into
individual white-space delimited tokens to form the argument count (argc) and argument
list (argv), which is then passed to a command-specific function.
 Shell Variables and Symbols — The command line processor makes substitutions for
shell variables and symbols. Shell variables are seen on the command line as strings
prefixed with $. The CLI looks to the string following the dollar sign to see if it matches
any of the currently stored shell variable names in MicroMonitor’s environment. If the
string matches a shell variable name, then a substitution is made; if not, the string is left
untouched. A very similar capability is provided for symbols or strings prefixed with %.
 CLI Editing and History — As each line is typed, the CLI provides the ability to modify
the already-typed characters in a way that is much more efficient than simply
backspacing to the point of the error and retyping from that point. History allows the user
to retrieve a command string that was entered earlier and either execute it again or
modify it to form a new command.
 Command Output Redirection — When the CLI passes control to a command function,
that function can use printf() and putchar() to transfer command-specific information to
the user. Redirection at the CLI means that all data printed by the command can be
redirected to RAM and eventually transferred from RAM to a file in the flash file system.
 User Levels and Password Protection — The CLI accesses each command by first
determining the current user level of the system and the user level required for the
command to execute. If the user level of the system is higher than the required user level
for the command, then the command is allowed; otherwise, the command is rejected by
the CLI.
 Fall Through to FFS for Script Execution — If the command is not found in the
command table, then as a last resort, the CLI passes the string to TFS to process as an
executable script (if a script with the same name as the command exists).
 Leading Underscore Processing — MicroMonitor can have an application running on
top of it just as can DOS. The application is likely to have its own command set, but there
are times when a command in the monitor is useful to the application (the monitor’s API
allows the application’s CLI to access commands in the monitor’s CLI). To support the
situation where the application and MicroMonitor both recognize the same command
string (“help” is the most common example), the monitor’s CLI throws away a leading
underscore. Thus the the string _help can be passed to an application where it will fall
through to the monitor’s CLI and be processed as help.

You might also like