X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=base%2Fscriptinv.c;h=7b67d299af4af002a076ba79e480188635c3345e;hb=c6f18281927becb769ab2ad2bc198b25f5e660b0;hp=1ac7e82ea14967943949bdf7f21f42aa2d236394;hpb=a079a543a386bd6946e48a628d2f768b3057dcc0;p=chiark-tcl.git
diff --git a/base/scriptinv.c b/base/scriptinv.c
index 1ac7e82..7b67d29 100644
--- a/base/scriptinv.c
+++ b/base/scriptinv.c
@@ -1,64 +1,91 @@
/*
+ * 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, see .
*/
-#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;
+ 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, &si->llength); if (rc) return rc;
+ rc= Tcl_ListObjLength(ip, xargs, &xlength); if (rc) return rc;
Tcl_IncrRefCount(xargs);
+ 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 **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);
- for (i=0; iipq, 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;
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);
+}