modules/tclscript/tclscript.c File Reference

#include <string.h>
#include <stdlib.h>
#include <tcl.h>
#include <eggdrop/eggdrop.h>

Go to the source code of this file.

Data Structures

struct  my_callback_cd_t
struct  my_args_data_t
struct  tcl_listener

Typedefs

typedef struct tcl_listener tcl_listener_t

Functions

static int my_command_handler (ClientData client_data, Tcl_Interp *myinterp, int objc, Tcl_Obj *CONST objv[])
static Tcl_Obj * c_to_tcl_var (Tcl_Interp *myinterp, script_var_t *v)
static int tcl_to_c_var (Tcl_Interp *myinterp, Tcl_Obj *obj, script_var_t *var, int type)
static int my_tcl_cb_delete (event_owner_t *owner, void *me)
static int my_load_script (void *ignore, char *fname)
static int my_link_var (void *ignore, script_linked_var_t *var)
static int my_unlink_var (void *ignore, script_linked_var_t *var)
static int my_create_command (void *ignore, script_raw_command_t *info)
static int my_delete_command (void *ignore, script_raw_command_t *info)
static int my_get_arg (void *ignore, script_args_t *args, int num, script_var_t *var, int type)
static void set_linked_var (script_linked_var_t *var, script_var_t *val)
static char * my_trace_callback (ClientData client_data, Tcl_Interp *irp, char *name1, char *name2, int flags)
static void log_error_message (Tcl_Interp *myinterp)
static int my_tcl_callbacker (script_callback_t *me,...)
static int party_tcl (partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
static int add_tcl_chan (ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
static int rem_tcl_chan (ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
static int tclscript_secondly ()
static int tclscript_close (int why)
EXPORT_SCOPE int tclscript_LTX_start (egg_module_t *modinfo)

Variables

static const char rcsid [] = "$Id: tclscript.c,v 1.52 2007-04-14 15:21:13 sven Exp $"
static event_owner_t tcl_owner
static script_module_t my_script_interface
static Tcl_Interp * ginterp
static char * error_logfile = NULL
static tcl_listener_tlistener_list_head = NULL
static bind_list_t party_commands []
static bind_list_t secondly_binds []


Typedef Documentation

typedef struct tcl_listener tcl_listener_t


Function Documentation

static int add_tcl_chan ( ClientData  cdata,
Tcl_Interp *  interp,
int  objc,
Tcl_Obj *CONST  objv[] 
) [static]

Definition at line 645 of file tclscript.c.

References tcl_listener::fd, tcl_listener::name, tcl_listener::next, NULL, and sockbuf_attach_listener().

Referenced by tclscript_LTX_start().

00646 {
00647   Tcl_Channel chan;
00648   char *chan_name;
00649   int modes;
00650   void *fd;
00651   tcl_listener_t *listener;
00652 
00653   if (objc != 2) {
00654     Tcl_WrongNumArgs(interp, 0, NULL, "channel-name");
00655     return(TCL_ERROR);
00656   }
00657 
00658   chan_name = Tcl_GetStringFromObj(objv[1], NULL);
00659   if (!chan_name) return(TCL_ERROR);
00660   chan = Tcl_GetChannel(interp, chan_name, &modes);
00661   if (!chan) return(TCL_ERROR);
00662   if (Tcl_GetChannelHandle(chan, TCL_READABLE, &fd)) return(TCL_ERROR);
00663   listener = malloc(sizeof(*listener));
00664   listener->next = listener_list_head;
00665   listener->name = strdup(chan_name);
00666   listener->fd = (int) fd;
00667   listener_list_head = listener;
00668   sockbuf_attach_listener((int) fd);
00669   return(0);
00670 }

static Tcl_Obj * c_to_tcl_var ( Tcl_Interp *  myinterp,
script_var_t v 
) [static]

Definition at line 341 of file tclscript.c.

References byte_array_b::bytes, byte_array_b::do_free, partymember::full_id_name, user::handle, byte_array_b::len, script_var_b::len, NULL, SCRIPT_ARRAY, SCRIPT_BYTES, SCRIPT_FREE, SCRIPT_FREE_VAR, SCRIPT_INTEGER, SCRIPT_PARTIER, SCRIPT_POINTER, SCRIPT_STRING, SCRIPT_STRING_LIST, SCRIPT_TYPE_MASK, SCRIPT_UNSIGNED, SCRIPT_USER, SCRIPT_VAR, script_var_b::type, and script_var_b::value.

Referenced by my_command_handler(), my_tcl_callbacker(), and set_linked_var().

00342 {
00343   Tcl_Obj *result;
00344 
00345   result = NULL;
00346   /* If it's an array, we call ourselves recursively. */
00347   if (v->type & SCRIPT_ARRAY) {
00348     Tcl_Obj *element;
00349     int i;
00350 
00351     result = Tcl_NewListObj(0, NULL);
00352     /* If it's an array of script_var_t's, then it's easy. */
00353     if ((v->type & SCRIPT_TYPE_MASK) == SCRIPT_VAR) {
00354       script_var_t **v_list;
00355 
00356       v_list = (script_var_t **)v->value;
00357       for (i = 0; i < v->len; i++) {
00358         element = c_to_tcl_var(myinterp, v_list[i]);
00359         Tcl_ListObjAppendElement(myinterp, result, element);
00360       }
00361     }
00362     else {
00363       /* Otherwise, we have to turn them into fake script_var_t's. */
00364       script_var_t v_sub;
00365       void **values;
00366 
00367       values = (void **)v->value;
00368       for (i = 0; i < v->len; i++) {
00369         v_sub.type = v->type & (~SCRIPT_ARRAY);
00370         v_sub.value = values[i];
00371         v_sub.len = -1;
00372         element = c_to_tcl_var(myinterp, &v_sub);
00373         Tcl_ListObjAppendElement(myinterp, result, element);
00374       }
00375     }
00376     /* Whew */
00377     if (v->type & SCRIPT_FREE) free(v->value);
00378     if (v->type & SCRIPT_FREE_VAR) free(v);
00379     return(result);
00380   }
00381 
00382   /* Here is where we handle the basic types. */
00383   switch (v->type & SCRIPT_TYPE_MASK) {
00384     case SCRIPT_INTEGER:
00385     case SCRIPT_UNSIGNED:
00386       result = Tcl_NewIntObj((int) v->value);
00387       break;
00388     case SCRIPT_STRING: {
00389       char *str = v->value;
00390 
00391       if (!str) str = "";
00392       if (v->len == -1) v->len = strlen(str);
00393 #ifdef USE_TCL_BYTE_ARRAYS
00394       result = Tcl_NewByteArrayObj((unsigned char *) str, v->len);
00395 #else
00396       result = Tcl_NewStringObj(str, v->len);
00397 #endif
00398       if (v->value && v->type & SCRIPT_FREE) free(v->value);
00399       break;
00400     }
00401     case SCRIPT_STRING_LIST: {
00402       char **str = v->value;
00403       Tcl_Obj *element;
00404 
00405       result = Tcl_NewListObj(0, NULL);
00406       while (str && *str) {
00407 #ifdef USE_TCL_BYTE_ARRAYS
00408         element = Tcl_NewByteArrayObj((unsigned char *) (*str), strlen(*str));
00409 #else
00410         element = Tcl_NewStringObj(*str, strlen(*str));
00411 #endif
00412         Tcl_ListObjAppendElement(myinterp, result, element);
00413         str++;
00414       }
00415       break;
00416     }
00417     case SCRIPT_BYTES: {
00418       byte_array_t *bytes = v->value;
00419 #ifdef USE_TCL_BYTE_ARRAYS
00420       result = Tcl_NewByteArrayObj(bytes->bytes, bytes->len);
00421 #else
00422       result = Tcl_NewStringObj(bytes->bytes, bytes->len);
00423 #endif
00424       if (bytes->do_free) free(bytes->bytes);
00425       if (v->type & SCRIPT_FREE) free(bytes);
00426       break;
00427     }
00428     case SCRIPT_POINTER: {
00429       char str[32];
00430 
00431       sprintf(str, "#%u", (unsigned int) v->value);
00432       result = Tcl_NewStringObj(str, -1);
00433       break;
00434     }
00435     case SCRIPT_PARTIER: {
00436       partymember_t *p = v->value;
00437 
00438       if (p) result = Tcl_NewStringObj(p->full_id_name, -1);
00439       else result = Tcl_NewStringObj("*", -1);
00440       break;
00441     }
00442     case SCRIPT_USER: {
00443       /* An eggdrop user record (struct userrec *). */
00444       char *handle;
00445       user_t *u = v->value;
00446 
00447       if (u) handle = u->handle;
00448       else handle = "*";
00449       result = Tcl_NewStringObj(handle, -1);
00450       break;
00451     }
00452     default:
00453       /* Default: just pass a string with an error message. */
00454       result = Tcl_NewStringObj("unsupported type", -1);
00455   }
00456   if (v->type & SCRIPT_FREE_VAR) free(v);
00457   return(result);
00458 }

static void log_error_message ( Tcl_Interp *  myinterp  )  [static]

Definition at line 214 of file tclscript.c.

References _, error_logfile, LOG_MISC, NULL, and putlog().

Referenced by my_tcl_callbacker().

00215 {
00216   FILE *fp;
00217   const char *errmsg;
00218   time_t timenow;
00219 
00220   errmsg = Tcl_GetStringResult(myinterp);
00221   putlog(LOG_MISC, "*", "Tcl Error: %s", errmsg);
00222 
00223   if (!error_logfile || !error_logfile[0]) return;
00224 
00225   timenow = time(NULL);
00226   fp = fopen(error_logfile, "a");
00227   if (!fp) putlog(LOG_MISC, "*", _("Error opening Tcl error log (%s)!"), error_logfile);
00228   else {
00229     errmsg = Tcl_GetVar(myinterp, "errorInfo", TCL_GLOBAL_ONLY);
00230     fprintf(fp, "%s", asctime(localtime(&timenow)));
00231     fprintf(fp, "%s\n\n", errmsg);
00232     fclose(fp);
00233   }
00234 }

static int my_command_handler ( ClientData  client_data,
Tcl_Interp *  myinterp,
int  objc,
Tcl_Obj *CONST  objv[] 
) [static]

Definition at line 567 of file tclscript.c.

References c_to_tcl_var(), script_raw_command_t::callback, script_raw_command_t::client_data, script_args_b::client_data, cmd, my_args_data_t::irp, script_var_b::len, script_args_b::len, script_args_b::module, NULL, my_args_data_t::objv, SCRIPT_ERROR, script_var_b::type, and script_var_b::value.

00568 {
00569   script_raw_command_t *cmd = (script_raw_command_t *)client_data;
00570   script_var_t retval;
00571   Tcl_Obj *tcl_retval = NULL;
00572   script_args_t args;
00573   my_args_data_t argdata;
00574   int err;
00575 
00576   /* Initialize args. */
00577   argdata.irp = myinterp;
00578   argdata.objv = objv;
00579   args.module = &my_script_interface;
00580   args.client_data = &argdata;
00581   args.len = objc-1;
00582 
00583   /* Initialize retval. */
00584   retval.type = 0;
00585   retval.value = NULL;
00586   retval.len = -1;
00587 
00588   /* Execute callback. */
00589   cmd->callback(cmd->client_data, &args, &retval);
00590   err = retval.type & SCRIPT_ERROR;
00591 
00592   /* Process the return value. */
00593   tcl_retval = c_to_tcl_var(myinterp, &retval);
00594 
00595   if (tcl_retval) Tcl_SetObjResult(myinterp, tcl_retval);
00596   else Tcl_ResetResult(myinterp);
00597 
00598   if (err) return TCL_ERROR;
00599   return TCL_OK;
00600 }

static int my_create_command ( void *  ignore,
script_raw_command_t info 
) [static]

Definition at line 307 of file tclscript.c.

References script_raw_command_t::class, egg_mprintf(), ginterp, my_command_handler(), script_raw_command_t::name, and NULL.

00308 {
00309   char *cmdname;
00310 
00311   if (info->class && strlen(info->class)) {
00312     cmdname = egg_mprintf("%s_%s", info->class, info->name);
00313   }
00314   else {
00315     cmdname = strdup(info->name);
00316   }
00317   Tcl_CreateObjCommand(ginterp, cmdname, my_command_handler, (ClientData) info, NULL);
00318   free(cmdname);
00319 
00320   return(0);
00321 }

static int my_delete_command ( void *  ignore,
script_raw_command_t info 
) [static]

Definition at line 324 of file tclscript.c.

References script_raw_command_t::class, egg_mprintf(), ginterp, and script_raw_command_t::name.

00325 {
00326   char *cmdname;
00327 
00328   if (info->class && strlen(info->class)) {
00329     cmdname = egg_mprintf("%s_%s", info->class, info->name);
00330   }
00331   else {
00332     cmdname = strdup(info->name);
00333   }
00334   Tcl_DeleteCommand(ginterp, cmdname);
00335   free(cmdname);
00336 
00337   return(0);
00338 }

static int my_get_arg ( void *  ignore,
script_args_t args,
int  num,
script_var_t var,
int  type 
) [static]

Definition at line 602 of file tclscript.c.

References script_args_b::client_data, my_args_data_t::irp, my_args_data_t::objv, and tcl_to_c_var().

00603 {
00604   my_args_data_t *argdata;
00605 
00606   argdata = (my_args_data_t *)args->client_data;
00607   return tcl_to_c_var(argdata->irp, argdata->objv[num+1], var, type);
00608 }

static int my_link_var ( void *  ignore,
script_linked_var_t var 
) [static]

Definition at line 186 of file tclscript.c.

References script_linked_var_b::class, egg_mprintf(), ginterp, my_trace_callback(), script_linked_var_b::name, NULL, and set_linked_var().

00187 {
00188   char *varname;
00189 
00190   if (var->class && strlen(var->class)) varname = egg_mprintf("%s(%s)", var->class, var->name);
00191   else varname = strdup(var->name);
00192 
00193   set_linked_var(var, NULL);
00194   Tcl_TraceVar(ginterp, varname, TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, (Tcl_VarTraceProc *)my_trace_callback, var);
00195 
00196   free(varname);
00197   return(0);
00198 }

static int my_load_script ( void *  ignore,
char *  fname 
) [static]

Definition at line 105 of file tclscript.c.

References _, ginterp, LOG_MISC, putlog(), SCRIPT_ERR_CODE, SCRIPT_ERR_NOT_RESPONSIBLE, and SCRIPT_OK.

00106 {
00107   int result;
00108   int len;
00109 
00110   /* Check the filename and make sure it ends in .tcl */
00111   len = strlen(fname);
00112   if (len < 4 || fname[len-1] != 'l' || fname[len-2] != 'c' || fname[len-3] != 't' || fname[len-4] != '.') {
00113     /* Nope, let someone else load it. */
00114     return SCRIPT_ERR_NOT_RESPONSIBLE;
00115   }
00116 
00117   result = Tcl_EvalFile (ginterp, fname);
00118   if (result != TCL_OK) {
00119     putlog (LOG_MISC, "*", _("Failed to load script %s: %s"),
00120         fname, Tcl_GetStringResult (ginterp));
00121     return SCRIPT_ERR_CODE;
00122   }
00123 
00124   return SCRIPT_OK; 
00125 }

static int my_tcl_callbacker ( script_callback_t me,
  ... 
) [static]

Definition at line 238 of file tclscript.c.

References c_to_tcl_var(), script_callback_b::callback_data, my_callback_cd_t::command, script_var_b::len, log_error_message(), my_callback_cd_t::myinterp, SCRIPT_INTEGER, SCRIPT_UNSIGNED, script_callback_b::syntax, script_var_b::type, and script_var_b::value.

Referenced by tcl_to_c_var().

00239 {
00240   Tcl_Obj *arg, *final_command, *result;
00241   Tcl_Interp *interp;
00242   script_var_t var;
00243   my_callback_cd_t *cd; /* My callback client data */
00244   int i, n, retval;
00245   va_list va;
00246 
00247   /* This struct contains the interp and the obj command. */
00248   cd = (my_callback_cd_t *)me->callback_data;
00249 
00250   /* Get a copy of the command, then append args. */
00251   final_command = Tcl_DuplicateObj(cd->command);
00252 
00253   if (me->syntax) n = strlen(me->syntax);
00254   else n = 0;
00255 
00256   va_start(va, me);
00257   for (i = 0; i < n; i++) {
00258     var.type = me->syntax[i];
00259     if (var.type == SCRIPT_INTEGER || var.type == SCRIPT_UNSIGNED) var.value = (void *) (va_arg(va, int));
00260     else var.value = va_arg(va, void *);
00261     var.len = -1;
00262     arg = c_to_tcl_var(cd->myinterp, &var);
00263     Tcl_ListObjAppendElement(cd->myinterp, final_command, arg);
00264   }
00265   va_end(va);
00266 
00267   interp = cd->myinterp;
00268 
00269 #ifdef USE_TCL_BYTE_ARRAYS
00270   n = Tcl_EvalObjEx(interp, final_command, TCL_EVAL_GLOBAL);
00271 #else
00272   n = Tcl_GlobalEvalObj(interp, final_command);
00273 #endif
00274 
00275   if (n == TCL_OK) {
00276     result = Tcl_GetObjResult(interp);
00277     Tcl_GetIntFromObj(interp, result, &retval);
00278   }
00279   else {
00280     log_error_message(interp);
00281     Tcl_BackgroundError(interp);
00282   }
00283 
00284   /* Clear any errors or stray messages. */
00285   Tcl_ResetResult(interp);
00286 
00287   return(retval);
00288 }

static int my_tcl_cb_delete ( event_owner_t owner,
void *  me 
) [static]

Definition at line 291 of file tclscript.c.

References script_callback_b::callback_data, my_callback_cd_t::command, script_callback_b::name, my_callback_cd_t::name, and script_callback_b::syntax.

00292 {
00293   script_callback_t *me = data;
00294   my_callback_cd_t *cd;
00295 
00296   cd = me->callback_data;
00297   Tcl_DecrRefCount(cd->command);
00298   if (cd->name) free(cd->name);
00299   if (me->syntax) free(me->syntax);
00300   if (me->name) free(me->name);
00301   free(cd);
00302   free(me);
00303   return(0);
00304 }

static char* my_trace_callback ( ClientData  client_data,
Tcl_Interp *  irp,
char *  name1,
char *  name2,
int  flags 
) [static]

Definition at line 151 of file tclscript.c.

References script_linked_var_b::callbacks, my_link_var(), NULL, script_var_callbacks_b::on_read, script_linked_var_on_write(), SCRIPT_READONLY, set_linked_var(), tcl_to_c_var(), and script_linked_var_b::type.

Referenced by my_link_var(), and my_unlink_var().

00152 {
00153   script_linked_var_t *linked_var = (script_linked_var_t *)client_data;
00154   script_var_t newvalue = {0};
00155 
00156   if (flags & TCL_INTERP_DESTROYED) return(NULL);
00157 
00158   if (flags & TCL_TRACE_READS) {
00159     if (linked_var->callbacks && linked_var->callbacks->on_read) {
00160       int r = (linked_var->callbacks->on_read)(linked_var, &newvalue);
00161       if (r) return(NULL);
00162     }
00163     set_linked_var(linked_var, &newvalue);
00164   }
00165   else if (flags & TCL_TRACE_WRITES) {
00166     Tcl_Obj *obj;
00167 
00168     if (linked_var->type & SCRIPT_READONLY) return("read only variable");
00169 
00170     obj = Tcl_GetVar2Ex(irp, name1, name2, 0);
00171     if (!obj) return("Error setting variable");
00172 
00173     tcl_to_c_var(irp, obj, &newvalue, linked_var->type);
00174     script_linked_var_on_write(linked_var, &newvalue);
00175   }
00176   else if (flags & TCL_TRACE_UNSETS) {
00177     /* If someone unsets a variable, we'll just reset it. */
00178     if (flags & TCL_TRACE_DESTROYED) my_link_var(NULL, linked_var);
00179     else set_linked_var(linked_var, NULL);
00180     return("read only variable");
00181   }
00182   return(NULL);
00183 }

static int my_unlink_var ( void *  ignore,
script_linked_var_t var 
) [static]

Definition at line 201 of file tclscript.c.

References script_linked_var_b::class, egg_mprintf(), ginterp, my_trace_callback(), and script_linked_var_b::name.

00202 {
00203   char *varname;
00204 
00205   if (var->class && strlen(var->class)) varname = egg_mprintf("%s(%s)", var->class, var->name);
00206   else varname = strdup(var->name);
00207 
00208   Tcl_UntraceVar(ginterp, varname, TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, (Tcl_VarTraceProc *)my_trace_callback, var);
00209 
00210   free(varname);
00211   return(0);
00212 }

static int party_tcl ( partymember_t p,
char *  nick,
user_t u,
char *  cmd,
char *  text 
) [static]

Definition at line 610 of file tclscript.c.

References _, BIND_RET_LOG, egg_isowner(), ginterp, user::handle, partymember_printf(), and partymember_write().

00611 {
00612   const char *str;
00613 
00614   if (!u || !egg_isowner(u->handle)) {
00615     partymember_write(p, _("You must be a permanent owner (defined in the config file) to use this command.\n"), -1);
00616     return(BIND_RET_LOG);
00617   }
00618 
00619   if (!text) {
00620     partymember_write(p, _("Syntax: .tcl <tclexpression>"), -1);
00621     return(0);
00622   }
00623 
00624   if (Tcl_GlobalEval(ginterp, text) != TCL_OK) {
00625     str = Tcl_GetVar(ginterp, "errorInfo", TCL_GLOBAL_ONLY);
00626     if (!str) str = Tcl_GetStringResult(ginterp);
00627     partymember_printf(p, _("Tcl error: %s\n\n"), str);
00628   }
00629   else {
00630     str = Tcl_GetStringResult(ginterp);
00631     partymember_printf(p, _("Tcl: %s\n\n"), str);
00632   }
00633   return(0);
00634 }

static int rem_tcl_chan ( ClientData  cdata,
Tcl_Interp *  interp,
int  objc,
Tcl_Obj *CONST  objv[] 
) [static]

Definition at line 672 of file tclscript.c.

References tcl_listener::fd, tcl_listener::name, tcl_listener::next, NULL, and sockbuf_detach_listener().

Referenced by tclscript_LTX_start().

00673 {
00674   char *chan_name;
00675   tcl_listener_t *listener, *prev;
00676 
00677   if (objc != 2) {
00678     Tcl_WrongNumArgs(interp, 0, NULL, "channel-name");
00679     return(TCL_ERROR);
00680   }
00681 
00682   chan_name = Tcl_GetStringFromObj(objv[1], NULL);
00683   if (!chan_name) return(TCL_ERROR);
00684 
00685   prev = NULL;
00686   for (listener = listener_list_head; listener; listener = listener->next) {
00687     if (!strcasecmp(listener->name, chan_name)) break;
00688     prev = listener;
00689   }
00690   if (!listener) return(TCL_ERROR);
00691 
00692   if (prev) prev->next = listener->next;
00693   else listener_list_head = listener->next;
00694   sockbuf_detach_listener(listener->fd);
00695   free(listener->name);
00696   free(listener);
00697   return(0);
00698 }

static void set_linked_var ( script_linked_var_t var,
script_var_t val 
) [static]

Definition at line 128 of file tclscript.c.

References c_to_tcl_var(), script_linked_var_b::class, ginterp, script_var_b::len, script_linked_var_b::name, NULL, SCRIPT_TYPE_MASK, script_linked_var_b::type, script_var_b::type, script_linked_var_b::value, and script_var_b::value.

00129 {
00130   Tcl_Obj *obj;
00131   script_var_t script_var;
00132 
00133   if (!val || !val->type) {
00134     script_var.type = var->type & SCRIPT_TYPE_MASK;
00135     script_var.len = -1;
00136     script_var.value = *(void **)var->value;
00137     val = &script_var;
00138   }
00139 
00140   obj = c_to_tcl_var(ginterp, val);
00141 
00142   if (var->class && strlen(var->class)) {
00143     Tcl_SetVar2Ex(ginterp, var->class, var->name, obj, TCL_GLOBAL_ONLY);
00144   }
00145   else {
00146     Tcl_SetVar2Ex(ginterp, var->name, NULL, obj, TCL_GLOBAL_ONLY);
00147   }
00148 }

static int tcl_to_c_var ( Tcl_Interp *  myinterp,
Tcl_Obj *  obj,
script_var_t var,
int  type 
) [static]

Definition at line 463 of file tclscript.c.

References _, byte_array_b::bytes, script_callback_b::callback, script_callback_b::callback_data, my_callback_cd_t::command, byte_array_b::len, script_var_b::len, my_tcl_callbacker(), my_callback_cd_t::myinterp, script_callback_b::name, NULL, script_callback_b::owner, partymember_lookup(), SCRIPT_BYTES, SCRIPT_CALLBACK, SCRIPT_FREE, SCRIPT_INTEGER, SCRIPT_PARTIER, SCRIPT_STRING, SCRIPT_TYPE_MASK, SCRIPT_UNSIGNED, SCRIPT_USER, script_var_b::type, user_lookup_by_handle(), and script_var_b::value.

Referenced by my_get_arg(), and my_trace_callback().

00464 {
00465   int err = TCL_OK;
00466 
00467   var->type = type;
00468   var->len = -1;
00469   var->value = NULL;
00470 
00471   switch (type & SCRIPT_TYPE_MASK) {
00472     case SCRIPT_STRING: {
00473       char *str;
00474       int len;
00475 
00476 #ifdef USE_TCL_BYTE_ARRAYS
00477         unsigned char *bytes;
00478 
00479         bytes = Tcl_GetByteArrayFromObj(obj, &len);
00480         str = malloc(len+1);
00481         memcpy(str, bytes, len);
00482         str[len] = 0;
00483         var->type |= SCRIPT_FREE;
00484 #else
00485         str = Tcl_GetStringFromObj(obj, &len);
00486 #endif
00487       var->value = str;
00488       var->len = len;
00489       break;
00490     }
00491     case SCRIPT_BYTES: {
00492       byte_array_t *byte_array;
00493 
00494       byte_array = malloc(sizeof(*byte_array));
00495 
00496 #ifdef USE_TCL_BYTE_ARRAYS
00497       byte_array->bytes = Tcl_GetByteArrayFromObj(obj, &byte_array->len);
00498 #else
00499       byte_array->bytes = Tcl_GetStringFromObj(obj, &byte_array->len);
00500 #endif
00501 
00502       var->value = byte_array;
00503       var->type |= SCRIPT_FREE;
00504       break;
00505     }
00506     case SCRIPT_UNSIGNED:
00507     case SCRIPT_INTEGER: {
00508       int intval = 0;
00509 
00510       err = Tcl_GetIntFromObj(myinterp, obj, &intval);
00511       var->value = (void *) intval;
00512       break;
00513     }
00514     case SCRIPT_CALLBACK: {
00515       script_callback_t *cback; /* Callback struct */
00516       my_callback_cd_t *cdata; /* Our client data */
00517 
00518       cback = calloc(1, sizeof(*cback));
00519       cdata = calloc(1, sizeof(*cdata));
00520       cback->callback = (Function) my_tcl_callbacker;
00521       cback->callback_data = cdata;
00522       cback->name = strdup(Tcl_GetString(obj));
00523       cback->owner = &tcl_owner;
00524       cdata->myinterp = myinterp;
00525       cdata->command = obj;
00526       Tcl_IncrRefCount(obj);
00527 
00528       var->value = cback;
00529       break;
00530     }
00531     case SCRIPT_PARTIER: {
00532       const char *name;
00533 
00534       name = Tcl_GetString(obj);
00535       var->value = partymember_lookup(name, NULL, -1);
00536       break;
00537     }
00538     case SCRIPT_USER: {
00539       user_t *u;
00540       script_var_t handle;
00541 
00542       /* Call ourselves recursively to get the handle as a string. */
00543       tcl_to_c_var(myinterp, obj, &handle, SCRIPT_STRING);
00544       u = user_lookup_by_handle((char *)handle.value);
00545       if (handle.type & SCRIPT_FREE) free(handle.value);
00546       var->value = u;
00547       if (!u) {
00548         Tcl_AppendResult(myinterp, "User not found", NULL);
00549         err++;
00550       }
00551       break;
00552     }
00553     default: {
00554       char vartype[2];
00555 
00556       vartype[0] = type;
00557       vartype[1] = 0;
00558       Tcl_AppendResult(myinterp, _("Cannot convert Tcl object to unknown variable type '"), vartype, "'.", NULL);
00559       err++;
00560     }
00561   }
00562 
00563   return(err);
00564 }

static int tclscript_close ( int  why  )  [static]

Definition at line 735 of file tclscript.c.

References bind_rem_list(), ginterp, and script_unregister_module().

Referenced by tclscript_LTX_start().

00736 {
00737   Tcl_DeleteInterp(ginterp);
00738 
00739   bind_rem_list("party", party_commands);
00740   bind_rem_list("secondly", secondly_binds);
00741 
00742   script_unregister_module(&my_script_interface);
00743   return(0);
00744 }

int tclscript_LTX_start ( egg_module_t modinfo  ) 

Definition at line 748 of file tclscript.c.

References add_tcl_chan(), egg_module::author, bind_add_list(), egg_module::close_func, egg_module::description, error_logfile, ginterp, event_owner_b::module, egg_module::name, NULL, rem_tcl_chan(), script_playback(), script_register_module(), tclscript_close(), and egg_module::version.

00749 {
00750   tcl_owner.module = modinfo;
00751 
00752   modinfo->name = "tclscript";
00753   modinfo->author = "eggdev";
00754   modinfo->version = "1.0.0";
00755   modinfo->description = "provides tcl scripting support";
00756   modinfo->close_func = tclscript_close;
00757 
00758   /* Create the interpreter and let tcl load its init.tcl */
00759   ginterp = Tcl_CreateInterp();
00760   Tcl_Init(ginterp);
00761 
00762   error_logfile = strdup("logs/tcl_errors.log");
00763   Tcl_LinkVar(ginterp, "error_logfile", (char *)&error_logfile, TCL_LINK_STRING);
00764 
00765   script_register_module(&my_script_interface);
00766   script_playback(&my_script_interface);
00767 
00768   bind_add_list("party", party_commands);
00769   bind_add_list("secondly", secondly_binds);
00770 
00771   Tcl_CreateObjCommand(ginterp, "net_add_tcl", add_tcl_chan, NULL, NULL);
00772   Tcl_CreateObjCommand(ginterp, "net_rem_tcl", rem_tcl_chan, NULL, NULL);
00773   return(0);
00774 }

static int tclscript_secondly (  )  [static]

Definition at line 700 of file tclscript.c.

00701 {
00702   Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
00703   return(0);
00704 }


Variable Documentation

char* error_logfile = NULL [static]

Definition at line 77 of file tclscript.c.

Tcl_Interp* ginterp [static]

Definition at line 75 of file tclscript.c.

Definition at line 642 of file tclscript.c.

Initial value:

Definition at line 67 of file tclscript.c.

Initial value:

 {
  {"n", "tcl", (Function) party_tcl},
  {0}
}

Definition at line 725 of file tclscript.c.

const char rcsid[] = "$Id: tclscript.c,v 1.52 2007-04-14 15:21:13 sven Exp $" [static]

Definition at line 21 of file tclscript.c.

Initial value:

Definition at line 730 of file tclscript.c.

Initial value:

 {
  "tclscript", 0,
  0, 0,
  my_tcl_cb_delete
}

Definition at line 61 of file tclscript.c.


Generated on Sun Nov 30 18:43:36 2008 for eggdrop1.9 by  doxygen 1.5.6