flxinstall.cpp

Go to the documentation of this file.
00001 /** flxinstall.spp Utility to create/install/remove faudes-lua-extensions */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005 Copyright (C) 2011 Thomas Moor
00006 
00007 This library is free software; you can redistribute it and/or
00008 modify it under the terms of the GNU Lesser General Public
00009 License as published by the Free Software Foundation; either
00010 version 2.1 of the License, or (at your option) any later version.
00011 
00012 This library is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 Lesser General Public License for more details.
00016 
00017 You should have received a copy of the GNU Lesser General Public
00018 License along with this library; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00020    
00021 
00022 
00023 #include <string>
00024 #include <set>
00025 #include <cctype>
00026 #include <cstdlib>
00027 #include <ctime>
00028 #include <iostream>
00029 #include <fstream>
00030 #include "corefaudes.h"
00031 
00032 
00033 using namespace faudes;
00034 
00035 // ******************************************************************
00036 // error exit
00037 // ******************************************************************
00038 
00039 void usage_exit(const std::string& rMessage="") {
00040   // ui hints
00041   if(rMessage!="") {
00042     std::cerr << "" << std::endl;
00043     std::cerr << "flxinstall: " << rMessage << ": ERROR." << std::endl;
00044     std::cerr << "" << std::endl;
00045     exit(1);
00046   }
00047   std::cerr << "flxinstall: " << VersionString()  << std::endl;
00048   std::cerr << "" << std::endl;
00049   std::cerr << "utility to create/install/remove faudes-lua-extension "<< std::endl;
00050   std::cerr << std::endl << "usage: " << std::endl;
00051   std::cerr << "flxinstall  <other options> <mode>  <input-file(s)> <output-file/path>" << std::endl;
00052   std::cerr << "with <mode> as follows:" << std::endl;
00053   std::cerr << " -c  create extension (*.flx file) from input files" << std::endl;
00054   std::cerr << " -i  install extension (*.flx file) to libFAUDES installation" << std::endl;
00055   std::cerr << " -r  remove extensions from libFAUDES installation" << std::endl;
00056   std::cerr << " -x  extract extension (*.flx file) to output directory" << std::endl;
00057   std::cerr << " -t  extract and test extension (*.flx file) to output directory" << std::endl;
00058   std::cerr << std::endl;
00059   std::cerr << "note: <other options> address the default target layout" << std::endl;
00060   exit(1);
00061 }
00062 
00063 
00064 // ******************************************************************
00065 // Configuration
00066 // ******************************************************************
00067 
00068 
00069 std::string mXmlSeparator = "<!-- ================================================================================ -->";
00070 
00071 
00072 // source/contents/detination
00073 std::set < std::string > mSourceFiles;
00074 std::string mSourceFile;
00075 std::string mTarget;
00076 std::string mExtensionName;
00077 std::set < std::string > mReferencePages;
00078 std::set < std::string > mGeneratorFiles;
00079 std::set < std::string > mImageFiles;
00080 std::set < std::string > mLuaFunctions;
00081 
00082 
00083 // destination layout (effective, defaults to libfaudes std)
00084 std::string mFaudesBase;
00085 std::string mFaudesBin;
00086 std::string mFaudesBinLuafaudes;
00087 std::string mFaudesBinLuaflx;
00088 std::string mFaudesBinRef2html;
00089 bool mFaudesStandalone = false;
00090 std::string mFaudesBinLua2ref;
00091 std::string mFaudesDoc;
00092 std::string mFaudesDocCss;
00093 std::string mFaudesDocToc;
00094 std::string mFaudesDocNav;
00095 std::string mFaudesDocRti;
00096 std::string mFaudesDocReference;
00097 std::string mFaudesDocLuafaudes;
00098 std::string mFaudesDocImages;
00099 std::string mFaudesDocRefsrc;
00100 std::string mFaudesDocTemp;
00101 
00102 
00103 
00104 // ******************************************************************
00105 // helper: make/remove dir
00106 // ******************************************************************
00107 
00108 // mkdir 
00109 void MakeDirectory(const std::string& rPath, const std::string& rDir="") {
00110   std::string dir = rPath;
00111   if(rDir!="") dir += faudes_pathsep() + rDir;
00112   if(DirectoryExists(dir)) return;
00113   std::cerr << "flxinstall: creating dir \"" << dir << "\"" << std::endl;
00114   int sysret=std::system(std::string("mkdir " + dir).c_str());
00115   if(sysret!=0) {
00116     std::cerr << "flxinstall: error while creating directory \"" << dir << "\"" << std::endl;
00117     usage_exit();
00118   }
00119 }
00120 
00121 
00122 // remove unix hidden files from list
00123 std::set < std::string >  EraseHiddenFiles(const std::set < std::string > & src) {
00124   std::set < std::string > res;
00125   for(std::set < std::string >::iterator fit=src.begin(); fit!=src.end(); fit++) {
00126     if(*fit=="") continue;
00127     if((*fit).at(0)=='.') continue;
00128     res.insert(*fit);
00129   }
00130   return res;
00131 }
00132 
00133 
00134 
00135 // ******************************************************************
00136 // helper: lua to ref process
00137 // ******************************************************************
00138 
00139 void Lua2ref(const std::string& rLuaFile, const std::string& rRefFile="") {
00140   // bail out 
00141   if(mFaudesBinLua2ref=="") {
00142     std::cerr << "flxinstall: ignoring lua script \"" << rLuaFile << "\"" << std::endl;
00143     return;
00144   }
00145   // set up target
00146   std::string dst=rRefFile;
00147   if(dst=="") {
00148     dst=PrependDirectory(ExtractDirectory(rLuaFile),ExtractBasename(rLuaFile)+ ".fref");
00149   }
00150   // set up command
00151   std::string cmd= mFaudesBinLua2ref + " " + rLuaFile + " > " + dst;
00152   // run 
00153   std::cerr << "flxinstall: converting lua script \"" << rLuaFile << "\"" << std::endl;
00154   int sysret=std::system(cmd.c_str());
00155   if(sysret!=0) {
00156     std::cerr << "flxinstall: error while converting lua script \"" << rLuaFile << "\"" << std::endl;
00157     usage_exit();
00158   }
00159     
00160 }
00161 
00162 // ******************************************************************
00163 // helper: gen to ref process
00164 // ******************************************************************
00165 
00166 void Gen2ref(const std::string& rGenFile, const std::string& rRefFile="") {
00167   std::cerr << "flxinstall: converting generator file \"" << rGenFile << "\"" << std::endl;
00168   std::string bas = ExtractBasename(rGenFile);
00169   // set up source and target
00170   std::string dst=rRefFile;
00171   if(dst=="") {
00172     dst=PrependDirectory(ExtractDirectory(rGenFile),bas+".fref");
00173   }
00174   TokenWriter tw(dst);
00175   TokenReader tr(rGenFile);
00176   // convert
00177   try {
00178     // reference page
00179     Token btag;
00180     btag.SetBegin("ReferencePage");
00181     btag.InsAttributeString("chapter","images");
00182     btag.InsAttributeString("section","none");
00183     btag.InsAttributeString("page","none");
00184     btag.InsAttributeString("title","Example Data");
00185     tw << btag;
00186     // headline
00187     tw.WriteCharacterData("<h1> Example Date: "+bas+".gen </h1>\n");
00188     // svg image
00189     tw.WriteCharacterData("<h3> Dot-processed graph as SVG-image </h3>\n");
00190     tw.WriteCharacterData("<object type=\"image/svg+xml\" name=\"graph\" data=\""+bas+".svg\">\n");
00191     tw.WriteCharacterData("<a class=\"faudes_image\" href=\""+bas+".svg\">\n");
00192     tw.WriteCharacterData("<img src=\"$genfile.png\" title=\"Click on image to download SVG formated file.\" />\n");
00193     tw.WriteCharacterData("</a></object>");
00194     // headline
00195     tw.WriteCharacterData("<h3>Token IO</h3>\n");
00196     // copy generator
00197     tw.WriteBegin("pre");
00198     const std::string& genstr=tr.ReadSection();
00199     tw.WriteText(genstr); // this will escape critical entities
00200     tw.WriteEnd("pre");
00201     // close my elements
00202     tw.WriteCharacterData("<p>&nbsp;</p><p>&nbsp;</p>\n");
00203     tw.WriteEnd("ReferencePage");
00204   } catch( faudes::Exception&){
00205     std::cerr << "flxinstall: error while converting generator \"" << rGenFile << "\"" << std::endl;
00206     usage_exit();
00207   }
00208 }
00209 
00210 
00211 // ******************************************************************
00212 // helper: copy files
00213 // ******************************************************************
00214 
00215 // extract and copy token section
00216 void InsertSection(TokenReader& rTr, TokenWriter& rTw, const std::string& mLabel) {
00217   // get begin
00218   Token btag;
00219   rTr.ReadBegin(mLabel,btag);
00220   // copy section
00221   rTw.Write(btag);
00222   std::string scttext = rTr.ReadSection();
00223   rTw.WriteCharacterData(scttext);
00224   rTw.WriteEnd(mLabel);    
00225   // read end tag
00226   rTr.ReadEnd(mLabel);
00227 }
00228 
00229 // extract and copy page data
00230 void InsertReferencePage(TokenReader& rTr, TokenWriter& rTw, const std::string mSection="") {
00231   // get begin
00232   Token btag;
00233   rTr.ReadBegin("ReferencePage",btag);
00234   // fix attributes
00235   if(!btag.ExistsAttributeString("chapter")) 
00236     btag.InsAttributeString("chapter","Reference");
00237   if(!btag.ExistsAttributeString("section")) 
00238   if(mSection!="")
00239     btag.InsAttributeString("section",mSection);
00240   // copy section
00241   rTw.Write(btag);
00242   std::string scttext = rTr.ReadSection();
00243   rTw.WriteCharacterData(scttext);
00244   rTw.WriteEnd("ReferencePage");    
00245   // read end tag
00246   rTr.ReadEnd("ReferencePage");
00247 }
00248 
00249 
00250 // extract and copy luafunction
00251 void InsertLuaFunction(TokenReader& rTr, TokenWriter& rTw) {
00252   // get begin
00253   Token btag;
00254   rTr.ReadBegin("LuaFunctionDefinition",btag);
00255   // copy section
00256   rTw.Write(btag);
00257   std::string scttext = rTr.ReadSection();
00258   rTw.WriteCharacterData(scttext);
00259   rTw.WriteEnd("LuaFunctionDefinition");    
00260   // read end tag
00261   rTr.ReadEnd("LuaFunctionDefinition");
00262 }
00263 
00264 
00265 
00266 // extract and copy tutorial (from xml to plain)
00267 void InsertPlainLuaTutorial(TokenReader& rTr, TokenWriter& rTw) {
00268   // get begin
00269   Token btag;
00270   rTr.ReadBegin("LuaTutorial",btag);
00271   // copy cdata
00272   std::string codestr;
00273   Token code;
00274   while(rTr.Peek(code)) {
00275     if(!code.IsString()) break;
00276     rTr.Get(code);
00277     codestr.append(code.StringValue());
00278   }
00279   *rTw.Streamp() << codestr;
00280   // read end tag
00281   rTr.ReadEnd("LuaTutorial");
00282 }
00283 
00284 
00285 // extract and copy tutorial (from plain to xml)
00286 void InsertLuaTutorial(TokenReader& rTr, TokenWriter& rTw) {
00287   // read script file to buffer
00288   char* buffer=0;
00289   long int size=0;
00290   try{
00291     rTr.Rewind();
00292     rTr.Streamp()->seekg(0, std::ios::end);
00293     std::streampos last = rTr.Streamp()->tellg();
00294     rTr.Streamp()->seekg(0, std::ios::beg);
00295     std::streampos first = rTr.Streamp()->tellg();
00296     size=(long int) last-first;
00297     buffer = new char[last-first]; 
00298     rTr.Streamp()->read(buffer, last-first);
00299     rTr.Rewind();
00300   } catch (std::ios::failure&) {
00301     std::cerr << "flxinstall: io error when reading  \"" << rTr.FileName() << "\": ERROR." << std::endl;
00302     exit(1);
00303   }
00304   // convert (better solution?)
00305   std::string bufferstr;
00306   bufferstr.assign(buffer,size);
00307   // relative destination
00308   std::string name=rTr.FileName();
00309   name=ExtractFilename(name);
00310   // write cdata encoded entry
00311   Token btag;
00312   btag.SetBegin("LuaTutorial");
00313   btag.InsAttributeString("name",name);
00314   rTw.Write(btag);
00315   rTw.WriteVerbatim(bufferstr);
00316   rTw.WriteEnd("LuaTutorial");
00317   // discard buffer
00318   delete buffer;
00319 }
00320 
00321 
00322 
00323 // copy source as binary image file
00324 void InsertImageFile(TokenReader& rTr,TokenWriter& rTw) {
00325   // read image file to buffer
00326   char* buffer=0;
00327   long int size=0;
00328   try{
00329     rTr.Rewind();
00330     rTr.Streamp()->seekg(0, std::ios::end);
00331     std::streampos last = rTr.Streamp()->tellg();
00332     rTr.Streamp()->seekg(0, std::ios::beg);
00333     std::streampos first = rTr.Streamp()->tellg();
00334     size=(long int) last-first;
00335     buffer = new char[last-first]; 
00336     rTr.Streamp()->read(buffer, last-first);
00337     rTr.Rewind();
00338   } catch (std::ios::failure&) {
00339     std::cerr << "flxinstall: io error when reading  \"" << rTr.FileName() << "\": ERROR." << std::endl;
00340     exit(1);
00341   }
00342   // relative destination
00343   std::string name=rTr.FileName();
00344   name=ExtractFilename(name);
00345   // write Base64 encoded entry
00346   Token btag;
00347   btag.SetBegin("ImageFile");
00348   btag.InsAttributeString("name",name);
00349   rTw.Write(btag);
00350   rTw.WriteBinary(buffer,size);
00351   rTw << "\n";
00352   rTw.WriteEnd("ImageFile");
00353   // discard buffer
00354   delete buffer;
00355 }
00356 
00357 
00358 
00359 // copy source as binary data file
00360 void InsertDataFile(TokenReader& rTr,TokenWriter& rTw) {
00361   // read data file to buffer
00362   char* buffer=0;
00363   long int size=0;
00364   try{
00365     rTr.Rewind();
00366     rTr.Streamp()->seekg(0, std::ios::end);
00367     std::streampos last = rTr.Streamp()->tellg();
00368     rTr.Streamp()->seekg(0, std::ios::beg);
00369     std::streampos first = rTr.Streamp()->tellg();
00370     size=(long int) last-first;
00371     buffer = new char[last-first]; 
00372     rTr.Streamp()->read(buffer, last-first);
00373     rTr.Rewind();
00374   } catch (std::ios::failure&) {
00375     std::cerr << "flxinstall: io error when reading  \"" << rTr.FileName() << "\": ERROR." << std::endl;
00376     exit(1);
00377   }
00378   // relative destination
00379   std::string name=rTr.FileName();
00380   name=ExtractFilename(name);
00381   // write Base64 encoded entry
00382   Token btag;
00383   btag.SetBegin("DataFile");
00384   btag.InsAttributeString("name",name);
00385   rTw.Write(btag);
00386   rTw.WriteBinary(buffer,size);
00387   rTw << "\n";
00388   rTw.WriteEnd("DataFile");
00389   // discard buffer
00390   delete buffer;
00391 }
00392 
00393 
00394 
00395 
00396 // ******************************************************************
00397 // create
00398 // ******************************************************************
00399 
00400 
00401 // control
00402 void CreateExtensionFile(void) {
00403 
00404   // ************ pass 1: inspect sources
00405 
00406   // traverse images
00407   for(std::set < std::string >::iterator fit=mSourceFiles.begin(); fit!=mSourceFiles.end(); fit++) {
00408     // test extension
00409     std::string ext=ExtractExtension(*fit);
00410     std::string bas=ExtractBasename(*fit);
00411     std::string pbas=ExtractDirectory(*fit)+bas; 
00412     // case: full generator image
00413     if( mSourceFiles.find(pbas + ".gen") != mSourceFiles.end())
00414     if( mSourceFiles.find(pbas + ".svg") != mSourceFiles.end())
00415     if( mSourceFiles.find(pbas + ".png") != mSourceFiles.end()) { 
00416       if( mGeneratorFiles.find(pbas) == mGeneratorFiles.end()) {
00417         std::cerr << "flxinstall: scanning full generator image \"" << pbas << ".*\"" << std::endl;
00418         mGeneratorFiles.insert(pbas);
00419       }
00420       continue;
00421     } 
00422     // skip non images
00423     if(! ((ext=="png") || (ext=="svg") || (ext=="jpeg") || (ext=="jpg") )) continue;
00424     // case: std image/binary
00425     std::cerr << "flxinstall: scanning image file \"" << *fit << "\"" << std::endl;
00426     mImageFiles.insert(*fit);
00427   }
00428   // traverse luafunctions
00429   for(std::set < std::string >::iterator fit=mSourceFiles.begin(); fit!=mSourceFiles.end(); fit++) {
00430     // test extension
00431     std::string ext=ExtractExtension(*fit);
00432     std::string bas=ExtractBasename(*fit);
00433     // cases: luafunction
00434     if(ext=="rti" && mImageFiles.find(bas)==mImageFiles.end()) {
00435       std::cerr << "flxinstall: scanning luafunction \"" << *fit << "\"" << std::endl;
00436       TokenReader tr(*fit);
00437       Token btag;
00438       tr.ReadBegin("LuaFunctionDefinition",btag);
00439       if(!btag.ExistsAttributeString("name")) {
00440         std::cerr << "flxinstall: name not specified " << tr.FileLine() << ": ERROR." << std::endl;
00441         exit(1);
00442       }
00443       // extract name and space
00444       std::string name;
00445       std::string space;
00446       name=btag.AttributeStringValue("name");
00447       size_t pos=name.find("::"); 
00448       if(pos!=std::string::npos) {
00449         space=name.substr(0,pos);
00450         name=name.substr(pos+2);
00451       }
00452       // insist in matching space
00453       if(space!="" && mExtensionName!="" && space!=mExtensionName) {
00454         std::cerr << "flxinstall: namespace must match extension name" << tr.FileLine() << ": ERROR." << std::endl;
00455         exit(1);
00456       }
00457       mExtensionName=space;
00458       // done
00459       tr.ReadEnd("LuaFunctionDefinition");
00460     }
00461   }
00462   // traverse ref pages
00463   for(std::set < std::string >::iterator fit=mSourceFiles.begin(); fit!=mSourceFiles.end(); fit++) {
00464     // test extension
00465     std::string ext=ExtractExtension(*fit);
00466     std::string bas=ExtractBasename(*fit);
00467     // cases: reference page
00468     if(ext=="fref") {
00469       std::cerr << "flxinstall: scanning reference page \"" << *fit << "\"" << std::endl;
00470       TokenReader tr(*fit);
00471       Token btag;
00472       tr.ReadBegin("ReferencePage",btag);
00473       if(!btag.ExistsAttributeString("page")) {
00474         std::cerr << "flxinstall: page not specified " << tr.FileLine() << ": ERROR." << std::endl;
00475         exit(1);
00476       }
00477       if(!btag.ExistsAttributeString("title")) {
00478         std::cerr << "flxinstall: title not specified " << tr.FileLine() << std::endl;
00479         exit(1);
00480       }
00481       if(btag.ExistsAttributeString("chapter")) 
00482       if(btag.AttributeStringValue("chapter")!="Reference") {
00483         std::cerr << "flxinstall: chapter must be \"Reference\" " << tr.FileLine() << ": ERROR." << std::endl;
00484         exit(1);
00485       }
00486       if(btag.ExistsAttributeString("section")) 
00487       if(mExtensionName.size()==0) {
00488         mExtensionName=btag.AttributeStringValue("section");
00489       }
00490       if(btag.ExistsAttributeString("section")) 
00491       if(mExtensionName!=btag.AttributeStringValue("section")) {
00492         std::cerr << "flxinstall: section name \"" << mExtensionName << "\" expected " 
00493              << tr.FileLine() << ": ERROR." << std::endl;
00494         exit(1);
00495       }
00496       std::string page=btag.AttributeStringValue("page");
00497       std::transform(page.begin(), page.end(), page.begin(), tolower);
00498       // swallow page number
00499       std::string ppage=page;
00500       std::size_t upos = ppage.find_first_of("_");
00501       std::size_t dpos = 0;
00502       for(; dpos < ppage.size();dpos++) 
00503         if(!isdigit(ppage.at(dpos))) break;
00504       if(upos!=std::string::npos)
00505         if(upos==dpos)
00506           if(upos+1<ppage.size()) 
00507             ppage=ppage.substr(upos+1,ppage.size()-upos-1);
00508       // record
00509       if(mReferencePages.find(ppage)!=mReferencePages.end()) {
00510         std::cerr << "flxinstall: double page label \"" << ppage << "\" "
00511             << tr.FileLine() << ": ERROR." << std::endl;
00512         exit(1);
00513       }
00514       mReferencePages.insert(ppage);
00515       tr.ReadEnd("ReferencePage");
00516     }
00517   }
00518   if(mReferencePages.find("index")==mReferencePages.end()) {
00519     std::cerr << "flxinstall: missing index page, will be generated on installation." << std::endl;
00520   }
00521 
00522 
00523   // ************ pass 2: read/copy sources
00524 
00525   // set up target
00526   TokenWriter* ptw=0;
00527   if(mTarget=="") {
00528     mTarget=mExtensionName + ".flx";
00529     std::transform(mTarget.begin(), mTarget.end(), mTarget.begin(), tolower);
00530   }
00531   if(mTarget!="-")
00532     ptw=new TokenWriter(mTarget,"LuaExtension");
00533   else    
00534     ptw=new TokenWriter(TokenWriter::Stdout);
00535   // indicate tool version
00536   *ptw->Streamp() << "<!-- flxinstall " << VersionString() << " -->" << std::endl;
00537   // start tag
00538   Token btag;
00539   btag.SetBegin("LuaExtension");
00540   btag.InsAttributeString("name",mExtensionName);
00541   ptw->Write(btag);
00542   // traverse files
00543   for(std::set < std::string >::iterator fit=mSourceFiles.begin(); fit!=mSourceFiles.end(); fit++) {
00544     // test extension
00545     std::string ext=ExtractExtension(*fit);
00546     std::string bas=ExtractBasename(*fit);
00547     std::string pbas=ExtractDirectory(*fit)+bas; 
00548     // cases: reference page
00549     if(ext=="fref") {
00550       std::cerr << "flxinstall: appending reference page from \"" << *fit << "\"" << std::endl;
00551       *ptw << "\n" << "\n";
00552       *ptw->Streamp() << mXmlSeparator << std::endl;
00553       *ptw->Streamp() << mXmlSeparator << std::endl;
00554       *ptw->Streamp() << mXmlSeparator << std::endl;
00555       *ptw->Streamp() << "<!-- reference page from source \"" << *fit << "\" -->" << std::endl;
00556       *ptw << "\n" << "\n";
00557       TokenReader tr(*fit);
00558       InsertReferencePage(tr,*ptw,mExtensionName);
00559       continue;
00560     }  
00561     // cases: code
00562     if(ext=="rti") {
00563       std::cerr << "flxinstall: appending lua function from \"" << *fit << "\"" << std::endl;
00564       *ptw << "\n" << "\n";
00565       *ptw->Streamp() << mXmlSeparator << std::endl;
00566       *ptw->Streamp() << mXmlSeparator << std::endl;
00567       *ptw->Streamp() << mXmlSeparator << std::endl;
00568       *ptw->Streamp() << "<!-- lua function from source \"" << *fit << "\" -->" << std::endl;
00569       *ptw << "\n" << "\n";
00570       TokenReader tr(*fit);
00571       InsertLuaFunction(tr,*ptw);
00572       continue;
00573     }  
00574     // cases: binary image
00575     if(mImageFiles.find(*fit)!=mImageFiles.end()) {
00576       std::cerr << "flxinstall: appending image/binary file from \"" << *fit << "\"" << std::endl;
00577       *ptw << "\n" << "\n";
00578       *ptw->Streamp() << mXmlSeparator << std::endl;
00579       *ptw->Streamp() << mXmlSeparator << std::endl;
00580       *ptw->Streamp() << mXmlSeparator << std::endl;
00581       *ptw->Streamp() << "<!-- binary file from source \"" << *fit << "\" -->" << std::endl;
00582       *ptw << "\n" << "\n";
00583       TokenReader tr(*fit);
00584       InsertImageFile(tr,*ptw);
00585       continue;
00586     } 
00587     // cases: full generator image
00588     if(mGeneratorFiles.find(pbas)!=mGeneratorFiles.end()) {
00589       std::cerr << "flxinstall: appending full generator from \"" << pbas << ".*\"" << std::endl;
00590       *ptw << "\n" << "\n";
00591       *ptw->Streamp() << mXmlSeparator << std::endl;
00592       *ptw->Streamp() << mXmlSeparator << std::endl;
00593       *ptw->Streamp() << mXmlSeparator << std::endl;
00594       *ptw->Streamp() << "<!-- full generator image from source \"" << pbas << ".*\" -->" << std::endl;
00595       *ptw << "\n" << "\n";
00596       TokenReader trg(pbas+".gen");
00597       InsertImageFile(trg,*ptw);
00598       *ptw << "\n" << "\n";
00599       TokenReader trs(pbas+".svg");
00600       InsertImageFile(trs,*ptw);
00601       *ptw << "\n" << "\n";
00602       TokenReader trp(pbas+".png");
00603       InsertImageFile(trp,*ptw);
00604       mGeneratorFiles.erase(pbas);
00605       continue;
00606     } 
00607     // cases: tutorial
00608     if(ext=="lua") {
00609       std::cerr << "flxinstall: appending tutorial from \"" << *fit << "\"" << std::endl;
00610       *ptw << "\n" << "\n";
00611       *ptw->Streamp() << mXmlSeparator << std::endl;
00612       *ptw->Streamp() << mXmlSeparator << std::endl;
00613       *ptw->Streamp() << mXmlSeparator << std::endl;
00614       *ptw->Streamp() << "<!-- tutorial from source \"" << *fit << "\" -->" << std::endl;
00615       *ptw << "\n" << "\n";
00616       TokenReader tr(*fit);
00617       InsertLuaTutorial(tr,*ptw);
00618       continue;
00619     }  
00620     // cases: data directory
00621     if(ext=="" && bas=="data") {
00622       std::set< std::string > datafiles = ReadDirectory(*fit);
00623       datafiles=EraseHiddenFiles(datafiles);
00624       if(datafiles.size()==0) continue;
00625       std::cerr << "flxinstall: appending data files \"" << *fit << "\"" << std::endl;
00626       *ptw << "\n" << "\n";
00627       *ptw->Streamp() << mXmlSeparator << std::endl;
00628       *ptw->Streamp() << mXmlSeparator << std::endl;
00629       *ptw->Streamp() << mXmlSeparator << std::endl;
00630       *ptw->Streamp() << "<!-- data from source \"" << *fit << "\" -->" << std::endl;
00631       *ptw << "\n" << "\n";
00632       std::set< std::string >::iterator dit;
00633       for(dit=datafiles.begin();dit!=datafiles.end();dit++) {
00634   std::string srcfile=PrependDirectory(*fit,*dit);
00635         TokenReader tr(srcfile);
00636         InsertDataFile(tr,*ptw);
00637       }
00638     }  
00639   }
00640   // cleanup/close
00641   *ptw << "\n" << "\n";
00642   ptw->WriteEnd("LuaExtension"); 
00643   delete ptw;
00644 }
00645 
00646 
00647 // ******************************************************************
00648 // test libfaudes installation
00649 // ******************************************************************
00650 
00651 // inspect libfaudes distribution to locate luafaudes (use mFaudesBin)
00652 void TestLuafaudes(void) {
00653   // read bin dir
00654   if(!DirectoryExists(mFaudesBin)){
00655     std::cerr << "flxinstall: cannot open libfaudes binary path \"" << mFaudesBin << "\": ERROR." << std::endl;
00656     exit(1);
00657   }
00658   std::set< std::string > binfiles = ReadDirectory(mFaudesBin);
00659   // find luafaudes
00660   mFaudesBinLuafaudes="";
00661   if(binfiles.find("luafaudes.exe")!= binfiles.end()) {
00662     mFaudesBinLuafaudes=PrependDirectory(mFaudesBin,"luafaudes.exe");
00663   }
00664   if(binfiles.find("luafaudes")!= binfiles.end()) {
00665     mFaudesBinLuafaudes=PrependDirectory(mFaudesBin,"luafaudes");
00666   }
00667   if(!FileExists(mFaudesBinLuafaudes)) {
00668     std::cerr << "flxinstall: warning: cannot open luafaudes in \"" << mFaudesBin << "\"" << std::endl;
00669     mFaudesBinLuafaudes="";
00670   }
00671 }
00672 
00673 // inspect libfaudes distribution
00674 void TestFaudesTarget(void) {
00675   mFaudesBase=mTarget;
00676   std::set< std::string > faudesfiles = ReadDirectory(mFaudesBase);
00677   // bad dir
00678   if(faudesfiles.empty()) {
00679     std::cerr << "flxinstall: cannot open target directory \"" << mFaudesBase << "\": ERROR." << std::endl;
00680     exit(1);
00681   }
00682   // bin (allow overwrite)
00683   if(mFaudesBin=="") {
00684     mFaudesBin=mFaudesBase;
00685     if(faudesfiles.find("bin")!= faudesfiles.end())
00686       mFaudesBin=PrependDirectory(mFaudesBase,"bin");
00687   }
00688   if(!DirectoryExists(mFaudesBin)){
00689     std::cerr << "flxinstall: cannot open libfaudes binary path in \"" << mFaudesBin << "\": ERROR." << std::endl;
00690     exit(1);
00691   }
00692   std::set< std::string > binfiles = ReadDirectory(mFaudesBin);
00693   // insist in ref2html
00694   mFaudesBinRef2html="";
00695   if(binfiles.find("ref2html.exe")!= binfiles.end()) {
00696     mFaudesBinRef2html=PrependDirectory(mFaudesBin,"ref2html.exe");
00697   }
00698   if(binfiles.find("ref2html")!= binfiles.end()) {
00699     mFaudesBinRef2html=PrependDirectory(mFaudesBin,"ref2html");
00700   }
00701   if(mFaudesBinRef2html=="") {
00702     std::cerr << "flxinstall: cannot open ref2html tool in \"" << mFaudesBin << "\": ERROR." << std::endl;
00703     exit(1);
00704   }
00705   // ref2html options
00706   if(mFaudesStandalone) mFaudesBinRef2html += " -app";
00707   // find luafaudes
00708   TestLuafaudes();
00709   // default flx
00710   mFaudesBinLuaflx=PrependDirectory(mFaudesBin,"luafaudes.flx");
00711   // doc (allow overwrite)
00712   if(mFaudesDoc=="") {
00713     mFaudesDoc=mFaudesBase;
00714     if(faudesfiles.find("doc")!= faudesfiles.end()) {
00715       mFaudesDoc=PrependDirectory(mFaudesDoc,"doc");
00716     } else if(faudesfiles.find("Doc")!= faudesfiles.end()) {
00717       mFaudesDoc=PrependDirectory(mFaudesDoc,"Doc");
00718     } else if(faudesfiles.find("Documentation")!= faudesfiles.end()) {
00719       mFaudesDoc=PrependDirectory(mFaudesDoc,"Documentation");
00720     } 
00721     if(!DirectoryExists(mFaudesDoc)){
00722       std::cerr << "flxinstall: cannot open libfaudes documentation path in \"" << mFaudesBase << "\": ERROR." << std::endl;
00723       exit(1);
00724     }
00725   }
00726   if(!DirectoryExists(mFaudesDoc)){
00727     std::cerr << "flxinstall: cannot open libfaudes documentation path at \"" << mFaudesDoc << "\": ERROR." << std::endl;
00728     exit(1);
00729   }
00730   std::set< std::string > docfiles = ReadDirectory(mFaudesDoc);
00731   // css (allow overwrite)
00732   if(mFaudesDocCss=="") mFaudesDocCss="faudes.css";
00733   mFaudesDocCss=ExtractFilename(mFaudesDocCss); // ignore directory
00734   // reference
00735   mFaudesDocReference=mFaudesDoc;
00736   if(docfiles.find("reference")!= docfiles.end()) {
00737     mFaudesDocReference=PrependDirectory(mFaudesDoc,"reference");
00738   } else if(docfiles.find("Reference")!= faudesfiles.end()) {
00739     mFaudesDocReference=PrependDirectory(mFaudesDoc,"Reference");
00740   }
00741   if(!DirectoryExists(mFaudesDocReference)){
00742     std::cerr << "flxinstall: cannot open libfaudes reference path in \"" << mFaudesDoc << "\": ERROR." << std::endl;
00743     exit(1);
00744   }
00745   std::set< std::string > regfiles = ReadDirectory(mFaudesDocReference);
00746   // luafaudes doc (default: non-existent)
00747   mFaudesDocLuafaudes="";
00748   if(docfiles.find("luafaudes")!= docfiles.end()) {
00749     mFaudesDocLuafaudes=PrependDirectory(mFaudesDoc,"luafaudes");
00750   } else if(docfiles.find("Luafaudes")!= docfiles.end()) {
00751     mFaudesDocLuafaudes=PrependDirectory(mFaudesDoc,"Luafaudes");
00752   } 
00753   // lua2ref (try luafaudes on lua2ref.lua)
00754   if(mFaudesBinLuafaudes!="") {
00755     std::string script =  mFaudesBase + faudes_pathsep() + "tools" + faudes_pathsep() 
00756        + "lua2ref" + faudes_pathsep() + "lua2ref.lua";
00757     mFaudesBinLua2ref=mFaudesBinLuafaudes + " " + script;
00758     if(!FileExists(script)) mFaudesBinLua2ref = "";
00759     if(!FileExists(mFaudesBinLuafaudes)) mFaudesBinLua2ref = "";
00760   }
00761   // lua2ref (try perl on lua2ref.pl)
00762   if(mFaudesBinLua2ref=="") {
00763     mFaudesBinLua2ref = mFaudesBase + faudes_pathsep() + "tools" + faudes_pathsep() 
00764        + "lua2ref" + faudes_pathsep() + "lua2ref.pl";
00765     if(!FileExists(mFaudesBinLua2ref)) mFaudesBinLua2ref = "";
00766   }
00767   // images
00768   mFaudesDocImages="";
00769   if(docfiles.find("images")!= docfiles.end()) {
00770     mFaudesDocImages=PrependDirectory(mFaudesDoc,"images");
00771   } else {
00772     std::cerr << "flxinstall: cannot open images in \"" << mFaudesDoc << "\": ERROR." << std::endl;
00773     exit(1);
00774   }
00775   // refsrc
00776   mFaudesDocRefsrc="";
00777   if(docfiles.find("refsrc")!= docfiles.end()) {
00778     mFaudesDocRefsrc=PrependDirectory(mFaudesDoc,"refsrc");
00779   } else {
00780     std::cerr << "flxinstall: cannot open refsrc in \"" << mFaudesDoc << "\": ERROR." << std::endl;
00781     exit(1);
00782   }
00783   std::set< std::string > refsrcfiles = ReadDirectory(mFaudesDocRefsrc);
00784   // rti (allow overwrite)
00785   if(mFaudesDocRti=="") mFaudesDocRti = PrependDirectory(mFaudesDocRefsrc,"libfaudes.rti");
00786   if(!FileExists(mFaudesDocRti)){
00787     std::cerr << "flxinstall: cannot open libfaudes.rti at \"" << mFaudesDocRti << "\": ERROR." << std::endl;
00788     exit(1);
00789   }
00790   // cnav (allow overwrite)
00791   if(mFaudesDocNav=="") mFaudesDocNav="faudes_navigation.include_fref";
00792   mFaudesDocNav=ExtractFilename(mFaudesDocNav); // ignore directory
00793   mFaudesDocNav=PrependDirectory(mFaudesDocRefsrc,mFaudesDocNav); // enforce directory
00794   if(!FileExists(mFaudesDocNav)){
00795     std::cerr << "flxinstall: cannot open navigation file \"" << mFaudesDocNav << "\": ERROR." << std::endl;
00796     exit(1);
00797   }
00798   // temp
00799   mFaudesDocTemp=PrependDirectory(mFaudesDocRefsrc,"tmp_flx");
00800   if(docfiles.find("tmp_flx")== docfiles.end()) {
00801     std::cerr << "flxinstall: creating temp dir \"" << mFaudesDocTemp << "\"" << std::endl;
00802     MakeDirectory(mFaudesDocTemp);
00803   } 
00804   mFaudesDocToc=PrependDirectory(mFaudesDocTemp,"toc.ftoc");
00805 }
00806 
00807  
00808 // ******************************************************************
00809 // extract reference pages
00810 // ******************************************************************
00811 
00812 
00813 void  XtractReferencePages(TokenReader& rTr, const std::string& rDstDir) {
00814   // read outer tag
00815   Token btag;
00816   rTr.Rewind();
00817   rTr.ReadBegin("LuaExtension",btag);
00818   if(!btag.ExistsAttributeString("name")) {
00819     std::cerr << "flxinstall: lua-extension must have a name attribute " << rTr.FileLine() << ": ERROR." << std::endl;
00820     exit(1);
00821   }
00822   mExtensionName=btag.AttributeStringValue("name");  
00823   // scan for reference page sections
00824   while(!rTr.Eos("LuaExtension")) {
00825     rTr.Peek(btag);
00826     // skip tokens
00827     if(!btag.IsBegin()) {
00828       rTr.Get(btag);
00829       continue;
00830     }
00831     // skip sections
00832     if(btag.StringValue()!="ReferencePage") {
00833       rTr.ReadBegin(btag.StringValue());
00834       rTr.ReadEnd(btag.StringValue());
00835       continue;
00836     }
00837     // extract title & friends
00838     std::string title="libFAUDES Reference";
00839     if(btag.ExistsAttributeString("title")) 
00840       title=btag.AttributeStringValue("title");
00841     std::string chapter="Reference";
00842     if(btag.ExistsAttributeString("chapter")) 
00843       chapter=btag.AttributeStringValue("chapter");
00844     std::string section="";
00845     if(btag.ExistsAttributeString("section")) 
00846       section=btag.AttributeStringValue("section");
00847     std::string page="";
00848     if(btag.ExistsAttributeString("page")) 
00849       page=btag.AttributeStringValue("page");
00850     // insist in page and section
00851     if(page=="" || section=="") {
00852       std::cerr << "flxinstall: skipping undefined page at " << rTr.FileLine() << std::endl;
00853       rTr.ReadBegin("ReferencePage",btag);
00854       rTr.ReadEnd("ReferencePage");
00855       continue;
00856     } 
00857     // normalize & report 
00858     std::transform(section.begin(), section.end(), section.begin(), tolower);
00859     std::transform(page.begin(), page.end(), page.begin(), tolower);
00860     // swallow page number
00861     std::string ppage=page;
00862     std::size_t upos = ppage.find_first_of("_");
00863     std::size_t dpos = 0;
00864     for(; dpos < ppage.size();dpos++) 
00865       if(!isdigit(ppage.at(dpos))) break;
00866     if(upos!=std::string::npos)
00867       if(upos==dpos)
00868         if(upos+1<ppage.size()) 
00869           ppage=ppage.substr(upos+1,ppage.size()-upos-1);
00870     // basename
00871     std::string basename= section + "_" + ppage;
00872     mReferencePages.insert(basename);
00873     // dst file
00874     std::string dstfile=rDstDir + faudes_pathsep() + basename + ".fref";
00875     std::cerr << "flxinstall: extracting reference page to \"" << dstfile << "\"" << std::endl;
00876     TokenWriter dst(dstfile);
00877     InsertReferencePage(rTr,dst);
00878   }  
00879 }
00880 
00881 // ******************************************************************
00882 // extract image files
00883 // ******************************************************************
00884 
00885 
00886 void  XtractImageFiles(TokenReader& rTr,const std::string& rDstDir) {
00887   // read outer tag
00888   Token btag;
00889   rTr.Rewind();
00890   rTr.ReadBegin("LuaExtension",btag);
00891   if(!btag.ExistsAttributeString("name")) {
00892     std::cerr << "flxinstall: lua-extension must have a name attribute " << rTr.FileLine() << ": ERROR." << std::endl;
00893     exit(1);
00894   }
00895   mExtensionName=btag.AttributeStringValue("name");  
00896   // scan for image files
00897   while(!rTr.Eos("LuaExtension")) {
00898     rTr.Peek(btag);
00899     // skip tokens
00900     if(!btag.IsBegin()) {
00901       rTr.Get(btag);
00902       continue;
00903     }
00904     // skip sections
00905     if(btag.StringValue()!="ImageFile") {
00906       rTr.ReadBegin(btag.StringValue());
00907       rTr.ReadEnd(btag.StringValue());
00908       continue;
00909     }
00910     // read begin tag
00911     rTr.ReadBegin("ImageFile",btag);
00912     std::string name=btag.AttributeStringValue("name");
00913     if(name==""){
00914       std::cerr << "flxinstall: image file must specify name " << rTr.FileLine() << std::endl;
00915       rTr.ReadEnd("ImageFile");
00916       continue;
00917     } 
00918     // skip non-image formats
00919     std::string ext = ExtractExtension(name);
00920     if(ext!="png" && ext!="svg" && ext!="jpg" && ext!="jpeg") {
00921       rTr.ReadEnd("ImageFile");
00922       continue;
00923     }
00924     // read data
00925     Token data;
00926     rTr.Get(data);
00927     if(!data.IsBinary()){
00928       std::cerr << "flxinstall: skipping invalid image data " << rTr.FileLine() << std::endl;
00929       rTr.ReadEnd("ImageFile");
00930       continue;
00931     } 
00932     // dst file
00933     std::transform(name.begin(), name.end(), name.begin(), tolower);
00934     std::string dstfile=rDstDir + faudes_pathsep() + name;
00935     std::cerr << "flxinstall: extracting image to \"" << dstfile << "\"" << std::endl;
00936     // record
00937     mImageFiles.insert(dstfile);
00938     // setup stream
00939     std::fstream fsout;
00940     fsout.exceptions(std::ios::badbit|std::ios::failbit);
00941     try{
00942       fsout.open(dstfile.c_str(), std::ios::out | std::ios::binary); 
00943       fsout.write(data.StringValue().c_str(),data.StringValue().size());
00944       fsout.close();
00945     } 
00946     catch (std::ios::failure&) {
00947       std::cerr << "flxinstall: file io error when writing  \"" << dstfile << "\"" << std::endl;
00948     }
00949     // read end tag
00950     rTr.ReadEnd("ImageFile");
00951   }  
00952 }
00953 
00954 void  XtractImageGenFiles(TokenReader& rTr,const std::string& rDstDir) {
00955   // read outer tag
00956   Token btag;
00957   rTr.Rewind();
00958   rTr.ReadBegin("LuaExtension",btag);
00959   if(!btag.ExistsAttributeString("name")) {
00960     std::cerr << "flxinstall: lua-extension must have a name attribute " << rTr.FileLine() << ": ERROR." << std::endl;
00961     exit(1);
00962   }
00963   mExtensionName=btag.AttributeStringValue("name");  
00964   // scan for image files
00965   while(!rTr.Eos("LuaExtension")) {
00966     rTr.Peek(btag);
00967     // skip tokens
00968     if(!btag.IsBegin()) {
00969       rTr.Get(btag);
00970       continue;
00971     }
00972     // skip sections
00973     if(btag.StringValue()!="ImageFile") {
00974       rTr.ReadBegin(btag.StringValue());
00975       rTr.ReadEnd(btag.StringValue());
00976       continue;
00977     }
00978     // read begin tag
00979     rTr.ReadBegin("ImageFile",btag);
00980     std::string name=btag.AttributeStringValue("name");
00981     if(name==""){
00982       std::cerr << "flxinstall: image file must specify name " << rTr.FileLine() << std::endl;
00983       rTr.ReadEnd("ImageFile");
00984       continue;
00985     } 
00986     // skip non-gen formats
00987     std::string ext = ExtractExtension(name);
00988     if(ext!="gen"){
00989       rTr.ReadEnd("ImageFile");
00990       continue;
00991     }
00992     // read data
00993     Token data;
00994     rTr.Get(data);
00995     if(!data.IsBinary()){
00996       std::cerr << "flxinstall: skipping invalid image data " << rTr.FileLine() << std::endl;
00997       rTr.ReadEnd("ImageFile");
00998       continue;
00999     } 
01000     // dst file
01001     std::transform(name.begin(), name.end(), name.begin(), tolower);
01002     std::string dstfile=rDstDir + faudes_pathsep() + name;
01003     std::cerr << "flxinstall: extracting image to \"" << dstfile << "\"" << std::endl;
01004     // record
01005     mImageFiles.insert(dstfile);
01006     // setup stream
01007     std::fstream fsout;
01008     fsout.exceptions(std::ios::badbit|std::ios::failbit);
01009     try{
01010       fsout.open(dstfile.c_str(), std::ios::out | std::ios::binary); 
01011       fsout.write(data.StringValue().c_str(),data.StringValue().size());
01012       fsout.close();
01013     } 
01014     catch (std::ios::failure&) {
01015       std::cerr << "flxinstall: file io error when writing  \"" << dstfile << "\"" << std::endl;
01016     }
01017     // read end tag
01018     rTr.ReadEnd("ImageFile");
01019   }  
01020 }
01021 
01022 
01023 // ******************************************************************
01024 // extract lua code
01025 // ******************************************************************
01026 
01027 
01028 
01029 void  XtractLuaFunctions(TokenReader& rTr, TokenWriter& rTw) {
01030   // read outer tag
01031   Token btag;
01032   rTr.Rewind();
01033   rTr.ReadBegin("LuaExtension",btag);
01034   if(!btag.ExistsAttributeString("name")) {
01035     std::cerr << "flxinstall: lua-extension must have a name attribute " << rTr.FileLine() << ": ERROR." << std::endl;
01036     exit(1);
01037   }
01038   mExtensionName=btag.AttributeStringValue("name");  
01039   // scan for reference page sections
01040   while(!rTr.Eos("LuaExtension")) {
01041     rTr.Peek(btag);
01042     // skip tokens
01043     if(!btag.IsBegin()) {
01044       rTr.Get(btag);
01045       continue;
01046     }
01047     // skip sections
01048     if(btag.StringValue()!="LuaFunctionDefinition") {
01049       rTr.ReadBegin(btag.StringValue());
01050       rTr.ReadEnd(btag.StringValue());
01051       continue;
01052     }
01053     // extract title & friends
01054     std::string name;
01055     std::string space;
01056     if(btag.ExistsAttributeString("name")){
01057       name=btag.AttributeStringValue("name");
01058       size_t pos=name.find("::"); 
01059       if(pos!=std::string::npos) {
01060         space=name.substr(0,pos);
01061         name=name.substr(pos+2);
01062       }
01063     }
01064     // insist in name 
01065     if(name=="") {
01066       std::cerr << "flxinstall: skipping undefined lua function at " << rTr.FileLine() << std::endl;
01067       rTr.ReadBegin("LuaFunctionDefinition",btag);
01068       rTr.ReadEnd("LuafunctionDefinition");
01069       continue;
01070     } 
01071     // insist in space to match 
01072     /*
01073     if(space!=mExtensionName) {
01074       std::cerr << "flxinstall: skipping undefined lua function at " << rTr.FileLine() << std::endl;
01075       rTr.ReadBegin("LuaFunctionDefinition",btag);
01076       rTr.ReadEnd("LuafunctionDefinition");
01077       continue;
01078     } 
01079     */
01080     // record
01081     mLuaFunctions.insert(name);
01082     // copy
01083     std::cerr << "flxinstall: extracting lua function \"" << name << "\"" << std::endl;
01084     *rTw.Streamp() << mXmlSeparator << std::endl;
01085     *rTw.Streamp() << mXmlSeparator << std::endl;
01086     *rTw.Streamp() << "<!-- lua function from lua-extension " << rTr.FileLine() << " -->" << std::endl;
01087     rTw << "\n" << "\n";
01088     InsertLuaFunction(rTr,rTw);
01089   }  
01090 }
01091 
01092 // ******************************************************************
01093 // extract lua tutorials
01094 // ******************************************************************
01095 
01096 void  XtractLuaTutorials(TokenReader& rTr, const std::string& rDstDir) {
01097   // read outer tag
01098   Token btag;
01099   rTr.Rewind();
01100   rTr.ReadBegin("LuaExtension",btag);
01101   if(!btag.ExistsAttributeString("name")) {
01102     std::cerr << "flxinstall: lua-extension must have a name attribute " << rTr.FileLine() << ": ERROR." << std::endl;
01103     exit(1);
01104   }
01105   mExtensionName=btag.AttributeStringValue("name");  
01106   // scan for reference page sections
01107   while(!rTr.Eos("LuaExtension")) {
01108     rTr.Peek(btag);
01109     // skip tokens
01110     if(!btag.IsBegin()) {
01111       rTr.Get(btag);
01112       continue;
01113     }
01114     // skip sections
01115     if(btag.StringValue()!="LuaTutorial") {
01116       rTr.ReadBegin(btag.StringValue());
01117       rTr.ReadEnd(btag.StringValue());
01118       continue;
01119     }
01120     // test for name
01121     std::string name=btag.AttributeStringValue("name");
01122     if(name==""){
01123       std::cerr << "flxinstall: lua tutorial must specify name " << rTr.FileLine() << std::endl;
01124       rTr.ReadEnd("LuaTutorial");
01125       continue;
01126     } 
01127     // set up destination and copy
01128     std::transform(name.begin(), name.end(), name.begin(), tolower);
01129     std::string dstfile=rDstDir + faudes_pathsep() + name;
01130     std::cerr << "flxinstall: extracting lua tutorial to \"" << dstfile << "\"" << std::endl;
01131     TokenWriter tw(dstfile);
01132     InsertPlainLuaTutorial(rTr,tw);
01133   }
01134 }
01135 
01136 // ******************************************************************
01137 // generate default reference page
01138 // ******************************************************************
01139 
01140 void DefaultIndexPage(const std::string& rDstDir) {
01141   // name of index files
01142   std::string index=mExtensionName + "_index";
01143   std::transform(index.begin(), index.end(), index.begin(), tolower);
01144   // test existence
01145   if(mReferencePages.find(index)!=mReferencePages.end()) {
01146     std::cerr << "flxinstall: index page provided" << std::endl;
01147     return;
01148   } 
01149   // error case
01150   if(mReferencePages.size()>0) {
01151     std::cerr << "flxinstall: reference page missing: \"" << index << ".fref\": ERROR" << std::endl;
01152     exit(1);
01153   } 
01154   // generates defaultindex page
01155   std::cerr << "flxinstall: generate index page" << std::endl;
01156   TokenWriter tw(rDstDir + faudes_pathsep() + index + ".fref","ReferencePage");
01157   *tw.Streamp() << "<!-- flxinstall " << VersionString() << ": auto generated index -->" << std::endl;
01158   *tw.Streamp() << "<ReferencePage chapter=\"Reference\" section=\"" << mExtensionName << 
01159     "\" page=\"0_Index\" title=\""<< mExtensionName << " Index\" >" << std::endl;
01160   // headline
01161   *tw.Streamp() << "<h1> " << mExtensionName << ": Functions </h1>" << std::endl;
01162   // list functions
01163   std::set< std::string >::iterator fit;
01164   for(fit=mLuaFunctions.begin(); fit!= mLuaFunctions.end(); fit++) {
01165     *tw.Streamp() << "<ffnct_reference name=\"" << *fit << "\" />" << std::endl;
01166   }
01167   // done
01168   *tw.Streamp() << "</ReferencePage>" << std::endl;
01169 } 
01170 
01171 
01172 
01173 
01174 // ******************************************************************
01175 // install extension
01176 // ******************************************************************
01177 
01178 // control
01179 void InstallExtensionFiles(void) {
01180 
01181   // clear context
01182   mImageFiles.clear();
01183 
01184   // clean tmp (this is for dstinstall to see only relevant files in the temp directory)
01185   std::set< std::string > tmpfiles = ReadDirectory(mFaudesDocTemp);
01186   for(std::set < std::string >::iterator fit=tmpfiles.begin(); fit!=tmpfiles.end(); fit++) {
01187     std::string dfile=PrependDirectory(mFaudesDocTemp,*fit);
01188     if(!RemoveFile(dfile)) {
01189       std::cerr << "flxinstall: failed to remove \"" << *fit << "\"" << std::endl;
01190     };
01191   }
01192 
01193   // prepare luafaudes.flx
01194   TokenWriter* twflx = new TokenWriter(PrependDirectory(mFaudesDocTemp,"luafaudes.flx"));
01195 
01196   // convenience: reinterpret directories 
01197   std::set< std::string > srcfiles;
01198   for(std::set < std::string >::iterator fit=mSourceFiles.begin(); fit!=mSourceFiles.end(); fit++) {
01199     std::string sfile = *fit;
01200     if(ExtractExtension(sfile)=="flx") {
01201       srcfiles.insert(sfile);
01202       continue;
01203     }
01204     std::set< std::string > sdir = ReadDirectory(sfile);
01205     sdir=EraseHiddenFiles(sdir);
01206     for(std::set < std::string >::iterator dit=sdir.begin();dit!=sdir.end();dit++) {
01207       sfile=PrependDirectory(*fit,*dit);
01208       srcfiles.insert(sfile);
01209     }
01210   }
01211 
01212   // traverse flx-files and extract
01213   for(std::set < std::string >::iterator fit=srcfiles.begin(); fit!=srcfiles.end(); fit++) {
01214     // test extension
01215     std::string ext=ExtractExtension(*fit);
01216     std::string bas=ExtractBasename(*fit);
01217     // cases: flx
01218     if(ext=="flx") {
01219       std::cerr << "flxinstall: extracting lua-extension from \"" << *fit << "\"" << std::endl;
01220       // clear extension context
01221       mReferencePages.clear();
01222       mLuaFunctions.clear();
01223       mExtensionName="";
01224       // extract component files
01225       TokenReader rTr(*fit);
01226       XtractReferencePages(rTr,mFaudesDocTemp);
01227       XtractLuaTutorials(rTr,mFaudesDocTemp);
01228       XtractImageFiles(rTr,mFaudesDocImages);  
01229       XtractImageGenFiles(rTr,mFaudesDocTemp);  
01230       XtractLuaFunctions(rTr,*twflx);
01231       // autogenerate index if necessary
01232       DefaultIndexPage(mFaudesDocTemp);      
01233       continue;
01234     } 
01235   }
01236 
01237   // copy composed flx file to accompanie luafaudes binary
01238   delete twflx;
01239   FileCopy(PrependDirectory(mFaudesDocTemp,"luafaudes.flx"),mFaudesBinLuaflx);
01240 
01241   // report
01242   std::cerr << "flxinstall: generating list of source files" << std::endl;
01243 
01244   // record all files relevant to toc
01245   std::set< std::string > tocsource;
01246   // record all basenames to detect doublet fref
01247   std::set< std::string > frefbase;
01248 
01249 
01250   // collect all fref files for processing to doc/
01251   std::set< std::string > docsource;
01252   std::set< std::string > docrefsrc = ReadDirectory(mFaudesDocRefsrc);
01253   for(std::set < std::string >::iterator fit=docrefsrc.begin(); fit!=docrefsrc.end(); fit++) {
01254     std::string ext=ExtractExtension(*fit);
01255     std::string bas=ExtractBasename(*fit);
01256     std::string ffile=PrependDirectory(mFaudesDocRefsrc,*fit);
01257     if(ext!="fref") continue;
01258     if(frefbase.find(bas)!=frefbase.end()){
01259       std::cerr << "flxinstall: reference file doublet \"" << *fit << "\" from std dist: ERROR." << std::endl;
01260       exit(1);
01261     }
01262     docsource.insert(ffile);
01263     tocsource.insert(ffile);
01264     frefbase.insert(bas);
01265   }
01266 
01267   // collect all fref files for processing to doc/reference
01268   std::set< std::string > docrefsource;
01269   std::set< std::string > docrefsrcref = ReadDirectory(PrependDirectory(mFaudesDocRefsrc,"reference"));
01270   for(std::set < std::string >::iterator fit=docrefsrcref.begin(); fit!=docrefsrcref.end(); fit++) {
01271     std::string ext=ExtractExtension(*fit);
01272     std::string bas=ExtractBasename(*fit);
01273     std::string ffile=PrependDirectory(PrependDirectory(mFaudesDocRefsrc,"reference"),*fit);
01274     if(ext!="fref") continue;
01275     if(frefbase.find(bas)!=frefbase.end()){
01276       std::cerr << "flxinstall: reference file doublet \"" << *fit << "\" from std dist: ERROR." << std::endl;
01277       exit(1);
01278     }
01279     docrefsource.insert(ffile);
01280     tocsource.insert(ffile);
01281     frefbase.insert(bas);
01282   }
01283   std::set< std::string > doctmpdir = ReadDirectory(mFaudesDocTemp);
01284   for(std::set < std::string >::iterator fit=doctmpdir.begin(); fit!=doctmpdir.end(); fit++) {
01285     std::string ext=ExtractExtension(*fit);
01286     std::string bas=ExtractBasename(*fit);
01287     std::string ffile=PrependDirectory(mFaudesDocTemp,*fit);
01288     if(ext!="fref") continue;
01289     if(frefbase.find(bas)!=frefbase.end()){
01290       std::cerr << "flxinstall: reference file doublet \"" << *fit << "\" from ext: ERROR." << std::endl;
01291       exit(1);
01292     }
01293     docrefsource.insert(ffile);
01294     tocsource.insert(ffile);
01295     frefbase.insert(bas);
01296   }
01297 
01298 
01299   // collect/generate all luatutorial files for processing to doc/luafaudes
01300   std::set< std::string > docluasource;
01301   std::set< std::string > docrefsrclua = ReadDirectory(PrependDirectory(mFaudesDocRefsrc,"luafaudes"));
01302   for(std::set < std::string >::iterator fit=docrefsrclua.begin(); fit!=docrefsrclua.end(); fit++) {
01303     std::string ext=ExtractExtension(*fit);
01304     std::string bas=ExtractBasename(*fit);
01305     std::string ffile=PrependDirectory(PrependDirectory(mFaudesDocRefsrc,"luafaudes"),*fit);
01306     if(ext!="fref") continue;
01307     if(frefbase.find(bas)!=frefbase.end()){
01308       std::cerr << "flxinstall: reference file doublet \"" << *fit << "\" from lua doc: ERROR." << std::endl;
01309       exit(1);
01310     }
01311     docluasource.insert(ffile);
01312     tocsource.insert(ffile);  // list of tutorials is required in toc
01313     frefbase.insert(bas);
01314   }
01315   /*std::set< std::string > */tmpfiles = ReadDirectory(mFaudesDocTemp);
01316   for(std::set < std::string >::iterator fit=tmpfiles.begin(); fit!=tmpfiles.end(); fit++) {
01317     std::string ext=ExtractExtension(*fit);
01318     std::string bas=ExtractBasename(*fit);
01319     std::string lfile=PrependDirectory(mFaudesDocTemp,*fit);
01320     std::string ffile=PrependDirectory(mFaudesDocTemp,bas+".fref");
01321     // skip non-lua
01322     if(ext!="lua") continue;
01323     // test for corresponding fref file
01324     std::string fref = ExtractBasename(*fit) + ".fref";
01325     if(tmpfiles.find(fref)!=tmpfiles.end()) continue;
01326     // process
01327     Lua2ref(lfile,ffile);
01328     // record (conditional for e.g. dstinstall, where no lua tutorials are generated)
01329     if(FileExists(ffile)) {
01330       docluasource.insert(ffile);
01331       tocsource.insert(ffile);  // list of tutorials is required in toc
01332       frefbase.insert(bas);
01333     }
01334   }
01335 
01336   // convert/generate full generator images to fref (dest: doc/images)
01337   std::set< std::string > docimgsource;
01338   std::set< std::string > docrefsrcimg = ReadDirectory(PrependDirectory(mFaudesDocRefsrc,"images"));
01339   for(std::set < std::string >::iterator fit=docrefsrcimg.begin(); fit!=docrefsrcimg.end(); fit++) {
01340     std::string ext=ExtractExtension(*fit);
01341     std::string bas=ExtractBasename(*fit);
01342     std::string ffile=PrependDirectory(PrependDirectory(mFaudesDocRefsrc,"images"),*fit);
01343     if(ext!="fref") continue;
01344     docimgsource.insert(ffile);
01345   }
01346   std::set< std::string > imgfiles = ReadDirectory(mFaudesDocTemp);
01347   for(std::set < std::string >::iterator fit=imgfiles.begin(); fit!=imgfiles.end(); fit++) {
01348     std::string ext=ExtractExtension(*fit);
01349     std::string bas=ExtractBasename(*fit);
01350     std::string gfile=PrependDirectory(mFaudesDocTemp,*fit);
01351     std::string ffile=PrependDirectory(mFaudesDocTemp,bas+".fref");
01352     // skip non-gen
01353     if(ext!="gen") continue;
01354     // test whther we wrote that file
01355     if(mImageFiles.find(gfile)==mImageFiles.end()) continue;
01356     // process to fref
01357     Gen2ref(gfile,ffile);
01358     // record (conditional)
01359     if(FileExists(ffile)) 
01360       docimgsource.insert(ffile);
01361   }
01362 
01363 
01364   // compose toc
01365   std::string toccmd;
01366   for(std::set < std::string >::iterator fit=tocsource.begin(); fit!=tocsource.end(); fit++) {
01367     toccmd+= " " + *fit;
01368   }
01369   toccmd=mFaudesBinRef2html + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -toc " + toccmd
01370     + " " + mFaudesDocToc;
01371   std::cerr << "flxinstall: creating toc" << std::endl;
01372   if(std::system(toccmd.c_str())!=0) {
01373     std::cerr << "flxinstall: processing" << std::endl << toccmd << std::endl;
01374     std::cerr << "flxinstall: error setting up toc: ERROR." << std::endl;
01375     exit(1);
01376   }
01377   std::cerr << "flxinstall: creating toc: done" << std::endl;
01378 
01379 
01380   // process all pages to doc
01381   std::string doccmd;
01382   for(std::set < std::string >::iterator fit=docsource.begin(); fit!=docsource.end(); fit++) {
01383     doccmd += " " + *fit;
01384   }
01385   doccmd= mFaudesBinRef2html 
01386        + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01387        + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc 
01388        + doccmd +  " " + mFaudesDoc;
01389   std::cerr << "flxinstall: processing doc base" << std::endl;
01390   if(std::system(doccmd.c_str())!=0) {
01391     std::cerr << "flxinstall: processing" << std::endl << doccmd << std::endl;
01392     std::cerr << "flxinstall: error while processing doc base: ERROR." << std::endl;
01393     exit(1);
01394   }
01395   std::cerr << "flxinstall: processing doc base: done" << std::endl;
01396 
01397   // process all pages to doc/reference
01398   std::string refcmd;
01399   for(std::set < std::string >::iterator fit=docrefsource.begin(); fit!=docrefsource.end(); fit++) {
01400     refcmd += " " + *fit;
01401   }
01402   refcmd= mFaudesBinRef2html 
01403        + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01404        + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc + " -rel ../  " 
01405        + refcmd +  " " + mFaudesDocReference;
01406   std::cerr << "flxinstall: processing user reference" << std::endl;
01407   if(std::system(refcmd.c_str())!=0) {
01408     std::cerr << "flxinstall: processing" << std::endl << refcmd << std::endl;
01409     std::cerr << "flxinstall: error while processing user reference: ERROR." << std::endl;
01410     exit(1);
01411   }
01412   std::cerr << "flxinstall: processing user reference: done" << std::endl;
01413 
01414   // process all pages to doc/luafaudes
01415   if(mFaudesDocLuafaudes!="" && docluasource.size()>0) {
01416     std::string luacmd;
01417     for(std::set < std::string >::iterator fit=docluasource.begin(); fit!=docluasource.end(); fit++) {
01418       luacmd += " " + *fit;
01419     }
01420     luacmd= mFaudesBinRef2html 
01421          + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01422          + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc + " -rel ../  " 
01423          + luacmd +  " " + mFaudesDocLuafaudes; 
01424     std::cerr << "flxinstall: processing lua tutorial" << std::endl;
01425     if(std::system(luacmd.c_str())!=0) {
01426       std::cerr << "flxinstall: processing" << std::endl << luacmd << std::endl;
01427       std::cerr << "flxinstall: error while processing lua tutorial: ERROR." << std::endl;
01428       exit(1);
01429     }
01430     std::cerr << "flxinstall: processing lua tutorial: done" << std::endl;
01431   }
01432 
01433   // process all pages to doc/images/
01434   if(mFaudesDocImages!="" && docimgsource.size()>0) {
01435     std::string imgcmd;
01436     for(std::set < std::string >::iterator fit=docimgsource.begin(); fit!=docimgsource.end(); fit++) 
01437       imgcmd += " " + *fit;
01438     imgcmd= mFaudesBinRef2html 
01439          + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01440          + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc + " -rel ../  " 
01441          + imgcmd +  " " + mFaudesDocImages;
01442     std::cerr << "flxinstall: processing image files" << std::endl;
01443     if(std::system(imgcmd.c_str())!=0) {
01444       std::cerr << "flxinstall: processing" << std::endl << imgcmd << std::endl;
01445       std::cerr << "flxinstall: error while processing image files: ERROR." << std::endl;
01446       exit(1);
01447     }
01448     std::cerr << "flxinstall: processing image files: done" << std::endl;
01449   }
01450 
01451 
01452   // copy index file: main index
01453   if(FileExists(PrependDirectory(mFaudesDocRefsrc,"faudes_about.fref"))) {
01454     std::string dst=PrependDirectory(mFaudesDoc,"index.html");
01455     std::string proccmd= mFaudesBinRef2html 
01456         + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01457         + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc + " -rel ./  " 
01458         + PrependDirectory(mFaudesDocRefsrc,"faudes_about.fref") +  " " + dst;
01459     std::cerr << "flxinstall: fix html index " << std::endl;
01460     if(std::system(proccmd.c_str())!=0) {
01461       std::cerr << "flxinstall: error when processing index.html: ERROR." <<std::endl;
01462       exit(1);
01463     }
01464   }
01465 
01466   // copy index file: luafaudes
01467   if(mFaudesDocLuafaudes!="" && DirectoryExists(PrependDirectory(mFaudesDocRefsrc,"luafaudes"))){
01468     std::string dst=PrependDirectory(mFaudesDocLuafaudes,"index.html");
01469     std::string proccmd= mFaudesBinRef2html 
01470         + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01471         + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc + " -rel ../  " 
01472         + PrependDirectory(mFaudesDocRefsrc,"luafaudes/faudes_luafaudes.fref") +  " " + dst;
01473     std::cerr << "flxinstall: fix html index " << std::endl;
01474     if(std::system(proccmd.c_str())!=0) {
01475       std::cerr << "flxinstall: error when processing index.html: ERROR." <<std::endl;
01476       exit(1);
01477     }
01478   }
01479 
01480   // copy index file: reference
01481   if(mFaudesDocReference!="" && DirectoryExists(PrependDirectory(mFaudesDocRefsrc,"reference"))){
01482     std::string dst=PrependDirectory(mFaudesDocReference,"index.html");
01483     std::string proccmd= mFaudesBinRef2html 
01484         + " -rti " + mFaudesDocRti + " -flx " + mFaudesBinLuaflx + " -cnav " + mFaudesDocNav
01485         + " -css " + mFaudesDocCss + " -inc " + mFaudesDocToc + " -rel ../  " 
01486         + PrependDirectory(mFaudesDocRefsrc,"reference/reference_index.fref") +  " " + dst;
01487     std::cerr << "flxinstall: fix html index " << std::endl;
01488     if(std::system(proccmd.c_str())!=0) {
01489       std::cerr << "flxinstall: error when processing index.html: ERROR." <<std::endl;
01490       exit(1);
01491     }
01492   }
01493 
01494   // clean tmp 
01495   // (dont do so: keep frefs for dstinstall to extract index for qhc)
01496   /*
01497   for(std::set < std::string >::iterator fit=tmpfiles.begin(); fit!=tmpfiles.end(); fit++) {
01498     std::string dfile=PrependDirectory(mFaudesDocTemp,*fit);
01499     RemoveFile(*fit);
01500   }
01501   */
01502 
01503   std::cerr << "flxinstall: done" << std::endl;
01504   
01505 
01506   
01507 }
01508 
01509 
01510 // ******************************************************************
01511 // extract extension
01512 // ******************************************************************
01513 
01514 // control
01515 void ExtractExtensionFile(void) {
01516 
01517   // test extension
01518   std::string ext=ExtractExtension(mSourceFile);
01519   std::string bas=ExtractBasename(mSourceFile);
01520   if(ext!="flx") 
01521     usage_exit("extract must specify a *.flx source");
01522   // prepare to read
01523   TokenReader tr(mSourceFile);
01524   Token btag;
01525   tr.ReadBegin("LuaExtension",btag);
01526   if(!btag.ExistsAttributeString("name")) {
01527     std::cerr << "flxinstall: lua-extension must have a name attribute " << tr.FileLine() << ": ERROR." << std::endl;
01528     exit(1);
01529   }
01530   mExtensionName=btag.AttributeStringValue("name");  
01531   // scan for relevant sections
01532   while(!tr.Eos("LuaExtension")) {
01533     tr.Peek(btag);
01534     // skip tokens
01535     if(!btag.IsBegin()) {
01536       tr.Get(btag);
01537       continue;
01538     }
01539     // switch sections: fref
01540     if(btag.StringValue()=="ReferencePage") {
01541       // figure destination
01542       if(!btag.ExistsAttributeString("page")) {
01543         std::cerr << "flxinstall: skipping referencepage without page attribute" << std::endl;
01544         tr.ReadBegin(btag.StringValue());
01545         tr.ReadEnd(btag.StringValue());
01546         continue;
01547       }
01548       std::string page=mExtensionName + "_" + btag.AttributeStringValue("page") +".fref";
01549       std::transform(page.begin(), page.end(), page.begin(), tolower);
01550       std::string dstname= mTarget + faudes_pathsep() + page;
01551       std::cerr << "flxinstall: extracting reference page to \"" << dstname << "\"" << std::endl;
01552       // do copy
01553       TokenWriter tw(dstname,"ReferencePage");
01554       InsertReferencePage(tr,tw,mExtensionName);
01555       continue;
01556     }
01557     // switch sections: lua function
01558     if(btag.StringValue()=="LuaFunctionDefinition") {
01559       // figure destination
01560       if(!btag.ExistsAttributeString("name")) { 
01561         std::cerr << "flxinstall: skipping lua function without name attribute" << std::endl;
01562         tr.ReadBegin(btag.StringValue());
01563         tr.ReadEnd(btag.StringValue());
01564         continue;
01565       }
01566       std::string name=btag.AttributeStringValue("name");
01567       size_t pos=name.find("::"); // test this construct for "xyz::"
01568       if(pos!=std::string::npos) name=name.substr(pos+2);
01569       name = name +".rti";
01570       std::transform(name.begin(), name.end(), name.begin(), tolower);
01571       std::string dstname= mTarget + faudes_pathsep() + name;
01572       std::cerr << "flxinstall: extracting lua function to \"" << dstname << "\"" << std::endl;
01573       // do copy
01574       TokenWriter tw(dstname,"LuaFunctionDefinition");
01575       InsertLuaFunction(tr,tw);
01576       continue;
01577     }
01578     // switch sections: image file
01579     if(btag.StringValue()=="ImageFile") {
01580       // figure destination
01581       if(!btag.ExistsAttributeString("name")) { 
01582         std::cerr << "flxinstall: skipping image file without name attribute" << std::endl;
01583         tr.ReadBegin(btag.StringValue());
01584         tr.ReadEnd(btag.StringValue());
01585         continue;
01586       }
01587       std::string name= btag.AttributeStringValue("name");
01588       std::transform(name.begin(), name.end(), name.begin(), tolower);
01589       std::string dstname= mTarget + faudes_pathsep() + name;
01590       std::cerr << "flxinstall: extracting image file to \"" << dstname << "\"" << std::endl;
01591       TokenWriter tw(dstname);
01592       // read data
01593       tr.ReadBegin("ImageFile");
01594       Token data;
01595       tr.Get(data);
01596       if(!data.IsBinary()){
01597       }
01598       // copy to C++ stream
01599       std::fstream fsout;
01600       fsout.exceptions(std::ios::badbit|std::ios::failbit);
01601       try{
01602         fsout.open(dstname.c_str(), std::ios::out | std::ios::binary); 
01603         fsout.write(data.StringValue().c_str(),data.StringValue().size());
01604         fsout.close();
01605       } 
01606       catch (std::ios::failure&) {
01607         std::cerr << "flxinstall: file io error when writing  \"" << dstname << "\"" << std::endl;
01608       }
01609       // done
01610       tr.ReadEnd("ImageFile");
01611       continue;
01612     }
01613     // switch sections: data file
01614     if(btag.StringValue()=="DataFile") {
01615       // figure destination
01616       if(!btag.ExistsAttributeString("name")) { 
01617         std::cerr << "flxinstall: skipping data file without name attribute" << std::endl;
01618         tr.ReadBegin(btag.StringValue());
01619         tr.ReadEnd(btag.StringValue());
01620         continue;
01621       }
01622       std::string name= "data" + faudes_pathsep() + btag.AttributeStringValue("name");
01623       std::transform(name.begin(), name.end(), name.begin(), tolower);
01624       std::string dstname= mTarget + faudes_pathsep() + name;
01625       std::cerr << "flxinstall: extracting data file to \"" << dstname << "\"" << std::endl;
01626       // insist in data directiory
01627       MakeDirectory(mTarget,"data");
01628       TokenWriter tw(dstname);
01629       // read data
01630       tr.ReadBegin("DataFile");
01631       Token data;
01632       tr.Peek(data);
01633       // case 1: binary
01634       if(data.IsBinary()){
01635         tr.Get(data);
01636         // copy to C++ stream
01637         std::fstream fsout;
01638         fsout.exceptions(std::ios::badbit|std::ios::failbit);
01639         try{
01640           fsout.open(dstname.c_str(), std::ios::out | std::ios::binary); 
01641           fsout.write(data.StringValue().c_str(),data.StringValue().size());
01642           fsout.close();
01643         } catch (std::ios::failure&) {
01644           std::cerr << "flxinstall: file io error when writing  \"" << dstname << "\"" << std::endl;
01645         }
01646       }
01647       // case 2: token stream
01648       else if(data.IsBegin()){
01649         // copy to token writer
01650         InsertSection(tr,tw,data.StringValue());
01651       }
01652       // case 3: error
01653       else {
01654         std::cerr << "flxinstall: skipping invalid data " << tr.FileLine() << std::endl;
01655       } 
01656       // read end tag
01657       tr.ReadEnd("DataFile");
01658       continue;
01659     }
01660     // switch sections: data file
01661     if(btag.StringValue()=="LuaTutorial") {
01662       // figure destination
01663       if(!btag.ExistsAttributeString("name")) { 
01664         std::cerr << "flxinstall: skipping tutorial without name attribute" << std::endl;
01665         tr.ReadBegin(btag.StringValue());
01666         tr.ReadEnd(btag.StringValue());
01667         continue;
01668       }
01669       std::string name=btag.AttributeStringValue("name");
01670       std::transform(name.begin(), name.end(), name.begin(), tolower);
01671       std::string dstname= mTarget + faudes_pathsep() + name;
01672       std::cerr << "flxinstall: extracting tutorial to \"" << dstname << "\"" << std::endl;
01673       // do copy
01674       TokenWriter tw(dstname);
01675       InsertPlainLuaTutorial(tr,tw);
01676       continue;
01677     }
01678     // skip unknown
01679     tr.ReadBegin(btag.StringValue());
01680     tr.ReadEnd(btag.StringValue());
01681   }
01682   // done
01683   tr.ReadEnd("LuaExtension");
01684 }
01685 
01686 // ******************************************************************
01687 // run test cases
01688 // ******************************************************************
01689 
01690 // uses mSource for std flx
01691 
01692 void RunTestCases() {
01693   // insist in luafaudes
01694   if(!FileExists(mFaudesBinLuafaudes)) {
01695     std::cerr << "flxinstall: cannot execute luafaudes" << std::endl;
01696     exit(1);
01697   }
01698   // read target directory to extract lua scripts
01699   std::set< std::string > allfiles = ReadDirectory(mTarget);
01700   std::set< std::string > luascripts;
01701   for(std::set < std::string >::iterator fit=allfiles.begin(); fit!=allfiles.end(); fit++) 
01702     if(ExtractExtension(*fit)=="lua") luascripts.insert(*fit);
01703   // loop scripts
01704   for(std::set < std::string >::iterator fit=luascripts.begin(); fit!=luascripts.end(); fit++) {
01705     // build command
01706     std::string cmd = mFaudesBinLuafaudes + " -x " +mSourceFile + " " + *fit;
01707     // run
01708     std::cerr << "flxinstall: execute: " << cmd << std::endl;
01709     int sysret=std::system(cmd.c_str());
01710     if(sysret!=0) {
01711       std::cerr << "flxinstall: error while running lua script \"" << *fit << "\"" << std::endl;
01712       exit(1);
01713     }
01714  
01715 
01716   }
01717 
01718 
01719 }
01720 
01721 // ******************************************************************
01722 // command line ui
01723 // ******************************************************************
01724 
01725 
01726 int main(int argc, char *argv[]) {
01727 
01728   // local config 
01729   bool doc=false;
01730   bool doi=false;
01731   bool dor=false;
01732   bool dox=false;
01733   bool dot=false;
01734 
01735   // min args
01736   if(argc < 2) usage_exit();
01737 
01738   // primitive commad line parsing
01739   int i;
01740   for(i=1; i<argc; i++) {
01741     std::string option(argv[i]);
01742     // overwrite doc
01743     if(option=="-tdoc") { 
01744       i++; if(i>=argc) usage_exit();
01745       mFaudesDoc=argv[i];
01746       continue;
01747     }
01748     // overwrite bin
01749     if(option=="-tbin") { 
01750       i++; if(i>=argc) usage_exit();
01751       mFaudesBin=argv[i];
01752       continue;
01753     }
01754     // overwrite rti
01755     if(option=="-trti") { 
01756       i++; if(i>=argc) usage_exit();
01757       mFaudesDocRti=argv[i];
01758       continue;
01759     }
01760     // overwrite cnav
01761     if(option=="-tcnav") { 
01762       i++; if(i>=argc) usage_exit();
01763       mFaudesDocNav=argv[i];
01764       continue;
01765     }
01766     // overwrite css
01767     if(option=="-tcss") { 
01768       i++; if(i>=argc) usage_exit();
01769       mFaudesDocCss=argv[i];
01770       continue;
01771     }
01772     // target standalone
01773     if(option=="-tapp") { 
01774       mFaudesStandalone = true;
01775       continue;
01776     }
01777     // mode: compile
01778     if(option=="-c") { 
01779       i++; doc=true;
01780       break;
01781     }
01782     // mode: install
01783     if(option=="-i") { 
01784       i++; doi=true;
01785       break;
01786     }
01787     // mode: remove
01788     if(option=="-r") { 
01789       i++; dor=true;
01790       break;
01791     }
01792     // mode: extract
01793     if(option=="-x") { 
01794       i++; dox=true;
01795       break;
01796     }
01797     // mode: test
01798     if(option=="-t") { 
01799       i++; dot=true;
01800       break;
01801     }
01802     // option: help
01803     if((option=="-?") || (option=="--help")) {
01804       usage_exit();
01805       continue;
01806     }
01807     // option: unknown
01808     if(option.size()>1)
01809     if(option.at(0)=='-') {
01810       usage_exit("unknown option " + option);
01811       continue;
01812     }
01813     // must choose mode
01814     usage_exit("must set either -c, -i, -r, -x or -t mode" );
01815   }
01816 
01817   // create
01818   if(doc) {
01819     // figure source files 
01820     for(;i<argc-1;i++) {
01821       mSourceFiles.insert(std::string(argv[i]));
01822     }
01823     // convenience: if its a directory, use all files inside
01824     if(mSourceFiles.size()==1) {
01825       std::set< std::string > srcfiles = ReadDirectory(std::string(argv[i-1]));
01826       srcfiles=EraseHiddenFiles(srcfiles);
01827       if(srcfiles.size()>0) {
01828         mSourceFiles.clear();
01829         for(std::set < std::string >::iterator fit=srcfiles.begin(); fit!=srcfiles.end(); fit++) 
01830           mSourceFiles.insert(PrependDirectory(std::string(argv[i-1]),*fit));
01831       }
01832     }
01833     // have a target file
01834     if(!(i<argc))
01835       usage_exit("target *.flx-file not specified");
01836     //  figure target file
01837     mTarget=std::string(argv[i]);
01838     // consistency: insist in .flx target
01839     if(mTarget!="-")
01840     if(ExtractExtension(mTarget)!="flx") 
01841       usage_exit("target *.flx-file not specified");
01842     // doit
01843     CreateExtensionFile();
01844     exit(0);
01845   }
01846 
01847   // install
01848   if(doi) {
01849     // have at least one source
01850     if(!(i<argc-1)) 
01851       usage_exit("source and target must be specified");
01852     // figure source files 
01853     for(;i<argc-1;i++) {
01854       mSourceFiles.insert(std::string(argv[i]));
01855     }
01856     // convenience: if its a directory, use all files inside
01857     if(mSourceFiles.size()==1) {
01858       std::set< std::string > srcfiles = ReadDirectory(std::string(argv[i-1]));
01859       srcfiles=EraseHiddenFiles(srcfiles);
01860       if(srcfiles.size()>0) {
01861         mSourceFiles.clear();
01862         for(std::set < std::string >::iterator fit=srcfiles.begin(); fit!=srcfiles.end(); fit++) 
01863           if(ExtractExtension(*fit)=="flx")   
01864             mSourceFiles.insert(PrependDirectory(std::string(argv[i-1]),*fit));
01865       }
01866     }
01867     // insist in flx source
01868     for(std::set < std::string >::iterator fit=mSourceFiles.begin(); fit!=mSourceFiles.end(); fit++) 
01869       if(ExtractExtension(*fit)!="flx") 
01870         usage_exit("sources must be *.flx-files: "+ *fit);
01871     // figure target directory
01872     mTarget=std::string(argv[i]);
01873     TestFaudesTarget();
01874     // doit
01875     InstallExtensionFiles();
01876     exit(0);
01877   }
01878 
01879   // remove
01880   if(dor) {
01881     // have at least one file
01882     if(i!=argc-1)
01883       usage_exit("target not specified");
01884     //  figure target file
01885     mTarget=std::string(argv[i]);
01886     TestFaudesTarget();
01887     // doit
01888     InstallExtensionFiles();
01889     if(FileExists(mFaudesBinLuaflx)) FileDelete(mFaudesBinLuaflx);
01890     exit(0);
01891   }
01892 
01893   // xtract
01894   if(dox) {
01895     // insist
01896     if(!(i<argc-1))
01897       usage_exit("source and destination must be specified");
01898     // figure source
01899     mSourceFile=std::string(argv[i++]);
01900     if(ExtractExtension(mSourceFile)!="flx") 
01901       usage_exit("source must be an *.flx-file");
01902     // destination
01903     mTarget=std::string(argv[i++]);
01904     // test consistent args
01905     if((i<argc))
01906       usage_exit("too many arguments");
01907     // doit
01908     MakeDirectory(".",mTarget);
01909     ExtractExtensionFile();
01910     exit(0);
01911   }
01912 
01913   // test
01914   if(dot) {
01915     // insist
01916     if(!(i<argc-1))
01917       usage_exit("source and temp dir must be specified");
01918     // figure source
01919     mSourceFile=std::string(argv[i++]);
01920     if(ExtractExtension(mSourceFile)!="flx") 
01921       usage_exit("source must be an *.flx-file");
01922     // destination
01923     mTarget=std::string(argv[i++]);
01924     // test consistent args
01925     if((i<argc))
01926       usage_exit("too many arguments");
01927     // insist in target to be the current directory and empty
01928     if((mTarget != ".") && (mTarget != "./"))
01929       usage_exit("target must be \".\" or \"./\"");
01930     std::set< std::string > curdir = ReadDirectory(mTarget);
01931     if(curdir.size()!=0)
01932       usage_exit("target must be empty");
01933     // test for luafaudes (expects mFaudesBin)
01934     TestLuafaudes();
01935     // do extract and test
01936     ExtractExtensionFile();
01937     RunTestCases();
01938     // done
01939     exit(0);
01940   }
01941 
01942   // error
01943   usage_exit();
01944 
01945   // never get here
01946   return 1;
01947 }

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen