1 |
/* |
2 |
* UserData.c |
3 |
* by Kirk Abbott and Ben Allan |
4 |
* Created: 1/94 |
5 |
* Version: $Revision: 1.19 $ |
6 |
* Version control file: $RCSfile: UserData.c,v $ |
7 |
* Date last modified: $Date: 2003/08/23 18:43:09 $ |
8 |
* Last modified by: $Author: ballan $ |
9 |
* |
10 |
* This file is part of the ASCEND Tcl/Tk interface |
11 |
* |
12 |
* Copyright 1997, Carnegie Mellon University |
13 |
* |
14 |
* The ASCEND Tcl/Tk interface is free software; you can redistribute |
15 |
* it and/or modify it under the terms of the GNU General Public License as |
16 |
* published by the Free Software Foundation; either version 2 of the |
17 |
* License, or (at your option) any later version. |
18 |
* |
19 |
* The ASCEND Tcl/Tk interface is distributed in hope that it will be |
20 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
22 |
* General Public License for more details. |
23 |
* |
24 |
* You should have received a copy of the GNU General Public License |
25 |
* along with the program; if not, write to the Free Software Foundation, |
26 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
27 |
* COPYING. COPYING is found in ../compiler. |
28 |
*/ |
29 |
|
30 |
#include <stdarg.h> |
31 |
#include <tcl.h> |
32 |
#include <utilities/ascConfig.h> |
33 |
#include <utilities/ascMalloc.h> |
34 |
#include <utilities/ascPanic.h> |
35 |
#include <general/list.h> |
36 |
#include <general/hashpjw.h> |
37 |
#include <compiler/compiler.h> |
38 |
#include <compiler/instance_enum.h> |
39 |
#include <compiler/fractions.h> |
40 |
#include <compiler/dimen.h> |
41 |
#include <compiler/atomvalue.h> |
42 |
#include <compiler/instquery.h> |
43 |
#include <compiler/visitinst.h> |
44 |
#include <compiler/units.h> |
45 |
#include "HelpProc.h" |
46 |
#include "UserData.h" |
47 |
#include "Qlfdid.h" |
48 |
#include "UnitsProc.h" |
49 |
#include "BrowserProc.h" |
50 |
|
51 |
#ifndef lint |
52 |
static CONST char UserDataID[] = "$Id: UserData.c,v 1.19 2003/08/23 18:43:09 ballan Exp $"; |
53 |
#endif |
54 |
|
55 |
|
56 |
#define USERDATA_HASHSIZE 31 |
57 |
|
58 |
enum UserInfo_enum { |
59 |
real_info, probe_info, inst_info, list_info, |
60 |
error_info |
61 |
}; |
62 |
|
63 |
char *UserInfo_strings[] = { |
64 |
"real_info", "probe_info", "inst_info", "list_info", |
65 |
"error_info" /* must be last */ |
66 |
}; |
67 |
|
68 |
struct Real_Info { |
69 |
struct Instance *i; |
70 |
double value; |
71 |
}; |
72 |
|
73 |
struct UserData { |
74 |
char *id; |
75 |
enum UserInfo_enum t; |
76 |
union { |
77 |
struct Instance *i; |
78 |
struct gl_list_t *list; /* store anything you want here |
79 |
* just set the type appropriately */ |
80 |
} u; |
81 |
}; |
82 |
|
83 |
struct UserDataEntry { |
84 |
struct UserData *data; |
85 |
struct UserDataEntry *next; |
86 |
}; |
87 |
|
88 |
|
89 |
/* |
90 |
* global variables. |
91 |
*/ |
92 |
static struct UserDataEntry *UserDataLibrary[USERDATA_HASHSIZE]; |
93 |
static int UserDataLibraryInited = 0; |
94 |
|
95 |
void Asc_UserDataLibraryInitialize(void) |
96 |
{ |
97 |
unsigned c; |
98 |
if (!UserDataLibraryInited) { |
99 |
for ( c = 0 ; c < USERDATA_HASHSIZE ; UserDataLibrary[c++] = NULL ); |
100 |
UserDataLibraryInited++; |
101 |
} |
102 |
} |
103 |
|
104 |
static |
105 |
struct UserData *UserDataCreate(char *id, enum UserInfo_enum t) |
106 |
{ |
107 |
struct UserData *result; |
108 |
result = (struct UserData *)ascmalloc(sizeof(struct UserData)); |
109 |
assert(result); |
110 |
result->t = t; |
111 |
result->id = id; /* the node owns the string */ |
112 |
switch(t) { |
113 |
case real_info: |
114 |
case probe_info: |
115 |
case list_info: |
116 |
result->u.list = NULL; |
117 |
break; |
118 |
case inst_info: |
119 |
result->u.i = NULL; |
120 |
break; |
121 |
default: |
122 |
Asc_Panic(2, "UserDataCreate", |
123 |
"Unknown information type in UserDataCreate\n"); |
124 |
} |
125 |
return result; |
126 |
} |
127 |
|
128 |
/* |
129 |
* Note : For the case of list_info, we can not tell what |
130 |
* information was stored in the library. It is the users |
131 |
* responsibilty to deallocate that memory, as only the list |
132 |
* structure is destroyed. |
133 |
*/ |
134 |
|
135 |
static |
136 |
void DestroyUserData(struct UserData *user_data) |
137 |
{ |
138 |
if (!user_data) { |
139 |
return; |
140 |
} |
141 |
switch(user_data->t) { |
142 |
case real_info: |
143 |
if (user_data->u.list) { |
144 |
gl_free_and_destroy(user_data->u.list); |
145 |
} |
146 |
break; |
147 |
case probe_info: |
148 |
break; |
149 |
case inst_info: |
150 |
user_data->u.i = NULL; |
151 |
break; |
152 |
case list_info: |
153 |
if (user_data->u.list) { |
154 |
gl_destroy(user_data->u.list); /* see NOTE above */ |
155 |
} |
156 |
break; |
157 |
default: |
158 |
break; |
159 |
} |
160 |
} |
161 |
|
162 |
static char *GenerateId(char *prefix) |
163 |
{ |
164 |
static int counter = 0; |
165 |
char *id; |
166 |
/* The caller owns the string. |
167 |
* The extra bytes are for the numeric index |
168 |
*/ |
169 |
id = (char *)ascmalloc((strlen(prefix)+1+20) * sizeof(char)); |
170 |
sprintf(id,"%s%d",prefix,counter++); |
171 |
return id; |
172 |
} |
173 |
|
174 |
static |
175 |
char *UserDataId(struct UserData *user_data) |
176 |
{ |
177 |
assert(user_data); |
178 |
return user_data->id; |
179 |
} |
180 |
|
181 |
static |
182 |
enum UserInfo_enum UserDataType(struct UserData *user_data) |
183 |
{ |
184 |
assert(user_data); |
185 |
return user_data->t; |
186 |
} |
187 |
|
188 |
|
189 |
static |
190 |
void AddUserData(struct UserData *user_data) |
191 |
{ |
192 |
unsigned long bucket; |
193 |
struct UserDataEntry *ptr; |
194 |
CONST char *id; |
195 |
|
196 |
assert(user_data); |
197 |
id = UserDataId(user_data); |
198 |
bucket = hashpjw(id,USERDATA_HASHSIZE); |
199 |
ptr = UserDataLibrary[bucket]; |
200 |
/* search for name collisions */ |
201 |
while (ptr) { |
202 |
if (strcmp(id,UserDataId(ptr->data))==0) { |
203 |
return; |
204 |
} |
205 |
ptr = ptr->next; |
206 |
} |
207 |
/* add new function to the head of the list. */ |
208 |
ptr = (struct UserDataEntry *) |
209 |
ascmalloc(sizeof(struct UserDataEntry)); |
210 |
ptr->next = UserDataLibrary[bucket]; |
211 |
ptr->data = user_data; |
212 |
UserDataLibrary[bucket] = ptr; |
213 |
} |
214 |
|
215 |
static |
216 |
struct UserData *LookupUserData(char *id) |
217 |
{ |
218 |
unsigned long bucket; |
219 |
struct UserDataEntry *ptr; |
220 |
char *name; |
221 |
if (!id) { |
222 |
return NULL; |
223 |
} |
224 |
bucket = hashpjw(id,USERDATA_HASHSIZE); |
225 |
ptr = UserDataLibrary[bucket]; |
226 |
while (ptr) { |
227 |
name = UserDataId(ptr->data); |
228 |
if (strcmp(name,id)==0) { |
229 |
return ptr->data; |
230 |
} |
231 |
ptr = ptr->next; |
232 |
} |
233 |
return NULL; /* name not found */ |
234 |
} |
235 |
|
236 |
static |
237 |
struct UserData *RemoveUserData(char *id) |
238 |
{ |
239 |
unsigned long bucket; |
240 |
struct UserDataEntry *ptr, **tmp; |
241 |
struct UserData *result; |
242 |
char *name; |
243 |
if (!id) { |
244 |
return NULL; |
245 |
} |
246 |
bucket = hashpjw(id,USERDATA_HASHSIZE); |
247 |
tmp = &UserDataLibrary[bucket]; |
248 |
ptr = UserDataLibrary[bucket]; |
249 |
while (ptr) { |
250 |
name = UserDataId(ptr->data); |
251 |
if (strcmp(name,id)==0) { |
252 |
*tmp = ptr->next; |
253 |
result = ptr->data; |
254 |
ascfree((char *)ptr); /* deallocate the node */ |
255 |
return result; |
256 |
} |
257 |
tmp = &ptr->next; |
258 |
ptr = ptr->next; |
259 |
} |
260 |
return NULL; /* node info not found */ |
261 |
} |
262 |
|
263 |
static |
264 |
void DestroyUserDataLibrary(void) |
265 |
{ |
266 |
unsigned c; |
267 |
struct UserDataEntry *ptr, *next; |
268 |
for(c=0;c<USERDATA_HASHSIZE;c++) { |
269 |
if (UserDataLibrary[c]!=NULL) { |
270 |
ptr = UserDataLibrary[c]; |
271 |
while(ptr!=NULL) { /* destroy the chain */ |
272 |
DestroyUserData(ptr->data); |
273 |
next = ptr->next; |
274 |
ascfree((char *)ptr); |
275 |
ptr = next; |
276 |
} |
277 |
UserDataLibrary[c] = NULL; |
278 |
} |
279 |
} |
280 |
} |
281 |
|
282 |
static |
283 |
enum UserInfo_enum MapStringToEnum(char *string) |
284 |
{ |
285 |
if (!string) { |
286 |
return error_info; |
287 |
} |
288 |
if (strncmp(string,"real_info",4)==0) { |
289 |
return real_info; |
290 |
} |
291 |
if (strncmp(string,"probe_info",4)==0) { |
292 |
return probe_info; |
293 |
} |
294 |
if (strncmp(string,"inst_info",4)==0) { |
295 |
return inst_info; |
296 |
} |
297 |
if (strncmp(string,"list_info",4)==0) { |
298 |
return list_info; |
299 |
} |
300 |
return error_info; |
301 |
} |
302 |
|
303 |
|
304 |
int Asc_UserDataCreateCmd(ClientData cdata, Tcl_Interp *interp, |
305 |
int argc, CONST84 char *argv[]) |
306 |
{ |
307 |
struct UserData *user_data; |
308 |
enum UserInfo_enum t; |
309 |
char *id; |
310 |
|
311 |
(void)cdata; /* stop gcc whine about unused parameter */ |
312 |
|
313 |
if ( argc != 2 ) { |
314 |
Tcl_SetResult(interp, "wrong # args : Usage __userdata_create type", |
315 |
TCL_STATIC); |
316 |
return TCL_ERROR; |
317 |
} |
318 |
t = MapStringToEnum(QUIET(argv[1])); |
319 |
if (t==error_info) { |
320 |
Tcl_SetResult(interp, "Unknown user_data type given", TCL_STATIC); |
321 |
return TCL_ERROR; |
322 |
} |
323 |
id = GenerateId(QUIET(argv[1])); |
324 |
user_data = UserDataCreate(id,t); |
325 |
if (user_data) { |
326 |
AddUserData(user_data); |
327 |
Tcl_AppendResult(interp,id,(char *)NULL); |
328 |
return TCL_OK; |
329 |
} else { |
330 |
Tcl_SetResult(interp, "Serious error in creating user_data", TCL_STATIC); |
331 |
return TCL_ERROR; |
332 |
} |
333 |
} |
334 |
|
335 |
int Asc_UserDataDestroyCmd(ClientData cdata, Tcl_Interp *interp, |
336 |
int argc, CONST84 char *argv[]) |
337 |
{ |
338 |
struct UserData *user_data; |
339 |
|
340 |
(void)cdata; /* stop gcc whine about unused parameter */ |
341 |
|
342 |
if (( argc > 3 )||( argc < 2 )) { |
343 |
Tcl_SetResult(interp, |
344 |
"wrong # args : Usage __userdata_destroy ?one?all? <id>", |
345 |
TCL_STATIC); |
346 |
return TCL_ERROR; |
347 |
} |
348 |
if ((strcmp(argv[1],"one")==0)&&( argc == 3 )) { |
349 |
user_data = RemoveUserData(QUIET(argv[2])); |
350 |
if (user_data) { |
351 |
DestroyUserData(user_data); |
352 |
} |
353 |
return TCL_OK; |
354 |
} else if (strcmp(argv[1],"all")==0) { |
355 |
DestroyUserDataLibrary(); |
356 |
UserDataLibraryInited = 0; /* set up to allow a reinitialization */ |
357 |
return TCL_OK; |
358 |
} else { |
359 |
Tcl_SetResult(interp, "incorrect args to __userdata_destroy", TCL_STATIC); |
360 |
return TCL_ERROR; |
361 |
} |
362 |
} |
363 |
|
364 |
static |
365 |
void UserData_UpdateRealInfo(struct UserData *user_data) |
366 |
{ |
367 |
struct Real_Info *ri; |
368 |
struct Instance *i; |
369 |
unsigned long len,c; |
370 |
|
371 |
assert(user_data); |
372 |
if ((user_data->u.list==NULL)||(user_data->t!=real_info)) { |
373 |
FPRINTF(stderr,"Major error in UserData_RestoreRealInfo\n"); |
374 |
return; |
375 |
} |
376 |
len = gl_length(user_data->u.list); |
377 |
for (c=1;c<=len;c++) { |
378 |
ri = (struct Real_Info *)gl_fetch(user_data->u.list,c); |
379 |
i = ri->i; |
380 |
ri->value = RealAtomValue(i); |
381 |
} |
382 |
} |
383 |
|
384 |
static |
385 |
void UserData_RestoreRealInfo(struct UserData *user_data) |
386 |
{ |
387 |
struct Real_Info *ri; |
388 |
struct Instance *i; |
389 |
unsigned long len,c; |
390 |
|
391 |
assert(user_data); |
392 |
if ((user_data->u.list==NULL)||(user_data->t!=real_info)) { |
393 |
FPRINTF(stderr,"Major error in UserData_RestoreRealInfo\n"); |
394 |
return; |
395 |
} |
396 |
len = gl_length(user_data->u.list); |
397 |
for (c=1;c<=len;c++) { |
398 |
ri = (struct Real_Info *)gl_fetch(user_data->u.list,c); |
399 |
i = ri->i; |
400 |
SetRealAtomValue(i,ri->value,(unsigned)0); |
401 |
} |
402 |
} |
403 |
|
404 |
/* |
405 |
* global variables. |
406 |
*/ |
407 |
struct gl_list_t *g_tmp_userlist = NULL; |
408 |
|
409 |
/* |
410 |
* at present (and for no good reason) this function is supposed to |
411 |
* record the values of real variables and real child of atoms values. |
412 |
* It needs to be generalized. |
413 |
* It probably shouldn't record values of constants ever, but it |
414 |
* should handle all types of vars. |
415 |
*/ |
416 |
static |
417 |
void UserDataSaveValuesFunc(struct Instance *i) |
418 |
{ |
419 |
struct Real_Info *ri; |
420 |
if (i) { |
421 |
switch(InstanceKind(i)) { |
422 |
case REAL_INST: |
423 |
case REAL_ATOM_INST: |
424 |
ri = (struct Real_Info *)ascmalloc(sizeof(struct Real_Info)); |
425 |
ri->i = i; |
426 |
ri->value = (AtomAssigned(i)) ? RealAtomValue(i) : 0.0; |
427 |
gl_append_ptr(g_tmp_userlist,(char *)ri); |
428 |
break; |
429 |
case INTEGER_INST: |
430 |
case INTEGER_ATOM_INST: |
431 |
/* do something,break; */ |
432 |
case SYMBOL_INST: |
433 |
case SYMBOL_ATOM_INST: |
434 |
/* do something,break; */ |
435 |
case BOOLEAN_INST: |
436 |
case BOOLEAN_ATOM_INST: |
437 |
/* do something,break; */ |
438 |
case REAL_CONSTANT_INST: |
439 |
case INTEGER_CONSTANT_INST: |
440 |
case SYMBOL_CONSTANT_INST: |
441 |
case BOOLEAN_CONSTANT_INST: |
442 |
case SET_ATOM_INST: |
443 |
/* do nothing,break; */ |
444 |
case REL_INST: |
445 |
case LREL_INST: |
446 |
case MODEL_INST: |
447 |
case ARRAY_INT_INST: |
448 |
case ARRAY_ENUM_INST: |
449 |
case WHEN_INST: |
450 |
case SET_INST: |
451 |
case DUMMY_INST: |
452 |
case SIM_INST: |
453 |
/* do nothing,break; */ |
454 |
break; |
455 |
default: |
456 |
FPRINTF(stderr, "invalid type in switch in UserDataSaveValuesFunc\n"); |
457 |
break; |
458 |
} |
459 |
} |
460 |
} |
461 |
|
462 |
static |
463 |
struct gl_list_t *UserDataSaveValues(struct Instance *i, |
464 |
struct gl_list_t *list) |
465 |
{ |
466 |
g_tmp_userlist = list; |
467 |
VisitInstanceTree(i,UserDataSaveValuesFunc,0,1); |
468 |
g_tmp_userlist = NULL; |
469 |
return list; |
470 |
} |
471 |
|
472 |
int Asc_UserDataSaveValuesCmd(ClientData cdata, Tcl_Interp *interp, |
473 |
int argc, CONST84 char *argv[]) |
474 |
{ |
475 |
struct Instance *from; |
476 |
struct UserData *user_data, *tmp; |
477 |
struct gl_list_t *list; |
478 |
char *id; |
479 |
|
480 |
(void)cdata; /* stop gcc whine about unused parameter */ |
481 |
|
482 |
if ( argc != 3 ) { |
483 |
Tcl_SetResult(interp, "__userdata_save from to", TCL_STATIC); |
484 |
return TCL_ERROR; |
485 |
} |
486 |
if (strcmp(argv[1],"current")==0) { |
487 |
from = g_curinst; |
488 |
} else if (strcmp(argv[1],"search")==0) { |
489 |
from = g_search_inst; |
490 |
} else { |
491 |
user_data = LookupUserData(QUIET(argv[1])); |
492 |
if (!user_data) { |
493 |
Tcl_SetResult(interp, "Error with the reference instance", TCL_STATIC); |
494 |
return TCL_ERROR; |
495 |
} |
496 |
if (UserDataType(user_data)!=inst_info) { |
497 |
Tcl_SetResult(interp, "Error with the reference instance", TCL_STATIC); |
498 |
return TCL_ERROR; |
499 |
} |
500 |
from = user_data->u.i; |
501 |
} |
502 |
if (from==NULL) { |
503 |
Tcl_SetResult(interp, "reference instance is NULL", TCL_STATIC); |
504 |
return TCL_ERROR; |
505 |
} |
506 |
|
507 |
tmp = LookupUserData(QUIET(argv[2])); |
508 |
if (!tmp) { /* does not exist -- so build a real_info list */ |
509 |
list = gl_create(1000L); |
510 |
list = UserDataSaveValues(from,list); |
511 |
id = Asc_MakeInitString(strlen(argv[2])); |
512 |
strcpy(id,argv[2]); |
513 |
tmp = UserDataCreate(id,real_info); /* create the node */ |
514 |
tmp->u.list = list; /* set node information */ |
515 |
AddUserData(tmp); /* add node to table */ |
516 |
return TCL_OK; |
517 |
} else{ /* the list exists so just update the list information */ |
518 |
if (UserDataType(tmp)!=real_info) { |
519 |
Tcl_SetResult(interp, "Incompatible types with Saving Values", |
520 |
TCL_STATIC); |
521 |
return TCL_ERROR; |
522 |
} |
523 |
UserData_UpdateRealInfo(tmp); |
524 |
return TCL_OK; |
525 |
} |
526 |
} |
527 |
|
528 |
int Asc_UserDataRestoreValuesCmd(ClientData cdata, Tcl_Interp *interp, |
529 |
int argc, CONST84 char *argv[]) |
530 |
{ |
531 |
struct UserData *user_data; |
532 |
|
533 |
(void)cdata; /* stop gcc whine about unused parameter */ |
534 |
|
535 |
if ( argc != 2 ) { |
536 |
Tcl_SetResult(interp, "wrong # args : Usage __userdata_restore id", |
537 |
TCL_STATIC); |
538 |
return TCL_ERROR; |
539 |
} |
540 |
user_data = LookupUserData(QUIET(argv[1])); |
541 |
if (!user_data) { |
542 |
Tcl_SetResult(interp, "user_data requested does not exist", TCL_STATIC); |
543 |
return TCL_ERROR; |
544 |
} |
545 |
if ((user_data->u.list==NULL)||(user_data->t!=real_info)) { |
546 |
Tcl_SetResult(interp, "cannot restore non real_info", TCL_STATIC); |
547 |
return TCL_ERROR; |
548 |
} |
549 |
UserData_RestoreRealInfo(user_data); |
550 |
return TCL_OK; |
551 |
} |
552 |
|
553 |
int Asc_UserDataInitializeCmd(ClientData cdata, Tcl_Interp *interp, |
554 |
int argc, CONST84 char *argv[]) |
555 |
{ |
556 |
/* usage is __userdata_initialize */ |
557 |
(void)cdata; /* stop gcc whine about unused parameter */ |
558 |
(void)interp; /* stop gcc whine about unused parameter */ |
559 |
(void)argc; /* stop gcc whine about unused parameter */ |
560 |
(void)argv; /* stop gcc whine about unused parameter */ |
561 |
|
562 |
Asc_UserDataLibraryInitialize(); |
563 |
return TCL_OK; |
564 |
} |
565 |
|
566 |
static |
567 |
void UserDataTypeFunc(Tcl_Interp *interp,struct UserData *user_data) |
568 |
{ |
569 |
switch(UserDataType(user_data)) { |
570 |
case real_info: |
571 |
Tcl_AppendResult(interp,"real_info",(char *)NULL); |
572 |
return; |
573 |
case probe_info: |
574 |
Tcl_AppendResult(interp,"probe_info",(char *)NULL); |
575 |
return; |
576 |
case inst_info: |
577 |
Tcl_AppendResult(interp,"inst_info",(char *)NULL); |
578 |
return; |
579 |
case list_info: |
580 |
Tcl_AppendResult(interp,"list_info",(char *)NULL); |
581 |
return; |
582 |
case error_info: |
583 |
default: |
584 |
Tcl_AppendResult(interp,"error_info",(char *)NULL); |
585 |
return; |
586 |
} |
587 |
} |
588 |
|
589 |
int Asc_UserDataQueryCmd(ClientData cdata, Tcl_Interp *interp, |
590 |
int argc, CONST84 char *argv[]) |
591 |
{ |
592 |
/* some general query commands |
593 |
usage is __userdata_query ?type?exists? id */ |
594 |
struct UserData *user_data; |
595 |
|
596 |
(void)cdata; /* stop gcc whine about unused parameter */ |
597 |
|
598 |
if ( argc != 3 ) { |
599 |
Tcl_SetResult(interp, "wrong # args : __userdata_query ?type?exists? id", |
600 |
TCL_STATIC); |
601 |
return TCL_ERROR; |
602 |
} |
603 |
if (strncmp(argv[1],"type",4)==0) { /* type */ |
604 |
user_data = LookupUserData(QUIET(argv[2])); |
605 |
if (!user_data) { |
606 |
Tcl_AppendResult(interp,"error_info",(char *)NULL); |
607 |
return TCL_OK; |
608 |
} else { |
609 |
UserDataTypeFunc(interp,user_data); |
610 |
return TCL_OK; |
611 |
} |
612 |
} else if (strncmp(argv[1],"exists",4)==0) { /* exists */ |
613 |
user_data = LookupUserData(QUIET(argv[2])); |
614 |
if (user_data) { |
615 |
Tcl_SetResult(interp, "1", TCL_STATIC); |
616 |
} else { |
617 |
Tcl_SetResult(interp, "0", TCL_STATIC); |
618 |
} |
619 |
return TCL_OK; |
620 |
} else { |
621 |
Tcl_SetResult(interp, "Invalid args to __userdata_query", TCL_STATIC); |
622 |
return TCL_ERROR; |
623 |
} |
624 |
} |
625 |
|
626 |
int Asc_UserDataPrintLibrary(ClientData cdata, Tcl_Interp *interp, |
627 |
int argc, CONST84 char *argv[]) |
628 |
{ |
629 |
unsigned c; |
630 |
struct UserDataEntry *ptr; |
631 |
|
632 |
(void)cdata; /* stop gcc whine about unused parameter */ |
633 |
(void)argc; /* stop gcc whine about unused parameter */ |
634 |
(void)argv; /* stop gcc whine about unused parameter */ |
635 |
|
636 |
Tcl_AppendResult(interp,"{",(char *)NULL); /* start building the list */ |
637 |
for(c=0;c<USERDATA_HASHSIZE;c++) { |
638 |
if (UserDataLibrary[c]!=NULL) { |
639 |
ptr = UserDataLibrary[c]; |
640 |
while(ptr!=NULL) { |
641 |
Tcl_AppendResult(interp,"{ ",UserDataId(ptr->data)," ",(char *)NULL); |
642 |
UserDataTypeFunc(interp,ptr->data); |
643 |
Tcl_AppendResult(interp,"} ",(char *)NULL); |
644 |
ptr = ptr->next; |
645 |
} |
646 |
} |
647 |
} |
648 |
Tcl_AppendResult(interp,"}",(char *)NULL); /* end building the list */ |
649 |
return TCL_OK; |
650 |
} |