00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <ctype.h>
00019 #include "charm.h"
00020 #include "pup.h"
00021 #include "ckhashtable.h"
00022
00023 PUP::er::~er() {}
00024
00025 void PUP::er::operator()(able& a)
00026 {a.pup(*this);}
00027
00028 void PUP::er::comment(const char *message)
00029 { }
00030
00031 const char * PUP::er::typeString() const
00032 {
00033 if (isSizing()) return "sizing";
00034 else if (isPacking()) return "packing";
00035 else if (isUnpacking()) return "unpacking";
00036 return "unknown";
00037 }
00038
00039 void PUP::er::synchronize(unsigned int m)
00040 { }
00041
00042
00043
00044
00045
00046 #ifdef CK_CHECK_PUP
00047 static int bannerDisplayed=0;
00048 static void showBanner(void) {
00049 bannerDisplayed=1;
00050 fprintf(stderr,"CK_CHECK_PUP pup routine checking enabled\n");
00051 CmiPrintf("CK_CHECK_PUP pup routine checking enabled\n");
00052 }
00053
00054 class pupCheckRec {
00055 unsigned char magic[4];
00056 unsigned char type;
00057 unsigned char length[3];
00058 enum {pupMagic=0xf36c5a21,typeMask=0x75};
00059 int getMagic(void) const {return (magic[3]<<24)+(magic[2]<<16)+(magic[1]<<8)+magic[0];}
00060 void setMagic(int v) {for (int i=0;i<4;i++) magic[i]=(v>>(8*i));}
00061 PUP::dataType getType(void) const {return (PUP::dataType)(type^typeMask);}
00062 void setType(PUP::dataType v) {type=v^typeMask;}
00063 int getLength(void) const {return (length[2]<<16)+(length[1]<<8)+length[0];}
00064 void setLength(int v) {for (int i=0;i<3;i++) length[i]=(v>>(8*i));}
00065
00066
00067
00068
00069 void compare(const char *kind,const char *why,int packed,int unpacked) const
00070 {
00071 if (packed==unpacked) return;
00072
00073 fprintf(stderr,"CK_CHECK_PUP error!\nPacked %s (%d, or %08x) does "
00074 "not equal unpacked value (%d, or %08x)!\nThis means %s\n",
00075 kind,packed,packed,unpacked,unpacked,why);
00076 CmiPrintf("CK_CHECK_PUP error! Run with debugger for more info.\n");
00077
00078 abort();
00079 }
00080 public:
00081 void write(PUP::dataType t,int n) {
00082 if (!bannerDisplayed) showBanner();
00083 setMagic(pupMagic);
00084 type=t^typeMask;
00085 setLength(n);
00086 }
00087 void check(PUP::dataType t,int n) const {
00088 compare("magic number",
00089 "you unpacked more than you packed, or the values were corrupted during transport",
00090 getMagic(),pupMagic);
00091 compare("data type",
00092 "the pack and unpack paths do not match up",
00093 getType(),t);
00094 compare("length",
00095 "you may have forgotten to pup the array length",
00096 getLength(),n);
00097 }
00098 };
00099 #endif
00100
00101
00102 void PUP::sizer::bytes(void * ,int n,size_t itemSize,dataType )
00103 {
00104 #ifdef CK_CHECK_PUP
00105 nBytes+=sizeof(pupCheckRec);
00106 #endif
00107 #ifndef CMK_OPTIMIZE
00108 if (n<0) CkAbort("PUP::sizer> Tried to pup a negative number of items!");
00109 const unsigned int maxPupBytes=1024*1024*1024;
00110 if (((unsigned int)(n*itemSize))>maxPupBytes)
00111 CkAbort("PUP::sizer> Tried to pup absurdly large number of bytes!");
00112 #endif
00113 nBytes+=n*itemSize;
00114 }
00115
00116
00117 void PUP::toMem::bytes(void *p,int n,size_t itemSize,dataType t)
00118 {
00119 #ifdef CK_CHECK_PUP
00120 ((pupCheckRec *)buf)->write(t,n);
00121 buf+=sizeof(pupCheckRec);
00122 #endif
00123 n*=itemSize;
00124 memcpy((void *)buf,p,n);
00125 buf+=n;
00126 }
00127 void PUP::fromMem::bytes(void *p,int n,size_t itemSize,dataType t)
00128 {
00129 #ifdef CK_CHECK_PUP
00130 ((pupCheckRec *)buf)->check(t,n);
00131 buf+=sizeof(pupCheckRec);
00132 #endif
00133 n*=itemSize;
00134 memcpy(p,(const void *)buf,n);
00135 buf+=n;
00136 }
00137
00138
00139 void PUP::toDisk::bytes(void *p,int n,size_t itemSize,dataType )
00140 { fwrite(p,itemSize,n,F);}
00141 void PUP::fromDisk::bytes(void *p,int n,size_t itemSize,dataType )
00142 { fread(p,itemSize,n,F);}
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 PUP::seekBlock::seekBlock(PUP::er &Np,int nSections)
00161 :nSec(nSections),p(Np)
00162 {
00163 if (nSections<0 || nSections>maxSections)
00164 CmiAbort("Invalid # of sections passed to PUP::seekBlock!");
00165 p.impl_startSeek(*this);
00166 if (p.isPacking())
00167 {
00168 secTabOff=p.impl_tell(*this);
00169 for (int i=0;i<=nSec;i++) secTab[i]=-1;
00170 }
00171 p(secTab,nSec+1);
00172 hasEnded=CmiFalse;
00173 }
00174 PUP::seekBlock::~seekBlock()
00175 {
00176 if (!hasEnded)
00177 endBlock();
00178 }
00179
00180 void PUP::seekBlock::seek(int toSection)
00181 {
00182 if (toSection<0 || toSection>=nSec)
00183 CmiAbort("Invalid section # passed to PUP::seekBlock::seek!");
00184 if (p.isPacking())
00185 secTab[toSection]=p.impl_tell(*this);
00186 else if (p.isUnpacking())
00187 p.impl_seek(*this,secTab[toSection]);
00188
00189 }
00190
00191 void PUP::seekBlock::endBlock(void)
00192 {
00193 if (p.isPacking()) {
00194
00195 secTab[nSec]=p.impl_tell(*this);
00196 p.impl_seek(*this,secTabOff);
00197 p(secTab,nSec+1);
00198 }
00199
00200 p.impl_seek(*this,secTab[nSec]);
00201 p.impl_endSeek(*this);
00202 hasEnded=CmiTrue;
00203 }
00204
00206
00207
00208
00209 void PUP::er::impl_startSeek(PUP::seekBlock &s)
00210 {}
00211 int PUP::er::impl_tell(seekBlock &s)
00212 {return 0;}
00213 void PUP::er::impl_seek(seekBlock &s,int off)
00214 {}
00215 void PUP::er::impl_endSeek(seekBlock &s)
00216 {}
00217
00218
00219
00220 void PUP::mem::impl_startSeek(seekBlock &s)
00221 {s.data.ptr=buf;}
00222 int PUP::mem::impl_tell(seekBlock &s)
00223 {return buf-s.data.ptr;}
00224 void PUP::mem::impl_seek(seekBlock &s,int off)
00225 {buf=s.data.ptr+off;}
00226
00227
00228 void PUP::disk::impl_startSeek(seekBlock &s)
00229 {s.data.loff=ftell(F);}
00230 int PUP::disk::impl_tell(seekBlock &s)
00231 {return (int)(ftell(F)-s.data.loff);}
00232 void PUP::disk::impl_seek(seekBlock &s,int off)
00233 {fseek(F,s.data.loff+off,0);}
00234
00235
00236 void PUP::wrap_er::impl_startSeek(seekBlock &s)
00237 {p.impl_startSeek(s);}
00238 int PUP::wrap_er::impl_tell(seekBlock &s)
00239 {return p.impl_tell(s);}
00240 void PUP::wrap_er::impl_seek(seekBlock &s,int off)
00241 {p.impl_seek(s,off);}
00242 void PUP::wrap_er::impl_endSeek(seekBlock &s)
00243 {p.impl_endSeek(s);}
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 static PUP::able::PUP_ID null_PUP_ID(0);
00262
00263 PUP::able *PUP::able::clone(void) const {
00264
00265 PUP::able *ret=get_constructor(get_PUP_ID()) ();
00266
00267
00268 PUP::able *mthis=(PUP::able *)this;
00269 int size;
00270 { PUP::sizer ps; mthis->pup(ps); size=ps.size(); }
00271 void *buf=malloc(size);
00272 { PUP::toMem pt(buf); mthis->pup(pt); }
00273
00274
00275 { PUP::fromMem pf(buf); ret->pup(pf); }
00276 free(buf);
00277
00278 return ret;
00279 }
00280
00281
00282 PUP::able::~able() {}
00283 void PUP::able::pup(PUP::er &p) {}
00284
00285
00286
00287 void PUP::able::PUP_ID::setName(const char *name)
00288 {
00289 int i,o,n=strlen(name);
00290 int t[len]={0};
00291 for (o=0;o<n;o++)
00292 for (i=0;i<len;i++) {
00293 unsigned char c=name[o];
00294 int shift1=(((o+2)*(i+1)*5+4)%13);
00295 int shift2=(((o+2)*(i+1)*3+2)%11)+13;
00296 t[i]+=(c<<shift1)+(c<<shift2);
00297 }
00298 for (i=0;i<len;i++)
00299 hash[i]=(unsigned char)(t[i]%20117 + t[i]%1217 + t[i]%157);
00300 }
00301
00302
00303 class PUP_regEntry {
00304 public:
00305 PUP::able::PUP_ID id;
00306 const char *name;
00307 PUP::able::constructor_function ctor;
00308 PUP_regEntry(const char *Nname,
00309 const PUP::able::PUP_ID &Nid,PUP::able::constructor_function Nctor)
00310 :id(Nid),name(Nname),ctor(Nctor) {}
00311 PUP_regEntry(int zero) {
00312 name=NULL;
00313 }
00314 };
00315
00316 typedef CkHashtableTslow<PUP::able::PUP_ID,PUP_regEntry> PUP_registry;
00317
00318 static PUP_registry *PUP_getRegistry(void) {
00319 static PUP_registry *reg=NULL;
00320 if (reg==NULL)
00321 reg=new PUP_registry();
00322 return reg;
00323 }
00324
00325 const PUP_regEntry *PUP_getRegEntry(const PUP::able::PUP_ID &id)
00326 {
00327 const PUP_regEntry *cur=(const PUP_regEntry *)(
00328 PUP_getRegistry()->CkHashtable::get((const void *)&id) );
00329 if (cur==NULL)
00330 CmiAbort("Unrecognized PUP::able::PUP_ID. is there an unregistered module?");
00331 return cur;
00332 }
00333
00334 PUP::able::PUP_ID PUP::able::register_constructor
00335 (const char *className,constructor_function fn)
00336 {
00337 PUP::able::PUP_ID id(className);
00338 PUP_getRegistry()->put(id)=PUP_regEntry(className,id,fn);
00339 return id;
00340 }
00341
00342 PUP::able::constructor_function PUP::able::get_constructor
00343 (const PUP::able::PUP_ID &id)
00344 {
00345 return PUP_getRegEntry(id)->ctor;
00346 }
00347
00348
00349 void PUP::er::object(able** a)
00350 {
00351 const PUP_regEntry *r=NULL;
00352 if (isUnpacking())
00353 {
00354 PUP::able::PUP_ID id;
00355 id.pup(*this);
00356 if (id==null_PUP_ID) {*a=NULL; return;}
00357 r=PUP_getRegEntry(id);
00358
00359 *a=(r->ctor)();
00360
00361 } else {
00362 if (*a==NULL) {
00363 null_PUP_ID.pup(*this);
00364 return;
00365 } else {
00366 const PUP::able::PUP_ID &id=(*a)->get_PUP_ID();
00367 id.pup(*this);
00368 r=PUP_getRegEntry(id);
00369 }
00370 }
00371 syncComment(PUP::sync_begin_object,r->name);
00372 (*a)->pup(*this);
00373 syncComment(PUP::sync_end_object);
00374 }
00375
00376
00377
00378 char *PUP::toTextUtil::beginLine(void) {
00379
00380 for (int i=0;i<level;i++) cur[i]='\t';
00381 cur[level]=0;
00382 return cur+level;
00383 }
00384 void PUP::toTextUtil::endLine(void) {
00385 cur=advance(cur);
00386 }
00387 void PUP::toTextUtil::beginEnv(const char *type,int n)
00388 {
00389 char *o=beginLine();
00390 sprintf(o,"begin "); o+=strlen(o);
00391 sprintf(o,type,n); o+=strlen(o);
00392 sprintf(o," {\n");
00393 endLine();
00394 level++;
00395 }
00396 void PUP::toTextUtil::endEnv(const char *type)
00397 {
00398 level--;
00399 sprintf(beginLine(),"} end %s;\n",type);
00400 endLine();
00401 }
00402 PUP::toTextUtil::toTextUtil(unsigned int inType,char *buf)
00403 :er(inType)
00404 {
00405 cur=buf;
00406 level=0;
00407 }
00408
00409 void PUP::toTextUtil::comment(const char *message)
00410 {
00411 sprintf(beginLine(),"//%s\n",message); endLine();
00412 }
00413
00414 void PUP::toTextUtil::synchronize(unsigned int m)
00415 {
00416 sprintf(beginLine(),"sync=0x%08x\n",m); endLine();
00417 #if 0
00418 char *o=beginLine();
00419 sprintf(o,"sync=");o+=strlen(o);
00420 const char *consonants="bcdfgjklmprstvxz";
00421 const char *vowels="aeou";
00422 for (int firstBit=0;firstBit<32;firstBit+=6) {
00423 sprintf(o,"%c%c%c", consonants[0xf&(m>>firstBit)],
00424 vowels[0x3&(m>>(firstBit+4))],
00425 (firstBit==30)?';':'-');
00426 o+=strlen(o);
00427 }
00428 sprintf(o,"\n"); endLine();
00429 #endif
00430 }
00431
00432 void PUP::toTextUtil::bytes(void *p,int n,size_t itemSize,dataType t) {
00433 if (t==Tchar)
00434 {
00435 char *o=beginLine();
00436 sprintf(o,"string=");o+=strlen(o);
00437 *o++='\"';
00438
00439 const char *c=(const char *)p;
00440 for (int i=0;i<n;i++) {
00441 if (c[i]=='\n') {
00442 sprintf(o,"\\n");o+=strlen(o);
00443 } else if (iscntrl(c[i])) {
00444 sprintf(o,"\\x%02X",(unsigned char)c[i]);o+=strlen(o);
00445 } else if (c[i]=='\\' || c[i]=='\"') {
00446 sprintf(o,"\\%c",c[i]);o+=strlen(o);
00447 } else
00448 *o++=c[i];
00449 }
00450
00451 sprintf(o,"\";\n");o+=strlen(o);
00452 endLine();
00453 } else if (t==Tbyte || t==Tuchar)
00454 {
00455 beginEnv("byte %d",n);
00456 const unsigned char *c=(const unsigned char *)p;
00457 char *o=beginLine();
00458 for (int i=0;i<n;i++) {
00459 sprintf(o,"%02X ",c[i]);o+=strlen(o);
00460 if (i%25==24 && (i+1!=n))
00461 {
00462 sprintf(o,"\n"); o+=strlen(o);
00463 endLine(); o=beginLine();
00464 }
00465 }
00466 sprintf(o,"\n");
00467 endLine();
00468 endEnv("byte");
00469 }
00470 else
00471 {
00472 if (n!=1) beginEnv("array %d",n);
00473 for (int i=0;i<n;i++) {
00474 char *o=beginLine();
00475 switch(t) {
00476 case Tshort: sprintf(o,"short=%d;\n",((short *)p)[i]); break;
00477 case Tushort: sprintf(o,"ushort=%u;\n",((unsigned short *)p)[i]); break;
00478 case Tint: sprintf(o,"int=%d;\n",((int *)p)[i]); break;
00479 case Tuint: sprintf(o,"uint=%u;\n",((unsigned int *)p)[i]); break;
00480 case Tlong: sprintf(o,"long=%ld;\n",((long *)p)[i]); break;
00481 case Tulong: sprintf(o,"ulong=%lu;\n",((unsigned long *)p)[i]); break;
00482 case Tfloat: sprintf(o,"float=%.7g;\n",((float *)p)[i]); break;
00483 case Tdouble: sprintf(o,"double=%.15g;\n",((double *)p)[i]); break;
00484 case Tbool: sprintf(o,"bool=%s;\n",((CmiBool *)p)[i]?"true":"false"); break;
00485 #if CMK_LONG_DOUBLE_DEFINED
00486 case Tlongdouble: sprintf(o,"longdouble=%Lg;\n",((long double *)p)[i]);break;
00487 #endif
00488 #ifdef CMK_PUP_LONG_LONG
00489 case Tlonglong: sprintf(o,"longlong=%lld;\n",((CMK_PUP_LONG_LONG *)p)[i]);break;
00490 case Tulonglong: sprintf(o,"ulonglong=%llu;\n",((unsigned CMK_PUP_LONG_LONG *)p)[i]);break;
00491 #endif
00492 case Tpointer: sprintf(o,"pointer=%p;\n",((void **)p)[i]); break;
00493 default: CmiAbort("Unrecognized pup type code!");
00494 }
00495 endLine();
00496 }
00497 if (n!=1) endEnv("array");
00498 }
00499 }
00500 void PUP::toTextUtil::object(able** a) {
00501 beginEnv("object");
00502 er::object(a);
00503 endEnv("object");
00504 }
00505
00506
00507
00508 char *PUP::sizerText::advance(char *cur) {
00509 charCount+=strlen(cur);
00510 return line;
00511 }
00512
00513 PUP::sizerText::sizerText(void)
00514 :toTextUtil(IS_SIZING+IS_COMMENTS,line),charCount(0) { }
00515
00516
00517 char *PUP::toText::advance(char *cur) {
00518 charCount+=strlen(cur);
00519 return buf+charCount;
00520 }
00521
00522 PUP::toText::toText(char *outBuf)
00523 :toTextUtil(IS_PACKING+IS_COMMENTS,outBuf),buf(outBuf),charCount(0) { }
00524
00525
00526 void PUP::toTextFile::bytes(void *p,int n,size_t itemSize,dataType t)
00527 {
00528 for (int i=0;i<n;i++)
00529 switch(t) {
00530 case Tchar: fprintf(f," '%c'",((char *)p)[i]); break;
00531 case Tuchar:
00532 case Tbyte: fprintf(f," %02X",((unsigned char *)p)[i]); break;
00533 case Tshort: fprintf(f," %d",((short *)p)[i]); break;
00534 case Tushort: fprintf(f," %u",((unsigned short *)p)[i]); break;
00535 case Tint: fprintf(f," %d",((int *)p)[i]); break;
00536 case Tuint: fprintf(f," %u",((unsigned int *)p)[i]); break;
00537 case Tlong: fprintf(f," %ld",((long *)p)[i]); break;
00538 case Tulong: fprintf(f," %lu",((unsigned long *)p)[i]); break;
00539 case Tfloat: fprintf(f," %.7g",((float *)p)[i]); break;
00540 case Tdouble: fprintf(f," %.15g",((double *)p)[i]); break;
00541 case Tbool: fprintf(f," %s",((CmiBool *)p)[i]?"true":"false"); break;
00542 #if CMK_LONG_DOUBLE_DEFINED
00543 case Tlongdouble: fprintf(f," %Lg",((long double *)p)[i]);break;
00544 #endif
00545 #ifdef CMK_PUP_LONG_LONG
00546 case Tlonglong: fprintf(f," %lld",((CMK_PUP_LONG_LONG *)p)[i]);break;
00547 case Tulonglong: fprintf(f," %llu",((unsigned CMK_PUP_LONG_LONG *)p)[i]);break;
00548 #endif
00549 case Tpointer: fprintf(f," %p",((void **)p)[i]); break;
00550 default: CmiAbort("Unrecognized pup type code!");
00551 };
00552 fprintf(f,"\n");
00553 }
00554 void PUP::toTextFile::comment(const char *message)
00555 {
00556 fprintf(f,"! %s\n",message);
00557 }
00558
00559 void PUP::fromTextFile::parseError(const char *what) {
00560
00561 long cur = ftell(f);
00562 int lineno=0;
00563 rewind(f);
00564 while (!feof(f)) {
00565 char c;
00566 fscanf(f,"%c",&c);
00567 if (c=='\n') lineno++;
00568 if (ftell(f) > cur) break;
00569 }
00570 fprintf(stderr,"Parse error during pup from text file: %s at line: %d\n",what, lineno);
00571 CmiAbort("Parse error during pup from text file!\n");
00572 }
00573 int PUP::fromTextFile::readInt(const char *fmt) {
00574 int ret=0;
00575 if (1!=fscanf(f,fmt,&ret)) {
00576 if (feof(f)) return 0;
00577 else parseError("could not match integer");
00578 }
00579 return ret;
00580 }
00581 unsigned int PUP::fromTextFile::readUint(const char *fmt) {
00582 unsigned int ret=0;
00583 if (1!=fscanf(f,fmt,&ret)) {
00584 if (feof(f)) return 0u;
00585 else parseError("could not match unsigned integer");
00586 }
00587 return ret;
00588 }
00589 CMK_TYPEDEF_INT8 PUP::fromTextFile::readLongInt(const char *fmt) {
00590 CMK_TYPEDEF_INT8 ret=0;
00591 if (1!=fscanf(f,fmt,&ret)) {
00592 if (feof(f)) return 0u;
00593 else parseError("could not match large integer");
00594 }
00595 return ret;
00596 }
00597 double PUP::fromTextFile::readDouble(void) {
00598 double ret=0;
00599 if (1!=fscanf(f,"%lg",&ret)) {
00600 if (feof(f)) return 0.0;
00601 else parseError("could not match double");
00602 }
00603 return ret;
00604 }
00605 void PUP::fromTextFile::bytes(void *p,int n,size_t itemSize,dataType t)
00606 {
00607 for (int i=0;i<n;i++)
00608 switch(t) {
00609 case Tchar:
00610 if (1!=fscanf(f," '%c'",&((char *)p)[i]))
00611 parseError("Could not match character");
00612 break;
00613 case Tuchar:
00614 case Tbyte: ((unsigned char *)p)[i]=(unsigned char)readInt("%02X"); break;
00615 case Tshort:((short *)p)[i]=(short)readInt(); break;
00616 case Tushort: ((unsigned short *)p)[i]=(unsigned short)readUint(); break;
00617 case Tint: ((int *)p)[i]=readInt(); break;
00618 case Tuint: ((unsigned int *)p)[i]=readUint(); break;
00619 case Tlong: ((long *)p)[i]=readInt(); break;
00620 case Tulong:((unsigned long *)p)[i]=readUint(); break;
00621 case Tfloat: ((float *)p)[i]=(float)readDouble(); break;
00622 case Tdouble:((double *)p)[i]=readDouble(); break;
00623 #if CMK_LONG_DOUBLE_DEFINED
00624 case Tlongdouble: {
00625 long double ret=0;
00626 if (1!=fscanf(f,"%Lg",&ret)) parseError("could not match long double");
00627 ((long double *)p)[i]=ret;
00628 } break;
00629 #endif
00630 #ifdef CMK_PUP_LONG_LONG
00631 case Tlonglong: {
00632 CMK_PUP_LONG_LONG ret=0;
00633 if (1!=fscanf(f,"%lld",&ret)) parseError("could not match long long");
00634 ((CMK_PUP_LONG_LONG *)p)[i]=ret;
00635 } break;
00636 case Tulonglong: {
00637 unsigned CMK_PUP_LONG_LONG ret=0;
00638 if (1!=fscanf(f,"%llu",&ret)) parseError("could not match unsigned long long");
00639 ((unsigned CMK_PUP_LONG_LONG *)p)[i]=ret;
00640 } break;
00641 #endif
00642 case Tbool: {
00643 char tmp[20];
00644 if (1!=fscanf(f," %20s",tmp)) parseError("could not read boolean string");
00645 CmiBool val=CmiFalse;
00646 if (0==strcmp(tmp,"true")) val=CmiTrue;
00647 else if (0==strcmp(tmp,"false")) val=CmiFalse;
00648 else parseError("could not recognize boolean string");
00649 ((CmiBool *)p)[i]=val;
00650 }
00651 break;
00652 case Tpointer: {
00653 void *ret=0;
00654 if (1!=fscanf(f,"%p",&ret)) parseError("could not match pointer");
00655 ((void **)p)[i]=ret;
00656 } break;
00657 default: CmiAbort("Unrecognized pup type code!");
00658 };
00659 }
00660 void PUP::fromTextFile::comment(const char *message)
00661 {
00662 char c;
00663
00664 while (isspace(c=fgetc(f))) {}
00665
00666 if (c!='!') return;
00667
00668 char *commentBuf=(char *)CmiTmpAlloc(1024);
00669 fgets(commentBuf,1024,f);
00670 CmiTmpFree(commentBuf);
00671 }
00672
00673
00674
00675
00676
00677
00678