Posted to tcl by de at Wed May 16 00:41:03 GMT 2018view pretty

#include <tcl.h>
#include <time.h>

static int
timeObjCmd (
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
) {
    Tcl_Obj *objPtr;
    Tcl_Obj *objs[4];
    int i, result;
    int count;
    struct timespec tp;
    time_t startSec;
    long   startNano;
    
    if (objc == 2) {
	count = 1;
    } else if (objc == 3) {
	result = Tcl_GetIntFromObj(interp, objv[2], &count);
	if (result != TCL_OK) {
	    return result;
	}
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?count?");
	return TCL_ERROR;
    }

    objPtr = objv[1];
    i = count;
    if (clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &tp) != 0) {
        return TCL_ERROR;
    }
    startNano = tp.tv_sec * 1000000000 + tp.tv_nsec;

    while (i-- > 0) {
	result = Tcl_EvalObjEx(interp, objPtr, 0);
	if (result != TCL_OK) {
	    return result;
	}
    }

    if (clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &tp) != 0) {
        return TCL_ERROR;
    }

    if (count <= 1) {
        objs[0] = Tcl_NewLongObj ((tp.tv_sec * 1000000000 + tp.tv_nsec - startNano)
                                  / 1000);
    } else {
        objs[0] = Tcl_NewDoubleObj ((tp.tv_sec * 1000000000.0 + tp.tv_nsec - startNano)
                                    / (count * 1000));
    }
    
    /*
     * Construct the result as a list because many programs have always parsed
     * as such (extracting the first element, typically).
     */

    objs[1] = Tcl_NewStringObj ("microseconds", -1);
    objs[2] = Tcl_NewStringObj ("per", -1);
    objs[3] = Tcl_NewStringObj ("iteration", -1);
    Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));

    return TCL_OK;
        
}

int
Time_Init (interp)
     Tcl_Interp *interp; /* Interpreter to initialize. */
{
    Tcl_InitStubs(interp, "8", 0);
    Tcl_CreateObjCommand(interp, "time::time", timeObjCmd, NULL, NULL );
    Tcl_PkgProvide(interp, "time", "1.0");
    return TCL_OK;
}