Object Oriented Shell

Bill Birch bill at ibmpcug.co.uk
Wed Jan 30 04:33:15 AEST 1991


		Bill Birch's Object-Oriented Shell (oosh)

			2 November 1990




CONTENTS

	1	Introduction
	2	Classes and File Structure
	3	Execution of Methods
	4	Special Methods

		4.1	Defining a Class with "defclass"
		4.2	Defining a Method with "defmethod"
	
	5	Compound Classes
	6	On Replacing "make" with an OO Shell
	7	Conclusions
	










1	Introduction

	This shell is an experiment in application of object-oriented
	ideas to the UNIX environment. It is a shell which allows the user 
	to define what commands are appropriate for a particular kind of file.
	
	When using the standard shells, users are expected to remember exactly
	which command program to run to for a particular file type. For example
	to print a 'C' source program you must type:
	
		$ pr -e5 -n foobar.c | lpr

	whereas to print a document you need to type:

		$ nroff -mm foobar.mm | qprt -q3
	
	two entirely different strings for the same desired result!

	"oosh" uses the suffix of filenames to key into a class tree
	which defines the behaviour for all the defined objects. In the above 
	example, you type the same in both cases:

		$ print foobar.c
		$ print foobar.mm

	I have taken the view that the basic object should be a file in
	this environment. The UNIX operating system does not provide support 
	for OO, thus a file cannot have properties or methods attached to it
	unless they are in the file itself, (except the obvious ones). 

	Therefore, an individual file can only inherit the methods of its 
	class, and cannot have its own unique methods. However, there is 
	nothing to prevent classes of objects being defined that are 
	directories. These "compound" objects can contain methods 
	and properties as sub-files.
	
	The experimental nature of this prototype has meant an implementation
	in Bourne shell. Obviously a compiled version would execute faster,
	but would require more programming effort.  

	The rest of this document introduces the "how it works" of oosh.
	It is not a user manual, but a note to fellow programmers. 
	

2	Classes and File Structure

2.1	Classes and Suffixes

	In this system, files are objects. All files must have a suffix
	as in "/tmp/foo.txt" which has a suffix of "txt". The suffix
	denotes the class of the file.  All the private data of the file
	is stored in the file itself. Objects have no other data (unless
	it is a compound object which is a directory). 

	For every defined class there is an entry in the "oosh/classes"
	directory. These entries are soft links (ln -s) to the correct
	directory in the class tree. Thus the suffix of a file indirectly 
	points into the class tree.

2.2	The Class Tree

	The class tree consists of a tree of Unix directories, with the
	root being "oosh/top". Each directory represents a class, hence its
	super-class is the directory "..", and each subclass is a directory 
	entry. For Example here is a partial "ls -R" of my class tree:

		 oosh/top:
		 methods
		 file			# file is a class of objects

		 oosh/top/file:
		 ascii			# ascii is a type of file
		 bin			# bin is a type of file

		 oosh/top/file/ascii:
		 methods
		 c			# c is a type of ascii file
		 ml			# ml is a type of ascii file
		 txt			# txt is a type of ascii file

		 oosh/top/file/ascii/c:
		 methods

		 oosh/top/file/ascii/c/methods:
		 open
		 pg

		 oosh/top/file/ascii/methods:
		 open

		 oosh/top/methods:
		 copy
		 cut
		 open
		 pg
		 print
		 defclass
		 defmethod

	Each class directory can contain a subdirectory called "methods" which
	contains executable files for operating on objects of that class. The
	"top" directory's method directory contains all the default methods
	for all objects eg:

		 copy
		 cut
		 open
		 pg
		 print

	Executable files in a methods directory take the object name
	as it's first parameter.

