/* Do leak detection on the specified process. */
parse upper arg Pre 'FOR ' After
ForSpecified = FALSE
UntilSpecified = FALSE
if After \= '' then
  ForSpecified = TRUE
else
  do
    parse upper arg Pre 'UNTIL ' After
    if After \= '' then
      UntilSpecified = TRUE
  end
/*say 'Pre = 'Pre', After = 'After', ForSpecified = 'ForSpecified', UntilSpecified = 'UntilSpecified*/

parse var Pre ProcessName DelayValue junk
/*
if datatype( ProcessName) = 'NUM' then
  do
    DelayValue = ProcessName
    ProcessName = 'SYSTEM'
  end
  */
if ProcessName = '' then
  ProcessName = 'SYSTEM'

if datatype( DelayValue) \= 'NUM' then
  DelayValue = 30

if ((ForSpecified = TRUE) & (UntilSpecified = TRUE)) then
  do
    say 'FOR and UNTIL cannot both be specified.'
    ProcessName = '?'
  end

if (ForSpecified = TRUE) then
  do
    parse var After Duration ' HOURS'
    if datatype( Duration) \= 'NUM' then
      do
        say '"Duration" is not a number.'
        ProcessName = '?'
      end
    say 'Leak detection will run for 'Duration' hours.'
  end
if (UntilSpecified = TRUE) then
  do
    parse var After ATime AmPm junk
    if datatype( ATime) \= 'NUM' then
      do
        say '"ATime" is not a number.'
        ProcessName = '?'
      end
    if AmPm = 'PM' then
      ATime = ATime + 12
    say 'Leak detection will run until 'ATime':00:00.'
  end

if ProcessName = '?' then
  do
    say 'This REXX command file does memory leak detection on either the entire system'
    say '  or a specified process.  It uses both THESEUS0.DLL and THESEUS1.DLL.'
    say 'Syntax: "LEAKDET ProcessName [DelayValue] [FOR n [HOURS] | UNTIL n AM|PM]"'
    say 'Where:'
    say '  ProcessName is the name of the process to check for memory leaks.  If the'
    say '    process is not active, the command file will wait for it to start.  The'
    say '    command file terminates when the program terminates.  If there are multiple'
    say '    processes with the same name, the last one started is used.  If the name'
    say '    "system" is used (or if the name is omitted), the entire system is checked.'
    say '  DelayValue is the number of seconds to delay between leak detection passes.'
    say '    If no value is specified, the default is 30 seconds.'
    say '  "FOR n [HOURS]" means to do the run for "n" hours.'
    say '  "UNTIL n AM|PM" means to do the run until "n am" or "n pm".'
    say 'The inputs are not case sensitive.'
    say 'The command file can be terminated with either Ctrl-C or Ctrl-Break.'
    say 'Example: leakdet for 5 hours'
    say '  Do leak detection on the whole system at a 30 second rate for 5 hours.'
    say 'Example: leakdet myprog 60 until 10 pm'
    say '  Do leak detection on the process "myprog" every 60 seconds until 10 PM.'
    exit
  end

call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
call RxFuncAdd 'RT2LoadFuncs', 'THESEUS0', 'RT2LoadFuncs'
rc = RT2LoadFuncs()
if rc \= 0 then
  do
    say 'There was an error.'
    exit
  end
call RxFuncAdd 'RT2LoadFuncs1', 'THESEUS1', 'RT2LoadFuncs1'
rc = RT2LoadFuncs1()
if rc \= 0 then
  do
    say 'There was an error.'
    exit
  end

ProcessPid = 0
LookCount = 0
if ProcessName = 'SYSTEM' then
  do
    say 'Leak detecting the entire system at 'DelayValue' second rate.'
    rc = RT2LeakStart('leak_handle');
  end
else
  do
    do until ProcessPid \= 0
      call RT2FindProcesses 'pTable'
      if datatype( ProcessName) = 'NUM' then
         do i= 1 to pTable.0
           parse value pTable.i with pid parent threads name
           if ProcessName = pid then
             do
                ProcessPid = pid
                ProcessName = name
                leave
             end
         end
      else
         do i = 1 to pTable.0
           parse value pTable.i with pid parent threads name
           if name = ProcessName then
             ProcessPid = pid
         end
      if ProcessPid = 0 then
        do
          if LookCount = 0 then
            say 'Waiting until the process is active.  (Will look each second.)'
          LookCount = LookCount + 1
          call SysSleep 1
        end
    end
    say 'Leak detecting process "'ProcessName'", at 'DelayValue' second rate.'
/*  say 'The process was found with PID = 'ProcessPid'.'*/
    rc = RT2LeakStart('leak_handle', ProcessPid);
  end

say 'Leak detection run started at 'time()' on 'date(Language)'.'

if (ForSpecified = TRUE) then
  do
    CurrentTime = time('R')
    Duration = Duration * 3600   /* Convert from hours to seconds. */
  end

do until always = never
  call SysSleep DelayValue
  say
  /* In the RT2LeakTick call, the second parameter is a boolean as to whether
     or not to use the previous data as the base data.  0 = no, 1 = yes. */
  rc = RT2LeakTick('leak_handle', 1)
  if (ForSpecified = TRUE) then
    do
      if (time('E') >= Duration) then
        do
          say 'The run duration has expired.  The time is 'time()', the date is 'date(Language)'.'
          exit
        end
    end
  if (UntilSpecified = TRUE) then
    do
      parse value time() with Hours ':' Minutes ':' Seconds
      if (Hours >= ATime) then
        do
          say 'The end run time has occured.  The time is 'time()', the date is 'date(Language)'.'
          exit
        end
    end
  if rc = -2 then
    do
      say 'The process has terminated.  The time is 'time()', the date is 'date(Language)'.'
      exit
    end
  else
    say 'Leak detection run at 'time()' on 'date(Language)'.'
end
