# BASH shell routines to add Forth-like functionality to the shell # this file matches the documentation of version 32 # http://www.osdata.com/programming/shell/unixbook.pdf # most recent version of these routines is at # http://www.osdata.com/programming/shell/forthfunctions # note that not every revision of the PDF has changes in # the documentation for this file and its contents # variables export DataStackPointer=0 declare -a DataStack; export DataStack export ReturnStackPointer=0 declare -a ReturnStack; export ReturnStack # functions ShowDataStack () { echo "stack size of " $DataStackPointer; if [ "$DataStackPointer" -gt "0" ] ; then loopcounter=$DataStackPointer while [ $loopcounter -gt 0 ] ; do echo ${DataStack["$loopcounter"]} let "loopcounter=$loopcounter - 1" done else echo "the stack is empty" fi unset loopcounter #clear out variable } # end ShowDataStack push () { let "DataStackPointer=$DataStackPointer + 1" #preincrement DataStack["$DataStackPointer"]=$1 #push data item on top of stack } # end push pop () { let "DataStackPointer=$DataStackPointer - 1" #postdecrement } # end pop popout () { printf ${DataStack["$DataStackPointer"]} #pop data item from top of stack and print let "DataStackPointer=$DataStackPointer - 1" #postdecrement } # end popout dot () { echo ${DataStack["$DataStackPointer"]} #pop data item from top of stack and print let "DataStackPointer=$DataStackPointer - 1" #postdecrement } # end dot DUP () { temporary=${DataStack["$DataStackPointer"]} #make temporary copy of data item from top of stack let "DataStackPointer=$DataStackPointer + 1" #preincrement DataStack["$DataStackPointer"]=$temporary #store duplicate unset temporary #clear out variable } # end DUP qDUP () { if [ ${DataStack["$DataStackPointer"]} -eq 0 ] ; then #test for zero string on top of stack return 0 #if zero, take no action, return OK fi temporary=${DataStack["$DataStackPointer"]} #make temporary copy of data item from top of stack let "DataStackPointer=$DataStackPointer + 1" #preincrement DataStack["$DataStackPointer"]=$temporary #store duplicate unset temporary #clear out variable } # end qDUP OVER () { let "TemporaryPointer=$DataStackPointer - 1" #create pointer down one from top of stack temporary=${DataStack["$TemporaryPointer"]} #make temporary copy of data item one down in stack let "DataStackPointer=$DataStackPointer + 1" #preincrement DataStack["$DataStackPointer"]=$temporary #store duplicate unset temporary #clear out variable unset TemporaryPointer #clear out variable } # end OVER PICK () { let "TemporaryPointer=$DataStackPointer - $1" #create pointer down one from top of stack temporary=${DataStack["$TemporaryPointer"]} #make temporary copy of data item one down in stack let "DataStackPointer=$DataStackPointer + 1" #preincrement DataStack["$DataStackPointer"]=$temporary #store duplicate unset temporary #clear out variable unset TemporaryPointer #clear out variable } # end PICK DROP () { let "DataStackPointer=$DataStackPointer - 1" #postdecrement } # end DROP SWAP () { let "TemporaryPointer=$DataStackPointer - 1" #create pointer down one from top of stack temporary=${DataStack["$TemporaryPointer"]} #make temporary copy of data item one down in stack DataStack["$TemporaryPointer"]=${DataStack["$DataStackPointer"]} #move the top item to 2nd location down DataStack["$DataStackPointer"]=$temporary #put former 2nd down on top of stack unset temporary #clear out variable unset TemporaryPointer #clear out variable } # end SWAP ROT () { let "TemporaryPointer=$DataStackPointer - 2" #create pointer down two from top of stack let "SecondPointer=$DataStackPointer - 1" #create pointer down one from top of stack temporary=${DataStack["$TemporaryPointer"]} #make temporary copy of data item one down in stack DataStack["$TemporaryPointer"]=${DataStack["$SecondPointer"]} #move the 2nd down item to 3rd location down DataStack["$SecondPointer"]=${DataStack["$DataStackPointer"]} #move the top item to 2nd location down DataStack["$DataStackPointer"]=$temporary #put former 3rd down on top of stack unset temporary #clear out variable unset TemporaryPointer #clear out variable unset SecondPointer #clear out variable } # end ROT ROLL () { if [ $DataStackPointer -gt "$1" ] ; then #check to make sure enough items on stack let "DestinationPointer=$DataStackPointer - $1" SavedItem=${DataStack["$DestinationPointer"]} #save old item let "SourcePointer =$DestinationPointer + 1" LoopCounter=$1 while [ $LoopCounter -gt 0 ] ; #move data loop do DataStack["$DestinationPointer"]=${DataStack["$SourcePointer"]} #move data let "DestinationPointer=$DestinationPointer + 1" #post increment let "SourcePointer=$SourcePointer + 1" #post increment let "LoopCounter=$LoopCounter - 1" done DataStack["$DataStackPointer"]=$SavedItem unset LoopCounter #clear out variable unset SavedItem #clear out variable unset SourcePointer #clear out variable unset DestinationPointer #clear out variable fi # end if good input } # end ROLL DEPTH () { temporary=$DataStackPointer #save the existing depth of the stack let "DataStackPointer=$DataStackPointer + 1" #preincrement DataStack["$DataStackPointer"]=$temporary #push depth on top of stack } # end DEPTH