Back to index

lightning-sunbird  0.9+nobinonly
htmlgen.cpp
Go to the documentation of this file.
00001 /*========================================================
00002   To Do:
00003     1. Tag sequences on the command line p..table
00004     2. Dumping documents into the right place
00005  *========================================================*/
00006 
00007 
00008 /*========================================================
00009   Special keywords:
00010     $0..$9:     represent command line arguments
00011     @file:      the name of the file being writtent
00012     @nextfile:  the name of the next file to be written
00013     @import:    imports text from another file.
00014  *========================================================*/
00015 
00016 
00017 #include <iostream.h>
00018 #include <fstream.h>
00019 #include <strstrea.h>
00020 #include <string>
00021 
00022 #include <stdlib.h>
00023 #include <errno.h>
00024 #include <time.h>
00025 #include <direct.h>
00026 
00027 
00028 static char* tagTable[] = {
00029   "A", "ABBR", "ACRONYM", "ADDRESS", "APPLET", "AREA", 
00030   "B", "BASE", "BASEFONT", "BDO", "BGSOUND", "BIG", "BLINK", "BLOCKQUOTE", "BODY", "BR", "BUTTON", 
00031   "CAPTION", "CENTER", "CITE", "CODE", "COL", "COLGROUP", 
00032   "DD", "DEL", "DFN", "DIR", "DIV", "DL", "DT", 
00033   "EM", "EMBED", 
00034   "FIELDSET", "FONT", "FORM", "FRAME", "FRAMESET", 
00035   "H1", "H2", "H3", "H4", "H5", "H6", "HEAD", "HR", "HTML", 
00036   "I", "IFRAME", "ILAYER", "IMG", "INPUT", "INS", "ISINDEX", 
00037   "KBD", "KEYGEN", 
00038   "LABEL", "LAYER", "LEGEND", "LI", "LINK", "LISTING", 
00039   "MAP", "MENU", "META", "MULTICOL", 
00040   "NOBR", "NOEMBED", "NOFRAMES", "NOLAYER", "NOSCRIPT", 
00041   "OBJECT", "OL", "OPTGROUP", "OPTION", 
00042   "P", "PARAM", "PLAINTEXT", "PRE", 
00043   "Q", 
00044   "S","SAMP","SCRIPT","SELECT","SERVER","SMALL","SOUND","SPACER","SPAN","STRIKE","STRONG","STYLE","SUB","SUP", 
00045   "TABLE", "TBODY", "TD", "TEXTAREA", "TFOOT", "TH", "THEAD", "TITLE", "TR", "TT", 
00046   "U", "UL", 
00047   "VAR", 
00048   "WBR", 
00049   "XMP",
00050   0
00051 };
00052 static char gCWD[1025];
00053 static char gPrevFile[128];
00054 static char gThisFile[128];
00055 static char gNextFile[128];
00056 static int  gFileIndex=0;
00057 
00058 
00059 int findTag(const char* aTagName) {
00060   int low = 0;
00061   int high = 107;
00062   while (low <= high) {
00063     int middle = (low + high) >> 1;
00064     int result = stricmp(aTagName, tagTable[middle]);
00065     if (result == 0)
00066       return middle;
00067     if (result < 0)
00068       high = middle - 1; 
00069     else
00070       low = middle + 1; 
00071   }
00072   return -1;
00073 }
00074 
00075 
00083 int findNearestTag(char* aTag){
00084   int result=-1;
00085   if(aTag){
00086     char  theChar=toupper(aTag[0]);
00087     int theIndex=-1;
00088     while(tagTable[++theIndex]){
00089       if(toupper(tagTable[theIndex][0])==theChar) {
00090         return theIndex;
00091       }
00092     }
00093   }
00094   if(toupper(aTag[0])<'A')
00095     result=0;
00096   else result=107;
00097   return result;
00098 }
00099 
00100 char* getNthTagAfter(int aRangeIndex,char* aStartTag){
00101   int theIndex=findTag(aStartTag);
00102   if(-1==theIndex){
00103     theIndex=findNearestTag(aStartTag);
00104   }
00105   if(-1<theIndex){
00106     //now that you have the tag, 
00107     return tagTable[theIndex+aRangeIndex];
00108   }
00109   return 0; 
00110 }
00111 
00118 class CMacros {
00119 public:
00120         CMacros() {
00121           mCount=0;
00122           mFilename[0]=0;
00123           memset(mKeys,0,sizeof(mKeys));
00124           memset(mRanges,0,sizeof(mRanges));
00125           memset(mIndex,0,sizeof(mIndex));
00126           mBorrowedKeys=false;
00127         }
00128 
00129         CMacros(const CMacros& aCopy) {
00130           mBorrowedKeys=true;
00131           mCount=aCopy.mCount;
00132           strcpy(mFilename,aCopy.mFilename);
00133           memcpy(mKeys,aCopy.mKeys,sizeof(mKeys));
00134           memcpy(mIndex,aCopy.mIndex,sizeof(mIndex));
00135         }
00136 
00137         ~CMacros(){
00138           if(!mBorrowedKeys) {
00139             for(int i=0;i<mCount;i++){
00140               delete [] mKeys[i];
00141               mKeys[i]=0;
00142             }
00143           }
00144         }
00145 
00146   bool  addMacro(char* aString) {
00147     
00148           //copy a macro name...
00149           //start by stripping off the macro key (everything up to the equal sign...
00150           if(aString){
00151             int sLen=strlen(aString);
00152             if(sLen>0){
00153               if((strchr(aString,',')) || (strchr(aString,'-'))) {
00154                 mRanges[mCount]=new char[sLen+1];
00155                 strcpy(mRanges[mCount++],aString);
00156               }
00157               else {
00158                 mKeys[mCount]=new char[sLen+1];
00159                 strcpy(mKeys[mCount++],aString);
00160               }
00161               return true;
00162             }
00163           }
00164           return false;
00165         }
00166 
00167   int   getCount() {return mCount;}
00168   
00169   char* getMacro(int anIndex) {
00170           if(anIndex<mCount)
00171             return mKeys[anIndex];
00172           return 0;
00173         }
00174 
00175   char* getFilename(void) {return mFilename;}
00176 
00177   char* getRangeValueAt(char* aRange,int aRangeIndex) {
00178           static char theBuffer[100];
00179           char* result=0;
00180           char* p1=aRange;
00181           char* p2=0;
00182           int   offset=0;
00183           int   count=-1;
00184             
00185           theBuffer[0]=0;
00186           if(p2=strchr(&aRange[offset],',')) {
00187               //in this case, our keys are taken 1 at a time from the range itself.
00188             while((++count<aRangeIndex) && (p1) && (p2)) {  
00189               p1=p2+1;
00190               p2=strchr(p1,',');
00191             }
00192             if(p1 && (count==aRangeIndex)) {
00193               strncat(theBuffer,p1,p2-p1);
00194             }
00195             result=theBuffer;
00196           }
00197           else if(p2=strchr(&aRange[offset],'-')) {
00198               //in this case, our keys are computed based on HTMLTags within the given range (exclusive).
00199             strncat(theBuffer,p1,p2-p1); 
00200             char* tag=getNthTagAfter(aRangeIndex,theBuffer);
00201             p2++; //p2 now points at the last item...
00202             if(tag){
00203               int end=findNearestTag(p2);
00204               char* endTag=tagTable[end];
00205               if(endTag){
00206                 int icmp=stricmp(tag,endTag);
00207                 if(icmp<=0){
00208                   strcpy(theBuffer,tag);
00209                 }
00210                 else theBuffer[0]=0;
00211                 result=theBuffer;
00212               }
00213               else result=0;
00214             }
00215           }
00216           return result;
00217         }
00218 
00219   bool  first(void) {
00220           bool result=true;
00221           for(int i=0;i<mCount;i++){
00222             mIndex[i]=0;
00223             if(mRanges[i]){
00224               char* key=getRangeValueAt(mRanges[i],mIndex[i]);
00225               if(key) {
00226                 if(!mKeys[i])
00227                   mKeys[i]=new char[100];
00228                 strcpy(mKeys[i],key);
00229               }
00230             }
00231             //otherwise key is already set...
00232           }
00233           sprintf(gThisFile,"out%i.html",gFileIndex++);
00234           sprintf(gNextFile,"out%i.html",gFileIndex);
00235           return result;
00236         }
00237 
00238   bool  next(void) {
00239 
00240           //the trick here is to find the rightmost range and increment it.
00241           //if it wraps, then reset it to 0, and increment the next range to the left.
00242           int rangeIndex=mCount;
00243           bool done=false;
00244           while((0<=--rangeIndex) && (!done)) {
00245             if(mRanges[rangeIndex]) {
00246               //ok, now we know the right most range object.
00247               //let's see if it can be incremented...
00248               char* key=getRangeValueAt(mRanges[rangeIndex],++mIndex[rangeIndex]);
00249               if((0==key)  || (0==key[0])){
00250                 mIndex[rangeIndex]=0;
00251                 char* key=getRangeValueAt(mRanges[rangeIndex],mIndex[rangeIndex]);
00252               }//if
00253               else done=true;
00254               mKeys[rangeIndex][0]=0;
00255               if(key)
00256                 strcpy(mKeys[rangeIndex],key);
00257             }//if
00258           }//while
00259           strcpy(gPrevFile,gThisFile);
00260           sprintf(gThisFile,"out%i.html",gFileIndex++);
00261           sprintf(gNextFile,"out%i.html",gFileIndex);
00262           return done;
00263         }
00264 
00271   bool  consume(istrstream& aStream){
00272           char theBuffer[100];
00273           bool readDefs=false; 
00274 
00275           while(!aStream.eof()){
00276             aStream >> theBuffer;
00277             if(!stricmp(theBuffer,"-F")){
00278               //copy the filename...
00279               aStream >> theBuffer;
00280               strcpy(mFilename,theBuffer);
00281               readDefs=false;
00282             }
00283 #if 0
00284             else if(!stricmp(theBuffer,"-D")){
00285               readDefs=true;
00286             }
00287 #endif
00288             else if(!stricmp(theBuffer,"-O")){
00289               aStream >> theBuffer;
00290               readDefs=false;
00291             }
00292             else {
00293               if(theBuffer[0]){
00294                 addMacro(theBuffer);
00295                 theBuffer[0]=0;
00296               }
00297             }
00298           }
00299           return true;
00300         }
00301 
00302   void  buildArgBuffer(char* aBuffer) {
00303           aBuffer[0]=0;
00304           if(mFilename[0]) {
00305             sprintf(aBuffer,"-o %s -f %s ",gThisFile,mFilename);
00306           }
00307           for(int i=0;i<mCount;i++){
00308             if(mKeys[i]) {
00309               strcat(aBuffer,mKeys[i]);
00310               strcat(aBuffer," ");
00311             }
00312           }
00313         }
00314 
00315   void  dump(void) {
00316           for(int i=0;i<mCount;i++){
00317             cout << mKeys[i] << " ";
00318           }
00319           cout << endl;
00320         }
00321 
00322 protected:
00323   int   mCount;
00324   char* mKeys[100];
00325   char* mRanges[100];
00326   int   mIndex[100];
00327   char  mFilename[125];
00328   bool  mBorrowedKeys;
00329 };
00330 
00337 void expandKeywords(char* aBuffer,CMacros& aMacroSet){
00338   char  temp[1024];
00339   char  theWord[100];
00340 
00341   temp[0]=0;
00342   if(strchr(aBuffer,'@')){
00343 
00344     int pos=-1;
00345     while(aBuffer[++pos]==' ')
00346       strcat(temp," ");
00347 
00348     istrstream iStr(aBuffer);
00349     while(!iStr.eof()){
00350         theWord[0]=0;
00351         iStr>>theWord;
00352         char* thePos=strchr(theWord,'@');
00353         if(thePos){
00354           strncat(temp,theWord,thePos-theWord);
00355           if(!strnicmp(thePos,"@file",5)){
00356             strcat(temp,gThisFile);
00357             thePos+=5;
00358           }
00359           else if(!strnicmp(thePos,"@nextfile",9)){
00360             strcat(temp,gNextFile);
00361             thePos+=9;
00362           }
00363           else if(!strnicmp(thePos,"@prevfile",9)){
00364             strcat(temp,gPrevFile);
00365             thePos+=9;
00366           }
00367           strcat(temp,thePos);
00368         }
00369         else strcat(temp,theWord);
00370         strcat(temp," ");
00371     }
00372     strcpy(aBuffer,temp);
00373   }
00374 }
00375 
00382 void expandMacros(char* aBuffer,CMacros& aMacroSet){
00383   char  temp[1024];
00384   int rPos=-1;
00385   int wPos=0;
00386 
00387   if(aBuffer){
00388     while(aBuffer[++rPos]){
00389       if('$'==aBuffer[rPos]){
00390         temp[wPos]=0;
00391         ++rPos; //skip the $...        
00392         int theIndex=aBuffer[rPos]-'0';
00393         char* theMacro=aMacroSet.getMacro(theIndex);
00394         if(theMacro){
00395           strcat(temp,theMacro);
00396           wPos=strlen(temp);
00397         }
00398       }
00399       else temp[wPos++]=aBuffer[rPos];
00400     }
00401     temp[wPos]=0;
00402     strcpy(aBuffer,temp);
00403   }
00404 }
00405 
00412 int processFile(char* aDir,CMacros& aMacroList,fstream& anOutputStream,fstream& anInputStream){
00413   int result=0;
00414 
00415   if(anInputStream.is_open()){
00416     bool  done=false;
00417     char  theBuffer[1024];
00418     char* p=0;
00419 
00420     while((!done) && (0==result)){
00421     
00422       anInputStream.getline(theBuffer,sizeof(theBuffer)-1);
00423       if(anInputStream.gcount()){
00424 
00425           //before doing anything else, expand the macros and keywords...
00426         expandMacros(theBuffer,aMacroList);
00427         expandKeywords(theBuffer,aMacroList);
00428 
00429         //Now process each line:
00430         p=strstr(theBuffer,"@import");
00431         if(p) {
00432 
00433           //First, see if the line is an htmlgen statement; if so, recurse to read new file...
00434           char theFilename[1024];
00435 
00436           strcpy(theFilename,"htmlgen -F ");
00437           p+=8;
00438           strcat(theFilename,p);
00439 
00440           //If you're here, we found an htmlgen statement. 
00441           //  To handle this, we have to:
00442           //    1. strip off the @htmlgen
00443           //    2. grab the filename and collect the args,
00444           //    3. and recurse...
00445           
00446           fstream theInStream(p,ios::in);
00447           result=processFile(aDir,aMacroList,anOutputStream,theInStream);
00448         }
00449         else anOutputStream << theBuffer << endl;
00450       }
00451       else done=true;
00452     }
00453   }
00454   return result;
00455 }
00456 
00457 
00464 int iterate(istrstream& aInputArgs){
00465   int result=0;
00466 
00467   CMacros theArgs;
00468   theArgs.consume(aInputArgs);
00469 
00470   char theFilename[1024];
00471 
00472   bool done=!theArgs.first();
00473   while((!done) && (0==result)){
00474     CMacros theTempArgs(theArgs);
00475 
00476     //theTempArgs.buildArgBuffer(theBuffer);
00477     //    istrstream theArgStream(theBuffer);
00478 
00479     sprintf(theFilename,"%s\\%s",gCWD,gThisFile);
00480     fstream theOutStream(theFilename,ios::trunc);    
00481 
00482     char* theInFile=theArgs.getFilename();
00483     fstream theInStream(theInFile,ios::in);
00484 
00485     result=processFile(gCWD,theTempArgs,theOutStream,theInStream);
00486     theArgs.dump();
00487     done=!theArgs.next();
00488   }
00489   return result;
00490 }
00491 
00498 int main(int argc,char* argv[]){
00499   int result=0;
00500 
00501   gPrevFile[0]=gThisFile[0]=gNextFile[0];
00502   if(argc>1){
00503     char theBuffer[1024];
00504     theBuffer[0]=0;
00505 
00506     for(int i=1;i<argc;i++){
00507       strcat(theBuffer,argv[i]);
00508       strcat(theBuffer," ");
00509     }
00510 
00511     _getcwd(gCWD,sizeof(gCWD)-1);
00512     istrstream aStrStream(theBuffer);
00513     result=iterate(aStrStream);
00514   }
00515   else cout<<endl <<"HTMLGenerator usage -f filename [yyy | xxx,yyy | xxx-yyy]" << endl;
00516   return result;
00517 }