rem: if (argc < 3 || argc > 6) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ?-once? ?-thread? interval " "{ script | procname ?arg? }\"", (char *) NULL); return TCL_ERROR; }
context: static Ns_SchedProc FreeSched;static int ReturnValidId(Tcl_Interp *interp, int id, Callback *cbPtr);static int AtCmd(AtProc *procPtr, Tcl_Interp *interp, int argc, char **argv);/* *---------------------------------------------------------------------- * * NsTclAt -- * *	Implements ns_atsignal, ns_atshutdown, and ns_atexit commands. * * Results: *	Tcl result.  * * Side effects: *	See docs.  * *---------------------------------------------------------------------- */static intAtCmd(AtProc *procPtr, Tcl_Interp *interp, int argc, char **argv){    Callback *cbPtr;    if (argc != 2 && argc != 3) {        Tcl_AppendResult(interp, "wrong # args: should be \"",            argv[0], " script | procname ?arg?\"", NULL);        return TCL_ERROR;    }    cbPtr = NewCallback(interp, argv[1], argv[2]);    if (procPtr == Ns_RegisterAtSignal) {    	(*procPtr) (NsTclSignalProc, cbPtr);    } else {    	(*procPtr) (NsTclCallback, cbPtr);    }    return TCL_OK;}    intNsTclAtSignalCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return AtCmd(Ns_RegisterAtSignal, interp, argc, argv);}intNsTclAtShutdownCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return AtCmd(Ns_RegisterShutdown, interp, argc, argv);}intNsTclAtExitCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return AtCmd(Ns_RegisterAtExit, interp, argc, argv);}/* *---------------------------------------------------------------------- * * NsAfterCmd -- * *	Implements ns_after. * * Results: *	Tcl result.  * * Side effects: *	See docs.  * *---------------------------------------------------------------------- */intNsTclAfterCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    int id, seconds;    Callback *cbPtr;    if (argc != 3) {	Tcl_AppendResult(interp, "wrong # args: should be \"",	    argv[0], " seconds script\"", NULL);	return TCL_ERROR;    }    if (Tcl_GetInt(interp, argv[1], &seconds) != TCL_OK) {	return TCL_ERROR;    }    cbPtr = NewCallback(interp, argv[2], NULL);    id = Ns_After(seconds, (Ns_Callback *) NsTclSchedProc, cbPtr, FreeCallback);    return ReturnValidId(interp, id, cbPtr);}   /* *---------------------------------------------------------------------- * * SchedCmd -- * *	Implements ns_unschedule_proc, ns_cancel, ns_pause, and *	ns_resume commands. * * Results: *	Tcl result.  * * Side effects: *	See docs.  * *---------------------------------------------------------------------- */static intSchedCmd(Tcl_Interp *interp, int argc, char **argv, int cmd){    int id, ok;    char buf[10];    if (argc != 2) {        Tcl_AppendResult(interp, "wrong # args: should be \"",            argv[0], " id\"", NULL);        return TCL_ERROR;    }    if (Tcl_GetInt(interp, argv[1], &id) != TCL_OK) {        return TCL_ERROR;    }    switch (cmd) {    case 'u':    case 'c':    	ok = Ns_Cancel(id);	break;    case 'p':    	ok = Ns_Pause(id);	break;    case 'r':    	ok = Ns_Resume(id);	break;    default:	ok = -1;    }    if (cmd != 'u') {    	sprintf(buf, "%d", ok);	Tcl_SetResult(interp, buf, TCL_VOLATILE);    }    return TCL_OK;}intNsTclCancelCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return SchedCmd(interp, argc, argv, 'c');}intNsTclPauseCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return SchedCmd(interp, argc, argv, 'p');}intNsTclResumeCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return SchedCmd(interp, argc, argv, 'r');}intNsTclUnscheduleCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    return SchedCmd(interp, argc, argv, 'u');}/* *---------------------------------------------------------------------- * * NsTclSchedDailyCmd -- * *	Implements ns_schedule_daily.  * * Results: *	Tcl result.  * * Side effects: *	See docs.  * *---------------------------------------------------------------------- */intNsTclSchedDailyCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    Callback    *cbPtr;    int          flags;    int          first;    int          id;    int          hour, minute;    /* 12 cases (arg count & number after cmd and -options are handled):     *      0    1        2        3         4         5          6     *   * cmd hour     minute   script                              (4 args)/3     *   * cmd hour     minute   procname                            (4 args)/3     *   * cmd hour     minute   procname  arg                       (5 args)/4     *   * cmd -once    hour     minute    script                    (5 args)/3     *   * cmd -once    hour     minute    procname                  (5 args)/3     *   * cmd -once    hour     minute    procname  arg             (6 args)/4     *   * cmd -thread  hour     minute    script                    (5 args)/3     *   * cmd -thread  hour     minute    procname                  (5 args)/3     *   * cmd -thread  hour     minute    procname  arg             (6 args)/4     *   * cmd -once    -thread  hour      minute    script          (6 args)/3     *   * cmd -once    -thread  hour      minute    procname        (6 args)/3     *   * cmd -once    -thread  hour      minute    procname  arg   (7 args)/4     */    if (argc < 4 || argc > 7) {        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],			 " ?-once? ?-thread? hour minute "			 "{ script | procname ?arg? }\"", (char *) NULL);        return TCL_ERROR;    }    first = 1;    flags = 0;    while (argc--) {        if (strcmp(argv[first], "-thread") == 0) {            flags |= NS_SCHED_THREAD;        } else if (strcmp(argv[first], "-once") == 0) {            flags |= NS_SCHED_ONCE;        } else {	    break;        }	first++;    }    /*     * First is now the first argument that is not a switch.     */    if (Tcl_GetInt(interp, argv[first++], &hour) != TCL_OK) {        return TCL_ERROR;    }    if (hour < 0 || hour > 23) {        Tcl_AppendResult(interp, "invalid hour \"", argv[first - 1],			 "\": should be >= 0 and <= 23", NULL);        return TCL_ERROR;    }    if (Tcl_GetInt(interp, argv[first++], &minute) != TCL_OK) {        return TCL_ERROR;    }    if (minute < 0 || minute > 59) {        Tcl_AppendResult(interp, "invalid minute \"", argv[first - 1],			 "\": should be >= 0 and <= 59", NULL);        return TCL_ERROR;    }    /*     * Bear in mind that argc has been changed when counting switches,     * so assume that there are no switches when reading the 4 here.     */    cbPtr = NewCallback(interp, argv[first], argv[first+1]);    id = Ns_ScheduleDaily(NsTclSchedProc, cbPtr, flags,			  hour, minute, FreeSched);    return ReturnValidId(interp, id, cbPtr);}/* *---------------------------------------------------------------------- * * NsTclSchedWeeklyCmd -- * *	Implements ns_sched_weekly. * * Results: *	Tcl result.  * * Side effects: *	See docs.  * *---------------------------------------------------------------------- */intNsTclSchedWeeklyCmd(ClientData arg, Tcl_Interp *interp, int argc,		     char **argv){    Callback    *cbPtr;    int          flags;    int          first;    int          id;    int          day, hour, minute;    /* 12 cases (arg count & number after cmd and -options are handled):     *     0    1        2        3        4     5       6      7     *  * cmd day      hour     minute  script                       (5 args)/4     *  * cmd day      hour     minute  proc                         (5 args)/4     *  * cmd day      hour     minute  proc    arg                  (6 args)/5     *  * cmd -once    day      hour    minute  script               (6 args)/4     *  * cmd -once    day      hour    minute  proc                 (6 args)/4     *  * cmd -once    day      hour    minute  proc    arg          (7 args)/5     *  * cmd -thread  day      hour    minute  script               (6 args)/4     *  * cmd -thread  day      hour    minute  proc                 (6 args)/4     *  * cmd -thread  day      hour    minute  proc    arg          (7 args)/5     *  * cmd -once    -thread  day     hour    minute  script       (7 args)/4     *  * cmd -once    -thread  day     hour    minute  proc         (7 args)/4     *  * cmd -once    -thread  day     hour    minute  proc    arg  (8 args)/5     */    if (argc < 5 || argc > 8) {        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],			 " ?-once? ?-thread? day hour minute "			 "{ script | procname ?arg? }\"", (char *) NULL);        return TCL_ERROR;    }    first = 1;    flags = 0;    while (argc--) {        if (strcmp(argv[first], "-thread") == 0) {            flags |= NS_SCHED_THREAD;        } else if (strcmp(argv[first], "-once") == 0) {            flags |= NS_SCHED_ONCE;        } else {	    break;        }        first++;    }    /*     * First is now the first argument that is not a switch.     */    if (Tcl_GetInt(interp, argv[first++], &day) != TCL_OK) {        return TCL_ERROR;    }    if (day < 0 || day > 6) {        Tcl_AppendResult(interp, "invalid day \"", argv[first - 1],			 "\": should be >= 0 and <= 6", NULL);        return TCL_ERROR;    }    if (Tcl_GetInt(interp, argv[first++], &hour) != TCL_OK) {        return TCL_ERROR;    }    if (hour < 0 || hour > 23) {        Tcl_AppendResult(interp, "invalid hour \"", argv[first - 1],			 "\": should be >= 0 and <= 23", NULL);        return TCL_ERROR;    }    if (Tcl_GetInt(interp, argv[first++], &minute) != TCL_OK) {        return TCL_ERROR;    }    if (minute < 0 || minute > 59) {        Tcl_AppendResult(interp, "invalid minute \"", argv[first - 1],			 "\": should be >= 0 and <= 59", NULL);        return TCL_ERROR;    }    cbPtr = NewCallback(interp, argv[first], argv[first+1]);    id = Ns_ScheduleWeekly(NsTclSchedProc, cbPtr, flags,    	    	    	   day, hour, minute, FreeSched);    return ReturnValidId(interp, id, cbPtr);}/* *---------------------------------------------------------------------- * * NsTclSchedCmd -- * *	Implements ns_schedule_proc.  * * Results: *	Tcl result.  * * Side effects: *	See docs.  * *---------------------------------------------------------------------- */intNsTclSchedCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    Callback	*cbPtr;    int          interval;    int          flags;    int          first;    int          id;    /* 12 cases (arg count & number after cmd and -options are handled):     *      0    1        2          3         4     *   * cmd interval script                               (3 args)/2     *   * cmd interval procname                             (3 args)/2     *   * cmd interval procname  arg                        (4 args)/3     *   * cmd -once    interval  script                     (4 args)/2     *   * cmd -once    interval  procname                   (4 args)/2     *   * cmd -once    interval  procname  arg              (5 args)/3     *   * cmd -thread  interval  script                     (4 args)/2     *   * cmd -thread  interval  procname                   (4 args)/2     *   * cmd -thread  interval  procname  arg              (5 args)/3     *   * cmd -once    -thread   interval  script           (5 args)/2     *   * cmd -once    -thread   interval  procname         (5 args)/2     *   * cmd -once    -thread   interval  procname arg     (6 args)/3     */    if (argc < 3 || argc > 6) {        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],			 " ?-once? ?-thread? interval "			 "{ script | procname ?arg? }\"", 			 (char *) NULL);        return TCL_ERROR;    }    first = 1;    flags = 0;    while (argc--) {        if (strcmp(argv[first], "-thread") == 0) {            flags |= NS_SCHED_THREAD;        } else if (strcmp(argv[first], "-once") == 0) {            flags |= NS_SCHED_ONCE;        } else {	    break;	}        first++;    }    /*     * First is now the first argument that is not a switch.     */    if (Tcl_GetInt(interp, argv[first++], &interval) != TCL_OK) {        return TCL_ERROR;    }    cbPtr = NewCallback(interp, argv[first], argv[first+1]);    id = Ns_ScheduleProcEx(NsTclSchedProc, cbPtr, flags, interval, FreeSched);    return ReturnValidId(interp, id, cbPtr);}/* *---------------------------------------------------------------------- * * ReturnValidId -- * *	Update the interp result with the given schedule id if valid. *	Otherwise, free the script and leave an error in the interp. * * Results: *	TCL_OK or TCL_ERROR. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intReturnValidId(Tcl_Interp *interp, int id, Callback *cbPtr){    char buf[10];    if (id == NS_ERROR) {	Tcl_SetResult(interp, "could not schedule procedure", TCL_STATIC);	FreeCallback(cbPtr);        return TCL_ERROR;    }    sprintf(buf, "%d", id);    Tcl_SetResult(interp, buf, TCL_VOLATILE);    return TCL_OK;}/* *---------------------------------------------------------------------- * * EvalCallback -- * *	This is a callback function that runs scheduled tcl  *	procedures registered with ns_schedule_*.  * * Results: *	None.  * * Side effects: *	Will run a Tcl proc/script.  * *---------------------------------------------------------------------- */static voidEvalCallback(void *arg){    Callback *cbPtr = arg;        (void) Ns_TclEval(NULL, cbPtr->server, cbPtr->script);}/* *---------------------------------------------------------------------- * * NewCallback -- * *	Create a new script callback. * * Results: *	Pointer to Callback. * * Side effects: *	None. * *---------------------------------------------------------------------- */static Callback *NewCallback(Tcl_Interp *interp, char *proc, char *arg){    Callback *cbPtr;    char *argv[2];    argv[0] = proc;    argv[1] = arg;    cbPtr = ns_malloc(sizeof(Callback));    cbPtr->server = Ns_TclInterpServer(interp);    cbPtr->script = Tcl_Concat(arg ? 2 : 1, argv);    return cbPtr;}/* *---------------------------------------------------------------------- * * FreeCallback -- * *	Free a Callback created with NewCallback. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidFreeCallback(void *arg){    Callback *cbPtr = arg;    ckfree(cbPtr->script);    ns_free(cbPtr);}static voidFreeSched(void *arg, int id){    FreeCallback(arg);}