home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / howlong.zip / HOWLONG.C
C/C++ Source or Header  |  1999-12-16  |  7KB  |  274 lines

  1. /*
  2.  * HowLong - measure execution times of processes via DosTmr builtin funcs
  3.  * (c) 1999 by Heinz Repp
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. #if defined (__OS2__)
  10.   #define  INCL_DOSPROFILE
  11.   #define  INCL_DOSPROCESS
  12.   #include <os2.h>
  13. #elif defined (_WIN32)
  14.   #include <win.h>
  15.   #include <mapidefs.h>
  16.   #define ulLo LowPart
  17.   #define ulHi HighPart
  18.   typedef LARGE_INTEGER QWORD;
  19. #else
  20.   #error Compiles only with OS/2 or 32 bit Windows!
  21. #endif
  22.  
  23.  
  24. QWORD Ticks2Secs (QWORD ticks, ULONG ticks_per_sec)
  25. {
  26.   ULONG  interlow;
  27.   int    tpsbits, nextbits, bitoffset;
  28.   ldiv_t ldivres;
  29.  
  30.   /* findout how many bits ticks_per_sec uses */
  31.   tpsbits = 0;
  32.   while (ticks_per_sec >> ++tpsbits);
  33.   nextbits = 31 - tpsbits; /* long int of ldiv_t has 31 bit */
  34.  
  35.   /* divide ticks by ticks_per_seconds (quotient: seconds,
  36.      remainder: ticks left to form the fraction of one second) */
  37.   bitoffset = 32;
  38.   ldivres.rem = ticks.ulHi % ticks_per_sec; /* wraparound at 2^32 seconds */
  39.   ticks.ulHi = 0;
  40.   do
  41.   {
  42.     bitoffset -= nextbits;
  43.     ldivres = ldiv (ldivres.rem << nextbits |
  44.                     ticks.ulLo >> bitoffset & ~(~0ul << nextbits),
  45.                     ticks_per_sec);
  46.     ticks.ulHi |= ldivres.quot << bitoffset;
  47.   } while (bitoffset > nextbits);
  48.   ldivres = ldiv (ldivres.rem << bitoffset |
  49.                   ticks.ulLo & ~(~0ul << bitoffset),
  50.                   ticks_per_sec);
  51.   ticks.ulHi |= ldivres.quot;
  52.  
  53.   /* multiply remainder by one million */
  54.   ticks.ulLo = ((unsigned long) ldivres.rem & ~(~0ul << 12)) *
  55.                1000000ul;
  56.   interlow = 0ul;
  57.   bitoffset = 0;
  58.   while (bitoffset + 12 < tpsbits)
  59.   {
  60.     interlow |= (ticks.ulLo & ~(~0ul << 12)) << bitoffset;
  61.     ticks.ulLo >>= 12;
  62.     bitoffset += 12;
  63.     ticks.ulLo += ((unsigned long) ldivres.rem >> bitoffset & ~(~0ul << 12)) *
  64.                   1000000ul;
  65.   }
  66.   interlow |= ticks.ulLo << bitoffset;
  67.   ticks.ulLo >>= 32 - bitoffset;
  68.  
  69.   /* add ticks_per_sec/2 for exact rounding */
  70.   interlow += ticks_per_sec >> 1;
  71.   if (interlow < ticks_per_sec) /* overflow */
  72.     ticks.ulLo++;
  73.  
  74.   /* divide intermediate by ticks_per_seconds (quotient: microseconds) */
  75.   bitoffset = tpsbits - 11;
  76.   ldivres = ldiv (ticks.ulLo << (32 - bitoffset) | interlow >> bitoffset,
  77.                   ticks_per_sec);
  78.   ticks.ulLo = ldivres.quot << bitoffset;
  79.   while (bitoffset > nextbits)
  80.   {
  81.     bitoffset -= nextbits;
  82.     ldivres = ldiv (ldivres.rem << nextbits |
  83.                     interlow >> bitoffset & ~(~0ul << nextbits),
  84.                     ticks_per_sec);
  85.     ticks.ulLo |= ldivres.quot << bitoffset;
  86.   }
  87.   ticks.ulLo |= (ldivres.rem << bitoffset |
  88.                  interlow & ~(~0ul << bitoffset)) /
  89.                 ticks_per_sec;
  90.  
  91.   /* correct if rounding caused overflow */
  92.   if (ticks.ulLo >= 1000000ul)
  93.   {
  94.     ticks.ulLo -= 1000000ul;
  95.     ticks.ulHi++;
  96.   }
  97.  
  98.   return ticks;
  99. }
  100.  
  101.  
  102. int main (int argc, char *argv[])
  103. {
  104.   UCHAR        command[300];
  105.   QWORD        start, stop;
  106.   ULONG        tfreq;
  107. #if defined (__OS2__)
  108.   UCHAR        reserr[CCHMAXPATH] = {0};
  109.   RESULTCODES  rescode;
  110.   PID          ended;
  111. #elif defined (_WIN32)
  112.   PROCESS_INFORMATION pInfo;
  113.   STARTUPINFO         sInfo;
  114.   DWORD               exitCode;
  115. #endif
  116.  
  117.   /* check for commandline args */
  118.   if (argc < 2)
  119.   {
  120.     printf ("Usage: %s <executable> [<arguments> ...]\n", argv[0]);
  121. #if defined (__OS2__)
  122.     DosExit (EXIT_PROCESS, 1);
  123. #elif defined (_WIN32)
  124.     ExitProcess (1);
  125. #endif
  126.   }
  127.  
  128.   /* construct command strings: program name and arguments */
  129.   {
  130.     register char *src, *dst;
  131.     int  i;
  132.     BOOL flag = TRUE;
  133.  
  134.     /* 1st argument = target program;
  135.        flag means it is specified without extension */
  136.     src = argv[1];
  137.     dst = command;
  138.     while (*src)
  139.     {
  140.       switch (*dst++ = *src++)
  141.       {
  142.         case '.':
  143.           /* dot in program name means extension is explicitly stated */
  144.           flag = FALSE;
  145.           break;
  146.         case '\\':
  147.         case '/':
  148.           /* ignore any dots before last path delimiter */
  149.           flag = TRUE;
  150.       }
  151.     }
  152.  
  153.     /* if no extension given: append '.exe' */
  154.     if (flag)
  155.     {
  156.       *dst++ = '.';
  157.       *dst++ = 'e';
  158.       *dst++ = 'x';
  159.       *dst++ = 'e';
  160.     }
  161.  
  162. #if defined (__OS2__)
  163.     /* append null */
  164.     *dst = 0;
  165. #elif defined (_WIN32)
  166.     /* insert space */
  167.     *dst = ' ';
  168. #endif
  169.  
  170.     /* any further arguments = target program arguments;
  171.        flag means that argument has one or more spaces */
  172.     if (argc > 2)
  173.     {
  174.       i = 2;
  175.       do
  176.       {
  177.         flag = FALSE;
  178.         src = argv[i];
  179.         while (*src)
  180.         {
  181.           if (*src == ' ')
  182.           {
  183.             flag = TRUE;
  184.             break;
  185.           }
  186.           src++;
  187.         }
  188.  
  189.         src = argv[i];
  190.         /* if spaces in argument: surround it with double quotes */
  191.         if (flag)
  192.           *++dst = '\"';
  193.         while (*++dst = *src++);
  194.         if (flag)
  195.           *dst++ = '\"';
  196.         *dst = ' ';
  197.       } while (++i < argc);
  198.     }
  199. #if defined (__OS2__)
  200.     else
  201.       dst++;
  202. #endif
  203.  
  204.     *dst = 0;    /* terminate argument string */
  205. #if defined (__OS2__)
  206.     *++dst = 0;  /* terminate command */
  207. #endif
  208.   }
  209.  
  210. #if defined (__OS2__)
  211.   if (DosExecPgm (reserr, sizeof (reserr), EXEC_ASYNCRESULT,
  212.                   command, NULL, &rescode, command))
  213. #elif defined (_WIN32)
  214.   sInfo.cb              = sizeof(STARTUPINFO);
  215.   sInfo.lpReserved      = NULL;
  216.   sInfo.lpReserved2     = NULL;
  217.   sInfo.cbReserved2     = 0;
  218.   sInfo.lpDesktop       = NULL;
  219.   sInfo.lpTitle         = NULL;
  220.   sInfo.dwFlags         = 0;
  221.   sInfo.dwX             = 0;
  222.   sInfo.dwY             = 0;
  223.   sInfo.dwFillAttribute = 0;
  224.   sInfo.wShowWindow     = SW_SHOW;
  225.  
  226.   if (! CreateProcess(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL,
  227.                       &sInfo, &pInfo))
  228. #endif
  229.   {
  230.     printf ( "Unable to run <%s>.\n", command);
  231.   }
  232.   else
  233.   {
  234. #if defined (__OS2__)
  235.     DosTmrQueryTime (&start);
  236.     DosWaitChild (DCWA_PROCESS, DCWW_WAIT,
  237.                   &rescode, &ended, rescode.codeTerminate);
  238.     DosTmrQueryTime (&stop);
  239. #elif defined (_WIN32)
  240.     QueryPerformanceCounter (&start);
  241.     WaitForSingleObject (pInfo.hProcess, INFINITE);
  242.     QueryPerformanceCounter (&stop);
  243.     GetExitCodeProcess (pInfo.hProcess, &exitCode);
  244. #endif
  245.  
  246.     /* subtract start time ticks from stop time ticks */
  247.     stop.ulHi -= start.ulHi;
  248.     if (stop.ulLo < start.ulLo) stop.ulHi--;
  249.     stop.ulLo -= start.ulLo;
  250.  
  251.     /* get timer ticks per second */
  252. #if defined (__OS2__)
  253.     DosTmrQueryFreq (&tfreq);
  254. #elif defined (_WIN32)
  255.     QueryPerformanceFrequency (&start);
  256.     tfreq = start.ulLo;
  257. #endif
  258.  
  259.     /* convert to seconds and microseconds */
  260.     stop = Ticks2Secs (stop, tfreq);
  261.  
  262.     printf ("\n<%s> ended after %lu.%06lu sec with rc=%lu.\n",
  263.             argv[1], stop.ulHi, stop.ulLo,
  264. #if defined (__OS2__)
  265.             rescode.codeResult
  266. #elif defined (_WIN32)
  267.             exitCode
  268. #endif
  269.            );
  270.   }
  271.  
  272.   return 0;
  273. }
  274.