X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=base%2Fscriptinv.c;h=179802e084f05daa19f1923b523829c9dbdcac57;hp=482f4877e6f2683651aa2fadc665ab8938ed16e9;hb=ca8b96bf81245f21fe3906c71dc2994bfc5e516f;hpb=2bdb81ea2a5035b0b3a37ec819ee12edb8595f76 diff --git a/base/scriptinv.c b/base/scriptinv.c index 482f487..179802e 100644 --- a/base/scriptinv.c +++ b/base/scriptinv.c @@ -1,58 +1,81 @@ /* + * base code for various Tcl extensions + * Copyright 2006-2012 Ian Jackson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. */ -#include "hbytes.h" +#include "chiark-tcl-base.h" -void scriptinv_init(ScriptToInvoke *si) { - si->obj= 0; +void cht_scriptinv_init(ScriptToInvoke *si) { + si->ipq= 0; + si->script= 0; si->xargs= 0; } -void scriptinv_cancel(ScriptToInvoke *si) { - if (si->obj) { Tcl_DecrRefCount(si->obj); si->obj= 0; } +void cht_scriptinv_cancel(ScriptToInvoke *si) { + if (si->script) { Tcl_DecrRefCount(si->script); si->script= 0; } if (si->xargs) { Tcl_DecrRefCount(si->xargs); si->xargs= 0; } + si->ipq= 0; } -int scriptinv_set(ScriptToInvoke *si, Tcl_Interp *ip, +int cht_scriptinv_set(ScriptToInvoke *si, Tcl_Interp *ip, Tcl_Obj *newscript, Tcl_Obj *xargs) { int rc, xlength; - scriptinv_cancel(si); + cht_scriptinv_cancel(si); + if (!newscript) return 0; - rc= Tcl_ListObjLength(ip, newscript, &si->llength); if (rc) return rc; + rc= Tcl_ListObjLength(ip, newscript, &si->llen); if (rc) return rc; Tcl_IncrRefCount(newscript); if (xargs) { rc= Tcl_ListObjLength(ip, xargs, &xlength); if (rc) return rc; Tcl_IncrRefCount(xargs); - si->llength += xlength; + assert(si->llen < INT_MAX/2 && xlength < INT_MAX/2); + si->llen += xlength; } - si->obj= newscript; + si->script= newscript; si->xargs= xargs; - si->ip= ip; + si->ipq= ip; return 0; } -void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj *const *argv) { +int cht_scriptinv_invoke_fg(ScriptToInvoke *si, int argc, + Tcl_Obj *const *argv) { Tcl_Obj *invoke=0; int i, rc; - assert(si->obj); + if (!si->ipq) return TCL_OK; + for (i=0; iobj); + invoke= Tcl_DuplicateObj(si->script); Tcl_IncrRefCount(invoke); if (si->xargs) { - rc= Tcl_ListObjAppendList(si->ip, invoke, si->xargs); + rc= Tcl_ListObjAppendList(si->ipq, invoke, si->xargs); if (rc) goto x_rc; } - rc= Tcl_ListObjReplace(si->ip, invoke,si->llength,0, argc,argv); + rc= Tcl_ListObjReplace(si->ipq, invoke,si->llen,0, argc,argv); if (rc) goto x_rc; - rc= Tcl_EvalObjEx(si->ip,invoke,TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); + rc= Tcl_EvalObjEx(si->ipq, invoke, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); if (rc) goto x_rc; rc= 0; @@ -60,5 +83,11 @@ void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj *const *argv) { x_rc: for (i=0; iip); + return rc; } + +void cht_scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj *const *argv) { + int rc; + rc= cht_scriptinv_invoke_fg(si, argc, argv); + if (rc) Tcl_BackgroundError(si->ipq); +}