home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------
- // ^FILE: shells.c - implement classes for the various Unix shells
- //
- // ^DESCRIPTION:
- // This file packages all the information we need to know about each
- // of the shells that cmdparse(1) will support into a set of (sub)classes.
- //
- // ^HISTORY:
- // 04/19/92 Brad Appleton <brad@ssd.csd.harris.com> Created
- //-^^---------------------------------------------------------------------
-
- #include <stdlib.h>
- #include <iostream.h>
- #include <string.h>
- #include <ctype.h>
-
- #include <fifolist.h>
-
- #include "shells.h"
- #include "argtypes.h"
-
- //--------------------------------------------------------------- ShellVariable
-
- ShellVariable::ShellVariable(const char * name)
- : var_name(name), var_value(NULL)
- {
- }
-
- ShellVariable::~ShellVariable(void)
- {
- }
-
- //------------------------------------------------------------ ShellArrayValues
-
- DECLARE_FIFO_LIST(CharPtrList, char *);
-
- struct ShellArrayValues {
- CharPtrList list;
- CharPtrListArray array;
-
- ShellArrayValues(void);
- } ;
-
- ShellArrayValues::ShellArrayValues(void)
- : array(list)
- {
- list.self_cleaning(1);
- }
-
- //------------------------------------------------------------------ ShellArray
-
- ShellArray::ShellArray(const char * name)
- : array_name(name), array_value(NULL)
- {
- }
-
- ShellArray::~ShellArray(void)
- {
- delete array_value ;
- }
-
- void
- ShellArray::append(const char * value)
- {
- if (array_value == NULL) {
- array_value = new ShellArrayValues ;
- }
- char ** valptr = new char* ;
- if (valptr) {
- *valptr = (char *)value;
- array_value->list.add(valptr);
- }
- }
-
- unsigned
- ShellArray::count(void) const
- {
- return ((array_value) ? array_value->list.count() : 0);
- }
-
- const char *
- ShellArray::operator[](unsigned index) const
- {
- return ((array_value) ? array_value->array[index] : NULL);
- }
-
- //----------------------------------------------------------- AbstractUnixShell
-
- AbstractUnixShell::~AbstractUnixShell(void)
- {
- }
-
- //------------------------------------------------------------------- UnixShell
-
- UnixShell::UnixShell(const char * shell_name)
- : shell(NULL), valid(1)
- {
- if (::strcmp(BourneShell::NAME, shell_name) == 0) {
- shell = new BourneShell ;
- } else if (::strcmp("ash", shell_name) == 0) {
- shell = new BourneShell ;
- } else if (::strcmp(KornShell::NAME, shell_name) == 0) {
- shell = new KornShell ;
- } else if (::strcmp(BourneAgainShell::NAME, shell_name) == 0) {
- shell = new BourneAgainShell ;
- } else if (::strcmp(CShell::NAME, shell_name) == 0) {
- shell = new CShell ;
- } else if (::strcmp("tcsh", shell_name) == 0) {
- shell = new CShell ;
- } else if (::strcmp("itcsh", shell_name) == 0) {
- shell = new CShell ;
- } else if (::strcmp(ZShell::NAME, shell_name) == 0) {
- shell = new ZShell ;
- } else if (::strcmp(Plan9Shell::NAME, shell_name) == 0) {
- shell = new Plan9Shell ;
- } else if (::strcmp(PerlShell::NAME, shell_name) == 0) {
- shell = new PerlShell ;
- } else if (::strcmp(TclShell::NAME, shell_name) == 0) {
- shell = new TclShell ;
- } else {
- valid = 0;
- }
- }
-
- UnixShell::~UnixShell(void)
- {
- delete shell;
- }
-
- const char *
- UnixShell::name(void) const
- {
- return ((shell) ? shell->name() : NULL);
- }
-
- void
- UnixShell::unset_args(const char * name) const
- {
- if (shell) shell->unset_args(name);
- }
-
- int
- UnixShell::is_positionals(const char * name) const
- {
- return ((shell) ? shell->is_positionals(name) : 0);
- }
-
- void
- UnixShell::set(const ShellVariable & variable) const
- {
- if (shell) shell->set(variable);
- }
-
- void
- UnixShell::set(const ShellArray & array, int variant) const
- {
- if (shell) shell->set(array, variant);
- }
-
- //----------------------------------------------------------------- varname
-
- // Remove any "esoteric" portions of a vraible name (such as a leading '$')
- //
- inline static const char *
- varname(const char * name, char skip)
- {
- return ((*name == skip) && (*(name + 1))) ? (name + 1): name ;
- }
-
- //----------------------------------------------------------------- BourneShell
-
- const char * BourneShell::NAME = "sh" ;
-
- BourneShell::BourneShell(void)
- {
- }
-
- BourneShell::~BourneShell(void)
- {
- }
-
- const char *
- BourneShell::name(void) const
- {
- return BourneShell::NAME ;
- }
-
- void
- BourneShell::unset_args(const char *) const
- {
- cout << "shift $# ;" << endl ;
- }
-
- int
- BourneShell::is_positionals(const char * name) const
- {
- name = varname(name, '$');
- return ((::strcmp(name, "--") == 0) || (::strcmp(name, "-") == 0) ||
- (::strcmp(name, "@") == 0) || (::strcmp(name, "*") == 0)) ;
- }
-
- void
- BourneShell::set(const ShellVariable & variable) const
- {
- const char * name = varname(variable.name(), '$');
- if (is_positionals(name)) {
- cout << "set -- '" ;
- } else {
- cout << name << "='" ;
- }
- escape_value(variable.value());
- cout << "';" << endl ;
- }
-
- void
- BourneShell::set(const ShellArray & array, int variant) const
- {
- int ndx;
- const char * name = varname(array.name(), '$');
-
- if (is_positionals(name)) {
- // set -- 'arg1' 'arg2' ...
- cout << "set -- ";
- for (ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- cout << '\'' ;
- escape_value(array[ndx]);
- cout << '\'' ;
- }
- cout << ';' << endl ;
- } else if (variant) {
- // argname_count=N
- // argname1='arg1'
- // ...
- // argnameN='argN'
- cout << name << "_count=" << array.count() << ';' << endl ;
- for (ndx = 0 ; ndx < array.count() ; ndx++) {
- cout << name << (ndx + 1) << "='";
- escape_value(array[ndx]);
- cout << "';" << endl ;
- }
- } else {
- // argname='arg1 arg2 ...'
- cout << name << "='";
- for (ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- escape_value(array[ndx]);
- }
- cout << "';" << endl ;
- }
- }
-
- void
- BourneShell::escape_value(const char * value) const
- {
- for ( ; *value ; value++) {
- switch (*value) {
- case '\'' :
- cout << "'\\''" ;
- break ;
-
- case '\\' :
- case '\b' :
- case '\r' :
- case '\v' :
- case '\f' :
- cout << '\\' ; // fall thru to default case
- default :
- cout << char(*value) ;
- }
- } //for
- }
-
- //------------------------------------------------------------------- KornShell
-
- const char * KornShell::NAME = "ksh" ;
-
- KornShell::KornShell(void)
- {
- }
-
- KornShell::~KornShell(void)
- {
- }
-
- const char *
- KornShell::name(void) const
- {
- return KornShell::NAME ;
- }
-
- void
- KornShell::unset_args(const char *) const
- {
- cout << "set -- ;" << endl ;
- }
-
- void
- KornShell::set(const ShellVariable & variable) const
- {
- BourneShell::set(variable);
- }
-
- void
- KornShell::set(const ShellArray & array, int variant) const
- {
- const char * name = varname(array.name(), '$');
- if (is_positionals(name)) {
- cout << "set -- " ;
- } else {
- cout << "set " << (variant ? '+' : '-') << "A " << name << ' ' ;
- }
- for (int ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- cout << '\'' ;
- escape_value(array[ndx]);
- cout << '\'' ;
- }
- cout << ';' << endl ;
- }
-
- //------------------------------------------------------------ BourneAgainShell
-
- const char * BourneAgainShell::NAME = "bash" ;
-
- BourneAgainShell::BourneAgainShell(void)
- {
- }
-
- BourneAgainShell::~BourneAgainShell(void)
- {
- }
-
- const char *
- BourneAgainShell::name(void) const
- {
- return BourneAgainShell::NAME ;
- }
-
- void
- BourneAgainShell::set(const ShellVariable & variable) const
- {
- BourneShell::set(variable);
- }
-
- void
- BourneAgainShell::set(const ShellArray & array, int variant) const
- {
- BourneShell::set(array, variant);
- }
-
- //---------------------------------------------------------------------- CShell
-
- const char * CShell::NAME = "csh" ;
-
- CShell::CShell(void)
- {
- }
-
- CShell::~CShell(void)
- {
- }
-
- const char *
- CShell::name(void) const
- {
- return CShell::NAME ;
- }
-
- void
- CShell::unset_args(const char *) const
- {
- cout << "set argv=();" << endl ;
- }
-
- int
- CShell::is_positionals(const char * name) const
- {
- name = varname(name, '$');
- return (::strcmp(name, "argv") == 0);
- }
-
- void
- CShell::set(const ShellVariable & variable) const
- {
- const char * name = varname(variable.name(), '$');
- int posl = is_positionals(name);
- cout << "set " << name << '=' ;
- if (posl) cout << '(' ;
- cout << '\'' ;
- escape_value(variable.value());
- cout << '\'' ;
- if (posl) cout << ')' ;
- cout << ';' << endl ;;
- }
-
- void
- CShell::set(const ShellArray & array, int ) const
- {
- cout << "set " << varname(array.name(), '$') << "=(" ;
- for (int ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- cout << '\'' ;
- escape_value(array[ndx]);
- cout << '\'' ;
- }
- cout << ");" << endl ;
- }
-
- void
- CShell::escape_value(const char * value) const
- {
- for ( ; *value ; value++) {
- switch (*value) {
- case '\'' :
- cout << "'\\''" ;
- break ;
-
- case '!' :
- case '\n' :
- case '\b' :
- case '\r' :
- case '\v' :
- case '\f' :
- cout << '\\' ; // fall thru to default case
- default :
- cout << char(*value) ;
- }
- } //for
- }
-
- //---------------------------------------------------------------------- ZShell
-
- const char * ZShell::NAME = "zsh" ;
-
- ZShell::ZShell(void)
- {
- }
-
- ZShell::~ZShell(void)
- {
- }
-
- const char *
- ZShell::name(void) const
- {
- return ZShell::NAME ;
- }
-
- void
- ZShell::unset_args(const char *) const
- {
- cout << "argv=();" << endl ;
- }
-
- int
- ZShell::is_positionals(const char * name) const
- {
- name = varname(name, '$');
- return ((::strcmp(name, "--") == 0) || (::strcmp(name, "-") == 0) ||
- (::strcmp(name, "@") == 0) || (::strcmp(name, "*") == 0) ||
- (::strcmp(name, "argv") == 0));
- }
-
- void
- ZShell::set(const ShellVariable & variable) const
- {
- const char * name = varname(variable.name(), '$');
- int posl = is_positionals(name);
- cout << name << '=' ;
- if (posl) cout << '(' ;
- cout << '\'' ;
- escape_value(variable.value());
- cout << '\'' ;
- if (posl) cout << ')' ;
- cout << ';' << endl ;;
- }
-
- void
- ZShell::set(const ShellArray & array, int ) const
- {
- cout << varname(array.name(), '$') << "=(" ;
- for (int ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- cout << '\'' ;
- escape_value(array[ndx]);
- cout << '\'' ;
- }
- cout << ");" << endl ;
- }
-
- void
- ZShell::escape_value(const char * value) const
- {
- for ( ; *value ; value++) {
- switch (*value) {
- case '\'' :
- cout << "'\\''" ;
- break ;
-
- case '!' :
- case '\\' :
- case '\b' :
- case '\r' :
- case '\v' :
- case '\f' :
- cout << '\\' ; // fall thru to default case
- default :
- cout << char(*value) ;
- }
- } //for
- }
-
- //------------------------------------------------------------------ Plan9Shell
-
- const char * Plan9Shell::NAME = "rc" ;
-
- Plan9Shell::Plan9Shell(void)
- {
- }
-
- Plan9Shell::~Plan9Shell(void)
- {
- }
-
- const char *
- Plan9Shell::name(void) const
- {
- return Plan9Shell::NAME ;
- }
-
- void
- Plan9Shell::unset_args(const char *) const
- {
- cout << "*=();" << endl ;
- }
-
- int
- Plan9Shell::is_positionals(const char * name) const
- {
- name = varname(name, '$');
- return (::strcmp(name, "*") == 0);
- }
-
- void
- Plan9Shell::set(const ShellVariable & variable) const
- {
- const char * name = varname(variable.name(), '$');
- int posl = is_positionals(name);
- cout << name << '=' ;
- if (posl) cout << '(' ;
- cout << '\'' ;
- escape_value(variable.value());
- cout << '\'' ;
- if (posl) cout << ')' ;
- cout << ';' << endl ;;
- }
-
- void
- Plan9Shell::set(const ShellArray & array, int ) const
- {
- cout << varname(array.name(), '$') << "=(" ;
- for (int ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- cout << '\'' ;
- escape_value(array[ndx]);
- cout << '\'' ;
- }
- cout << ");" << endl ;
- }
-
- void
- Plan9Shell::escape_value(const char * value) const
- {
- for ( ; *value ; value++) {
- switch (*value) {
- case '\'' :
- cout << "''" ;
- break ;
-
- case '\\' :
- case '\b' :
- case '\r' :
- case '\v' :
- case '\f' :
- cout << '\\' ; // fall thru to default case
- default :
- cout << char(*value) ;
- }
- } //for
- }
-
- //------------------------------------------------------------------- PerlShell
-
- const char * PerlShell::NAME = "perl" ;
-
- PerlShell::PerlShell(void)
- {
- static const char perl_true[] = "1" ;
- static const char perl_false[] = "0" ;
-
- // use different defaults for TRUE and FALSE
- ShellCmdArgBool::True(perl_true);
- ShellCmdArgBool::False(perl_false);
- }
-
- PerlShell::~PerlShell(void)
- {
- }
-
- const char *
- PerlShell::name(void) const
- {
- return PerlShell::NAME ;
- }
-
- void
- PerlShell::unset_args(const char *) const
- {
- cout << "@ARGV = ();" << endl ;
- }
-
- int
- PerlShell::is_positionals(const char * name) const
- {
- name = varname(name, '@');
- return (::strcmp(name, "ARGV") == 0);
- }
-
- void
- PerlShell::set(const ShellVariable & variable) const
- {
- const char * name = varname(variable.name(), '$');
- int array = (*name == '@') ;
- cout << (array ? "" : "$") << name << " = " ;
- if (array) cout << '(' ;
- cout << '\'' ;
- escape_value(variable.value());
- cout << '\'' ;
- if (array) cout << ')' ;
- cout << ';' << endl ;;
- }
-
- void
- PerlShell::set(const ShellArray & array, int ) const
- {
- const char * name = varname(array.name(), '@');
- int scalar = (*name == '$') ;
- cout << (scalar ? "" : "@") << name << " = " ;
- cout << (scalar ? '\'' : '(') ;
- for (int ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << (scalar ? " " : ", ") ;
- if (! scalar) cout << '\'' ;
- escape_value(array[ndx]);
- if (! scalar) cout << '\'' ;
- }
- cout << (scalar ? '\'' : ')') ;
- cout << ";" << endl ;
- }
-
- void
- PerlShell::escape_value(const char * value) const
- {
- for ( ; *value ; value++) {
- switch (*value) {
- case '\t' : cout << "\\t" ; break ;
- case '\n' : cout << "\\n" ; break ;
- case '\b' : cout << "\\b" ; break ;
- case '\r' : cout << "\\r" ; break ;
- case '\v' : cout << "\\v" ; break ;
- case '\f' : cout << "\\f" ; break ;
-
- case '\'' :
- case '\\' :
- cout << "\\" ; // fall thru to default
- default :
- cout << char(*value) ;
- }
- } //for
- }
-
- //------------------------------------------------------------------- TclShell
-
- const char * TclShell::NAME = "tcl" ;
-
- TclShell::TclShell(void)
- {
- static const char tcl_true[] = "1" ;
- static const char tcl_false[] = "0" ;
-
- // use different defaults for TRUE and FALSE
- ShellCmdArgBool::True(tcl_true);
- ShellCmdArgBool::False(tcl_false);
- }
-
- TclShell::~TclShell(void)
- {
- }
-
- const char *
- TclShell::name(void) const
- {
- return TclShell::NAME ;
- }
-
- void
- TclShell::unset_args(const char * name) const
- {
- cout << "set " << varname(name, '$') << " {};" << endl ;
- }
-
- int
- TclShell::is_positionals(const char * name) const
- {
- name = varname(name, '$');
- return ((::strcmp(name, "argv") == 0) || (::strcmp(name, "args") == 0));
- }
-
- void
- TclShell::set(const ShellVariable & variable) const
- {
- const char * name = varname(variable.name(), '$');
- cout << "set " << name << ' ' ;
- cout << '"' ;
- escape_value(variable.value());
- cout << '"' ;
- cout << ';' << endl ;;
- }
-
- void
- TclShell::set(const ShellArray & array, int ) const
- {
- const char * name = varname(array.name(), '@');
- int scalar = (*name == '$') ;
- cout << "set " << name << " [ list " ;
- for (int ndx = 0 ; ndx < array.count() ; ndx++) {
- if (ndx) cout << ' ' ;
- cout << '"' ;
- escape_value(array[ndx]);
- cout << '"' ;
- }
- cout << " ]" ;
- cout << ";" << endl ;
- }
-
- void
- TclShell::escape_value(const char * value) const
- {
- for ( ; *value ; value++) {
- switch (*value) {
- case '\t' : cout << "\\t" ; break ;
- case '\n' : cout << "\\n" ; break ;
- case '\b' : cout << "\\b" ; break ;
- case '\r' : cout << "\\r" ; break ;
- case '\v' : cout << "\\v" ; break ;
- case '\f' : cout << "\\f" ; break ;
-
- case '\'' :
- case '\\' :
- case '{' :
- case '}' :
- case '[' :
- case ']' :
- case '$' :
- case ';' :
- case '"' :
- cout << "\\" ; // fall thru to default
- default :
- cout << char(*value) ;
- }
- } //for
- }
-
-