]> git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/ifcontext.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[wxWidgets.git] / utils / HelpGen / src / ifcontext.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 27/12/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleskandars Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #include <stdio.h>
24
25 #include "ifcontext.h"
26
27 /***** Implementation for class spInterFileContext *****/
28
29 size_t spInterFileContext::GetFileNo( const wxString& fname )
30 {
31 for ( size_t i = 0; i != m_Files.size(); ++i )
32 {
33 if ( fname == m_Files[i] )
34 return i;
35 }
36
37 wxFAIL_MSG("File not found in array in function spInterFileContext::GetFileNo()");
38
39 return 0;
40 }
41
42 size_t spInterFileContext::GetFileNoOfContext( spContext& ctx )
43 {
44 spContext* pCtx = ctx.GetEnclosingContext( SP_CTX_FILE );
45
46 // DBG:: outer-file context should be present
47 wxASSERT( pCtx && pCtx->GetType() == SP_CTX_FILE );
48
49 return GetFileNo( ((spFile*)pCtx)->m_FileName );
50 }
51
52 /*** public interface ***/
53
54 spInterFileContext::spInterFileContext()
55 {}
56
57 spInterFileContext::~spInterFileContext()
58 {}
59
60 void spInterFileContext::AddFile( const wxString& fname, const wxString& content )
61 {
62 m_Files.push_back( fname );
63 m_Contents.push_back( content );
64 }
65
66 void spInterFileContext::RemoveContext( spContext& ctx )
67 {
68 wxASSERT( ctx.PositionIsKnown() ); // DBG:: should be checked by-user code
69
70 size_t fNo = GetFileNoOfContext( ctx );
71
72 mDeletionMarks.push_back( spBookmark( ctx.mSrcOffset, ctx.mContextLength, fNo ) );
73 }
74
75 void spInterFileContext::InsertBookmarkSorted( BookmarkListT& lst, spBookmark& mark )
76 {
77 for( size_t i = 0; i != lst.size(); ++i )
78
79 if ( lst[i].mFrom > mark.mFrom )
80 {
81 lst.insert( &lst[i], mark );
82 return;
83 }
84
85 lst.push_back( mark );
86 }
87
88 void spInterFileContext::DoAppendSourceFragment( wxString& source,
89 wxString& result,
90 size_t pos, size_t len )
91 {
92 mFiltered.erase( mFiltered.begin(), mFiltered.end() );
93
94 size_t i;
95
96 for( i = 0; i != mDeletionMarks.size(); ++i )
97 {
98 spBookmark& mark = mDeletionMarks[i];
99
100 if ( mark.mFileNo == mCurFileNo &&
101 mark.mFrom >= pos && mark.mFrom < pos + len )
102
103 InsertBookmarkSorted( mFiltered, mark );
104 }
105
106 size_t cur = pos;
107
108 for( i = 0; i != mFiltered.size(); ++ i )
109 {
110 spBookmark& mark = mFiltered[i];
111
112 result.append( source, cur, ( (size_t)mark.mFrom - cur ) );
113
114 cur = size_t( mark.mFrom + mark.mLen );
115
116 if ( cur >= pos + len ) // check if we've overstepped the current source-fragment
117 {
118 // wxASSERT(0); // DBG:: with current imp. this should not happen
119 wxFAIL_MSG("Overstepped the current source fragment in function\nspInterFileContext::DoAppendSourceFragment()");
120 cur = pos + len; break;
121 }
122 }
123
124 result.append( source, cur, ( pos + len ) - cur );
125 }
126
127 void spInterFileContext::GenerateContextBody( spContext& ctx,
128 wxString& source,
129 wxString& result,
130 size_t& lastSavedPos,
131 size_t& lastKnownPos )
132 {
133 if ( ctx.PositionIsKnown() )
134 lastKnownPos = ctx.mSrcOffset;
135
136 if ( ctx.IsVirtualContext() )
137 {
138 // add fragment accumulated before this context
139
140 DoAppendSourceFragment( source, result,
141 size_t(lastSavedPos),
142 size_t(lastKnownPos - lastSavedPos) );
143
144 // add context body
145
146 result += ctx.GetVirtualContextBody();
147
148 lastSavedPos = lastKnownPos;
149
150 if ( ctx.PositionIsKnown() )
151 {
152 if ( ctx.VitualContextHasChildren() )
153 {
154 lastKnownPos = ctx.mSrcOffset + ctx.mHeaderLength;
155
156 lastSavedPos = lastKnownPos;
157 }
158 else
159 {
160 lastKnownPos = ctx.mSrcOffset + ctx.mContextLength;
161
162 lastSavedPos = lastKnownPos;
163
164 return; // have not children
165 }
166 }
167 }
168
169 MMemberListT& lst = ctx.GetMembers();
170
171 for( size_t i = 0; i != lst.size(); ++i )
172 {
173 GenerateContextBody( *lst[i], source, result, lastSavedPos, lastKnownPos );
174 }
175
176 if ( ctx.IsVirtualContext() )
177 {
178 if ( ctx.VitualContextHasChildren() && !ctx.GetFooterOfVirtualContextBody().empty() )
179 {
180 // append the reminder space after children of the context
181
182 DoAppendSourceFragment( result, source,
183 size_t(lastSavedPos),
184 size_t(lastKnownPos - lastSavedPos) );
185
186 // add footer
187 result += ctx.GetFooterOfVirtualContextBody();
188
189 lastKnownPos = ctx.mSrcOffset + ctx.mContextLength;
190
191 lastSavedPos = lastKnownPos;
192 }
193 }
194
195 if ( ctx.PositionIsKnown() )
196
197 lastKnownPos = ctx.mSrcOffset + ctx.mContextLength;
198 }
199
200 void spInterFileContext::GenrateContents()
201 {
202 MMemberListT& lst = GetMembers();
203
204 for( size_t f = 0; f != lst.size(); ++f )
205 {
206 wxString& fname = ((spFile*)lst[f])->m_FileName;
207
208 size_t fileNo = GetFileNo( fname );
209
210 wxString& source = m_Contents[ fileNo ];
211
212 wxString result;
213
214 size_t lastKnownPos = 0, // the begining of the file is always "known"
215 lastSavedPos = 0;
216
217 mCurFileNo = fileNo;
218
219 GenerateContextBody( *lst[f], source, result, lastSavedPos, lastKnownPos );
220
221 // the end of file is always known
222
223 lastKnownPos = m_Contents[ fileNo ].length();
224
225 // append the reminder
226
227 DoAppendSourceFragment( source, result,
228 size_t(lastSavedPos),
229 size_t(lastKnownPos - lastSavedPos) );
230
231 // replace original contnet with newly generated one
232
233 m_Contents[ fileNo ] = result;
234 }
235 }
236
237 void spInterFileContext::ParseContents( SourceParserPlugin* pPlugin )
238 {
239 mDeletionMarks.erase( mDeletionMarks.begin(), mDeletionMarks.end() );
240
241 RemoveChildren(); // clean up top-level context
242
243 mParser.SetPlugin( pPlugin );
244
245 for( size_t i = 0; i != m_Files.size(); ++i )
246 {
247 wxChar* s = (char*)(m_Contents[i].c_str());
248
249 spFile* pFCtx = mParser.Parse( s, s + m_Contents[i].length() );
250
251 pFCtx->m_FileName = m_Files[i];
252
253 AddMember( pFCtx );
254 }
255 }
256
257 void spInterFileContext::WriteToFiles()
258 {
259 for( size_t i = 0; i != m_Files.size(); ++i )
260 {
261 FILE* fp = fopen( m_Files[i].c_str(), "w+t" );
262
263 if ( fp != NULL )
264 {
265 fwrite( m_Contents[i].c_str(), sizeof(char), m_Contents[i].length(), fp );
266
267 fclose( fp );
268 }
269 }
270 }
271
272 wxString spInterFileContext::GetBody( spContext* pCtx )
273 {
274 wxASSERT( pCtx->PositionIsKnown() ); // DBG:: should be checked by-user code
275
276 wxString& source = m_Contents[ GetFileNoOfContext( *pCtx ) ];
277
278 return wxString( source.c_str() + pCtx->mSrcOffset, pCtx->mContextLength );
279 }
280
281 wxString spInterFileContext::GetHeader( spContext* pCtx )
282 {
283 wxASSERT( pCtx->PositionIsKnown() ); // DBG:: should be checked by-user code
284
285 wxASSERT( pCtx->mHeaderLength != -1 ); // DBG:: -/-
286
287 wxString& source = m_Contents[ GetFileNoOfContext( *pCtx ) ];
288
289 return wxString( source.c_str() + pCtx->mSrcOffset, pCtx->mHeaderLength );
290 }