ECGSYN - A realistic ECG waveform generator 1.0.0
(56,582 bytes)
/*
opt.c version 3.17 ... modified for Cygwin windows compatibility
(varargs.h replaced by stdarg.h)
OPT is a subroutine library which facilitates the convenient
input of parameters to a C or C++ program. Parameters are parsed
from a command line, with further facilities for reading options
from files, from environment strings, or from an interactive
environment. The aim of the opt package is to permit programs to
be both user- and programmer- friendly. The package attempts to
on the one hand provide a direct and relatively full-featured
input interface to the ultimate user of the program, and at the
same time impose a minimal amount of work on the programmer to
"attach" the package to his or her software. A texinfo file is
part of the distribution; or you can view the html documentation at:
http://nis-www.lanl.gov/~jt/Software/opt/opt_toc.html
Download the lastest version of the source code from:
http://nis-www.lanl.gov/~jt/Software/
opt is available to the public under the GNU General Public License:
http://www.gnu.org/copyleft/gpl.html
This SOFTWARE has been authored by an employee of the University of
California, operator of the Los Alamos National Laboratory under
Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
U.S. Government has rights to use, reproduce, and distribute this
SOFTWARE. The public may copy, distribute, prepare derivative works
and publicly display this SOFTWARE without charge, provided that this
Notice and any statement of authorship are reproduced on all
copies. Neither the Government nor the University makes any warranty,
express or implied, or assumes any liability or responsibility for the
use of this SOFTWARE. If SOFTWARE is modified to produce derivative
works, such modified SOFTWARE should be clearly marked, so as not to
confuse it with the version available from LANL.
*/
#define SINGLEFILE 1
#ifndef DISABLE_VARARGS
#define DISABLE_VARARGS 0
#endif
#ifndef DISABLE_LONGJUMP
#define DISABLE_LONGJUMP 0
#endif
#ifndef DISABLE_SIGNAL
#define DISABLE_SIGNAL 0
#endif
#include <stdio.h>
#ifdef convex
#include <strings.h>
#else
#include <string.h>
#endif
#ifdef __TURBOC__
#include <stdlib.h>
#include <alloc.h>
#endif
#include <ctype.h>
#if !DISABLE_LONGJUMP
#include <setjmp.h>
#endif
#if !DISABLE_SIGNAL
#include <signal.h>
#endif
#if !DISABLE_VARARG
#ifdef __TURBOC__
#include <stdarg.h>
#else
#include <stdarg.h>
#endif
#endif
static char gstr[160]; /* generally useful global string */
/* opt.h */
/*
User Include File for options package
*/
#ifndef _OPT_H
#define _OPT_H /* Signal that this header file has been included */
/*
* These are delimiter characters
*/
#define DELIM '-' /* option delimiter character */
#define ALTDELIM '/' /* alternate delimiter character */
#define OPTFROMFILE '@' /* denotes options are in a file */
#define OPTTOFILE '%' /* says to put options in a file */
#define DOCUMENT '-' /* write document to file */
#define INTERACT '$' /* Flags interactive menu */
#define HELPCH '?' /* Help character */
/*
* These are not available on command line
* But may be invoked from a file
*/
#define IGNOREEOL ';' /* Ignore until the end of line */
#define RUN '=' /* Says to just run to completion */
#define QUITCH '.' /* Quit character */
/*
* These are not available on command line or from a file
* But may be invoked from the menu
*/
#define BANG '!' /* Shell escape character */
#define ADDITIONAL_OPTS '+' /* Additional options */
typedef enum {
INT, UNSINT, LONG, CHAR,
INTLEVEL,
FLOAT, DOUBLE,
FLAG, NEGFLAG, ABSFLAG, ABSNEGFLAG,
VSTRING, CSTRING, UNDELIMV, UNDELIMC
}
opt_TYPE;
typedef int (*PFI)();
#define OPT_EXT ".opt" /* standard options file extension */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef ARGCHECK
#ifdef __TURBOC__
#define ARGCHECK
#endif /* __TURBOC__ */
#ifdef __cplusplus
#define ARGCHECK
#endif /* __cplusplus */
#endif /* ARGCHECK */
#ifdef ARGCHECK
extern int opt_register(char *,opt_TYPE,char,char *);
extern void opt_usage_set(char *);
extern void opt_title_set(char *);
extern void opt_verify_set(PFI);
extern void opt_doc_set(PFI);
extern void opt_quit_set(PFI);
extern void opt_run_set(PFI);
extern void opt_help_setf(PFI);
extern void opt_help_set(char,char *);
extern void opt_ufilter_set(PFI);
extern void opt_dfilter_set(PFI);
extern void opt_env_set(char *);
extern void opt_default_set(char *);
#if DISABLE_VARARGS
extern void opt_errmess(char *);
extern void opt_message(char *);
extern void opt_warning(char *);
extern void opt_fatal(char *);
#else
extern void opt_errmess();
extern void opt_message();
extern void opt_warning();
extern void opt_fatal();
#endif /* DISABLE_VARARGS */
extern void opt_abort_run(void);
extern int opt_begin_run(PFI);
extern int getopts(int,char **);
#else
extern int opt_register();
extern void opt_usage_set();
extern void opt_title_set();
extern void opt_verify_set();
extern void opt_doc_set();
extern void opt_quit_set();
extern void opt_run_set();
extern void opt_help_setf();
extern void opt_help_set();
extern void opt_help_set();
extern void opt_ufilter_set();
extern void opt_dfilter_set();
extern void opt_env_set();
extern void opt_default_set();
extern void opt_errmess();
extern void opt_message();
extern void opt_warning();
extern void opt_fatal();
extern void opt_abort_run();
extern int opt_begin_run();
extern int getopts();
#endif /* ARGCHECK */
/*********************************
* Macro's for registering options
*/
#define optregister(val,typ,c,str) opt_register((char *)&val,typ,c,str)
#define optrunset(r) {int r(); opt_run_set( r );}
#endif /* _OPT_H */
/* ag.h */
#ifndef _AG_H
#define _AG_H
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/*************************************
* ARGVECTOR structure
* Basically, an (argc,argv) construct
* with indices to which character of
* which word is the current position
*/
typedef struct
{
char **v; /* argument vector */
int c; /* argument count */
int iw; /* current word */
int ic; /* current character */
}
ARGVECTOR;
/*
* Function prototypes
*/
#ifdef ARGCHECK
extern ARGVECTOR *ag_new(int,char **,ARGVECTOR *);
extern int ag_enstring(char *,ARGVECTOR *,int);
extern void ag_reset(ARGVECTOR *);
extern int ag_w_number(ARGVECTOR *);
extern void ag_w_advance(ARGVECTOR *);
extern int ag_eow(ARGVECTOR *);
extern int ag_end(ARGVECTOR *);
extern char ag_c(ARGVECTOR *);
extern char ag_c_next(ARGVECTOR *);
extern char ag_cnn_next(ARGVECTOR *);
extern char ag_c_advance(ARGVECTOR *);
extern char ag_backspace(ARGVECTOR *);
extern char *ag_s(ARGVECTOR *);
extern char *ag_s_next(ARGVECTOR *);
extern char *ag_s_advance(ARGVECTOR *);
extern char *argnext(ARGVECTOR *);
extern double argnextnum(ARGVECTOR *);
#else
extern ARGVECTOR *ag_new();
extern int ag_enstring();
extern void ag_reset();
extern int ag_w_number();
extern void ag_w_advance();
extern int ag_eow();
extern int ag_end();
extern char ag_c();
extern char ag_c_next();
extern char ag_cnn_next();
extern char ag_c_advance();
extern char ag_backspace();
extern char *ag_s();
extern char *ag_s_next();
extern char *ag_s_advance();
extern char *argnext();
extern double argnextnum();
#endif /* ARGCHECK */
#endif /* _AG_H */
/* opt_p.h */
/*
* Private header file for OPT package.
*/
#ifndef _OPT_P_H
#define _OPT_P_H
#define OPT_MAXSTRLEN 80
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef OKAY
#define OKAY 0
#define NOT_OKAY (-1)
#endif
#ifndef DEBUG
#define DEBUG 0
#endif
typedef enum { False=FALSE, True=TRUE } flag;
/******************
* Global variables
*/
extern int nregopts; /* Number of registered options */
extern flag menuflag; /* Is menu ON? */
extern flag fileflag; /* Are options being read from a file? */
/*********************
* Function Prototypes
*/
#ifndef ARGCHECK
#ifdef __TURBOC__
#define ARGCHECK
#endif /* __TURBOC__ */
#endif /* ARGCHECK */
#ifdef ARGCHECK
extern int opt_register(char *,opt_TYPE,char,char *);
extern int opt_number(char);
extern int opt_fprint(FILE *,int);
extern int opt_tofile(FILE *);
extern char *optstrval(int);
extern char *optstrtyp(int);
extern int opt_undelim(ARGVECTOR *);
extern int opt_delim(ARGVECTOR *);
extern void opt_get_help(char);
#else
extern int opt_register();
extern int opt_number();
extern int opt_fprint();
extern int opt_tofile();
extern char *optstrval();
extern char *optstrtyp();
extern int opt_undelim();
extern int opt_delim();
extern void opt_get_help();
#endif
/* --------------- */
/* Process Options */
/* --------------- */
extern char *opt_program_name;
extern PFI dfilter_fcn,
ufilter_fcn,
verify_fcn,
doc_fcn,
quit_fcn,
help_fcn,
run_fcn;
#ifdef ARGCHECK
extern void opt_wr_title(void);
extern void opt_process(int,char **);
extern int opt_fromfname(char *);
extern int opt_tofname(char *);
extern int opt_getline(char *,FILE *);
extern char *opt_mstring(int);
extern int opt_number(char);
extern char *short_progname(char *);
extern int opt_undelim(ARGVECTOR *);
extern int opt_delim(ARGVECTOR *);
extern void opt_menu(void);
extern void usage(char *);
extern void opt_help();
extern void opt_quit();
extern void opt_doc();
extern void opt_usage(FILE *);
#else
extern void opt_wr_title();
extern void opt_process();
extern int opt_fromfname();
extern int opt_getline();
extern int opt_tofname();
extern int opt_delim();
extern int opt_number();
extern int opt_undelim();
extern void opt_menu();
extern char *opt_mstring();
extern void opt_doc();
extern void opt_help();
extern void opt_quit();
extern void usage();
extern void opt_usage();
extern char *short_progname();
extern int ignore_after_char();
#endif /* ARGCHECK */
#endif /* _OPT_P_H */
/* ag.c */
#ifndef SINGLEFILE
#include <stdio.h>
#ifdef convex
#include <strings.h>
#else
#include <string.h>
#endif
#include "ag.h"
#endif
/* primitive routines for manipulation argument vectors */
/*
make-new-argvector ag_new()
reset-argvector ag_reset()
flag-end-of-word ag_eow()
what-is-character ag_c()
what-is-string ag_s()
read-character ag_c()
read-next-character ag_c_next()
read-next-non-null-character ag_cnn_next()
read-character-advance ag_c_advance()
read-string ag_s()
read-next-string ag_s_next()
read-string-advance ag_s_advance()
word-number ag_w_number()
word-advance ag_w_advance()
backspace ag_backspace()
clear ag_clear()
get-next-argument argnext()
get-next-argument-value argnextnum()
*/
ARGVECTOR *
ag_new(argc,argv,ag)
int argc;
char **argv;
ARGVECTOR *ag;
{
ag->v = argv;
ag->c = argc;
ag->iw = 0;
ag->ic = 0;
return(ag);
}
ag_fprint(fp,ag)
FILE *fp;
ARGVECTOR *ag;
{
int i;
for(i=0; i<ag->c; ++i)
fprintf(fp,"[%s]",ag->v[i]);
fprintf(fp,"\n");
}
void
ag_reset(ag)
ARGVECTOR *ag;
{
ag->iw = 0;
ag->ic = 0;
}
int
ag_w_number(ag)
ARGVECTOR *ag;
{
return( ag->iw );
}
void
ag_w_advance(ag)
ARGVECTOR *ag;
{
++(ag->iw); /* advance to next word */
ag->ic=0; /* beginning of next word */
}
/* ag_eow: end of word
flag whether current position is at end of word
*/
int
ag_eow(ag)
ARGVECTOR *ag;
{
if( ag->iw >= ag->c )
return(TRUE);
if( ag->ic >= strlen(ag->v[ag->iw]) )
return(TRUE);
return(FALSE);
}
/* ag_end: end of command line
flag whether current position is at end of command line
*/
int
ag_end(ag)
ARGVECTOR *ag;
{
if( ag->iw >= ag->c )
return(TRUE);
if( ag_eow(ag) && ag->iw == (ag->c)-1 )
return(TRUE);
return(FALSE);
}
/* ag_c: return current character
do not advance
*/
char
ag_c(ag)
ARGVECTOR *ag;
{
return(ag->v[ag->iw][ag->ic]);
}
char
ag_c_next(ag)
ARGVECTOR *ag;
{
return(ag->v[ag->iw][ag->ic+1]);
}
char
ag_cnn_next(ag)
ARGVECTOR *ag;
{
if( ag_c_next(ag) == '\0' )
{
if(ag->iw+1 >= ag->c)
return('\0');
else return(ag->v[ag->iw+1][0]);
}
else return( ag_c_next(ag) );
}
/* ag_c_advance: read current character, and advance to next
return '\0' if end of word
do not advance to next word
*/
char
ag_c_advance(ag)
ARGVECTOR *ag;
{
char c; /* current character */
if( ag_eow(ag) )
return(c='\0'); /* return NULL to signal that current*/
/* character is past end of word */
c = ag->v[ag->iw][ag->ic];
++(ag->ic); /* advance to next character */
return(c);
}
char
ag_backspace(ag)
ARGVECTOR *ag;
{
if( --(ag->ic) < 0 ) /* if back past beginning of word */
{ ag->ic=0;
if(--(ag->iw) < 0) /* goto beginning of previous word */
ag_reset(ag); /* if no previous, reset */
else
{ while( !ag_eow(ag) ) /* goto end of prevous word */
ag_c_advance(ag);
ag_backspace(ag); /* back to just before end */
}
}
return(ag->v[ag->iw][ag->ic]);
}
/* ag_s: returns current string
returns "" if current position is at end of word
returns NULL if past end of argument vector
*/
char *
ag_s(ag)
ARGVECTOR *ag;
{
if( ag->iw < ag->c )
return( ag->v[ag->iw]+ag->ic );
else return( NULL );
}
char *
ag_s_next(ag)
ARGVECTOR *ag;
{
if( ag->v[ag->iw][ag->ic+1] == '\0' )
{
if(ag->iw+1 >= ag->c)
return(NULL);
else return(ag->v[ag->iw+1]);
}
else return( ag->v[ag->iw]+ag->ic+1 );
}
/* ag_s_advance: read current string and advance to next
returns NULL if current string is at end
does not check advanced string
*/
char *
ag_s_advance(ag)
ARGVECTOR *ag;
{
char *s; /* current string */
if( ag_eow(ag) ) /* if end of word, go to next word */
ag_w_advance(ag);
if( ag_eow(ag) ) /* if still at end of word, */
s = NULL; /* signify by returning NULL */
else s = ag->v[ag->iw] + ag->ic;
ag_w_advance(ag); /* advance to next word */
return(s);
}
int
ag_clear(ag)
ARGVECTOR *ag;
{
while( !ag_end(ag) )
argnext(ag);
return 1;
}
/* ------------------------ */
/* return the next argument */
/* ------------------------ */
char *
argnext(ag)
ARGVECTOR *ag;
{
static char nullchar='\0';
char *s;
s = ag_s_advance(ag);
if( s==NULL )
s = &nullchar;
return(s);
}
/* ------------------------------------------- */
/* return the numerical value of next argument */
/* ------------------------------------------- */
double
argnextnum(ag)
ARGVECTOR *ag;
{
extern double atof();
return( atof(argnext(ag)) );
}
/* opt_reg.c */
/************************ register options ********************************
*
* options are stored in an array,
* each element of which is a structure
*
* The members of the structure contain information about
* 1) the variable which is altered
* 2) the type of variable
* 3) a character by which the variable is invoked
* 4) a brief description of the variable's role in the program
* 5) a longer help message
*
* The structure elements are not assigned directly, but are
* "registered" with a call to the function opt_register().
*
* In this file are the routines which access the structure of
* registered options.
*
* I) Register options and help strings
* II) Get number corresponding to name of option
* III) Print options out
* a) to a file which can be used as an input command line
* b) to the screen as part of a usage message
* c) to the screen as part of an interactive menu
* IV) Process single delimited and undelimited options
*/
#ifndef SINGLEFILE
#include <stdio.h>
#ifdef convex
#include <strings.h>
#else
#include <string.h>
#endif
#ifdef __TURBOC__
#include <alloc.h>
#endif
#include "ag.h"
#include "opt_p.h"
static char gstr[160]; /* global string for general use */
#endif
/* -------------------------- */
/* List of Registered Options */
/* -------------------------- */
#define MAXOPTS 62 /* one for each upper and lower case letter */
typedef struct
{
char *value; /* pointer to value of option */
opt_TYPE type; /* will be cast according to type */
char name; /* name by which option is invoked */
char *brief; /* a brief description */
char *help; /* longer help message */
}
EACH_OPT;
static EACH_OPT optlist[MAXOPTS]; /* array of options */
int nregopts=0; /* number of registered opts */
/* ---------- */
/* OPT macros */
/* ---------- */
#define OPT_isflagtype(o) \
((o)==FLAG || (o)==NEGFLAG || (o)==ABSFLAG || (o)==ABSNEGFLAG)
#define OPT_isundelimtype(o) ((o)==UNDELIMV || (o)==UNDELIMC)
/* ----------------------------------------------- */
/* OPTVALUE: a macro to get the value of an option */
/* ----------------------------------------------- */
#define OPTVALUE(typ,i) ((typ)(*((typ *)(optlist[i].value))))
#define SETOPTVALUE(typ,i,val) { typ *xptr; \
xptr = (typ *)(optlist[i].value); \
*xptr = val; \
}
/* ------------------------------- */
/* Routine to register each option */
/* ------------------------------- */
int
opt_register(val,otype,name,brief)
char *val;
opt_TYPE otype;
char name;
char *brief;
{
if( nregopts >= MAXOPTS )
opt_fatal("opt_register: too many options");
if( name != '\0' && opt_number(name) != -1 )
{
char gstr[80];
sprintf(gstr,"opt_register: Duplicate option name \'%c\'",name),
opt_warning(gstr);
}
/* Programmer may specify that an option is to be an
* undelimted option by setting the name to '\0'
*/
if(name=='\0')
{
if(otype==VSTRING)
otype=UNDELIMV;
if(otype==CSTRING)
otype=UNDELIMC;
}
/* Having checked for various warnings, now register the options */
optlist[nregopts].value = val;
optlist[nregopts].type = otype;
optlist[nregopts].name = name;
optlist[nregopts].brief = brief;
optlist[nregopts].help = NULL;
/* UN-delimited strings are set to NULL when registered */
/* This enables them to be invoked on the command line */
if(otype==UNDELIMC)
*(optlist[nregopts].value)='\0';
if(otype==UNDELIMV)
SETOPTVALUE(char *,nregopts,NULL)
++nregopts;
return(nregopts);
}
void
opt_help_set(c,help)
char c, *help;
{
int n;
n = opt_number(c);
if (n>=0 && n<nregopts)
optlist[n].help = help;
else
sprintf(gstr,"opt_help_set: Unregistered option name \'%c\'",c),
opt_warning(gstr);
}
void
opt_get_help(c)
char c;
{
int n;
n = opt_number(c);
if (n>=0 && n<nregopts && optlist[n].help != NULL)
sprintf(gstr,"%c: %s\n",c,optlist[n].help),
opt_message(gstr);
else
sprintf(gstr,"Help unavailable for \'%c\'\n",c),
opt_message(gstr);
}
/* --------------------------------------- */
/* Get number corresponding to option name */
/* --------------------------------------- */
/* opt_number returns the number of a named option.
* if c=='\0', signifying an undelimited option,
* then the number of the FIRST undelimited option is returned
*/
int
opt_number(c)
char c;
{
int i=0; /* see which registered option */
for(i=0; i<nregopts; ++i)
{
if( c == optlist[i].name )
return(i);
}
return(-1); /* to signify not an option */
}
/* -------------------------------------------- */
/* Print value of registered option to a string */
/* -------------------------------------------- */
/* optstrval:
* returns the value of the ith registered option as a string
* Thus if x = 12.6, this returns the string "12.6"
* The return value is a pointer to a static string which is
* overwritten with each call
* FLAG values are returned as "+" or "-"
* INTLEVEL values are returned as "- -xxxx..." depending on value
*/
char *
optstrval(i)
int i;
{
int maybe;
static char stval_buf[80];
switch( optlist[i].type )
{
case INT:
sprintf(stval_buf,"%d", OPTVALUE(int,i) );
break;
case UNSINT:
sprintf(stval_buf,"%u", OPTVALUE(unsigned int,i) );
break;
case LONG:
sprintf(stval_buf,"%ld", OPTVALUE(long,i) );
break;
case FLOAT:
sprintf(stval_buf,"%g", OPTVALUE(float,i) );
break;
case DOUBLE:
sprintf(stval_buf,"%lg", OPTVALUE(double,i) );
break;
case CHAR:
sprintf(stval_buf,"%c", OPTVALUE(char,i));
break;
case INTLEVEL:
{
int j;
char buff[80];
strcpy(stval_buf,"-"); /* Begin with level==OFF */
for(j=0; j< OPTVALUE(int,i); ++j)
{
sprintf(buff,(j==0?" -%c":"%c"),optlist[i].name);
strcat(stval_buf,buff);
}
}
break;
case FLAG:
case ABSFLAG:
maybe = OPTVALUE(int,i);
sprintf(stval_buf,"%c", (maybe==TRUE ? '+' : '-') );
break;
case NEGFLAG:
case ABSNEGFLAG:
maybe = OPTVALUE(int,i);
sprintf(stval_buf,"%c", (maybe==TRUE ? '-' : '+') );
break;
case CSTRING:
case UNDELIMC:
sprintf(stval_buf,"\"%s\"",optlist[i].value);
break;
case VSTRING:
case UNDELIMV:
if( optlist[i].value == NULL ) /* this should never happen */
sprintf(stval_buf,"\"\"");
else
if( OPTVALUE(char *,i) == NULL )
sprintf(stval_buf,"\"\"");
else
sprintf(stval_buf,"\"%s\"",OPTVALUE(char *,i));
break;
default:
opt_fatal("optstrval: Undefined o-type");
break;
}
/* ---- Return value is static buffer ---- */
return(stval_buf);
}/*optstrval*/
/* optstrtyp:
* returns the type of the ith registered option as a string
* Thus if x = 12.6 is a float , this returns the string "<real>"
* The return value is a pointer to a static string which is
* overwritten with each call
*/
char *
optstrtyp(i)
int i;
{
static char sttyp_buf[80];
switch( optlist[i].type )
{
case INT:
case UNSINT:
case LONG:
strcpy(sttyp_buf,"<integer>");
break;
case FLOAT:
case DOUBLE:
strcpy(sttyp_buf,"<real>");
break;
case CHAR:
strcpy(sttyp_buf,"<character>");
break;
case INTLEVEL:
case FLAG:
case NEGFLAG:
case ABSFLAG:
case ABSNEGFLAG:
strcpy(sttyp_buf,"<flag>");
break;
case VSTRING:
case CSTRING:
case UNDELIMV:
case UNDELIMC:
strcpy(sttyp_buf,"<string>");
break;
default:
opt_fatal("usage: undefined o-type");
}
return(sttyp_buf);
}
/* ------------------------------ */
/* Put registered options to file */
/* ------------------------------ */
int
opt_tofile(fp)
FILE *fp;
{
int i;
char *format;
char *fnumstr="-%c %-38s %c%s\n"; /* numbers and strings */
char *fflgchr="-%c%-38s %c%s\n"; /* flags and characters */
void opt_fileheader();
opt_fileheader(fp);
for(i=0; i<nregopts; ++i)
{
if( OPT_isundelimtype( optlist[i].type ) )
continue;
if( OPT_isflagtype( optlist[i].type )
|| optlist[i].type == INTLEVEL
|| optlist[i].type == CHAR )
format = fflgchr;
else
format = fnumstr;
fprintf(fp,format,optlist[i].name,
optstrval(i),IGNOREEOL,optlist[i].brief);
}
}
void
opt_fileheader(fp)
FILE *fp;
{
extern char *opt_program_name;
int i,n;
char buf[80];
sprintf(buf,"Options file created by: [%.30s]",opt_program_name);
n = strlen(buf);
fputc(IGNOREEOL,fp);
fprintf(fp,"%s",buf);
fputc(IGNOREEOL,fp); fputc('\n',fp);
fputc(IGNOREEOL,fp);
for(i=0;i<n;++i) fprintf(fp,"-");
fputc(IGNOREEOL,fp); fputc('\n',fp);
}
/* ----------------------------------------- */
/* write options out to the interactive menu */
/* ----------------------------------------- */
char *
opt_mstring(i)
int i;
{
static char mstring[180];
char flgstr[10];
char *s;
char *optstrval();
char *format = "%c %-40s %s";
if( OPT_isundelimtype( optlist[i].type ) )
return(NULL);
s = optstrval(i);
if( optlist[i].type == INTLEVEL )
{
int f;
f = OPTVALUE(int,i);
if(f==0)
strcpy(flgstr,"OFF");
else if (f==1)
strcpy(flgstr,"ON");
else
sprintf(flgstr,"ON:%d",f);
s=flgstr;
}
else
if( optlist[i].type == CHAR )
{
switch (s[0])
{
case '\0': sprintf(flgstr,"\'\\0\'"); break;
case '\n': sprintf(flgstr,"\'\\n\'"); break;
case '\t': sprintf(flgstr,"\'\\t\'"); break;
case ' ': sprintf(flgstr,"\' \'"); break;
default: sprintf(flgstr,"%c",s[0]); break;
}
s = flgstr;
}
else
if( OPT_isflagtype( optlist[i].type ) )
{
if( *s == '+' )
strcpy(flgstr,"TRUE");
if( *s == '-' )
strcpy(flgstr,"FALSE");
s=flgstr;
}
sprintf(mstring,format,optlist[i].name,optlist[i].brief,s);
return(mstring);
}
int
opt_fprint(fp,i)
FILE *fp;
int i;
{
char *optstrval();
fprintf(fp,"-%c%-17s %c%s\n",optlist[i].name,
optstrval(i),IGNOREEOL,optlist[i].brief);
return(i);
}
/* ----------------------------------------------------- */
/* write a usage statement describing registered options */
/* ----------------------------------------------------- */
void
opt_usage()
{
char buf[100];
char *dformat = " -%c %-12s\t%s\n";
char *uformat = " %-12s\t%s\n";
int i;
for(i=0; i<nregopts; ++i)
{
if( OPT_isundelimtype( optlist[i].type ) )
{
sprintf(buf,uformat,
optstrtyp(i),optlist[i].brief);
opt_message(buf);
}
else
{
sprintf(buf,dformat,optlist[i].name,
optstrtyp(i),optlist[i].brief);
opt_message(buf);
}
}
}
/* ----------------------- */
/* Get and process options */
/* ----------------------- */
/*
* The routines below make use of the ARGVECTOR structure
* defined in "ag.h" to process the command line options
*/
/* -------------------------------------- */
/* get and process an UN-delimited option */
/* -------------------------------------- */
int
opt_undelim(ag)
ARGVECTOR *ag;
{
int i;
char *s;
if(1)
{
/* This is the hook that the programmer can install
* to filter undelimited strings from the command line
*/
extern PFI ufilter_fcn;
if( ufilter_fcn != NULL )
if( (*ufilter_fcn)(ag_s(ag),ag) != 0 )
return(1);
}
if(DEBUG)
{
opt_message("opt_udelim: ");
ag_fprint(ag);
}
/* Find the first un-initialized undelimited option */
/* and set that to the argument string */
/* Note that once an undelimited option has been initialized */
/* it cannot be reset to a new value unless it is somehow */
/* set back to NULL or blank */
s = ag_s_advance(ag);
for(i=0; i<nregopts; ++i)
{
if( optlist[i].type==UNDELIMC && *(optlist[i].value)=='\0' )
{
strcpy( optlist[i].value, s );
return(1);
}
if( optlist[i].type==UNDELIMV && OPTVALUE(char *,i)==NULL )
{
SETOPTVALUE(char *,i,(char *)malloc(strlen(s)+1));
strcpy( OPTVALUE(char *,i), s );/* ?? */
return(1);
}
}
return(0);
}
/* ---------------------------------- */
/* get and process a delimited option */
/* ---------------------------------- */
opt_delim(ag)
ARGVECTOR *ag;
{
int i;
opt_TYPE o;
char c;
char *s;
int yes,no,maybe,toggle; /* flag values */
/**************************************************
* first, check to see if the programmer wants to
* interrupt this delimited option: if so, it will
* be done by the routine (*dfilter_fcn)(), which
* the programmer has provided and a
* nonzero value will be returned.
***************************************************/
if(1)
{
extern PFI dfilter_fcn;
if( dfilter_fcn != NULL )
if( (*dfilter_fcn)(ag_s(ag),ag) != 0 )
return(1);
}
c = ag_c_advance(ag); /* first character gives name of option */
i = opt_number(c); /* this is number of option w/ name 'c' */
if(i<0) /* if invalid option name */
{
char s[80];
sprintf(s,"%c not a registered option name\n",c);
opt_warning(s);
return(0);
}
/* ------------- */
/* act on option */
/* ------------- */
switch( o=optlist[i].type )
{
case INT:
SETOPTVALUE(int,i, argnextnum(ag));
break;
case UNSINT:
SETOPTVALUE(unsigned int,i, argnextnum(ag));
break;
case LONG:
SETOPTVALUE(long,i, argnextnum(ag));
break;
case FLOAT:
SETOPTVALUE(float,i, argnextnum(ag));
break;
case DOUBLE:
SETOPTVALUE(double,i, argnextnum(ag));
break;
case CHAR:
SETOPTVALUE(char,i, ag_c_advance(ag));
break;
case FLAG:
case NEGFLAG:
case ABSFLAG:
case ABSNEGFLAG:
/* define terms:
* yes: value of flag when ON
* no: value of flag when OFF
* maybe: present value of flag
* toggle: negative of maybe
*/
maybe = OPTVALUE(int,i);
toggle = (maybe==TRUE ? FALSE : TRUE);
if( o==FLAG || o==ABSFLAG ) yes=TRUE;
else yes=FALSE;
no = (yes==TRUE ? FALSE : TRUE);
c = ag_c(ag); /* character following 'c' */
switch(c)
{
case '+':
*((int *)(optlist[i].value)) = yes;
ag_c_advance(ag); /* eat the '+' */
break;
case '-':
*((int *)(optlist[i].value)) = no;
ag_c_advance(ag); /* eat the '-' */
break;
default:
if( o==ABSFLAG || o==ABSNEGFLAG )
*((int *)(optlist[i].value)) = maybe;
else /* otherwise toggle value */
*((int *)(optlist[i].value)) = toggle;
break;
}
break;
case INTLEVEL:
SETOPTVALUE(int,i,OPTVALUE(int,i) + 1); /* default is to increment */
c = ag_c(ag);
switch(c)
{
case '+':
/* we've already incremented */
ag_c_advance(ag);
break;
case '-':
SETOPTVALUE(int,i,0);
ag_c_advance(ag);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
SETOPTVALUE(int,i,c-'0');
ag_c_advance(ag);
default:
break;
}
break;
case VSTRING:
s = argnext(ag);
if( OPTVALUE(char *,i) != NULL )
free( OPTVALUE(char *,i)); /* if prev. malloc'd */
*((char **)(optlist[i].value)) = (char *)malloc( strlen(s)+1 );
strcpy( OPTVALUE(char *,i) , s );
break;
case CSTRING:
strncpy( optlist[i].value , argnext(ag), OPT_MAXSTRLEN );
break;
case UNDELIMC:
case UNDELIMV:
opt_fatal("opt_delim: can't process UNDELIM type");
break;
default:
opt_fatal("opt_delim: don't know this type");
break;
}
return(1);
}
/* opt_proc.c */
/*
* process options in the OPT package
*/
#ifndef SINGLEFILE
#include <stdio.h>
#include <ctype.h>
#ifdef convex
#include <strings.h>
#else
#include <string.h>
#endif
#ifdef __TURBOC__
#include <alloc.h>
#include <stdarg.h>
#endif
#include "ag.h"
#include "opt_p.h"
static char gstr[160]; /* general purpose global string */
#endif /* SINGLEFILE */
/******************
* Global variables
*/
char *opt_program_name;
flag fileflag = False;
char *optfile_name;
char *opt_envstring=NULL;
char *opt_defstring=NULL;
PFI dfilter_fcn=NULL,
ufilter_fcn=NULL,
verify_fcn=NULL, /* NOTE: this has been disabled ! */
doc_fcn=NULL,
quit_fcn=NULL,
help_fcn=NULL,
run_fcn=NULL;
/****************************
* Static Function prototypes
*/
static int line2argv();
static int l2a();
static flag break_word();
static char *Title = NULL;
static char *Usage = NULL;
/***************************
* set title, usage, etc. *
***************************/
void
opt_title_set(s)
char *s;
{
if(Title != NULL)
free(Title);
Title = (char *)calloc(strlen(s)+1,sizeof(char));
if(Title == NULL)
sprintf(gstr,"opt_title_set: cannot allocate for %s",s),
opt_fatal(gstr);
strcpy(Title,s);
}
void
opt_wr_title()
{
sprintf(gstr,"%s\n",
(Title==NULL ? opt_program_name : Title));
opt_message(gstr);
}
void
opt_usage_set(s)
char *s;
{
if(Usage != NULL)
free(Usage);
Usage = (char *)calloc(strlen(s)+1,sizeof(char));
if(Usage == NULL)
sprintf(gstr,"opt_usage_set: cannot allocate for %s",s),
opt_fatal(gstr);
strcpy(Usage,s);
}
void
opt_dfilter_set(fcn)
PFI fcn;
{
extern PFI dfilter_fcn;
dfilter_fcn = fcn;
}
void
opt_ufilter_set(fcn)
PFI fcn;
{
extern PFI ufilter_fcn;
ufilter_fcn = fcn;
}
void
opt_verify_set(fcn)
PFI fcn;
{
extern PFI verify_fcn;
opt_warning("The verify facility has been disabled!!");
verify_fcn = fcn;
}
void
opt_quit_set(fcn)
PFI fcn;
{
extern PFI quit_fcn;
quit_fcn = fcn;
}
void
opt_doc_set(fcn)
PFI fcn;
{
extern PFI doc_fcn;
doc_fcn = fcn;
}
void
opt_help_setf(fcn)
PFI fcn;
{
extern PFI help_fcn;
help_fcn = fcn;
}
void
opt_run_set(fcn)
PFI fcn;
{
extern PFI run_fcn;
run_fcn = fcn;
}
void
opt_env_set(s)
char *s;
{
extern char *opt_envstring;
opt_envstring = s;
}
void
opt_default_set(s)
char *s;
{
extern char *opt_defstring;
opt_defstring = s;
}
/* ------------------------------------------------------------------ */
/* ------- */
/* getopts */
/* ------- */
/*
* this is the routine that is called from main(argc,argv).
* returns value of argc.
*/
int
getopts(argc,argv)
int argc;
char *argv[];
{
int nargc;
char **nargv;
char *short_progname();
char *append_string();
/*
* Before processing, set the global variables
* opt_program_name : name of routine that is running
* optfile_name : default name of options file
*/
opt_program_name = short_progname(argv[0]);
optfile_name = append_string(opt_program_name,OPT_EXT);
/* Begin options processing */
/* ------------------------ */
/* First process default string */
opt_lineprocess(opt_defstring);
/* Second, check environment variable */
if(opt_envstring != NULL)
{
char *s;
char *getenv();
s = getenv(opt_envstring);
opt_lineprocess(s);
}
/* Finally, parse the command line */
opt_process(argc-1,argv+1);
return(argc);
}
char *
append_string(s,t)
char *s,*t;
{
/* input two strings "s" and "t":
* concatenates them to get string "st"
* which it allocates space for and returns
*/
char *st;
st = (char *)malloc( strlen(s)+strlen(t)+1 );
strcpy(st,s);
strcat(st,t);
return(st);
}
char *
short_progname(pname)
char *pname;
{
char *p;
int len;
/*
* inelegant routine
* returns the shortened name of the program named [pname].
* It (recursively) strips off leading directory or drive number
* and trailing ".EXE" in the case of MS-DOS executable
*/
p = pname;
while( *p != '/' && *p!='\\' && *p!=':' && *p!='\0' )
++p;
if( *p=='\0')
{ /* remove .EXE if it exists */
len = strlen(pname);
if( len > 4 )
{
if( ( 0==strcmp(pname+len-4,".EXE") ||
0==strcmp(pname+len-4,".exe") ) )
pname[len-4]='\0';
}
return( pname );
}
else
return( short_progname(++p) );
}
/* ----------------------------------------------------------------- */
/* ------- */
/* process */
/* ------- */
/****************************************************************
* opt_process():
* INPUT:
* argc, argv;
*
* this is the central receiving facility for the options package.
* opt_process takes an argument list given by (argc,argv) and
* and processes it,
* Although the input may come from either of
* system command line
* options file
* interactive command line
* the behavior is slightly different if the global menuflag is set
*/
void
opt_process(argc,argv)
int argc;
char *argv[];
{
char c;
char *s;
int iword;
ARGVECTOR agvect,*ag;
/*
* convert the argument vector (argc,argv) into
* an ARGVECTOR structure, to ease manipulations
*/
if( argc==0 )
return;
ag = &agvect;
ag_new(argc,argv,ag);
if(DEBUG)
{
ag_fprint(stderr,ag);
}
/* Loop through the options in the argument vector */
while( !ag_end(ag) )
{
if( ag_eow(ag) ) /* if necessary... */
ag_w_advance(ag); /* advance to next word */
if(DEBUG)
if( ag->ic != 0 ) /* this should never happen */
opt_warning("opt_process: not on first character");
c=ag_c_advance(ag); /* first character of word */
/* ------ */
/* switch */
/* ------ */
switch( c )
{
case DELIM:
case ALTDELIM:
/* if unadorned "-" */
if( ag_eow(ag) )
{
if (!menuflag && !fileflag)
{
usage(""); /* usage message */
opt_abort_run();
}
ag_clear(ag);
}
/* if "--something" */
else
if( ag_c(ag) == c )
{
if (!menuflag && !fileflag)
{
usage(argnext(ag));
opt_abort_run();
}
}
/* if "-something" */
else
{
iword = ag_w_number(ag);
while( iword==ag_w_number(ag) && !ag_eow(ag) )
opt_delim(ag);
}
break;
case OPTFROMFILE:
if(1)
{
flag tmp_fileflag;
tmp_fileflag = fileflag;
fileflag = True;
opt_fromfname(argnext(ag));
fileflag = tmp_fileflag;
}
break;
case OPTTOFILE:
opt_tofname(argnext(ag));
break;
case HELPCH:
if( !fileflag)
opt_help(argnext(ag));
break;
case INTERACT:
if ( !menuflag ) /* If not called already */
opt_menu(); /* Call the menu */
else /* otherwise */
{
menuflag=False; /* turn off menu */
ag_clear(ag);
}
break;
case IGNOREEOL:
ag_clear(ag);
break;
case RUN:
if( run_fcn != NULL )
opt_begin_run(run_fcn);
else
{
/* if run_fcn is not set, and 'RUN' is called
* from the menu, then exit the menu, so that
* the routine is run, and then program will exit
*/
if ( menuflag )
{
menuflag=False; /* turn off menu */
ag_clear(ag);
}
else
{
/* RUN called from a file or the command line:
* There is no reason to be doing this.
*/
opt_warning("No Run Function has been registered");
}
break;
case QUITCH:
opt_quit();
break;
case BANG:
if (!menuflag)
opt_warning("Shell can only be invoked from the menu");
else
{
sprintf(gstr,"Shell to system invalid unless \'%c\'",BANG);
strcat(gstr," is the first character in the line\n");
opt_warning(gstr);
}
#if 0
/* bang...shell to system */
if(1)
{
char s[160];
strcpy(s,argnext(ag));
system(s);
break;
}
#endif
case ' ': /* blanks and empty characters, ignore */
case '\t':
case '\0':
break;
default:
/* in the default case, option may be undelimited */
/* ---------------------------------------------- */
ag_backspace(ag);
if(DEBUG)
{
sprintf(gstr,
"opt_process: in default section [%s]\n",ag_s(ag));
opt_warning(gstr);
}
if(1)
{
char s[80];
strcpy(s,ag_s(ag));
if( opt_undelim(ag) == 0)
{
sprintf(gstr,
"%c (in %s) is invalid delimeter\n",
c,s);
opt_warning(gstr);
}
}
break;
}
}
}
}/*opt_process*/
/* opt_lineprocess()
* process a string, by converting it first into an argument vector
* then calling opt_process
* return the number of processed arguments
*/
int
opt_lineprocess(line)
char *line;
{
int nargc;
char **nargv;
if( line==NULL || *line=='\0') return(0);
line2argv(&nargc,&nargv,line);
opt_process(nargc,nargv);
return(nargc);
}
/* line2argv(): converts a one-line string into an argument vector */
static int
line2argv(pargc,pargv,line)
int *pargc;
char ***pargv;
char *line;
{
char *lincp;
if(line==NULL)
{
*pargc = 0;
**pargv = NULL;
return(0);
}
/*
* First thing to do is copy the line into
* a buffer ("lincp") so that input line will
* not be corrupted -- also so that input line
* doesn't have to be double null terminated
*/
lincp = (char *)calloc(strlen(line)+2,sizeof(char));
strcpy(lincp,line);
/*
* Next step is to double null terminate
* the copied line
*/
lincp[strlen(line)+1]='\0';
/* count words in line */
*pargc = l2a(lincp,NULL);
/* allocate array for arg vector */
*pargv = (char **)malloc(((*pargc)+1)*sizeof(char *));
/* fill arg vector with words in line */
l2a(lincp,*pargv);
/*
* Note that lincp cannot be freed since
* that space is used by pargv
*/
return(*pargc);
}
#define QUOTE '\"'
#define BKSLASH '\\'
/* l2a */
/* l2a() is slave routine to line2argv() */
/* if argv==NULL then count the words in the line */
/* if argv!=NULL then put those words into argv[] */
/* WARNINGS:
* l2a assumes that input line is double-null terminated!!
* the line buffer is pointed to by argv[]'s so do not
* free the input line buffer
*/
/* quoted material counts as a single word */
/* so that -s"string with spaces"-g is parsed */
/* into
-s
string with spaces
-g
*/
/* Comment: should be able to escape with backslash */
static int
l2a(line,argv)
char *line;
char **argv;
{
flag inquote=False; /* flag: inside quotation */
int iarg;
for(iarg=0; *line != '\0'; ++iarg)
{
if(!inquote)
{
while( isspace(*line) )
++line; /* skip leading blank spaces */
if( *line == QUOTE )
{
inquote=True;
++line; /* skip past leading quote */
}
}
if(argv!=NULL) /* point to */
argv[iarg] = line; /* first character of line */
while( !break_word(inquote,line) )
++line;
if( *line==QUOTE ) /* toggle quote */
{
inquote = (inquote==True ? False : True );
if(argv==NULL) ++line; /* skip past quote */
}
if(argv!=NULL)
{
*line='\0'; /* Null terminate string */
++line; /* and go to next character */
}
else
while( isspace(*line) )
++line; /* skip trailing blanks */
}
return(iarg);
}
static flag
break_word(inquote,line)
flag inquote;
char *line;
{
if( *line == '\0' || *line==QUOTE )
return(True);
if( !inquote && isspace(*line) )
return(True);
return(False);
}
/* --------------------------- */
/* write out a usage statement */
/* --------------------------- */
/* usage("") gives minimal usage message
usage("-") gives fuller usage message
usage("--") gives output document
*/
static void short_usage();
static void long_usage();
static void doc_usage();
void
usage(s)
char *s;
{
if (s==NULL || *s=='\0')
{
short_usage();
sprintf(gstr,"For a list of options, type:\n"), opt_message(gstr);
sprintf(gstr,"\t%s %c%c\n",opt_program_name,DELIM,DELIM);
doc_usage();
return;
}
else
if (*s == DELIM )
{
++s;
if (*s=='\0')
{
short_usage();
doc_usage();
long_usage();
return;
}
if (*s==DELIM)
{
opt_doc();
return;
}
}
}
static void
short_usage()
{
if(Title != NULL)
sprintf(gstr,"%s\n",Title), opt_message(gstr);
if(Usage != NULL)
sprintf(gstr,"[%s] %s\n",opt_program_name,Usage), opt_message(gstr);
sprintf(gstr,"To invoke the menu, type:\n\t%s %c\n",
opt_program_name,INTERACT),
opt_message(gstr);
}
static void
long_usage()
{
sprintf(gstr,"The options are:\n"), opt_message(gstr);
opt_usage();
}
static void
doc_usage()
{
if(doc_fcn != NULL)
{
sprintf(gstr,"For fuller documentation, type:\n\t"),
opt_message(gstr);
sprintf(gstr,"%s %c%c%c\n",opt_program_name,
DELIM,DELIM,DELIM),
opt_message(gstr);
}
}
/* --------------------------------- */
/* put current options in named file */
/* --------------------------------- */
int
opt_tofname(fname)
char *fname;
{
FILE *fp;
if( *fname != OPTTOFILE )
{
free((char *)optfile_name);
optfile_name = append_string(fname,"");
}
if( access(optfile_name,0)==0 )
{
sprintf(gstr,"Options file [%s] has been overwritten\n",
optfile_name), opt_message(gstr);
backup_file(optfile_name);
}
fp = fopen(optfile_name,"w");
if(fp==NULL)
{
sprintf(gstr,"cant open file %s\n",fname), opt_message(gstr);
return(0);
}
opt_tofile(fp);
fclose(fp);
return(1);
}
#ifdef __TURBOC__
backup_file(fname)
char *fname;
{}
#else
backup_file(fname)
char *fname;
{
char fname_backup[80];
sprintf(fname_backup,"%s%s",fname,"~");
sprintf(gstr,"%s %s %s","cp",fname,fname_backup);
system(gstr);
sprintf(gstr,"File [%s] is backup file\n",fname_backup);
opt_message(gstr);
}
#endif
/* ----------------------------------------- */
/* get and process options from a named file */
/* ----------------------------------------- */
#define MAXOPLINE 256
int
opt_fromfname(fname)
char *fname;
{
FILE *fp;
char line[MAXOPLINE+2]; /* leave room for termination */
if( *fname != OPTFROMFILE ) /* if not default file */
{
if( access(fname,0)!=0 ) /* if file doesn't exist */
{
sprintf(gstr,"File [%s] does not exist\n",fname);
opt_message(gstr);
return(0);
}
else
{
free((char *)optfile_name);
optfile_name = append_string(fname,"");
}
}
fp = fopen(optfile_name,"r");
if(fp==NULL)
{
sprintf(gstr,"Cannot open options file [%s]\n",optfile_name);
opt_warning(gstr);
return(0);
}
while( opt_getline(line,fp) > 0 )
opt_lineprocess(line);
fclose(fp);
return(1);
}
int
opt_getline(line,fp)
char *line;
FILE *fp;
{
int c;
int count=0;
while( (c=getc(fp)) != '\n' && c!=EOF )
{
*line = (char)c;
++line;
if( ++count > MAXOPLINE-3 )
{
opt_warning("Options line too long");
break;
}
}
*line++ = '\0'; /* double terminate line !! */
*line++ = '\0';
return(count);
}/*opt_getline*/
/* ------------------- */
/* basic help function */
/* ------------------- */
void
opt_help(s)
char *s;
{
if(s==NULL || *s=='\0')
{
sprintf(gstr,"\t%c %-20s\n",DELIM,"Options delimiter"),
opt_message(gstr);
sprintf(gstr,"\t%c %-20s\n",HELPCH,"Help"),
opt_message(gstr);
sprintf(gstr,"\t%c %-20s\n",RUN,"Run program and return to menu"),
opt_message(gstr);
sprintf(gstr,"\t%c %-20s\n",BANG,"Shell to Operating System"),
opt_message(gstr);
if (menuflag)
sprintf(gstr,"\t%c %-20s\n",INTERACT,"Exit menu"),
opt_message(gstr);
else
sprintf(gstr,"\t%c %-20s\n",INTERACT,"Invoke menu"),
opt_message(gstr);
sprintf(gstr,"\t%c %-20s\n",ADDITIONAL_OPTS,"Additional options"),
opt_message(gstr);
sprintf(gstr,"\t%c<filename> %-20s\n",OPTFROMFILE,
"Get options from file",optfile_name),
opt_message(gstr);
sprintf(gstr,"\t%c%c %-2s [%s]\n",OPTFROMFILE,OPTFROMFILE,
"Get options from file",optfile_name),
opt_message(gstr);
sprintf(gstr,"\t%c<filename> %-20s\n",OPTTOFILE,
"Put options in file"),
opt_message(gstr);
sprintf(gstr,"\t%c%c %-2s [%s]\n",OPTTOFILE,OPTTOFILE,
"Put options in file",optfile_name),
opt_message(gstr);
sprintf(gstr,"\t%c %-20s\n",QUITCH,"Quit"),
opt_message(gstr);
}
else
{
/* first check if help is available for single character delimiter */
if( s[1]=='\0' && opt_number(s[0]) >=0 )
opt_get_help(s[0]);
else
{
if( help_fcn==NULL )
sprintf(gstr,"Help unavailable for: [%s]\n",s),
opt_message(gstr);
else
(*help_fcn)(s);
}
}
}
/* ------ */
/* quit() */
/* ------ */
void
opt_quit()
{
if( quit_fcn == NULL )
opt_abort_run();
else
{
(*quit_fcn)();
opt_abort_run();
}
}
/* ---------- */
/* document() */
/* ---------- */
void
opt_doc()
{
if( doc_fcn == NULL )
return;
else
(*doc_fcn)();
}
/* opt_menu.c */
#ifndef SINGLEFILE
#include <stdio.h>
#include <ctype.h>
#ifdef convex
#include <strings.h>
#else
#include <string.h>
#endif
#ifdef __TURBOC__
#include <alloc.h>
#endif
#include "opt_p.h"
#endif /* SINGLEFILE */
/* --------------------- menu flag ------------------- */
flag menuflag=False;
static char mgstring[160]; /* global menu string */
#define menu_wr_string(str) opt_message(str)
#define menu_getresponse(respond) opt_getline(respond,stdin)
static void write_the_menu();
static int auto_prefix_delim();
/* ---------------------------------------------------- */
/* opt_menu: Get options from an interactive menu */
/* ---------------------------------------------------- */
#define MAXRESPONDLINE 280
#ifndef MAXOPTSINMENU
#define MAXOPTSINMENU 20
#endif
void
opt_menu()
{
char respond[MAXRESPONDLINE+2];
static int maxoptsinmenu=MAXOPTSINMENU;
flag fullmenu;
int iop,iopfrom,iopto;
menuflag=True; /* turn on MENUFLAG in case it is not set already */
iopfrom = 0;
iopto = ( nregopts < maxoptsinmenu ? nregopts : maxoptsinmenu );
respond[0]='\0';
opt_wr_title();
write_the_menu(iopfrom,iopto);
while( menuflag )
{
menu_wr_string("-> ");
menu_getresponse(respond);
switch(*respond)
{
case ADDITIONAL_OPTS:
if( respond[1] != '\0' && respond[1] != ' ' )
{
maxoptsinmenu = atoi(respond+1);
if(maxoptsinmenu < 1)
maxoptsinmenu = nregopts;
sprintf(mgstring,"Scroll %d options\n",maxoptsinmenu);
menu_wr_string(mgstring);
iopfrom = 0;
iopto =
( nregopts < maxoptsinmenu ? nregopts : maxoptsinmenu );
}
else
{
iopfrom += maxoptsinmenu;
if( iopfrom > nregopts)
iopfrom = 0;
iopto = iopfrom + maxoptsinmenu;
if( iopto > nregopts )
iopto = nregopts;
}
write_the_menu(iopfrom,iopto);
break;
case INTERACT:
menuflag=False;
break;
case BANG:
system( respond+1 );
break;
case '\0':
write_the_menu(iopfrom,iopto);
break;
case QUITCH:
/* only quit if the QUITCH is followed by whitespace */
if ( respond[1]=='\0' || respond[1]==' ' )
opt_abort_run(0);
break;
case DELIM:
case ALTDELIM:
opt_lineprocess(respond);
break;
default:
auto_prefix_delim(respond);
opt_lineprocess(respond);
break;
}
}
}/* opt_menu */
/**********
* write_the_menu:
* write the menu including options from iopfrom to iopto.
*/
static void
write_the_menu(iopfrom,iopto)
int iopfrom,iopto;
{
int iop;
flag fullmenu;
fullmenu = ((iopfrom==0 && iopto==nregopts) ? True : False );
if( !fullmenu )
{
sprintf(mgstring,"menu: %d->%d [%d]\n",iopfrom,iopto,nregopts);
menu_wr_string(mgstring);
}
for(iop=iopfrom; iop<iopto; ++iop)
{
char *s;
s = opt_mstring(iop);
if (s!=NULL)
{
strcpy( mgstring, s );
menu_wr_string(mgstring);
menu_wr_string("\n");
}
}
if (!fullmenu)
{
sprintf(mgstring,"%c Additional options\n",ADDITIONAL_OPTS);
menu_wr_string(mgstring);
}
sprintf(mgstring,"(Type %c for Help)\n",HELPCH);
menu_wr_string(mgstring);
}
/* auto_prefix_delim:
* this is a fru-fru piece of code that automatically
* sticks a DELIM character onto the front of a string
* in cases where it imagines that that is what the user
* really meant. Thus
* -> m4
* gives the same effect as
* -> -m4
* But be warned that this only applies in limited cases.
* Eg.,
* -> m4 b3
* is not the same as
* -> -m4 -b3
*
* a '-' will be prepended in the case that
* the first character is a registered name
*/
static int
auto_prefix_delim(r)
char *r;
{
if( opt_number( *r ) != -1 )
{
int len;
len = strlen(r)+1; /* +1 since double terminated */
while(len>=0)
{
r[len+1]=r[len];
--len;
}
r[0]=DELIM;
return(1);
}
else
return(0);
}/* auto_prefix_delim */
/**************************
* some useful utilities *
**************************/
/*
* 1) Variable argument lists: for error messages
* opt_errmess(), gives message and then aborts run
* 2) Long Jump: for aborting run() without losing the entire job
* opt_begin_run()
* opt_abort_run()
* 3) Signal: trapping ^C so that it aborts run()
*
*/
/* Can be disabled by setting constants
* DISABLE_VARARG,
* DISABLE_LONGJUMP,
* DISABLE_SIGNAL
*/
#ifndef SINGLEFILE
#include <stdio.h>
#include "opt_p.h"
#endif
static void set_signal(/* void */);
static void unset_signal(/* void */);
static void catch_signal(/* void */);
void
opt_message(s)
char *s;
{
if (s != NULL)
fputs(s,stderr);
}
void
opt_warning(s)
char *s;
{
fputs(opt_program_name,stderr);
fputs(":: ",stderr);
fputs("OPT Warning: ",stderr);
fputs(s,stderr);
fputs("\n",stderr);
}
void
opt_fatal(s)
char *s;
{
fputs(opt_program_name,stderr);
fputs(":: ",stderr);
fputs("OPT Fatal error: ",stderr);
fputs(s,stderr);
exit(1);
}
/**********
* VARARG *
**********/
#if DISABLE_VARARG
void
opt_errmess(s)
char *s;
{
fputs(opt_program_name,stderr);
fputs(":: ",stderr);
fputs(s,stderr);
opt_abort_run();
}
#else /* if not DISABLE_VARARGS */
#ifdef __TURBOC__
/* Turbo-C implements variable argument lists differently than SUN */
#ifndef SINGLEFILE
#include <stdarg.h>
#endif
void
opt_errmess(char *format, ...)
{
va_list argptr;
va_start(argptr,format);
vfprintf(stderr,format,argptr);
va_end(argptr);
opt_abort_run();
}
#else /* if not __TURBOC__ but default instead */
#ifndef SINGLEFILE
#include <stdarg.h>
#endif
#endif /* if __TURBOC__ */
#endif /* end VARARGS */
/************
* LONGJUMP *
************/
#if DISABLE_LONGJUMP
int
opt_begin_run(run)
int (*run)();
{ return( (*run)() );
}
void
opt_abort_run()
{ exit(1);
}
#else /* if not DISABLE_LONGJUMP */
#ifndef SINGLEFILE
#include <setjmp.h>
#endif
static jmp_buf opt_jumpstart;
static int opt_jump_set=FALSE;
void
opt_abort_run()
{
if(opt_jump_set)
longjmp(opt_jumpstart,1);
else
exit(1);
}
int
opt_begin_run(run)
int (*run)();
{
int value;
opt_jump_set=TRUE;
set_signal();
value = setjmp(opt_jumpstart);
if(value!=0)
opt_message("Run aborted...try again\n");
else
value = (*run)();
unset_signal();
opt_jump_set=FALSE;
return value;
}
#endif /* end LONGJUMP */
/**********
* SIGNAL *
**********/
#if DISABLE_SIGNAL
static void
set_signal()
{}
static void
unset_signal()
{}
#else
#ifndef SINGLEFILE
#include <signal.h>
#endif
static void (*old_catcher)();
static void
set_signal()
{
old_catcher = signal(SIGINT,catch_signal);
}
static void
unset_signal()
{
signal(SIGINT,old_catcher);
}
#ifdef __TURBOC__
static void catch_signal(sig)
int sig;
#else
#ifdef convex
static void catch_signal(sig,code,scp)
int sig, code;
struct sigcontext *scp;
#else /* default */
static void catch_signal(sig,code,scp,addr)
int sig, code;
struct sigcontext *scp;
char *addr;
#endif
#endif
{
opt_message("\nOPT Interrupted:\n");
longjmp(opt_jumpstart,1);
perror("Did not long-jump");
exit(0);
}
#endif /* end SIGNAL */