This is strindent.c in view mode; [Download] [Up]
//-------------------------------------------------------------------------
// ^FILE: strindent.c - implement the strindent() function
//
// ^DESCRIPTION:
// This file implements the function strmatch() which matches a
// keyword (case insensitive) and the function strindent() which
// prints a hanging, indented paragraph.
//
// On VMS systems - we also implement a replacement for "getenv()"
// named "getsym()" to get the value of a VMS symbol.
//
// ^HISTORY:
// 12/05/91 Brad Appleton <brad@ssd.csd.harris.com> Created
//-^^-----------------------------------------------------------------------
#include <iostream.h>
#include <string.h>
#include <ctype.h>
#include "cmdline.h"
// Need a portable version of tolower
//
// NOTE:: I would make this inline except that cfront refuses
// to inline it because it is used twice in expressions
//
#define TO_LOWER(c) ((isupper(c)) ? tolower(c) : c)
//-------
// ^FUNCTION: strmatch - match a keyword
//
// ^SYNOPSIS:
// static CmdLine::strmatch_t CmdLine::strmatch(src, attempt, len);
//
// ^PARAMETERS:
// const char * src;
// -- the actual keyword to match against
//
// const char * attempt;
// -- the "candidate" that may or may not match the keyword
//
// unsigned len;
// -- the number of character of "attempt" to consider (==0 if all
// characters of "attempt" should be used).
//
// ^DESCRIPTION:
// See if "attempt" matches "src" (either partially or completely) and
// return the result.
//
// ^REQUIREMENTS:
// None that havent been discusses in the PARAMETERS section.
//
// ^SIDE-EFFECTS:
// None.
//
// ^RETURN-VALUE:
// str_EXACT if "attempt" completely matches "src"
// str_PARTIAL is "attempt" partially matches "src"
// str_NONE otherwise
//
// ^ALGORITHM:
// For each character (in order) of "attempt" to be considered
// if attempt[i] != src[i] (case insensitive) return str_NONE
// end-for
// if we have exhausted "src" return str_EXACT,
// else return str_PARTIAL
//-^^----
CmdLine::strmatch_t
CmdLine::strmatch(const char * src, const char * attempt, unsigned len)
{
unsigned i;
if (src == attempt) return str_EXACT ;
if ((src == NULL) || (attempt == NULL)) return str_NONE ;
if ((! *src) && (! *attempt)) return str_EXACT ;
if ((! *src) || (! *attempt)) return str_NONE ;
for (i = 0 ; ((i < len) || (! len)) && (attempt[i] != '\0') ; i++) {
if (TO_LOWER(src[i]) != TO_LOWER(attempt[i])) return str_NONE ;
}
return (src[i] == '\0') ? str_EXACT : str_PARTIAL ;
}
//--------------------------------------------------------------------------
// ^FUNCTION: strindent - print a hanging indented paragraph
//
// ^SYNOPSIS:
// void CmdLine::strindent(os, maxcols, margin, title, indent, text)
//
// ^PARAMETERS:
// ostream & os;
// -- the stream to which output is sent
//
// unsigned maxcols;
// -- the maximum width (in characters) of the output
//
// unsigned margin;
// -- the number of spaces to use as the left margin
//
// char * title;
// -- the paragraph title
//
// unsigned indent;
// -- the distance between the title and the paragraph body
//
// char * text;
// -- the body of the paragraph
//
// ^DESCRIPTION:
// Strindent will print on os, a titled, indented paragraph as follows:
//
// <----------------------- maxcols --------------------------->
// <--- margin --><----- indent ---->
// title This is the first sentence
// of the paragraph. Etc ...
//
// ^REQUIREMENTS:
// - maxcols and indent must be positive numbers with maxcols > indent.
// - title should NOT contain any tabs or newlines.
//
// ^SIDE-EFFECTS:
// Output is printed to os.
//
// ^RETURN-VALUE:
// None.
//
// ^ALGORITHM:
// Print the paragraph title and then print the text.
// Lines are automatically adjusted so that each one starts in the
// appropriate column.
//-^^-----------------------------------------------------------------------
void
CmdLine::strindent(ostream & os,
unsigned maxcols,
unsigned margin,
const char * title,
unsigned indent,
const char * text)
{
// If we were given non-sensical parameters then dont use them
if (margin > maxcols) margin = 0;
if ((indent + margin) >= maxcols) indent = 1;
// print the title (left-justified)
os.width(margin);
os << "" ;
long save_flags = os.flags();
os.setf(ios::left, ios::adjustfield);
os.width(indent);
os << ((title) ? title : "");
os.flags(save_flags);
if (text == NULL) {
os << endl ;
return;
}
// If the title is too big, start the paragraph on a new line
if (title && (::strlen(title) > indent)) {
os << endl ;
os.width(margin + indent);
os << "";
}
// Loop through the paragraph text witing to print until we absolutely
// have to.
//
unsigned col = margin + indent + 1;
unsigned index = 0 ;
unsigned last_white = 0 ;
const char * p = text ;
while (p[index]) {
switch (p[index]) {
// If we have a space - just remember where it is
case ' ' :
last_white = index;
++col;
++index;
break;
// If we have a tab - remember where it is and assume it
// will take up 8 spaces in the output.
//
case '\t' :
last_white = index;
col += 8;
++index;
break;
// If we have a form-feed, carriage-return, or newline, then
// print what we have so far (including this character) and
// start a new line.
//
case '\n' :
case '\r' :
case '\f' :
os.write(p, index + 1);
p += index + 1;
col = margin + indent + 1;
index = last_white = 0;
if (*p) {
os.width(margin + indent);
os << "";
}
break;
default:
++col;
++index;
break;
} //switch
// Are we forced to start a new line?
if (col > maxcols) {
// Yes - if possible, print upto the last whitespace character
// and start the next line on a word-boundary
if (last_white) {
os.write(p, last_white);
p += last_white;
while (*p == ' ') ++p;
} else {
// No word boundary in sight - just split the line here!
os.write(p, index);
p += index;
}
os << endl ;
// We just printed a newline - dont print another one right now
while ((*p == '\n') || (*p == '\r') || (*p == '\f')) ++p;
col = margin + indent + 1;
index = last_white = 0;
if (*p) {
os.width(margin + indent);
os << "";
}
} else if (index && (! p[index])) {
os << p << endl ;
}
} //while
}
#ifdef vms
# include <descrip.h>
# include <libdef.h>
extern "C" {
long lib$get_symbol(...);
void exit(int);
}
//----------------------
// ^FUNCTION: getsym - retrieve the value of a VMS symbol
//
// ^SYNOPSIS:
// const char * getsym(sym_name)
//
// ^PARAMETERS:
// char * sym_name;
// -- name of the symbol to retrieve
//
// ^DESCRIPTION:
// Get_symbol will lookup the named symbol and return its value
// as a string.
//
// ^REQUIREMENTS:
// sym_name should correspond to the name of a pre-defined symbol.
//
// ^SIDE-EFFECTS:
// None. NO storage is allocated for the symbol-value and it will
// be overwritten by the next call to this function.
//
// ^RETURN-VALUE:
// NULL if the symbol is not found, otherwise it returns a pointer
// to a static buffer containing the contents of the symbol value.
// You MUST be finished using this buffer before another call to
// get_symbol is made.
//
// ^ACKNOWLEDGEMENTS:
// Thanx to Jim Barbour for writing most of this code. --BDA
//
// ^ALGORITHM:
// Trivial - just use the LIB$GET_SYMBOL system service.
//-^^-------------------
const char *
getsym(const char * sym_name)
{
static char sym_value[256];
unsigned long stat;
unsigned short buflen;
$DESCRIPTOR(sym_name_d, sym_name);
$DESCRIPTOR(sym_value_d, sym_value);
sym_value_d.dsc$w_length = sizeof(sym_value);
sym_name_d.dsc$w_length = ::strlen(sym_name);
stat = lib$get_symbol(&sym_name_d, &sym_value_d, &buflen, (void *)0);
if (stat == LIB$_NOSUCHSYM) {
return NULL;
} else if (! (stat & 1)) {
::exit(stat);
}
sym_value[buflen] = '\0';
return sym_value;
}
#endif /* vms */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.