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   

Generated on Mon Mar 20 22:00:11 2006 for GT2005 by doxygen 1.3.6