home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / utils / HelpGen / src / scriptbinder.cpp < prev    next >
C/C++ Source or Header  |  2001-11-19  |  13KB  |  621 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        No names yet.
  3. // Purpose:     Contrib. demo
  4. // Author:      Aleksandras Gluchovas
  5. // Modified by:
  6. // Created:     22/09/98
  7. // RCS-ID:      $Id: scriptbinder.cpp,v 1.5 2001/11/18 12:32:15 GD Exp $
  8. // Copyright:   (c) Aleskandars Gluchovas
  9. // Licence:       wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // For compilers that support precompilation, includes "wx/wx.h".
  13. #include "wx/wxprec.h"
  14.  
  15. #ifdef __BORLANDC__
  16. #pragma hdrstop
  17. #endif
  18.  
  19. #ifndef WX_PRECOMP
  20. #include "wx/wx.h"
  21. #endif
  22.  
  23. #ifndef __DARWIN__
  24. #  include <malloc.h>
  25. #endif
  26. #include <string.h>
  27. #include <memory.h>
  28.  
  29. #include <stdio.h>   // import sprintf() (for doubles)
  30. #include <stdlib.h>  // import atoi()    (for integers)
  31.  
  32. #include "scriptbinder.h"
  33.  
  34. // helper functions
  35.  
  36. static size_t log2(size_t nr)
  37. {
  38.     size_t tmp = 0;
  39.     while (nr >= 2 ) 
  40.     {
  41.         nr /= 2;
  42.         ++tmp;
  43.     }
  44.  
  45.     return tmp;
  46. }
  47.  
  48. /***** Implementation for class ScriptStream *****/
  49.  
  50. ScriptStream::ScriptStream()
  51.     : mpBuf(0),
  52.       mSize(0),
  53.       mCapacity(0)
  54. {}
  55.  
  56. ScriptStream::~ScriptStream()
  57. {
  58.     if ( mpBuf ) delete mpBuf;
  59. }
  60.  
  61. void ScriptStream::WriteBytes( const void* srcBuf, size_t count )
  62. {
  63.     if ( !count ) return;
  64.  
  65.     // increase the capacity if necessary
  66.     if ( mSize + count > mCapacity )
  67.     {
  68.             mCapacity = 
  69.                 (  0x2 << (log2( mSize + count ) + 1 ) );
  70.  
  71.             if ( mCapacity < 128 ) mCapacity = 128;
  72.  
  73.             char* oldBuf = mpBuf;
  74.  
  75.             mpBuf = new char[mCapacity];
  76.  
  77.             if ( oldBuf )
  78.             {
  79.                 memcpy( mpBuf, oldBuf, mSize );
  80.                 delete oldBuf;
  81.             }
  82.     }
  83.  
  84.     // append new data
  85.     memcpy( &mpBuf[mSize], srcBuf, count );
  86.  
  87.     mSize += count;
  88. }
  89.  
  90. ScriptStream& ScriptStream::operator<<( const char* str )
  91. {
  92.     WriteBytes( str, strlen( str ) );
  93.  
  94.     return *this;
  95. }
  96.  
  97. ScriptStream& ScriptStream::operator<<( const string& str )
  98. {
  99.     if ( str.length() < 512 )
  100.     {
  101.         char buf[512];
  102.         size_t len = str.length();
  103.  
  104.         for( size_t i = 0; i != len; ++i )
  105.             buf[i] = str[i];
  106.  
  107.         WriteBytes( buf, len );
  108.     }
  109.     else
  110.         WriteBytes( str.c_str(), str.length() );
  111.  
  112.     return *this;
  113. }
  114.  
  115. ScriptStream& ScriptStream::operator<<( char ch )
  116. {
  117.     WriteBytes( &ch, 1 );
  118.  
  119.     return *this;
  120. }
  121.  
  122. void ScriptStream::endl()
  123. {
  124.     char ch = '\n';
  125.     WriteBytes( &ch, 1 );
  126. }
  127.  
  128. /***** Implementation for class ScriptTemplate *****/
  129.  
  130. ScriptTemplate::ScriptTemplate( const string& templateText )
  131. {
  132.     string tmp = templateText;
  133.  
  134.     mTText = (char*)malloc( tmp.length() + 1 );
  135.  
  136.     strcpy( mTText, tmp.c_str() );
  137. }
  138.  
  139. ScriptTemplate::~ScriptTemplate()
  140. {
  141.     for( size_t i = 0; i != mVars.size(); ++i )
  142.  
  143.         delete mVars[i];
  144.  
  145.     free( mTText );
  146. }
  147.  
  148. bool ScriptTemplate::HasVar( const char* name )
  149. {
  150.     for( size_t i = 0; i != mVars.size(); ++i ) 
  151.  
  152.         if ( strcmp( mVars[i]->mName, name ) == 0 )
  153.  
  154.             return 1;
  155.  
  156.     return 0;
  157. }
  158.  
  159. void ScriptTemplate::AddStringVar ( const char* name, int ofs )
  160. {
  161.     mVars.push_back( new TVarInfo( name, ofs, TVAR_STRING ) );
  162. }
  163.  
  164. void ScriptTemplate::AddIntegerVar( const char* name, int ofs )
  165. {
  166.     mVars.push_back( new TVarInfo( name, ofs, TVAR_INTEGER ) );
  167. }
  168.  
  169. void ScriptTemplate::AddDoubleVar ( const char* name, int ofs )
  170. {
  171.     mVars.push_back( new TVarInfo( name, ofs, TVAR_DOUBLE ) );
  172. }
  173.  
  174. void ScriptTemplate::AddObjectRefArray( const char*     name,
  175.                                         int                ofsRefToFirstObj,
  176.                                         int                ofsObjSizeInt,
  177.                                         int                ofsObjRefTempl
  178.                                       )
  179. {
  180.     TArrayInfo* pInfo = new TArrayInfo( name );
  181.  
  182.     mVars.push_back( pInfo );
  183.  
  184.     pInfo->mRefOfs         = ofsRefToFirstObj;
  185.     pInfo->mSizeIntOfs     = ofsObjSizeInt;
  186.     pInfo->mObjRefTemplOfs = ofsObjRefTempl;
  187. }
  188.  
  189. inline void ScriptTemplate::PrintVar( TVarInfo*   pInfo, 
  190.                                     void*       dataObj, 
  191.                                     ScriptStream& stm )
  192. {
  193.     char buf[128];
  194.  
  195.     switch ( pInfo->mType )
  196.     {
  197.         case TVAR_INTEGER :
  198.             {
  199.                 sprintf(buf, "%d",*( (int*) ((char*)dataObj + pInfo->mOfs) ) );
  200.                 
  201.                 stm.WriteBytes( buf, strlen(buf ) );
  202.                 break;
  203.             }
  204.  
  205.         case TVAR_STRING :
  206.             {
  207.                 string& str = *( (string*) ((char*)dataObj+pInfo->mOfs) );
  208.  
  209.                 const char* cs = str.c_str();
  210. #ifdef DEBUG_WEIRED_OFFSETS
  211.                 cout << "DBG:: cs address is " << (int)cs << endl;
  212.                 cout << "DBG:: str address is " << (int)(&str) << endl;
  213.                 cout << "DBG:: dataObj points to " << (int)dataObj << endl;
  214.                 cout << "DBG:: pInfo->mOfs value is " << (int)pInfo->mOfs << endl;
  215.                 cout << "DBG:: d+pInfo->mOfs is " << (int)((char*)dataObj + pInfo->mOfs) << endl;
  216.                 cout << "DBG:: pInfo->mName is " << pInfo->mName << endl;
  217.                 cout << "DBG:: pInfo->mType is " << pInfo->mType << endl;
  218.                 cout << "DBG:: end of dump. " << endl;
  219.  
  220.                 cout << "DBG:: cs value is " << endl << cs << endl;
  221. #endif
  222.                 stm.WriteBytes( cs, strlen(cs) );
  223.                 break;
  224.             }
  225.  
  226.         case TVAR_DOUBLE :
  227.             {
  228.                 sprintf( buf, "%f", 
  229.                          *( (double*)( (char*)dataObj+pInfo->mOfs)  ) );
  230.  
  231.                 stm.WriteBytes( buf, strlen(buf ) );
  232.                 break;
  233.             }
  234.  
  235.         case TVAR_REF_ARRAY :
  236.             {
  237.                 TArrayInfo& info = *((TArrayInfo*)pInfo);
  238.  
  239.                 int sz = *((int*) ( (char*)dataObj+info.mSizeIntOfs ));
  240.                 if ( !sz ) 
  241.                 {
  242.                     // DBG::
  243.                     int u = 0;
  244.                     ++u;
  245.                     break;
  246.                 }
  247.  
  248.                 int*   array = *((int**)( (char*)dataObj+info.mRefOfs ));
  249.     
  250.                 ScriptTemplate* pRefTempl;
  251.  
  252.                 for( int i = 0; i != sz; ++i )
  253.                 {
  254.                     pRefTempl = 
  255.                         *((ScriptTemplate**)((char*)(array[i])+info.mObjRefTemplOfs));
  256.  
  257.                     pRefTempl->PrintScript( (void*)array[i], stm );
  258.                 }
  259.  
  260.                 break;
  261.             }
  262.  
  263.         default : break;
  264.     }
  265. }
  266.  
  267. void ScriptTemplate::PrintScript( void* dataObj, ScriptStream& stm )
  268. {
  269.     char* cur   = mTText;
  270.  
  271.     // template parsing loop
  272.     do
  273.     {
  274.         char* start = cur;
  275.  
  276.         while( *cur != '\0' && *cur != '$' ) ++cur;
  277.  
  278.         // flush text collected between variables
  279.         stm.WriteBytes( start, cur - start );
  280.  
  281.         if ( *cur == '\0' ) break;
  282.  
  283.         cur += 2; // skip to the name of the var
  284.  
  285.         start = cur;
  286.  
  287.         while( *cur != ')' ) ++cur;
  288.  
  289.         // put terminating zero temorarely
  290.  
  291.         *cur = '\0';
  292.  
  293.         // look up variable
  294.  
  295.         size_t sz = mVars.size();
  296.         bool found = 0;
  297.  
  298.         for( size_t i = 0; i != sz; ++i ) 
  299.         {
  300.             if ( strcmp( mVars[i]->mName, start ) == 0 )
  301.             {
  302.                 PrintVar( mVars[i], dataObj, stm );
  303.  
  304.                 *cur = ')';    // remove terminating zero
  305.                 ++cur;
  306.                 found = 1;
  307.                 break;
  308.             }
  309.         }
  310.  
  311.         // variable referred by template script is not
  312.         // registered to this tempalte object
  313.         // ASSERT( found ); 
  314.  
  315.     } while(1);
  316. }
  317.  
  318. /***** implementation for class ScriptSection *****/
  319.  
  320. int ScriptSection::mIdCounter = 0;
  321.  
  322. ScriptSection::ScriptSection( const string&   name,
  323.                               const string&   body,
  324.                               ScriptTemplate* pSectionTemplate,
  325.                               ScriptTemplate* pReferenceTemplate,
  326.                               bool            autoHide,
  327.                               bool            sorted
  328.                             )
  329.     : mpParent ( NULL ),
  330.  
  331.       mName    ( name ),
  332.       mBody    ( body ),
  333.  
  334.       mAutoHide( autoHide ),
  335.       mSortOn  ( sorted ),
  336.  
  337.       mpSectTempl( pSectionTemplate ),
  338.       mpRefTempl ( pReferenceTemplate ),
  339.  
  340.       mRefCount( 0 ),
  341.       mArrSize( 0 )
  342. {
  343.     // generate GUID
  344.  
  345.     char buf[32];
  346.     sprintf( buf, "%d", ++mIdCounter );
  347.     mId = buf;
  348. }
  349.  
  350. ScriptSection::~ScriptSection()
  351. {
  352.     SectListT lst = mSubsections;
  353.  
  354.     while( mSubsections.size() )
  355.  
  356.         mSubsections[0]->RemoveRef();
  357.  
  358.     for( size_t i = 0; i != mReferences.size(); ++i )
  359.  
  360.         mReferences[i]->RemoveRef();
  361. }
  362.  
  363. void ScriptSection::AddRef()
  364. {
  365.     ++mRefCount;
  366. }
  367.  
  368. void ScriptSection::RemoveRef()
  369. {
  370.     if ( !mRefCount || !(--mRefCount) )
  371.     {
  372.         if (mpParent)
  373.         {
  374.             // remove ourselves from parent's list
  375.  
  376.             SectListT& lst = mpParent->mSubsections;
  377.             for( size_t i = 0; i != lst.size(); ++i )
  378.  
  379.                 if ( lst[i] == this )
  380.                 {
  381.                     lst.erase( &lst[i] );
  382.                     break;
  383.                 }
  384.         }
  385.  
  386.         delete this;
  387.     }
  388. }
  389.  
  390. ScriptSection* ScriptSection::GetSubsection( const char* name )
  391. {
  392.     // FOR NOW:: fixed section name length
  393.     char buf[128];
  394.  
  395.     size_t cur = 0;
  396.  
  397.     while( name[cur] && name[cur] != '/' )
  398.     {
  399.         buf[cur] = name[cur];
  400.         ++cur;
  401.     }
  402.  
  403.     // ASSERT( cur < sizeof(buf) );
  404.  
  405.     buf[cur] = '\0';
  406.  
  407.     size_t sz = mSubsections.size();
  408.  
  409.     for( size_t i = 0; i != sz; ++i )
  410.     {
  411.         // DBG::
  412.         //ScriptSection& sect = *mSubsections[i];
  413.  
  414.         if ( mSubsections[i]->mName == buf )
  415.         {
  416.             if ( name[cur] == '/' )
  417.  
  418.                 // search recursivelly
  419.                 return mSubsections[i]->GetSubsection( &name[cur+1] );
  420.             else
  421.                 return mSubsections[i];
  422.         }
  423.     }
  424.  
  425.     return 0;
  426. }
  427.  
  428. void ScriptSection::AddSection( ScriptSection* pSection,
  429.                                 bool addToReferencesToo
  430.                               )
  431. {
  432.     mSubsections.push_back( pSection );
  433.  
  434.     pSection->AddRef();
  435.  
  436.     // can add section to multiple containers
  437.     // ASSERT( pSection->mpParent == 0 );
  438.  
  439.     pSection->mpParent = this;
  440.  
  441.     if ( addToReferencesToo )
  442.  
  443.         AddReference( pSection );
  444. }
  445.  
  446. void ScriptSection::AddReference( ScriptSection* pReferredSection )
  447. {
  448.     mReferences.push_back( pReferredSection );
  449.  
  450.     pReferredSection->AddRef();
  451.  
  452.     // set up mandatory fields used by ScriptTemplate
  453.     mArrSize  = mReferences.size();
  454.     if ( mArrSize )
  455.         mRefFirst = (void*)&mReferences[0];
  456. }
  457.  
  458. SectListT& ScriptSection::GetSubsections()
  459. {
  460.     return mSubsections;
  461. }
  462.  
  463. // static method:
  464. void ScriptSection::RegisterTemplate( ScriptTemplate& sectionTempalte )
  465. {
  466.     int nameOfs, bodyOfs, idOfs,
  467.         arrRefOfs, arrSizeOfs, refTemplOfs;
  468.  
  469.     // obtaining offsets of member vars
  470.     
  471.     GET_VAR_OFS( ScriptSection, mName,     &nameOfs    )
  472.     GET_VAR_OFS( ScriptSection, mBody,     &bodyOfs    )
  473.     GET_VAR_OFS( ScriptSection, mId,       &idOfs      )
  474.     GET_VAR_OFS( ScriptSection, mRefFirst, &arrRefOfs  )
  475.     GET_VAR_OFS( ScriptSection, mArrSize,  &arrSizeOfs )
  476.  
  477.     GET_VAR_OFS( ScriptSection, mpRefTempl, &refTemplOfs )
  478.  
  479.     // registering member variables with given script template
  480.  
  481.     sectionTempalte.AddStringVar( "NAME", nameOfs );
  482.     sectionTempalte.AddStringVar( "BODY", bodyOfs );
  483.     sectionTempalte.AddStringVar( "ID",   idOfs   );
  484.  
  485.     sectionTempalte.AddObjectRefArray( "REFLIST",
  486.                                        arrRefOfs, arrSizeOfs, refTemplOfs );
  487. }
  488.  
  489. void ScriptSection::Print( ScriptStream& stm )
  490. {
  491.     // TBD:: sorting
  492.  
  493.     // print out this content first
  494.     if ( mpSectTempl )
  495.  
  496.         mpSectTempl->PrintScript( this, stm );
  497.  
  498.     // attach contents subsections at the end of this content
  499.  
  500.     for( size_t i = 0; i != mSubsections.size(); ++i )
  501.  
  502.         mSubsections[i]->Print( stm );
  503. }
  504.  
  505. void ScriptSection::DoRemoveEmptySections(int& nRemoved, SectListT& removedLst)
  506. {
  507.     for( size_t i = 0; i != mSubsections.size(); ++i )
  508.     {
  509.         ScriptSection& sect = *mSubsections[i];
  510.  
  511.         sect.DoRemoveEmptySections( nRemoved, removedLst );
  512.  
  513.         if (sect.mAutoHide )
  514.             
  515.             if ( sect.mReferences.size() == 0 )
  516.             {
  517.                 bool found = 0;
  518.                 for( size_t k = 0; k != removedLst.size(); ++k )
  519.  
  520.                     if ( removedLst[k] == § )
  521.                     {
  522.                         found = 1;
  523.                         break;
  524.                     }
  525.                 
  526.                 if ( !found )
  527.                 {
  528.                     removedLst.push_back( § );
  529.                     ++nRemoved;
  530.  
  531.                     delete §
  532.                     --i;
  533.                 }
  534.             }
  535.     }
  536. }
  537.  
  538. void ScriptSection::DoRemoveDeadLinks( SectListT& removedLst)
  539. {
  540.     size_t dsz = removedLst.size();
  541.  
  542.     for( size_t i = 0; i != mSubsections.size(); ++i )
  543.     {
  544.         mSubsections[i]->DoRemoveDeadLinks( removedLst );
  545.     }
  546.  
  547.     for( size_t n = 0; n != mReferences.size(); ++n )
  548.     {
  549.         for( size_t k = 0; k != dsz; ++k )
  550.  
  551.             if ( removedLst[k] == mReferences[n] )
  552.             {
  553.                 mReferences.erase( &mReferences[n] );
  554.                 --n;
  555.  
  556.                 // set up mandatory fields used by ScriptTemplate
  557.                 mArrSize  = mReferences.size();
  558.                 if ( mArrSize )
  559.                     mRefFirst = (void*)&mReferences[0];
  560.  
  561.                 break;
  562.             }
  563.     }
  564. }
  565.  
  566.  
  567. void ScriptSection::RemoveEmptySections()
  568. {
  569.     // FIXME:: this is very_very_very slow alg.! +"doesn't work"
  570.  
  571.     int nRemoved = 0;
  572.  
  573.     do
  574.     {
  575.         SectListT removedLst;
  576.         nRemoved = 0;
  577.  
  578.         DoRemoveEmptySections( nRemoved, removedLst );
  579.  
  580.         DoRemoveDeadLinks( removedLst );
  581.     }
  582.     while( nRemoved );
  583. }
  584.  
  585. /***** Iimplementation for class DocGeneratorBase *****/
  586.  
  587. bool DocGeneratorBase::SaveDocument( const char*    fname, 
  588.                                      const char*    fopenOptions,
  589.                                      ScriptSection* pFromSection
  590.                                    )
  591. {
  592.     FILE* fp = fopen( fname, fopenOptions );
  593.  
  594.     if ( (int)fp == -1 ) return 0;
  595.  
  596.     ScriptStream stm;
  597.  
  598.     // check if derived class agrees about saving it
  599.     if ( !OnSaveDocument( stm ) ) return 0;
  600.  
  601.     if ( pFromSection )
  602.  
  603.         pFromSection->Print( stm );
  604.     else
  605.     {
  606.         ScriptSection* pTopSect = GetTopSection();
  607.         // ASSERT( pTopSect );
  608.         pTopSect->Print( stm );
  609.     }
  610.  
  611.     size_t nWrite = fwrite( stm.GetBuf(), 1, stm.GetBufSize(), fp );
  612.  
  613.     if ( nWrite != stm.GetBufSize() ) return 0;
  614.  
  615.     fclose( fp );
  616.  
  617.     return 1;
  618.  
  619.     // that^s it
  620. }
  621.