proj home

Files   Classes   Functions   Hierarchy  

makestate.h

Go to the documentation of this file.
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 

Generated on Fri Mar 4 00:49:28 2011 for Chelton Evans Source by  doxygen 1.5.8