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.