File: ms.c

package info (click to toggle)
tcllib 1.20%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 68,064 kB
  • sloc: tcl: 216,842; ansic: 14,250; sh: 2,846; xml: 1,766; yacc: 1,145; pascal: 881; makefile: 107; perl: 84; f90: 84; python: 33; ruby: 13; php: 11
file content (379 lines) | stat: -rw-r--r-- 10,550 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/* struct::tree - critcl - layer 2 definitions
 *
 * -> Support for the tree methods in layer 3.
 */

#include <ms.h>
#include <m.h>
#include <t.h>
#include <tn.h>
#include <util.h>

/* .................................................. */

/*
 *---------------------------------------------------------------------------
 *
 * tms_getchildren --
 *
 *	Retrieval of the children for a node, either only direct children or
 *	all, possibly filtering.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	Only internal, memory allocation changes ...
 *
 *---------------------------------------------------------------------------
 */

int
tms_getchildren (TN* n, int all,
		 int cmdc, Tcl_Obj** cmdv,
		 Tcl_Obj* tree, Tcl_Interp* interp)
{
    int	      res;
    int	      listc = 0;
    Tcl_Obj** listv = NULL;

    if (all) {
	listv = tn_getdescendants (n, &listc);
    } else {
	listv = tn_getchildren	  (n, &listc);
    }

    if (!listc) {
	/* => (listv == NULL) */
	Tcl_SetObjResult (interp, Tcl_NewListObj (0, NULL));
	return TCL_OK;
    }

    res = tn_filternodes (&listc, listv, cmdc, cmdv, tree, interp);

    if (res != TCL_OK) {
	ckfree ((char*) listv);
	return TCL_ERROR;
    }

    if (!listc) {
	Tcl_SetObjResult (interp, Tcl_NewListObj (0, NULL));
    } else {
	Tcl_SetObjResult (interp, Tcl_NewListObj (listc, listv));
    }

    ckfree ((char*) listv);
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * tms_assign --
 *
 *	Copies the argument tree over into this one. Uses direct
 *	access to internal data structures for matching tree objects, and
 *	goes through a serialize/deserialize combination otherwise.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	Only internal, memory allocation changes ...
 *
 *---------------------------------------------------------------------------
 */

int
tms_assign (Tcl_Interp* interp, T* t, Tcl_Obj* srccmd)
{
    Tcl_CmdInfo srcCmd;

    if (!Tcl_GetCommandInfo(interp,
			    Tcl_GetString (srccmd),
			    &srcCmd)) {
	Tcl_AppendResult (interp, "invalid command name \"",
			  Tcl_GetString (srccmd), "\"", NULL);
	return TCL_ERROR;
    }

    if (srcCmd.objProc == tms_objcmd) {
	/* The source tree object is managed by this code also. We can
	 * retrieve and copy the data directly.
	 */

	T* src = (T*) srcCmd.objClientData;

	return t_assign (t, src);

    } else {
	/* The source tree is not managed by this package Use
	 * (de)serialization to transfer the information We do not invoke the
	 * command proc directly
	 */

	int	 res;
	Tcl_Obj* ser;
	Tcl_Obj* cmd [2];

	/* Phase 1: Obtain serialization object by invoking the object method
	 */

	cmd [0] = srccmd;
	cmd [1] = Tcl_NewStringObj ("serialize", -1);

	Tcl_IncrRefCount (cmd [0]);
	Tcl_IncrRefCount (cmd [1]);

	res = Tcl_EvalObjv (interp, 2, cmd, 0);

	Tcl_DecrRefCount (cmd [0]);
	Tcl_DecrRefCount (cmd [1]);

	if (res != TCL_OK) {
	    return TCL_ERROR;
	}

	ser = Tcl_GetObjResult (interp);
	Tcl_IncrRefCount (ser);
	Tcl_ResetResult (interp);

	/* Phase 2: Copy into ourselves using regular deserialization
	 */

	res = t_deserialize (t, interp, ser);
	Tcl_DecrRefCount (ser);
	return res;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * tms_set --
 *
 *	Copies this tree over into the argument tree. Uses direct access to
 *	internal data structures for matching tree objects, and goes through a
 *	serialize/deserialize combination otherwise.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	Only internal, memory allocation changes ...
 *
 *---------------------------------------------------------------------------
 */

int
tms_set (Tcl_Interp* interp, T* t, Tcl_Obj* dstcmd)
{
    Tcl_CmdInfo dstCmd;

    if (!Tcl_GetCommandInfo(interp,
			    Tcl_GetString (dstcmd),
			    &dstCmd)) {
	Tcl_AppendResult (interp, "invalid command name \"",
			  Tcl_GetString (dstcmd), "\"", NULL);
	return TCL_ERROR;
    }

    if (dstCmd.objProc == tms_objcmd) {
	/* The destination tree object is managed by this code also We can
	 * retrieve and copy the data directly.
	 */

	T* dest = (T*) dstCmd.objClientData;

	return t_assign (dest, t);

    } else {
	/* The destination tree is not managed by this package Use
	 * (de)serialization to transfer the information We do not invoke the
	 * command proc directly.
	 */

	int	 res;
	Tcl_Obj* ser;
	Tcl_Obj* cmd [3];

	/* Phase 1: Obtain our serialization */

	ser = tms_serialize (t->root);

	/* Phase 2: Copy into destination by invoking its deserialization
	 * method
	 */

	cmd [0] = dstcmd;
	cmd [1] = Tcl_NewStringObj ("deserialize", -1);
	cmd [2] = ser;

	Tcl_IncrRefCount (cmd [0]);
	Tcl_IncrRefCount (cmd [1]);
	Tcl_IncrRefCount (cmd [2]);

	res = Tcl_EvalObjv (interp, 3, cmd, 0);

	Tcl_DecrRefCount (cmd [0]);
	Tcl_DecrRefCount (cmd [1]);
	Tcl_DecrRefCount (cmd [2]); /* == ser, is gone now */

	if (res != TCL_OK) {
	    return TCL_ERROR;
	}

	Tcl_ResetResult (interp);
	return TCL_OK;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * tms_serialize --
 *
 *	Generates Tcl value from tree, serialized tree data.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	Only internal, memory allocation changes ...
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj*
tms_serialize (TN* n)
{
    Tcl_Obj*  ser;
    int	      end;
    int	      listc;
    Tcl_Obj** listv;
    Tcl_Obj*  empty;

    listc = 3 * (tn_ndescendants (n) + 1);
    listv = NALLOC (listc, Tcl_Obj*);
    empty = Tcl_NewObj ();
    Tcl_IncrRefCount (empty);

    end = tn_serialize (n, listc, listv, 0, -1, empty);

    ASSERT (listc == end, "Bad serialization");

    ser = Tcl_NewListObj (listc, listv);

    Tcl_DecrRefCount (empty);
    ckfree((char*) listv);

    return ser;
}

/*
 *---------------------------------------------------------------------------
 *
 * tms_objcmd --
 *
 *	Implementation of tree objects, the main dispatcher function.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	Per the called methods.
 *
 *---------------------------------------------------------------------------
 */

int
tms_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv)
{
    T*	t = (T*) cd;
    int m;

    static CONST char* methods [] = {
	"-->",	       "=",	      "ancestors", "append",   "attr",
	"children",    "cut",	      "delete",	   "depth",    "descendants",
	"deserialize", "destroy",     "exists",	   "get",      "getall",
	"height",      "index",	      "insert",	   "isleaf",   "keyexists",
	"keys",	       "lappend",     "leaves",	   "move",     "next",
	"nodes",       "numchildren", "parent",	   "previous", "rename",
	"rootname",    "serialize",   "set",	   "size",     "splice",
	"swap",	       "unset",	      "walk",	   "walkproc",
	NULL
    };
    enum methods {
	M_TSET,	       M_TASSIGN,     M_ANCESTORS, M_APPEND,   M_ATTR,
	M_CHILDREN,    M_CUT,	      M_DELETE,	   M_DEPTH,    M_DESCENDANTS,
	M_DESERIALIZE, M_DESTROY,     M_EXISTS,	   M_GET,      M_GETALL,
	M_HEIGHT,      M_INDEX,	      M_INSERT,	   M_ISLEAF,   M_KEYEXISTS,
	M_KEYS,	       M_LAPPEND,     M_LEAVES,	   M_MOVE,     M_NEXT,
	M_NODES,       M_NUMCHILDREN, M_PARENT,	   M_PREVIOUS, M_RENAME,
	M_ROOTNAME,    M_SERIALIZE,   M_SET,	   M_SIZE,     M_SPLICE,
	M_SWAP,	       M_UNSET,	      M_WALK,	   M_WALKPROC
    };

    if (objc < 2) {
	Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?");
	return TCL_ERROR;
    } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option",
				    0, &m) != TCL_OK) {
	return TCL_ERROR;
    }

    /* Dispatch to methods. They check the #args in detail before performing
     * the requested functionality
     */

    switch (m) {
    case M_TASSIGN:	return tm_TASSIGN     (t, interp, objc, objv);
    case M_TSET:	return tm_TSET	      (t, interp, objc, objv);
    case M_ANCESTORS:	return tm_ANCESTORS   (t, interp, objc, objv);
    case M_APPEND:	return tm_APPEND      (t, interp, objc, objv);
    case M_ATTR:	return tm_ATTR	      (t, interp, objc, objv);
    case M_CHILDREN:	return tm_CHILDREN    (t, interp, objc, objv);
    case M_CUT:		return tm_CUT	      (t, interp, objc, objv);
    case M_DELETE:	return tm_DELETE      (t, interp, objc, objv);
    case M_DEPTH:	return tm_DEPTH	      (t, interp, objc, objv);
    case M_DESCENDANTS: return tm_DESCENDANTS (t, interp, objc, objv);
    case M_DESERIALIZE: return tm_DESERIALIZE (t, interp, objc, objv);
    case M_DESTROY:	return tm_DESTROY     (t, interp, objc, objv);
    case M_EXISTS:	return tm_EXISTS      (t, interp, objc, objv);
    case M_GET:		return tm_GET	      (t, interp, objc, objv);
    case M_GETALL:	return tm_GETALL      (t, interp, objc, objv);
    case M_HEIGHT:	return tm_HEIGHT      (t, interp, objc, objv);
    case M_INDEX:	return tm_INDEX	      (t, interp, objc, objv);
    case M_INSERT:	return tm_INSERT      (t, interp, objc, objv);
    case M_ISLEAF:	return tm_ISLEAF      (t, interp, objc, objv);
    case M_KEYEXISTS:	return tm_KEYEXISTS   (t, interp, objc, objv);
    case M_KEYS:	return tm_KEYS	      (t, interp, objc, objv);
    case M_LAPPEND:	return tm_LAPPEND     (t, interp, objc, objv);
    case M_LEAVES:	return tm_LEAVES      (t, interp, objc, objv);
    case M_MOVE:	return tm_MOVE	      (t, interp, objc, objv);
    case M_NEXT:	return tm_NEXT	      (t, interp, objc, objv);
    case M_NODES:	return tm_NODES	      (t, interp, objc, objv);
    case M_NUMCHILDREN: return tm_NUMCHILDREN (t, interp, objc, objv);
    case M_PARENT:	return tm_PARENT      (t, interp, objc, objv);
    case M_PREVIOUS:	return tm_PREVIOUS    (t, interp, objc, objv);
    case M_RENAME:	return tm_RENAME      (t, interp, objc, objv);
    case M_ROOTNAME:	return tm_ROOTNAME    (t, interp, objc, objv);
    case M_SERIALIZE:	return tm_SERIALIZE   (t, interp, objc, objv);
    case M_SET:		return tm_SET	      (t, interp, objc, objv);
    case M_SIZE:	return tm_SIZE	      (t, interp, objc, objv);
    case M_SPLICE:	return tm_SPLICE      (t, interp, objc, objv);
    case M_SWAP:	return tm_SWAP	      (t, interp, objc, objv);
    case M_UNSET:	return tm_UNSET	      (t, interp, objc, objv);
    case M_WALK:	return tm_WALK	      (t, interp, objc, objv);
    case M_WALKPROC:	return tm_WALKPROC    (t, interp, objc, objv);
    }
    /* Not coming to this place */
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */