You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
4.9 KiB
208 lines
4.9 KiB
# treec.tcl -- |
|
# |
|
# Implementation of a tree data structure for Tcl. |
|
# This code based on critcl, API compatible to the PTI [x]. |
|
# [x] Pure Tcl Implementation. |
|
# |
|
# Copyright (c) 2005 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
|
# |
|
# See the file "license.terms" for information on usage and redistribution |
|
# of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
|
# |
|
# RCS: @(#) $Id: tree_c.tcl,v 1.6 2008/03/25 07:15:34 andreas_kupries Exp $ |
|
|
|
package require critcl |
|
# @sak notprovided struct_treec |
|
package provide struct_treec 2.1.1 |
|
package require Tcl 8.2 |
|
|
|
namespace eval ::struct { |
|
# Supporting code for the main command. |
|
|
|
catch { |
|
#critcl::cheaders -g |
|
#critcl::debug memory symbols |
|
} |
|
|
|
critcl::cheaders tree/*.h |
|
critcl::csources tree/*.c |
|
|
|
critcl::ccode { |
|
/* -*- c -*- */ |
|
|
|
#include <util.h> |
|
#include <t.h> |
|
#include <tn.h> |
|
#include <ms.h> |
|
#include <m.h> |
|
|
|
/* .................................................. */ |
|
/* Global tree management, per interp |
|
*/ |
|
|
|
typedef struct TDg { |
|
long int counter; |
|
char buf [50]; |
|
} TDg; |
|
|
|
static void |
|
TDgrelease (ClientData cd, Tcl_Interp* interp) |
|
{ |
|
ckfree((char*) cd); |
|
} |
|
|
|
static CONST char* |
|
TDnewName (Tcl_Interp* interp) |
|
{ |
|
#define KEY "tcllib/struct::tree/critcl" |
|
|
|
Tcl_InterpDeleteProc* proc = TDgrelease; |
|
TDg* tdg; |
|
|
|
tdg = Tcl_GetAssocData (interp, KEY, &proc); |
|
if (tdg == NULL) { |
|
tdg = (TDg*) ckalloc (sizeof (TDg)); |
|
tdg->counter = 0; |
|
|
|
Tcl_SetAssocData (interp, KEY, proc, |
|
(ClientData) tdg); |
|
} |
|
|
|
tdg->counter ++; |
|
sprintf (tdg->buf, "tree%ld", tdg->counter); |
|
return tdg->buf; |
|
|
|
#undef KEY |
|
} |
|
|
|
static void |
|
TDdeleteCmd (ClientData clientData) |
|
{ |
|
/* Release the whole tree. */ |
|
t_delete ((T*) clientData); |
|
} |
|
} |
|
|
|
# Main command, tree creation. |
|
|
|
critcl::ccommand tree_critcl {dummy interp objc objv} { |
|
/* Syntax |
|
* - epsilon |1 |
|
* - name |2 |
|
* - name =|:=|as|deserialize source |4 |
|
*/ |
|
|
|
CONST char* name; |
|
T* td; |
|
Tcl_Obj* fqn; |
|
Tcl_CmdInfo ci; |
|
|
|
#define USAGE "?name ?=|:=|as|deserialize source??" |
|
|
|
if ((objc != 4) && (objc != 2) && (objc != 1)) { |
|
Tcl_WrongNumArgs (interp, 1, objv, USAGE); |
|
return TCL_ERROR; |
|
} |
|
|
|
if (objc < 2) { |
|
name = TDnewName (interp); |
|
} else { |
|
name = Tcl_GetString (objv [1]); |
|
} |
|
|
|
if (!Tcl_StringMatch (name, "::*")) { |
|
/* Relative name. Prefix with current namespace */ |
|
|
|
Tcl_Eval (interp, "namespace current"); |
|
fqn = Tcl_GetObjResult (interp); |
|
fqn = Tcl_DuplicateObj (fqn); |
|
Tcl_IncrRefCount (fqn); |
|
|
|
if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { |
|
Tcl_AppendToObj (fqn, "::", -1); |
|
} |
|
Tcl_AppendToObj (fqn, name, -1); |
|
} else { |
|
fqn = Tcl_NewStringObj (name, -1); |
|
Tcl_IncrRefCount (fqn); |
|
} |
|
Tcl_ResetResult (interp); |
|
|
|
if (Tcl_GetCommandInfo (interp, |
|
Tcl_GetString (fqn), |
|
&ci)) { |
|
Tcl_Obj* err; |
|
|
|
err = Tcl_NewObj (); |
|
Tcl_AppendToObj (err, "command \"", -1); |
|
Tcl_AppendObjToObj (err, fqn); |
|
Tcl_AppendToObj (err, "\" already exists, unable to create tree", -1); |
|
|
|
Tcl_DecrRefCount (fqn); |
|
Tcl_SetObjResult (interp, err); |
|
return TCL_ERROR; |
|
} |
|
|
|
if (objc == 4) { |
|
Tcl_Obj* type = objv[2]; |
|
Tcl_Obj* src = objv[3]; |
|
int srctype; |
|
|
|
static CONST char* types [] = { |
|
":=", "=", "as", "deserialize", NULL |
|
}; |
|
enum types { |
|
T_ASSIGN, T_IS, T_AS, T_DESER |
|
}; |
|
|
|
if (Tcl_GetIndexFromObj (interp, type, types, "type", |
|
0, &srctype) != TCL_OK) { |
|
Tcl_DecrRefCount (fqn); |
|
Tcl_ResetResult (interp); |
|
Tcl_WrongNumArgs (interp, 1, objv, USAGE); |
|
return TCL_ERROR; |
|
} |
|
|
|
td = t_new (); |
|
|
|
switch (srctype) { |
|
case T_ASSIGN: |
|
case T_AS: |
|
case T_IS: |
|
if (tms_assign (interp, td, src) != TCL_OK) { |
|
t_delete (td); |
|
Tcl_DecrRefCount (fqn); |
|
return TCL_ERROR; |
|
} |
|
break; |
|
|
|
case T_DESER: |
|
if (t_deserialize (td, interp, src) != TCL_OK) { |
|
t_delete (td); |
|
Tcl_DecrRefCount (fqn); |
|
return TCL_ERROR; |
|
} |
|
break; |
|
} |
|
} else { |
|
td = t_new (); |
|
} |
|
|
|
td->cmd = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), |
|
tms_objcmd, (ClientData) td, |
|
TDdeleteCmd); |
|
|
|
Tcl_SetObjResult (interp, fqn); |
|
Tcl_DecrRefCount (fqn); |
|
return TCL_OK; |
|
} |
|
|
|
namespace eval tree { |
|
critcl::ccommand prune_critcl {dummy interp objc objv} { |
|
return 5; |
|
} |
|
} |
|
} |
|
|
|
# ### ### ### ######### ######### ######### |
|
## Ready
|
|
|