Next: 11. Solutions to the Exercises
Up: A Tutorial on the
Previous: 9. Debugging Macros
We conclude this tutorial with a list of recommendations which should help
to write robust and transportable macros that will perform well in different
applications, and --last but not least!-- will avoid unnecessary
problems when switching to new releases:
- When a macro is leaving a module, always use ``
quit
'' at the
level of the primary select. Do not use the explicit ``n=end
''
option, since this would require explicit modification if in a later release
new options are added to the module. - Do not assume that all users and all applications use the same switch
and module parameter settings as you do. Whenever possible, write macros
to be independent of particular switch or module parameter settings. Often
this can be done very easily by inserting conditionals which test the switch
setting directly (
~?i&...
) or that verify the presence of an optional
question (~?q...
). - When a macro needs to modify switches, make sure that they are set back
to their initial value at the end of the macro. Saving the initial state of
all switches is done easily by saving the value of the switch register
i
at the beginning of the macro. This allows, at the end of the macro, to
reset those switches that were changed in the macro to their initial state. - It is a good practice that macros which generate reports, plots
and batch output files use the flexible file naming commands
reports=
, plots=
and batchout=
to define their own
file names. However, if these commands are used it is important to reset
the modified file names to the setting that were active before the macro
was started. This can be achieved by using the commands
reports=^
, plots=^
and/or batchout=^
, which will set
the file names back to the names that were active before the last change. - External commands (
~!...
) are executed by the
operating system of the host computer. Such commands may render the macro
incompatible with different host computers. If a macro contains such
dependencies, this should be clearly documented. Better even, the macro
should test for the correct operating system (using system parameter 2004),
or, if possible, adapt itself to the various host types by providing
several versions of the ~!
command, each preceded by the corresponding
conditional. - It is recommended that macros which modify the data bank should
create a log book comment when they are started. If this comment contains
the macro name and the run time parameters (e.g. c='mymacro %1% %2% %3%'),
the log book can later be consulted to reconstruct the history of the data
bank. For macros that run for a long time and have a high risk of being
interrupted prematurely, it is sometimes even advisable to generate a log book
entry at the beginning and one after normal completion, so that runs that
did not terminate normally will be recognizable as such in the log book.
- If a macro requires a certain number of parameters, a test should be
done at the beginning to verify if enough parameters are provided. If not,
a message should be displayed which shows a summary of the usage of the
macro. This way, a user which is not sure about the calling convention of
a macro, can always call it without parameters to obtain instructions on
the calling sequence.
- Many macros need to store auxiliary data vectors that are just needed
during the macro run, but do not have to be preserved. If these vectors are
limited to use within the network calculator, the best choice is to use
the temporary network attributes tmpxy, as these are always
available and will be deleted automatically when module 2.41 is left.
If the auxiliary vectors are used outside the network calculator, they
should either be specifyable as macro parameter, or be stored in extra
attributes named
@tmp..
that are created at the beginning
and deleted at the end of the macro. - Scalars in the range
ms90
- ms99
should stay reserved
for use as scratch pads. By observing this rule, macros which need scalars
to hold temporary data, can always use these scalars without any danger
that this would distroy any important data. - When using conditionals on floating point registers, be very careful
with testing for equality. Unless the contents of the floating point register
is known to be a true integer (i.e. stored there as integer value or obtained
by operations involving only integer values) in the range 1 to 4194303,
rounding errors may occur that make the use of strict equality comparisons
unsafe.
- Switch 15 is a convenient way of activating the output of internal debugging
information. This switch can safely be assumed OFF during normal operation.
If the macro finds it to be ON, this could be used to set the output control
register to echo dialog output and input and activate the fall-back to
single step mode. If the macro creates auxiliary data vectors which are usually
deleted at the end, it is sometimes useful not to delete them when switch 15 is
ON, to allow analyzing them post-mortem.
Next: 11. Solutions to the Exercises
Up: A Tutorial on the
Previous: 9. Debugging Macros
Heinz Spiess, EMME/2 Support Center
Fri Sep 27 13:04:28 MET DST 1996