#!/bin/sh
######################################
##### Model Transformation Tools #####
######################################
# Bourne shell script: mtt_header
# Headings for functions
# Copyright (C) 2000 by Peter J. Gawthrop
###############################################################
## Version control history
###############################################################
## $Id$
## $Log$
## Revision 1.28 2001/02/17 03:48:17 geraint
## Use assignment LHS to gather tmp variable names.
## Prevents collection of long expressions, eg: tmp34*(tmp75
##
## Revision 1.27 2001/02/14 06:06:34 geraint
## Removed octave_value_list wrappers from standalone.exe - speed improvements
##
## Revision 1.26 2001/02/05 08:50:58 geraint
## Octave 2.1.x compatability.
##
## Revision 1.28 2001/01/17 21:16:15 geraint
## uncomment parameter assignments in .m reps
##
## Revision 1.27 2001/01/14 23:51:26 geraint
## declare parameters as variables instead of constants
##
## Revision 1.26 2001/01/07 21:22:47 geraint
## Compatibility with Octave 2.1.x
## vector_value ---> column_vector_value
##
## Revision 1.25 2000/12/05 12:05:26 peterg
## Changed to () form
##
## Revision 1.24 2000/12/05 10:04:52 peterg
## Fixed dummy variable bug
##
## Revision 1.23 2000/12/05 09:47:50 peterg
## Include crs as c files
##
## Revision 1.22 2000/12/04 12:19:12 peterg
## Changed $() to `` and $() to expr for sh compatibility -- geraint
##
## Revision 1.21 2000/12/04 08:52:40 peterg
## Zapped () in functions for sh compatibility
##
## Revision 1.20 2000/12/04 08:19:27 peterg
## Added switch declarations - in logic.cc
##
## Revision 1.19 2000/12/03 16:11:43 peterg
## Corrected bug in logic declatations
##
## Revision 1.18 2000/12/03 16:06:22 peterg
## Fixed bug in generating dummies
## Added logic declarations
##
## Revision 1.17 2000/12/01 20:55:01 peterg
## Added Geraint's fix for zeroing matrices
##
## Revision 1.16 2000/12/01 17:56:30 peterg
## Removed spurious echo '## Set matrices to zero' - thanks Geraint
##
## Revision 1.15 2000/11/29 21:06:16 peterg
## Removed Npar creation - not needed??
##
## Revision 1.14 2000/11/27 11:51:43 peterg
## Added zero matrices in matlab code
##
## Revision 1.13 2000/11/09 17:19:52 peterg
## Geraint's pow() mods
##
## Revision 1.12 2000/11/09 16:09:46 peterg
## Declare dummy variables (mtt_s1 etc)
##
## Revision 1.11 2000/11/09 15:29:35 peterg
## lower-case declarations
##
## Revision 1.10 2000/11/07 17:20:51 peterg
## useful-functions.hh now included locally
##
## Revision 1.9 2000/11/07 16:56:24 peterg
## Version from Geraint
##
## Revision 1.2 2000/11/03 00:55:42 geraint
## typo: missed out 'd' in mttedx
## todo: need to accommodate mttsimpar
##
## Revision 1.1 2000/11/02 04:28:39 geraint
## Initial revision
##
## Revision 1.8 2000/10/17 16:35:03 peterg
## No parameter,state or input conversion in txt files
##
## Revision 1.7 2000/10/17 09:53:20 peterg
## Fixed logic rep
##
## Revision 1.6 2000/10/17 08:37:23 peterg
## Included logic rep
##
## Revision 1.5 2000/10/14 09:12:14 peterg
## No dies arguments and output itself
##
## Revision 1.4 2000/10/14 06:49:31 peterg
## Make parameter listing representation dependent
##
## Revision 1.3 2000/10/11 08:59:15 peterg
## Added csex rep
##
## Revision 1.2 2000/10/11 08:01:42 peterg
## Added noglobal fudge
##
## Revision 1.1 2000/10/10 21:02:27 peterg
## Initial revision
##
###############################################################
# Arguments
system=$1
rep=$2
language=$3
fun_name=${1}_${2}
#args=$4
#output=$5
#extras=$6
# Find system constants
Nx=`mtt_getsize $system x` # States
Nxx=`mtt_getsize $system xx` # States x States
Nu=`mtt_getsize $system u` # Inputs
Ny=`mtt_getsize $system y` # Outputs
Nyz=`mtt_getsize $system yz` # Zero outputs
##Npar=`wc -l $system\_sympar.txt | awk '{print $1}'`
# get octave version
octave_development=`octave --version | awk '{print $4}' | awk -F\. '{print $2}'`
case `$MATRIX --version | awk -F\. '{print $2}'` in
0) # stable
vector_value=vector_value
;;
1) # development
vector_value=column_vector_value
;;
*)
vector_value=column_vector_value
;;
esac
# Representation-specific stuff
eqnargs='mttx,mttu,mttt,mttpar'
inputeqnargs='mttx,mtty,mttt,mttpar'
case $rep in
cse)
states=yes;
inputs=yes;
parameters=yes;
output='mttdx,mtte'
args=$eqnargs
;;
csex)
states=yes;
inputs=yes;
parameters=yes;
output=mttedx
args=$eqnargs
;;
cseo)
states=yes;
inputs=yes;
parameters=yes;
output=mtty
args=$eqnargs
;;
dm)
states=no;
inputs=no;
parameters=yes;
output='mtta,mttb,mttc,mttd,mtte'
args=mttpar
zeromatrices='a b c d e';
;;
input)
states=yes;
inputs=no;
parameters=yes;
output=mttu
args=$inputeqnargs
declareinputs=yes
;;
logic)
states=no;
inputs=no;
parameters=yes;
output=mttopen
args=$eqnargs
declareinputs=yes
declarestates=yes
declareswitches=yes
;;
numpar)
states=no;
inputs=no;
parameters=no;
output='mttpar'
;;
ode)
states=yes;
inputs=yes;
parameters=yes;
output='mttdx'
args=$eqnargs
;;
odeo)
states=yes;
inputs=yes;
parameters=yes;
output='mtty'
args=$eqnargs
;;
ode2odes)
states=no;
inputs=no;
parameters=no;
output='y,x,t'
args='x,par,simpar'
;;
simpar)
states=no;
inputs=no;
parameters=no;
output='mttsimpar'
;;
sm)
states=no;
inputs=no;
parameters=yes;
output='mtta,mttb,mttc,mttd'
args=mttpar;
zeromatrices='a b c d';
;;
smxa)
states=no;
inputs=no;
parameters=yes;
output='mtta'
args=$eqnargs
;;
smxax)
states=no;
inputs=no;
parameters=yes;
output='mttax'
args=$eqnargs
;;
state)
states=no;
inputs=no;
parameters=yes;
output=mttx
args=mttpar
declarestates=yes
;;
*)
echo Representation $rep not supported - sorry; exit 1
esac
## Sort out parentheses
if [ -n "$args" ]; then
Args='('$args')'
fi
if [ -n "$output" ]; then
Output="[$output] = "
fi
# Lanuage specific stuff
case $language in
m)
Lc='##';
Rc='';
Lb='(';
Rb=')';
function="function"
declaration="$Output$1_$rep$Args;"
noglobals=true; # Fudge to make mtt_m2p work
start='## BEGIN Code'
finish='## END Code'
var_declaration=
declarestates=no
declareinputs=no
declareswitches=no
;;
txt)
modeline='## -*-octave-*- Put Emacs into octave-mode ##';
Lc='##';
Rc='';
Lb='(';
Rb=')';
function=""
declaration=""
start=''
parameters=no
states=no
inputs=no
declarestates=no
declareinputs=no
declareswitches=no
;;
oct)
modeline="// -*-c++-*- Put Emacs into c++-mode";
Lc='//';
oct_header=yes;
constant_declaration="const double "
var_declaration="double "
minusone="-1"
map="_map"
declaredummies=yes
;;
*)
echo Language $language not supported - sorry; exit 1
esac
if [ "$rep" = "simpar" ]; then
output=${output}${map} # Output is simpar_map in this case
fi
zero_matrices()
{
## Set matrices to zero
echo
## echo '## Set matrices to zero'
for name in $zeromatrices; do
case $name in
a)
N=$Nx; M=$Nx
;;
b)
N=$Nx; M=$Nu
;;
c)
N=$Ny; M=$Nx
;;
d)
N=$Ny; M=$Nu
;;
e)
N=$Nx; M=$Nx
;;
*)
esac
echo " mtt$name = zeros($N,$M);"
done
}
declare_dummies()
{
# Get the dummies
dummies="mtt_tmp"
rm -f mtt_dummies
for dummy in $dummies; do
grep "${dummy}[0-9]*[ \t\n]*=" < ${fun_name}.m |\
awk '{
if (match($1,dummy)==1)
print $1
}' dummy=$dummy >> mtt_dummies
done
dummy_list=`sort -u mtt_dummies`
# Comments
cat <<EOF
$Lc Declarations of dummies $Rc
EOF
for dummy in $dummy_list; do
echo ' ' $var_declaration $dummy';'
done
} # declare_dummies
declare_switches ()
{
cat <<EOF
$Lc Declarations of switches $Rc
EOF
strip_comments <${system}_switch.txt |\
awk '{printf(" double %s_logic = 0;\n", tolower($1))}'
} # declare_switches
declare_vars()
{
# Grab the names
names=`awk '{if ($1==var_type) print tolower($4)}' var_type=$1 ${system}_struc.txt`
# Comments
cat <<EOF
$Lc Declarations for $1 names $Rc
EOF
# Declarations
for name in $names; do
echo ' '$var_declaration $name';'
done
}
array2constant()
{
# Parameters
if [ "$parameters" = "yes" ]; then
cat <<EOF
$Lc Parameters $Rc
EOF
sympar2par_txt2m ${system} "" "$var_declaration" "$minusone"
fi
# States
if [ "$states" = "yes" ]; then
cat <<EOF
$Lc States $Rc
EOF
N=`n2m 1 $Nx`
for i in $N; do
echo $constant_declaration 'mttx'$i' = mttx('$i$minusone');'
done
fi
if [ "$declarestates" = "yes" ]; then
declare_vars state
fi
# Inputs
if [ "$inputs" = "yes" ]; then
cat <<EOF
$Lc Inputs $Rc
EOF
N=`n2m 1 $Nu`
for i in $N; do
echo $constant_declaration 'mttu'$i' = mttu('$i$minusone');'
done
fi
if [ "$declareinputs" = "yes" ]; then
declare_vars input
fi
if [ "$declaredummies" = "yes" ]; then
declare_dummies
fi
if [ "$declareswitches" = "yes" ]; then
declare_switches
fi
zero_matrices;
}
# Argument specific stuff
get_arg_specific_stuff ()
{
arg_name=${1:-""}
case ${arg_name} in
mtta | mtte)
arg_type="Matrix"
arg_size="(MTTNX,MTTNX)"
;;
mttb)
arg_type="Matrix"
arg_size="(MTTNX,MTTNU)"
;;
mttc)
arg_type="Matrix"
arg_size="(MTTNY,MTTNX)"
;;
mttd)
arg_type="Matrix"
arg_size="(MTTNY,MTTNU)"
;;
mttax | mttdx | mttedx | mttx | mttopen)
arg_type="ColumnVector"
arg_size="(MTTNX)"
;;
mttpar)
arg_type="ColumnVector"
arg_size="(MTTNPAR)"
;;
mttsimpar_map)
arg_type="Octave_map"
arg_size="";
;;
mttu)
arg_type="ColumnVector"
arg_size="(MTTNU)"
;;
mtty)
arg_type="ColumnVector"
arg_size="(MTTNY)"
;;
mttt)
arg_type="const double"
arg_size=""
;;
nil)
arg_type="void *"
arg_size="(0x0)"
;;
*)
echo "Argument ${arg} not supported - sorry"; exit 1
esac
}
get_field ()
{ # parse comma separated string
s=${1:-""} # comma separated string
i=${2:-0} # field number in string
if [ 0 -eq ${i} ]; then # return number of fields
echo ${s} |\
awk -F\, '{ print NF }'
else # return ith field
echo ${s} |\
awk -F\, -v i=${i} '{ print $i }'
fi
}
get_extra_fields ()
{ # return list of words in s2 and not in s1
s1=${1:-""} # comma separated list
s2=${2:-""} # comma separated list
c1=`get_field ${s1} 0` # count words in s1
c2=`get_field ${s2} 0` # count words in s2
ans=""
i2=0 # s2 word index
while [ ${i2} -lt ${c2} ]; do
flag=0 # appearance of word in s1 and s2?
i2=`expr ${i2} + 1`
w2=`get_field ${s2} ${i2}` # i2 th word in s2
i1=0 # s1 word index
while [ ${i1} -lt ${c1} ]; do
i1=`expr ${i1} + 1`
w1=`get_field ${s1} ${i1}` # i1 th word in s1
if [ ${w2} = ${w1} ]; then
flag=1 # w2 occurs in s1
fi
done
if [ ${flag} -eq 0 ]; then # w2 is not in s1?
if [ -z ${ans:-""} ]; then # string is empty?
ans=${w2} # assign w2
else
ans=${ans},${w2} # append w2
fi
fi
done
echo ${ans}
}
write_DLD_header()
{
cat <<EOF
#ifndef STANDALONE
#include <octave/oct.h>
#include <octave/ov-struct.h>
#include <octave/toplev.h>
#include <math.h>
#include "useful-functions.hh"
#include "${system}_cr.h"
#include "${system}_def.h"
#include "${system}_sympar.h"
DEFUN_DLD (${system}_${rep}, args, ,
"Usage: [$output] = ${system}_${rep}($args)
Octave ${rep} representation of system ${system}
Generated by MTT on `date`")
{
octave_value_list retval;
#endif // ! STANDALONE
EOF
}
map_DLD_inputs ()
{
s=${1:-""} # comma separated input list
if [ -z ${s:-""} ];then return; fi
printf "#ifndef STANDALONE\n"
c=`get_field ${s} 0` # count of inputs
i=0
printf " if (${c} != args.length ()) usage (\"${fun_name} expected ${c} argument(s): ${s}\");\n\n"
while [ ${i} -lt ${c} ]; do
j=${i}
i=`expr ${i} + 1`
w=`get_field ${s} ${i}` # argument name
get_arg_specific_stuff ${w}
case ${arg_type} in
"const double")
printf " ${arg_type}\t${w}\t= args(${j}).double_value ();\n"
;;
ColumnVector | Matrix | *)
printf " ${arg_type}\t${w}\t= args(${j}).%s ();\n" ${vector_value}
;;
esac
done
printf "#endif // ! STANDALONE\n\n"
}
declare_DLD_outputs ()
{
s=${1:-""} # comma separated output list
c=`get_field ${s} 0` # count of outputs
i=0
while [ ${i} -lt ${c} ]; do
i=`expr ${i} + 1`
w=`get_field ${s} ${i}` # argument name
get_arg_specific_stuff ${w}
printf " ${arg_type}\t${w}\t${arg_size};\n"
done
}
return_DLD_outputs ()
{
s=${1:-""} # comma separated output list
c=`get_field ${s} 0` # count of outputs
i=0
cat <<EOF
\/\/ END Code
#ifndef STANDALONE
EOF
while [ ${i} -lt ${c} ]; do
j=${i}
i=`expr ${i} + 1`
w=`get_field ${s} ${i}`
printf " retval (${j})\t= octave_value (${w});\n"
done
cat <<EOF
return (retval);
}
#endif // ! STANDALONE
EOF
}
write_standalone_header ()
{
get_arg_specific_stuff ${output}
cat <<EOF
#ifdef STANDALONE
#include <octave/oct.h>
#include <octave/ov-struct.h>
#include "useful-functions.hh"
#include "${system}_cr.h"
#include "${system}_def.h"
#include "${system}_sympar.h"
${arg_type} F${system}_${rep} (
EOF
if [ -z ${args:-""} ]; then
printf "\tvoid"
else
c=`get_field ${args:-""} 0`
i=0
while [ ${i} -lt ${c} ]; do
i=`expr ${i} + 1`
if [ ${i} -lt ${c} ]; then
comma=","
else
comma=""
fi
w=`get_field ${args} ${i}`
get_arg_specific_stuff ${w}
printf "\t${arg_type}\t&${w}${comma}\n"
done
fi
cat <<EOF
)
{
#endif // STANDALONE
EOF
}
return_standalone_output ()
{
cat <<EOF
#ifdef STANDALONE
return ${output};
}
#endif // STANDALONE
EOF
}
# Header information
cat<<EOF
$modeline
$function $declaration
$Lc $declaration
$Lc System $system, representation $rep, language $language; $Rc
$Lc File $1_$rep.$language; $Rc
$Lc Generated by MTT on `date`; $Rc
EOF
if [ ${language} = "oct" ];then
write_standalone_header
write_DLD_header
map_DLD_inputs ${args}
undeclared=`get_extra_fields ${args:-"nil"} ${output:-"nil"}`
declare_DLD_outputs ${undeclared}
array2constant
case ${arg_type} in
Matrix)
printf " ${w}\t\t\t= zeros ${arg_size};\n"
;;
*)
;;
esac
cat <<EOF
// BEGIN Code
EOF
return_DLD_outputs ${output}
return_standalone_output
else
if [ -n "$noglobals" ]; then
cat<<EOF
## Horrible fudge to make mtt_m2p work
global ...
mtt_no_globals ;
EOF
fi
## Arrays
array2constant
# Mark start of code
echo
echo $start
fi