Files Classes Functions Hierarchy
00001 #ifndef MAKESTATE_H 00002 #define MAKESTATE_H 00003 00004 #include <cassert> 00005 #include <iostream> 00006 #include <queue> 00007 using namespace std; 00008 00009 #include <makefilebtglobals.h> 00010 #include <projfiles.h> 00011 #include <print.h> 00012 #include <systemcalls.h> 00013 #include <tokenizer.h> 00014 00021 template <typename CFC> 00022 class makestate 00023 { 00024 public: 00025 00028 CFC processed; 00030 CFC standard; 00032 CFC unknown; 00033 00035 CFC processqueue2; 00037 deque<compilationfile*> processqueue; 00039 void processqueueadd(compilationfile* cf); 00040 00042 CFC objs; 00043 00045 void standardbuild(); 00046 00048 ~makestate(); 00049 00051 void print(); 00052 00054 makestate(); 00055 00057 bool printobjs; 00059 bool printprocessed; 00061 bool printprocessqueue; 00063 bool printstandard; 00065 bool printunknown; 00067 bool printobjsdependencies; 00068 00070 void printdefaults(); 00071 00075 void printafterbuild(); 00076 00081 void eval(compilationfile& cf); 00085 void evaldriver(); 00086 00088 void objseval(compilationfile& cf); 00090 void objseval(compilationfile& cf, compilationfile& h ); 00091 00093 void objsdependenciesPass1(); 00095 void objsdependenciesPass2(); 00096 00097 00099 compilationfile* isinprocesschain(stringc & filename) const; 00100 00102 projfiles<CFC> proj; 00103 00105 string driver; 00106 00108 boolc valid(); 00109 00110 private: 00111 void printcontainer(CFC& i, stringc & cont); 00112 00113 }; 00114 00115 00116 //--------------------------------------------------------- 00117 // Implementation 00118 00119 template<typename CFC> 00120 compilationfile* makestate<CFC>::isinprocesschain(stringc & filename) const 00121 { 00122 compilationfile* x; 00123 00124 x = standard[filename]; 00125 if (x) 00126 return x; 00127 00128 x = processed[filename]; 00129 if (x) 00130 return x; 00131 00132 x = unknown[filename]; 00133 if (x) 00134 return x; 00135 00136 x = processqueue2[filename]; 00137 if (x) 00138 return x; 00139 00140 return 0; 00141 } 00142 00143 template<typename CFC> 00144 void makestate<CFC>::printafterbuild() 00145 { 00146 printprocessed=true; 00147 printstandard=false; 00148 printunknown=true; 00149 printobjs=false; 00150 printprocessqueue=false; 00151 printobjsdependencies=false; 00152 00153 print(); 00154 } 00155 00156 template<typename CFC> 00157 void makestate<CFC>::print() 00158 { 00159 if (printprocessed) 00160 printcontainer(processed,"processed"); 00161 if (printstandard) 00162 printcontainer(standard,"standard"); 00163 if (printunknown) 00164 printcontainer(unknown,"unknown"); 00165 if (printobjs) 00166 printcontainer(objs,"objs"); 00167 //printcontainer(processqueue2,"processqueue2"); 00168 00169 if (printprocessqueue) 00170 { 00171 cout << "processqueue: "; 00172 if (!processqueue.empty()) 00173 { 00174 for (deque<compilationfile*>::const_iterator i=processqueue.begin(); 00175 i != processqueue.end(); i++) 00176 cout << " " << (*i)->filename; 00177 cout << endl; 00178 } 00179 else 00180 cout << endl; 00181 } 00182 00183 if (printobjsdependencies) 00184 { 00185 cout << "objsdependencies:" << endl; 00186 compilationfile* x; 00187 for ( objs.reset(); !objs; ++objs ) 00188 { 00189 x = objs(); 00190 assert(x); 00191 cout << x->filename << ": "; 00192 uint imax=x->includes.size(); 00193 for (uint i=0; i<imax; ++i) 00194 { 00195 assert(x->includes[i]); 00196 cout << " " << x->includes[i]->filename; 00197 } 00198 cout << endl; 00199 } 00200 } 00201 00202 assert(valid()); 00203 cout << endl; 00204 } 00205 00206 template<typename CFC> 00207 void makestate<CFC>::printcontainer 00208 ( 00209 CFC& i, 00210 stringc & cont 00211 ) 00212 { 00213 cout << cont << ": "; 00214 i.reset(); 00215 if (!i) 00216 { 00217 for (; !i; ++i) 00218 { 00219 assert(i()!=0); 00220 cout << " " << i()->filename; 00221 } 00222 cout << endl; 00223 } 00224 else 00225 cout << endl; 00226 } 00227 00228 template<typename CFC> 00229 makestate<CFC>::~makestate() 00230 { 00231 // Cleanup as created separately 00232 for ( objs.reset(); !objs; ++objs) 00233 delete objs(); 00234 } 00235 00236 template<typename CFC> 00237 void makestate<CFC>::standardbuild() 00238 { 00239 string standardstring="algorithm bitset cassert cctype cfloat climits cmath complex cstddef cstdlib cstring ctime deque exception fstream functional iomanip ios iosfwd iostream istream iterator limits list local map memory new numeric ostream queue set sstream stack stdexcept streambuf string strstream typeinfo utility valarray vector"; 00240 00241 tokenizer ss(standardstring); 00242 ss.subtract(" "); 00243 00244 compilationfile* x; 00245 for (ss.reset(); !ss; ++ss) 00246 { 00247 x = new compilationfile("",ss(),compilationfile::header); 00248 standard.add(x); 00249 //cout << ss() << endl; 00250 } 00251 } 00252 00253 template<typename CFC> 00254 boolc makestate<CFC>::valid() 00255 { 00256 // The processqueue is contained in processqueue2 00257 // They should have the same elements exactly, but I am not 00258 // testing in the other direction. 00259 if (!processqueue.empty()) 00260 { 00261 for (deque<compilationfile*>::const_iterator i=processqueue.begin(); 00262 i != processqueue.end(); i++) 00263 { 00264 if ( processqueue2[ (*i)->filename ] == 0 ) 00265 return false; 00266 } 00267 } 00268 00269 return true; 00270 } 00271 00272 template<typename CFC> 00273 void makestate<CFC>::processqueueadd(compilationfile* cf) 00274 { 00275 processqueue2.add(cf); 00276 processqueue.push_back(cf); 00277 } 00278 00279 template<typename CFC> 00280 void makestate<CFC>::evaldriver() 00281 { 00282 assert(!proj.driver.empty()); 00283 00284 compilationfile* x = proj.files[proj.driverh()]; 00285 processed.add(x); 00286 compilationfile* x2 = proj.files[proj.drivercpp()]; 00287 processqueueadd(x2); 00288 x->linkheader = x; 00289 x->linksource = x2; 00290 } 00291 00292 template<typename CFC> 00293 void makestate<CFC>::eval(compilationfile& cf) 00294 { 00295 //cout << SHOW(cf.filename) << endl; 00296 //cout << SHOW(cf.linkheader) << endl; 00297 //cout << SHOW(cf.linksource) << endl; 00298 //cout << SHOW(cf.linkobj) << endl; 00299 // Has this object been evaluated before? 00300 if (cf.linkheader || cf.linksource || cf.linkobj) 00301 return; 00302 00303 assert(cf.includes.empty()); 00304 00305 assert(!cf.path.empty()); 00306 00307 systemcalls sys01 00308 ( 00309 "perl ../makefilebuildtool/extractheaders.pl " + cf.path + cf.filename, 00310 // "tempheaders.txt" 00311 makefilebtglobals::tempheaders 00312 ); 00313 sys01.eval(); 00314 00315 compilationfile* x; 00316 string filename; 00317 00318 for (uint i=0; i<sys01.lines.size(); ++i) 00319 { 00320 filename=sys01.lines[i]; 00321 if (standard[filename]) 00322 continue; 00323 00324 // Assume the headers have a .h extension. 00325 filename += ".h"; 00326 00327 x = isinprocesschain(filename); 00328 if (x) 00329 { 00330 // cf.includes.push_back(x); 00331 cf.includesadd(x); 00332 continue; 00333 } 00334 00335 assert(!x); //make sure continue works. 00336 //cout << "Not in process chain." << endl; 00337 //cout << SHOW(filename) << endl; 00338 00339 x = proj.files[filename]; 00340 if (!x) 00341 { 00342 unknown.add(new compilationfile("",filename)); 00343 continue; 00344 } 00345 00346 processqueueadd(x); 00347 00348 //cf.includes.push_back(x); 00349 cf.includesadd(x); 00350 00351 //cout << sys01.lines[i] << endl;; 00352 } 00353 00354 00355 if (cf.ft==compilationfile::header) 00356 { 00357 // Headers are included before cpp, 00358 00359 cf.linkheader= &cf; 00360 x = proj.files[cf.component()+".cpp"]; 00361 if (x) 00362 { 00363 cf.linksource = x; 00364 processqueueadd(x); 00365 } 00366 } 00367 00368 if (cf.ft==compilationfile::source) 00369 { 00370 cf.linksource = &cf; 00371 00372 x = proj.files[cf.component()+".h"]; 00373 assert(x); 00374 cf.linkheader = x; 00375 00376 assert(cf.component() == x->linkheader->component()); 00377 00378 x = new compilationfile(cf.path,cf.component()+".o"); 00379 x->linkobj = x; 00380 x->linksource = &cf; 00381 x->linkheader = cf.linkheader; 00382 00383 //cout << "*11*" << cf.filename << endl; 00384 cf.linkheader->linkobj = x; 00385 cf.linkobj = x; 00386 00387 objs.add(x); 00388 } 00389 00390 } 00391 00392 template<typename CFC> 00393 void makestate<CFC>::printdefaults() 00394 { 00395 printobjs=true; 00396 printprocessqueue=true; 00397 printprocessed=true; 00398 printstandard=false; 00399 printunknown=true; 00400 printobjsdependencies=false; 00401 } 00402 00403 template<typename CFC> 00404 makestate<CFC>::makestate() 00405 : driver("main") 00406 { 00407 // I have chosen this on my current project size, for example 00408 // I may have about 50 files being in a container realistically, 00409 // by making the default much larger it should handle more code 00410 // that has many more files. 00411 uintc size=500; 00412 processed.construct(size); 00413 standard.construct(size); 00414 unknown.construct(size); 00415 processqueue2.construct(size); 00416 objs.construct(size); 00417 00418 printdefaults(); 00419 } 00420 00421 template<typename CFC> 00422 void makestate<CFC>::objsdependenciesPass1() 00423 { 00424 // assert(objs.size()!=0); 00425 00426 for (objs.reset(); !objs; ++objs) 00427 objseval(*objs()); 00428 00429 // The driver programs virtual .h file is to be deleted. 00430 objs.reset(); 00431 if (!objs) 00432 objs()->includes.pop_back(); 00433 } 00434 00435 template<typename CFC> 00436 void makestate<CFC>::objsdependenciesPass2() 00437 { 00438 00439 compilationfile *x; 00440 compilationfile *y; 00441 for (objs.reset(); !objs; ++objs) 00442 { 00443 x=objs(); 00444 uint imax = x->includes.size(); 00445 for (uint i=0; i<imax; ++i) 00446 { 00447 y = x->includes[i]; 00448 if (y->ft!=compilationfile::obj) 00449 continue; 00450 00451 uint kmax = y->includes.size(); 00452 for (uint k=0; k<kmax; ++k) 00453 { 00454 if (x!=y->includes[k]) 00455 continue; 00456 00457 // Searched and found circular dependency 00458 //cout << SHOW(i) << " " << SHOW(k) << endl; 00459 x->includes[i] = x->includes[i]->linkheader; 00460 //x->includes.push_back( x->includes[i]->linksource ); 00461 x->includesadd(x->includes[i]->linksource ); 00462 y->includes[k] = y->includes[k]->linkheader; 00463 //y->includes.push_back( y->includes[k]->linksource ); 00464 y->includesadd( y->includes[k]->linksource ); 00465 } 00466 } 00467 } 00468 } 00469 00470 // Recursive descent 00471 template<typename CFC> 00472 void makestate<CFC>::objseval(compilationfile& cf, compilationfile& h ) 00473 { 00474 assert(cf.ft==compilationfile::obj); 00475 assert(h.ft==compilationfile::header); 00476 assert(h.linksource==0); 00477 assert(h.linkobj==0); 00478 00479 // Unknown files are assumed to work, often part of a library, 00480 // which I assume is constant. e.g. GL/gl.h GL/glut.h 00481 if (unknown[h.filename]) 00482 return; 00483 00484 // Stop infinite recursion, case already handled. 00485 if (cf.includesadd(&h)==false) 00486 return; 00487 00488 uint imax=h.includes.size(); 00489 compilationfile* y; 00490 for (uint i=0; i<imax; ++i) 00491 { 00492 y = h.includes[i]; 00493 if (y->linkobj) 00494 cf.includesadd(y->linkobj); 00495 else 00496 objseval(cf,*y); 00497 } 00498 } 00499 00500 template<typename CFC> 00501 void makestate<CFC>::objseval(compilationfile& cf) 00502 { 00503 assert(cf.ft==compilationfile::obj); 00504 00505 //cout << SHOW(cf.filename) << endl; 00506 00507 compilationfile* x; 00508 00509 // Descend into the header first. 00510 x = cf.linkheader; 00511 assert(x); 00512 assert(x->includesvalid()); 00513 assert(cf.includes.size()==0); 00514 00515 uint imax; 00516 compilationfile* y; 00517 00518 imax = x->includes.size(); 00519 for (uint i=0; i<imax; ++i) 00520 { 00521 y = x->includes[i]; 00522 assert(y!=0); 00523 if (y->linkobj) 00524 cf.includesadd(y->linkobj); 00525 else 00526 objseval(cf,*y); 00527 } 00528 00529 // Now descend into the cpp 00530 x = cf.linksource; 00531 assert(x); 00532 assert(x->includesvalid()); 00533 imax = x->includes.size(); 00534 for (uint i=0; i<imax; ++i) 00535 { 00536 y = x->includes[i]; 00537 if (y->linkobj) 00538 cf.includesadd(y->linkobj); 00539 else 00540 objseval(cf,*y); 00541 } 00542 00543 // Add the cpp and headers 00544 cf.includesadd(cf.linksource); 00545 cf.includesadd(cf.linkheader); 00546 } 00547 00548 #endif 00549
1.5.8