Add a flag to provide timer for the case of no objs in Meta-Balancer
[charm.git] / src / xlat-i / xi-symbol.C
1 #include <list>
2 using std::list;
3 #include <algorithm>
4 using std::for_each;
5 #include <stdlib.h>
6 #include "xi-symbol.h"
7 #include "CParsedFile.h"
8 #include <ctype.h> // for tolower()
9 #include <iostream>
10 using std::cerr;
11 using std::cout;
12 using std::endl;
13
14 #if ! CMK_BOOL_DEFINED
15 typedef enum {false = 0, true = 1} bool;
16 #endif
17
18 #include <fstream>
19
20 namespace xi {
21    
22 int fortranMode;
23 int internalMode;
24 const char *cur_file;
25 const char *python_doc;
26
27 const char *Prefix::Proxy="CProxy_";
28 const char *Prefix::ProxyElement="CProxyElement_";
29 const char *Prefix::ProxySection="CProxySection_";
30 const char *Prefix::Message="CMessage_";
31 const char *Prefix::Index="CkIndex_";
32 const char *Prefix::Python="CkPython_";
33
34
35 //Fatal error function
36 void die(const char *why,int line)
37 {
38         if (line==-1)
39                 fprintf(stderr,"%s: Charmxi fatal error> %s\n",cur_file,why);
40         else
41                 fprintf(stderr,"%s:%d: Charmxi fatal error> %s\n",cur_file,line,why);
42         exit(1);
43 }
44
45 // Make the name lower case
46 char* fortranify(const char *s, const char *suff1="", const char *suff2="", const char *suff3="")
47 {
48   int i, len1 = strlen(s), len2 = strlen(suff1),
49          len3 = strlen(suff2), len4 = strlen(suff3);
50   int c = len1+len2+len3+len4;
51   char str[1024], strUpper[1024];
52   strcpy(str, s);
53   strcat(str, suff1);
54   strcat(str, suff2);
55   strcat(str, suff3);
56   for(i = 0; i < c+1; i++)
57     str[i] = tolower(str[i]);
58   for(i = 0; i < c+1; i++)
59     strUpper[i] = toupper(str[i]);
60   char *retVal;
61   retVal = new char[2*c+20];
62   strcpy(retVal, "FTN_NAME(");
63   strcat(retVal, strUpper);
64   strcat(retVal, ",");
65   strcat(retVal, str);
66   strcat(retVal, ")");
67
68   return retVal;
69 }
70
71 void templateGuardBegin(bool templateOnly, XStr &str) {
72   if (templateOnly)
73     str << "#ifdef " << "CK_TEMPLATES_ONLY\n";
74   else
75     str << "#ifndef " << "CK_TEMPLATES_ONLY\n";
76 }
77 void templateGuardEnd(XStr &str) {
78   str << "#endif /* CK_TEMPLATES_ONLY */\n";
79 }
80
81 Value::Value(const char *s)
82 {
83   factor = 1;
84   val=s;
85   if(val == 0 || strlen(val)==0 ) return;
86   char *v = (char *)malloc(strlen(val)+5);
87   strcpy(v,val);
88   int pos = strlen(v)-1;
89   if(v[pos]=='K' || v[pos]=='k') {
90     v[pos] = '\0';
91     factor = 1024;
92   }
93   if(v[pos]=='M' || v[pos]=='m') {
94     v[pos] = '\0';
95     factor = 1024*1024;
96   }
97   val=v;
98 }
99
100
101 int
102 Value::getIntVal(void)
103 {
104   if(val==0 || strlen(val)==0) return 0;
105   return (atoi((const char *)val)*factor);
106 }
107
108
109 /**
110    Apply fn_ on each Construct in the list l, passing it arg as
111    the target. If between_ is passed, do that to arg between each
112    element.
113  */
114 template<typename T, typename U, typename A>
115 class perElemGenC
116 {
117     void (U::*fn)(A);
118     void (*between)(A);
119     A arg;
120 public:
121     perElemGenC(list<T*> &l,
122                A arg_,
123                void (U::*fn_)(A),
124                void (*between_)(A) = NULL)
125         : fn(fn_), between(between_), arg(arg_)
126         {
127             for_each(l.begin(), l.end(), *this);
128         }
129     void operator()(T* m)
130         {
131             if (m)
132             {
133                 (m->*fn)(arg);
134                 if (between)
135                     between(arg);
136             }
137         }
138 };
139
140 template<typename T, typename U, typename A>
141 void perElemGen(list<T*> &l, A& arg_, void (U::*fn_)(A&),
142 // Sun Studio 7 (C++ compiler version 5.4) can't handle this
143 //              void (*between_)(A&) = NULL)
144                 void (*between_)(A&))
145 {
146     perElemGenC<T, U, A&>(l, arg_, fn_, between_);
147 }
148
149 template<typename T, typename U, typename A>
150 void perElemGen(list<T*> &l, A& arg_, void (U::*fn_)(A&))
151 {
152     perElemGenC<T, U, A&>(l, arg_, fn_, NULL);
153 }
154
155 template<typename T, typename U, typename A>
156 void perElemGen(list<T*> &l, A* arg_, void (U::*fn_)(A*),
157 // See above
158 //              void (*between_)(A*) = NULL)
159                 void (*between_)(A*))
160 {
161     perElemGenC<T, U, A*>(l, arg_, fn_, between_);
162 }
163
164 template<typename T, typename U, typename A>
165 void perElemGen(list<T*> &l, A* arg_, void (U::*fn_)(A*))
166 {
167     perElemGenC<T, U, A*>(l, arg_, fn_, NULL);
168 }
169
170 /**
171    Apply fn_ on each non-NULL element in the list l.
172    If between_ is passed, do that between each element.
173  */
174 template<typename T, typename U>
175 class perElemC
176 {
177     void (U::*fn)();
178 public:
179     perElemC(list<T*> &l,
180                void (U::*fn_)())
181         : fn(fn_)
182         {
183             for_each(l.begin(), l.end(), *this);
184         }
185     void operator()(T* m)
186         {
187             if (m) {
188                 (m->*fn)();
189             }
190         }
191 };
192
193 template<typename T, typename U>
194 void perElem(list<T*> &l, void (U::*fn_)())
195 {
196     perElemC<T, U>(l, fn_);
197 }
198
199 void newLine(XStr &str)
200 {
201     str << endx;
202 }
203
204 ConstructList::ConstructList(int l, Construct *c, ConstructList *n)
205 {
206     constructs.push_back(c);
207     if (n)
208         constructs.insert(constructs.end(),
209                           n->constructs.begin(), n->constructs.end());
210     line = l;
211 }
212
213 void
214 ConstructList::setExtern(int e)
215 {
216   Construct::setExtern(e);
217   perElemGen(constructs, e, &Construct::setExtern);
218 }
219
220 void
221 ConstructList::setModule(Module *m)
222 {
223   Construct::setModule(m);
224   perElemGen(constructs, m, &Construct::setModule);
225 }
226
227 void
228 ConstructList::print(XStr& str)
229 {
230     perElemGen(constructs, str, &Construct::print);
231 }
232
233 int ConstructList::genAccels_spe_c_funcBodies(XStr& str) {
234     int rtn = 0;
235     for (list<Construct *>::iterator i = constructs.begin();
236          i != constructs.end(); ++i)
237         if (*i) rtn += (*i)->genAccels_spe_c_funcBodies(str);
238     return rtn;
239 }
240 void ConstructList::genAccels_spe_c_regFuncs(XStr& str) {
241     perElemGen(constructs, str, &Construct::genAccels_spe_c_regFuncs);
242 }
243 void ConstructList::genAccels_spe_c_callInits(XStr& str) {
244     perElemGen(constructs, str, &Construct::genAccels_spe_c_callInits);
245 }
246 void ConstructList::genAccels_spe_h_includes(XStr& str) {
247     perElemGen(constructs, str, &Construct::genAccels_spe_h_includes);
248 }
249 void ConstructList::genAccels_spe_h_fiCountDefs(XStr& str) {
250     perElemGen(constructs, str, &Construct::genAccels_spe_h_fiCountDefs);
251 }
252 void ConstructList::genAccels_ppe_c_regFuncs(XStr& str) {
253     perElemGen(constructs, str, &Construct::genAccels_ppe_c_regFuncs);
254 }
255
256
257 void
258 TParamList::print(XStr& str)
259 {
260   tparam->print(str);
261   if(next) {
262     str << ",";
263     next->print(str);
264   }
265 }
266
267 std::string TParamList::to_string()
268 {
269     XStr s;
270     print(s);
271     return s.get_string();
272 }
273
274
275 void
276 Type::genProxyName(XStr &str,forWhom forElement)
277 {
278   (void)str; (void)forElement;
279   die("type::genProxyName called (INTERNAL ERROR)");
280 }
281 void
282 Type::genIndexName(XStr &str)
283 {
284   (void)str;
285   die("type::genIndexName called (INTERNAL ERROR)");
286 }
287 void
288 Type::genMsgProxyName(XStr &str)
289 {
290   (void)str;
291   die("type::genMsgProxyName called (INTERNAL ERROR)");
292 }
293
294 void
295 NamedType::print(XStr& str)
296 {
297   if (scope) str << scope;
298   str << name;
299   if (tparams) str << "<"<<tparams<<" >";
300 }
301
302 void NamedType::genIndexName(XStr& str) { 
303     if (scope) str << scope;
304     str << Prefix::Index; 
305     str << name;
306     if (tparams) str << "<"<<tparams<<" >";
307 }
308
309 void NamedType::genMsgProxyName(XStr& str) { 
310     if (scope) str << scope;
311     str << Prefix::Message;
312     str << name;
313     if (tparams) str << "<"<<tparams<<" >";
314 }
315
316 void
317 PtrType::print(XStr& str)
318 {
319   type->print(str);
320   for(int i=0;i<numstars;i++)
321     str << "*";
322 }
323
324 void
325 TypeList::print(XStr& str)
326 {
327   type->print(str);
328   if(next) {
329     str << ", ";
330     next->print(str);
331   }
332 }
333
334 int TypeList::length(void) const
335 {
336   if (next) return next->length()+1;
337   else return 1;
338 }
339
340 MemberList::MemberList(Member *m, MemberList *n)
341 {
342     members.push_back(m);
343     if (n)
344         members.insert(members.end(), n->members.begin(), n->members.end());
345 }
346
347 MemberList::MemberList(list<Entry*>&l)
348 {
349   members.insert(members.begin(), l.begin(), l.end());
350   l.clear();
351 }
352
353 void
354 MemberList::print(XStr& str)
355 {
356     perElemGen(members, str, &Member::print);
357 }
358
359 void
360 MemberList::appendMember(Member *m)
361 {
362     members.push_back(m);
363 }
364
365 int MemberList::genAccels_spe_c_funcBodies(XStr& str) {
366     int rtn = 0;
367     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
368         if (*i)
369             rtn += (*i)->genAccels_spe_c_funcBodies(str);
370     return rtn;
371 }
372 void MemberList::genAccels_spe_c_regFuncs(XStr& str) {
373     perElemGen(members, str, &Member::genAccels_spe_c_regFuncs);
374 }
375 void MemberList::genAccels_spe_c_callInits(XStr& str) {
376     perElemGen(members, str, &Member::genAccels_spe_c_callInits);
377 }
378 void MemberList::genAccels_spe_h_includes(XStr& str) {
379     perElemGen(members, str, &Member::genAccels_spe_h_includes);
380 }
381 void MemberList::genAccels_spe_h_fiCountDefs(XStr& str) {
382     perElemGen(members, str, &Member::genAccels_spe_h_fiCountDefs);
383 }
384 void MemberList::genAccels_ppe_c_regFuncs(XStr& str) {
385     perElemGen(members, str, &Member::genAccels_ppe_c_regFuncs);
386 }
387
388
389 void
390 Chare::print(XStr& str)
391 {
392   if(external)
393     str << "extern ";
394   if(templat)
395     templat->genSpec(str);
396
397   str << chareTypeName()<<" "<<type;
398   if(bases) { str << ": "; bases->print(str); }
399   if(list) {
400     str << "{\n"; list->print(str); str << "};\n";
401   } else {
402     str << ";\n";
403   }
404 }
405
406 void
407 Message::print(XStr& str)
408 {
409   if(external)
410     str << "extern ";
411   if(templat)
412     templat->genSpec(str);
413   str << "message ";
414   type->print(str);
415   printVars(str);
416   str << ";\n";
417 }
418
419 void
420 TType::print(XStr& str)
421 {
422   str << "class ";
423   type->print(str);
424   if(init) {
425     str << "=";
426     init->print(str);
427   }
428 }
429
430 void
431 TName::print(XStr& str)
432 {
433   type->print(str);
434   str << " "<<name;
435   if(val) {
436     str << "=";
437     str << val;
438   }
439 }
440
441
442 void
443 TVarList::print(XStr& str)
444 {
445   tvar->print(str);
446   if(next) {
447     str << ", ";
448     next->print(str);
449   }
450 }
451
452 void
453 Template::print(XStr& str)
454 {
455   if(entity)
456     entity->print(str);
457 }
458
459 void
460 Entry::print(XStr& str)
461 {
462   if(isThreaded())
463     str << "threaded ";
464   if(isSync())
465     str << "sync ";
466   if(retType) {
467     retType->print(str);
468     str << " ";
469   }
470   str << name<<"(";
471   if(param)
472     param->print(str);
473   str << ")";
474   if(stacksize) {
475     str << " stacksize = ";
476     stacksize->print(str);
477   }
478   str << ";\n";
479 }
480
481 void
482 Module::print(XStr& str)
483 {
484   if(external)
485     str << "extern ";
486   str << "module "<<name;
487   if(clist) {
488     str << " {\n";
489     clist->print(str);
490     str << "}\n";
491   } else {
492     str << ";\n";
493   }
494 }
495
496 void Module::check() {
497   if (clist)
498     clist->check();
499 }
500
501 void ConstructList::check() {
502   perElem(constructs, &Construct::check);
503 }
504
505 void Scope::check() {
506   if (contents_)
507     contents_->check();
508 }
509
510 void Entry::check() {
511   if (!external) {
512     if(isConstructor() && retType && !retType->isVoid())
513       die("Constructors cannot return a value",line);
514
515     if (!isConstructor() && !retType)
516       die("Non-constructor entry methods must specify a return type (probably void)", line);
517   }
518 }
519
520 void Chare::check() {
521   if (list)
522     list->check();
523 }
524
525 void MemberList::check() {
526   perElem(members, &Member::check);
527 }
528
529 void
530 Module::generate()
531 {
532   using std::ofstream;
533   XStr declstr, defstr;
534   XStr pubDeclStr, pubDefStr, pubDefConstr;
535
536   // DMK - Accel Support
537   #if CMK_CELL != 0
538   XStr accelstr_spe_c, accelstr_spe_h;
539   #endif
540
541   declstr <<
542   "#ifndef _DECL_"<<name<<"_H_\n"
543   "#define _DECL_"<<name<<"_H_\n"
544   "#include \"charm++.h\"\n"
545   "#include <memory>\n";
546   if (fortranMode) declstr << "#include \"charm-api.h\"\n";
547   if (clist) clist->genDecls(declstr);
548   declstr << "extern void _register"<<name<<"(void);\n";
549   if(isMain()) {
550     declstr << "extern \"C\" void CkRegisterMainModule(void);\n";
551   }
552   declstr << "#endif"<<endx;
553   // Generate the publish class if there are structured dagger connect entries
554   int connectPresent = 0;
555   if (clist) clist->genPub(pubDeclStr, pubDefStr, pubDefConstr, connectPresent);
556   if (connectPresent == 1) {
557      pubDeclStr << "};\n\n";
558      pubDefConstr <<"}\n\n";
559   }
560
561   // defstr << "#ifndef _DEFS_"<<name<<"_H_"<<endx;
562   // defstr << "#define _DEFS_"<<name<<"_H_"<<endx;
563   genDefs(defstr);
564   templateGuardBegin(false, defstr);
565   defstr <<
566   "void _register"<<name<<"(void)\n"
567   "{\n"
568   "  static int _done = 0; if(_done) return; _done = 1;\n";
569   if (clist) clist->genReg(defstr);
570   defstr << "}\n";
571   if(isMain()) {
572     if (fortranMode) defstr << "extern void _registerf90main(void);\n";
573     defstr << "extern \"C\" void CkRegisterMainModule(void) {\n";
574     if (fortranMode) { // For Fortran90
575       defstr << "  // FORTRAN\n";
576       defstr << "  _registerf90main();\n";
577     }
578     defstr <<
579     "  _register"<<name<<"();\n"
580     "}\n";
581   }
582   templateGuardEnd(defstr);
583   // defstr << "#endif"<<endx;
584
585
586   // DMK - Accel Support
587   #if CMK_CELL != 0
588
589   /// Generate the SPE code file contents ///
590   accelstr_spe_c << "#ifndef __ACCEL_" << name << "_C__\n"
591                  << "#define __ACCEL_" << name << "_C__\n\n\n";
592   int numAccelEntries = genAccels_spe_c_funcBodies(accelstr_spe_c);
593   accelstr_spe_c << "\n\n#endif //__ACCEL_" << name << "_C__\n";
594
595   /// Generate the SPE header file contents ///
596   accelstr_spe_h << "#ifndef __ACCEL_" << name << "_H__\n"
597                  << "#define __ACCEL_" << name << "_H__\n\n\n";
598   genAccels_spe_h_includes(accelstr_spe_h);
599   accelstr_spe_h << "\n\n";
600   accelstr_spe_h << "#define MODULE_" << name << "_FUNC_INDEX_COUNT (" << numAccelEntries;
601   genAccels_spe_h_fiCountDefs(accelstr_spe_h);
602   accelstr_spe_h << ")\n\n\n";
603   accelstr_spe_h << "#endif //__ACCEL_" << name << "_H__\n";
604
605   #endif
606
607
608   XStr topname, botname;
609   topname<<name<<".decl.h";
610   botname<<name<<".def.h";
611   ofstream decl(topname.get_string()), def(botname.get_string());
612   if(!decl || !def) {
613     cerr<<"Cannot open "<<topname.get_string()<<"or "
614         <<botname.get_string()<<" for writing!!\n";
615     die("cannot create output files (check directory permissions)\n");
616   }
617   decl<<declstr.get_string();
618   def<<defstr.get_string();
619   if (connectPresent == 1) {
620     decl << pubDeclStr;
621     def << pubDefConstr;
622     def << pubDefStr;
623   }
624
625   // DMK - Accel Support
626   #if CMK_CELL != 0
627
628   /// Generate this module's code (actually create the files) ///
629   XStr accelname_c, accelname_h;
630   accelname_c << name << ".genSPECode.c";
631   accelname_h << name << ".genSPECode.h";
632   ofstream accel_c(accelname_c.get_string()), accel_h(accelname_h.get_string());
633   if (!accel_c) {
634     cerr << "Cannot open " << accelname_c.get_string() << " for writing!!\n";
635     die("Cannot create output files (check directory permissions)\n");
636   }
637   if (!accel_h) {
638     cerr << "Cannot open " << accelname_h.get_string() << " for writing!!\n";
639     die("Cannot create output files (check directory permissions)\n");
640   }
641   accel_c << accelstr_spe_c.get_string();
642   accel_h << accelstr_spe_h.get_string();
643   
644   // If this is the main module, generate the general C file and include this modules accel.h file
645   if (isMain()) {
646
647     XStr mainAccelStr_c;
648     mainAccelStr_c << "#include \"main__funcLookup__.genSPECode.h" << "\"\n"
649                    << "#include \"" << name << ".genSPECode.c" << "\"\n";
650     ofstream mainAccel_c("main__funcLookup__.genSPECode.c");
651     if (!mainAccel_c) {
652       cerr << "Cannot open main__funcLookup__.genSPECode.c for writing!!\n";
653       die("Cannot create output files (check directory permissions)");
654     }
655     mainAccel_c << mainAccelStr_c.get_string();
656
657     XStr mainAccelStr_h;
658     mainAccelStr_h << "#ifndef __MAIN_FUNCLOOKUP_H__\n"
659                    << "#define __MAIN_FUNCLOOKUP_H__\n\n"
660                    << "#include <spu_intrinsics.h>\n"
661                    << "#include <stdlib.h>\n"
662                    << "#include <stdio.h>\n"
663                    << "#include \"spert.h\"\n\n"
664                    << "#include \"simd.h\"\n"
665                    << "#include \"" << name << ".genSPECode.h" << "\"\n\n"
666                    << "#endif //__MAIN_FUNCLOOKUP_H__\n";
667     ofstream mainAccel_h("main__funcLookup__.genSPECode.h");
668     if (!mainAccel_h) {
669       cerr << "Cannot open main__funcLookup__.genSPECode.h for writing!!\n";
670       die("Cannot create output files (check directory permissions)");
671     }
672     mainAccel_h << mainAccelStr_h.get_string();
673
674   }
675
676   #endif
677 }
678
679 void
680 Module::preprocess()
681 {
682   if (clist!=NULL) clist->preprocess();
683 }
684
685 void
686 Module::genDepend(const char *cifile)
687 {
688   cout << name << ".decl.h " << name << ".def.h: "
689        << cifile << ".stamp" << endl;
690 }
691
692 void
693 ModuleList::print(XStr& str)
694 {
695     perElemGen(modules, str, &Module::print);
696 }
697
698 void
699 ModuleList::generate()
700 {
701   perElem(modules, &Module::generate);
702 }
703
704 void
705 ModuleList::check()
706 {
707   perElem(modules, &Module::check);
708 }
709
710 void
711 ModuleList::preprocess()
712 {
713   perElem(modules, &Module::preprocess);
714 }
715
716 void
717 ModuleList::genDepends(std::string ciFileBaseName)
718 {
719     perElemGen(modules, ciFileBaseName.c_str(), &Module::genDepend);
720 }
721
722 void
723 Readonly::print(XStr& str)
724 {
725   if(external)
726     str << "extern ";
727   str << "readonly ";
728   if(msg)
729     str << "message ";
730   type->print(str);
731   if(msg)
732     str << " *";
733   else
734     str << " ";
735   str << name;
736   if(dims)
737     dims->print(str);
738   str << ";\n";
739 }
740
741 void
742 MemberList::setChare(Chare *c)
743 {
744     perElemGen(members, c, &Member::setChare);
745 }
746
747 void
748 ConstructList::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
749 {
750     for (list<Construct*>::iterator i = constructs.begin(); 
751          i != constructs.end(); ++i)
752         if (*i) {
753             (*i)->genPub(declstr, defstr, defconstr, connectPresent);
754             declstr << endx;
755         }
756 }
757
758 void
759 ConstructList::genDecls(XStr& str)
760 {
761     perElemGen(constructs, str, &Construct::genDecls, newLine);
762 }
763
764 void
765 ConstructList::genDefs(XStr& str)
766 {
767     perElemGen(constructs, str, &Construct::genDefs, newLine);
768 }
769
770 void
771 ConstructList::genReg(XStr& str)
772 {
773     perElemGen(constructs, str, &Construct::genReg, newLine);
774 }
775
776 void
777 ConstructList::preprocess()
778 {
779   perElem(constructs, &Construct::preprocess);
780 }
781
782 XStr Chare::proxyName(int withTemplates)
783 {
784   XStr str;
785   str<<proxyPrefix()<<type;
786   if (withTemplates) str<<tvars();
787   return str;
788 }
789
790 XStr Chare::indexName(int withTemplates)
791 {
792   XStr str;
793   str<<Prefix::Index<<type;
794   if (withTemplates) str<<tvars();
795   return str;
796 }
797
798 XStr Chare::indexList()
799 {
800   // generating "int *index1, int *index2, int *index3"
801   XStr str;
802   if (!isArray()) { // Currently, only arrays are supported
803       cerr << (char *)baseName() << ": only chare arrays are currently supported\n";
804       exit(1);
805   }
806   XStr dim = ((Array*)this)->dim();
807   if (dim==(const char*)"1D")
808     str << "const int *index1";
809   else if (dim==(const char*)"2D")
810     str << "const int *index1, const int *index2";
811   else if (dim==(const char*)"3D")
812     str << "const int *index1, const int *index2, const int *index3";
813   else {
814       cerr << (char *)baseName() << ": only up to 3 dimension chare arrays are currently supported\n";
815       exit(1);
816   }
817   return str;
818 }
819
820 static const char *forWhomStr(forWhom w)
821 {
822   switch(w) {
823   case forAll: return Prefix::Proxy;
824   case forIndividual: return Prefix::ProxyElement;
825   case forSection: return Prefix::ProxySection;
826   case forIndex: return Prefix::Index;
827   case forPython: return "";
828   default: return NULL;
829   };
830 }
831
832 void NamedType::genProxyName(XStr& str,forWhom forElement)
833 {
834     const char *prefix=forWhomStr(forElement);
835     if (prefix==NULL)
836         die("Unrecognized forElement type passed to NamedType::genProxyName");
837     if (scope) str << scope;
838     str << prefix;
839     str << name;
840     if (tparams) str << "<"<<tparams<<" >";
841 }
842
843 void TypeList::genProxyNames(XStr& str, const char *prefix, const char *middle,
844                              const char *suffix, const char *sep,forWhom forElement)
845 {
846   if(type) {
847     str << prefix;
848     type->genProxyName(str,forElement);
849     if (middle!=NULL) {
850       str << middle;
851       type->genProxyName(str,forElement);
852     }
853     str << suffix;
854   }
855   if(next) {
856     str << sep;
857     next->genProxyNames(str, prefix, middle, suffix, sep,forElement);
858   }
859 }
860 void Chare::genProxyNames(XStr& str, const char *prefix,const char *middle,
861         const char *suffix, const char *sep)
862 {
863         bases->genProxyNames(str,prefix,middle,suffix,sep,forElement);
864 }
865 void Chare::genIndexNames(XStr& str, const char *prefix,const char *middle,
866         const char *suffix, const char *sep)
867 {
868         bases->genProxyNames(str,prefix,middle,suffix,sep,forIndex);
869 }
870 char *Chare::proxyPrefix(void)
871 {
872   return (char *)forWhomStr(forElement);
873 }
874
875 //Common multiple inheritance disambiguation code
876 void Chare::sharedDisambiguation(XStr &str,const XStr &super)
877 {
878     (void)super;
879     str << "\n    void ckDelegate(CkDelegateMgr *dTo,CkDelegateData *dPtr=NULL)"
880         << "\n    { ";
881     genProxyNames(str,"      ",NULL,"::ckDelegate(dTo,dPtr); ","");
882     str << "}"
883         << "\n    void ckUndelegate(void)"
884         << "\n    { ";
885     genProxyNames(str,"      ",NULL,"::ckUndelegate(); ","");
886     str << "}"
887         << "\n    void pup(PUP::er &p)"
888         << "\n    { ";
889     genProxyNames(str,"      ",NULL,"::pup(p); ","");
890     str << "}";
891     if (isPython()) {
892       str << "\n    void registerPython(const char *str)"
893           << "\n    { CcsRegisterHandler(str, CkCallback("<<Prefix::Index<<type<<"::pyRequest(0), *this)); }";
894     }
895     str << "\n";
896 }
897
898
899 static const char *CIClassStart = // prefix, name
900 "{\n"
901 "  public:\n"
902 ;
903
904 static const char *CIClassEnd =
905 "};\n"
906 ;
907
908 Chare::Chare(int ln, attrib_t Nattr, NamedType *t, TypeList *b, MemberList *l)
909          : attrib(Nattr), type(t), list(l), bases(b)
910 {
911         line = ln;
912         entryCount=1;
913         hasElement=0;
914         forElement=forAll;
915         hasSection=0;
916         bases_CBase=NULL;
917         setTemplate(0);
918         hasSdagEntry=0;
919         if (list)
920         {
921                 list->setChare(this);
922                 //Add migration constructor to MemberList
923                 if(isMigratable()) {
924                         Entry *e=new Entry(ln,SMIGRATE,NULL,
925                           (char *)type->getBaseName(),
926                           new ParamList(new Parameter(line,
927                                 new PtrType(new NamedType("CkMigrateMessage")))),0,0,0);
928                         e->setChare(this);
929                         list=new MemberList(e,list);
930                 }
931         }
932         if (bases==NULL) //Always add Chare as a base class
933                 bases = new TypeList(new NamedType("Chare"), NULL);
934 }
935
936 void
937 Chare::genRegisterMethodDef(XStr& str)
938 {
939   if(external || type->isTemplated())
940     return;
941   templateGuardBegin(isTemplated(), str);
942   str <<  tspec() <<
943   "void "<<indexName()<<"::__register(const char *s, size_t size) {\n"
944   "  __idx = CkRegisterChare(s, size,";
945   if (isMainChare()) str << " TypeMainChare";
946   else if (isGroup()) str << " TypeGroup";
947   else if (isNodeGroup()) str << " TypeNodeGroup";
948   else if (isArray()) str << " TypeArray";
949   else if (isChare()) str << " TypeChare";
950   else str << " TypeInvalid";
951   str << ");\n";
952   if (internalMode) str << "  CkRegisterChareInCharm(__idx);\n";
953   // register all bases
954   genIndexNames(str, "  CkRegisterBase(__idx, ",NULL, "::__idx);\n", "");
955   genSubRegisterMethodDef(str);
956   if(list)
957     list->genReg(str);
958   if (hasSdagEntry) {
959       str << "  " << baseName() << "::__sdag_register(); \n";
960   }
961   str << "}\n";
962   templateGuardEnd(str);
963 }
964
965 void
966 Chare::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
967 {
968   if(type->isTemplated())
969     return;
970   else
971   {
972     if(list)
973       list->genPub(declstr, defstr, defconstr, connectPresent);
974   }
975 }
976
977 void
978 Chare::genDecls(XStr& str)
979 {
980   if(type->isTemplated())
981     return;
982   str << "/* DECLS: "; print(str); str << " */\n";
983
984   // include python header and add two methods called execute and iterate.
985   // these cannot be added to the .ci file of the PythonCCS interface since
986   // different charm object require different definitions...
987   if (isPython()) {
988     str << "#include \"PythonCCS.h\"\n";
989     if (list) {
990       Entry *etemp = new Entry(0,0,new BuiltinType("void"),"pyRequest",new ParamList(new Parameter(0,new PtrType(new NamedType("CkCcsRequestMsg",0)),"msg")),0,0,0,0);
991       list->appendMember(etemp);
992       etemp->setChare(this);
993       //etemp = new Entry(0,0,new BuiltinType("void"),"getPrint",new ParamList(new Parameter(0,new PtrType(new NamedType("CkCcsRequestMsg",0)),"msg")),0,0,0,0);
994       //list->appendMember(etemp);
995       //etemp->setChare(this);
996     }
997   }
998
999   //Forward declaration of the user-defined implementation class*/
1000   str << tspec()<<" class "<<type<<";\n";
1001   str << tspec()<<" class "<<Prefix::Index<<type<<";\n";
1002   str << tspec()<<" class "<<Prefix::Proxy<<type<<";\n";
1003   if (hasElement)
1004     str << tspec()<<" class "<<Prefix::ProxyElement<<type<<";\n";
1005   if (hasSection)
1006     str << tspec()<<" class "<<Prefix::ProxySection<<type<<";\n";
1007   if (isPython())
1008     str << tspec()<<" class "<<Prefix::Python<<type<<";\n";
1009
1010  //Generate index class
1011   str << "/* --------------- index object ------------------ */\n";
1012   str << tspec()<< "class "<<Prefix::Index<<type;
1013   str << ":";
1014   genProxyNames(str, "public ",NULL, "", ", ");
1015   if(external || type->isTemplated())
1016   { //Just a template instantiation/forward declaration
1017     str << ";";
1018   }
1019   else
1020   { //Actual implementation
1021     str << CIClassStart;
1022     genTypedefs(str);
1023     str << "    static int __idx;\n";
1024     str << "    static void __register(const char *s, size_t size);\n";
1025     if(list)
1026       list->genIndexDecls(str);
1027     str << CIClassEnd;
1028   }
1029   str << "/* --------------- element proxy ------------------ */\n";
1030   genSubDecls(str);
1031   if (hasElement) {
1032     str << "/* ---------------- collective proxy -------------- */\n";
1033     forElement=forAll; genSubDecls(str); forElement=forIndividual;
1034   }
1035   if (hasSection) {
1036     str << "/* ---------------- section proxy -------------- */\n";
1037     forElement=forSection; genSubDecls(str); forElement=forIndividual;
1038   }
1039   if (isPython()) {
1040     str << "/* ---------------- python wrapper -------------- */\n";
1041     genPythonDecls(str);
1042   }
1043
1044   if(list) {
1045     //handle the case that some of the entries may be sdag Entries
1046     int sdagPresent = 0;
1047     XStr sdagStr;
1048     CParsedFile myParsedFile(this);
1049     list->collectSdagCode(&myParsedFile, sdagPresent);
1050     if(sdagPresent) {
1051       XStr classname;
1052       XStr sdagDecls;
1053       classname << baseName(0);
1054       resetNumbers();
1055       myParsedFile.doProcess(classname, sdagDecls, sdagDefs);
1056       str << sdagDecls;
1057     }
1058   }
1059
1060   // Create CBase_Whatever convenience type so that chare implementations can
1061   // avoid inheriting from a complex CBaseT templated type.
1062   TypeList *b=bases_CBase;
1063   if (b==NULL) b=bases; //Fall back to normal bases list if no CBase available
1064   if (templat) {
1065     templat->genSpec(str);
1066     str << "\nclass CBase_" << type << " : public ";
1067   } else {
1068     str << "typedef ";
1069   }
1070   str << "CBaseT" << b->length() << "<";
1071   if (isPython()) {
1072     str << Prefix::Python << type;
1073   } else {
1074     str << b;
1075   }
1076   str << ", CProxy_" << type;
1077   if (templat) {
1078     templat->genVars(str);
1079     str << " > {\npublic:\n\tCBase_" << type << "() : ";
1080     str << "CBaseT" << b->length() << "<" << b << ", CProxy_" << type;
1081     templat->genVars(str);
1082     str << ">() {}\n";
1083     str << "\tCBase_" << type << "(CkMigrateMessage* m) : ";
1084     str << "CBaseT" << b->length() << "<" << b << ", CProxy_" << type;
1085     templat->genVars(str);
1086     str << ">(m) {}\n";
1087     str << "\tvoid pup(PUP::er& p) {\n";
1088     str << "\t\tCBaseT" << b->length() << "<" << b << ", CProxy_" << type;
1089     templat->genVars(str);
1090     str << ">::pup(p);\n\t}\n};\n";
1091   } else {
1092     str << "> CBase_" << type << ";\n";
1093   }
1094 }
1095
1096 void
1097 Chare::preprocess()
1098 {
1099   if(list) list->preprocess();
1100 }
1101
1102 /*This disambiguation code is needed to support
1103   multiple inheritance in Chares (Groups, Arrays).
1104   They resolve ambiguous accessor calls to the parent "super".
1105   Because mutator routines need to change *all* the base
1106   classes, mutators are generated in xi-symbol.C.
1107 */
1108 static void
1109 disambig_proxy(XStr &str, const XStr &super)
1110 {
1111   str << "\n    int ckIsDelegated(void) const"
1112       << "\n    { return " << super << "::ckIsDelegated(); }"
1113       << "\n    inline CkDelegateMgr *ckDelegatedTo(void) const"
1114       << "\n    { return " << super << "::ckDelegatedTo(); }"
1115       << "\n    inline CkDelegateData *ckDelegatedPtr(void) const"
1116       << "\n    { return " << super << "::ckDelegatedPtr(); }"
1117       << "\n    CkGroupID ckDelegatedIdx(void) const"
1118       << "\n    { return " << super << "::ckDelegatedIdx(); }"
1119       << "\n";
1120 }
1121
1122 void
1123 Chare::genSubDecls(XStr& str)
1124 {
1125   XStr ptype;
1126   ptype<<proxyPrefix()<<type;
1127
1128   // Class declaration
1129   str << tspec()<< "class "<<ptype;
1130   if(external || type->isTemplated()) {
1131     str << ";";
1132     return;
1133   }
1134   str << ":";
1135   genProxyNames(str, "public ",NULL, "", ", ");
1136   str << CIClassStart;
1137
1138   genTypedefs(str);
1139
1140   // Various constructors:
1141   str << "    "<<ptype<<"(void) {};\n";
1142
1143   str << "    "<<ptype<<"(CkChareID __cid) : ";
1144   genProxyNames(str, "",NULL, "(__cid)", ", ");
1145   str << "{  }\n";
1146
1147   str << "    "<<ptype<<"(const Chare *c) : ";
1148   genProxyNames(str, "",NULL, "(c)", ", ");
1149   str << "{  }\n";
1150
1151   //Multiple inheritance-- resolve inheritance ambiguity
1152     XStr super;
1153     bases->getFirst()->genProxyName(super,forElement);
1154     disambig_proxy(str, super);
1155     str << "\n    inline void ckCheck(void) const"
1156         << "\n    { "<< super << "::ckCheck(); }"
1157         << "\n    const CkChareID &ckGetChareID(void) const"
1158         << "\n    { return " << super << "::ckGetChareID(); }"
1159         << "\n    operator const CkChareID &(void) const"
1160         << "\n    { return ckGetChareID(); }"
1161         << "\n";
1162
1163     sharedDisambiguation(str,super);
1164     str << "\n    void ckSetChareID(const CkChareID &c)"
1165         << "\n    {";
1166     genProxyNames(str,"      ",NULL,"::ckSetChareID(c); ","");
1167     str << "}"
1168         << "\n    "<<type<<tvars()<<" *ckLocal(void) const"
1169         << "\n    { return ("<<type<<tvars()<<" *)CkLocalChare(&ckGetChareID()); }"
1170         << "\n";
1171
1172   if(list)
1173     list->genDecls(str);
1174   str << CIClassEnd;
1175   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1176 }
1177
1178 void Chare::genPythonDecls(XStr& str) {
1179
1180   XStr ptype;
1181   ptype<<Prefix::Python<<type;
1182
1183   // Class declaration
1184   str << tspec()<< "class "<<ptype;
1185   if(external || type->isTemplated()) {
1186     str << ";";
1187     return;
1188   }
1189   str << ":";
1190   TypeList *b=bases_CBase;
1191   if (b==NULL) b=bases; //Fall back to normal bases list if no CBase available
1192   b->genProxyNames(str,"public ",NULL,"",", ",forPython);
1193   str << ", public PythonObject ";
1194   str << CIClassStart;
1195
1196   // default constructor methods
1197   str << "    "<<ptype<<"(void) {}\n";
1198   str << "    "<<ptype<<"(CkMigrateMessage *msg): ";
1199   b->genProxyNames(str,"",NULL,"(msg)",", ",forPython);
1200   str << " {}\n";
1201
1202   // define pupper
1203   str << "    void pup(PUP::er &p) {\n";
1204   b->genProxyNames(str,"      ",NULL,"::pup(p);","\n",forPython);
1205   str << "\n    }\n";
1206
1207   // define the python custom methods and their documentation
1208   str << "    static PyMethodDef CkPy_MethodsCustom[];\n";
1209   str << "    PyMethodDef *getMethods(void) {return CkPy_MethodsCustom;}\n";
1210   str << "    static const char *CkPy_MethodsCustomDoc;\n";
1211   str << "    const char *getMethodsDoc(void) {return CkPy_MethodsCustomDoc;}\n";
1212
1213   str << CIClassEnd;
1214
1215   // declare all static python methods and CkPy_MethodsCustom
1216   if (list)
1217     list->genPythonDecls(str);
1218   str << "\n";
1219
1220   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1221 }
1222
1223 void Chare::genPythonDefs(XStr& str) {
1224
1225   XStr ptype;
1226   ptype<<Prefix::Python<<type;
1227
1228   // generate the python methods array
1229   str << "PyMethodDef "<<ptype<<"::CkPy_MethodsCustom[] = {\n";
1230   if (list)
1231     list->genPythonStaticDefs(str);
1232   str << "  {NULL, NULL}\n};\n\n";
1233   // generate documentaion for the methods
1234   str << "const char * "<<ptype<<"::CkPy_MethodsCustomDoc = \"charm.__doc__ = \\\"Available methods for object "<<type<<":\\\\n\"";
1235   if (list)
1236     list->genPythonStaticDocs(str);
1237   str << "\n  \"\\\"\";\n\n";
1238
1239   if (list)
1240     list->genPythonDefs(str);
1241
1242 }
1243
1244 Group::Group(int ln, attrib_t Nattr,
1245         NamedType *t, TypeList *b, MemberList *l)
1246         :Chare(ln,Nattr|CGROUP,t,b,l)
1247 {
1248         hasElement=1;
1249         forElement=forIndividual;
1250         hasSection=1;
1251         bases_CBase=NULL;
1252         if (b==NULL) {//Add Group as a base class
1253                 delete bases;
1254                 if (isNodeGroup())
1255                         bases = new TypeList(new NamedType("NodeGroup"), NULL);
1256                 else {
1257                         bases = new TypeList(new NamedType("IrrGroup"), NULL);
1258                         bases_CBase = new TypeList(new NamedType("Group"), NULL);
1259                 }
1260         }
1261 }
1262
1263 void Group::genSubRegisterMethodDef(XStr& str) {
1264         if(!isTemplated()){
1265                 str << "   CkRegisterGroupIrr(__idx,"<<type<<"::isIrreducible());\n";
1266         }else{
1267                 str << "   CkRegisterGroupIrr(__idx," <<type<<tvars() <<"::isIrreducible());\n";
1268         }
1269 }
1270
1271 static void
1272 disambig_reduction_client(XStr &str, const XStr &super)
1273 {
1274   str << "\n    inline void setReductionClient(CkReductionClientFn fn,void *param=NULL) const"
1275       << "\n    { " << super << "::setReductionClient(fn,param); }"
1276       << "\n    inline void ckSetReductionClient(CkReductionClientFn fn,void *param=NULL) const"
1277       << "\n    { " << super << "::ckSetReductionClient(fn,param); }"
1278       << "\n    inline void ckSetReductionClient(CkCallback *cb) const"
1279       << "\n    { " << super << "::ckSetReductionClient(cb); }"
1280       << "\n";
1281 }
1282
1283 static void
1284 disambig_group(XStr &str, const XStr &super)
1285 {
1286   disambig_proxy(str, super);
1287   str << "inline void ckCheck(void) const {" << super << "::ckCheck();}\n"
1288       << "CkChareID ckGetChareID(void) const\n"
1289       << "   {return " << super << "::ckGetChareID();}\n"
1290       << "CkGroupID ckGetGroupID(void) const\n"
1291       << "   {return " << super << "::ckGetGroupID();}\n"
1292       << "operator CkGroupID () const { return ckGetGroupID(); }\n";
1293   disambig_reduction_client(str, super);
1294 }
1295
1296 void
1297 Group::genSubDecls(XStr& str)
1298 {
1299   XStr ptype; ptype<<proxyPrefix()<<type;
1300   XStr ttype; ttype<<type<<tvars();
1301   XStr super;
1302   bases->getFirst()->genProxyName(super,forElement);
1303
1304   // Class declaration:
1305   str << tspec()<< "class "<<ptype;
1306   if(external || type->isTemplated()) {
1307     str << ";";
1308     return;
1309   }
1310   str << ": ";
1311   genProxyNames(str, "public ",NULL, "", ", ");
1312   str << CIClassStart;
1313
1314   genTypedefs(str);
1315
1316   // Basic constructors:
1317   str << "    "<<ptype<<"(void) {}\n";
1318   str << "    "<<ptype<<"(const IrrGroup *g) : ";
1319   genProxyNames(str, "", NULL,"(g)", ", ");
1320   str << "{  }\n";
1321
1322   if (forElement==forIndividual)
1323   {//For a single element
1324     str << "    "<<ptype<<"(CkGroupID _gid,int _onPE,CK_DELCTOR_PARAM) : ";
1325     genProxyNames(str, "", NULL,"(_gid,_onPE,CK_DELCTOR_ARGS)", ", ");
1326     str << "{  }\n";
1327     str << "    "<<ptype<<"(CkGroupID _gid,int _onPE) : ";
1328     genProxyNames(str, "", NULL,"(_gid,_onPE)", ", ");
1329     str << "{  }\n";
1330
1331     disambig_group(str, super);
1332     str << "int ckGetGroupPe(void) const\n"
1333         << "{return " << super << "::ckGetGroupPe();}\n";
1334
1335   }
1336   else if (forElement==forSection)
1337   {//For a section of the group
1338     str << "    "<<ptype<<"(const CkGroupID &_gid,const int *_pelist,int _npes,CK_DELCTOR_PARAM) : ";
1339     genProxyNames(str, "", NULL,"(_gid,_pelist,_npes,CK_DELCTOR_ARGS)", ", ");
1340     str << "{  }\n";
1341     str << "    "<<ptype<<"(const CkGroupID &_gid,const int *_pelist,int _npes) : ";
1342     genProxyNames(str, "", NULL,"(_gid,_pelist,_npes)", ", ");
1343     str << "{  }\n";
1344     str << "    "<<ptype<<"(int n,const CkGroupID *_gid, int const * const *_pelist,const int *_npes) : ";
1345     genProxyNames(str, "", NULL,"(n,_gid,_pelist,_npes)", ", ");
1346     str << "{  }\n";
1347     str << "    "<<ptype<<"(int n,const CkGroupID *_gid, int const * const *_pelist,const int *_npes,CK_DELCTOR_PARAM) : ";
1348     genProxyNames(str, "", NULL,"(n,_gid,_pelist,_npes,CK_DELCTOR_ARGS)", ", ");
1349     str << "{  }\n";
1350     
1351     disambig_group(str, super);
1352     str << "inline int ckGetNumSections() const\n" <<
1353       "{ return " << super << "::ckGetNumSections(); }\n" <<
1354       "inline CkSectionInfo &ckGetSectionInfo()\n" <<
1355       "{ return " << super << "::ckGetSectionInfo(); }\n" <<
1356       "inline CkSectionID *ckGetSectionIDs()\n" <<
1357       "{ return " << super << "::ckGetSectionIDs(); }\n" <<
1358       "inline CkSectionID &ckGetSectionID()\n" <<
1359       "{ return " << super << "::ckGetSectionID(); }\n" <<
1360       "inline CkSectionID &ckGetSectionID(int i)\n" <<
1361       "{ return " << super << "::ckGetSectionID(i); }\n" <<
1362       "inline CkGroupID ckGetGroupIDn(int i) const\n" <<
1363       "{ return " << super << "::ckGetGroupIDn(i); }\n" <<
1364       "inline int *ckGetElements() const\n" <<
1365       "{ return " << super << "::ckGetElements(); }\n" <<
1366       "inline int *ckGetElements(int i) const\n" <<
1367       "{ return " << super << "::ckGetElements(i); }\n" <<
1368       "inline int ckGetNumElements() const\n" <<
1369       "{ return " << super << "::ckGetNumElements(); } \n" <<
1370       "inline int ckGetNumElements(int i) const\n" <<
1371       "{ return " << super << "::ckGetNumElements(i); }\n";
1372   }
1373   else if (forElement==forAll)
1374   {//For whole group
1375     str << "    "<<ptype<<"(CkGroupID _gid,CK_DELCTOR_PARAM) : ";
1376     genProxyNames(str, "", NULL,"(_gid,CK_DELCTOR_ARGS)", ", ");
1377     str << "{  }\n";
1378     str << "    "<<ptype<<"(CkGroupID _gid) : ";
1379     genProxyNames(str, "", NULL,"(_gid)", ", ");
1380     str << "{  }\n";
1381
1382     //Group proxy can be indexed into an element proxy:
1383     forElement=forIndividual;//<- for the proxyName below
1384     str << "    "<<proxyName(1)<<" operator[](int onPE) const\n";
1385     str << "      {return "<<proxyName(1)<<"(ckGetGroupID(),onPE,CK_DELCTOR_CALL);}\n";
1386     forElement=forAll;
1387
1388     disambig_group(str, super);
1389   }
1390
1391   //Multiple inheritance-- resolve inheritance ambiguity
1392   sharedDisambiguation(str,super);
1393   str<<"    void ckSetGroupID(CkGroupID g) {\n";
1394   genProxyNames(str,"      ",NULL,"::ckSetGroupID(g);\n","");
1395   str<<"    }\n";
1396
1397   str << "    "<<ttype<<"* ckLocalBranch(void) const {\n";
1398   str << "      return ckLocalBranch(ckGetGroupID());\n";
1399   str << "    }\n";
1400   str << "    static "<<ttype<< "* ckLocalBranch(CkGroupID gID) {\n";
1401   str << "      return ("<<ttype<<"*)";
1402   if(isNodeGroup())
1403     str << "CkLocalNodeBranch(gID);\n";
1404   else
1405     str << "CkLocalBranch(gID);\n";
1406   str << "    }\n";
1407   if(list)
1408     list->genDecls(str);
1409   str << CIClassEnd;
1410   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1411
1412 }
1413
1414 XStr indexSuffix2object(const XStr &indexSuffix) {
1415         if (indexSuffix==(const char*)"1D") return "CkIndex1D";
1416         if (indexSuffix==(const char*)"2D") return "CkIndex2D";
1417         if (indexSuffix==(const char*)"3D") return "CkIndex3D";
1418         if (indexSuffix==(const char*)"4D") return "CkIndex4D";
1419         if (indexSuffix==(const char*)"5D") return "CkIndex5D";
1420         if (indexSuffix==(const char*)"6D") return "CkIndex6D";
1421         if (indexSuffix==(const char*)"Max") return "CkIndexMax";
1422         else return indexSuffix;
1423 }
1424
1425 //Array Constructor
1426 Array::Array(int ln, attrib_t Nattr, NamedType *index,
1427         NamedType *t, TypeList *b, MemberList *l)
1428     : Chare(ln,Nattr|CARRAY|CMIGRATABLE,t,b,l)
1429 {
1430         hasElement=1;
1431         forElement=forIndividual;
1432         hasSection=1;
1433         index->print(indexSuffix);
1434       //printf("indexSuffix = %s\n", indexSuffix.charstar());
1435         if (indexSuffix!=(const char*)"none")
1436                 indexType<<"CkArrayIndex"<<indexSuffix;
1437         else indexType<<"CkArrayIndex";
1438
1439         if(b==0) { //No other base class:
1440                 delete bases;
1441                 if (0==strcmp(type->getBaseName(),"ArrayElement"))
1442                         //ArrayElement has special "ArrayBase" superclass
1443                         bases = new TypeList(new NamedType("ArrayBase"), NULL);
1444                 else {//Everybody else inherits from ArrayElementT<indexType>
1445                         bases=new TypeList(new NamedType("ArrayElement"),NULL);
1446                         XStr indexObject(indexSuffix2object(indexSuffix));
1447                         XStr parentClass;
1448                         parentClass<<"ArrayElementT<"<<indexObject<<">";
1449                         char *parentClassName=strdup(parentClass);
1450                         bases_CBase = new TypeList(new NamedType(parentClassName), NULL);
1451                 }
1452         }
1453 }
1454
1455 static void
1456 disambig_array(XStr &str, const XStr &super)
1457 {
1458   disambig_proxy(str, super);
1459   str << "\n    inline void ckCheck(void) const"
1460       << "\n    { " << super << "::ckCheck(); }"
1461       << "\n    inline operator CkArrayID () const"
1462       << "\n    { return ckGetArrayID(); }"
1463       << "\n    inline CkArrayID ckGetArrayID(void) const"
1464       << "\n    { return " << super << "::ckGetArrayID(); }"
1465       << "\n    inline CkArray *ckLocalBranch(void) const"
1466       << "\n    { return " << super << "::ckLocalBranch(); }"
1467       << "\n    inline CkLocMgr *ckLocMgr(void) const"
1468       << "\n    { return " << super << "::ckLocMgr(); }"
1469       << "\n"
1470       << "\n    inline static CkArrayID ckCreateEmptyArray(void)"
1471       << "\n    { return " << super << "::ckCreateEmptyArray(); }"
1472       << "\n    inline static CkArrayID ckCreateArray(CkArrayMessage *m,int ctor,const CkArrayOptions &opts)"
1473       << "\n    { return " << super << "::ckCreateArray(m,ctor,opts); }"
1474       << "\n    inline void ckInsertIdx(CkArrayMessage *m,int ctor,int onPe,const CkArrayIndex &idx)"
1475       << "\n    { " << super << "::ckInsertIdx(m,ctor,onPe,idx); }"
1476       << "\n    inline void doneInserting(void)"
1477       << "\n    { " << super << "::doneInserting(); }"
1478       << "\n"
1479       << "\n    inline void ckBroadcast(CkArrayMessage *m, int ep, int opts=0) const"
1480       << "\n    { " << super << "::ckBroadcast(m,ep,opts); }";
1481   disambig_reduction_client(str, super);
1482 }
1483
1484 void
1485 Array::genSubDecls(XStr& str)
1486 {
1487   XStr ptype; ptype<<proxyPrefix()<<type;
1488
1489   // Class declaration:
1490   str << tspec()<< " class "<<ptype;
1491   if(external || type->isTemplated()) {
1492     str << ";";
1493     return;
1494   }
1495   str << " : ";
1496   genProxyNames(str, "public ",NULL, "", ", ");
1497   str << CIClassStart;
1498
1499   genTypedefs(str);
1500
1501   str << "    "<<ptype<<"(void) {}\n";//An empty constructor
1502   if (forElement!=forSection)
1503   { //Generate constructor based on array element
1504           str << "    "<<ptype<<"(const ArrayElement *e) : ";
1505     genProxyNames(str, "", NULL,"(e)", ", ");
1506     str << "{  }\n";
1507   }
1508
1509   //Resolve multiple inheritance ambiguity
1510   XStr super;
1511   bases->getFirst()->genProxyName(super,forElement);
1512   sharedDisambiguation(str,super);
1513
1514   if (forElement==forIndividual)
1515   {/*For an individual element (no indexing)*/
1516     disambig_array(str, super);
1517     str << "\n    inline void ckInsert(CkArrayMessage *m,int ctor,int onPe)"
1518         << "\n    { " << super << "::ckInsert(m,ctor,onPe); }"
1519         << "\n    inline void ckSend(CkArrayMessage *m, int ep, int opts = 0) const"
1520         << "\n    { " << super << "::ckSend(m,ep,opts); }"
1521         << "\n    inline void *ckSendSync(CkArrayMessage *m, int ep) const"
1522         << "\n    { return " << super << "::ckSendSync(m,ep); }"
1523         << "\n    inline const CkArrayIndex &ckGetIndex() const"
1524         << "\n    { return " << super << "::ckGetIndex(); }"
1525         << "\n"
1526         << "\n    " << type << tvars() << " *ckLocal(void) const"
1527         << "\n    { return ("<<type<<tvars()<<" *)"<<super<<"::ckLocal(); }"
1528         << "\n";
1529
1530     //This constructor is used for array indexing
1531     str << "\n    " <<ptype<<"(const CkArrayID &aid,const "<<indexType<<" &idx,CK_DELCTOR_PARAM)"
1532         << "\n        :";
1533     genProxyNames(str, "",NULL, "(aid,idx,CK_DELCTOR_ARGS)", ", ");
1534     str << "\n    {}"
1535         << "\n    " <<ptype<<"(const CkArrayID &aid,const "<<indexType<<" &idx)"
1536         << "\n        :";
1537     genProxyNames(str, "",NULL, "(aid,idx)", ", ");
1538     str << "\n    {}"
1539         << "\n";
1540
1541     if ((indexType != (const char*)"CkArrayIndex") && (indexType != (const char*)"CkArrayIndexMax"))
1542     {
1543       // Emit constructors that take the base class array index too.  This proves
1544       // useful for runtime code that needs to access an element via a CkArrayIndex and
1545       // an array proxy. This might compromise type safety a wee bit and is hence not
1546       // propagated throughout.  For eg, CProxy_Foo::operator[] still accepts only the
1547       // appropriate CkArrayIndexND.
1548       str << "\n    " <<ptype<<"(const CkArrayID &aid,const CkArrayIndex &idx,CK_DELCTOR_PARAM)"
1549           << "\n        :";
1550       genProxyNames(str, "",NULL, "(aid,idx,CK_DELCTOR_ARGS)", ", ");
1551       str << "\n    {}"
1552           << "\n    " << ptype<<"(const CkArrayID &aid,const CkArrayIndex &idx)"
1553           << "\n        :";
1554       genProxyNames(str, "",NULL, "(aid,idx)", ", ");
1555       str << "\n    {}"
1556           << "\n";
1557     }
1558   }
1559   else if (forElement==forAll)
1560   {/*Collective, indexible version*/
1561     disambig_array(str, super);
1562
1563     //Build a simple, empty array
1564     str << "\n    static CkArrayID ckNew(void) { return ckCreateEmptyArray(); }";
1565
1566     XStr etype; etype<<Prefix::ProxyElement<<type<<tvars();
1567     if (indexSuffix!=(const char*)"none")
1568     {
1569       str << "\n    // Generalized array indexing:"
1570           << "\n    "<<etype<<" operator [] (const "<<indexType<<" &idx) const"
1571           << "\n    { return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL); }"
1572           << "\n    "<<etype<<" operator() (const "<<indexType<<" &idx) const"
1573           << "\n    { return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL); }"
1574           << "\n";
1575     }
1576
1577   //Add specialized indexing for these common types
1578     if (indexSuffix==(const char*)"1D")
1579     {
1580     str << "    " << etype << " operator [] (int idx) const \n"
1581         << "        {return "<< etype <<"(ckGetArrayID(), CkArrayIndex1D(idx), CK_DELCTOR_CALL);}\n"
1582         << "    " << etype <<" operator () (int idx) const \n"
1583         << "        {return "<< etype <<"(ckGetArrayID(), CkArrayIndex1D(idx), CK_DELCTOR_CALL);}\n";
1584     } else if (indexSuffix==(const char*)"2D") {
1585     str <<
1586     "    "<<etype<<" operator () (int i0,int i1) const \n"
1587     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex2D(i0,i1), CK_DELCTOR_CALL);}\n"
1588     "    "<<etype<<" operator () (CkIndex2D idx) const \n"
1589     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex2D(idx), CK_DELCTOR_CALL);}\n";
1590     } else if (indexSuffix==(const char*)"3D") {
1591     str <<
1592     "    "<<etype<<" operator () (int i0,int i1,int i2) const \n"
1593     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex3D(i0,i1,i2), CK_DELCTOR_CALL);}\n"
1594     "    "<<etype<<" operator () (CkIndex3D idx) const \n"
1595     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex3D(idx), CK_DELCTOR_CALL);}\n";
1596     } else if (indexSuffix==(const char*)"4D") {
1597     str <<
1598     "    "<<etype<<" operator () (short int i0,short int i1,short int i2,short int i3) const \n"
1599     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex4D(i0,i1,i2,i3), CK_DELCTOR_CALL);}\n"
1600     "    "<<etype<<" operator () (CkIndex4D idx) const \n"
1601     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex4D(idx), CK_DELCTOR_CALL);}\n";
1602     } else if (indexSuffix==(const char*)"5D") {
1603     str <<
1604     "    "<<etype<<" operator () (short int i0,short int i1,short int i2,short int i3,short int i4) const \n"
1605     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex5D(i0,i1,i2,i3,i4), CK_DELCTOR_CALL);}\n"
1606     "    "<<etype<<" operator () (CkIndex5D idx) const \n"
1607     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex5D(idx), CK_DELCTOR_CALL);}\n";
1608     } else if (indexSuffix==(const char*)"6D") {
1609     str <<
1610     "    "<<etype<<" operator () (short int i0,short int i1,short int i2,short int i3,short int i4,short int i5) const \n"
1611     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex6D(i0,i1,i2,i3,i4,i5), CK_DELCTOR_CALL);}\n"
1612     "    "<<etype<<" operator () (CkIndex6D idx) const \n"
1613     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex6D(idx), CK_DELCTOR_CALL);}\n";
1614     }
1615     str <<"    "<<ptype<<"(const CkArrayID &aid,CK_DELCTOR_PARAM) \n"
1616          "        :";genProxyNames(str, "",NULL, "(aid,CK_DELCTOR_ARGS)", ", ");str<<" {}\n";
1617     str <<"    "<<ptype<<"(const CkArrayID &aid) \n"
1618          "        :";genProxyNames(str, "",NULL, "(aid)", ", ");str<<" {}\n";
1619   }
1620   else if (forElement==forSection)
1621   { /* for Section, indexible version*/
1622     disambig_array(str, super);
1623     str << "\n    inline void ckSend(CkArrayMessage *m, int ep, int opts = 0)"
1624         << "\n    { " << super << "::ckSend(m,ep,opts); }"
1625         << "\n    inline CkSectionInfo &ckGetSectionInfo()"
1626         << "\n    { return " << super << "::ckGetSectionInfo(); }"
1627         << "\n    inline CkSectionID *ckGetSectionIDs()"
1628         << "\n    { return " << super << "::ckGetSectionIDs(); }"
1629         << "\n    inline CkSectionID &ckGetSectionID()"
1630         << "\n    { return " << super << "::ckGetSectionID(); }"
1631         << "\n    inline CkSectionID &ckGetSectionID(int i)"
1632         << "\n    { return " << super << "::ckGetSectionID(i); }"
1633         << "\n    inline CkArrayID ckGetArrayIDn(int i) const"
1634         << "\n    { return " << super << "::ckGetArrayIDn(i); } "
1635         << "\n    inline CkArrayIndex *ckGetArrayElements() const"
1636         << "\n    { return " << super << "::ckGetArrayElements(); }"
1637         << "\n    inline CkArrayIndex *ckGetArrayElements(int i) const"
1638         << "\n    { return " << super << "::ckGetArrayElements(i); }"
1639         << "\n    inline int ckGetNumElements() const"
1640         << "\n    { return " << super << "::ckGetNumElements(); } "
1641         << "\n    inline int ckGetNumElements(int i) const"
1642         << "\n    { return " << super << "::ckGetNumElements(i); }";
1643
1644     XStr etype; etype<<Prefix::ProxyElement<<type<<tvars();
1645     if (indexSuffix!=(const char*)"none")
1646     {
1647       str <<
1648     "    // Generalized array indexing:\n"
1649     "    "<<etype<<" operator [] (const "<<indexType<<" &idx) const\n"
1650     "        {return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL);}\n"
1651     "    "<<etype<<" operator() (const "<<indexType<<" &idx) const\n"
1652     "        {return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL);}\n";
1653     }
1654
1655   //Add specialized indexing for these common types
1656     if (indexSuffix==(const char*)"1D")
1657     {
1658     str <<
1659     "    "<<etype<<" operator [] (int idx) const \n"
1660     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex1D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1661     "    "<<etype<<" operator () (int idx) const \n"
1662     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex1D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1663     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex1D *elems, int nElems) {\n"
1664     "      return CkSectionID(aid, elems, nElems);\n"
1665     "    } \n"
1666     "    static CkSectionID ckNew(const CkArrayID &aid, int l, int u, int s) {\n"
1667     "      CkVec<CkArrayIndex1D> al;\n"
1668     "      for (int i=l; i<=u; i+=s) al.push_back(CkArrayIndex1D(i));\n"
1669     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1670     "    } \n";
1671     } else if (indexSuffix==(const char*)"2D") {
1672     str <<
1673     "    "<<etype<<" operator () (int idx) const \n"
1674     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex2D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1675     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex2D *elems, int nElems) {\n"
1676     "      return CkSectionID(aid, elems, nElems);\n"
1677     "    } \n"
1678     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2) {\n"
1679     "      CkVec<CkArrayIndex2D> al;\n"
1680     "      for (int i=l1; i<=u1; i+=s1) \n"
1681     "        for (int j=l2; j<=u2; j+=s2) \n"
1682     "          al.push_back(CkArrayIndex2D(i, j));\n"
1683     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1684     "    } \n";
1685     } else if (indexSuffix==(const char*)"3D") {
1686     str <<
1687     "    "<<etype<<" operator () (int idx) const \n"
1688     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex3D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1689     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex3D *elems, int nElems) {\n"
1690     "      return CkSectionID(aid, elems, nElems);\n"
1691     "    } \n"
1692     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3) {\n"
1693     "      CkVec<CkArrayIndex3D> al;\n"
1694     "      for (int i=l1; i<=u1; i+=s1) \n"
1695     "        for (int j=l2; j<=u2; j+=s2) \n"
1696     "          for (int k=l3; k<=u3; k+=s3) \n"
1697     "          al.push_back(CkArrayIndex3D(i, j, k));\n"
1698     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1699     "    } \n";
1700     } else if (indexSuffix==(const char*)"4D") {
1701     str <<
1702     "    "<<etype<<" operator () (int idx) const \n"
1703     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex4D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1704     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex4D *elems, int nElems) {\n"
1705     "      return CkSectionID(aid, elems, nElems);\n"
1706     "    } \n"
1707     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3, int l4, int u4, int s4) {\n"
1708     "      CkVec<CkArrayIndex4D> al;\n"
1709     "      for (int i=l1; i<=u1; i+=s1) \n"
1710     "        for (int j=l2; j<=u2; j+=s2) \n"
1711     "          for (int k=l3; k<=u3; k+=s3) \n"
1712     "            for (int l=l4; l<=u4; l+=s4) \n"
1713     "              al.push_back(CkArrayIndex4D(i, j, k, l));\n"
1714     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1715     "    } \n";
1716     } else if (indexSuffix==(const char*)"5D") {
1717     str <<
1718     "    "<<etype<<" operator () (int idx) const \n"
1719     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex5D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1720     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex5D *elems, int nElems) {\n"
1721     "      return CkSectionID(aid, elems, nElems);\n"
1722     "    } \n"
1723     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3, int l4, int u4, int s4, int l5, int u5, int s5) {\n"
1724     "      CkVec<CkArrayIndex5D> al;\n"
1725     "      for (int i=l1; i<=u1; i+=s1) \n"
1726     "        for (int j=l2; j<=u2; j+=s2) \n"
1727     "          for (int k=l3; k<=u3; k+=s3) \n"
1728     "            for (int l=l4; l<=u4; l+=s4) \n"
1729     "              for (int m=l5; m<=u5; m+=s5) \n"
1730     "                al.push_back(CkArrayIndex5D(i, j, k, l, m));\n"
1731     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1732     "    } \n";
1733     } else if (indexSuffix==(const char*)"6D") {
1734     str <<
1735     "    "<<etype<<" operator () (int idx) const \n"
1736     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex6D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1737     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex6D *elems, int nElems) {\n"
1738     "      return CkSectionID(aid, elems, nElems);\n"
1739     "    } \n"
1740     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3, int l4, int u4, int s4, int l5, int u5, int s5, int l6, int u6, int s6) {\n"
1741     "      CkVec<CkArrayIndex6D> al;\n"
1742     "      for (int i=l1; i<=u1; i+=s1) \n"
1743     "        for (int j=l2; j<=u2; j+=s2) \n"
1744     "          for (int k=l3; k<=u3; k+=s3) \n"
1745     "            for (int l=l4; l<=u4; l+=s4) \n"
1746     "              for (int m=l5; m<=u5; m+=s5) \n"
1747     "                for (int n=l6; n<=u6; n+=s6) \n"
1748     "                  al.push_back(CkArrayIndex6D(i, j, k, l, m, n));\n"
1749     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1750     "    } \n";
1751     }
1752
1753     str <<"    "<<ptype<<"(const CkArrayID &aid, CkArrayIndex *elems, int nElems, CK_DELCTOR_PARAM) \n"
1754          "        :";genProxyNames(str, "",NULL, "(aid,elems,nElems,CK_DELCTOR_ARGS)", ", ");str << " {}\n";
1755     str <<"    "<<ptype<<"(const CkArrayID &aid, CkArrayIndex *elems, int nElems) \n"
1756          "        :";genProxyNames(str, "",NULL, "(aid,elems,nElems)", ", ");str<<" {}\n";
1757     str <<"    "<<ptype<<"(const CkSectionID &sid)"
1758           "       :";genProxyNames(str, "",NULL, "(sid)", ", ");str<< " {}\n";
1759         str <<"    "<<ptype<<"(int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems, CK_DELCTOR_PARAM) \n"
1760           "        :";genProxyNames(str, "",NULL, "(n,aid,elems,nElems,CK_DELCTOR_ARGS)", ", ");str << " {}\n";
1761         str <<"    "<<ptype<<"(int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems) \n"
1762           "        :";genProxyNames(str, "",NULL, "(n,aid,elems,nElems)", ", ");str<<" {}\n";
1763     str <<
1764     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex *elems, int nElems) {\n"
1765     "      return CkSectionID(aid, elems, nElems);\n"
1766     "    } \n";
1767   }
1768
1769   if(list){
1770     list->genDecls(str);
1771   }
1772   str << CIClassEnd;
1773   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1774 }
1775
1776 void
1777 Chare::genTypedefs(XStr &str) {
1778    str << "    typedef "<<baseName(1)<<" local_t;\n";
1779    str << "    typedef "<<Prefix::Index<<baseName(1)<<" index_t;\n";
1780    str << "    typedef "<<Prefix::Proxy<<baseName(1)<<" proxy_t;\n";
1781
1782    if (hasElement)
1783      str << "    typedef "<<Prefix::ProxyElement<<baseName(1)<<" element_t;\n";
1784    else /* !hasElement, so generic proxy is element type */
1785      str << "    typedef "<<Prefix::Proxy<<baseName(1)<<" element_t;\n";
1786
1787    if (hasSection)
1788      str << "    typedef "<<Prefix::ProxySection<<baseName(1)<<" section_t;\n";
1789    str << "\n";
1790 }
1791
1792
1793
1794 void
1795 Chare::genDefs(XStr& str)
1796 {
1797   str << "/* DEFS: "; print(str); str << " */\n";
1798   if (fortranMode) { // For Fortran90
1799     if (!isArray()) { // Currently, only arrays are supported
1800       cerr << (char *)baseName() << ": only chare arrays are currently supported\n";
1801       exit(1);
1802     }
1803     // We have to generate the chare array itself
1804     str << "/* FORTRAN */\n";
1805     str << "extern \"C\" void " << fortranify(baseName(), "_allocate") << "(char **, void *, " << indexList() << ");\n";
1806     str << "extern \"C\" void " << fortranify(baseName(), "_pup") << "(pup_er p, char **, void *);\n";
1807     str << "extern \"C\" void " << fortranify(baseName(), "_resumefromsync") << "(char **, void *, " << indexList() << ");\n";
1808     str << "\n";
1809     XStr dim = ((Array*)this)->dim();
1810     str << "class " << baseName() << " : public ArrayElement" << dim << "\n";
1811     str << "{\n";
1812     str << "public:\n";
1813     str << "  char user_data[64];\n";
1814     str << "public:\n";
1815     str << "  " << baseName() << "()\n";
1816     str << "  {\n";
1817 //    str << "    CkPrintf(\"" << baseName() << " %d created\\n\",thisIndex);\n";
1818     str << "    CkArrayID *aid = &thisArrayID;\n";
1819     if (dim==(const char*)"1D")
1820       str << "    " << fortranify(baseName(), "_allocate") << "((char **)&user_data, &aid, &thisIndex);\n";
1821     else if (dim==(const char*)"2D")
1822       str << "    " << fortranify(baseName(), "_allocate") << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y);\n";
1823     else if (dim==(const char*)"3D")
1824       str << "    " << fortranify(baseName(), "_allocate") << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y, &thisIndex.z);\n";
1825     str << "      usesAtSync = CmiTrue;\n";
1826     str << "  }\n";
1827     str << "\n";
1828     str << "  " << baseName() << "(CkMigrateMessage *m)\n";
1829     str << "  {\n";
1830     str << "    /* CkPrintf(\"" << baseName() << " %d migrating\\n\",thisIndex);*/ \n";
1831     str << "  }\n";
1832     str << "\n";
1833
1834     str << "  virtual void pup(PUP::er &p)\n";
1835     str << "  {\n";
1836     str << "    ArrayElement" << dim << "::pup(p);\n";
1837     str << "    p(user_data, 64);\n";
1838     str << "    CkArrayID *aid = &thisArrayID;\n";
1839     str << "    ::" << fortranify(baseName(), "_pup") << "(&p, (char **)&user_data, &aid); \n";
1840     str << "  }\n";
1841     str << "\n";
1842
1843       // Define the Fortran interface function for ResumeFromSync
1844     str << "  void ResumeFromSync()\n";
1845     str << "  {\n";
1846     str << "    CkArrayID *aid = &thisArrayID;\n";
1847     str << "    ::" << fortranify(baseName(), "_resumefromSync");
1848     if (dim == (const char*)"1D") {
1849       str << "((char **)&user_data, &aid, &thisIndex);\n";
1850     }
1851     else if (dim == (const char*)"2D") {
1852       str << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y);\n";
1853     }
1854     else if (dim == (const char*)"3D") {
1855       str << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y, &thisIndex.z);\n";
1856     }
1857     str << "  }\n";
1858
1859     str << "};\n";
1860     str << "\n";
1861     if (dim==(const char*)"1D") {
1862       str << "extern \"C\" void " << fortranify(baseName(), "_cknew") << "(int *numElem, long *aindex)\n";
1863       str << "{\n";
1864       str << "    CkArrayID *aid = new CkArrayID;\n";
1865       str << "    *aid = CProxy_" << baseName() << "::ckNew(*numElem); \n";
1866     }
1867     else if (dim==(const char*)"2D") {
1868       str << "extern \"C\" void " << fortranify(baseName(), "_cknew") << "(int *numx, int *numy, long *aindex)\n";
1869       str << "{\n";
1870       str << "    CkArrayID *aid = new CkArrayID;\n";
1871       str << "    *aid = CProxy_" << baseName() << "::ckNew(); \n";
1872       str << "    CProxy_" << baseName() << " p(*aid);\n";
1873       str << "    for (int i=0; i<*numx; i++) \n";
1874       str << "      for (int j=0; j<*numy; j++) \n";
1875       str << "        p[CkArrayIndex2D(i, j)].insert(); \n";
1876       str << "    p.doneInserting(); \n";
1877     }
1878     else if (dim==(const char*)"3D") {
1879       str << "extern \"C\" void " << fortranify(baseName(), "_cknew") << "(int *numx, int *numy, int *numz, long *aindex)\n";
1880       str << "{\n";
1881       str << "    CkArrayID *aid = new CkArrayID;\n";
1882       str << "    *aid = CProxy_" << baseName() << "::ckNew(); \n";
1883       str << "    CProxy_" << baseName() << " p(*aid);\n";
1884       str << "    for (int i=0; i<*numx; i++) \n";
1885       str << "      for (int j=0; j<*numy; j++) \n";
1886       str << "        for (int k=0; k<*numz; k++) \n";
1887       str << "          p[CkArrayIndex3D(i, j, k)].insert(); \n";
1888       str << "    p.doneInserting(); \n";
1889     }
1890     str << "    *aindex = (long)aid;\n";
1891     str << "}\n";
1892
1893       // Define the Fortran interface function for AtSync
1894     if (dim == (const char*)"1D") {
1895       str << "extern \"C\" void "
1896           << fortranify(baseName(), "_atsync")
1897           << "(long* aindex, int *index1)\n";
1898       str << "{\n";
1899       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1900       str << "\n";
1901       str << "  CProxy_" << baseName() << " h(*aid);\n";
1902       str << "  h[*index1].ckLocal()->AtSync();\n";
1903     }
1904     else if (dim == (const char*)"2D") {
1905       str << "extern \"C\" void "
1906           << fortranify(baseName(), "_atsync")
1907           << "(long* aindex, int *index1, int *index2)\n";
1908       str << "{\n";
1909       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1910       str << "\n";
1911       str << "  CProxy_" << baseName() << " h(*aid);\n";
1912       str << "  h[CkArrayIndex2D(*index1, *index2)].ckLocal()->AtSync();\n";
1913     }
1914     else if (dim == (const char*)"3D") {
1915       str << "extern \"C\" void "
1916           << fortranify(baseName(), "_atsync")
1917           << "(long* aindex, int *index1, int *index2, int *index3)\n";
1918       str << "{\n";
1919       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1920       str << "\n";
1921       str << "  CProxy_" << baseName() << " h(*aid);\n";
1922       str << "  h[CkArrayIndex3D(*index1, *index2, *index3)].ckLocal()->AtSync();\n";
1923     }
1924     str << "}\n";
1925
1926   }
1927
1928   templateGuardBegin(isTemplated(), str);
1929   if(!type->isTemplated()) {
1930     if(external) str << "extern ";
1931     str << tspec()<<" int "<<indexName()<<"::__idx";
1932     if(!external) str << "=0";
1933     str << ";\n";
1934   }
1935   templateGuardEnd(str);
1936
1937   if(list)
1938   {//Add definitions for all entry points
1939     list->genDefs(str);
1940     if (hasElement)
1941     { //Define the entry points for the element
1942       forElement=forAll;
1943       list->genDefs(str);
1944       if (hasSection) {  // for Section
1945         forElement=forSection;
1946         list->genDefs(str);
1947       }
1948       forElement=forIndividual;
1949     }
1950   }
1951
1952   templateGuardBegin(isTemplated(), str);
1953   // define the python routines
1954   if (isPython()) {
1955     str << "/* ---------------- python wrapper -------------- */\n";
1956
1957     // write CkPy_MethodsCustom
1958     genPythonDefs(str);
1959   }
1960   templateGuardEnd(str);
1961
1962   if(!external && !type->isTemplated())
1963     genRegisterMethodDef(str);
1964   if (hasSdagEntry) {
1965     str << "\n";
1966     str << sdagDefs;
1967   }
1968 }
1969
1970 void
1971 Chare::genReg(XStr& str)
1972 {
1973   str << "/* REG: "; print(str); str << "*/\n";
1974   if(external || templat)
1975     return;
1976   str << "  "<<indexName()<<"::__register(\""<<type<<"\", sizeof("<<type<<"));\n";
1977 }
1978
1979 static const char *CIMsgClassAnsi =
1980 "{\n"
1981 "  public:\n"
1982 "    static int __idx;\n"
1983 "    void* operator new(size_t, void*p) { return p; }\n"
1984 "    void* operator new(size_t);\n"
1985 "    void* operator new(size_t, int*, const int);\n"
1986 "    void* operator new(size_t, int*);\n"
1987 "#if CMK_MULTIPLE_DELETE\n"
1988 "    void operator delete(void*p, void*){dealloc(p);}\n"
1989 "    void operator delete(void*p){dealloc(p);}\n"
1990 "    void operator delete(void*p, int*, const int){dealloc(p);}\n"
1991 "    void operator delete(void*p, int*){dealloc(p);}\n"
1992 "#endif\n"
1993 "    void operator delete(void*p, size_t){dealloc(p);}\n"
1994 "    static void* alloc(int,size_t, int*, int);\n"
1995 "    static void dealloc(void *p);\n"
1996 ;
1997
1998 void
1999 Message::genAllocDecl(XStr &str)
2000 {
2001   int i, num;
2002   XStr mtype;
2003   mtype << type;
2004   if(templat) templat->genVars(mtype);
2005   str << CIMsgClassAnsi;
2006   str << "    CMessage_" << mtype << "();\n";
2007   str << "    static void *pack(" << mtype << " *p);\n";
2008   str << "    static " << mtype << "* unpack(void* p);\n";
2009   num = numArrays();
2010   if(num>0) {
2011     str << "    void *operator new(size_t";
2012     for(i=0;i<num;i++)
2013       str << ", int";
2014     str << ");\n";
2015   }
2016   str << "    void *operator new(size_t, ";
2017   for(i=0;i<num;i++)
2018     str << "int, ";
2019   str << "const int);\n";
2020   str << "#if CMK_MULTIPLE_DELETE\n";
2021   if(num>0) {
2022     str << "    void operator delete(void *p";
2023     for(i=0;i<num;i++)
2024         str << ", int";
2025     str << "){dealloc(p);}\n";
2026   }
2027   str << "    void operator delete(void *p, ";
2028   for(i=0;i<num;i++)
2029     str << "int, ";
2030   str << "const int){dealloc(p);}\n";
2031   str << "#endif\n";
2032 }
2033
2034 void
2035 Message::genDecls(XStr& str)
2036 {
2037   XStr ptype;
2038   ptype<<proxyPrefix()<<type;
2039   if(type->isTemplated())
2040     return;
2041   str << "/* DECLS: "; print(str); str << " */\n";
2042   if(templat)
2043     templat->genSpec(str);
2044   str << "class ";
2045   type->print(str);
2046   str << ";\n";
2047   if(templat)
2048     templat->genSpec(str);
2049   str << "class "<<ptype;
2050   if(external || type->isTemplated()) {
2051     str << ";\n";
2052     return;
2053   }
2054   str << ":public CkMessage";
2055
2056   genAllocDecl(str);
2057
2058   if(!(external||type->isTemplated())) {
2059    // generate register function
2060     str << "    static void __register(const char *s, size_t size, CkPackFnPtr pack, CkUnpackFnPtr unpack) {\n";
2061     str << "      __idx = CkRegisterMsg(s, pack, unpack, dealloc, size);\n";
2062     str << "    }\n";
2063   }
2064   str << "};\n";
2065   
2066   if (strncmp(type->getBaseName(), "MarshallMsg_", 12) == 0) {
2067     MsgVarList *ml;
2068     MsgVar *mv;
2069     int i;
2070     str << "class " << type << " : public " << ptype << " {\n";
2071     str << "  public:\n";
2072     int num = numVars();
2073     for(i=0, ml=mvlist; i<num; i++, ml=ml->next) {
2074       mv = ml->msg_var;
2075       if (mv->isConditional() || mv->isArray()) {
2076         str << "    /* "; mv->print(str); str << " */\n";
2077         str << "    " << mv->type << " *" << mv->name << ";\n";
2078       }
2079     }
2080     str <<"};\n";
2081   }
2082 }
2083
2084 void
2085 Message::genDefs(XStr& str)
2086 {
2087   int i, count, num = numVars();
2088   int numArray = numArrays();
2089   MsgVarList *ml;
2090   MsgVar *mv;
2091   XStr ptype, mtype, tspec;
2092   ptype<<proxyPrefix()<<type;
2093   if(templat) templat->genVars(ptype);
2094   mtype << type;
2095   if(templat) templat->genVars(mtype);
2096   if(templat) { templat->genSpec(tspec); tspec << " "; }
2097
2098   str << "/* DEFS: "; print(str); str << " */\n";
2099
2100   templateGuardBegin(templat, str);
2101   if(!(external||type->isTemplated())) {
2102
2103     // new (size_t)
2104     str << tspec << "void *" << ptype << "::operator new(size_t s){\n";
2105     str << "  return " << mtype << "::alloc(__idx, s, 0, 0);\n}\n";
2106     // new (size_t, int*)
2107     str << tspec << "void *" << ptype << "::operator new(size_t s, int* sz){\n";
2108     str << "  return " << mtype << "::alloc(__idx, s, sz, 0);\n}\n";
2109     // new (size_t, int*, priobits)
2110     str << tspec << "void *" << ptype << "::operator new(size_t s, int* sz,";
2111     str << "const int pb){\n";
2112     str << "  return " << mtype << "::alloc(__idx, s, sz, pb);\n}\n";
2113     // new (size_t, int, int, ..., int)
2114     if(numArray>0) {
2115       str << tspec << "void *" << ptype << "::operator new(size_t s";
2116       for(i=0;i<numArray;i++)
2117         str << ", int sz" << i;
2118       str << ") {\n";
2119       str << "  int sizes[" << numArray << "];\n";
2120       for(i=0;i<numArray;i++)
2121         str << "  sizes[" << i << "] = sz" << i << ";\n";
2122       str << "  return " << mtype << "::alloc(__idx, s, sizes, 0);\n";
2123       str << "}\n";
2124     }
2125     // new (size_t, int, int, ..., int, priobits)
2126     // degenerates to  new(size_t, priobits)  if no varsize
2127     str << tspec << "void *"<< ptype << "::operator new(size_t s, ";
2128     for(i=0;i<numArray;i++)
2129       str << "int sz" << i << ", ";
2130     str << "const int p) {\n";
2131     if (numArray>0) str << "  int sizes[" << numArray << "];\n";
2132     for(i=0, count=0, ml=mvlist ;i<num; i++, ml=ml->next)
2133       if (ml->msg_var->isArray()) {
2134         str << "  sizes[" << count << "] = sz" << count << ";\n";
2135         count ++;
2136       }
2137     str << "  return " << mtype << "::alloc(__idx, s, " << (numArray>0?"sizes":"0") << ", p);\n";
2138     str << "}\n";
2139     // alloc(int, size_t, int*, priobits)
2140     str << tspec << "void* " << ptype;
2141     str << "::alloc(int msgnum, size_t sz, int *sizes, int pb) {\n";
2142     str << "  CkpvAccess(_offsets)[0] = ALIGN8(sz);\n";
2143     for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2144       mv = ml->msg_var;
2145       if (mv->isArray()) {
2146         str << "  if(sizes==0)\n";
2147         str << "    CkpvAccess(_offsets)[" << count+1 << "] = CkpvAccess(_offsets)[0];\n";
2148         str << "  else\n";
2149         str << "    CkpvAccess(_offsets)[" << count+1 << "] = CkpvAccess(_offsets)[" << count << "] + ";
2150         str << "ALIGN8(sizeof(" << mv->type << ")*sizes[" << count << "]);\n";
2151         count ++;
2152       }
2153     }
2154     str << "  return CkAllocMsg(msgnum, CkpvAccess(_offsets)[" << numArray << "], pb);\n";
2155     str << "}\n";
2156
2157     str << tspec << ptype << "::" << proxyPrefix() << type << "() {\n";
2158     str << mtype << " *newmsg = (" << mtype << " *)this;\n";
2159     for(i=0, count=0, ml=mvlist; i<num; i++,ml=ml->next) {
2160       mv = ml->msg_var;
2161       if (mv->isArray()) {
2162         str << "  newmsg->" << mv->name << " = (" << mv->type << " *) ";
2163         str << "((char *)newmsg + CkpvAccess(_offsets)[" << count << "]);\n";
2164         count ++;
2165       }
2166     }
2167     str << "}\n";
2168
2169     int numCond = numConditional();
2170     str << tspec << "void " << ptype << "::dealloc(void *p) {\n";
2171     if (numCond > 0) {
2172       str << "  " << mtype << " *msg = (" << mtype << "*) p;\n";
2173       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2174         mv = ml->msg_var;
2175         if (mv->isConditional()) {
2176           if (mv->type->isPointer()) die("conditional variable cannot be a pointer", line);
2177           str << "  CkConditional *cond_" << mv->name << " = static_cast<CkConditional*>(msg->" << mv->name << ");\n";
2178           str << "  if (cond_" << mv->name << "!=NULL) cond_" << mv->name << "->deallocate();\n";
2179         }
2180       }
2181     }
2182     str << "  CkFreeMsg(p);\n";
2183     str << "}\n";
2184     // pack
2185     str << tspec << "void* " << ptype << "::pack(" << mtype << " *msg) {\n";
2186     for(i=0, ml=mvlist; i<num; i++, ml=ml->next) {
2187       mv = ml->msg_var;
2188       if (mv->isArray()) {
2189         str << "  msg->" << mv->name << " = (" <<mv->type << " *) ";
2190         str << "((char *)msg->" << mv->name << " - (char *)msg);\n";
2191       }
2192     }
2193     if (numCond > 0) {
2194       str << "  int impl_off[" <<  numCond+1 << "];\n";
2195       str << "  impl_off[0] = UsrToEnv(msg)->getUsersize();\n";
2196       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2197         mv = ml->msg_var;
2198         if (mv->isConditional()) {
2199           str << "  if (msg->" << mv->name << "!=NULL) { /* conditional packing of ";
2200           mv->type->print(str); str << " " << mv->name << " */\n";
2201           str << "    PUP::sizer implP;\n";
2202           str << "    implP|*msg->" << mv->name << ";\n";
2203           str << "    impl_off[" << count+1 << "] = impl_off[" << count << "] + implP.size();\n";
2204           str << "  } else {\n";
2205           str << "    impl_off[" << count+1 << "] = impl_off[" << count << "];\n";
2206           str << "  }\n";
2207           count ++;
2208         }
2209       }
2210       str << "  " << mtype << " *newmsg = (" << mtype << "*) CkAllocMsg(__idx, impl_off["
2211           << numCond << "], UsrToEnv(msg)->getPriobits());\n";
2212       str << "  envelope *newenv = UsrToEnv(newmsg);\n";
2213       str << "  UInt newSize = newenv->getTotalsize();\n";
2214       str << "  CmiMemcpy(newenv, UsrToEnv(msg), impl_off[0]+sizeof(envelope));\n";
2215       str << "  newenv->setTotalsize(newSize);\n";
2216       str << "  if (UsrToEnv(msg)->getPriobits() > 0) CmiMemcpy(newenv->getPrioPtr(), UsrToEnv(msg)->getPrioPtr(), newenv->getPrioBytes());\n";
2217       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2218         mv = ml->msg_var;
2219         if (mv->isConditional()) {
2220           str << "  if (msg->" << mv->name << "!=NULL) { /* conditional packing of ";
2221           mv->type->print(str); str << " " << mv->name << " */\n";
2222           str << "    newmsg->" << mv->name << " = ("; mv->type->print(str);
2223           str << "*)(((char*)newmsg)+impl_off[" << count << "]);\n";
2224           str << "    PUP::toMem implP((void *)newmsg->" << mv->name << ");\n";
2225           str << "    implP|*msg->" << mv->name << ";\n";
2226           str << "    newmsg->" << mv->name << " = (" << mv->type << "*) ((char *)newmsg->" << mv->name << " - (char *)newmsg);\n";
2227           str << "  }\n";
2228           count++;
2229         }
2230       }
2231       str << "  CkFreeMsg(msg);\n";
2232       str << "  msg = newmsg;\n";
2233     }
2234     str << "  return (void *) msg;\n}\n";
2235     // unpack
2236     str << tspec << mtype << "* " << ptype << "::unpack(void* buf) {\n";
2237     str << "  " << mtype << " *msg = (" << mtype << " *) buf;\n";
2238     for(i=0, ml=mvlist; i<num; i++, ml=ml->next) {
2239       mv = ml->msg_var;
2240       if (mv->isArray()) {
2241         str << "  msg->" << mv->name << " = (" <<mv->type << " *) ";
2242         str << "((size_t)msg->" << mv->name << " + (char *)msg);\n";
2243       }
2244     }
2245     if (numCond > 0) {
2246       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2247         mv = ml->msg_var;
2248         if (mv->isConditional()) {
2249           str << "  if (msg->" << mv->name << "!=NULL) { /* conditional packing of ";
2250           mv->type->print(str); str << " " << mv->name << " */\n";
2251           str << "    PUP::fromMem implP((char*)msg + (size_t)msg->" << mv->name << ");\n";
2252           str << "    msg->" << mv->name << " = new " << mv->type << ";\n";
2253           str << "    implP|*msg->" << mv->name << ";\n";
2254           str << "  }\n";
2255           count ++;
2256         }
2257       }
2258     }
2259     str << "  return msg;\n}\n";
2260   }
2261   if(!templat) {
2262     if(!external && !type->isTemplated()) {
2263       str << "int "<< ptype <<"::__idx=0;\n";
2264     }
2265   } else {
2266     str << tspec << "int "<< ptype <<"::__idx=0;\n";
2267   }
2268   templateGuardEnd(str);
2269 }
2270
2271 void
2272 Message::genReg(XStr& str)
2273 {
2274   str << "/* REG: "; print(str); str << "*/\n";
2275   if(!templat && !external) {
2276     XStr ptype, mtype, tspec;
2277     ptype<<proxyPrefix()<<type;
2278     str << ptype << "::__register(\"" << type << "\", sizeof(" << type <<"),";
2279     str << "(CkPackFnPtr) " << type << "::pack,";
2280     str << "(CkUnpackFnPtr) " << type << "::unpack);\n";
2281   }
2282 }
2283
2284 void
2285 Template::setExtern(int e)
2286 {
2287   Construct::setExtern(e);
2288   entity->setExtern(e);
2289 }
2290
2291 void
2292 Template::genVars(XStr& str)
2293 {
2294   str << " < ";
2295   if(tspec)
2296     tspec->genShort(str);
2297   str << " > ";
2298 }
2299
2300 XStr generateTemplateSpec(TVarList* tspec)
2301 {
2302   XStr str;
2303
2304   if(tspec) {
2305     str << "template < ";
2306     tspec->genLong(str);
2307     str << " > ";
2308   }
2309
2310   return str;
2311 }
2312
2313 void
2314 Template::genSpec(XStr& str)
2315 {
2316   str << generateTemplateSpec(tspec);
2317 }
2318
2319 void
2320 Template::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
2321 {
2322   if(!external && entity) {
2323     entity->genPub(declstr, defstr, defconstr, connectPresent);
2324   }
2325 }
2326
2327 void
2328 Template::genDecls(XStr& str)
2329 {
2330   if(!external && entity) {
2331     entity->genDecls(str);
2332   }
2333 }
2334
2335 void
2336 Template::genDefs(XStr& str)
2337 {
2338   if(!external && entity)
2339     entity->genDefs(str);
2340 }
2341
2342 int Template::genAccels_spe_c_funcBodies(XStr& str) {
2343   int rtn = 0;
2344   if (!external && entity) { rtn += entity->genAccels_spe_c_funcBodies(str); }
2345   return rtn;
2346 }
2347
2348 void Template::genAccels_spe_c_regFuncs(XStr& str) {
2349   if (!external && entity) { entity->genAccels_spe_c_regFuncs(str); }
2350 }
2351
2352 void Template::genAccels_spe_c_callInits(XStr& str) {
2353   if (!external && entity) { entity->genAccels_spe_c_callInits(str); }
2354 }
2355
2356 void Template::genAccels_spe_h_includes(XStr& str) {
2357   if (!external && entity) { entity->genAccels_spe_h_includes(str); }
2358 }
2359
2360 void Template::genAccels_spe_h_fiCountDefs(XStr& str) {
2361   if (!external && entity) { entity->genAccels_spe_h_fiCountDefs(str); }
2362 }
2363
2364 void Template::genAccels_ppe_c_regFuncs(XStr& str) {
2365   if (!external && entity) { entity->genAccels_ppe_c_regFuncs(str); }
2366 }
2367
2368 void
2369 TVarList::genLong(XStr& str)
2370 {
2371   if(tvar)
2372     tvar->genLong(str);
2373   if(next) {
2374     str << ", ";
2375     next->genLong(str);
2376   }
2377 }
2378
2379 void
2380 TVarList::genShort(XStr& str)
2381 {
2382   if(tvar)
2383     tvar->genShort(str);
2384   if(next) {
2385     str << ", ";
2386     next->genShort(str);
2387   }
2388 }
2389
2390 void TType::genLong(XStr& str)
2391 {
2392   str << "class ";
2393   if(type)
2394     type->print(str);
2395   if(init) {
2396     str << "=";
2397     init->print(str);
2398   }
2399 }
2400
2401 void TType::genShort(XStr& str)
2402 {
2403   if(type)
2404     type->print(str);
2405 }
2406
2407 void TName::genLong(XStr& str)
2408 {
2409   if(type)
2410     type->print(str);
2411   str << " "<<name;
2412   if(val) {
2413     str << "="<<val;
2414   }
2415 }
2416
2417 void TName::genShort(XStr& str)
2418 {
2419   str << name;
2420 }
2421
2422 void
2423 Module::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
2424 {
2425   if(!external) {
2426     if (clist) clist->genPub(declstr, defstr, defconstr, connectPresent);
2427   }
2428 }
2429
2430
2431 void
2432 Module::genDecls(XStr& str)
2433 {
2434   if(external) {
2435     str << "#include \""<<name<<".decl.h\"\n";
2436   } else {
2437     if (clist) clist->genDecls(str);
2438   }
2439
2440   #if CMK_CELL != 0
2441     str << "extern int register_accel_spe_funcs__module_" << name << "(int curIndex);\n";
2442     if (isMain()) {
2443       str << "extern \"C\" void register_accel_spe_funcs(void);\n";
2444     }
2445   #endif
2446 }
2447
2448 void
2449 Module::genDefs(XStr& str)
2450 {
2451   if(!external)
2452     if (clist)
2453       clist->genDefs(str);
2454
2455   // DMK - Accel Support
2456   #if CMK_CELL != 0
2457
2458     if (!external) {
2459       templateGuardBegin(false, str);
2460
2461       // Create the registration function
2462       // NOTE: Add a check so modules won't register more than once.  It is possible that to modules
2463       //   could have 'extern' references to each other, creating infinite loops in the registration
2464       //   process.  Avoid this problem.
2465       str << "int register_accel_spe_funcs__module_" << name << "(int curIndex) {\n"
2466           << "  static int hasAlreadyRegisteredFlag = 0;\n"
2467           << "  if (hasAlreadyRegisteredFlag) { return curIndex; };\n"
2468           << "  hasAlreadyRegisteredFlag = 1;\n";
2469       genAccels_ppe_c_regFuncs(str);
2470       str << "  return curIndex;\n"
2471           << "}\n";
2472
2473       // Check to see if this is the main module (create top register function if so)
2474       if (isMain()) {
2475         str << "#include\"spert.h\"\n"  // NOTE: Make sure SPE_FUNC_INDEX_USER is defined
2476             << "extern \"C\" void register_accel_spe_funcs(void) {\n"
2477             << "  register_accel_spe_funcs__module_" << name << "(SPE_FUNC_INDEX_USER);\n"
2478             << "}\n";
2479       }
2480
2481       templateGuardEnd(str);
2482     }
2483
2484   #endif
2485 }
2486
2487 void
2488 Module::genReg(XStr& str)
2489 {
2490   if(external) {
2491     str << "  _register"<<name<<"();"<<endx;
2492   } else {
2493     if (clist) clist->genDefs(str);
2494   }
2495 }
2496
2497
2498 int Module::genAccels_spe_c_funcBodies(XStr& str) {
2499
2500   // If this is an external module decloration, just place an include
2501   if (external) {
2502     str << "#include \"" << name << ".genSPECode.c\"\n";
2503     return 0;
2504   }
2505
2506   // If this is the main module, generate the function lookup table
2507   if (isMain()) {
2508     str << "typedef void(*AccelFuncPtr)(DMAListEntry*);\n\n"
2509         << "typedef struct __func_lookup_table_entry {\n"
2510         << "  int funcIndex;\n"
2511         << "  AccelFuncPtr funcPtr;\n"
2512         << "} FuncLookupTableEntry;\n\n"
2513         << "FuncLookupTableEntry funcLookupTable[MODULE_" << name << "_FUNC_INDEX_COUNT];\n\n\n";
2514   }
2515
2516   // Process each of the sub-constructs
2517   int rtn = 0;
2518   if (clist) { rtn += clist->genAccels_spe_c_funcBodies(str); }
2519
2520   // Create the accelerated function registration function for accelerated entries local to this module
2521   // NOTE: Add a check so modules won't register more than once.  It is possible that to modules
2522   //   could have 'extern' references to each other, creating infinite loops in the registration
2523   //   process.  Avoid this problem.
2524   str << "int register_accel_funcs_" << name << "(int curIndex) {\n"
2525       << "  static int hasAlreadyRegisteredFlag = 0;\n"
2526       << "  if (hasAlreadyRegisteredFlag) { return curIndex; };\n"
2527       << "  hasAlreadyRegisteredFlag = 1;\n";
2528   genAccels_spe_c_regFuncs(str);
2529   str << "  return curIndex;\n"
2530       << "}\n\n\n";
2531
2532   // If this is the main module, generate the funcLookup function
2533   if (isMain()) {
2534
2535     str << "\n\n";
2536     str << "#ifdef __cplusplus\n"
2537         << "extern \"C\"\n"
2538         << "#endif\n"
2539         << "void funcLookup(int funcIndex,\n"
2540         << "                void* readWritePtr, int readWriteLen,\n"
2541         << "                void* readOnlyPtr, int readOnlyLen,\n"
2542         << "                void* writeOnlyPtr, int writeOnlyLen,\n"
2543         << "                DMAListEntry* dmaList\n"
2544         << "               ) {\n\n";
2545
2546     str << "  if ((funcIndex >= SPE_FUNC_INDEX_USER) && (funcIndex < (SPE_FUNC_INDEX_USER + MODULE_" << name << "_FUNC_INDEX_COUNT))) {\n"
2547
2548         //<< "    // DMK - DEBUG\n"
2549         //<< "    printf(\"[DEBUG-ACCEL] :: [SPE_%d] - Calling funcIndex %d...\\n\", (int)getSPEID(), funcIndex);\n"
2550
2551         << "    (funcLookupTable[funcIndex - SPE_FUNC_INDEX_USER].funcPtr)(dmaList);\n"
2552         << "  } else if (funcIndex == SPE_FUNC_INDEX_INIT) {\n"
2553         << "    if (register_accel_funcs_" << name << "(0) != MODULE_" << name << "_FUNC_INDEX_COUNT) {\n"
2554         << "      printf(\"ERROR : register_accel_funcs_" << name << "() returned an invalid value.\\n\");\n"
2555         << "    };\n";
2556     genAccels_spe_c_callInits(str);
2557     str << "  } else if (funcIndex == SPE_FUNC_INDEX_CLOSE) {\n"
2558         << "    // NOTE : Do nothing on close, but handle case...\n"
2559         << "  } else {\n"
2560         << "    printf(\"ERROR : Unknown funcIndex (%d) passed to funcLookup()... ignoring.\\n\", funcIndex);\n"
2561         << "  }\n";
2562
2563     str << "}\n";
2564   }
2565
2566   return rtn;
2567 }
2568
2569 void Module::genAccels_spe_c_regFuncs(XStr& str) {
2570   if (external) {
2571     str << "  curIndex = register_accel_funcs_" << name << "(curIndex);\n";
2572   } else {
2573     if (clist) { clist->genAccels_spe_c_regFuncs(str); }
2574   }
2575 }
2576
2577 void Module::genAccels_spe_c_callInits(XStr& str) {
2578   if (clist) { clist->genAccels_spe_c_callInits(str); }
2579 }
2580
2581 void Module::genAccels_spe_h_includes(XStr& str) {
2582   if (external) {
2583     str << "#include \"" << name << ".genSPECode.h\"\n";
2584   }
2585   if (clist) { clist->genAccels_spe_h_includes(str); }
2586 }
2587
2588 void Module::genAccels_spe_h_fiCountDefs(XStr& str) {
2589   if (external) {
2590     str << " + MODULE_" << name << "_FUNC_INDEX_COUNT";
2591   }
2592   if (clist) { clist->genAccels_spe_h_fiCountDefs(str); }
2593 }
2594
2595 void Module::genAccels_ppe_c_regFuncs(XStr& str) {
2596   if (external) {
2597     str << "  curIndex = register_accel_spe_funcs__module_" << name << "(curIndex);\n";
2598   } else {
2599     if (clist) { clist->genAccels_ppe_c_regFuncs(str); }
2600   }
2601 }
2602
2603 void
2604 Readonly::genDecls(XStr& str)
2605 {
2606   str << "/* DECLS: "; print(str); str << " */\n";
2607 }
2608
2609 void
2610 Readonly::genIndexDecls(XStr& str)
2611 {
2612   str << "/* DECLS: "; print(str); str << " */\n";
2613 }
2614
2615 //Turn this string into a valid identifier
2616 XStr makeIdent(const XStr &in)
2617 {
2618   XStr ret;
2619   const char *i=in.get_string_const();
2620   while (*i!=0) {
2621     //Quote all "special" characters
2622     if (*i==':') ret<<"_QColon_";
2623     else if (*i==' ') ret<<"_QSpace_";
2624     else if (*i=='+') ret<<"_QPlus_";
2625     else if (*i=='-') ret<<"_QMinus_";
2626     else if (*i=='*') ret<<"_QTimes_";
2627     else if (*i=='/') ret<<"_QSlash_";
2628     else if (*i=='%') ret<<"_QPercent_";
2629     else if (*i=='&') ret<<"_QAmpersand_";
2630     else if (*i=='.') ret<<"_QDot_";
2631     else if (*i==',') ret<<"_QComma_";
2632     else if (*i=='\'') ret<<"_QSQuote_";
2633     else if (*i=='\"') ret<<"_QQuote_";
2634     else if (*i=='(') ret<<"_QLparen_";
2635     else if (*i==')') ret<<"_QRparen_";
2636     else if (*i=='<') ret<<"_QLess_";
2637     else if (*i=='>') ret<<"_QGreater_";
2638     else if (*i=='{') ret<<"_QLbrace_";
2639     else if (*i=='}') ret<<"_QRbrace_";
2640     else ret << *i; //Copy character unmodified
2641     i++; //Advance to next
2642   }
2643   return ret;
2644 }
2645
2646 void
2647 Readonly::genDefs(XStr& str)
2648 {
2649   str << "/* DEFS: "; print(str); str << " */\n";
2650   if(!container && !strchr(name, ':')) {
2651     str << "extern ";
2652     type->print(str);
2653     if(msg)
2654       str << "*";
2655     str << " "<<name;
2656     if(dims)
2657       dims->print(str);
2658     str << ";\n";
2659   }
2660
2661   if (!msg) { //Generate a pup for this readonly
2662     templateGuardBegin(false, str);
2663     str << "extern \"C\" void __xlater_roPup_"<<makeIdent(qName());
2664     str <<    "(void *_impl_pup_er) {\n";
2665     str << "  PUP::er &_impl_p=*(PUP::er *)_impl_pup_er;\n";
2666     if(dims){
2667             str << "  _impl_p("<<qName()<<","; dims->printValue(str); str<<");\n";
2668     }else{
2669             str << "  _impl_p|"<<qName()<<";\n";
2670     }
2671     str << "}\n";
2672     templateGuardEnd(str);
2673   }
2674
2675   if (fortranMode) {
2676       str << "extern \"C\" void "
2677           << fortranify("set_", name)
2678           << "(int *n) { " << name << " = *n; }\n";
2679       str << "extern \"C\" void "
2680           << fortranify("get_", name)
2681           << "(int *n) { *n = " << name << "; }\n";
2682   }
2683 }
2684
2685 void
2686 Readonly::genReg(XStr& str)
2687 {
2688   if(external)
2689     return;
2690   if(msg) {
2691     if(dims) die("readonly Message cannot be an array",line);
2692     str << "  CkRegisterReadonlyMsg(\""<<qName()<<"\",\""<<type<<"\",";
2693     str << "(void **)&"<<qName()<<");\n";
2694   } else {
2695     str << "  CkRegisterReadonly(\""<<qName()<<"\",\""<<type<<"\",";
2696     str << "sizeof("<<qName()<<"),(void *) &"<<qName()<<",";
2697     str << "__xlater_roPup_"<<makeIdent(qName())<<");\n";
2698   }
2699 }
2700
2701 void TParamList::genSpec(XStr& str)
2702 {
2703   if(tparam)
2704     tparam->genSpec(str);
2705   if(next) {
2706     str << ", ";
2707     next->genSpec(str);
2708   }
2709 }
2710
2711 void MemberList::genIndexDecls(XStr& str)
2712 {
2713     perElemGen(members, str, &Member::genIndexDecls, newLine);
2714 }
2715
2716 void MemberList::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
2717 {
2718     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
2719         if (*i) {
2720             (*i)->genPub(declstr, defstr, defconstr, connectPresent);
2721             declstr << endx;
2722         }
2723 }
2724
2725 void MemberList::genDecls(XStr& str)
2726 {
2727     perElemGen(members, str, &Member::genDecls, newLine);
2728 }
2729
2730 void MemberList::collectSdagCode(CParsedFile *pf, int& sdagPresent)
2731 {
2732     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
2733         if (*i)
2734             (*i)->collectSdagCode(pf, sdagPresent);
2735 }
2736
2737 void MemberList::genDefs(XStr& str)
2738 {
2739     perElemGen(members, str, &Member::genDefs, newLine);
2740 }
2741
2742 void MemberList::genReg(XStr& str)
2743 {
2744     perElemGen(members, str, &Member::genReg, newLine);
2745 }
2746
2747 void MemberList::preprocess()
2748 {
2749   perElem(members, &Member::preprocess);
2750 }
2751
2752 void MemberList::lookforCEntry(CEntry *centry)
2753 {
2754     perElemGen(members, centry, &Member::lookforCEntry);
2755 }
2756
2757 void MemberList::genPythonDecls(XStr& str) {
2758     perElemGen(members, str, &Member::genPythonDecls, newLine);
2759 }
2760
2761 void MemberList::genPythonDefs(XStr& str) {
2762     perElemGen(members, str, &Member::genPythonDefs, newLine);
2763 }
2764
2765 void MemberList::genPythonStaticDefs(XStr& str) {
2766     perElemGen(members, str, &Member::genPythonStaticDefs);
2767 }
2768
2769 void MemberList::genPythonStaticDocs(XStr& str) {
2770     perElemGen(members, str, &Member::genPythonStaticDocs);
2771 }
2772
2773 void Entry::lookforCEntry(CEntry *centry)
2774 {
2775    // compare name
2776    if (strcmp(name, *centry->entry) != 0) return;
2777    // compare param
2778    if (param && !centry->paramlist) return;
2779    if (!param && centry->paramlist) return;
2780    if (param && !(*param == *centry->paramlist)) return;
2781
2782    isWhenEntry = 1;
2783    centry->decl_entry = this;
2784 }
2785
2786 void Chare::lookforCEntry(CEntry *centry)
2787 {
2788   if(list)
2789     list->lookforCEntry(centry);
2790   if (centry->decl_entry == NULL)  {
2791     cerr<<"Function \""<<centry->entry->get_string_const()
2792         <<"\" appears in Sdag When construct, but not defined as an entry function. "
2793         << endl;
2794     die("(FATAL ERROR)");
2795   }
2796 }
2797
2798 ///////////////////////////// ENTRY ////////////////////////////
2799
2800 void ParamList::checkParamList(){
2801   if(manyPointers){ 
2802     die("You may pass only a single pointer to a non-local entry method. It should point to a message.", param->line);
2803     abort();
2804   }
2805 }
2806
2807 Entry::Entry(int l, int a, Type *r, const char *n, ParamList *p, Value *sz, SdagConstruct *sc, const char *e, int connect, ParamList *connectPList) :
2808       attribs(a), retType(r), stacksize(sz), sdagCon(sc), name((char *)n), targs(0), intExpr(e), param(p), connectParam(connectPList), isConnect(connect)
2809 {
2810   line=l; container=NULL;
2811   entryCount=-1;
2812   isWhenEntry=0;
2813   if (param && param->isMarshalled() && !isThreaded()) attribs|=SNOKEEP;
2814
2815   if(!isThreaded() && stacksize) die("Non-Threaded methods cannot have stacksize",line);
2816   if(retType && !isSync() && !isIget() && !isLocal() && !retType->isVoid())
2817     die("A remote method normally returns void.  To return non-void, you need to declare the method as [sync], which means it has blocking semantics.",line);
2818   if (isPython()) pythonDoc = python_doc;
2819   if(!isLocal() && p){
2820     p->checkParamList();
2821   }
2822 }
2823
2824 void Entry::setChare(Chare *c) {
2825         Member::setChare(c);
2826         // mainchare constructor parameter is not allowed
2827         /* ****************** REMOVED 10/8/2002 ************************
2828         if (isConstructor()&&container->isMainChare() && param != NULL)
2829           if (!param->isCkArgMsgPtr())
2830            die("MainChare Constructor doesn't allow parameter!", line);
2831         Removed old treatment for CkArgMsg to allow argc, argv or void
2832         constructors for mainchares.
2833         * **************************************************************/
2834         if (isConstructor() && container->isMainChare() && param->isVoid()) {
2835           //Main chare always magically takes CkArgMsg
2836           Type *t = new PtrType(new NamedType("CkArgMsg"));
2837           param=new ParamList(new Parameter(line,t));
2838           std::cerr << "Charmxi> " << line << ": Deprecation warning: mainchare constructors should explicitly take CkArgMsg* if that's how they're implemented.\n";
2839         }
2840
2841         entryCount=c->nextEntry();
2842
2843         //Make a special "callmarshall" method, for communication optimizations to use:
2844         hasCallMarshall=param->isMarshalled() && !isThreaded() && !isSync() && !isExclusive() && !fortranMode;
2845         if (isSdag()) container->setSdag(1);
2846 }
2847
2848 // "parameterType *msg" or "void".
2849 // Suitable for use as the only parameter
2850 XStr Entry::paramType(int withDefaultVals,int withEO,int useConst)
2851 {
2852   XStr str;
2853   param->print(str,withDefaultVals,useConst);
2854   if (withEO) str<<eo(withDefaultVals,!param->isVoid());
2855   return str;
2856 }
2857
2858 // "parameterType *msg," if there is a non-void parameter,
2859 // else empty.  Suitable for use with another parameter following.
2860 XStr Entry::paramComma(int withDefaultVals,int withEO)
2861 {
2862   XStr str;
2863   if (!param->isVoid()) {
2864     str << paramType(withDefaultVals,withEO);
2865     str << ", ";
2866   }
2867   return str;
2868 }
2869 XStr Entry::eo(int withDefaultVals,int priorComma) {
2870   XStr str;
2871   if (param->isMarshalled()) {//FIXME: add options for void methods, too...
2872     if (priorComma) str<<", ";
2873     str<<"const CkEntryOptions *impl_e_opts";
2874     if (withDefaultVals) str<<"=NULL";
2875   }
2876   return str;
2877 }
2878
2879 void Entry::collectSdagCode(CParsedFile *pf, int& sdagPresent)
2880 {
2881   if (isSdag()) {
2882     sdagPresent = 1;
2883     pf->addNode(this);
2884   }
2885 }
2886
2887 XStr Entry::marshallMsg(void)
2888 {
2889   XStr ret;
2890   XStr epName = epStr();
2891   param->marshall(ret, epName);
2892   return ret;
2893 }
2894
2895 XStr Entry::epStr(bool isForRedn, bool templateCall)
2896 {
2897   XStr str;
2898   if (isForRedn)
2899     str<<"redn_wrapper_";
2900   str << name << "_";
2901
2902   if (param->isMessage()) {
2903     str<<param->getBaseName();
2904     str.replace(':', '_');
2905   }
2906   else if (param->isVoid())
2907     str<<"void";
2908   else
2909     str<<"marshall"<<entryCount;
2910
2911   if (tspec && templateCall) {
2912     str << "< ";
2913     tspec->genShort(str);
2914     str << " >";
2915   }
2916
2917   return str;
2918 }
2919
2920 XStr Entry::epIdx(int fromProxy, bool isForRedn)
2921 {
2922   XStr str;
2923   if (fromProxy) {
2924     str << indexName()<<"::";
2925     // If the chare is also templated, then we must avoid a parsing ambiguity
2926     if (tspec)
2927       str << "template ";
2928   }
2929   str << "idx_" << epStr(isForRedn, true) << "()";
2930   return str;
2931 }
2932
2933 XStr Entry::epRegFn(int fromProxy, bool isForRedn)
2934 {
2935   XStr str;
2936   if (fromProxy)
2937     str << indexName() << "::";
2938   str << "reg_" << epStr(isForRedn, true) << "()";
2939   return str;
2940 }
2941
2942 XStr Entry::chareIdx(int fromProxy)
2943 {
2944   XStr str;
2945   if (fromProxy)
2946     str << indexName()<<"::";
2947   str << "__idx";
2948   return str;
2949 }
2950
2951 //Return a templated proxy declaration string for
2952 // this Member's container with the given return type, e.g.
2953 // template<int N,class foo> void CProxy_bar<N,foo>
2954 // Works with non-templated Chares as well.
2955 XStr Member::makeDecl(const XStr &returnType, int forProxy, bool isStatic)
2956 {
2957   XStr str;
2958
2959   if (container->isTemplated())
2960     str << container->tspec() << "\n";
2961   str << generateTemplateSpec(tspec) << "\n";
2962   if (isStatic)
2963     str << "static ";
2964   str << returnType<<" ";
2965   if (forProxy)
2966         str<<container->proxyName();
2967   else
2968         str<<container->indexName();
2969   return str;
2970 }
2971
2972 XStr Entry::syncReturn(void) {
2973   XStr str;
2974   if(retType->isVoid())
2975     str << "  CkFreeSysMsg(";
2976   else
2977     str << "  return ("<<retType<<") (";
2978   return str;
2979 }
2980
2981 /*************************** Chare Entry Points ******************************/
2982
2983 void Entry::genChareDecl(XStr& str)
2984 {
2985   if(isConstructor()) {
2986     genChareStaticConstructorDecl(str);
2987   } else {
2988     // entry method declaration
2989     str << "    " << generateTemplateSpec(tspec) << "\n"
2990         << "    " << retType << " " << name << "(" << paramType(1,1) << ");\n";
2991   }
2992 }
2993
2994 void Entry::genChareDefs(XStr& str)
2995 {
2996   if (isImmediate()) {
2997       cerr << (char *)container->baseName() << ": Chare does not allow immediate message.\n";
2998       exit(1);
2999   }
3000   if (isLocal()) {
3001     cerr << (char*)container->baseName() << ": Chare does not allow LOCAL entry methods.\n";
3002     exit(1);
3003   }
3004
3005   if(isConstructor()) {
3006     genChareStaticConstructorDefs(str);
3007   } else {
3008     XStr params; params<<epIdx()<<", impl_msg, &ckGetChareID()";
3009     // entry method definition
3010     XStr retStr; retStr<<retType;
3011     str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<")\n";
3012     str << "{\n  ckCheck();\n"<<marshallMsg();
3013     if(isSync()) {
3014       str << syncReturn() << "CkRemoteCall("<<params<<"));\n";
3015     } else {//Regular, non-sync message
3016       str << "  if (ckIsDelegated()) {\n";
3017       str << "    int destPE=CkChareMsgPrep("<<params<<");\n";
3018       str << "    if (destPE!=-1) ckDelegatedTo()->ChareSend(ckDelegatedPtr(),"<<params<<",destPE);\n";
3019       str << "  }\n";
3020       XStr opts;
3021       opts << ",0";
3022       if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
3023       if (isInline())  opts << "+CK_MSG_INLINE";
3024       str << "  else CkSendMsg("<<params<<opts<<");\n";
3025     }
3026     str << "}\n";
3027   }
3028 }
3029
3030 void Entry::genChareStaticConstructorDecl(XStr& str)
3031 {
3032   str << "    static CkChareID ckNew("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
3033   str << "    static void ckNew("<<paramComma(1)<<"CkChareID* pcid, int onPE=CK_PE_ANY"<<eo(1)<<");\n";
3034   if (!param->isVoid())
3035     str << "    "<<container->proxyName(0)<<"("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
3036 }
3037
3038 void Entry::genChareStaticConstructorDefs(XStr& str)
3039 {
3040   str << makeDecl("CkChareID",1)<<"::ckNew("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
3041   str << "{\n"<<marshallMsg();
3042   str << "  CkChareID impl_ret;\n";
3043   str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
3044   str << "  return impl_ret;\n";
3045   str << "}\n";
3046
3047   str << makeDecl("void",1)<<"::ckNew("<<paramComma(0)<<"CkChareID* pcid, int impl_onPE"<<eo(0)<<")\n";
3048   str << "{\n"<<marshallMsg();
3049   str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, pcid, impl_onPE);\n";
3050   str << "}\n";
3051
3052   if (!param->isVoid()) {
3053     str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
3054     str << "{\n"<<marshallMsg();
3055     str << "  CkChareID impl_ret;\n";
3056     str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
3057     str << "  ckSetChareID(impl_ret);\n";
3058     str << "}\n";
3059   }
3060 }
3061
3062 /***************************** Array Entry Points **************************/
3063
3064 void Entry::genArrayDecl(XStr& str)
3065 {
3066   if(isConstructor()) {
3067     str << "    " << generateTemplateSpec(tspec) << "\n";
3068     genArrayStaticConstructorDecl(str);
3069   } else {
3070     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3071     str << "    " << generateTemplateSpec(tspec) << "\n";
3072     if(isIget())
3073       str << "    "<<"CkFutureID"<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
3074     else if(isLocal())
3075       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<") ;\n";
3076     else
3077       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
3078   }
3079 }
3080
3081 void Entry::genArrayDefs(XStr& str)
3082 {
3083   if(isIget() && !container->isForElement()) return;
3084   if (isImmediate()) {
3085       cerr << (char *)container->baseName() << ": Chare Array does not allow immediate message.\n";
3086       exit(1);
3087   }
3088
3089   if (isConstructor())
3090     genArrayStaticConstructorDefs(str);
3091   else
3092   {//Define array entry method
3093     const char *ifNot="CkArray_IfNotThere_buffer";
3094     if (isCreateHere()) ifNot="CkArray_IfNotThere_createhere";
3095     if (isCreateHome()) ifNot="CkArray_IfNotThere_createhome";
3096
3097     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3098
3099     XStr retStr; retStr<<retType;
3100     if(isIget())
3101       str << makeDecl("CkFutureID ",1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
3102     else if(isLocal())
3103       str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1,0)<<") \n";
3104     else
3105       str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
3106     str << "{\n  ckCheck();\n";
3107     if (!isLocal()) {
3108       str << marshallMsg();
3109       str << "  CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;\n";
3110       str << "  impl_amsg->array_setIfNotThere("<<ifNot<<");\n";
3111     } else {
3112       XStr unmarshallStr; param->unmarshall(unmarshallStr);
3113       str << "  LDObjHandle objHandle;\n  int objstopped=0;\n";
3114       str << "  "<<container->baseName()<<" *obj = ckLocal();\n";
3115       str << "#if CMK_ERROR_CHECKING\n";
3116       str << "  if (obj==NULL) CkAbort(\"Trying to call a LOCAL entry method on a non-local element\");\n";
3117       str << "#endif\n";
3118       if (!isNoTrace())
3119           str << "  _TRACE_BEGIN_EXECUTE_DETAILED(0,ForArrayEltMsg,(" << epIdx()
3120               << "),CkMyPe(), 0, ((CkArrayIndex&)ckGetIndex()).getProjectionID(((CkGroupID)ckGetArrayID()).idx));\n";
3121       str << "#if CMK_LBDB_ON\n  objHandle = obj->timingBeforeCall(&objstopped);\n#endif\n";
3122       str << "#if CMK_CHARMDEBUG\n"
3123       "  CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
3124       "#endif\n   ";
3125       if (!retType->isVoid()) str << retType<< " retValue = ";
3126       str << "obj->"<<name<<"("<<unmarshallStr<<");\n";
3127       str << "#if CMK_CHARMDEBUG\n"
3128       "  CpdAfterEp("<<epIdx()<<");\n"
3129       "#endif\n";
3130       str << "#if CMK_LBDB_ON\n  obj->timingAfterCall(objHandle,&objstopped);\n#endif\n";
3131       if (!isNoTrace()) str << "  _TRACE_END_EXECUTE();\n";
3132       if (!retType->isVoid()) str << "  return retValue;\n";
3133     }
3134     if(isIget()) {
3135             str << "  CkFutureID f=CkCreateAttachedFutureSend(impl_amsg,"<<epIdx()<<",ckGetArrayID(),ckGetIndex(),&CProxyElement_ArrayBase::ckSendWrapper);"<<"\n";
3136     }
3137
3138     if(isSync()) {
3139       str << syncReturn() << "ckSendSync(impl_amsg, "<<epIdx()<<"));\n";
3140     }
3141     else if (!isLocal())
3142     {
3143       XStr opts;
3144       opts << ",0";
3145       if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
3146       if (isInline())  opts << "+CK_MSG_INLINE";
3147       if(!isIget()) {
3148       if (container->isForElement() || container->isForSection()) {
3149         str << "  ckSend(impl_amsg, "<<epIdx()<<opts<<");\n";
3150       }
3151       else
3152         str << "  ckBroadcast(impl_amsg, "<<epIdx()<<opts<<");\n";
3153       }
3154     }
3155     if(isIget()) {
3156             str << "  return f;\n";
3157     }
3158     str << "}\n";
3159   }
3160 }
3161
3162 void Entry::genArrayStaticConstructorDecl(XStr& str)
3163 {
3164   if (container->getForWhom()==forIndividual)
3165       str<< //Element insertion routine
3166       "    void insert("<<paramComma(1,0)<<"int onPE=-1"<<eo(1)<<");";
3167   else if (container->getForWhom()==forAll) {
3168       str<< //With options
3169       "    static CkArrayID ckNew("<<paramComma(1,0)<<"const CkArrayOptions &opts"<<eo(1)<<");\n";
3170       if (container->isArray()) {
3171         XStr dim = ((Array*)container)->dim();
3172         if (dim==(const char*)"1D") {
3173           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const int s1"<<eo(1)<<");\n";
3174         } else if (dim==(const char*)"2D") {
3175           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const int s1, const int s2"<<eo(1)<<");\n";
3176         } else if (dim==(const char*)"3D") {
3177           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const int s1, const int s2, const int s3"<<eo(1)<<");\n";
3178         /*} else if (dim==(const char*)"4D") {
3179           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4"<<eo(1)<<");\n";
3180         } else if (dim==(const char*)"5D") {
3181           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n";
3182         } else if (dim==(const char*)"6D") {
3183           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5, const short s6"<<eo(1)<<");\n"; */
3184         }
3185       }
3186   }
3187   else if (container->getForWhom()==forSection) { }
3188 }
3189
3190 void Entry::genArrayStaticConstructorDefs(XStr& str)
3191 {
3192   if (container->getForWhom()==forIndividual)
3193       str<<
3194       makeDecl("void",1)<<"::insert("<<paramComma(0,0)<<"int onPE"<<eo(0)<<")\n"
3195       "{ \n"<<marshallMsg()<<
3196       "   ckInsert((CkArrayMessage *)impl_msg,"<<epIdx()<<",onPE);\n}\n";
3197   else if (container->getForWhom()==forAll){
3198       str<<
3199       makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const CkArrayOptions &opts"<<eo(0)<<")\n"
3200        "{ \n"<<marshallMsg()<<
3201          "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",opts);\n"
3202        "}\n";
3203       if (container->isArray()) {
3204         XStr dim = ((Array*)container)->dim();
3205         if (dim==(const char*)"1D") {
3206           str<<
3207             makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const int s1"<<eo(0)<<")\n"
3208             "{ \n"<<marshallMsg()<<
3209             "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",CkArrayOptions(s1));\n"
3210             "}\n";
3211         } else if (dim==(const char*)"2D") {
3212           str<<
3213             makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const int s1, const int s2"<<eo(0)<<")\n"
3214             "{ \n"<<marshallMsg()<<
3215             "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",CkArrayOptions(s1, s2));\n"
3216             "}\n";
3217         } else if (dim==(const char*)"3D") {
3218           str<<
3219             makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const int s1, const int s2, const int s3"<<eo(0)<<")\n"
3220             "{ \n"<<marshallMsg()<<
3221             "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",CkArrayOptions(s1, s2, s3));\n"
3222             "}\n";
3223         /*} else if (dim==(const char*)"4D") {
3224           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4"<<eo(1)<<");\n";
3225         } else if (dim==(const char*)"5D") {
3226           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n";
3227         } else if (dim==(const char*)"6D") {
3228           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5, const short s6"<<eo(1)<<");\n";
3229         */
3230         }
3231       }
3232   }
3233
3234 }
3235
3236
3237 /******************************** Group Entry Points *********************************/
3238
3239 void Entry::genGroupDecl(XStr& str)
3240 {
3241 #if 0
3242   if (isImmediate() && !container->isNodeGroup()) {
3243       cerr << (char *)container->baseName() << ": Group does not allow immediate message.\n";
3244       exit(1);
3245   }
3246 #endif
3247   if (isLocal() && container->isNodeGroup()) {
3248     cerr << (char*)container->baseName() << ": Nodegroup does not allow LOCAL entry methods.\n";
3249     exit(1);
3250   }
3251
3252   if(isConstructor()) {
3253     str << "    " << generateTemplateSpec(tspec) << "\n";
3254     genGroupStaticConstructorDecl(str);
3255   } else {
3256     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3257     str << "    " << generateTemplateSpec(tspec) << "\n";
3258     if (isLocal())
3259       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<");\n";
3260     else
3261       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1)<<");\n";
3262     // entry method on multiple PEs declaration
3263     if(!container->isForElement() && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
3264       str << "    " << generateTemplateSpec(tspec) << "\n";
3265       str << "    "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(1)<<");\n";
3266       str << "    " << generateTemplateSpec(tspec) << "\n";
3267       str << "    "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(1)<<");\n";
3268     }
3269   }
3270 }
3271
3272 void Entry::genGroupDefs(XStr& str)
3273 {
3274   //Selects between NodeGroup and Group
3275   char *node = (char *)(container->isNodeGroup()?"Node":"");
3276
3277   if(isConstructor()) {
3278     genGroupStaticConstructorDefs(str);
3279   } else {
3280     int forElement=container->isForElement();
3281     XStr params; params<<epIdx()<<", impl_msg";
3282     XStr paramg; paramg<<epIdx()<<", impl_msg, ckGetGroupID()";
3283     XStr parampg; parampg<<epIdx()<<", impl_msg, ckGetGroupPe(), ckGetGroupID()";
3284     // append options parameter
3285     XStr opts; opts<<",0";
3286     if (isImmediate()) opts << "+CK_MSG_IMMEDIATE";
3287     if (isInline())  opts << "+CK_MSG_INLINE";
3288     if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
3289
3290     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3291
3292     XStr retStr; retStr<<retType;
3293     XStr msgTypeStr;
3294     if (isLocal())
3295       msgTypeStr<<paramType(0,1,0);
3296     else
3297       msgTypeStr<<paramType(0,1);
3298     str << makeDecl(retStr,1)<<"::"<<name<<"("<<msgTypeStr<<")\n";
3299     str << "{\n  ckCheck();\n";
3300     if (!isLocal()) str <<marshallMsg();
3301
3302     if (isLocal()) {
3303       XStr unmarshallStr; param->unmarshall(unmarshallStr);
3304       str << "  "<<container->baseName()<<" *obj = ckLocalBranch();\n";
3305       str << "  CkAssert(obj);\n";
3306       if (!isNoTrace()) str << "  _TRACE_BEGIN_EXECUTE_DETAILED(0,ForBocMsg,("<<epIdx()<<"),CkMyPe(),0,NULL);\n";
3307       str << "#if CMK_LBDB_ON\n"
3308 "  // if there is a running obj being measured, stop it temporarily\n"
3309 "  LDObjHandle objHandle;\n"
3310 "  int objstopped = 0;\n"
3311 "  LBDatabase *the_lbdb = (LBDatabase *)CkLocalBranch(_lbdb);\n"
3312 "  if (the_lbdb->RunningObject(&objHandle)) {\n"
3313 "    objstopped = 1;\n"
3314 "    the_lbdb->ObjectStop(objHandle);\n"
3315 "  }\n"
3316 "#endif\n";
3317       str << "#if CMK_CHARMDEBUG\n"
3318       "  CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
3319       "#endif\n  ";
3320       if (!retType->isVoid()) str << retType << " retValue = ";
3321       str << "obj->"<<name<<"("<<unmarshallStr<<");\n";
3322       str << "#if CMK_CHARMDEBUG\n"
3323       "  CpdAfterEp("<<epIdx()<<");\n"
3324       "#endif\n";
3325       str << "#if CMK_LBDB_ON\n"
3326 "  if (objstopped) the_lbdb->ObjectStart(objHandle);\n"
3327 "#endif\n";
3328       if (!isNoTrace()) str << "  _TRACE_END_EXECUTE();\n";
3329       if (!retType->isVoid()) str << "  return retValue;\n";
3330     } else if(isSync()) {
3331       str << syncReturn() <<
3332         "CkRemote"<<node<<"BranchCall("<<paramg<<", ckGetGroupPe()));\n";
3333     }
3334     else
3335     { //Non-sync entry method
3336       if (forElement)
3337       {// Send
3338         str << "  if (ckIsDelegated()) {\n";
3339         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
3340         str << "     ckDelegatedTo()->"<<node<<"GroupSend(ckDelegatedPtr(),"<<parampg<<");\n";
3341         str << "  } else CkSendMsg"<<node<<"Branch"<<"("<<parampg<<opts<<");\n";
3342       }
3343       else if (container->isForSection())
3344       {// Multicast
3345         str << "  if (ckIsDelegated()) {\n";
3346         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
3347         str << "     ckDelegatedTo()->"<<node<<"GroupSectionSend(ckDelegatedPtr(),"<<params<<", ckGetNumSections(), ckGetSectionIDs());\n";
3348         str << "  } else {\n";
3349         str << "    void *impl_msg_tmp = (ckGetNumSections()>1) ? CkCopyMsg((void **) &impl_msg) : impl_msg;\n";
3350         str << "    for (int i=0; i<ckGetNumSections(); ++i) {\n";
3351         str << "       impl_msg_tmp= (i<ckGetNumSections()-1) ? CkCopyMsg((void **) &impl_msg):impl_msg;\n";
3352         str << "       CkSendMsg"<<node<<"BranchMulti("<<epIdx()<<", impl_msg_tmp, ckGetGroupIDn(i), ckGetNumElements(i), ckGetElements(i)"<<opts<<");\n";
3353         str << "    }\n";
3354         str << "  }\n";
3355       }
3356       else
3357       {// Broadcast
3358         str << "  if (ckIsDelegated()) {\n";
3359         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
3360         str << "     ckDelegatedTo()->"<<node<<"GroupBroadcast(ckDelegatedPtr(),"<<paramg<<");\n";
3361         str << "  } else CkBroadcastMsg"<<node<<"Branch("<<paramg<<opts<<");\n";
3362       }
3363     }
3364     str << "}\n";
3365
3366     // entry method on multiple PEs declaration
3367     if(!forElement && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
3368       str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(0)<<") {\n";
3369       str << marshallMsg();
3370       str << "  CkSendMsg"<<node<<"BranchMulti("<<paramg<<", npes, pes"<<opts<<");\n";
3371       str << "}\n";
3372       str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(0)<<") {\n";
3373       str << marshallMsg();
3374       str << "  CkSendMsg"<<node<<"BranchGroup("<<paramg<<", grp"<<opts<<");\n";
3375       str << "}\n";
3376     }
3377   }
3378 }
3379
3380 void Entry::genGroupStaticConstructorDecl(XStr& str)
3381 {
3382   if (container->isForElement()) return;
3383   if (container->isForSection()) return;
3384
3385   str << "    static CkGroupID ckNew("<<paramType(1,1)<<");\n";
3386   if (!param->isVoid()) {
3387     str << "    "<<container->proxyName(0)<<"("<<paramType(1,1)<<");\n";
3388   }
3389 }
3390
3391 void Entry::genGroupStaticConstructorDefs(XStr& str)
3392 {
3393   if (container->isForElement()) return;
3394   if (container->isForSection()) return;
3395
3396   //Selects between NodeGroup and Group
3397   char *node = (char *)(container->isNodeGroup()?"Node":"");
3398   str << makeDecl("CkGroupID",1)<<"::ckNew("<<paramType(0,1)<<")\n";
3399   str << "{\n"<<marshallMsg();
3400   str << "  return CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg);\n";
3401   str << "}\n";
3402
3403   if (!param->isVoid()) {
3404     str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramType(0,1)<<")\n";
3405     str << "{\n"<<marshallMsg();
3406     str << "  ckSetGroupID(CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg));\n";
3407     str << "}\n";
3408   }
3409 }
3410
3411 /******************* Python Entry Point Code **************************/
3412 void Entry::genPythonDecls(XStr& str) {
3413   str <<"/* STATIC DECLS: "; print(str); str << " */\n";
3414   if (isPython()) {
3415     // check the parameter passed to the function, it must be only an integer
3416     if (!param || param->next || !param->param->getType()->isBuiltin() || !((BuiltinType*)param->param->getType())->isInt()) {
3417       die("A python entry method must accept only one parameter of type `int`");
3418     }
3419
3420     str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg);\n";
3421   }
3422 }
3423
3424 void Entry::genPythonDefs(XStr& str) {
3425   str <<"/* DEFS: "; print(str); str << " */\n";
3426   if (isPython()) {
3427
3428     str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg) {\n";
3429     str << "  PyObject *dict = PyModule_GetDict(PyImport_AddModule(\"__main__\"));\n";
3430     str << "  int pyNumber = PyInt_AsLong(PyDict_GetItemString(dict,\"__charmNumber__\"));\n";
3431     str << "  PythonObject *pythonObj = (PythonObject *)PyLong_AsVoidPtr(PyDict_GetItemString(dict,\"__charmObject__\"));\n";
3432     str << "  "<<container->baseName()<<" *object = static_cast<"<<container->baseName()<<" *>(pythonObj);\n";
3433     str << "  object->pyWorkers[pyNumber].arg=arg;\n";
3434     str << "  object->pyWorkers[pyNumber].result=&CtvAccess(pythonReturnValue);\n";
3435     str << "  object->pyWorkers[pyNumber].pythread=PyThreadState_Get();\n";
3436     str << "  CtvAccess(pythonReturnValue) = 0;\n";
3437
3438     str << "  //pyWorker->thisProxy."<<name<<"(pyNumber);\n";
3439     str << "  object->"<<name<<"(pyNumber);\n";
3440
3441     str << "  //CthSuspend();\n";
3442
3443     str << "  if (CtvAccess(pythonReturnValue)) {\n";
3444     str << "    return CtvAccess(pythonReturnValue);\n";
3445     str << "  } else {\n";
3446     str << "    Py_INCREF(Py_None); return Py_None;\n";
3447     str << "  }\n";
3448     str << "}\n";
3449   }
3450 }
3451
3452 void Entry::genPythonStaticDefs(XStr& str) {
3453   if (isPython()) {
3454     str << "  {\""<<name<<"\",_Python_"<<container->baseName()<<"_"<<name<<",METH_VARARGS},\n";
3455   }
3456 }
3457
3458 void Entry::genPythonStaticDocs(XStr& str) {
3459   if (isPython()) {
3460     str << "\n  \""<<name<<" -- \"";
3461     if (pythonDoc) str <<(char*)pythonDoc;
3462     str <<"\"\\\\n\"";
3463   }
3464 }
3465
3466
3467 /******************* Accelerator (Accel) Entry Point Code ********************/
3468
3469 void Entry::genAccelFullParamList(XStr& str, int makeRefs) {
3470
3471   if (!isAccel()) return;
3472
3473   ParamList* curParam = NULL;
3474   int isFirst = 1;
3475
3476   // Parameters (which are read only by default)
3477   curParam = param;
3478   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
3479   while (curParam != NULL) {
3480
3481     if (!isFirst) { str << ", "; }
3482
3483     Parameter* param = curParam->param;
3484
3485     if (param->isArray()) {
3486       str << param->getType()->getBaseName() << "* " << param->getName();
3487     } else {
3488       str << param->getType()->getBaseName() << " " << param->getName();
3489     }
3490
3491     isFirst = 0;
3492     curParam = curParam->next;
3493   }
3494
3495   // Accel parameters
3496   curParam = accelParam;
3497   while (curParam != NULL) {
3498
3499     if (!isFirst) { str << ", "; }
3500
3501     Parameter* param = curParam->param;
3502     int bufType = param->getAccelBufferType();
3503     int needWrite = makeRefs && ((bufType == Parameter::ACCEL_BUFFER_TYPE_READWRITE) || (bufType == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY));
3504     if (param->isArray()) {
3505       str << param->getType()->getBaseName() << "* " << param->getName();
3506     } else {
3507       str << param->getType()->getBaseName() << ((needWrite) ? (" &") : (" ")) << param->getName();
3508     }
3509
3510     isFirst = 0;
3511     curParam = curParam->next;
3512   }
3513
3514   // Implied object pointer
3515   if (!isFirst) { str << ", "; }
3516   str << container->baseName() << "* impl_obj";
3517 }
3518
3519 void Entry::genAccelFullCallList(XStr& str) {
3520   if (!isAccel()) return;
3521
3522   int isFirstFlag = 1;
3523
3524   // Marshalled parameters to entry method
3525   ParamList* curParam = param;
3526   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
3527   while (curParam != NULL) {
3528     if (!isFirstFlag) str << ", ";
3529     isFirstFlag = 0;
3530     str << curParam->param->getName();
3531     curParam = curParam->next;
3532   }
3533
3534   // General variables (prefix with "impl_obj->" for member variables of the current object)