Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

# Tools/Xabsl2/yabsl/vsyabsl/stdservice_.cpp

Go to the documentation of this file.

    00001
    00002 /***************************************************************************
    00003          Copyright (c) Microsoft Corporation, All rights reserved.
    00004     This code sample is provided "AS IS" without warranty of any kind,
    00005     it is not recommended for use in a production environment.
    00006 ***************************************************************************/
    00007
    00008 #include "common.h"
    00009 #include "languagedef.h"
    00010 #include "stdservice.h"
    00011 #include "dllmain.h"
    00012 #include <tchar.h>
    00013
    00014
    00015 #define CHECK(r)       ((r) == ReasonCheck)
    00016 #define SELECT(r)      ((r) >= ReasonMemberSelect && (r) <= ReasonMethodTip)
    00017 #define METHODTIP(r)   ((r) == ReasonMethodTip || (r) == ReasonQuickInfo)
    00018 #define MATCHBRACES(r) ((r) == ReasonHighlightBraces || (r) == ReasonMatchBraces)
    00019 #define AUTOS(r)       ((r) == ReasonAutos)
    00020 #define CODESPAN(r)    ((r) == ReasonCodeSpan)
    00021 #define DOUBLE_BYTE_BUF_SIZE 10
    00022
    00023 //---------------------------------------------------------
    00024 //
    00025 //---------------------------------------------------------
    00026 int yywrap()
    00027 {
    00028     return 1;
    00029 }
    00030
    00031 void yyerror( const char* message )
    00032 {
    00033     return;
    00034 }
    00035
    00036
    00037 global Service*    g_service    = NULL;
    00038
    00039
    00040 /*---------------------------------------------------------
    00041   BSTR
    00042 ---------------------------------------------------------*/
    00043 BSTR BstrNew( const char* s )
    00044 {
    00045 static OLECHAR buffer[MaxStr+1];
    00046   if (s == NULL) return NULL;
    00047
    00048   mbstowcs( buffer, s, MaxStr ); buffer[MaxStr] = 0;
    00049   return SysAllocString( buffer );
    00050 }
    00051
    00052 BSTR BstrNewFormat( const char* s )
    00053 {
    00054   if (s == NULL) return SysAllocString( L"" );
    00055   if (s[0] == 0) return SysAllocString( L"" );
    00056   return BstrNew(s);
    00057 }
    00058
    00059 /*---------------------------------------------------------
    00060   ColorizerState
    00061 ---------------------------------------------------------*/
    00062 LexBuffer::LexBuffer( int size ) : cstate(0)
    00063 {
    00064   yy_buffer = yy_create_buffer( NULL, size );
    00065   prevBuffer= NULL;
    00066   input     = NULL;
    00067   inputStart= NULL;
    00068   inputLim  = NULL;
    00069
    00070   sink      = NULL;
    00071   reason    = ReasonColorize;
    00072   token     = NULL;
    00073   location.initialize();
    00074
    00075   yylloc.initialize();
    00076   yylval.initialize();
    00077   service   = NULL;
    00078 }
    00079
    00080 LexBuffer::~LexBuffer()
    00081 {
    00082   yy_delete_buffer( yy_buffer );
    00083   RELEASE(sink);
    00084 }
    00085
    00086 //---------------------------------------------------------
    00087 //  ColorizerState
    00088 //---------------------------------------------------------
    00089 const Bits MaxBitsValid   = sizeof(int) * 8;
    00090
    00091 ColorizerState::ColorizerState()
    00092 {
    00093     m_bitsValid = 0;
    00094     m_state     = 0;
    00095 }
    00096
    00097 ColorizerState::ColorizerState( in State state )
    00098 {
    00099     reset(state);
    00100 }
    00101
    00102 void ColorizerState::reset( in State state )
    00103 {
    00104     m_bitsValid = MaxBitsValid;
    00105     m_state     = state;
    00106 }
    00107
    00108 State ColorizerState::getState()
    00109 {
    00110     return m_state;
    00111 }
    00112
    00113 State ColorizerState::load( in Bits bits )
    00114 {
    00115     ASSERT( bits <= m_bitsValid );
    00116
    00117     State mask    = (1 << bits) - 1;
    00118     State result  = m_state & mask;
    00119     m_state     >>= bits;
    00120     m_bitsValid  -= bits;
    00121     return result;
    00122 }
    00123
    00124 void ColorizerState::save( in State state, in Bits bits )
    00125 {
    00126     ASSERT( bits + m_bitsValid <= MaxBitsValid );
    00127
    00128     State mask    = (1 << bits) - 1;
    00129     ASSERT( state <= mask );
    00130
    00131     m_state     <<= bits;
    00132     m_state      |= state;
    00133     m_bitsValid  += bits;
    00134 };
    00135
    00136
    00137 //---------------------------------------------------------
    00138 //  Location
    00139 //---------------------------------------------------------
    00140 local inline void updatePosition( in char c,
    00141                                   inout int& row,
    00142                                   inout int& idx   )
    00143 {
    00144     if (c == '\n')
    00145     {
    00146       idx = 0;
    00147       row += 1;
    00148     }
    00149     else //if (c != '\r')
    00150     {
    00151       idx += 1;
    00152     }
    00153 }
    00154
    00155 Location::Location()
    00156 {
    00157     initialize();
    00158 }
    00159
    00160 Location::Location( in const Location& loc1, const Location& loc2 )
    00161 {
    00162     startRow = loc1.startRow;
    00163     startIdx = loc1.startIdx;
    00164     endRow   = loc2.endRow;
    00165     endIdx   = loc2.endIdx;
    00166     text     = loc1.text;
    00167     textOfs  = loc1.textOfs;
    00168     textLen  = (loc2.textOfs - loc1.textOfs) + loc2.textLen;
    00169     token    = 0;
    00170 }
    00171
    00172 final void Location::initialize(void)
    00173 {
    00174     startRow = endRow = 0;
    00175     startIdx = endIdx = 0;
    00176     text     = NULL;
    00177     textLen  = 0;
    00178     textOfs  = 0;
    00179     token    = 0;
    00180 }
    00181
    00182 final void Location::update( in int _token,
    00183                              in const char* _text,
    00184                              in int _textLen )
    00185 {
    00186
    00187     textOfs += textLen;
    00188     startRow = endRow;
    00189     startIdx = endIdx;
    00190
    00191     token    = _token;
    00192     text     = _text;
    00193     textLen  = _textLen;
    00194
    00195     for (int i = 0; i < textLen; i++)
    00196     {
    00197         updatePosition( text[i], endRow, endIdx );
    00198     };
    00199 }
    00200
    00201 //---------------------------------------------------------
    00202 //  IBabelService: Init/Done
    00203 //---------------------------------------------------------
    00204 STDMETHODIMP  StdService::Init( in LCID lcid, in long reserved )
    00205 {
    00206   return S_OK;
    00207 }
    00208
    00209 STDMETHODIMP  StdService::Done()
    00210 {
    00211   return S_OK;
    00212 }
    00213
    00214 int endsWith(const char* s1, const char* s2)
    00215 {
    00216   int l1 = strlen(s1);
    00217   int l2 = strlen(s2);
    00218
    00219   if(l2 == 0)
    00220     return 1;
    00221
    00222   if(l1 < l2)
    00223     return 0;
    00224
    00225   return strncmp(s1 + l1 - l2 , s2, l2) == 0;
    00226 }
    00227
    00228
    00229 //---------------------------------------------------------
    00230 //  IBabelService: ParseSource
    00231 //---------------------------------------------------------
    00232 STDMETHODIMP  StdService::ParseSource( in BSTR source,
    00233                                        in IParseSink* sink,
    00234                                        in ParseReason reason,
    00235                                        in long reserved,
    00236                                        out IScope** scope )
    00237 {
    00238     TRACE("StdService::ParseSource");
    00239     enterParser();
    00240     {
    00241       switchBuffer( m_parserBuffer, 0, (source ? SysStringLen(source) : 0), source, sink, reason );
    00242       if (scope) *scope = NULL;
    00243
    00244     char filePath[1024];
    00245
    00246     getFileName(filePath, 1024);
    00247     if(endsWith(filePath, "yabsl.api"))
    00248     {
    00249     yyparse();
    00250     }
    00251     else
    00252     {
    00253     IScope* scope = NULL;
    00254
    00255
    00256
    00257     char temp[1024];
    00258     char apiFilename[1024];
    00259
    00260     DWORD dwBufLen = 1024;
    00261     HKEY hKey;
    00262     LONG lRet;
    00263
    00264     RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\VisualStudio\\7.1"), 0, KEY_QUERY_VALUE, &hKey);
    00265         lRet = RegQueryValueEx(hKey, TEXT("InstallDir"), NULL, NULL, (LPBYTE)temp, &dwBufLen);
    00266
    00267     CharToOem((LPCTSTR)temp, (LPSTR)apiFilename);
    00268     strcat(apiFilename, "yabsl.api");
    00269 /*
    00270     FILE *file;
    00271     file = fopen("C:\\log.txt", "wb");
    00272     fwrite(apiFilename, 1024, 1, file);
    00273     fclose(file);
    00274 */
    00275
    00276     //loadScope does IParseSink::GetPackage and IBabelPackage::LoadScope.
    00277     loadScope( apiFilename, &scope );
    00278
    00279     if (scope != NULL && m_buffer->sink != NULL && CHECK(m_buffer->reason)) {
    00280
    00281       enterSink();
    00282       {
    00283         m_buffer->sink->AddExtern( 1, 0, 1, 0, scope );
    00284       }
    00285       leaveSink();
    00286       scope->Release();
    00287     }
    00288
    00289     }
    00290
    00291 //      if (yyparse() != 0)
    00292 //    errorMessage( SevFatal, "sorry, parsing could not recover" );
    00293
    00294       doneBuffer();
    00295     }
    00296     leaveParser();
    00297
    00298     return S_OK;
    00299 }
    00300
    00301
    00302 //---------------------------------------------------------
    00303 //  IBabelService: ColorLine
    00304 //---------------------------------------------------------
    00305 STDMETHODIMP  StdService::ColorLine( in BSTR line,
    00306                                      in IColorSink* sink,
    00307                                      inout long* state )
    00308 {
    00309     //TRACE("StdService::ColorLine");
    00310     if (!state) return E_POINTER;
    00311
    00312     enterLexer();
    00313     {
    00314 //      if (g_service) { TRACE("entering colorizer while parsing"); }
    00315       switchBuffer( m_lexerBuffer, *state, (line ? SysStringLen(line) : 0), line, NULL, ReasonColorize );
    00316
    00317       if (line)
    00318       {
    00319         int   pos = 0;
    00320         Token token;
    00321
    00322         while ( (token = nextToken()) != 0)
    00323         {
    00324           if (sink)
    00325           {
    00326             const TokenInfo* tokenInfo  = lookupTokenInfo(token);
    00327
    00328             sink->Colorize( pos, pos + yyleng - 1
    00329                           , tokenInfo->colorClass
    00330                           , tokenInfo->charClass
    00331                           , tokenInfo->trigger );
    00332             pos += yyleng;
    00333           }
    00334         }
    00335       }
    00336
    00337       *state = doneBuffer();
    00338
    00339 //      if (g_service) { TRACE("leaving colorizer while parsing"); }
    00340     }
    00341     leaveLexer();
    00342
    00343     return S_OK;
    00344 };
    00345
    00346 //---------------------------------------------------------
    00347 //  NextToken
    00348 //---------------------------------------------------------
    00349 bool    StdService::isParserToken( in const TokenInfo& info) const
    00350 {
    00351   return (  info.charClass != CharWhiteSpace
    00352          && info.charClass != CharLineComment
    00353          && info.charClass != CharComment );
    00354 }
    00355
    00356 Token   StdService::parserNextToken(void)
    00357 {
    00358     Token            token;
    00359     const TokenInfo* info;
    00360
    00361     enterLexer();
    00362     {
    00363
    00364       do {
    00365           token  = nextToken();
    00366           info   = lookupTokenInfo( token );
    00367       }
    00368       while ( !isParserToken(*info) );
    00369       yylloc  = m_buffer->location;
    00370       yylval  = m_buffer->location;
    00371     }
    00372     leaveLexer();
    00373
    00374     return token;
    00375 };
    00376
    00377
    00378 Token   StdService::nextToken(void)
    00379 {
    00380   m_buffer->token = yylex();
    00381   m_buffer->location.update( m_buffer->token, yytext, yyleng );
    00382   return m_buffer->token;
    00383 };
    00384
    00385
    00386 //---------------------------------------------------------
    00387 //  IBabelService: ColorCount && GetColorInfo
    00388 //---------------------------------------------------------
    00389
    00390 STDMETHODIMP StdService::ColorCount( out ColorClass* count)
    00391 {
    00392     TRACE("StdService::ColorCount");
    00393     if (!count)  return E_POINTER;
    00394             else *count = 0;
    00395
    00396     const ColorInfo* info    = getColorInfo();
    00397     ColorClass       counter = 0;
    00398
    00399     ASSERT(info);
    00400     if (info)
    00401     {
    00402         while (info->colorClass != ColorClassEnd) { info++; counter++; }
    00403     };
    00404
    00405     *count = counter;
    00406     return S_OK;
    00407 };
    00408
    00409
    00410 STDMETHODIMP  StdService::GetColorInfo( in ColorClass index,
    00411                                         out BSTR* description,
    00412                                         out BSTR* style )
    00413 {
    00414     TRACE("StdService::GetColorInfo");
    00415     OLECHAR buffer[MaxStr+1];
    00416
    00417     const ColorInfo* info = lookupColorInfo( index );
    00418     if (info->colorClass != index) return E_INVALIDARG;
    00419
    00420     HRESULT hr = S_OK;
    00421     if (description)
    00422     {
    00423         if (info->description == NULL)
    00424         {
    00425             hr = E_FAIL;
    00426             goto Error;
    00427         }
    00428         mbstowcs( buffer, info->description, MaxStr ); buffer[MaxStr] = 0;
    00429         *description = SysAllocString( buffer );
    00430         if ((*description) == NULL)
    00431         {
    00432             hr = E_OUTOFMEMORY;
    00433             goto Error;
    00434         }
    00435     }
    00436
    00437     if (style)
    00438     {
    00439         if (info->style == NULL)
    00440         {
    00441             hr = E_FAIL;
    00442             goto Error;
    00443         }
    00444         mbstowcs( buffer, info->style, MaxStr ); buffer[MaxStr] = 0;
    00445         *style = SysAllocString( buffer );
    00446         if ((*style) == NULL)
    00447         {
    00448             hr = E_OUTOFMEMORY;
    00449             goto Error;
    00450         }
    00451     }
    00452 Error:
    00453     if (FAILED(hr))
    00454     {
    00455         if (description)
    00456             bstrFree(*description);
    00457         if (style)
    00458             bstrFree(*style);
    00459     }
    00460     return hr;
    00461 };
    00462
    00463
    00464 //---------------------------------------------------------
    00465 //  Token info
    00466 //---------------------------------------------------------
    00467 static TokenInfo defaultTokenInfo = { TokenEnd, ClassDefault, "<unknown>", CharDefault };
    00468
    00469 final const char* StdService::getTokenDescription( in Token token ) const
    00470 {
    00471     static char buffer[MaxErrorMessage];
    00472
    00473     const TokenInfo* info = lookupTokenInfo( token );
    00474     ASSERT(info);
    00475
    00476     if (info && info->token == token) //found a fit description
    00477     {
    00478       const char* text  = (m_buffer->location.text == NULL) ? "<unknown>" : m_buffer->location.text;
    00479       if (info->description != NULL)
    00480       {
    00481         _snprintf( buffer, MaxErrorMessage-1, info->description, text );
    00482         buffer[MaxErrorMessage-1] = 0;
    00483       }
    00484       else
    00485       {
    00486         buffer[0] = 0;
    00487       }
    00488       return buffer;
    00489     }
    00490     else
    00491     {
    00492       if (token == 0)   return "end-of-file";
    00493
    00494       if (token >= ' ')  sprintf( buffer, "token ('%c')", token );
    00495                     else sprintf( buffer, "token (0x%x)", token );
    00496       return buffer;
    00497     }
    00498 };
    00499
    00500
    00501 final const TokenInfo* StdService::lookupTokenInfo( Token token ) const
    00502 {
    00503     const TokenInfo* info  = getTokenInfo();
    00504     ASSERT(info);
    00505
    00506     if (info==NULL) info   = &defaultTokenInfo;
    00507     while (info->token != TokenEnd)       //walk through info in a linear fasion
    00508     {
    00509         if (info->token == token) break;
    00510         info++;
    00511     }
    00512
    00513     return info;
    00514 }
    00515
    00516
    00517 const TokenInfo* StdService::getTokenInfo(void) const
    00518 {
    00519     return &defaultTokenInfo;
    00520 }
    00521
    00522 //---------------------------------------------------------
    00523 //  Color info
    00524 //---------------------------------------------------------
    00525 local const ColorClass ColorMask = 0xFFFF;
    00526
    00527 final const ColorInfo* StdService::lookupColorInfo( in ColorClass colorClass ) const
    00528 {
    00529     static ColorInfo defaultColorInfo = { ColorClassEnd, "Text", "" };
    00530     const ColorInfo* info  = getColorInfo();
    00531
    00532     ASSERT(info);
    00533     if (info == NULL) info = &defaultColorInfo;
    00534
    00535     colorClass &= ColorMask;    //mask off attributes (ie. ClassHumanText)
    00536     while (info->colorClass != ColorClassEnd )
    00537     {
    00538         if (info->colorClass == colorClass) break;
    00539         info++;
    00540     }
    00541
    00542     ASSERT( info && info->colorClass != ColorClassEnd );
    00543     return info;
    00544 }
    00545
    00546 const ColorInfo* StdService::getColorInfo() const
    00547 {
    00548     static ColorInfo defaultColorInfoTable[] =
    00549     {
    00550  //       { ClassText,        "Text",     "" },
    00551         { ClassKeyword,     "Keyword",    "color: blue"  },
    00552         { ClassComment,     "Comment",    "color: darkgreen; text-kind: humantext" },
    00553         { ClassIdentifier,  "Identifier", "" },
    00554         { ClassString,      "String",     "color: purple" },
    00555         { ClassNumber,      "Number",     "" },
    00556         { ColorClassEnd,    "Text",       "" }
    00557     };
    00558
    00559     return defaultColorInfoTable;
    00560 }
    00561
    00562 //---------------------------------------------------------
    00563 //  Error messages
    00564 //---------------------------------------------------------
    00565
    00566 static char errorBuffer[MaxErrorMessage];
    00567
    00568
    00569 void StdService::fatalFlexError( in const char* message ) const
    00570 {
    00571   ASSERT(0);
    00572   lexicalError( SevFatal, message );
    00573 }
    00574
    00575 void StdService::lexicalError( in Severity sev,
    00576                                  in const char* message ) const
    00577 {
    00578     if (!CHECK(m_buffer->reason)) return;
    00579     if (!m_buffer->sink)          return;
    00580
    00581     Location location = m_buffer->location;
    00582     location.update( m_buffer->token, yytext, yyleng );
    00583     errorMessage( sev, message, &location );
    00584 };
    00585
    00586 void StdService::expectError( in const char* construct,
    00587                                 in const char* expecting,
    00588                                 in const Location* loc ) const
    00589 {
    00590     if (!CHECK(m_buffer->reason)) return;
    00591     _snprintf( errorBuffer, MaxErrorMessage-1,
    00592                 "Syntax error in %s; expecting \"%s\"", construct, expecting );
    00593     errorBuffer[MaxErrorMessage-1] = 0;
    00594     errorMessage( SevError, errorBuffer, loc );
    00595 }
    00596
    00597 void StdService::syntaxError( in const char* construct,
    00598                                 in const Location* loc   ) const
    00599 {
    00600     if (!CHECK(m_buffer->reason)) return;
    00601     const char* description = getTokenDescription( (yychar < 0 ? m_buffer->token : yychar ) );
    00602
    00603     _snprintf( errorBuffer, MaxErrorMessage-1,
    00604                 "Syntax error in %s  (unexpected %s)", construct, description );
    00605     errorBuffer[MaxErrorMessage-1] = 0;
    00606     errorMessage( SevError, errorBuffer, loc );
    00607 }
    00608
    00609 void StdService::errorMessage( in Severity sev,
    00610                                  in const char* message,
    00611                                  in const Location* loc  ) const
    00612 {
    00613     if (!CHECK(m_buffer->reason)) return;
    00614     if (!m_buffer->sink)          return;
    00615
    00616     if (loc == NULL) loc = &yylloc;
    00617
    00618     BSTR bstrMessage = BstrNew( message );
    00619     if (bstrMessage)
    00620     {
    00621       enterSink();
    00622       {
    00623         m_buffer->sink->ErrorMessage( loc->startRow, loc->endRow,
    00624                                       loc->startIdx, loc->endIdx,
    00625                                       sev, bstrMessage );
    00626         SysFreeString(bstrMessage);
    00627       }
    00628       leaveSink();
    00629     }
    00630 }
    00631
    00632 //---------------------------------------------------------
    00633 //  IBabelService::GetMethodFormat
    00634 //---------------------------------------------------------
    00635 STDMETHODIMP StdService::GetMethodFormat(out BSTR* parStart, out BSTR* parSep, out BSTR* parEnd,
    00636                                          out BSTR* typeStart, out BSTR* typeEnd,
    00637                                          out VARIANT_BOOL* typePrefixed )
    00638 {
    00639   const MethodFormat* methodFormat = getMethodFormat();
    00640   if (methodFormat)
    00641   {
    00642     if (parStart)     *parStart = BstrNewFormat(methodFormat->parStart);
    00643     if (parSep)       *parSep   = BstrNewFormat(methodFormat->parSep);
    00644     if (parEnd)       *parEnd   = BstrNewFormat(methodFormat->parEnd);
    00645     if (typeStart)    *typeStart= BstrNewFormat(methodFormat->typeStart);
    00646     if (typeEnd)      *typeEnd  = BstrNewFormat(methodFormat->typeEnd);
    00647     if (typePrefixed) *typePrefixed = methodFormat->typePrefixed;
    00648     return S_OK;
    00649   }
    00650   else
    00651     return E_NOTIMPL;
    00652 }
    00653
    00654 const MethodFormat* StdService::getMethodFormat() const
    00655 {
    00656   return NULL;
    00657 }
    00658
    00659 //---------------------------------------------------------
    00660 //  IBabelService::GetImageList
    00661 //---------------------------------------------------------
    00662 STDMETHODIMP StdService::GetImageList( out long* imageListHandle, out long* glyphCount )
    00663 {
    00664   OUTARG(imageListHandle);
    00665   OUTARG(glyphCount);
    00666
    00667   return E_NOTIMPL;
    00668 }
    00669
    00670
    00671 //---------------------------------------------------------
    00672 //  IBabelService::GetCommentFormat
    00673 //---------------------------------------------------------
    00674 STDMETHODIMP StdService::GetCommentFormat( out BSTR* lineStart,
    00675                                            out BSTR* blockStart, out BSTR* blockEnd,
    00676                                            out VARIANT_BOOL* useLineComments )
    00677 {
    00678   if (!lineStart) return E_INVALIDARG;
    00679   if (!blockStart) return E_INVALIDARG;
    00680   if (!blockEnd)  return E_INVALIDARG;
    00681   if (!useLineComments) return E_INVALIDARG;
    00682
    00683   const CommentFormat* commentFormat = getCommentFormat();
    00684   if (commentFormat)
    00685   {
    00686     *lineStart  = BstrNewFormat(commentFormat->lineStart);
    00687     *blockStart = BstrNewFormat(commentFormat->blockStart);
    00688     *blockEnd   = BstrNewFormat(commentFormat->blockEnd);
    00689     *useLineComments = commentFormat->useLineComments;
    00690     return S_OK;
    00691   }
    00692   else
    00693     return E_NOTIMPL;
    00694 }
    00695
    00696 const CommentFormat* StdService::getCommentFormat() const
    00697 {
    00698   return NULL;
    00699 }
    00700
    00701 //---------------------------------------------------------
    00702 //  Parenthesis
    00703 //---------------------------------------------------------
    00704 void StdService::matchPair( in const Location& loc1, in const Location& loc2 ) const
    00705 {
    00706   if (!m_buffer->sink) return;
    00707   if (!MATCHBRACES(m_buffer->reason)) return;
    00708
    00709   enterSink();
    00710   {
    00711     m_buffer->sink->MatchPair( loc1.startRow, loc1.startIdx, loc1.endRow, loc1.endIdx
    00712                              , loc2.startRow, loc2.startIdx, loc2.endRow, loc2.endIdx );
    00713   }
    00714   leaveSink();
    00715 }
    00716
    00717
    00718 void StdService::matchTriple( in const Location& loc1, in const Location& loc2, in const Location& loc3 ) const
    00719 {
    00720   if (!m_buffer->sink) return;
    00721   if (!MATCHBRACES(m_buffer->reason)) return;
    00722
    00723   enterSink();
    00724   {
    00725     m_buffer->sink->MatchTriple( loc1.startRow, loc1.startIdx, loc1.endRow, loc1.endIdx
    00726                                , loc2.startRow, loc2.startIdx, loc2.endRow, loc2.endIdx
    00727                                , loc3.startRow, loc3.startIdx, loc3.endRow, loc3.endIdx);
    00728   }
    00729   leaveSink();
    00730 }
    00731
    00732 //---------------------------------------------------------
    00733 //  Scope functions
    00734 //---------------------------------------------------------
    00735 final void StdService::addScope( in const Location& start, in const Location& end,
    00736                          in ScopeKind kind, in ScopeAccess access, in ScopeStorage storage,
    00737                          in const Location& name,
    00738                          in const Location& descStart, in const Location& descEnd,
    00739                          in const Location* type,
    00740                          in long glyph,
    00741                          in bool merge,
    00742                          in bool makeDescription /* = false */
    00743                         )
    00744 {
    00745   if (!m_buffer->sink) return;
    00746   if (!CHECK(m_buffer->reason)) return;
    00747
    00748   enterSink();
    00749   {
    00750      BSTR bstrName = tokenBstr(&name);
    00751      BSTR bstrType = type ? tokenBstr(type) : NULL;
    00752
    00753      BSTR bstrDescription = NULL;
    00754      if (makeDescription && bstrType)
    00755      {
    00756          OLECHAR buffer[MaxStr+5];
    00757          if (::SysStringLen(bstrType) + ::SysStringLen(bstrName) < MaxStr)
    00758          {
    00759             wcscpy(buffer, bstrType);
    00760             wcscat(buffer, L" ");
    00761             if (bstrName != NULL)
    00762                 wcscat(buffer, bstrName);
    00763             bstrDescription = ::SysAllocString(buffer);
    00764          }
    00765      }
    00766      else
    00767      {
    00768          bstrDescription = tokenBstr(&descStart,&descEnd);
    00769      }
    00770
    00771      m_buffer->sink->AddScope( start.startRow, start.startIdx, end.endRow, end.endIdx,
    00772                                kind, access, storage, glyph,
    00773                                bstrName, bstrType,
    00774                                bstrName, bstrDescription, merge );
    00775      // free the strings
    00776      bstrFree(bstrName);
    00777      bstrFree(bstrType);
    00778      bstrFree(bstrDescription);
    00779   }
    00780   leaveSink();
    00781 }
    00782
    00783 final void StdService::addScopeText( in const Location& start, in const Location& end,
    00784                          in ScopeKind kind, in ScopeAccess access, in ScopeStorage storage,
    00785                          in const char* name,
    00786                          in const char* description ,
    00787                          in const char* type    ,
    00788                          in const char* display ,
    00789                          in long glyph,
    00790                          in bool merge )
    00791 {
    00792   if (!m_buffer->sink) return;
    00793   if (!CHECK(m_buffer->reason)) return;
    00794
    00795   enterSink();
    00796   {
    00797     BSTR bstrName=BstrNew(name);
    00798     BSTR bstrType=BstrNew(type);
    00799     BSTR bstrDescription=BstrNew(description);
    00800     BSTR bstrDisplay=BstrNew(display);
    00801     m_buffer->sink->AddScope( start.startRow, start.startIdx, end.endRow, end.endIdx,
    00802                     kind, access, storage, glyph,
    00803                     bstrName, bstrType, bstrDisplay, bstrDescription,
    00804                     merge );
    00805     // free the strings
    00806     bstrFree(bstrName);
    00807     bstrFree(bstrType);
    00808     bstrFree(bstrDescription);
    00809     bstrFree(bstrDisplay);
    00810
    00811   }
    00812   leaveSink();
    00813 }
    00814
    00815 //---------------------------------------------------------
    00816 //  Scope functions
    00817 //---------------------------------------------------------
    00818 Location StdService::range( in const Location& loc1, in const Location& loc2 ) const
    00819 {
    00820   Location result(loc1,loc2);
    00821   return result;
    00822 }
    00823
    00824 const char* StdService::tokenText( in const Location* tokenStart
    00825                                  , in const Location* tokenEnd ) const
    00826 {
    00827    if (tokenStart == NULL) tokenStart = &m_buffer->location;
    00828    if (tokenEnd   == NULL) tokenEnd   = tokenStart;
    00829    {
    00830      static char buffer[MaxStr+1];
    00831      Location token( *tokenStart, *tokenEnd );
    00832      int len = MaxStr > token.textLen ? token.textLen : MaxStr;
    00833
    00834      wcstombs(buffer,m_buffer->inputStart + token.textOfs, len);
    00835      buffer[len] = 0;
    00836      return buffer;
    00837    }
    00838 }
    00839
    00840 BSTR StdService::tokenBstr( in const Location* tokenStart
    00841                           , in const Location* tokenEnd ) const
    00842 {
    00843    if (tokenStart == NULL) tokenStart = &m_buffer->location;
    00844    if (tokenEnd   == NULL) tokenEnd   = tokenStart;
    00845
    00846    Location token( *tokenStart, *tokenEnd );
    00847    int len = token.textLen;
    00848    return SysAllocStringLen( m_buffer->inputStart + token.textOfs, token.textLen );
    00849 }
    00850
    00851
    00852 final void StdService::addExtern( in const Location& start, in const Location& end,
    00853                                   in IScope* scope )
    00854 {
    00855   if (!m_buffer->sink) return;
    00856   if (!CHECK(m_buffer->reason)) return;
    00857
    00858   enterSink();
    00859   {
    00860     m_buffer->sink->AddExtern( start.startRow, start.startIdx, end.endRow, end.endIdx,
    00861                                scope );
    00862   }
    00863   leaveSink();
    00864 }
    00865
    00866 //---------------------------------------------------------
    00867 //  Context
    00868 //---------------------------------------------------------
    00869 void StdService::getProject( out IBabelProject** project )
    00870 {
    00871   if (project) *project = NULL;
    00872
    00873   if (!m_buffer->sink) return;
    00874   if (!CHECK(m_buffer->reason)) return;
    00875   if (!project) return;
    00876
    00877   HRESULT hr;
    00878   enterSink();
    00879   {
    00880     hr = m_buffer->sink->GetProject( project );
    00881   }
    00882   leaveSink();
    00883
    00884   if (FAILED(hr)) { *project = NULL; }
    00885   return;
    00886 }
    00887
    00888 void StdService::getPackage( out IBabelPackage** package )
    00889 {
    00890   if (package) *package = NULL;
    00891
    00892   if (!m_buffer->sink) return;
    00893   if (!CHECK(m_buffer->reason)) return;
    00894   if (!package) return;
    00895
    00896   HRESULT hr;
    00897   enterSink();
    00898   {
    00899     hr = m_buffer->sink->GetPackage( package );
    00900   }
    00901   leaveSink();
    00902
    00903   if (FAILED(hr)) { *package = NULL; }
    00904   return;
    00905 }
    00906
    00907 void StdService::getFileName( out char* filePath, in int nameLen )
    00908 {
    00909   if (filePath) filePath[0] = 0;
    00910
    00911   if (!m_buffer->sink) return;
    00912   if (!CHECK(m_buffer->reason)) return;
    00913   if (!filePath || nameLen <= 0) return;
    00914   HRESULT hr;
    00915
    00916   BSTR bstrFilePath = NULL;
    00917   enterSink();
    00918   {
    00919     hr = m_buffer->sink->GetFileName( &bstrFilePath );
    00920   }
    00921   leaveSink();
    00922
    00923   if (hr == S_OK && bstrFilePath)
    00924   {
    00925     wcstombs( filePath, bstrFilePath, nameLen );
    00926     SysFreeString(bstrFilePath);
    00927   }
    00928   return;
    00929 }
    00930
    00931
    00932 void StdService::searchFile( inout char* fileName, in int nameLen )
    00933 {
    00934   if (!fileName || nameLen <= 0) return;
    00935   IBabelProject* project = NULL;
    00936
    00937   getProject( &project );
    00938   if (!project) return;
    00939
    00940   BSTR bstrFileName = BstrNew(fileName);
    00941   if (!bstrFileName) { RELEASE(project); return; }
    00942
    00943   BSTR bstrFilePath = NULL;
    00944   HRESULT hr = project->SearchFile( bstrFileName, &bstrFilePath );
    00945   RELEASE(project);
    00946   SysFreeString(bstrFileName);
    00947   if (FAILED(hr)) return;
    00948
    00949   wcstombs(fileName,bstrFilePath,nameLen);
    00950   SysFreeString(bstrFilePath);
    00951   return;
    00952 }
    00953
    00954 void StdService::loadScope( in const char* fileName, out IScope** scope )
    00955 {
    00956   if (!scope) return;
    00957          else *scope = NULL;
    00958   if (!fileName) return;
    00959
    00960   IBabelPackage* package = NULL;
    00961   getPackage( &package );
    00962   if (!package) return;
    00963
    00964   IBabelProject* project = NULL;
    00965   getProject( &project );
    00966
    00967   BSTR bstrFileName = BstrNew(fileName);
    00968   if (!bstrFileName) { RELEASE(package); RELEASE(project); return; }
    00969
    00970   HRESULT hr = package->LoadScope( 0, bstrFileName, project, scope );
    00971   RELEASE(project);
    00972   RELEASE(package);
    00973   SysFreeString(bstrFileName);
    00974   if (FAILED(hr)) return;
    00975
    00976   return;
    00977 }
    00978
    00979 //---------------------------------------------------------
    00980 //  Member selection
    00981 //---------------------------------------------------------
    00982 void StdService::startName( in const Location& loc ) const
    00983 {
    00984   if (!SELECT(m_buffer->reason) && !AUTOS(m_buffer->reason)) return;
    00985   if (!m_buffer->sink) return;
    00986   enterSink();
    00987   {
    00988     m_buffer->sink->StartName( loc.endRow, loc.startIdx, loc.endIdx );
    00989   }
    00990   leaveSink();
    00991 }
    00992
    00993 void StdService::qualifyName( in const Location& locSelector, in const Location& loc) const
    00994 {
    00995   if (!SELECT(m_buffer->reason) && !AUTOS(m_buffer->reason)) return;
    00996   if (!m_buffer->sink) return;
    00997   enterSink();
    00998   {
    00999     m_buffer->sink->QualifyName( locSelector.endRow, locSelector.startIdx, locSelector.endIdx,
    01000                      loc.endRow, loc.startIdx, loc.endIdx );
    01001   }
    01002   leaveSink();
    01003 }
    01004
    01005
    01006 void StdService::autoExpression( in const Location& loc ) const
    01007 {
    01008   if (!AUTOS(m_buffer->reason)) return;
    01009   if (!m_buffer->sink) return;
    01010
    01011   enterSink();
    01012   {
    01013     m_buffer->sink->AutoExpression( loc.startRow, loc.startIdx, loc.endRow, loc.endIdx );
    01014   }
    01015   leaveSink();
    01016 }
    01017
    01018 void StdService::codeSpan( in const Location& start, in const Location& end ) const
    01019 {
    01020   if (!CODESPAN(m_buffer->reason)) return;
    01021   if (!m_buffer->sink) return;
    01022
    01023   enterSink();
    01024   {
    01025     m_buffer->sink->CodeSpan( start.startRow, start.startIdx, end.endRow, end.endIdx );
    01026   }
    01027   leaveSink();
    01028 }
    01029
    01030 //---------------------------------------------------------
    01031 //  Method info
    01032 //---------------------------------------------------------
    01033 void StdService::startParameters( in const Location& loc ) const
    01034 {
    01035   if (!m_buffer->sink) return;
    01036   if (!METHODTIP(m_buffer->reason)) return;
    01037   enterSink();
    01038   {
    01039     m_buffer->sink->StartParameters(loc.endRow,loc.endIdx);
    01040   }
    01041   leaveSink();
    01042 }
    01043
    01044 void StdService::parameter(in const Location& loc) const
    01045 {
    01046   if (!m_buffer->sink) return;
    01047   if (!METHODTIP(m_buffer->reason)) return;
    01048   enterSink();
    01049   {
    01050     m_buffer->sink->Parameter(loc.endRow,loc.endIdx);
    01051   }
    01052   leaveSink();
    01053 }
    01054
    01055 void StdService::endParameters(in const Location& loc) const
    01056 {
    01057   if (!m_buffer->sink) return;
    01058   if (!METHODTIP(m_buffer->reason)) return;
    01059   enterSink();
    01060   {
    01061     m_buffer->sink->EndParameters(loc.endRow,loc.endIdx);
    01062   }
    01063   leaveSink();
    01064 }
    01065
    01066
    01067 //---------------------------------------------------------
    01068 //  init/done
    01069 //---------------------------------------------------------
    01070
    01071 void StdService::initColorizerState( inout ColorizerState& cstate )
    01072 {
    01073     LexState lexstate = cstate.load( StateBits );
    01074     setLexState( lexstate );
    01075 }
    01076
    01077 void StdService::doneColorizerState( inout ColorizerState& cstate )
    01078 {
    01079     cstate.save( getLexState(), StateBits );
    01080 }
    01081
    01082 //---------------------------------------------------------
    01083 //  Construction & Destruction
    01084 //---------------------------------------------------------
    01085 StdService::StdService()
    01086 : m_lexerBuffer(1024), m_parserBuffer()
    01087 {
    01088   m_refCount = 1;
    01089
    01090   InitializeCriticalSection( &m_parserLock );
    01091   InitializeCriticalSection( &m_lexerLock  );
    01092
    01093   g_service  = (Service*)this;
    01094   m_buffer   = NULL;
    01095
    01096   ColorizerState cstate( 0 );
    01097   initColorizerState(cstate);
    01098 };
    01099
    01100 StdService::~StdService()
    01101 {
    01102   ASSERT(m_buffer == NULL);
    01103   g_service = NULL;
    01104   DeleteCriticalSection( &m_lexerLock );
    01105   DeleteCriticalSection( &m_parserLock );
    01106 }
    01107
    01108 final void StdService::enterParser()
    01109 {
    01110   EnterCriticalSection( &m_parserLock );
    01111 }
    01112
    01113 final void StdService::leaveParser()
    01114 {
    01115   LeaveCriticalSection( &m_parserLock );
    01116 }
    01117
    01118 final void StdService::enterLexer()
    01119 {
    01120   EnterCriticalSection( &m_lexerLock );
    01121 }
    01122
    01123 final void StdService::leaveLexer()
    01124 {
    01125   LeaveCriticalSection( &m_lexerLock );
    01126 }
    01127
    01128 //enter/leaveSink simply use the lexer lock
    01129 final void StdService::enterSink() const
    01130 {
    01131   EnterCriticalSection( const_cast<LPCRITICAL_SECTION>(&m_lexerLock) );
    01132 }
    01133
    01134 final void StdService::leaveSink() const
    01135 {
    01136   LeaveCriticalSection( const_cast<LPCRITICAL_SECTION>(&m_lexerLock) );
    01137 }
    01138
    01139 final void StdService::switchBuffer(
    01140                           in LexBuffer&       buffer,
    01141                           in State            state,
    01142                           in int              inputLen,
    01143                           in const InputChar* input,
    01144                           in IParseSink*      sink,
    01145                           in ParseReason      reason )
    01146 {
    01147   enterLexer();
    01148   {
    01149     ASSERT(buffer.prevBuffer == NULL);
    01150     ASSERT(buffer.input == NULL);
    01151
    01152     //save previous buffer
    01153     buffer.prevBuffer = m_buffer;
    01154     if (m_buffer)
    01155     {
    01156       TRACE("save buffer");
    01157       //save context
    01158       doneColorizerState( m_buffer->cstate );
    01159       m_buffer->yylloc  = yylloc;
    01160       m_buffer->yylval  = yylval;
    01161       m_buffer->service = g_service;
    01162     }
    01163
    01164     buffer.cstate.reset( state );
    01165     buffer.location.initialize();
    01166     buffer.token      = 0;
    01167     buffer.sink       = sink;
    01168     if (buffer.sink) buffer.sink->AddRef();
    01169     buffer.reason     = reason;
    01170     buffer.input      = input;
    01171     buffer.inputStart = input;
    01172     buffer.inputLim   = input + inputLen;
    01173     yy_flush_buffer( buffer.yy_buffer );
    01174
    01175     //set new buffer
    01176     m_buffer = &buffer;
    01177
    01178     //and switch
    01179     yy_switch_to_buffer( buffer.yy_buffer );
    01180     initColorizerState( buffer.cstate );
    01181   }
    01182   leaveLexer();
    01183   return;
    01184 }
    01185
    01186 final State StdService::doneBuffer()
    01187 {
    01188   State state = 0;
    01189   enterLexer();
    01190   {
    01191     ASSERT(m_buffer);
    01192
    01193     doneColorizerState( m_buffer->cstate );
    01194     state = m_buffer->cstate.getState();
    01195
    01196     yy_flush_buffer( m_buffer->yy_buffer );
    01197     m_buffer->inputLim  = NULL;
    01198     m_buffer->input     = NULL;
    01199     m_buffer->inputStart= NULL;
    01200     RELEASE(m_buffer->sink);
    01201     m_buffer->token     = 0;
    01202     m_buffer->location.initialize();
    01203
    01204     if (m_buffer->prevBuffer)
    01205     {
    01206       TRACE("restore buffer");
    01207       LexBuffer* prev = m_buffer->prevBuffer;
    01208       m_buffer->prevBuffer = NULL;
    01209
    01210       //restore previous buffer
    01211       m_buffer  = prev;
    01212
    01213       yylloc    = m_buffer->yylloc;
    01214       yylval    = m_buffer->yylval;
    01215       g_service = m_buffer->service;
    01216
    01217       yy_switch_to_buffer( m_buffer->yy_buffer );
    01218       initColorizerState( m_buffer->cstate );
    01219     }
    01220     else
    01221     {
    01222       m_buffer = NULL;
    01223     }
    01224   }
    01225   leaveLexer();
    01226   return state;
    01227 }
    01228
    01229 /*
    01230 final void StdService::internInit( in State state,
    01231                                    in int inputLen,
    01232                                    in const InputChar* input,
    01233                                    in IParseSink* sink )
    01234 {
    01235   enter();
    01236   {
    01237     g_service    = (Service*)this;
    01238
    01239     m_buffer->location.initialize();
    01240     m_buffer->token      = 0;
    01241     m_buffer->input      = input;
    01242     m_buffer->inputStart = input;
    01243     m_buffer->inputLim   = input + inputLen;
    01244     m_buffer->reason     = ReasonMatchingPair;
    01245     m_buffer->sink       = sink;
    01246     if (m_buffer->sink) m_buffer->sink->AddRef();
    01247
    01248     ColorizerState cstate( state );
    01249     init( cstate );
    01250   }
    01251   leave();
    01252 };
    01253
    01254 State StdService::internDone()
    01255 {
    01256   State state;
    01257
    01258   enter();
    01259   {
    01260     ColorizerState cstate;
    01261     done( cstate );
    01262
    01263     if (m_buffer->sink)
    01264     {
    01265         m_buffer->sink->Release();
    01266         m_buffer->sink = NULL;
    01267     }
    01268
    01269     m_buffer->input     = NULL;
    01270     m_buffer->inputLim  = NULL;
    01271
    01272     m_buffer->token     = 0;
    01273     m_buffer->location.initialize();
    01274
    01275     g_service = NULL;
    01276     state = cstate.getState();
    01277   }
    01278   leave();
    01279   return state;
    01280 };
    01281 */
    01282
    01283 //---------------------------------------------------------
    01284 //  Lexer state
    01285 //---------------------------------------------------------
    01286
    01287 void StdService::setLexState( in LexState lexstate )
    01288 {
    01289     primSetLexState( lexstate );
    01290 }
    01291
    01292 LexState StdService::getLexState() const
    01293 {
    01294     return primGetLexState();
    01295 }
    01296
    01297 //---------------------------------------------------------
    01298 //  Read input from our input buffer (called by the lexer)
    01299 //---------------------------------------------------------
    01300 void StdService::readInput( out char* buffer,
    01301                             out int* result,
    01302                             in  int maxSize )
    01303 {
    01304   enterLexer();
    01305   {
    01306     ASSERT(m_buffer);
    01307     ASSERT(buffer);
    01308     ASSERT(result);
    01309
    01310     // Check our output parameters for NULL
    01311     if (buffer == NULL || result == NULL)
    01312     {
    01313         return;
    01314     }
    01315
    01316     // Check that we have characters in the input buffer and space in the
    01317     // output buffer before the first iteration of the "do" loop.
    01318     if (m_buffer->input >= m_buffer->inputLim || m_buffer->input == NULL || maxSize == 0)
    01319     {
    01320         *result = 0;
    01321     }
    01322     else
    01323     {
    01324         char* current  = buffer;
    01325
    01326         do
    01327         {
    01328             //treat "\r\n" as " \n"  (MS-DOS CR/LF)
    01329             //treat just "\r" as "\n"  (UNIX)
    01330             if (m_buffer->input[0] == '\r')
    01331             {
    01332                 m_buffer->input++;
    01333                 // If we have reached then end of our input characters or we are
    01334                 // at the end of the output buffer we insert a "\n". If not we
    01335                 // check the next character and if it is a "\n" we insert a space
    01336                 // for the "\r". Any other character and we insert a "\n" for the "\r".
    01337                 if ((m_buffer->input < m_buffer->inputLim) && ((current - buffer) < (maxSize - 1)))
    01338                 {
    01339                     // We have not reached the end of our input or output buffers
    01340                     // so we can check if the next character is a "\n"
    01341                     if (m_buffer->input[0] == '\n')
    01342                         current[0] = ' ';
    01343                     else
    01344                         current[0] = '\n';
    01345                 }
    01346                 else
    01347                 {
    01348                     current[0] = '\n';
    01349                 }
    01350                 current++;
    01351             }
    01352             //treat "\0" (end of file) as "\n"
    01353             else if (m_buffer->input[0] == '\0' )
    01354             {
    01355                 current[0] = '\n';
    01356                 current++;
    01357                 m_buffer->input++;
    01358             }
    01359             else
    01360             {
    01361                 // Convert our input wide character to multibyte representation.
    01362                 // Note we need to ensure there is sufficent space in our output
    01363                 // buffer and we also need to test for failure
    01364                 char tempBuf[DOUBLE_BYTE_BUF_SIZE];   // Much bigger than we will ever need
    01365                 int  count;
    01366                 count = wctomb(tempBuf, m_buffer->input[0]);
    01367                 // If the conversion is successful then copy the byte(s) to the output
    01368                 if (count > 0)
    01369                 {
    01370                     if ((current - buffer) <= (maxSize - count)) // Check for room in the output buffer
    01371                     {
    01372                         memcpy(current, tempBuf, count);
    01373                         current += count;
    01374                     }
    01375                     else
    01376                     {
    01377                         // We don't have room so we output a space
    01378                         current[0] = ' ';
    01379                         current++;
    01380                     }
    01381                 }
    01382                 m_buffer->input++;
    01383             }
    01384         }
    01385         while (m_buffer->input < m_buffer->inputLim && ((current - buffer) < maxSize));
    01386
    01387         *result = (int)(current - buffer);
    01388     }
    01389   }
    01390   leaveLexer();
    01391 }
    01392
    01393
    01394
    01395 /*---------------------------------------------------------
    01396   IUnknown
    01397 -----------------------------------------------------------*/
    01398 STDMETHODIMP StdService::QueryInterface( in REFIID iid, out void** obj )
    01399 {
    01400   OUTARG(obj);
    01401
    01402   if (iid == IID_IUnknown)
    01403   {
    01404     TRACE("StdService::QueryInterface for IUnknown");
    01405     *obj = static_cast<IUnknown*>(this);
    01406   }
    01407   else if (iid == IID_IDispatch)
    01408   {
    01409     TRACE("StdService::QueryInterface for IDispatch");
    01410     *obj = static_cast<IDispatch*>(this);
    01411   }
    01412   else if (iid == IID_IBabelService)
    01413   {
    01414     TRACE("StdService::QueryInterface for IBabelService");
    01415     *obj = static_cast<IBabelService*>(this);
    01416   }
    01417   else
    01418     return E_NOINTERFACE;
    01419
    01420   AddRef();
    01421   return S_OK;
    01422 }
    01423
    01424 STDMETHODIMP_(ULONG) StdService::AddRef()
    01425 {
    01426   return IncRefCount(&m_refCount);
    01427 }
    01428
    01429 STDMETHODIMP_(ULONG) StdService::Release()
    01430 {
    01431   if (DecRefCount(&m_refCount) == 0)
    01432   {
    01433     delete this;
    01434     return 0;
    01435   }
    01436   else
    01437     return m_refCount;
    01438 }
    01439
    01440 /*---------------------------------------------------------
    01441   implement IDispatch (for IBabelService only)
    01442 -----------------------------------------------------------*/
    01443 STDMETHODIMP StdService::GetTypeInfoCount( out UINT* count )
    01444 {
    01445   OUTARG(count);
    01446
    01447   if (g_typeInfoBabelService) *count = 1;
    01448                       else *count = 0;
    01449   return S_OK;
    01450 }
    01451
    01452 STDMETHODIMP StdService::GetTypeInfo( in UINT index, in LCID lcid, out ITypeInfo** typeInfo )
    01453 {
    01454   OUTARG(typeInfo);
    01455   if (index != 0) return E_INVALIDARG;
    01456   if (!g_typeInfoBabelService) return TYPE_E_CANTLOADLIBRARY;
    01457
    01458   *typeInfo = g_typeInfoBabelService;
    01459   return S_OK;
    01460 }
    01461
    01462 STDMETHODIMP StdService::GetIDsOfNames( in REFIID iid, in OLECHAR** names, in UINT count,
    01463                                        in LCID lcid, out DISPID* dispids )
    01464 {
    01465   if (!g_typeInfoBabelService) return TYPE_E_CANTLOADLIBRARY;
    01466   return g_typeInfoBabelService->GetIDsOfNames( names, count, dispids );
    01467 }
    01468
    01469 STDMETHODIMP StdService::Invoke( in DISPID dispid, in REFIID iid, in LCID lcid,
    01470                                 in WORD flags, in DISPPARAMS* args,
    01471                                 out VARIANT* result, out EXCEPINFO* error, out UINT* errorArg )
    01472 {
    01473   if (!g_typeInfoBabelService) return TYPE_E_CANTLOADLIBRARY;
    01474   return g_typeInfoBabelService->Invoke( static_cast<IBabelService*>(this),
    01475                                       dispid, flags, args, result, error, errorArg );
    01476 }
    01477