3	Execution of Methods

	The execution of a method on an object first involves discovering
	the class of that object. Then the class tree is searched to find
	a method file to execute. The execution proceeds as follows:

	1	Extract the suffix of the file object.
	2	Find the soft link in "oosh/classes" which points to the
		correct place in the class tree.
	3	Change directory to the class's directory in the tree.
	4	Look to see if the method required is in the "methods" directory
		of this class.
	5	IF it is present, THEN
		execute the method file, passing the object as a parameter.
	      ELSE
		change to the super class ie "cd .."
		UNLESS we are in "top" in which case the method is unknown
			so just execute it in the normal UNIX shell.
		REPEAT from Step 4
	
	The actual code consists of two Bourne shell programs: "dispatch.sh" 
	covers steps 1 thru 3 and another, "tryit.sh" which executes steps 
	4 & 5 and is called recursively. The source code is listed in 
	appendix A.

	In order to provide the user with the familiar "command object"	
	command line syntax, every defined method is implemented by
	a softlink between a file in "oosh/bin" and "dispatch.sh". 
	For example here is a partial "ls -l" of "oosh/bin":

		lrwxrwxrwx   copy -> dispatch.sh
		lrwxrwxrwx   defclass -> dispatch.sh
		-rwxr--r--   dispatch.sh
		lrwxrwxrwx   open -> dispatch.sh
		lrwxrwxrwx   pg -> dispatch.sh
		lrwxrwxrwx   print -> dispatch.sh

	"dispatch.sh" uses its invoked name as the method specifier. eg

		$ open foo.txt

	actually executes "dispatch.sh" with $0 set to "open"



4	Special Methods

4.1	Defining a Class with "defclass"

	Syntax:
		$ defclass <super> <class>

	The method "defclass", which is supplied in oosh/top/methods
	is supplied with the name of a superclass and the name of the class
	to be defined. ie
	
		$ defclass .bin o

	defines "o" to be a subclass of "bin".

	It performs the following operations :

	1	Create a directory called <class> in the <superclass>'s
		directory.

	2	Create a directory called "methods" in <class>'s own
		directory.

	3	Create a softlink (ln -s) in "oosh/classes" to the
		<class>'s directory in the class tree.




4.2	Defining a Method with "defmethod"

	Syntax:
	
		$ defmethod <method name> <class> <executable>

	To add a new method to a class requires the following steps
	to be executed:

	1	Create a softlink in "oosh/bin" between <method name>
		and "dispatch.sh". This creates a synonym for the new method
		which when invoked from the shell actually calls "dispatch.sh".

	2	Copy the <executable> file into the class's "methods"
		directory in the class tree.

	Example:
	
		$ defmethod .pg exe /usr/bin/nm




5	Compound Objects

	In order to provide methods for objects on an individual basis
	each object must have a way of storing it's private methods.
	One approach is to create a class of objects which consist
	of more than one file, all contained within a single directory.

	The directory may contain many data and executable files private
	to the object.  To illustrate this here is a simple example of
	a comound class called "cmp". The "cmp" methods are relatively
	simple, and are all identical (softlinks can be used):

	An example object "tst.cmp" consists of the following files:

		./tst.cmp:
		methods
		slots
		
		./tst.cmp/methods:
		pg
		
		./tst.cmp/slots:
		f1
		f2
		f3
		f4

	The "methods" directory contains various executable files, and
	the "slots" directory contains data files.

	The execution of a method, simply requires that the method
	be available WITHIN the object itself to be executed. ie:

		#!/bin/bsh
		method=`basename $0`
		object=$1
		cd $object
		if test -x $object/methods/$method
		then
			$object/methods/$method $object
		fi

	Note that this behaviour requires no modification to the 
	rest of "oosh", and affects only objects of the "cmp" class.




6	On Replacing "make" with an OO Shell

	Probably the most useful tool for programmers is "make". 
	"make" has implicit rules that define the behaviour for all
	files with a given suffix. In OO terms this is the same as 
	defining methods that are applicable for all members of a class.

	To provide similar functions with an Object-Oriented Shell is
	easy. For example to compile a 'C' program with oosh you 
	could type:
	
		$ build fubar.o

	The method "build" for ".o" files would then execute the following
	just like "make" does:

	1	Look around for a dependancy file called fubar.c.
		IF it exists THEN
			"build fubar.c" in case it needs it.
		
	2	IF fubar.o exists AND fubar.c exists AND 
			fubar.c is younger than fubar.o
		THEN
			Compile fubar.c
		ELSE
			do nothing: "fubar.o is up to date"


	But what about further dependancies such as #include files?
	"make" handles this by parsing a Makefile script which lists
	all the dependancies. In OO terms the dependancy list of a target
	is a property of the object. So too are the command lines required
	to re-build the object. They constitute that object's individual
	"build" method.

	For example, to build executable programs with oosh, each 
	".exe" will need its dependancy list, and a command sequence 
	to link or compile the components together. This could be 
	implemented by the following scheme:

	*	Each buildable object consists of a compound object
		having its own directory.

	*	The component objects are listed in a file "./depends"

	*	The command script required to build the object
		is in the object's "./methods/build_after" method file.

	*	The method for this class of object first executes
		the "build" method for all the components in "./depends",
		IF any of the components are younger than the target object 
		THEN
			the object's own "build_after" method is invoked.

	In practice "make" programmers almost always use one directory
	per executable, so this approach is familiar. Keeping the
	source and build files of an library or program together
	in one directory is common. Are the source files that make
	up a program also to be viewed as private objects of that
	program?

	
