/[ascend]/trunk/tcltk98/generic/interface/UserData.c
ViewVC logotype

Contents of /trunk/tcltk98/generic/interface/UserData.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 389 - (show annotations) (download) (as text)
Thu Mar 30 06:24:10 2006 UTC (16 years, 1 month ago) by johnpye
File MIME type: text/x-csrc
File size: 16929 byte(s)
Cleaning up #includes in the Tcl/Tk interface. Doing this
all as a group so that it can be reversed out if necessary.
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 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22