00001
00002
00003
00004
00005
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
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
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
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
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
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
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
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
00271
00272
00273
00274
00275
00276
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
00292
00293
00294 doneBuffer();
00295 }
00296 leaveParser();
00297
00298 return S_OK;
00299 }
00300
00301
00302
00303
00304
00305 STDMETHODIMP StdService::ColorLine( in BSTR line,
00306 in IColorSink* sink,
00307 inout long* state )
00308 {
00309
00310 if (!state) return E_POINTER;
00311
00312 enterLexer();
00313 {
00314
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
00340 }
00341 leaveLexer();
00342
00343 return S_OK;
00344 };
00345
00346
00347
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
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
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)
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)
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
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;
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
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
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
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
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
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
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
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
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
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
00806 bstrFree(bstrName);
00807 bstrFree(bstrType);
00808 bstrFree(bstrDescription);
00809 bstrFree(bstrDisplay);
00810
00811 }
00812 leaveSink();
00813 }
00814
00815
00816
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
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
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
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
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
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
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
01153 buffer.prevBuffer = m_buffer;
01154 if (m_buffer)
01155 {
01156 TRACE("save buffer");
01157
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
01176 m_buffer = &buffer;
01177
01178
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
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
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
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
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
01311 if (buffer == NULL || result == NULL)
01312 {
01313 return;
01314 }
01315
01316
01317
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
01329
01330 if (m_buffer->input[0] == '\r')
01331 {
01332 m_buffer->input++;
01333
01334
01335
01336
01337 if ((m_buffer->input < m_buffer->inputLim) && ((current - buffer) < (maxSize - 1)))
01338 {
01339
01340
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
01353 else if (m_buffer->input[0] == '\0' )
01354 {
01355 current[0] = '\n';
01356 current++;
01357 m_buffer->input++;
01358 }
01359 else
01360 {
01361
01362
01363
01364 char tempBuf[DOUBLE_BYTE_BUF_SIZE];
01365 int count;
01366 count = wctomb(tempBuf, m_buffer->input[0]);
01367
01368 if (count > 0)
01369 {
01370 if ((current - buffer) <= (maxSize - count))
01371 {
01372 memcpy(current, tempBuf, count);
01373 current += count;
01374 }
01375 else
01376 {
01377
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
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
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