]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/Modules/tcl8.cxx
fixed compile errors
[wxWidgets.git] / wxPython / wxSWIG / Modules / tcl8.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
3 *
4 * Author : David Beazley
5 *
6 * Department of Computer Science
7 * University of Chicago
8 * 1100 E 58th Street
9 * Chicago, IL 60637
10 * beazley@cs.uchicago.edu
11 *
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
15
16 /***********************************************************************
17 * $Header$
18 *
19 * tcl8.cxx
20 *
21 * Module for creating Tcl 8.0 native wrapper functions. Older SWIG
22 * modules will work with Tcl 8.0, but this one provides a significant
23 * boost in performance.
24 ***********************************************************************/
25
26 #include "swig.h"
27 #include "tcl8.h"
28 #include <ctype.h>
29
30 static char *Tcl_config="swigtcl.swg";
31 static char *usage = "\
32 Tcl 8.0 Options (available with -tcl)\n\
33 -module name - Set name of module\n\
34 -prefix name - Set a prefix to be appended to all names\n\
35 -namespace - Build module into a Tcl 8 namespace. \n\
36 -noobject - Omit code for object oriented interface.\n\
37 -old - Use old SWIG interface (same as -noobject).\n\n";
38
39 static char *ns_name = 0;
40
41 static String mod_init;
42 static String mod_extern;
43
44 // ---------------------------------------------------------------------
45 // TCL8::parse_args(int argc, char *argv[])
46 //
47 // Parse tcl specific command line options
48 // ---------------------------------------------------------------------
49
50 void TCL8::parse_args(int argc, char *argv[]) {
51
52 int i = 1;
53 sprintf(LibDir,"%s",tcl_path);
54
55 // Look for certain command line options
56
57 for (i = 1; i < argc; i++) {
58 if (argv[i]) {
59 if (strcmp(argv[i],"-prefix") == 0) {
60 if (argv[i+1]) {
61 prefix = new char[strlen(argv[i+1])+2];
62 strcpy(prefix, argv[i+1]);
63 mark_arg(i);
64 mark_arg(i+1);
65 i++;
66 } else {
67 arg_error();
68 }
69 } else if (strcmp(argv[i],"-module") == 0) {
70 if (argv[i+1]) {
71 set_module(argv[i+1],0);
72 mark_arg(i);
73 mark_arg(i+1);
74 i++;
75 } else {
76 arg_error();
77 }
78 } else if (strcmp(argv[i],"-namespace") == 0) {
79 nspace = 1;
80 mark_arg(i);
81 } else if (strcmp(argv[i],"-old") == 0) {
82 shadow = 0;
83 mark_arg(i);
84 } else if (strcmp(argv[i],"-noobject") == 0) {
85 shadow = 0;
86 mark_arg(i);
87 } else if (strcmp(argv[i],"-help") == 0) {
88 fputs(usage,stderr);
89 }
90 }
91 }
92
93 // If a package has been specified, make sure it ends with a '_'
94
95 if (prefix) {
96 ns_name = copy_string(prefix);
97 if (prefix[strlen(prefix)] != '_') {
98 prefix[strlen(prefix)+1] = 0;
99 prefix[strlen(prefix)] = '_';
100 }
101 } else
102 prefix = "";
103
104 // Create a symbol SWIGTCL
105
106 add_symbol("SWIGTCL",0,0);
107 add_symbol("SWIGTCL8",0,0);
108
109 // Set name of typemaps
110
111 typemap_lang = "tcl8";
112
113 // Attempt to load up the C++ configuration files
114
115 get_file("delcmd8.swg",delcmd);
116 get_file("methodcmd8.swg",methodcmd);
117 get_file("objcmd8.swg",objcmd);
118
119 }
120
121 // ---------------------------------------------------------------------
122 // void TCL8::parse()
123 //
124 // Start parsing an interface file for Tcl.
125 // ---------------------------------------------------------------------
126
127 void TCL8::parse() {
128
129 fprintf(stderr,"Making wrappers for Tcl 8.x\n");
130
131 // Print out TCL specific headers
132
133 headers();
134
135 // Run the parser
136
137 yyparse();
138
139 }
140
141 // ---------------------------------------------------------------------
142 // TCL8::set_module(char *mod_name,char **mod_list)
143 //
144 // Sets the module name.
145 // Does nothing if it's already set (so it can be overridden as a command
146 // line option).
147 //
148 // mod_list is a NULL-terminated list of additional modules. This
149 // is really only useful when building static executables and other
150 // things.
151 //----------------------------------------------------------------------
152
153 void TCL8::set_module(char *mod_name, char **mod_list) {
154
155 char temp[256], *c;
156 int i;
157
158 if (module) return;
159
160 module = new char[strlen(mod_name)+1];
161 strcpy(module,mod_name);
162
163 // Fix capitalization for Tcl
164
165 c = module;
166 while (*c) {
167 *c = (char) tolower(*c);
168 c++;
169 }
170
171 // Now create an initialization function
172
173 sprintf(temp,"%s_Init", module);
174 init_name = new char[strlen(temp) + 1];
175 strcpy(init_name, temp);
176 *init_name = toupper(*init_name);
177
178 if (!ns_name) ns_name = copy_string(module);
179
180 // If namespaces have been specified, set the prefix to the module name
181
182 if ((nspace) && (strlen(prefix) < 1)) {
183 prefix = new char[strlen(module)+2];
184 strcpy(prefix,module);
185 prefix[strlen(module)] = '_';
186 prefix[strlen(module)+1] = 0;
187 }
188
189 // If additional modules have been specified, create some code for
190 // initializing them.
191
192 if (mod_list) {
193 i = 0;
194 while (mod_list[i]) {
195 c = mod_list[i];
196 while (*c) {
197 *c = (char) tolower(*c);
198 c++;
199 }
200 sprintf(temp,"%s_Init",mod_list[i]);
201 temp[0] = toupper(temp[0]);
202
203 // Dump out some initialization code
204
205 mod_init << tab4 << "if (" << temp << "(" << interp_name << ") == TCL_ERROR) {\n"
206 << tab8 << "return TCL_ERROR;\n"
207 << tab4 << "}\n\n";
208 mod_extern << "extern int " << temp << "(Tcl_Interp *);\n";
209 i++;
210 }
211 }
212 }
213
214
215 // ---------------------------------------------------------------------
216 // TCL8::set_init(char *iname)
217 //
218 // Sets the initialization function name.
219 // Does nothing if it's already set
220 //
221 //----------------------------------------------------------------------
222
223 void TCL8::set_init(char *iname) {
224
225 if (init_name) return;
226 init_name = new char[strlen(iname)+1];
227 strcpy(init_name, iname);
228
229 }
230
231 // ---------------------------------------------------------------------
232 // TCL8::headers(void)
233 //
234 // Generate the appropriate header files for TCL interface.
235 // ----------------------------------------------------------------------
236
237 void TCL8::headers(void)
238 {
239
240 emit_banner(f_header);
241 fprintf(f_header,"/* Implementation : TCL 8.0 */\n\n");
242 fprintf(f_header,"#include <tcl.h>\n");
243 fprintf(f_header,"#include <string.h>\n");
244 fprintf(f_header,"#include <stdlib.h>\n");
245 fprintf(f_header,"#define SWIGTCL\n");
246 fprintf(f_header,"#define SWIGTCL8\n");
247
248 // Include a Tcl configuration file for Unix,Mac,Wintel.
249
250 if (NoInclude) {
251 fprintf(f_header,"#define SWIG_NOINCLUDE\n");
252 }
253
254 if (insert_file("swigtcl8.swg",f_header) == -1) {
255 fprintf(stderr,"SWIG : Fatal error. Unable to locate 'swigtcl8.swg' in SWIG library.\n");
256 SWIG_exit(1);
257 }
258 }
259
260 // --------------------------------------------------------------------
261 // TCL8::initialize(void)
262 //
263 // Produces an initialization function. Assumes that the init function
264 // name has already been specified.
265 // ---------------------------------------------------------------------
266
267 void TCL8::initialize()
268 {
269
270 if ((!ns_name) && (nspace)) {
271 fprintf(stderr,"Tcl error. Must specify a namespace.\n");
272 SWIG_exit(1);
273 }
274
275 if (!init_name) {
276 init_name = "Swig_Init";
277 fprintf(stderr,"SWIG : *** Warning. No module name specified.\n");
278 }
279
280 fprintf(f_header,"#define SWIG_init %s\n", init_name);
281 if (!module) module = "swig";
282 fprintf(f_header,"#define SWIG_name \"%s\"\n", module);
283 if (nspace) {
284 fprintf(f_header,"#define SWIG_prefix \"%s::\"\n", ns_name);
285 fprintf(f_header,"#define SWIG_namespace \"%s\"\n\n", ns_name);
286 } else {
287 fprintf(f_header,"#define SWIG_prefix \"%s\"\n", prefix);
288 fprintf(f_header,"#define SWIG_namespace \"\"\n\n");
289 }
290 fprintf(f_header,"#ifdef __cplusplus\n");
291 fprintf(f_header,"extern \"C\" {\n");
292 fprintf(f_header,"#endif\n");
293 fprintf(f_header,"#ifdef MAC_TCL\n");
294 fprintf(f_header,"#pragma export on\n");
295 fprintf(f_header,"#endif\n");
296 fprintf(f_header,"SWIGEXPORT(int) %s(Tcl_Interp *);\n", init_name);
297 fprintf(f_header,"#ifdef MAC_TCL\n");
298 fprintf(f_header,"#pragma export off\n");
299 fprintf(f_header,"#endif\n");
300 fprintf(f_header,"#ifdef __cplusplus\n");
301 fprintf(f_header,"}\n");
302 fprintf(f_header,"#endif\n");
303
304
305 fprintf(f_init,"SWIGEXPORT(int) %s(Tcl_Interp *%s) {\n", init_name, interp_name);
306 if (nspace) {
307 fprintf(f_init,"#ifdef ITCL_NAMESPACES\n");
308 fprintf(f_init,"\t Itcl_Namespace spaceId;\n");
309 fprintf(f_init,"#endif\n");
310 }
311
312 fprintf(f_init,"\t if (%s == 0) \n", interp_name);
313 fprintf(f_init,"\t\t return TCL_ERROR;\n");
314
315 /* Set up SwigPtrType table */
316
317 fprintf(f_init,"\t SWIG_RegisterType();\n");
318
319 /* Check to see if other initializations need to be performed */
320
321 if (strlen(mod_extern.get())) {
322 fprintf(f_init,"%s\n",mod_init.get());
323 fprintf(f_header,"#ifdef __cplusplus\n");
324 fprintf(f_header,"extern \"C\" {\n");
325 fprintf(f_header,"#endif\n");
326 fprintf(f_header,"%s\n",mod_extern.get());
327 fprintf(f_header,"#ifdef __cplusplus\n");
328 fprintf(f_header,"}\n");
329 fprintf(f_header,"#endif\n");
330 }
331
332
333 /* Check to see if we're adding support for Tcl8 nspaces */
334 if (nspace) {
335 fprintf(f_init,"#if (TCL_MAJOR_VERSION >= 8)\n");
336 fprintf(f_init,"\t Tcl_Eval(%s,\"namespace eval %s { }\");\n", interp_name, ns_name);
337 fprintf(f_init,"#endif\n");
338 }
339 }
340
341 // ---------------------------------------------------------------------
342 // TCL8::close(void)
343 //
344 // Wrap things up. Close initialization function.
345 // ---------------------------------------------------------------------
346
347 void TCL8::close(void)
348 {
349
350 // Dump the pointer equivalency table
351
352 emit_ptr_equivalence(f_init);
353
354 // Close the init file and quit
355
356 fprintf(f_init,"%s",postinit.get());
357 fprintf(f_init,"\t return TCL_OK;\n");
358 fprintf(f_init,"}\n");
359
360 }
361
362 // ----------------------------------------------------------------------
363 // TCL8::get_pointer(char *iname, char *srcname, char *src, char *dest,
364 // DataType *t, String &f, char *ret)
365 //
366 // iname = name of function or variable
367 // srcname = name of source
368 // src = source variable in wrapper code
369 // dest = destination variable in wrapper code
370 // t = Datatype
371 // f = String where output is going to go
372 // ret = Return action
373 // ----------------------------------------------------------------------
374
375 void TCL8::get_pointer(char *iname, char *srcname, char *src, char *dest,
376 DataType *t, String &f, char *ret) {
377
378 // Pointers are read as hex-strings with encoded type information
379
380 f << tab4 << "if ((rettype = SWIG_GetPointerObj(interp," << src << ",(void **) &" << dest << ",";
381
382 if (t->type == T_VOID) f << "(char *) 0))) {\n";
383 else
384 f << "\"" << t->print_mangle() << "\"))) {\n";
385
386 // Now emit code according to the level of strictness desired
387
388 switch(TypeStrict) {
389 case 0: // No type checking
390 f << tab4 << "}\n";
391 break;
392 case 1: // Warning message only
393 f << tab8 << "fprintf(stderr,\"Warning : type mismatch in " << srcname
394 << " of " << iname << ". Expected " << t->print_mangle()
395 << ", received %s\\n\", rettype);\n"
396 << tab4 << "}\n";
397 case 2: // Super strict mode.
398 f << tab8 << "Tcl_SetStringObj(tcl_result, \"Type error in " << srcname << " of " << iname
399 << ". Expected " << t->print_mangle() << ", received \", -1);\n"
400 << tab8 << "Tcl_AppendToObj(tcl_result, rettype, -1);\n"
401 << tab8 << ret << ";\n"
402 << tab4 << "}\n";
403 break;
404 default :
405 fprintf(stderr,"Unknown strictness level\n");
406 break;
407 }
408 }
409
410
411 // ----------------------------------------------------------------------
412 // TCL8::create_command(char *cname, char *iname)
413 //
414 // Creates a Tcl command from a C function.
415 // ----------------------------------------------------------------------
416
417 void TCL8::create_command(char *cname, char *iname) {
418
419 char *wname = name_wrapper(cname,prefix);
420
421 fprintf(f_init,"\t Tcl_CreateObjCommand(%s, SWIG_prefix \"%s\",%s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", interp_name, iname, wname);
422
423 // Add interpreter name to repeatcmd hash table. This hash is used in C++ code
424 // generation to try and find repeated wrapper functions.
425
426 repeatcmd.add(iname,copy_string(wname));
427 }
428
429 // ----------------------------------------------------------------------
430 // TCL8::create_function(char *name, char *iname, DataType *d, ParmList *l)
431 //
432 // Create a function declaration and register it with the interpreter.
433 // ----------------------------------------------------------------------
434
435 void TCL8::create_function(char *name, char *iname, DataType *d, ParmList *l)
436 {
437 Parm *p;
438 int pcount,i,j;
439 char *wname;
440 char *usage = 0, *tm;
441 char source[64];
442 char target[64];
443 char argnum[32];
444 WrapperFunction f;
445 String cleanup, outarg, build;
446 int numopt= 0;
447 int have_build = 0;
448
449 // Make a wrapper name for this function
450
451 wname = name_wrapper(iname,prefix);
452
453 // Now write the wrapper function itself....this is pretty ugly
454
455 f.def << "static int " << wname << "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {\n";
456
457 f.code << tab4 << "clientData = clientData; objv = objv;\n";
458
459 // Print out variables for storing arguments.
460
461 pcount = emit_args(d, l, f);
462 numopt = l->numopt();
463
464 // Create a local variable for holding the interpreter result value
465
466 f.add_local("Tcl_Obj *", "tcl_result");
467
468 // Extract the tcl result object
469
470 f.code << tab4 << "tcl_result = Tcl_GetObjResult(interp);\n";
471
472 // Check the number of arguments
473
474 usage = usage_func(iname,d,l); // Create a usage string
475 f.code << tab4 << "if ((objc < " << (pcount-numopt) +1 << ") || (objc > " << l->numarg()+1 << ")) {\n"
476 << tab8 << "Tcl_SetStringObj(tcl_result,\"Wrong # args. " << usage << "\",-1);\n"
477 << tab8 << "return TCL_ERROR;\n"
478 << tab4 << "}\n";
479
480 // Extract parameters. This case statement should be used to extract
481 // Function parameters. Add more cases if you want to do more.
482
483 i = 0;
484 j = 0;
485 p = l->get_first();
486 while (p != 0) {
487 // Produce string representations of the source and target arguments
488 sprintf(source,"objv[%d]",j+1);
489 sprintf(target,"_arg%d",i);
490 sprintf(argnum,"%d",j+1);
491
492 // See if this argument is being ignored
493
494 if (!p->ignore) {
495 if (j >= (pcount-numopt))
496 f.code << tab4 << "if (objc >" << j+1 << ") { \n";
497
498 if ((tm = typemap_lookup("in","tcl8",p->t,p->name,source,target,&f))) {
499 // Yep. Use it instead of the default
500 f.code << tm << "\n";
501 f.code.replace("$argnum",argnum);
502 f.code.replace("$arg",source);
503 } else {
504 if (!p->t->is_pointer) {
505
506 // Extract a parameter by value.
507
508 switch(p->t->type) {
509
510 // Signed Integers
511
512 case T_BOOL:
513 case T_INT:
514 case T_SINT:
515 case T_SHORT:
516 case T_SSHORT:
517 case T_LONG:
518 case T_SLONG:
519 case T_SCHAR:
520
521 // Unsigned integers
522
523 case T_UINT:
524 case T_USHORT:
525 case T_ULONG:
526 case T_UCHAR:
527 f.add_local("int","tempint");
528 f.code << tab4 << "if (Tcl_GetIntFromObj(interp,objv[" << j+1 << "],&tempint) == TCL_ERROR) return TCL_ERROR;\n";
529 f.code << tab4 << "_arg" << i << " = " << p->t->print_cast() << " tempint;\n";
530 break;
531
532 // Floating point
533
534 case T_FLOAT:
535 case T_DOUBLE:
536 f.add_local("double","tempdouble");
537 f.add_local("Tcl_Obj *", "dupobj");
538 f.code << tab4 << "dupobj = Tcl_DuplicateObj(objv[" << j+1 << "]);\n"
539 << tab4 << "if (Tcl_GetDoubleFromObj(interp,dupobj,&tempdouble) == TCL_ERROR) {\n"
540 << tab8 << "Tcl_DecrRefCount(dupobj);\n"
541 << tab8 << "return TCL_ERROR;\n"
542 << tab4 << "}\n"
543 << tab4 << "Tcl_DecrRefCount(dupobj);\n"
544 << tab4 << "_arg" << i << " = " << p->t->print_cast() << " tempdouble;\n";
545 break;
546
547 // A single character
548
549 case T_CHAR :
550 f.add_local("char *","tempstr");
551 f.add_local("int","templength");
552 f.code << tab4 << "if ((tempstr = Tcl_GetStringFromObj(objv[" << j+1 << "],&templength)) == NULL) return TCL_ERROR;\n"
553 << tab4 << "_arg" << i << " = *tempstr;\n";
554 break;
555
556 // Void.. Do nothing.
557
558 case T_VOID :
559 break;
560
561 // User defined. This is an error.
562
563 case T_USER:
564
565 // Unsupported data type
566
567 default :
568 fprintf(stderr,"%s : Line %d: Unable to use type %s as a function argument.\n",
569 input_file, line_number, p->t->print_type());
570 break;
571 }
572 } else {
573
574 // Function argument is some sort of pointer
575 // Look for a string. Otherwise, just pull off a pointer.
576
577 if ((p->t->type == T_CHAR) && (p->t->is_pointer == 1)) {
578 f.add_local("int","templength");
579 f.code << tab4 << "if ((_arg" << i << " = Tcl_GetStringFromObj(objv[" << j+1 << "], &templength)) == NULL) return TCL_ERROR;\n";
580 } else {
581
582 // Have a generic pointer type here. Read it in as
583 // a hex-string
584 char arg_temp[256];
585
586 // Try to parse pointer value directly
587
588 #ifdef OLD
589 f.add_local("char *", "tempstr");
590 f.add_local("int","templength");
591 f.code << tab4 << "if ((tempstr = Tcl_GetStringFromObj(objv[" << j+1 << "],&templength)) == NULL) return TCL_ERROR;\n";
592 get_pointer(iname,arg_temp,"tempstr",target,p->t,f.code,"return TCL_ERROR");
593 #endif
594 sprintf(arg_temp,"argument %d",j+1);
595 f.add_local("char *", "rettype");
596 get_pointer(iname,arg_temp,source,target,p->t,f.code,"return TCL_ERROR");
597 }
598 }
599 }
600 if (j >= (pcount-numopt))
601 f.code << tab4 << "}\n";
602 j++;
603 }
604
605
606 // Check to see if there is any sort of "build" typemap (highly complicated)
607
608 if ((tm = typemap_lookup("build","tcl8",p->t,p->name,source,target))) {
609 build << tm << "\n";
610 have_build = 1;
611 }
612
613 // Check to see if there was any sort of a constaint typemap
614 if ((tm = typemap_lookup("check","tcl8",p->t,p->name,source,target))) {
615 // Yep. Use it instead of the default
616 f.code << tm << "\n";
617 f.code.replace("$argnum",argnum);
618 f.code.replace("$arg",source);
619 }
620
621 // Check if there was any cleanup code (save it for later)
622 if ((tm = typemap_lookup("freearg","tcl8",p->t,p->name,target,"tcl_result"))) {
623 // Yep. Use it instead of the default
624 cleanup << tm << "\n";
625 cleanup.replace("$argnum",argnum);
626 cleanup.replace("$arg",source);
627 }
628 // Look for output arguments
629 if ((tm = typemap_lookup("argout","tcl8",p->t,p->name,target,"tcl_result"))) {
630 outarg << tm << "\n";
631 outarg.replace("$argnum",argnum);
632 outarg.replace("$arg",source);
633 }
634 i++;
635 p = l->get_next(); // Get next parameter and continue
636 }
637
638
639 // If there was a "build" typemap, we need to go in and perform a serious hack
640
641 if (have_build) {
642 char temp1[32];
643 char temp2[256];
644 l->sub_parmnames(build); // Replace all parameter names
645 j = 1;
646 for (i = 0; i < l->nparms; i++) {
647 p = l->get(i);
648 if (strlen(p->name) > 0) {
649 sprintf(temp1,"_in_%s", p->name);
650 } else {
651 sprintf(temp1,"_in_arg%d", i);
652 }
653 sprintf(temp2,"argv[%d]",j);
654 build.replaceid(temp1,temp2);
655 if (!p->ignore)
656 j++;
657 }
658 f.code << build;
659 }
660
661 // Now write code to make the function call
662
663 emit_func_call(name,d,l,f);
664
665 // Extract the tcl result object
666
667 f.code << tab4 << "tcl_result = Tcl_GetObjResult(interp);\n";
668
669
670 // Return value if necessary
671
672 if ((tm = typemap_lookup("out","tcl8",d,name,"_result","tcl_result"))) {
673 // Yep. Use it instead of the default
674 f.code << tm << "\n";
675 } else if ((d->type != T_VOID) || (d->is_pointer)) {
676 if (!d->is_pointer) {
677
678 // Function returns a "value"
679
680 switch(d->type) {
681 // Is an integer
682 case T_BOOL:
683 case T_INT:
684 case T_SINT:
685 case T_SHORT:
686 case T_SSHORT:
687 case T_LONG :
688 case T_SLONG:
689 case T_SCHAR:
690 case T_UINT:
691 case T_USHORT:
692 case T_ULONG:
693 case T_UCHAR:
694 f.code << tab4 << "Tcl_SetIntObj(tcl_result,(long) _result);\n";
695 break;
696
697 // Is a single character. Assume we return it as a string
698 case T_CHAR :
699 f.code << tab4 << "Tcl_SetStringObj(tcl_result,&_result,1);\n";
700 break;
701
702 // Floating point number
703 case T_DOUBLE :
704 case T_FLOAT :
705 f.code << tab4 << "Tcl_SetDoubleObj(tcl_result,(double) _result);\n";
706 break;
707
708 // User defined type
709 case T_USER :
710
711 // Okay. We're returning malloced memory at this point.
712 // Probably dangerous, but who said safety was a good thing?
713
714 // f.add_local("char","resultchar[256]");
715 d->is_pointer++;
716 #ifdef OLD
717 f.code << tab4 << "SWIG_MakePtr(resultchar, (void *) _result,\"" << d->print_mangle() << "\");\n"
718 << tab4 << "Tcl_SetStringObj(tcl_result,resultchar,-1);\n";
719 #endif
720 f.code << tab4 << "SWIG_SetPointerObj(tcl_result,(void *) _result,\"" << d->print_mangle() << "\");\n";
721
722 d->is_pointer--;
723 break;
724
725 // Unknown type
726 default :
727 fprintf(stderr,"%s : Line %d: Unable to use return type %s in function %s.\n",
728 input_file, line_number, d->print_type(), name);
729 break;
730 }
731 } else {
732
733 // Is a pointer return type
734
735 if ((d->type == T_CHAR) && (d->is_pointer == 1)) {
736 // Return a character string
737 f.code << tab4 << "Tcl_SetStringObj(tcl_result,_result,-1);\n";
738 } else {
739 #ifdef OLD
740 f.add_local("char","resultchar[256]");
741 f.code << tab4 << "SWIG_MakePtr(resultchar, (void *) _result,\"" << d->print_mangle() << "\");\n"
742 << tab4 << "Tcl_SetStringObj(tcl_result,resultchar,-1);\n";
743 #endif
744
745 f.code << tab4 << "SWIG_SetPointerObj(tcl_result,(void *) _result,\"" << d->print_mangle() << "\");\n";
746 }
747 }
748 }
749
750
751 // Dump output argument code
752 f.code << outarg;
753
754 // Dump the argument cleanup code
755 f.code << cleanup;
756
757 // Look for any remaining cleanup
758
759 if (NewObject) {
760 if ((tm = typemap_lookup("newfree","tcl8",d,iname,"_result",""))) {
761 f.code << tm << "\n";
762 }
763 }
764
765 if ((tm = typemap_lookup("ret","tcl8",d,name,"_result",""))) {
766 // Yep. Use it instead of the default
767 f.code << tm << "\n";
768 }
769
770 // Wrap things up (in a manner of speaking)
771
772 f.code << tab4 << "return TCL_OK;\n}";
773
774 // Substitute the cleanup code
775 f.code.replace("$cleanup",cleanup);
776 f.code.replace("$name",iname);
777
778 // Dump out the function
779
780 f.print(f_wrappers);
781
782 // Now register the function with Tcl
783
784 fprintf(f_init,"\t Tcl_CreateObjCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name, iname, wname);
785
786 // If there's a documentation entry, produce a usage string
787
788 if (doc_entry) {
789
790 static DocEntry *last_doc_entry = 0;
791
792 // Use usage as description
793 doc_entry->usage << usage;
794
795 // Set the cinfo field to specific a return type
796
797 if (last_doc_entry != doc_entry) {
798 doc_entry->cinfo << "returns " << d->print_type();
799 last_doc_entry = doc_entry;
800 }
801 }
802 }
803
804 // -----------------------------------------------------------------------
805 // TCL8::link_variable(char *name, char *iname, DataType *t,
806 // int ex)
807 //
808 // Create a TCL link to a variable.
809 // -----------------------------------------------------------------------
810
811 void TCL8::link_variable(char *name, char *iname, DataType *t)
812 {
813
814 String s;
815 char *tm, *tm1;
816
817 // See if there were any typemaps
818
819 tm = typemap_lookup("varin","tcl8",t,name,"","");
820 tm1 = typemap_lookup("varout","tcl8",t,name,"","");
821 if (tm || tm1) {
822 fprintf(stderr,"%s : Line %d. Warning. varin/varout typemap methods not supported.",
823 input_file, line_number);
824 }
825
826 // Check the datatype. Must be a valid Tcl type (there aren't many)
827
828 if (((t->type == T_INT) && (!t->is_pointer)) ||
829 ((t->type == T_UINT) && (!t->is_pointer)) ||
830 ((t->type == T_SINT) && (!t->is_pointer)) ||
831 ((t->type == T_DOUBLE) && (!t->is_pointer)) ||
832 ((t->type == T_BOOL) && (!t->is_pointer)) ||
833 ((t->type == T_CHAR) && (t->is_pointer == 1))) {
834
835 // This is a valid TCL type.
836
837 if (t->type == T_UINT)
838 fprintf(stderr,"%s : Line %d : ** Warning. Linkage of unsigned type may be unsafe.\n",
839 input_file, line_number);
840
841 // Now add symbol to the TCL interpreter
842
843 switch(t->type) {
844 case T_CHAR :
845 if (t->arraystr) {
846 // Is an array. We have to do something different
847 fprintf(f_wrappers,"static char *tclvar%s = %s;\n",name,name);
848 s << "(char *) &tclvar" << name << ", TCL_LINK_STRING";
849 } else {
850 s << "(char *) &" << name << ", TCL_LINK_STRING";
851 }
852 break;
853 case T_BOOL:
854 case T_INT :
855 case T_UINT:
856 case T_SINT:
857 s << "(char *) &" << name << ", TCL_LINK_INT";
858 break;
859 case T_DOUBLE :
860 s << "(char *) &" << name << ", TCL_LINK_DOUBLE";
861 break;
862 default :
863 fprintf(f_init,"Fatal error. Internal error (Tcl:link_variable)\n");
864 break;
865 }
866
867 if (Status & STAT_READONLY)
868 s << " | TCL_LINK_READ_ONLY);\n";
869 else
870 s << ");\n";
871
872 fprintf(f_init,"\t Tcl_LinkVar(%s, SWIG_prefix \"%s\", %s",interp_name, iname, s.get());
873
874 // Make a usage string for it
875
876 if (doc_entry) {
877 doc_entry->usage << usage_var(iname,t);
878 doc_entry->cinfo = "";
879 doc_entry->cinfo << "Global : " << t->print_type() << " " << name;
880 }
881 } else {
882
883 // Have some sort of "other" type.
884 // We're going to emit some functions to set/get it's value instead
885
886 emit_set_get(name,iname, t);
887 if (doc_entry) {
888 doc_entry->cinfo = "";
889 doc_entry->cinfo << "Global : " << t->print_type() << " " << iname;
890 }
891
892 // If shadow classes are enabled and we have a user-defined type
893 // that we know about, create a command for it.
894
895 if (shadow) {
896 if ((t->type == T_USER) && (t->is_pointer < 1)) {
897 // See if the datatype is in our hash table
898 if (hash.lookup(t->name)) {
899 // Yep. Try to create a command for it
900
901 postinit << tab4 << "{\n"
902 << tab8 << "char cmd[] = \""
903 << (char *) hash.lookup(t->name) << " " << iname << " -this ["
904 << iname << "_get ]\";\n"
905 << tab8 << "Tcl_GlobalEval(interp,cmd);\n"
906 << tab4 << "}\n";
907 }
908 }
909 }
910 }
911 }
912
913 // -----------------------------------------------------------------------
914 // TCL8::declare_const(char *name, char *iname, DataType *type, char *value)
915 //
916 // Makes a constant. Really just creates a variable and links to it.
917 // Tcl variable linkage allows read-only variables so we'll use that
918 // instead of just creating a Tcl variable.
919 // ------------------------------------------------------------------------
920
921 void TCL8::declare_const(char *name, char *, DataType *type, char *value) {
922
923 int OldStatus = Status; // Save old status flags
924 DataType *t;
925 char var_name[256];
926 char *tm;
927 String rvalue;
928 Status = STAT_READONLY; // Enable readonly mode.
929
930 // Make a static variable;
931
932 sprintf(var_name,"_wrap_const_%s",name);
933
934 // See if there's a typemap
935 rvalue = value;
936 if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
937 rvalue << "\"";
938 "\"" >> rvalue;
939 }
940 if ((type->type == T_CHAR) && (type->is_pointer == 0)) {
941 rvalue << "'";
942 "'" >> rvalue;
943 }
944 if ((tm = typemap_lookup("const","tcl8",type,name,rvalue.get(),name))) {
945 // Yep. Use it instead of the default
946 fprintf(f_init,"%s\n",tm);
947 } else {
948
949 // Create variable and assign it a value
950
951 if (type->is_pointer == 0) {
952 switch(type->type) {
953 case T_BOOL: case T_INT: case T_SINT: case T_DOUBLE:
954 fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
955 link_variable(var_name,name,type);
956 break;
957 case T_SHORT:
958 case T_LONG:
959 case T_SSHORT:
960 case T_SCHAR:
961 case T_SLONG:
962 fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
963 fprintf(f_header,"static char *%s_char;\n", var_name);
964 if (CPlusPlus)
965 fprintf(f_init,"\t %s_char = new char[32];\n",var_name);
966 else
967 fprintf(f_init,"\t %s_char = (char *) malloc(32);\n",var_name);
968
969 fprintf(f_init,"\t sprintf(%s_char,\"%%ld\", (long) %s);\n", var_name, var_name);
970 sprintf(var_name,"%s_char",var_name);
971 t = new DataType(T_CHAR);
972 t->is_pointer = 1;
973 link_variable(var_name,name,t);
974 delete t;
975 break;
976 case T_UINT:
977 case T_USHORT:
978 case T_ULONG:
979 case T_UCHAR:
980 fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
981 fprintf(f_header,"static char *%s_char;\n", var_name);
982 if (CPlusPlus)
983 fprintf(f_init,"\t %s_char = new char[32];\n",var_name);
984 else
985 fprintf(f_init,"\t %s_char = (char *) malloc(32);\n",var_name);
986
987 fprintf(f_init,"\t sprintf(%s_char,\"%%lu\", (unsigned long) %s);\n", var_name, var_name);
988 sprintf(var_name,"%s_char",var_name);
989 t = new DataType(T_CHAR);
990 t->is_pointer = 1;
991 link_variable(var_name,name,t);
992 delete t;
993 break;
994 case T_FLOAT:
995 type->type = T_DOUBLE;
996 strcpy(type->name,"double");
997 fprintf(f_header,"static %s %s = %s (%s);\n", type->print_type(), var_name, type->print_cast(), value);
998 link_variable(var_name,name,type);
999 break;
1000
1001 case T_CHAR:
1002 type->is_pointer++;
1003 fprintf(f_header,"static %s %s = \"%s\";\n", type->print_type(), var_name, value);
1004 link_variable(var_name,name,type);
1005 type->is_pointer--;
1006 break;
1007 default:
1008 fprintf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number);
1009 break;
1010 }
1011 } else {
1012 // Have some sort of pointer value here
1013 if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
1014 // Character string
1015 fprintf(f_header,"static %s %s = \"%s\";\n", type->print_type(), var_name, value);
1016 link_variable(var_name,name,type);
1017 } else {
1018 // Something else. Some sort of pointer value
1019 fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
1020 fprintf(f_header,"static char *%s_char;\n", var_name);
1021 if (CPlusPlus)
1022 fprintf(f_init,"\t %s_char = new char[%d];\n",var_name,(int) strlen(type->print_mangle())+ 20);
1023 else
1024 fprintf(f_init,"\t %s_char = (char *) malloc(%d);\n",var_name, (int) strlen(type->print_mangle())+ 20);
1025
1026 t = new DataType(T_CHAR);
1027 t->is_pointer = 1;
1028 fprintf(f_init,"\t SWIG_MakePtr(%s_char, (void *) %s,\"%s\");\n",
1029 var_name, var_name, type->print_mangle());
1030 sprintf(var_name,"%s_char",var_name);
1031 link_variable(var_name,name,t);
1032 delete t;
1033 }
1034 }
1035 }
1036
1037 // Create a documentation entry for this
1038
1039 if (doc_entry) {
1040 doc_entry->usage = ""; // Destroy any previous information from linking
1041 doc_entry->usage << usage_const(name, type, value);
1042 doc_entry->cinfo = "";
1043 doc_entry->cinfo << "Constant : " << type->print_type();
1044 }
1045
1046 Status = OldStatus;
1047 }
1048
1049 // ----------------------------------------------------------------------
1050 // TCL8::usage_var(char *iname, DataType *t, char **s)
1051 //
1052 // Produces a usage string for a tcl variable. Stores it in s
1053 // ----------------------------------------------------------------------
1054
1055 char *TCL8::usage_var(char *iname, DataType *t) {
1056
1057 static char temp[1024];
1058
1059 if (!nspace) {
1060 sprintf(temp,"$%s%s", prefix, iname);
1061 } else {
1062 sprintf(temp,"%s::%s", ns_name, iname);
1063 }
1064 if (!(((t->type == T_INT) && (!t->is_pointer)) ||
1065 ((t->type == T_UINT) && (!t->is_pointer)) ||
1066 ((t->type == T_DOUBLE) && (!t->is_pointer)) ||
1067 ((t->type == T_BOOL) && (!t->is_pointer)) ||
1068 ((t->type == T_CHAR) && (t->is_pointer)))) {
1069 /* We emitted a pair of set/get functions instead. Doc will be generated for that */
1070 return temp;
1071 }
1072 return temp;
1073 }
1074
1075
1076
1077 // ---------------------------------------------------------------------------
1078 // char *TCL8::usage_string(char *iname, DataType *t, ParmList *l),
1079 //
1080 // Generates a generic usage string for a Tcl function.
1081 // ---------------------------------------------------------------------------
1082
1083 char * TCL8::usage_string(char *iname, DataType *, ParmList *l) {
1084
1085 static String temp;
1086 Parm *p;
1087 int i, numopt,pcount;
1088
1089 temp = "";
1090 temp << iname << " ";
1091
1092 /* Now go through and print parameters */
1093 i = 0;
1094 pcount = l->nparms;
1095 numopt = l->numopt();
1096 p = l->get_first();
1097 while (p != 0) {
1098
1099 // Only print an argument if not ignored
1100
1101 if (!typemap_check("ignore","tcl8",p->t,p->name)) {
1102 if (i >= (pcount-numopt))
1103 temp << "?";
1104
1105 /* If parameter has been named, use that. Otherwise, just print a type */
1106
1107 if ((p->t->type != T_VOID) || (p->t->is_pointer)) {
1108 if (strlen(p->name) > 0) {
1109 temp << p->name;
1110 }
1111 else {
1112 temp << "{ " << p->t->print_type() << " }";
1113 }
1114 }
1115 if (i >= (pcount-numopt))
1116 temp << "?";
1117 temp << " ";
1118 i++;
1119 }
1120 p = l->get_next();
1121 }
1122 return temp;
1123 }
1124
1125 // ---------------------------------------------------------------------------
1126 // char *TCL8::usage_func(char *iname, DataType *t, ParmList *l),
1127 //
1128 // Produces a usage string for a function in Tcl
1129 // ---------------------------------------------------------------------------
1130
1131 char * TCL8::usage_func(char *iname, DataType *t, ParmList *l) {
1132
1133 String temp;
1134
1135 if (nspace) {
1136 temp << ns_name << "::" << iname;
1137 } else {
1138 temp << prefix << iname;
1139 }
1140 return usage_string(temp,t,l);
1141 }
1142
1143 // -----------------------------------------------------------------
1144 // TCL8::usage_const(char *name, DataType *type, char *value)
1145 // char **s)
1146 //
1147 // Makes a usage string and returns it
1148 // -----------------------------------------------------------------
1149
1150 char *TCL8::usage_const(char *name, DataType *, char *value) {
1151 static String temp;
1152 temp = "";
1153 if (nspace) {
1154 temp << ns_name << "::" << name << " = " << value;
1155 } else {
1156 temp << "$" << prefix << name << " = " << value;
1157 }
1158 return temp.get();
1159 }
1160
1161 // -------------------------------------------------------------------
1162 // TCL8::add_native(char *name, char *funcname)
1163 //
1164 // This adds an already written Tcl wrapper function to our
1165 // initialization function.
1166 // -------------------------------------------------------------------
1167
1168
1169 void TCL8::add_native(char *name, char *funcname) {
1170
1171 fprintf(f_init,"\t Tcl_CreateCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name, name, funcname);
1172
1173 if (doc_entry) {
1174 if (nspace)
1175 doc_entry->usage << ns_name << "::" << name << " args";
1176 else
1177 doc_entry->usage << prefix << name << " args";
1178
1179 doc_entry->cinfo << "Native method : " << funcname;
1180 }
1181
1182 }
1183
1184 // -------------------------------------------------------------------
1185 // TCL8::pragma(char *lname, char *name, char *value)
1186 //
1187 // Handle pragmas.
1188 // --------------------------------------------------------------------
1189
1190 void TCL8::pragma(char *, char *, char *) {
1191
1192 }
1193
1194 // ---------------------------------------------------------------------
1195 // C++ Handling
1196 //
1197 // The following functions provide some support for C++ classes and
1198 // C structs.
1199 // ---------------------------------------------------------------------
1200
1201 void TCL8::cpp_open_class(char *classname, char *rename, char *ctype, int strip) {
1202
1203 this->Language::cpp_open_class(classname,rename,ctype,strip);
1204
1205 if (shadow) {
1206
1207 config = "";
1208 cget = "";
1209 methods = "";
1210 options = "";
1211 config_options = "";
1212 methodnames = "";
1213
1214 have_constructor = 0;
1215 have_destructor = 0;
1216 have_methods = 0;
1217 have_config = 0;
1218 have_cget = 0;
1219
1220 if (rename)
1221 class_name = copy_string(rename);
1222 else
1223 class_name = copy_string(classname);
1224
1225 base_class = (char *) 0;
1226 if (!strip) {
1227 class_type = new char[strlen(ctype)+2];
1228 sprintf(class_type,"%s ", ctype);
1229 } else
1230 class_type = "";
1231
1232 real_classname = copy_string(classname);
1233 }
1234 }
1235
1236 void TCL8::cpp_close_class() {
1237 String code,temp;
1238 DataType *t;
1239
1240 this->Language::cpp_close_class();
1241 if (shadow) {
1242
1243 t = new DataType;
1244 sprintf(t->name,"%s%s", class_type, real_classname);
1245 t->type = T_USER;
1246 t->is_pointer = 1;
1247
1248 // Note : The object oriented interface is defined by three files
1249 // delcmd8.swg - Object deletion wrapper
1250 // methodcmd8.swg - Method invocation command
1251 // objcmd8.swg - Command to create a new object
1252 //
1253 // These files are located in the SWIG library. This module
1254 // grabs the files and performs marker replacements to
1255 // build the wrapper function.
1256
1257 // Generate a Tcl function for object destruction
1258
1259 if (have_destructor) {
1260 code << delcmd;
1261 }
1262
1263 // Dump out method code
1264 code << methodcmd;
1265
1266 // Dump out object creation command
1267 code << objcmd;
1268
1269 // Now perform marker replacements
1270 code.replace("@CLASS@",class_name);
1271 temp = "";
1272 temp << name_destroy(class_name);
1273 code.replace("@DESTRUCTOR@",temp);
1274 code.replace("@CLASSTYPE@",t->print_type());
1275 "configure " >> methodnames;
1276 "cget " >> methodnames;
1277 code.replace("@METHODLIST@", methodnames);
1278 code.replace("@CLASSMANGLE@",t->print_mangle());
1279 code.replace("@METHODS@",methods);
1280 code.replace("@CONFIGMETHODS@",config);
1281 code.replace("@CGETMETHODS@",cget);
1282 if (have_constructor) {
1283 temp = "";
1284 temp << name_wrapper(name_construct(class_name),prefix);
1285 } else {
1286 temp = "0";
1287 }
1288 code.replace("@TCLCONSTRUCTOR@",temp);
1289 code.replace("@CONFIGLIST@",config_options);
1290 code.replace("@CGETLIST@",options);
1291 if (have_destructor) {
1292 temp = "TclDelete";
1293 temp << class_name;
1294 } else {
1295 temp = "0";
1296 }
1297 code.replace("@TCLDESTRUCTOR@",temp);
1298 fprintf(f_wrappers,"%s\n", code.get());
1299
1300 fprintf(f_init,"\t Tcl_CreateObjCommand(interp,SWIG_prefix \"%s\",Tcl%sCmd, (ClientData) NULL, NULL);\n", class_name, class_name);
1301 }
1302 }
1303
1304 void TCL8::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) {
1305
1306 char *realname;
1307 String temp;
1308 char *rname;
1309
1310 this->Language::cpp_member_func(name,iname,t,l);
1311
1312 if (shadow) {
1313 if (iname)
1314 realname = iname;
1315 else
1316 realname = name;
1317
1318 // Add stubs for this member to our class handler function
1319
1320 if (have_methods)
1321 methods << tab4 << "else ";
1322 else
1323 methods << tab4;
1324
1325 temp = "";
1326 temp << name_member(realname,class_name);
1327 rname = (char *) repeatcmd.lookup(temp);
1328 if (!rname)
1329 rname = name_wrapper(temp.get(),prefix);
1330
1331 methods << "if (strcmp(_str,\"" << realname << "\") == 0) {\n"
1332 << tab4 << tab4 << "cmd = " << rname << ";\n"
1333 << tab4 << "}";
1334
1335 have_methods = 1;
1336 methodnames << realname << " ";
1337
1338 if (doc_entry) {
1339 doc_entry->usage = "";
1340 doc_entry->usage << usage_string(realname,t,l);
1341 }
1342 }
1343 }
1344
1345 void TCL8::cpp_variable(char *name, char *iname, DataType *t) {
1346 char *realname;
1347 String temp;
1348 char *rname;
1349
1350 this->Language::cpp_variable(name, iname, t);
1351
1352 if (shadow) {
1353 if (iname)
1354 realname = iname;
1355 else
1356 realname = name;
1357
1358 char *bc = class_name;
1359
1360 // Write config code
1361
1362 if (!(Status & STAT_READONLY)) {
1363 if (!have_config) {
1364 config << tab8 << tab8;
1365 } else {
1366 config << " else ";
1367 }
1368
1369 // Try to figure out if there is already a wrapper for this
1370
1371 temp = "";
1372 temp << name_set(name_member(realname,bc));
1373 rname = (char *) repeatcmd.lookup(temp);
1374 if (!rname)
1375 rname = name_wrapper(temp.get(),prefix);
1376
1377 config << "if (strcmp(_str,\"-" << realname << "\") == 0) {\n"
1378 << tab8 << tab8 << tab4 << "cmd = " << rname << ";\n"
1379 << tab8 << tab8 << "} ";
1380
1381 have_config = 1;
1382 }
1383
1384 // Write cget code
1385
1386 if (!have_cget) {
1387 cget << tab8 << tab8;
1388 } else {
1389 cget << " else ";
1390 }
1391
1392
1393 // Try to figure out if there is a wrapper for this function
1394 temp = "";
1395 temp << name_get(name_member(realname,bc));
1396 rname = (char *) repeatcmd.lookup(temp);
1397 if (!rname)
1398 rname = name_wrapper(temp.get(),prefix);
1399
1400 cget << "if (strcmp(_str,\"-" << realname << "\") == 0) {\n"
1401 << tab8 << tab8 << tab4 << "cmd = " << rname << ";\n"
1402 << tab8 << tab8 << "} ";
1403 have_cget = 1;
1404
1405 options << "-" << realname << " ";
1406 if (!(Status & STAT_READONLY)) {
1407 config_options << "-" << realname << " ";
1408 }
1409 if (doc_entry){
1410 doc_entry->usage = "";
1411 doc_entry->usage << "-" << realname << "\n";
1412 }
1413 }
1414 }
1415
1416 void TCL8::cpp_constructor(char *name, char *iname, ParmList *l) {
1417 this->Language::cpp_constructor(name,iname,l);
1418
1419 if (shadow) {
1420 if ((!have_constructor) && (doc_entry)) {
1421 doc_entry->usage = "";
1422 doc_entry->usage << class_name << usage_string(" name",0,l);
1423 }
1424 have_constructor = 1;
1425 }
1426 }
1427 void TCL8::cpp_destructor(char *name, char *newname) {
1428 this->Language::cpp_destructor(name,newname);
1429 if (shadow) {
1430 if (!have_destructor) {
1431 if (doc_entry) {
1432 doc_entry->usage = "rename obj {}";
1433 }
1434 }
1435 have_destructor = 1;
1436 }
1437 }
1438
1439 void TCL8::cpp_inherit(char **baseclass, int) {
1440 this->Language::cpp_inherit(baseclass);
1441 }
1442
1443 void TCL8::cpp_declare_const(char *name, char *iname, DataType *type, char *value) {
1444 this->Language::cpp_declare_const(name,iname,type,value);
1445 }
1446
1447 // --------------------------------------------------------------------------------
1448 // TCL8::add_typedef(DataType *t, char *name)
1449 //
1450 // This is called whenever a typedef is encountered. When shadow classes are
1451 // used, this function lets us discovered hidden uses of a class. For example :
1452 //
1453 // struct FooBar {
1454 // ...
1455 // }
1456 //
1457 // typedef FooBar *FooBarPtr;
1458 //
1459 // --------------------------------------------------------------------------------
1460
1461 void TCL8::add_typedef(DataType *t, char *name) {
1462
1463 if (!shadow) return;
1464
1465 // First check to see if there aren't too many pointers
1466
1467 if (t->is_pointer > 1) return;
1468 if (hash.lookup(name)) return; // Already added
1469
1470 // Now look up the datatype in our shadow class hash table
1471
1472 if (hash.lookup(t->name)) {
1473
1474 // Yep. This datatype is in the hash
1475 // Put this types 'new' name into the hash
1476 hash.add(name,copy_string((char *) hash.lookup(t->name)));
1477 }
1478 }
1479
1480 // -----------------------------------------------------------------------
1481 // TCL8::cpp_class_decl(char *name, char *rename, char *type)
1482 //
1483 // Treatment of an empty class definition. Used to handle
1484 // shadow classes across modules.
1485 // -----------------------------------------------------------------------
1486
1487 void TCL8::cpp_class_decl(char *name, char *rename, char *type) {
1488 char temp[256];
1489 this->Language::cpp_class_decl(name,rename, type);
1490
1491 if (shadow) {
1492 hash.add(name,copy_string(rename));
1493 // Add full name of datatype to the hash table
1494 if (strlen(type) > 0) {
1495 sprintf(temp,"%s %s", type, name);
1496 hash.add(temp,copy_string(rename));
1497 }
1498 }
1499 }