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