/*
**	time.c - measure command execution time
**	Copyright © 1994-95 Michael Letowski
*/

#define __USE_SYSBASE

#include <exec/types.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <dos/dostags.h>
#include <devices/timer.h>
#include <utility/tagitem.h>
#include <support/types.h>
#include <support/dos.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/timer.h>

#include "time.rev.h"


#define DOS_NAME		"dos.library"
#define DOS_VERN		37
#define TIMER_NAME	"timer.device"

STATIC CONST TEXT VersionString[]=
	VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);

#define TEMPLATE		"NOHEAD/S,COMMAND/F/A"

struct Options
{
	LONG   opt_NoHeader;													/* NOHEAD/S */
	STRPTR opt_Command;														/* COMMAND/F/A */
};	/* Options */

LONG Time(VOID)
{
	STATIC CONST struct TagItem SysTags[]=
	{
		{SYS_UserShell,	TRUE},
		{TAG_DONE,			0}
	};	/* SysTags */

	struct ExecBase *SysBase=*((struct ExecBase **)4);
	struct DosLibrary *DOSBase;
	struct Library *TimerBase;

	struct Options Opts;
	struct timeval TV1,TV2;
	struct RDArgs *Args;
	struct MsgPort *Port;
	struct timerequest *TR;
	LONG RC=RETURN_FAIL;

	/* Open libraries */
	unless(DOSBase=(struct DosLibrary *)OpenLibrary(DOS_NAME,DOS_VERN))
		throw2(SetResult2(ERROR_INVALID_RESIDENT_LIBRARY),	NO_DOS);

	/* Read args */
	clear(&Opts);
	unless(Args=ReadArgs(TEMPLATE,(LONG *)&Opts,NULL))
		throw2(PrintFault(IoErr(),PROG_NAME),	NO_ARGS);

	/* Do timing */
	if(Port=CreateMsgPort())
	{
		if(TR=CreateIORequest(Port,sizeof(*TR)))
		{
			if(OpenDevice(TIMER_NAME,UNIT_VBLANK,(struct IORequest *)TR,0)==0)
			{
				TimerBase=(struct Library *)TR->tr_node.io_Device;

				GetSysTime(&TV1);
				RC=SystemTagList(Opts.opt_Command,SysTags) ? RETURN_ERROR : RETURN_OK;
				GetSysTime(&TV2);
				SubTime(&TV2,&TV1);

				/* Print results */
				if(RC==RETURN_ERROR)										/* Error during execution */
					PrintFault(IoErr(),PROG_NAME);
				if(Opts.opt_NoHeader)	VPrintf("%lu.%06lu\n",&TV2);
				else									VPrintf("Execution time: %lu.%06lu s.\n",&TV2);

				CloseDevice((struct IORequest *)TR);
			}
			DeleteIORequest(TR);
		}
		DeleteMsgPort(Port);
	}

	if(RC==RETURN_FAIL)												/* Couldn't use timer */
		CauseIoErr(ERROR_NO_FREE_STORE,PROG_NAME);

	catch(NO_ARGS,	FreeArgs(Args));
	catch(NO_DOS,		CloseLibrary((struct Library *)DOSBase));
	return(RC);
}	/* Time */
