{ |one, step, back| }

The Shape Example in Shell Script

Contributed by Monty Stein

Code for Shell Script

File: shapes.sh

#!/usr/bin/bash

##  Example of OO inheritance in shell, now let us never speak of it again
##   - Monty Stein  Aug 3, 1998

# Function (and data) table handlers.  Stores everything similarly to the
# way Python will print out a dictionary:  key1:value1,key2:value2,...

# dump it in a format much like a flat file DB
function functbldump {
  echo "$1"|tr , "\012"
}

# recover from flat file DB and put back into string
function functblundump {
  (tr "\012" , <$1;echo )|sed 's/,,*/,/g'
}

# add a key:value pair to the string
function functbladd {
  functbldump "$1" >/tmp/temp$$
  echo "$2:$3" >>/tmp/temp$$
  functblundump /tmp/temp$$
  rm -f /tmp/temp$$
}

# get a value for a key.  Note: the last named key overrides
function functblget {
  functbldump "$1" >/tmp/temp$$
  T=`egrep "^$2:" /tmp/temp$$|tail -1|cut -d: -f2`
  if [ -z "$T" ]
  then
    echo "WARN: cannot get key $2 from function table:\n$1" 1>&2
  fi
  echo "$T"
  rm -f /tmp/temp$$
}


##########

function Shape {
  T=""
  T=`functbladd "$T" x $1`
  T=`functbladd "$T" y $2`
  T=`functbladd "$T" set_x Shape_set_x`
  T=`functbladd "$T" set_y Shape_set_y`
  T=`functbladd "$T" relative_move Shape_relative_move`
  T=`functbladd "$T" draw Shape_draw`
  echo "$T"
}

function Shape_set_x {
  echo `functbladd "$1" x $2`
}

function Shape_set_y {
  echo `functbladd "$1" y $2`
}

function Shape_relative_move {
  T="$1"
  X=`functblget "$T" x`
  Y=`functblget "$T" y`
  X=`expr "$X" + $2`
  Y=`expr "$Y" + $3`
  T=`functbladd "$T" x $X`
  T=`functbladd "$T" y $Y`
  echo "$T"
}

function Shape_draw {
  echo "default Shape draw" 1>&2
  echo "$1"
}


  
###########

function Rectangle {
  T=`Shape $1 $2`
  T=`functbladd "$T" width $3`
  T=`functbladd "$T" height $4`
  T=`functbladd "$T" set_width Rectangle_set_width`
  T=`functbladd "$T" set_height Rectangle_set_height`
  T=`functbladd "$T" draw Rectangle_draw`
  echo "$T"
}

function Rectangle_set_width {
  echo `functbladd "$1" width $2`
}

function Rectangle_set_height {
  echo `functbladd "$1" height $2`
}

function Rectangle_draw {
  X=`functblget "$1" x`
  Y=`functblget "$1" y`
  WIDTH=`functblget "$1" width`
  HEIGHT=`functblget "$1" height`
  echo "drawing rectangle ($X,$Y) with width $WIDTH, height $HEIGHT" 1>&2
  echo "$1"
}



###########

function Circle {
  T=`Shape $1 $2`
  T=`functbladd "$T" radius $3`
  T=`functbladd "$T" set_radius Circle_set_radius`
  T=`functbladd "$T" draw Circle_draw`
  echo "$T"
}

function Circle_set_radius {
  echo `functbladd "$1" radius $2`
}

function Circle_draw {
  X=`functblget "$1" x`
  Y=`functblget "$1" y`
  RADIUS=`functblget "$1" radius`
  echo "drawing circle ($X,$Y) with radius $RADIUS" 1>&2
  echo "$1"
}



############

function DoSomethingWithShape {
  T="$1"
  T=`eval \`functblget "$T" draw\` "$T"`
  T=`eval \`functblget "$T" relative_move\` "$T" 100 100`
  T=`eval \`functblget "$T" draw\` "$T"`
  echo "$T"
}




###################################################
# using shapes polymorphically
export SHAPES_0=`Rectangle 10 20 5 6`
export SHAPES_1=`Circle 15 25 8`

for i in 0 1
do
  #the export tricks the shell into loading into a shell variabled name
  #the env call does much the same, but extracts
  export SHAPES_$i="`DoSomethingWithShape \`env|egrep "^SHAPES_$i="|sed 's/^.*=//g'\``"
done

# access a rectangle specific function
export RECT=`Rectangle 0 0 15 15`
RECT=`eval \`functblget "$RECT" set_width\` "$RECT" 30`
RECT=`eval \`functblget "$RECT" draw\` "$RECT"`

Output

drawing rectangle (10,20) with width 5, height 6
drawing rectangle (110,120) with width 5, height 6
drawing circle (15,25) with radius 8
drawing circle (115,125) with radius 8
drawing rectangle (0,0) with width 30, height 15