7	CONCLUSIONS

	This prototype OO shell is exciting, but many practical problems
	remain to be addressed. For example, oosh needs to be 
	faster, thus a compiled implementation is indicated. Oosh is
	not efficient in its use of OS resources, requiring many files
	and directories to store objects.

	Also, oosh cannot handle lists of objects, it does not cope
	well with command line switches. Is it possible to devise
	command line switches that can be meaningful to a large
	number of classes?  Neither is there provision for methods that
	require more than one object of different classes.

	Despite these limitations in this simple prototype I feel that
	it shows that an Object Oriented shell is a helpful tool
	and fits naturally to the programming task. It also shows 
	that an OO Shell will eventually replace "make" and its ilk.
	



APPENDIX A	Source Code

A.1	"dispatch.sh"


    1	#!/bin/sh
    2	method=`basename $0`
    3	#
    4	object=`pwd`/$1
    5	base=`basename $object`
    6	suffix=`echo $object | sed -f /u/bill/oosh/bin/suffix.sed`
    7	echo method: $method object: $object suffix $suffix marg $marg
    8	if test -r /u/bill/oosh/classes/$suffix
    9	then
   10		cd /u/bill/oosh/classes/$suffix
   11	else
   12		cd /u/bill/oosh/classes/top
   13	fi
   14	cd `pwd`				# Adjust soft links
   15	/u/bill/oosh/bin/tryit.sh $method $object $suffix $args $marg

A.2	"tryit.sh"


    1	#!/bin/sh
    2	#				tryit.sh
    3	method=$1
    4	object=$2
    5	class=$3
    6	#
    7	#
    8	#
    9	if test `pwd` = /u/bill/oosh
   10	then
   11		echo cannot find method $method for $object
   12	else
   13	if test -x methods/$method
   14	then
   15		methods/$method $object
   16	else
   17		cd ..
   18		/u/bill/oosh/bin/tryit.sh $method $object $class $margs
   19	fi
   20	fi
   21	

A.3	"top/methods/defclass"


    1	#!/bin/sh
    2	object=$1
    3	super=$2
    4	class=`echo $3 | sed -f /u/bill/oosh/bin/suffix.sed`
    5	echo super $super class $class 4 $4
    6	if test -d /u/bill/oosh/classes/$super
    7	then
    8		cd /u/bill/oosh/classes/$super
    9		cd `pwd`
   10		if test -d $class
   11		then
   12			echo defclass: $class probably exists already
   13		else
   14			mkdir $class
   15			mkdir $class/methods
   16			ln -s `pwd`/$class /u/bill/oosh/classes/$class
   17		fi
   18	else
   19		echo defclass: $super does not exist
   20	fi

A.4	"top/methods/defmethod"


    1	#!/bin/bsh
    2	object=$1
    3	method=$2
    4	class=$3
    5	exec=$4
    6	echo defmethod: method $method class $class exec $exec
    7	if test ! -x /u/bill/oosh/bin/$method
    8	then
    9		ln -s /u/bill/oosh/bin/dispatch /u/bill/oosh/bin/$method
   10	fi
   11	if test -d /u/bill/oosh/classes/$class
   12	then
   13		cd /u/bill/oosh/classes/$class
   14		cd `pwd`
   15		if test -d ./methods
   16		then
   17			rm ./methods/$method
   18			cp $exec ./methods/$method
   19		else
   20			echo defmethod: missing methods directory in `pwd`
   21		fi
   22	else
   23		echo defmethod: Class $class does not exist
   24	fi

-- 
Automatic Disclaimer:
The views expressed above are those of the author alone and may not
represent the views of the IBM PC User Group.
-- 



More information about the Comp.unix.programmer mailing list