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