This is usage.c in view mode; [Download] [Up]
//------------------------------------------------------------------------
// ^FILE: usage.c - functions to print the usage of a CmdLine
//
// ^DESCRIPTION:
// This file contains the functions that are used to print the
// command-line usage of a command that is represented by a CmdLine
// object.
//
// ^HISTORY:
// 01/09/92 Brad Appleton <brad@ssd.csd.harris.com> Created
//
// 03/01/93 Brad Appleton <brad@ssd.csd.harris.com>
// - Added cmd_description field to CmdLine
//-^^---------------------------------------------------------------------
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include "cmdline.h"
#include "states.h"
#include "arglist.h"
#ifdef vms
# define getenv getsym
extern const char * getsym(const char *);
#endif
//-------
// ^FUNCTION: CmdLine::get_usage_level
//
// ^SYNOPSIS:
// CmdLine::CmdUsageLevel CmdLine::get_usage_level(void)
//
// ^PARAMETERS:
// NONE.
//
// ^DESCRIPTION:
// Gets the usage_level that tells us how "verbose" we should be
// when printing usage-messages. This usage_level is recorded in
// the environment variable $USAGE_LEVEL. This variable may have the
// following values:
//
// 0 : Dont print usage at all.
// 1 : Print a terse usage message (command-line syntax only).
// 2 : Print a verbose usage message (include argument descriptions).
//
// If $USAGE_LEVEL is not defined or is empty, then the default
// usage_level is 2.
//
// ^REQUIREMENTS:
//
// ^SIDE-EFFECTS:
// None.
//
// ^RETURN-VALUE:
// The usage level to use.
//
// ^ALGORITHM:
// Read the usage_level from the environment and return it.
//-^^----
CmdLine::CmdUsageLevel
CmdLine::get_usage_level(void)
{
long level;
char * end_scan, * level_str = ::getenv("USAGE_LEVEL");
if (level_str == NULL) return VERBOSE_USAGE ;
if (*level_str == '\0') return NO_USAGE ;
level = ::strtol(level_str, &end_scan, 0);
if (end_scan == level_str) return VERBOSE_USAGE ;
switch(level) {
case 0 : return NO_USAGE ;
case 1 : return TERSE_USAGE ;
default: return VERBOSE_USAGE ;
}
}
//-------
// ^FUNCTION: CmdLine::print_synopsis
//
// ^SYNOPSIS:
// unsigned CmdLine::print_synopsis(syntax, os, cols)
//
// ^PARAMETERS:
// CmdLine::CmdLineSyntax syntax;
// -- the syntax to use (long-option, short-option, or both)
// when printing the synopsis.
//
// ostream & os;
// -- where to print.
//
// int cols;
// -- the maximum width of a line.
//
// ^DESCRIPTION:
// Print a command-line synopsis (the command-line syntax).
// The synopsis should be printed to "os" using the desired syntax,
// in lines that are no more than "cols" characters wide.
//
// ^REQUIREMENTS:
//
// ^SIDE-EFFECTS:
// Prints on "os".
//
// ^RETURN-VALUE:
// The length of the longest argument-buf that was printed.
//
// ^ALGORITHM:
// It's kind of complicated so follow along!
//-^^----
unsigned
CmdLine::print_synopsis(CmdLine::CmdLineSyntax syntax,
ostream & os,
int cols) const
{
#ifdef vms_style
static char usg_prefix[] = "Format: ";
#else
static char usg_prefix[] = "Usage: ";
#endif
unsigned ll, positionals, longest = 0;
// first print the command name
os << usg_prefix << cmd_name ;
ll = (cmd_name ? ::strlen(cmd_name) : 0) + (sizeof(usg_prefix) - 1);
// set margin so that we always start printing arguments in a column
// that is *past* the command name.
//
unsigned margin = ll + 1;
// print option-syntax followed by positional parameters
int first;
char buf[256] ;
for (positionals = 0 ; positionals < 2 ; positionals++) {
first = 1;
CmdArgListListIter list_iter(cmd_args);
for (CmdArgList * alist = list_iter() ; alist ; alist = list_iter()) {
CmdArgListIter iter(alist);
for (CmdArg * cmdarg = iter() ; cmdarg ; cmdarg = iter()) {
unsigned len, pl;
// don't display hidden arguments
if (cmdarg->syntax() & CmdArg::isHIDDEN) continue;
if (!positionals && (cmdarg->syntax() & CmdArg::isPOS)) continue;
if (positionals && !(cmdarg->syntax() & CmdArg::isPOS)) continue;
// figure out how wide this parameter is (for printing)
pl = len = fmt_arg(cmdarg, buf, sizeof(buf), syntax, VERBOSE_USAGE);
if (! len) continue;
if (cmdarg->syntax() & CmdArg::isLIST) pl -= 4 ; // " ..."
if (! (cmdarg->syntax() & CmdArg::isREQ)) pl -= 2 ; // "[]"
if (pl > longest) longest = pl;
// Will this fit?
if ((ll + len + 1) > (cols - first)) {
os << char('\n') ;
os.width(margin);
os << "" ; // No - start a new line;
ll = margin;
} else {
os << char(' ') ; // Yes - just throw in a space
++ll;
}
ll += len;
os << buf;
first = 0;
} //for each cmdarg
} //for each arg-list
} //for each parm-type
os << endl ;
return longest ;
}
//-------
// ^FUNCTION: CmdLine::print_descriptions
//
// ^SYNOPSIS:
// unsigned CmdLine::print_descriptions(syntax, os, cols, longest)
//
// ^PARAMETERS:
// CmdLine::CmdLineSyntax syntax;
// -- the syntax to use (long-option, short-option, or both)
// when printing the synopsis.
//
// ostream & os;
// -- where to print.
//
// int cols;
// -- the maximum width of a line.
//
// unsigned longest;
// -- value returned by print_synopsis.
//
// ^DESCRIPTION:
// Print a command argument descriptions (using the command-line syntax).
// The descriptions should be printed to "os" using the desired syntax,
// in lines that are no more than "cols" characters wide.
//
// ^REQUIREMENTS:
// "longest" should correspond to a value returned by print_synopsis
// that used the same "cmd" and syntax.
//
// ^SIDE-EFFECTS:
// Prints on "os".
//
// ^RETURN-VALUE:
// None.
//
// ^ALGORITHM:
// Print the description for each argument.
//-^^----
void
CmdLine::print_descriptions(CmdLine::CmdLineSyntax syntax,
ostream & os,
int cols,
unsigned longest) const
{
int positionals, options = 0;
char buf[256];
for (positionals = 0 ; positionals < 2 ; positionals++) {
CmdArgListListIter list_iter(cmd_args);
for (CmdArgList * alist = list_iter() ; alist ; alist = list_iter()) {
CmdArgListIter iter(alist);
for (CmdArg * cmdarg = iter() ; cmdarg ; cmdarg = iter()) {
// don't display hidden arguments
if (cmdarg->syntax() & CmdArg::isHIDDEN) continue;
if (!positionals && (cmdarg->syntax() & CmdArg::isPOS)) continue;
if (positionals && !(cmdarg->syntax() & CmdArg::isPOS)) continue;
#ifdef vms_style
if ( !options++ ) os << "Qualifiers/Parameters:\n" ;
#else
if ( !options++ ) os << "Options/Arguments:\n" ;
#endif
if (! fmt_arg(cmdarg, buf, sizeof(buf), syntax, TERSE_USAGE)) {
continue;
}
const char * description = cmdarg->description();
if ((description == NULL) || (! *description)) continue;
strindent(os, cols, 8, buf, (longest + 2), description);
} //for each cmdarg
} //for each arg-list
} //for each parm-type
}
//-------
// ^FUNCTION: CmdLine::usage - print command-usage
//
// ^SYNOPSIS:
// void CmdLine::usage(os, usage_level);
//
// ^PARAMETERS:
// ostream & os;
// -- where to print.
//
// CmdLine::CmdUsageLevel usage_level;
// -- verboseness to use.
//
// ^DESCRIPTION:
// Print the usage for the given CmdLine object on "os".
//
// ^REQUIREMENTS:
//
// ^SIDE-EFFECTS:
// Prints on "os".
//
// ^RETURN-VALUE:
// None.
//
// ^ALGORITHM:
// - get the usage level.
// - determine which syntax to use
// - get the max-columns for "os".
// - print synopsis if required.
// - print descriptions if required.
//-^^----
ostream &
CmdLine::usage(ostream & os, CmdLine::CmdUsageLevel usage_level) const
{
// get user-specified usage-level
// (if status is zero this must be an explicit request so force verbose)
//
if (usage_level == DEFAULT_USAGE) usage_level = get_usage_level();
if (usage_level == NO_USAGE) return os;
// determine syntax to use
CmdLineSyntax cmd_syntax = syntax() ;
// get screen size (dont know how to do this yet)
int max_cols = 79;
// print command-line synopsis
unsigned longest = print_synopsis(cmd_syntax, os, max_cols) ;
if (usage_level == TERSE_USAGE) return os;
// now print argument descriptions
os << "\n" ;
print_descriptions(cmd_syntax, os, max_cols, longest) ;
// now print the command-description if there is one
if (cmd_description && *cmd_description) {
os << "\nDescription:" << endl;
strindent(os, max_cols, 8, "", 0, cmd_description);
}
return os;
}
ostream &
CmdLine::usage(CmdLine::CmdUsageLevel usage_level) const {
return usage(*cmd_err, usage_level);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.