1928d9501c78c3d7bad6ece93c19c4c65cfe0aee
[charm.git] / src / xlat-i / xi-symbol.C
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 #include <iostream.h>
9 #include <fstream.h>
10 //  #include <string>
11 #include <stdlib.h>
12 #include "xi-symbol.h"
13 #include <ctype.h> // for tolower()
14
15 CompileMode compilemode;
16 MessageList message_list;
17 int fortranMode;
18
19 // Make the name lower case
20 char* fortranify(const char *s)
21 {
22   int i, len = strlen(s);
23   char *retVal;
24   retVal = new char[len+1];
25   for(i = 0; i < len; i++)
26     retVal[i] = tolower(s[i]);
27   retVal[len] = 0;
28
29   return retVal;
30 }
31
32 Value::Value(char *s)
33 {
34   factor = 1;
35   val = s;
36   if(val == 0 || strlen(val)==0 ) return;
37   int pos = strlen(val)-1;
38   if(val[pos]=='K' || val[pos]=='k') {
39     val[pos] = '\0';
40     factor = 1024;
41   }
42   if(val[pos]=='M' || val[pos]=='m') {
43     val[pos] = '\0';
44     factor = 1024*1024;
45   }
46 }
47
48
49 int
50 Value::getIntVal(void)
51 {
52   if(val==0 || strlen(val)==0) return 0;
53   return (atoi((const char *)val)*factor);
54 }
55
56 void 
57 ConstructList::setExtern(int e) 
58 {
59   Construct::setExtern(e);
60   if(construct)
61     construct->setExtern(e);
62   if(next)
63     next->setExtern(e);
64 }
65
66 void 
67 ConstructList::print(XStr& str) 
68 {
69   if(construct)
70     construct->print(str);
71   if(next) 
72     next->print(str);
73 }
74
75 void 
76 TParamList::print(XStr& str) 
77 {
78   tparam->print(str); 
79   if(next) { 
80     str << ","; 
81     next->print(str); 
82   }
83 }
84
85
86 void 
87 Type::genProxyName(XStr &str) 
88 {
89   cerr<< getBaseName() << " type has no proxy!!\n";
90   exit(1);
91 }
92     
93 void 
94 NamedType::print(XStr& str)
95 {
96   str << name;
97   if(tparams) {
98     str << "<"<<tparams<<">";
99   }
100 }
101
102 void 
103 PtrType::print(XStr& str)
104 {
105   type->print(str);
106   for(int i=0;i<numstars;i++)
107     str << "*";
108 }
109
110 void 
111 TypeList::print(XStr& str)
112 {
113   type->print(str);
114   if(next) {
115     str << ", ";
116     next->print(str);
117   }
118 }
119
120 void 
121 MemberList::print(XStr& str)
122 {
123   member->print(str);
124   if(next)
125     next->print(str);
126 }
127
128
129 void 
130 Chare::print(XStr& str)
131 {
132   if(external)
133     str << "extern ";
134   if(templat)
135     templat->genSpec(str);
136   
137   str << chareTypeName()<<" "<<type;
138   if(bases) { str << ": "; bases->print(str); }
139   if(list) {
140     str << "{\n"; list->print(str); str << "};\n";
141   } else {
142     str << ";\n";
143   }
144 }
145
146 void 
147 Message::print(XStr& str)
148 {
149   if(external)
150     str << "extern ";
151   if(templat)
152     templat->genSpec(str);
153   str << "message ";
154   type->print(str);
155   if(isVarrays()) {
156     str << "{\n";
157     mvlist->print(str);
158     str << "}\n";
159   }
160   str << ";\n";
161 }
162
163 void 
164 TType::print(XStr& str)
165 {
166   str << "class ";
167   type->print(str);
168   if(init) {
169     str << "=";
170     init->print(str);
171   }
172 }
173
174 void 
175 TName::print(XStr& str)
176 {
177   type->print(str);
178   str << " "<<name;
179   if(val) {
180     str << "=";
181     str << val;
182   }
183 }
184
185
186 void 
187 TVarList::print(XStr& str)
188 {
189   tvar->print(str);
190   if(next) {
191     str << ", ";
192     next->print(str);
193   }
194 }
195
196 void 
197 Template::print(XStr& str)
198 {
199   if(entity)
200     entity->print(str);
201 }
202
203 void 
204 Entry::print(XStr& str)
205 {
206   if(isThreaded())
207     str << "threaded ";
208   if(isSync())
209     str << "sync ";
210   if(retType) {
211     retType->print(str);
212     str << " ";
213   }
214   str << name<<"(";
215   if(param)
216     param->print(str);
217   str << ")";
218   if(stacksize) {
219     str << " stacksize = "; 
220     stacksize->print(str);
221   }
222   str << ";\n";
223 }
224
225 void 
226 Module::print(XStr& str)
227 {
228   if(external)
229     str << "extern ";
230   str << "module "<<name;
231   if(clist) {
232     str << " {\n";
233     clist->print(str);
234     str << "}\n";
235   } else {
236     str << ";\n";
237   }
238 }
239
240 void
241 Module::generate()
242 {
243   XStr declstr, defstr;
244   
245   declstr << 
246   "#ifndef _DECL_"<<name<<"_H_\n"
247   "#define _DECL_"<<name<<"_H_\n"
248   "#include \"charm++.h\"\n";
249   clist->genDecls(declstr);
250   declstr << "extern void _register"<<name<<"(void);\n";
251   if(isMain()) {
252     declstr << "extern \"C\" void CkRegisterMainModule(void);\n";
253   }
254   declstr << "#endif"<<endx;
255   // defstr << "#ifndef _DEFS_"<<name<<"_H_"<<endx;
256   // defstr << "#define _DEFS_"<<name<<"_H_"<<endx;
257   clist->genDefs(defstr);
258   defstr << 
259   "#ifndef CK_TEMPLATES_ONLY\n"
260   "void _register"<<name<<"(void)\n"
261   "{\n"
262   "  static int _done = 0; if(_done) return; _done = 1;\n";
263   clist->genReg(defstr);
264   defstr << "}\n";
265   if(isMain()) {
266     if (fortranMode) defstr << "extern void _registerf90main(void);\n";
267     defstr << "extern \"C\" void CkRegisterMainModule(void) {\n";
268     if (fortranMode) { // For Fortran90
269       defstr << "  // FORTRAN\n";
270       defstr << "  _registerf90main();\n";
271     }
272     defstr << 
273     "  _register"<<name<<"();\n"
274     "  _REGISTER_DONE();\n"
275     "}\n";
276   }
277   defstr << "#endif\n";
278   // defstr << "#endif"<<endx;
279   XStr topname, botname;
280   topname<<name<<".decl.h";
281   botname<<name<<".def.h";
282   ofstream decl(topname.get_string()), def(botname.get_string());
283   if(!decl || !def) {
284     cerr<<"Cannot open "<<topname.get_string()<<"or "
285         <<botname.get_string()<<" for writing!!\n";
286     exit(1);
287   }
288   decl<<declstr.get_string();
289   def<<defstr.get_string();
290 }
291
292 void 
293 ModuleList::print(XStr& str) 
294 {
295   module->print(str);
296   if(next)
297     next->print(str);
298 }
299
300 void 
301 ModuleList::generate()
302 {
303   module->generate();
304   if(next)
305     next->generate();
306 }
307
308 void 
309 Readonly::print(XStr& str)
310 {
311   if(external)
312     str << "extern ";
313   str << "readonly ";
314   if(msg)
315     str << "message ";
316   type->print(str);
317   if(msg)
318     str << " *";
319   else
320     str << " ";
321   str << name;
322   if(dims)
323     dims->print(str);
324   str << ";\n";
325 }
326
327 void
328 MemberList::setChare(Chare *c)
329 {
330   member->setChare(c);
331   if(next)
332     next->setChare(c);
333 }
334
335 int
336 MemberList::isPure(void)
337 {
338   if(member->isPure())
339     return 1;
340   if(next)
341     return next->isPure();
342   return 0;
343 }
344
345 void
346 ConstructList::genDecls(XStr& str)
347 {
348   if(construct) {
349     construct->genDecls(str);
350     str << endx;
351   }
352   if(next)
353     next->genDecls(str);
354 }
355
356 void
357 ConstructList::genDefs(XStr& str)
358 {
359   if(construct) {
360     construct->genDefs(str);
361     str << endx;
362   }
363   if(next)
364     next->genDefs(str);
365 }
366
367 void
368 ConstructList::genReg(XStr& str)
369 {
370   if(construct) {
371     construct->genReg(str);
372     str << endx;
373   }
374   if(next)
375     next->genReg(str);
376 }
377
378 static const char *CIChareStart = // prefix, name
379 "{\n"
380 "  public:\n"
381 "    static int __idx;\n"
382 ;
383
384 static const char *CIChareEnd =
385 "};\n"
386 ;
387
388 Chare::Chare(int ln, NamedType *t, TypeList *b, MemberList *l, int mig)
389          : type(t), list(l), bases(b), migratable(mig) 
390 {
391         line = ln;
392         setTemplate(0); 
393         abstract=0;
394         if (list)
395         {
396                 list->setChare(this);
397                 if (list->isPure()) abstract=1;
398                 else /*not at abstract class--*/
399                 //Add migration constructor to MemberList
400                   if(!t->isTemplated() && migratable) {
401                         Entry *e=new Entry(ln,SMIGRATE,NULL,
402                         (char *)type->getBaseName(),
403                         new PtrType(new NamedType("CkMigrateMessage")));
404                         e->setChare(this);
405                         list=new MemberList(e,list);
406                   }
407         }
408 }
409
410
411 void
412 Chare::genRegisterMethodDecl(XStr& str)
413 {
414   if(external || type->isTemplated())
415     return;
416   str << "    static void __register(const char *s, size_t size);\n";
417 }
418
419 void
420 Chare::genRegisterMethodDef(XStr& str)
421 {
422   if(external || type->isTemplated())
423     return;
424   if(!templat) {
425     str << "#ifndef CK_TEMPLATES_ONLY\n";
426   } else {
427     str << "#ifdef CK_TEMPLATES_ONLY\n";
428   }
429   genTSpec(str);
430   str <<  
431   "    void "<<proxyName()<<"::__register(const char *s, size_t size) {\n"
432   "      __idx = CkRegisterChare(s, size);\n";
433   // register all bases
434   if(bases !=0)
435     bases->genProxyNames(str, "  _REGISTER_BASE(__idx, ", "::__idx);\n", "");
436   if(list)
437     list->genReg(str);
438   if(migratable) {
439     str << "      CkRegisterMigCtor(__idx, " << 
440                     "__idx_"<<type->getBaseName()<<"_CkMigrateMessage);\n";
441   }
442   str << "    }\n";
443   str << "#endif\n";
444 }
445
446 void
447 Chare::genDecls(XStr& str)
448 {
449   if(type->isTemplated())
450     return;
451   str << "/* DECLS: "; print(str); str << " */\n";
452   if(templat)
453     templat->genSpec(str);
454   str << "class "<<type<<";\n";
455   if(templat)
456     templat->genSpec(str);
457   genSubDecls(str);
458 }
459
460
461 void
462 Chare::genSubDecls(XStr& str)
463 {
464   XStr ptype;
465   ptype<<proxyPrefix()<<type;
466   
467   str << "class "<<ptype;
468   if(external || type->isTemplated()) {
469     str << ";";
470     return;
471   }
472   str << ": public virtual _CK_CID";
473   if(bases!=0) {
474     str << ", ";
475     bases->genProxyNames(str, "public ", "", ", ");
476   }
477   str << CIChareStart;
478   genRegisterMethodDecl(str);
479   if(isAbstract())
480     str << "    "<<ptype<<"(void) {};\n";
481   str << "    "<<ptype<<"(CkChareID __cid) ";
482   if(bases !=0) {
483     str << ":";
484     bases->genProxyNames(str, "", "(__cid)", ", ");
485   }
486   str << "{ ckSetChareId(__cid); }\n";
487   str << "    CkChareID ckGetChareId(void) { return _ck_cid; }\n";
488   str << "    void ckSetChareId(CkChareID __cid) {_CHECK_CID(__cid,__idx);_ck_cid=__cid;}\n";
489   if(list)
490     list->genDecls(str);
491   str << CIChareEnd;
492 }
493
494 void
495 Group::genSubDecls(XStr& str)
496 {
497   XStr ptype,ttype;
498   ptype<<proxyPrefix()<<type;
499   ttype<<type;
500   if(templat) {
501     templat->genVars(ttype);
502   }
503   
504   str << "class "<<ptype;
505   if(external || type->isTemplated()) {
506     str << ";";
507     return;
508   }
509   str << ": ";
510   if(isNodeGroup())
511     str << " public virtual _CK_NGID";
512   else
513     str << " public virtual _CK_GID";
514   if(bases!=0) {
515     str << ", ";
516     bases->genProxyNames(str, "public ", "", ", ");
517   }
518   str << CIChareStart;
519   genRegisterMethodDecl(str);
520   if(isAbstract())
521     str << "    "<<ptype<<"(void) {};\n";
522   str << "    "<<ptype<<"(CkGroupID _gid) ";
523   if(bases !=0) {
524     str << ":";
525     bases->genProxyNames(str, "", "(_gid)", ", ");
526   }
527   str << "{ _ck_gid = _gid; _setChare(0); }\n";
528   str << "    "<<ptype<<"(CkChareID __cid) ";
529   if(bases !=0) {
530     str << ":";
531     bases->genProxyNames(str, "", "(__cid)", ", ");
532   }
533   str << "{ ckSetChareId(__cid); }\n";
534   str << "    CkChareID ckGetChareId(void) { return _ck_cid; }\n";
535   str << "    void ckSetChareId(CkChareID __cid){_CHECK_CID(__cid,__idx);_ck_cid=__cid;_setChare(1);}\n";
536   str << "    CkGroupID ckGetGroupId(void) { return _ck_gid; }\n";
537   str << "    void ckSetGroupId(CkGroupID _gid){_ck_gid=_gid;_setChare(0);}\n";
538   str << "    "<<ttype<<"* ckLocalBranch(void) {\n";
539   str << "      return ("<<ttype;
540   if(isNodeGroup())
541     str << " *) CkLocalNodeBranch(_ck_gid);\n";
542   else
543     str << " *) CkLocalBranch(_ck_gid);\n";
544   str << "    }\n";
545   str << "    static "<<ttype;
546   str << "* ckLocalBranch(CkGroupID gID) {\n";
547   str << "      return ("<<ttype;
548   if(isNodeGroup())
549     str << " *) CkLocalNodeBranch(gID);\n";
550   else
551     str << " *) CkLocalBranch(gID);\n";
552   str << "    }\n";
553   if(list)
554     list->genDecls(str);
555   str << CIChareEnd;
556 }
557
558
559 //Array Constructor
560 Array::Array(int ln, NamedType *index,
561         NamedType *t, TypeList *b, MemberList *l)  
562     : Chare(ln,t,b,l,0x01) 
563 {
564         index->print(indexSuffix);
565         if (indexSuffix!=(const char*)"none")
566                 indexType<<"CkArrayIndex"<<indexSuffix;
567         else indexType<<"CkArrayIndex";
568 //Add ArrayElement to the list of bases (if we're not ArrayElement ourselves)
569         if((!bases)&&(0!=strcmp(type->getBaseName(),"ArrayElement")))
570                 bases = new TypeList(new NamedType("ArrayElement"), bases);
571 }
572
573 void
574 Array::genSubDecls(XStr& str)
575 {
576   XStr ptype;
577   ptype<<proxyPrefix()<<type;
578   
579   str << "class "<<ptype;
580   if(external || type->isTemplated()) {
581     str << ";";
582     return;
583   }
584   str << " : ";
585   bool fakeBase=false;
586   if(bases==0) {
587         fakeBase=true;//<- "CkArrayBase" is a base class, but is used only for implementation.
588         bases=new TypeList(new NamedType("CkArrayBase"),NULL);
589   }
590   bases->genProxyNames(str, "public ", "", ", ");
591   
592   str << CIChareStart;
593   genRegisterMethodDecl(str);
594   
595   //Create an empty array
596   str <<"    static CkGroupID buildArrayGroup(CkGroupID mapID=_RRMapID,int numInitial=0)\n"
597         "    {\n"
598         "        return CkArray::CreateArray(mapID,numInitial);\n"
599         "    }\n";
600
601   if (is1D()) //Create an array with some 1D elements
602   {
603     str <<"    static CkGroupID buildArrayGroup(int ctorIndex,int numInitial,CkGroupID mapID,\n"
604         "            CkArrayMessage *msg)\n"
605         "    {\n"
606         "        CkGroupID id=buildArrayGroup(mapID,numInitial);\n"
607         "        CProxy_CkArrayBase(id).base_insert1D(ctorIndex,numInitial,msg);\n"
608         "        return id;\n"
609         "    }\n";
610   }
611   
612   //This constructor is used for array indexing
613   str << "  protected:\n"
614          "    "<<ptype<<"(const CkArrayID &aid,const "<<indexType<<" &idx)\n"
615          "        :";bases->genProxyNames(str, "", "(aid,idx)", ", ");str<<" {}\n";
616 //         "      :CProxy_CkArrayBase(aid,idx) {}\n";
617   str << "  public:\n"
618          "    "<<ptype<<"(const CkArrayID &aid) \n"
619          "        :";bases->genProxyNames(str, "", "(aid)", ", ");str<<" {}\n";
620 //         "      :CProxy_CkArrayBase(aid) {}\n";
621   str << "    "<<ptype<<"(void) {}\n";//An empty constructor
622   
623   str<< //Build a simple, empty array
624   "    static CkArrayID ckNew(void) {return CkArrayID(buildArrayGroup());}\n"
625   "    static CkArrayID ckNew_mapped(CkGroupID mapID) {return CkArrayID(buildArrayGroup(mapID));}\n";
626   
627   if (indexSuffix!=(const char*)"none")
628   {
629     str <<
630     "//Generalized array indexing: (these KEEP the index you pass in!)\n"
631     "    "<<ptype<<" operator [] (const "<<indexType<<" &idx) const\n"
632     "        {return "<<ptype<<"(_aid, idx);}\n"
633     "    "<<ptype<<" operator() (const "<<indexType<<" &idx) const\n"
634     "        {return "<<ptype<<"(_aid, idx);}\n";
635   }
636   
637   //Add specialized indexing for these common types
638   if (indexSuffix==(const char*)"1D")
639   {
640     str << 
641     "    "<<ptype<<" operator [] (int idx) const \n"
642     "        {return "<<ptype<<"(_aid, CkArrayIndex1D(idx));}\n"
643     "    "<<ptype<<" operator () (int idx) const \n"
644     "        {return "<<ptype<<"(_aid, CkArrayIndex1D(idx));}\n";
645   } else if (indexSuffix==(const char*)"2D") {
646     str << 
647     "    "<<ptype<<" operator () (int i0,int i1) const \n"
648     "        {return "<<ptype<<"(_aid, CkArrayIndex2D(i0,i1));}\n";
649   } else if (indexSuffix==(const char*)"3D") {
650     str << 
651     "    "<<ptype<<" operator () (int i0,int i1,int i2) const \n"
652     "        {return "<<ptype<<"(_aid, CkArrayIndex3D(i0,i1,i2));}\n";
653   }
654   if (fakeBase) bases=NULL;//<- return bases to original value
655
656   if(list)
657     list->genDecls(str);
658   str << CIChareEnd;
659 }
660
661 void
662 Chare::genDefs(XStr& str)
663 {
664   str << "/* DEFS: "; print(str); str << " */\n";
665   if (fortranMode) { // For Fortran90
666     if (!isArray()) { // Currently, only arrays are supported
667       cerr << (char *)baseName() << ": only chare arrays are currently supported\n";
668       exit(1);
669     }
670     // We have to generate the chare array itself
671     str << "/* FORTRAN */\n";
672     str << "extern \"C\" void " << fortranify(baseName()) << "_allocate_(char **, void *);\n";
673     str << "\n";
674     str << "class " << baseName() << " : public ArrayElement1D\n";
675     str << "{\n";
676     str << "public:\n";
677     str << "  char user_data[64];\n";
678     str << "public:\n";
679     str << "  " << baseName() << "()\n";
680     str << "  {\n";
681 //    str << "    CkPrintf(\"" << baseName() << " %d created\\n\",thisIndex);\n";
682     str << "    CkArrayID *aid = &thisArrayID;\n";
683     str << "    " << fortranify(baseName()) << "_allocate_((char **)&user_data, &aid);\n";
684     str << "  }\n";
685     str << "\n";
686     str << "  " << baseName() << "(CkMigrateMessage *m)\n";
687     str << "  {\n";
688     str << "    CkPrintf(\"" << baseName() << " %d migrating\\n\",thisIndex);\n";
689     str << "  }\n";
690     str << "\n";
691     str << "};\n";
692     str << "\n";
693     str << "extern \"C\" void " << fortranify(baseName()) << "_cknew_(int *numElem, long *aindex)\n";
694     str << "{\n";
695     str << "    CkArrayID *aid = new CkArrayID;\n";
696     str << "    *aid = CProxy_" << baseName() << "::ckNew(*numElem); \n";
697     str << "    *aindex = (long)aid;\n";
698     str << "}\n";
699
700   }
701   if(!type->isTemplated()) {
702     if(!templat) {
703       str << "#ifndef CK_TEMPLATES_ONLY\n";
704     } else {
705       str << "#ifdef CK_TEMPLATES_ONLY\n";
706     }
707     if(external) str << "extern ";
708     genTSpec(str);
709     str << "int "<<proxyName()<<"::__idx";
710     if(!external) str << "=0";
711     str << ";\n";
712     str << "#endif\n";
713   }
714   if(!external && !type->isTemplated())
715     genRegisterMethodDef(str);
716   if(list) 
717   {//Add definitions for all entry points
718     
719     if(isTemplated())
720       str << "#ifdef CK_TEMPLATES_ONLY\n";
721     else
722       str << "#ifndef CK_TEMPLATES_ONLY\n";
723     list->genDefs(str);
724     str << "#endif /*CK_TEMPLATES_ONLY*/\n";
725   }
726 }
727
728 void
729 Chare::genReg(XStr& str)
730 {
731   str << "/* REG: "; print(str); str << "*/\n";
732   if(external || templat)
733     return;
734   str << "  "<<proxyPrefix();
735   str << type<<"::__register(\""<<type<<"\", sizeof("<<type<<"));\n";
736 }
737
738 static const char *CIMsgClass =
739 "{\n"
740 "  public:\n"
741 "    static int __idx;\n"
742 "    void*operator new(size_t s){return CkAllocMsg(__idx,s,0);}\n"
743 "    void operator delete(void *p){CkFreeMsg(p);}\n"
744 "    void*operator new(size_t,void*p){return p;}\n"
745 "    void*operator new(size_t s, int p){return CkAllocMsg(__idx,s,p);}\n"
746 ;
747
748 static const char *CIMsgClassAnsi =
749 "{\n"
750 "  public:\n"
751 "    static int __idx;\n"
752 "    void*operator new(size_t s){return CkAllocMsg(__idx,s,0);}\n"
753 "    void operator delete(void *p){CkFreeMsg(p);}\n"
754 "    void*operator new(size_t,void*p){return p;}\n"
755 "    void operator delete(void*,void*){}\n"
756 "    void*operator new(size_t s, int p){return CkAllocMsg(__idx,s,p);}\n"
757 "    void operator delete(void *,int){}\n"
758 ;
759
760 static const char *CIAllocDecl =
761 "    void *operator new(size_t s, int *sz, int p);\n"
762 ;
763
764 static const char *CIAllocDeclAnsi =
765 "    void *operator new(size_t s, int *sz, int p);\n"
766 "    void operator delete(void*,int *,int);\n"
767 ;
768
769 void
770 Message::genAllocDecl(XStr &str)
771 {
772   if(compilemode==ansi)
773     str << CIMsgClassAnsi;
774   else str << CIMsgClass;
775
776   if(isVarsize()) {
777     if(compilemode==ansi)
778       str << CIAllocDeclAnsi;
779     else str << CIAllocDecl;
780   }
781   if(isVarrays()) {
782     int num = mvlist->len();
783     str << "    void *operator new(size_t s,";
784     int i;
785     for(i=0;i<num;i++)
786       str << "int sz" << i << ", ";
787     str << "int p);\n";
788     if(compilemode==ansi) {
789       str << "    void operator delete(void*,";
790       for(i=0;i<num;i++)
791         str << "int, ";
792       str << "int);\n";
793     }
794   }
795 }
796
797 void
798 Message::genVarraysMacros(XStr& str)
799 {
800   int num = mvlist->len();
801   assert(num>0);
802   MsgVarList *ml = mvlist;
803   MsgVar *mv = ml->msg_var;
804   int i;
805   str << "\n#define " << type << "_VARSIZE_MACROS() \\\n";
806   str << "  static void* alloc(int msgnum, int sz, int *sizes, int pb) {\\\n";
807   str << "    int offsets[" << num+1 << "];\\\n";
808   str << "    offsets[0] = ALIGN8(sz);\\\n";
809   for(i=1; i<=num; i++) {
810     str << "    offsets[" << i << "] = offsets[" << i-1 << "] + ";
811     str << "ALIGN8(sizeof(" << mv->type << ")*sizes[" << i-1 << "]);\\\n";
812     ml = ml->next;
813     if (ml != 0) mv = ml->msg_var;
814   }
815   ml = mvlist;
816   mv = ml->msg_var;
817   str << "    " << type << " *newmsg = (" << type << " *) ";
818   str << "CkAllocMsg(msgnum, offsets[" << num << "], pb);\\\n";
819   for(i=0;i<num;i++) {
820     str << "    newmsg->" << mv->name << " = (" << mv->type << " *) ";
821     str << "((char *)newmsg + offsets[" << i << "]);\\\n";
822     ml = ml->next;
823     if (ml != 0) mv = ml->msg_var;
824   }
825   str << "    return (void *) newmsg;\\\n";
826   str << "  }\\\n";
827   str << "  static void* pack(" << type << "* msg) {\\\n";
828   ml = mvlist;
829   mv = ml->msg_var;
830   for(i=0;i<num;i++) {
831     str << "    msg->" << mv->name << " = (" <<mv->type << " *) ";
832     str << "((char *)msg->" << mv->name << " - (char *)msg);\\\n";
833     ml = ml->next;
834     if (ml != 0) mv = ml->msg_var;
835   }
836   str << "    return (void *) msg;\\\n";
837   str << "  }\\\n";
838   str << "  static " << type << "* unpack(void* buf) {\\\n";
839   str << "    " << type << " * msg = (" << type << " *) buf;\\\n";
840   ml = mvlist;
841   mv = ml->msg_var;
842   for(i=0;i<num;i++) {
843     str << "    msg->" << mv->name << " = (" <<mv->type << " *) ";
844     str << "((size_t)msg->" << mv->name << " + (char *)msg);\\\n";
845     ml = ml->next;
846     if (ml != 0) mv = ml->msg_var;
847   }
848   str << "    return msg;\\\n";
849   str << "  }\n";
850 }
851
852 void
853 Message::genDecls(XStr& str)
854 {
855   XStr ptype;
856   ptype<<proxyPrefix()<<type;
857   if(type->isTemplated())
858     return;
859   if(isVarrays())
860     genVarraysMacros(str);
861   str << "/* DECLS: "; print(str); str << " */\n";
862   if(templat)
863     templat->genSpec(str);
864   str << "class ";
865   type->print(str);
866   str << ";\n";
867   if(templat)
868     templat->genSpec(str);
869   str << "class "<<ptype;
870   if(external || type->isTemplated()) {
871     str << ";";
872     return;
873   }
874 //OSL 4/11/2000-- make *all* messages inherit from CkArrayMessage.
875 //  This means users don't have to remember to type ",public ArrayMessage";
876 // and eventually CkArrayMessage will be integrated into the envelope anyway.
877   str << ":public CkArrayMessage";
878
879   genAllocDecl(str);
880
881   if(!(external||type->isTemplated())) {
882    // generate register function
883     str << "    static void __register(const char *s, size_t size, CkPackFnPtr pack, CkUnpackFnPtr unpack) {\n";
884     str << "      __idx = CkRegisterMsg(s, pack, unpack, 0, size);\n";
885     str << "    }\n";
886   }
887   str << "};\n";
888 }
889
890 void
891 Message::genDefs(XStr& str)
892 {
893   XStr ptype;
894   ptype<<proxyPrefix()<<type;
895   
896   str << "/* DEFS: "; print(str); str << " */\n";
897   if(!templat) {
898     str << "#ifndef CK_TEMPLATES_ONLY\n";
899   } else {
900     str << "#ifdef CK_TEMPLATES_ONLY\n";
901   }
902   if(!(external||type->isTemplated())) {
903     // generate varsize new operator
904     if(isVarsize()) {
905       if(templat) {
906         templat->genSpec(str);
907         str << " ";
908       }
909       str << "void *"<<ptype;
910       if(templat)
911         templat->genVars(str);
912       str << "::operator new(size_t s, int *sz, int p)\n";
913       str << "{\n";
914       str << "  return ";
915       type->print(str);
916       if(templat)
917         templat->genVars(str);
918       str << "::alloc(__idx, s, sz, p);\n";
919       str << "}\n";
920
921       if(compilemode==ansi) {
922         // Generate corresponding delete
923         if(templat) {
924           templat->genSpec(str);
925           str << " ";
926         }
927         str << "void "<<ptype;
928         if(templat)
929           templat->genVars(str);
930         str << "::operator delete(void *p, int *, int)\n";
931         str << "{\n";
932         str << "  CkFreeMsg(p);\n";
933         str << "}\n";
934       }
935     }
936     if(isVarrays()) {
937       int num = mvlist->len();
938       if(templat) {
939         templat->genSpec(str);
940         str << " ";
941       }
942       str << "void *"<<ptype;
943       if(templat)
944         templat->genVars(str);
945       str << "::operator new(size_t s, ";
946       int i;
947       for(i=0;i<num;i++)
948         str << "int sz" << i << ", ";
949       str << "int p) {\n";
950       str << "  int i, sizes[" << num << "];\n";
951       for(i=0;i<num;i++)
952         str << "  sizes[" << i << "] = sz" << i << ";\n";
953       str << "  return ";
954       type->print(str);
955       if(templat)
956         templat->genVars(str);
957       str << "::alloc(__idx, s, sizes, p);\n";
958       str << "}\n";
959
960       if(compilemode==ansi) {
961         // Generate corresponding delete
962         if(templat) {
963           templat->genSpec(str);
964           str << " ";
965         }
966         str << "void "<<ptype;
967         if(templat)
968           templat->genVars(str);
969         str << "::operator delete(void *p, \n";
970         for(i=0;i<num;i++)
971           str << "int,";
972         str << "int) {\n";
973         str << "  CkFreeMsg(p);\n";
974         str << "}\n";
975       }
976     }
977   }
978   if(!templat) {
979     if(!external && !type->isTemplated()) {
980       str << "int "<<ptype<<"::__idx=0;\n";
981
982       // Define the Marshalling message for Fortran
983       if (fortranMode)
984       {
985         str << "/* FORTRAN */\n";
986         str << "class " << type 
987             << " : public CMessage_" << type << "\n";
988         str << "{\npublic:\n";
989         contents->genUnmarshalList2(str);
990         str << "};\n";
991       }
992     }
993   } else {
994     templat->genSpec(str);
995     str << "int "<<proxyPrefix()<<type;
996     templat->genVars(str);
997     str <<"::__idx=0;\n";
998   }
999   str << "#endif\n";
1000 }
1001
1002 void
1003 Message::genReg(XStr& str)
1004 {
1005   str << "/* REG: "; print(str); str << "*/\n";
1006   if(!templat && !external) {
1007     str << "  "<<proxyPrefix()<<type<<"::";
1008     str << "__register(\""<<type<<"\", sizeof("<<type<<"),";
1009     if(isPacked()||isVarsize()) {
1010       str << "(CkPackFnPtr) "<<type;
1011       if(templat)
1012         templat->genVars(str);
1013       str << "::pack, ";
1014       str << "(CkUnpackFnPtr) "<<type;
1015       if(templat)
1016         templat->genVars(str);
1017       str << "::unpack);\n";
1018     } else {
1019       str << "0, 0);\n";
1020     }
1021   }
1022 }
1023
1024 void
1025 Template::genVars(XStr& str)
1026 {
1027   str << " < ";
1028   if(tspec)
1029     tspec->genShort(str);
1030   str << " > ";
1031 }
1032
1033 void
1034 Template::genSpec(XStr& str)
1035 {
1036   str << "template ";
1037   str << "< ";
1038   if(tspec)
1039     tspec->genLong(str);
1040   str << " > ";
1041 }
1042
1043 void
1044 Template::genDecls(XStr& str)
1045 {
1046   if(!external && entity) {
1047     entity->genDecls(str);
1048   }
1049 }
1050
1051 void
1052 Template::genDefs(XStr& str)
1053 {
1054   if(!external && entity)
1055     entity->genDefs(str);
1056 }
1057
1058 void
1059 Template::genReg(XStr& str)
1060 {
1061 }
1062
1063 void
1064 TVarList::genLong(XStr& str)
1065 {
1066   if(tvar)
1067     tvar->genLong(str);
1068   if(next) {
1069     str << ", ";
1070     next->genLong(str);
1071   }
1072 }
1073
1074 void
1075 TVarList::genShort(XStr& str)
1076 {
1077   if(tvar)
1078     tvar->genShort(str);
1079   if(next) {
1080     str << ", ";
1081     next->genShort(str);
1082   }
1083 }
1084
1085 void TType::genLong(XStr& str)
1086 {
1087   str << "class ";
1088   if(type)
1089     type->print(str);
1090   if(init) {
1091     str << "=";
1092     init->print(str);
1093   }
1094 }
1095
1096 void TType::genShort(XStr& str)
1097 {
1098   if(type)
1099     type->print(str);
1100 }
1101
1102 void TName::genLong(XStr& str)
1103 {
1104   if(type)
1105     type->print(str);
1106   str << " "<<name;
1107   if(val) {
1108     str << "="<<val;
1109   }
1110 }
1111
1112 void TName::genShort(XStr& str)
1113 {
1114   str << name;
1115 }
1116
1117 void
1118 Module::genDecls(XStr& str)
1119 {
1120   if(external) {
1121     str << "#include \""<<name<<".decl.h\"\n";
1122   } else {
1123     clist->genDecls(str);
1124   }
1125 }
1126
1127 void
1128 Module::genDefs(XStr& str)
1129 {
1130   if(!external)
1131     clist->genDefs(str);
1132 }
1133
1134 void
1135 Module::genReg(XStr& str)
1136 {
1137   if(external) {
1138     str << "      _register"<<name<<"();"<<endx;
1139   } else {
1140     clist->genDefs(str);
1141   }
1142 }
1143
1144 void
1145 Readonly::genDecls(XStr& str)
1146 {
1147   str << "/* DECLS: "; print(str); str << " */\n";
1148   /*
1149   if(container) { // local static var
1150   } else { // global var
1151     str << "extern ";
1152     type->print(str);
1153     if(msg)
1154       str << "*";
1155     str << " "<<name;
1156     if(dims)
1157       dims->print(str);
1158     str << ";";
1159   }
1160   */
1161 }
1162
1163 void
1164 Readonly::genDefs(XStr& str)
1165 {
1166   str << "/* DEFS: "; print(str); str << " */\n";
1167   if(!container && !strchr(name, ':')) {
1168     str << "extern ";
1169     type->print(str);
1170     if(msg)
1171       str << "*";
1172     str << " "<<name;
1173     if(dims)
1174       dims->print(str);
1175     str << ";\n";
1176   }
1177   if (fortranMode) {
1178       str << "extern \"C\" void set_"
1179           << fortranify(name)
1180           << "_(int *n) { " << name << " = *n; }\n";
1181       str << "extern \"C\" void get_"
1182           << fortranify(name)
1183           << "_(int *n) { *n = " << name << "; }\n";
1184   }
1185 }
1186
1187 void
1188 Readonly::genReg(XStr& str)
1189 {
1190   if(external)
1191     return;
1192   if(msg) {
1193     if(dims) {
1194       cerr<<"line "<<line<<":Readonly Message cannot be an array!!\n";
1195       exit(1);
1196     }
1197     str << "  CkRegisterReadonlyMsg((void **) &";
1198     if(container) {
1199       str << container->baseName()<<"::";
1200     }
1201     str << name<<");\n";
1202   } else {
1203     str << "  CkRegisterReadonly(sizeof(";
1204     type->print(str);
1205     if(dims)
1206       dims->print(str);
1207     str << "), (void *) &";
1208     if(container) {
1209       str << container->baseName()<<"::";
1210     }
1211     str << name<<");\n";
1212   }
1213 }
1214
1215 void TParamList::genSpec(XStr& str)
1216 {
1217   if(tparam)
1218     tparam->genSpec(str);
1219   if(next) {
1220     str << ", ";
1221     next->genSpec(str);
1222   }
1223 }
1224
1225 void TypeList::genProxyNames(XStr& str, const char *prefix, 
1226                              const char *suffix, const char *sep)
1227 {
1228   if(type) {
1229     str << prefix;
1230     type->genProxyName(str);
1231     str << suffix;
1232   }
1233   if(next) {
1234     str << sep;
1235     next->genProxyNames(str, prefix, suffix, sep);
1236   }
1237 }
1238
1239 void TypeList::genProxyNames2(XStr& str, const char *prefix, 
1240                              const char *middle, const char *suffix, 
1241                              const char *sep)
1242 {
1243   if(type) {
1244     str << prefix;
1245     type->genProxyName(str);
1246     str << middle;
1247     type->genProxyName(str);
1248     str << suffix;
1249   }
1250   if(next) {
1251     str << sep;
1252     next->genProxyNames2(str, prefix, middle, suffix, sep);
1253   }
1254 }
1255
1256 void TypeList::genUnmarshalList0(XStr& str, int depth)
1257 {
1258   if(type) {
1259 //    type->print(str);
1260     str << type->getBaseName();
1261     str << "*";
1262   }
1263   if(next) {
1264     str << ", ";
1265     next->genUnmarshalList0(str, depth+1);
1266   }
1267 }
1268
1269 void TypeList::genUnmarshalList1(XStr& str, const char* message_name, int depth)
1270 {
1271   if(type) {
1272     if (type->typeName() != arrayType)
1273       str << "&((" << message_name << "*)msg)->p" << depth;
1274     else
1275       str << "((" << message_name << "*)msg)->p" << depth;
1276   }
1277   if(next) {
1278     str << ", ";
1279     next->genUnmarshalList1(str, message_name, depth+1);
1280   }
1281 }
1282
1283 void TypeList::genUnmarshalList2(XStr& str, int depth)
1284 {
1285   if(type) {
1286 //    str << "  " << type->getBaseName() << " p" << depth << ";\n";
1287     char p[10];
1288     sprintf(p, "p%d", depth);
1289     type->printVar(str, p);
1290     str<<";\n";
1291   }
1292   if(next) {
1293     next->genUnmarshalList2(str, depth+1);
1294   }
1295 }
1296
1297 void TypeList::genUnmarshalList3(XStr& str, int depth)
1298 {
1299   if(type) {
1300     str << type->getBaseName() << " *p" << depth;
1301   }
1302   if(next) {
1303     str << ", ";
1304     next->genUnmarshalList3(str, depth+1);
1305   }
1306 }
1307
1308 void TypeList::genUnmarshalList4(XStr& str, int depth)
1309 {
1310   if(type) {
1311     if (type->typeName() != arrayType) 
1312       str << "  msg->p" << depth << " = *p" << depth << ";\n";
1313     else {
1314       ArrayType *atype = (ArrayType *)type;
1315       str << "  memcpy(msg->p" << depth << ", p" << depth << ", ";
1316       atype->printDim(str);
1317       str << "*sizeof(" << atype->getBaseName() << "));\n";
1318     }
1319   }
1320   if(next) {
1321     next->genUnmarshalList4(str, depth+1);
1322   }
1323 }
1324
1325 void MemberList::genDecls(XStr& str)
1326 {
1327   if(member)
1328     member->genDecls(str);
1329   if(next) {
1330     str << endx;
1331     next->genDecls(str);
1332   }
1333 }
1334
1335 void MemberList::genDefs(XStr& str)
1336 {
1337   if(member)
1338     member->genDefs(str);
1339   if(next) {
1340     str << endx;
1341     next->genDefs(str);
1342   }
1343 }
1344
1345 void MemberList::genReg(XStr& str)
1346 {
1347   if(member)
1348     member->genReg(str);
1349   if(next) {
1350     str << endx;
1351     next->genReg(str);
1352   }
1353 }
1354
1355 ///////////////////////////// ENTRY ////////////////////////////
1356
1357
1358 Entry::Entry(int l, int a, EnType *r, char *n, EnType *p, Value *sz) :
1359       attribs(a), retType(r), name(n), param(p), stacksize(sz)
1360
1361   line=l; setChare(0); 
1362   if(!isVirtual() && isPure()) {
1363     cerr << "Line "<<line<<": Non-virtual methods cannot be pure virtual!!\n";
1364     abort();
1365   }
1366   if(!isThreaded() && stacksize) {
1367     cerr << "Line "<<line<<": Non-Threaded methods cannot have stacksize spec.!!\n";
1368     abort();
1369   }
1370   if(retType && !isSync() && !retType->isVoid()) {
1371     cerr << "Line "<<line<<": Async methods cannot have non-void return type!!\n";
1372     abort();
1373   }
1374 }
1375
1376
1377 // "parameterType *msg" or "void".
1378 // Suitable for use as the only parameter
1379 XStr Entry::paramType(void)
1380 {
1381   XStr str;
1382   if(param) {
1383     str << param;
1384     if(!param->isVoid())  
1385         str << "msg";
1386   }
1387   return str;
1388 }
1389
1390 // "parameterType *msg," if there is a non-void parameter, 
1391 // else empty.  Suitable for use with another parameter following.
1392 XStr Entry::paramComma(void)
1393 {
1394   XStr str;
1395   if(param&&!param->isVoid())  
1396         str << param<<"msg, ";
1397   return str;
1398 }
1399
1400 // Returns a dummy message declaration if the current
1401 // parameter type is void.
1402 XStr Entry::voidParamDecl(void)
1403 {
1404   if((!param) || param->isVoid())
1405     return "      void *msg = CkAllocSysMsg();\n";
1406   else
1407     return "";
1408 }
1409
1410 XStr Entry::epIdx(int include__idx_)
1411 {
1412   XStr str;
1413   if(include__idx_) str << "__idx_";
1414   str << name;
1415   if(param) str << "_"<<param->getBaseName();
1416   return str;
1417 }
1418
1419 //Return a templated proxy declaration string for 
1420 // this Member's container with the given return type, e.g.
1421 // template<int N,class foo> void CProxy_bar<N,foo>
1422 // Works with non-templated Chares as well.
1423 XStr Member::makeDecl(const char *returnType)
1424 {
1425   XStr str;
1426   
1427   if (container->isTemplated())
1428     {container->genTSpec(str);str << " ";}
1429   str << returnType<<" "<<container->proxyName();
1430   return str;
1431 }
1432
1433 /*************************** Chare Entry Points ******************************/
1434
1435 void Entry::genChareDecl(XStr& str)
1436 {
1437   if(isConstructor()) {
1438     genChareStaticConstructorDecl(str);
1439   } else {
1440     // entry method declaration
1441     str << "    "<<Virtual()<<retType<<" "<<name<<"("<<paramType()<<");\n";
1442     // entry method declaration with future
1443     if(isSync()) {
1444       str << "    "<<Virtual()<<" void "<<name<<"("<<paramComma()<<"CkFutureID*);\n";
1445     }
1446   }
1447 }
1448
1449 void Entry::genChareDefs(XStr& str)
1450 {
1451   if(isConstructor()) {
1452     genChareStaticConstructorDefs(str);
1453   } else {
1454     // entry method definition
1455     container->genTSpec(str);
1456     str << retType<<" "<<container->proxyName()<<"::"<<name<<"("<<paramType()<<")\n";
1457     str << "{\n";
1458     if(param->isVoid())
1459       str << "  void *msg = CkAllocSysMsg();\n";
1460     if(isSync()) {
1461       if(retType->isVoid()) {
1462         str << "  CkFreeSysMsg(CkRemoteCall("<<epIdx()<<", msg, &_ck_cid));\n";
1463       } else {
1464         str << "  return ("<<retType<<") CkRemoteCall("<<epIdx()<<", msg, &_ck_cid);\n";
1465       }
1466     } else {
1467       str << "  CkSendMsg("<<epIdx()<<", msg, &_ck_cid);\n";
1468     }
1469     str << "}\n";
1470     // entry method definition with future
1471     if(isSync()) {
1472       str << makeDecl(" void")<<"::"<<name<<"("<<paramComma()<<"CkFutureID *fut)\n";
1473       str << "{\n"<<voidParamDecl();
1474       str << "  *fut = CkRemoteCallAsync("<<epIdx()<<", msg, &_ck_cid);\n";
1475       str << "}\n";
1476     }
1477   }
1478 }
1479
1480 void Entry::genChareStaticConstructorDecl(XStr& str)
1481 {
1482   if(container->isAbstract()) return;
1483
1484   str << "    static void ckNew("<<paramComma()<<"int onPE=CK_PE_ANY);\n";
1485   str << "    static void ckNew("<<paramComma()<<"CkChareID* pcid, int onPE=CK_PE_ANY);\n";
1486   str << "    "<<container->proxyName(0)<<"("<<paramComma()<<"int onPE=CK_PE_ANY);\n";
1487     
1488 }
1489
1490 void Entry::genChareStaticConstructorDefs(XStr& str)
1491 {
1492   if(container->isAbstract()) return;
1493   
1494   str << makeDecl("void")<<"::ckNew("<<paramComma()<<"int onPE)\n";
1495   str << "{\n"<<voidParamDecl();
1496   str << "  CkCreateChare(__idx, "<<epIdx()<<", msg, 0, onPE);\n";
1497   str << "}\n";
1498
1499   str << makeDecl("void")<<"::ckNew("<<paramComma()<<"CkChareID* pcid, int onPE)\n";
1500   str << "{\n"<<voidParamDecl();
1501   str << "  CkCreateChare(__idx, "<<epIdx()<<", msg, pcid, onPE);\n";
1502   str << "}\n";
1503   str << makeDecl(" ")<<"::"<<container->proxyName(0)<<"("<<paramComma()<<"int onPE)\n";
1504   str << "{\n"<<voidParamDecl();
1505   str << "  CkCreateChare(__idx, "<<epIdx()<<", msg, &_ck_cid, onPE);\n";
1506   str << "}\n";
1507 }
1508
1509 /***************************** Array Entry Points **************************/
1510
1511 void Entry::genArrayDecl(XStr& str)
1512 {
1513   if(isConstructor()) {
1514     genArrayStaticConstructorDecl(str);
1515   } else {
1516     // entry method broadcast declaration
1517     str << "    "<<Virtual()<<retType<<" "<<name<<"("<<paramType()<<") const;\n";
1518   }
1519 }
1520
1521 void Entry::genArrayDefs(XStr& str)
1522 {
1523   if (isConstructor())
1524     genArrayStaticConstructorDefs(str);
1525   else
1526   {//Define array entry method
1527     container->genTSpec(str);
1528     str<<retType<<" "<<container->proxyName()<<"::"<<name<<"("<<paramType()<<") const\n";
1529     str<< "{\n";
1530     if (!param||param->isVoid())
1531       str << "      CkArrayMessage *msg=(CkArrayMessage*)CkAllocMsg(0, sizeof(CkArrayMessage),0);\n";
1532     str << "      if(_idx.nInts==-1) \n";
1533     str << "        base_broadcast(msg, "<<epIdx()<<");\n";
1534     str << "      else\n";
1535     str << "        base_send(msg, "<<epIdx()<<");\n";
1536     str << "}\n";
1537   }
1538 }
1539
1540 void Entry::genArrayStaticConstructorDecl(XStr& str)
1541 {
1542   if(container->isAbstract()) return;
1543   
1544   if ( ((Array *)container) ->is1D())
1545       str<< //With numInitial
1546       "    static CkArrayID ckNew("<<paramComma()<<"int numInitial,CkGroupID mapID=_RRMapID);\n";
1547     
1548   str<<
1549     "    void insert("<<paramComma()<<"int onPE=-1);";
1550 }
1551
1552 void Entry::genArrayStaticConstructorDefs(XStr& str)
1553 {
1554     if(container->isAbstract()) return;
1555     
1556     const char *callMsg;//"msg" or "NULL"
1557     if (!param||param->isVoid()) callMsg="NULL"; else callMsg="msg";
1558     
1559     //Add user-callable array constructors--
1560     if (((Array *)container)->is1D())
1561     //1D element constructors can take a number of initial elements
1562        str<< //With numInitial
1563        makeDecl("CkArrayID")<<"::ckNew("<<paramComma()<<"int numElements,CkGroupID mapID)\n"
1564        "{ return CkArrayID(buildArrayGroup("<<epIdx()<<",numElements,mapID,"<<callMsg<<"));}\n";
1565     str<<
1566     makeDecl("void")<<"::insert("<<paramComma()<<"int onPE)\n"
1567     "{ base_insert("<<epIdx()<<",onPE,"<<callMsg<<");}\n";
1568 }
1569
1570
1571 /******************************** Group Entry Points *********************************/
1572
1573 void Entry::genGroupDecl(XStr& str)
1574 {  
1575   //Selects between NodeGroup and Group
1576   char *node = (char *)(container->isNodeGroup()?"Node":"");
1577
1578   if(isConstructor()) {
1579     genGroupStaticConstructorDecl(str);
1580   } else {
1581     // entry method broadcast declaration
1582     if(!isSync()) {
1583       str << "    "<<Virtual()<<retType<<" "<<name<<"("<<paramType()<<")";
1584       str << "{\n"<<voidParamDecl();
1585       str << "      if(_isChare())\n";
1586       str << "        CkSendMsg("<<epIdx()<<", msg, &_ck_cid);\n";
1587       str << "      else\n";
1588       str << "        CkBroadcastMsg"<<node<<"Branch("<<epIdx()<<", msg, _ck_gid);\n";
1589       str << "    }\n";
1590     }
1591     // entry method onPE declaration
1592     str << "    "<<Virtual()<<retType<<" "<<name<<"("<<paramComma()<<"int onPE)";
1593     str << " {\n"<<voidParamDecl();
1594     if(isSync()) {
1595       if(retType->isVoid()) {
1596         str << "    CkFreeSysMsg(";
1597       } else {
1598         str << "    return ("<<retType<<") ";
1599       }
1600       str << "(CkRemote"<<node<<"BranchCall("<<epIdx()<<", "<<paramComma()<<"_ck_gid, onPE));\n";
1601       str << "    }\n";
1602     } else {
1603       str << "      CkSendMsg"<<node<<"Branch("<<epIdx()<<", msg, onPE, _ck_gid);\n";
1604       str << "    }\n";
1605     }
1606     // entry method on multi PEs declaration
1607     if(!isSync() && !container->isNodeGroup()) {
1608       str << "    "<<Virtual()<<retType<<" "<<name<<"("<<paramComma();
1609       str << "int npes, int *pes)";
1610       str << " {\n"<<voidParamDecl();
1611       str << "      CkSendMsg"<<node<<"BranchMulti(";
1612       str <<epIdx()<<", msg, npes, pes, _ck_gid);\n";
1613       str << "    }\n";
1614     }
1615     // entry method onPE declaration with future
1616     if(isSync()) {
1617       str << "    "<<Virtual()<<"void "<<name<<"("<<paramComma()<<"int onPE, CkFutureID *fut)";
1618       str << " {\n"<<voidParamDecl();
1619       str << "      *fut = ";
1620       str << "CkRemote"<<node<<"BranchCallAsync("<<epIdx()<<", msg, _ck_gid, onPE);\n";
1621       str << "    }\n";
1622     }
1623     // entry method forChare declaration with future
1624     if(isSync()) {
1625       str << "    "<<Virtual()<<"void "<<name<<"("<<paramComma()<<"CkFutureID *fut)";
1626       str << " {\n"<<voidParamDecl();
1627       str << "      *fut = CkRemoteCallAsync("<<epIdx()<<", msg, &_ck_cid);\n";
1628       str << "    }\n";
1629     }
1630   }
1631 }
1632 void Entry::genGroupDefs(XStr& str)
1633 {
1634   if(isConstructor()) {
1635     genGroupStaticConstructorDefs(str);
1636   } else {
1637   }
1638 }
1639
1640 void Entry::genGroupStaticConstructorDecl(XStr& str)
1641 {
1642   if(container->isAbstract()) return;
1643
1644   str << "    static CkGroupID ckNew("<<paramType()<<");\n";
1645   str << "    static CkGroupID ckNewSync("<<paramType()<<");\n";
1646   str << "    "<<container->proxyName(0)<<"("<<paramComma()<<"int retEP, CkChareID *cid);\n";
1647   str << "    "<<container->proxyName(0)<<"("<<paramType()<<");\n";
1648 }
1649
1650 void Entry::genGroupStaticConstructorDefs(XStr& str)
1651 {
1652   if(container->isAbstract()) return;
1653   
1654   //Selects between NodeGroup and Group
1655   char *node = (char *)(container->isNodeGroup()?"Node":"");
1656   str << makeDecl("CkGroupID")<<"::ckNew("<<paramType()<<")\n";
1657   str << "{\n"<<voidParamDecl();
1658   str << "  return CkCreate"<<node<<"Group(__idx, "<<epIdx()<<", msg, 0, 0);\n";
1659   str << "}\n";
1660
1661   str << makeDecl("CkGroupID")<<"::ckNewSync("<<paramType()<<")\n";
1662   str << "{\n"<<voidParamDecl();
1663   str << "  return CkCreate"<<node<<"GroupSync(__idx, "<<epIdx()<<", msg);\n";
1664   str << "}\n";
1665
1666   str << makeDecl(" ")<<"::"<<container->proxyName(0)<<
1667          "("<<paramComma()<<"int retEP, CkChareID *cid)\n";
1668   str << "{\n"<<voidParamDecl();
1669   str << "  _ck_gid = CkCreate"<<node<<"Group(__idx, "<<epIdx()<<", msg, retEP, cid);\n";
1670   str << "  _setChare(0);\n";
1671   str << "}\n";
1672
1673   str << makeDecl(" ")<<"::"<<container->proxyName(0)<<"("<<paramType()<<")\n";
1674   str << "{\n"<<voidParamDecl();
1675   str << "  _ck_gid = CkCreate"<<node<<"Group(__idx, "<<epIdx()<<", msg, 0, 0);\n";
1676   str << "  _setChare(0);\n";
1677   str << "}\n";
1678 }
1679
1680 /******************* Shared Entry Point Code **************************/
1681
1682 void Entry::genDecls(XStr& str)
1683 {
1684   if(container->isArray()&&param==NULL) {param=new BuiltinType("void");}
1685   if(isConstructor() && retType && !retType->isVoid()) {
1686     cerr << "Line "<<line<<": Constructors cannot return a value!!\n";
1687     abort();
1688   }
1689   
1690   str << "/* DECLS: "; print(str); str << " */\n";
1691   if(retType==0 && !isConstructor()) {
1692       cerr<<"line "<<line<<":Entry methods must specify a return type. ";
1693       cerr<<"use void if necessary\n";
1694       exit(1);
1695   }  
1696   
1697   if (attribs&SMIGRATE) 
1698     {} //User cannot call the migration constructor
1699   else if(container->isGroup()) {
1700       genGroupDecl(str);
1701   } else if(container->isArray()) {
1702       genArrayDecl(str);
1703   } else { // chare or mainchare
1704       genChareDecl(str);
1705   }
1706   
1707   // Entry point index storage
1708   str << "    static int  "<<epIdx()<<";\n";
1709   
1710   // ckIdx, so user can find the entry point number
1711   str << "    static int  ckIdx_"<<name<<"("<<paramType()<<") { return "<<epIdx()<<"; }\n"; 
1712
1713   // call function declaration
1714   if(isConstructor() && container->isAbstract())
1715     return;
1716   else {
1717     str << "    static void _call_"<<epIdx(0)<<"(";
1718     if(param) {
1719       str << "void* msg, ";
1720     } else {
1721       if(!isConstructor()) {
1722         cerr <<"line "<<line<<" Only constructors allowed to have empty parameter list\n";
1723         exit(1);
1724       }
1725       str << "CkArgMsg* msg, ";
1726     }
1727     str << container->baseName()<< "* obj);\n";
1728     if(isThreaded()) {
1729       str << "    static void _callthr_"<<epIdx(0)<<"(CkThrCallArg *);\n";
1730     }
1731   }
1732 }
1733
1734
1735
1736 //This routine is only used in Entry::genDefs.
1737 // It ends the current procedure with a call to awaken another thread,
1738 // and defines the thread function to handle that call.
1739 XStr Entry::callThread(const XStr &procName,int prependEntryName)
1740 {
1741   XStr str,procFull;
1742   procFull<<"_callthr_";
1743   if(prependEntryName) procFull<<name<<"_";
1744   procFull<<procName;
1745   
1746   str << "  CthAwaken(CthCreate((CthVoidFn)"<<procFull
1747    <<", new CkThrCallArg(msg,obj), "<<getStackSize()<<"));\n}\n";
1748   str << makeDecl("void")<<"::"<<procFull<<"(CkThrCallArg *arg)\n";
1749   str << "{\n";\
1750   str << "  void *msg = arg->msg;\n";
1751   str << "  "<<container->baseName()<<" *obj = ("<<container->baseName()<<" *) arg->obj;\n";
1752   str << "  delete arg;\n";
1753   return str;
1754 }
1755
1756 void Entry::genDefs(XStr& str)
1757 {
1758   XStr containerType=container->baseName();
1759   XStr cpType,cpComma;
1760   char *freeMsgVoid=(char*) "";
1761   if((!param)||(param->isVoid()))
1762   {
1763     if(container->isArray())
1764       freeMsgVoid=(char*) "  CkFreeMsg(msg);\n";
1765     else
1766       freeMsgVoid=(char*) "  CkFreeSysMsg(msg);\n";
1767   }
1768   if(param&&!param->isVoid())
1769   {//Add type casts for the message parameter
1770      cpType<<"("<<param<<")msg";
1771      cpComma<<"("<<param<<")msg,";
1772   }
1773   
1774   str << "/* DEFS: "; print(str); str << " */\n";
1775   
1776   //Define storage for entry point number
1777   container->genTSpec(str);
1778   str << "int "<<container->proxyName()<<"::"<<epIdx()<<"=0;\n";
1779
1780   if (attribs&SMIGRATE) 
1781     {} //User cannot call the migration constructor
1782   else if(container->isGroup()){
1783     genGroupDefs(str);
1784   } else if(container->isArray()) {
1785     genArrayDefs(str);
1786   } else
1787     genChareDefs(str);
1788   
1789   // call function
1790   if(isConstructor() && container->isAbstract())
1791     return; // no call function for a constructor of an abstract chare
1792   else if(isSync()) {
1793   //A synchronous method can return a value, and must finish before
1794   // the caller can proceed.
1795     if(isConstructor()) {
1796       cerr<<"line "<<line<<":Constructors cannot be sync methods."<<endl;
1797       exit(1);
1798     }
1799     str << makeDecl("void")<<"::_call_"<<epIdx(0)<<"(void* msg, "<<containerType<<"* obj)\n";
1800     str << "{\n";
1801     if(isThreaded()) str << callThread(epIdx(0));
1802     str << "  int ref = CkGetRefNum(msg), src = CkGetSrcPe(msg);\n";
1803     str << "  void *retMsg=";
1804     if(retType->isVoid()) {
1805       str << "CkAllocSysMsg();\n  ";
1806     } else {
1807       str << "(void *) ";
1808     }
1809     str << "obj->"<<name<<"("<<cpType<<");\n"<<freeMsgVoid;
1810     str << "  CkSendToFuture(ref, retMsg, src);\n";
1811     str << "}\n";
1812   } else if(isExclusive()) {
1813   //An exclusive method 
1814     if(!container->isNodeGroup()) {
1815       cerr<<"line "<<line<<":Only entry methods of a nodegroup can be exclusive."<<endl;
1816       exit(1);
1817     }
1818     if(isConstructor()) {
1819       cerr<<"line "<<line<<":Constructors cannot be exclusive methods."<<endl;
1820       exit(1);
1821     }
1822     if(param==0) {
1823       cerr<<"line "<<line<<":Entry methods must specify a message parameter. ";
1824       cerr<<"use void if necessary\n";
1825       exit(1);
1826     }
1827     str << makeDecl("void")<<"::_call_"<<epIdx(0)<<"(void* msg, "<<containerType<<"* obj)\n";
1828     str << "{\n";
1829     if(isThreaded()) str << callThread(epIdx(0));
1830     str << "  if(CmiTryLock(obj->__nodelock)) {\n";
1831     str << "    "<<container->proxyName()<<" pobj(CkGetNodeGroupID());\n";
1832     str << "    pobj."<<name<<"("<<cpComma<<"CkMyNode());\n"<<freeMsgVoid;
1833     str << "    return;\n";
1834     str << "  }\n";
1835     str << "  obj->"<<name<<"("<<cpType<<");\n"<<freeMsgVoid;
1836     str << "  CmiUnlock(obj->__nodelock);\n";
1837     str << "}\n";
1838   } else {//Not sync, exclusive, or an array constructor-- just a regular method
1839
1840     if (!isConstructor() && fortranMode) { // Fortran90
1841       const char* msg_name = param->getBaseName();
1842       TypeList *msg_contents = (message_list.find(msg_name))->getContents();
1843
1844       str << "/* FORTRAN SECTION */\n";
1845
1846       // Declare the Fortran Entry Function
1847       // This is called from C++
1848       str << "extern \"C\" void " << fortranify(name) << "_(char **, int*, ";
1849       msg_contents->genUnmarshalList0(str);
1850       str << ");\n";
1851
1852 /*
1853       // Define the Marshalling message
1854       str << "class " << msg_name 
1855           << " : public CMessage_" << msg_name << "\n";
1856       str << "{\npublic:\n";
1857       msg_contents->genUnmarshalList2(str);
1858       str << "};\n";
1859 */
1860
1861       // Define the Fortran interface function
1862       // This is called from Fortran to send the message to a chare.
1863       str << "extern \"C\" void "
1864         //<< container->proxyName() << "_" 
1865           << fortranify("SendTo_")
1866           << fortranify(container->baseName())
1867           << "_" << fortranify(name)
1868           << "_(long* aindex, int *index, ";
1869       msg_contents->genUnmarshalList3(str);
1870       str << ")\n";
1871       str << "{\n";
1872       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1873       str << "\n";
1874       str << "  // marshalling\n";
1875       str << "  " << container->proxyName() << " h(*aid);\n";
1876       str << "  " << msg_name <<" *msg = new " << msg_name <<";\n";
1877       //      str << "    msg->data = *data;\n";
1878       msg_contents->genUnmarshalList4(str);
1879       str << "  h[*index]." << name << "(msg);\n";
1880       str << "}\n";
1881     }
1882
1883     str << makeDecl("void")<<"::_call_"<<epIdx(0)
1884       <<"("<<((param)?"void":"CkArgMsg")<<"* msg, "<<containerType<<"* obj)\n";
1885     str << "{\n";
1886     if(isThreaded()) str << callThread(epIdx(0));
1887     if(isConstructor()) {
1888       str << "  new (obj) "<<containerType;
1889       if(param) {
1890         if(!param->isVoid()) {
1891           str << "(("<<param<<")msg);\n";
1892         } else {//Constructor takes no msg-- must blow away old parameter
1893           str << "();\n";
1894           if (container->isArray()) str << "  CkFreeMsg(msg);\n";
1895           else str << "  CkFreeSysMsg(msg);\n";
1896         }
1897       } else {//For main chare--
1898         str << "((CkArgMsg*)msg);\n";
1899       }
1900     } else {//Not a constructor
1901       if (fortranMode) { // Fortran90
1902         str << "  int index = obj->getIndex();\n";
1903         str << "  " << fortranify(name)
1904             << "_((char **)(obj->user_data), &index, ";
1905         const char* msg_name = param->getBaseName();
1906         TypeList *msg_contents = (message_list.find(msg_name))->getContents();
1907         msg_contents->genUnmarshalList1(str, param->getBaseName());
1908         str << ");\n";
1909       } else {
1910         if(isThreaded()&&(param->isVoid()))
1911           str << freeMsgVoid<<"  obj->"<<name<<"("<<cpType<<");\n";
1912         else
1913           str << "  obj->"<<name<<"("<<cpType<<");\n"<<freeMsgVoid;
1914       }
1915     }
1916     str << "}\n";
1917   }
1918 }
1919
1920 void Entry::genReg(XStr& str)
1921 {
1922   str << "    /* REG: "<<*this << "*/\n";
1923   if(isConstructor() && container->isAbstract())
1924     return;
1925     
1926   str << "      "<<epIdx()<<" = CkRegisterEp(\""<<name 
1927  <<"\", (CkCallFnPtr)_call_"<<epIdx(0)<<", ";
1928   if(param && !param->isVoid() && !(attribs&SMIGRATE)) {
1929     param->genMsgProxyName(str);
1930     str << "::__idx, ";
1931   } else {
1932     str << "0, ";
1933   }
1934   str << "__idx);\n";
1935   if(container->isMainChare() && isConstructor()) {
1936     str << "      CkRegisterMainChare(__idx, "<<epIdx()<<");\n";
1937   }
1938 }
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951