New Macro Profiler

This macro profiler allows you to insert statements into your code that will profile the execution time of your code.  There is support for multiple timers, updates can be message'd or dumped to a file, timers may be paused, restarted, or reset at any point.  mp pulls all of its own code out of the timing stream, so you don't have to worry if time was spent tracking the time spent (it wasn't).  Additonally the profiler will comment itself out of your code if {&MP-DOTIMING} is not defined.  This allows you to leave profiling code in your source, but not have it affect the run-time performace of the final product.

NOTE:
These include file macros are based entirely on the old mp macros.  I simply changed the parameter passing method to named parameters (vs. the {1} style).  I also added comments and headers to the include files and procedures.  Additionally, the original macros had some troubles initializing the system if you ran code multiple times in the same Progress session (ie. in the editor).  So, I removed all of the automagic initalization.  Now all initialization is manual.  There is a template initialization file mpwrap.p included.  Check it out.  Additionally, default behavior is for the mp*.* files to comment themselves out.  But, best of all, no need for double or triple quoting literal strings!

You'll need a wrapper .p to call the code you're interested in timing.  Use this to generate a filename, get comments/remarks on the test being done, and any other info.  You'll also need to call mpinit.p and mpclose.p to setup and shutdown the globals and the stream of output.  The init and close procedures write time and date information to the stream, along with the current propath.

MP MACRO PARAMETERS
All of the macros use the same parameters, so I'll outline the parameters and their usage before explaining what macros are available.

Remember to quote all named preprocessor arguments, even if they're only one word.  (&TIMER=footime will not work.)

&TIMER:  This is the name of the timer to be used by the macro.  Timer names should be one word.  Case does not matter.  The name of the timer is displayed with each sub-total and total, so
make it descriptive.  It is a good practice to include a timer name in all of your mp.i calls, even if the macro does not make use of the TIMER.  This way the mpdrop.i macros will correctly drop everything related to the given timer. [See mpdrop.i below]

&MP-MACRO:  This is the name of the sub-macro to call.  Almost all of the macros are called through mp.i, and this tells mp.i which macro to use. MUST BE ALL LOWER CASE, or your code won't work on Un*x boxes.  The file included by the mp.i is simply {adeshar/mp{&MP-MACRO}.i ).

&MP-DEBUG:  Define to something no-null (I use "yes") to have the mp macros use &MESSAGE statements to tell you what they are doing.  Very usefull when the compiler barfs on your code, and you don't know why.

&INFOSTR: Use this to pass literal strings to the messaging functions of mp.  Its a good idea to include the file the message is located in.  Along with some useful data about where you are in the file.  For example: {... &INFOSTR="[_uibmain.p] About to run _cr_cust.p."

&INFOVAR: Use this to dump variables to the timing file.  Variables should be character vars, or you'll have to STRING() the name.  ie &INFOVAR="char-var-name" or &INFOVAR="STRING(int-var-name)".  Useful for dumping loop iteration counters and file names.

&MP-DELAY: The number of milliseconds to delay.  Only the delay macro uses this.

&<whatever>:  You can use any other argument you want, the macro system will just ignore it.  This might be good for comments. (?)

The mp macros also use one global preprocessor variable &MP-DOTIMING.  If this variable is defined, then all of the macros do their work.  If it is not defined, then none of the mp code is included in the compile.  Simply include adeshar/mpdotime.i at the top of your file to turn on all of
the timing macros available.

-----------------MP INIT/CLOSE-DOWN PROCEDURES----------------------

mpinit.p
 * Does an init of the globals. Call ONCE at the top of your 
 * wrapper function.
 *
 * Parameters:  outfile: ? if none, otherwise use name.
 *                     messon : true if messages should be on.


mpclose.p
 * This procedure closes the output file, if it is defined.
 * And performs other clean-up, if any.
  

-----------------------MP INCLUDE FILES------------------------------

mpdecl.i
 * Declares a timer.  Does NOT initalize the timer.  Also declares
 * the standard mp globals.  This file should be included once for 
 * each timer that will be used in a file.
 *
 * Note: This can't take itself out of the timing stream because it 
 *       gets called TO DECLARE the variables.
 *
 * Parameters: {&TIMER} name of the timer to declare/init.


mpdotime.i
 * Include this file if you want to time.  
 *
 * NOTE: You cannot call this macro through mp.i
 *       Only affects current file (scope of &GLOBAL-DEFINE)


mpdrop.i
 * Include this file if you want to prevent a specific timer
 * from being included in the build.  Only parsed if global 
 * timing is turned on.  Any macro called through mp.i with
 * &TIMER defined correctly, and all references to mpdecl.i
 * with the appropriate &TIMER will be preprocessed out.
 *
 * NOTE: You cannot call this macro through mp.i
 *       ALSO, this only affects the CURRENT file. (Scope 
 *       of &GLOBAL-DEFINE)
 *
 * Parameters: {&TIMER} Name of timer to stop including.


mp.i
 * Main macro.  Most macros are called "through" this one.
 *
 * Parameters: {&MP-MACRO} submacro to call
 *             {&TIMER} name of timer to use.  Restrict to one token.
 *             {&INFOSTR} string parameter for macros that use them.
 *             {&INFOVAR} variable reference for macros that use them.
 *             {&MP-DEBUG} define as anything to include useful &MESSSAGE.


mpd.i
 * This file defines all of the globals that mp uses.
 * Include this file when you want to reference some of the 
 * generic globals, and you don't have a timer declared.


mpdelay.i
 * This file delays the machine for {&DELAY} milli-seconds.
 * Good for testing mp itself, among other things.


mpx.i
 * Useful for turning mp.i macros into comments. Just Add the X.
 

---------------MP MACROS (called through MP.I)-----------------------

&MP-MACRO="mess"
 * Display a message to the current stream.
 *    
 * NOTE: Do not include this file directly.  First, it will not
 *       remove itself from the count of time executed.  Second,
 *       it will not comment itself out if {&MP-DOTIMING} is not
 *       defined.  Call using mp.i as a wrapper.
 *
 * Parameters: {&INFOSTR} the message to display. [OPTIONAL]
 *             {&INFOVAR} variable to attach at end of string. [OPTIONAL]
 *                Just use var name if char var, else use
 *                {... &INFOVAR="STRING(var-name)" .... }
 *             {&TIMER} Name of the timer this is relevant to. [OPTIONAL]
 *                Only needed if you plan on using mpdrop.i to control compiles.


&MP-MACRO="pause"
 * Pauses the timer.
 *
 * NOTE: Do not include this file directly.  First, it will not
 *       remove itself from the count of time executed.  Second,
 *       it will not comment itself out if {&MP-DOTIMING} is not
 *       defined.  Call using mp.i as a wrapper.
 *
 * Parameters: {&TIMER} name of timer to pause.


&MP-MACRO="resume"
 * Resumes a paused timer.  If timer is not paused, no harm done.
 *
 * Parameters: {&TIMER} name of timer to resume.

 
&MP-MACRO="start"
 * Starts a timer.
 *
 * NOTE: Do not include this file directly.  First, it will not
 *       remove itself from the count of time executed.  Second,
 *       it will not comment itself out if {&MP-DOTIMING} is not
 *       defined.  Call using mp.i as a wrapper.
 *
 * Parameters: {&TIMER} name of timer to start


&MP-MACRO="stotal"
 * Dumps a subtotal to the current output.
 *
 * NOTE: Do not include this file directly.  First, it will not
 *       remove itself from the count of time executed.  Second,
 *       it will not comment itself out if {&MP-DOTIMING} is not
 *       defined.  Call using mp.i as a wrapper.
 *
 * Parameters: {&TIMER} name of timer to display
 *             {&INFOSTR} Description string to display [OPTIONAL]
 *             {&INFOVAR} Variable to include in the string. [OPTIONAL]
 *                  e.g. &INFOVAR="widget-name" or &INFOVAR="STRING(wid-num)"
 *             {&MP-DEBUG} define as something if you want a &MESSAGE 
 *                      showing the parameters sent in. [OPTIONAL]
 *
 *             INFOSTR is displayed before INFOVAR (if both are used),
 *                 also,  INFOVAR does _not_ include its name in the 
 *                 output, if you want to, include it in INFOSTR.


&MP-MACRO="total"
 * Dumps a total to the output stream.
 * NOTE: RESETS TIMER AFTER DISPLAYING TOTAL.
 * 
 * NOTE: Do not include this file directly.  First, it will not
 *       remove itself from the count of time executed.  Second,
 *       it will not comment itself out if {&MP-DOTIMING} is not
 *       defined.  Call using mp.i as a wrapper.
 *
 * Parameters: {&TIMER} name of timer to total
