File: | cppuhelper/source/weak.cxx |
Location: | line 153, column 13 |
Description: | Value stored to 'n' is never read |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | /************************************************************************* |
3 | * |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
5 | * |
6 | * Copyright 2000, 2010 Oracle and/or its affiliates. |
7 | * |
8 | * OpenOffice.org - a multi-platform office productivity suite |
9 | * |
10 | * This file is part of OpenOffice.org. |
11 | * |
12 | * OpenOffice.org is free software: you can redistribute it and/or modify |
13 | * it under the terms of the GNU Lesser General Public License version 3 |
14 | * only, as published by the Free Software Foundation. |
15 | * |
16 | * OpenOffice.org is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU Lesser General Public License version 3 for more details |
20 | * (a copy is included in the LICENSE file that accompanied this code). |
21 | * |
22 | * You should have received a copy of the GNU Lesser General Public License |
23 | * version 3 along with OpenOffice.org. If not, see |
24 | * <http://www.openoffice.org/license.html> |
25 | * for a copy of the LGPLv3 License. |
26 | * |
27 | ************************************************************************/ |
28 | |
29 | #include <osl/mutex.hxx> |
30 | #include <cppuhelper/weakagg.hxx> |
31 | #include <cppuhelper/interfacecontainer.hxx> |
32 | #include "cppuhelper/exc_hlp.hxx" |
33 | |
34 | using namespace osl; |
35 | using namespace com::sun::star::uno; |
36 | |
37 | /** */ //for docpp |
38 | namespace cppu |
39 | { |
40 | |
41 | // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#) |
42 | inline static Mutex & getWeakMutex() SAL_THROW(()) |
43 | { |
44 | static Mutex * s_pMutex = 0; |
45 | if (! s_pMutex) |
46 | s_pMutex = new Mutex(); |
47 | return *s_pMutex; |
48 | } |
49 | |
50 | //------------------------------------------------------------------------ |
51 | //-- OWeakConnectionPoint ---------------------------------------------------- |
52 | //------------------------------------------------------------------------ |
53 | class OWeakConnectionPoint : public XAdapter |
54 | { |
55 | public: |
56 | /** |
57 | Hold the weak object without an acquire (only the pointer). |
58 | */ |
59 | OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW(()) |
60 | : m_aRefCount( 0 ) |
61 | , m_pObject(pObj) |
62 | , m_aReferences( getWeakMutex() ) |
63 | {} |
64 | |
65 | // XInterface |
66 | Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); |
67 | void SAL_CALL acquire() throw(); |
68 | void SAL_CALL release() throw(); |
69 | |
70 | // XAdapter |
71 | ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException); |
72 | void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException); |
73 | void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException); |
74 | |
75 | /// Called from the weak object if the reference count goes to zero. |
76 | void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); |
77 | |
78 | private: |
79 | OWeakConnectionPoint(OWeakConnectionPoint &); // not defined |
80 | void operator =(OWeakConnectionPoint &); // not defined |
81 | |
82 | virtual ~OWeakConnectionPoint() {} |
83 | |
84 | /// The reference counter. |
85 | oslInterlockedCount m_aRefCount; |
86 | /// The weak object |
87 | OWeakObject* m_pObject; |
88 | /// The container to hold the weak references |
89 | OInterfaceContainerHelper m_aReferences; |
90 | }; |
91 | |
92 | // XInterface |
93 | Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType ) |
94 | throw(com::sun::star::uno::RuntimeException) |
95 | { |
96 | return ::cppu::queryInterface( |
97 | rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) ); |
98 | } |
99 | |
100 | // XInterface |
101 | void SAL_CALL OWeakConnectionPoint::acquire() throw() |
102 | { |
103 | osl_incrementInterlockedCount( &m_aRefCount ); |
104 | } |
105 | |
106 | // XInterface |
107 | void SAL_CALL OWeakConnectionPoint::release() throw() |
108 | { |
109 | if (! osl_decrementInterlockedCount( &m_aRefCount )) |
110 | delete this; |
111 | } |
112 | |
113 | void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException) |
114 | { |
115 | Any ex; |
116 | OInterfaceIteratorHelper aIt( m_aReferences ); |
117 | while( aIt.hasMoreElements() ) |
118 | { |
119 | try |
120 | { |
121 | ((XReference *)aIt.next())->dispose(); |
122 | } |
123 | catch (com::sun::star::lang::DisposedException &) {} |
124 | catch (RuntimeException &) |
125 | { |
126 | ex = cppu::getCaughtException(); |
127 | } |
128 | } |
129 | if (ex.hasValue()) |
130 | { |
131 | cppu::throwException(ex); |
132 | } |
133 | } |
134 | |
135 | // XInterface |
136 | Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException) |
137 | { |
138 | Reference< XInterface > ret; |
139 | |
140 | ClearableMutexGuard guard(getWeakMutex()); |
141 | |
142 | if (m_pObject) |
143 | { |
144 | oslInterlockedCount n = osl_incrementInterlockedCount( &m_pObject->m_refCount ); |
145 | |
146 | if (n > 1) |
147 | { |
148 | // The refence is incremented. The object cannot be destroyed. |
149 | // Release the guard at the earliest point. |
150 | guard.clear(); |
151 | // WeakObject has a (XInterface *) cast operator |
152 | ret = *m_pObject; |
153 | n = osl_decrementInterlockedCount( &m_pObject->m_refCount ); |
Value stored to 'n' is never read | |
154 | } |
155 | else |
156 | // Another thread wait in the dispose method at the guard |
157 | n = osl_decrementInterlockedCount( &m_pObject->m_refCount ); |
158 | } |
159 | |
160 | return ret; |
161 | } |
162 | |
163 | // XInterface |
164 | void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef) |
165 | throw(::com::sun::star::uno::RuntimeException) |
166 | { |
167 | m_aReferences.addInterface( (const Reference< XInterface > &)rRef ); |
168 | } |
169 | |
170 | // XInterface |
171 | void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef) |
172 | throw(::com::sun::star::uno::RuntimeException) |
173 | { |
174 | m_aReferences.removeInterface( (const Reference< XInterface > &)rRef ); |
175 | } |
176 | |
177 | |
178 | //------------------------------------------------------------------------ |
179 | //-- OWeakObject ------------------------------------------------------- |
180 | //------------------------------------------------------------------------ |
181 | |
182 | #ifdef _MSC_VER |
183 | // Accidentally occurs in msvc mapfile = > had to be outlined. |
184 | OWeakObject::OWeakObject() SAL_THROW(()) |
185 | : m_refCount( 0 ), |
186 | m_pWeakConnectionPoint( 0 ) |
187 | { |
188 | } |
189 | #endif |
190 | |
191 | // XInterface |
192 | Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) |
193 | { |
194 | return ::cppu::queryInterface( |
195 | rType, |
196 | static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) ); |
197 | } |
198 | |
199 | // XInterface |
200 | void SAL_CALL OWeakObject::acquire() throw() |
201 | { |
202 | osl_incrementInterlockedCount( &m_refCount ); |
203 | } |
204 | |
205 | // XInterface |
206 | void SAL_CALL OWeakObject::release() throw() |
207 | { |
208 | if (osl_decrementInterlockedCount( &m_refCount ) == 0) { |
209 | // notify/clear all weak-refs before object's dtor is executed |
210 | // (which may check weak-refs to this object): |
211 | disposeWeakConnectionPoint(); |
212 | // destroy object: |
213 | delete this; |
214 | } |
215 | } |
216 | |
217 | void OWeakObject::disposeWeakConnectionPoint() |
218 | { |
219 | OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" )do { if (true && (!(m_refCount == 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "219" ": "), "%s", "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" ); } } while (false); |
220 | if (m_pWeakConnectionPoint != 0) { |
221 | OWeakConnectionPoint * const p = m_pWeakConnectionPoint; |
222 | m_pWeakConnectionPoint = 0; |
223 | try { |
224 | p->dispose(); |
225 | } |
226 | catch (RuntimeException const& exc) { |
227 | OSL_FAIL(do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "229" ": "), "%s", OUStringToOString( exc.Message, (((rtl_TextEncoding ) 11)) ).getStr()); } } while (false) |
228 | OUStringToOString(do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "229" ": "), "%s", OUStringToOString( exc.Message, (((rtl_TextEncoding ) 11)) ).getStr()); } } while (false) |
229 | exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "229" ": "), "%s", OUStringToOString( exc.Message, (((rtl_TextEncoding ) 11)) ).getStr()); } } while (false); |
230 | static_cast<void>(exc); |
231 | } |
232 | p->release(); |
233 | } |
234 | } |
235 | |
236 | OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) ) |
237 | { |
238 | } |
239 | |
240 | // XWeak |
241 | Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter() |
242 | throw (::com::sun::star::uno::RuntimeException) |
243 | { |
244 | if (!m_pWeakConnectionPoint) |
245 | { |
246 | // only acquire mutex if member is not created |
247 | MutexGuard aGuard( getWeakMutex() ); |
248 | if( !m_pWeakConnectionPoint ) |
249 | { |
250 | OWeakConnectionPoint * p = new OWeakConnectionPoint(this); |
251 | p->acquire(); |
252 | m_pWeakConnectionPoint = p; |
253 | } |
254 | } |
255 | |
256 | return m_pWeakConnectionPoint; |
257 | } |
258 | |
259 | //------------------------------------------------------------------------ |
260 | //-- OWeakAggObject ---------------------------------------------------- |
261 | //------------------------------------------------------------------------ |
262 | OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) ) |
263 | { |
264 | } |
265 | |
266 | // XInterface |
267 | void OWeakAggObject::acquire() throw() |
268 | { |
269 | Reference<XInterface > x( xDelegator ); |
270 | if (x.is()) |
271 | x->acquire(); |
272 | else |
273 | OWeakObject::acquire(); |
274 | } |
275 | |
276 | // XInterface |
277 | void OWeakAggObject::release() throw() |
278 | { |
279 | Reference<XInterface > x( xDelegator ); |
280 | if (x.is()) |
281 | x->release(); |
282 | else |
283 | OWeakObject::release(); |
284 | } |
285 | |
286 | // XInterface |
287 | Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) |
288 | { |
289 | Reference< XInterface > x( xDelegator ); // harden ref |
290 | return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType )); |
291 | } |
292 | |
293 | // XAggregation |
294 | Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) |
295 | { |
296 | return ::cppu::queryInterface( |
297 | rType, |
298 | static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ), |
299 | static_cast< XAggregation * >( this ), |
300 | static_cast< XWeak * >( this ) ); |
301 | } |
302 | |
303 | // XAggregation |
304 | void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException) |
305 | { |
306 | xDelegator = rDelegator; |
307 | } |
308 | |
309 | } |
310 | |
311 | /** */ //for docpp |
312 | namespace com |
313 | { |
314 | /** */ //for docpp |
315 | namespace sun |
316 | { |
317 | /** */ //for docpp |
318 | namespace star |
319 | { |
320 | /** */ //for docpp |
321 | namespace uno |
322 | { |
323 | |
324 | |
325 | //------------------------------------------------------------------------ |
326 | //-- OWeakRefListener ----------------------------------------------------- |
327 | //------------------------------------------------------------------------ |
328 | class OWeakRefListener : public XReference |
329 | { |
330 | public: |
331 | OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(()); |
332 | OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(()); |
333 | virtual ~OWeakRefListener() SAL_THROW(()); |
334 | |
335 | // XInterface |
336 | Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException); |
337 | void SAL_CALL acquire() throw(); |
338 | void SAL_CALL release() throw(); |
339 | |
340 | // XReference |
341 | void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); |
342 | |
343 | /// The reference counter. |
344 | oslInterlockedCount m_aRefCount; |
345 | /// The connection point of the weak object |
346 | Reference< XAdapter > m_XWeakConnectionPoint; |
347 | |
348 | private: |
349 | OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW(()); |
350 | }; |
351 | |
352 | OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(()) |
353 | : com::sun::star::uno::XReference() |
354 | , m_aRefCount( 1 ) |
355 | { |
356 | try |
357 | { |
358 | m_XWeakConnectionPoint = rRef.m_XWeakConnectionPoint; |
359 | |
360 | if (m_XWeakConnectionPoint.is()) |
361 | { |
362 | m_XWeakConnectionPoint->addReference((XReference*)this); |
363 | } |
364 | } |
365 | catch (RuntimeException &) { OSL_ASSERT( 0 )do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "365" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } // assert here, but no unexpected() |
366 | osl_decrementInterlockedCount( &m_aRefCount ); |
367 | } |
368 | |
369 | OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(()) |
370 | : m_aRefCount( 1 ) |
371 | { |
372 | try |
373 | { |
374 | Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) ); |
375 | |
376 | if (xWeak.is()) |
377 | { |
378 | m_XWeakConnectionPoint = xWeak->queryAdapter(); |
379 | |
380 | if (m_XWeakConnectionPoint.is()) |
381 | { |
382 | m_XWeakConnectionPoint->addReference((XReference*)this); |
383 | } |
384 | } |
385 | } |
386 | catch (RuntimeException &) { OSL_ASSERT( 0 )do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "386" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } // assert here, but no unexpected() |
387 | osl_decrementInterlockedCount( &m_aRefCount ); |
388 | } |
389 | |
390 | OWeakRefListener::~OWeakRefListener() SAL_THROW(()) |
391 | { |
392 | try |
393 | { |
394 | if (m_XWeakConnectionPoint.is()) |
395 | { |
396 | acquire(); // dont die again |
397 | m_XWeakConnectionPoint->removeReference((XReference*)this); |
398 | } |
399 | } |
400 | catch (RuntimeException &) { OSL_ASSERT( 0 )do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "400" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } // assert here, but no unexpected() |
401 | } |
402 | |
403 | // XInterface |
404 | Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException) |
405 | { |
406 | return ::cppu::queryInterface( |
407 | rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) ); |
408 | } |
409 | |
410 | // XInterface |
411 | void SAL_CALL OWeakRefListener::acquire() throw() |
412 | { |
413 | osl_incrementInterlockedCount( &m_aRefCount ); |
414 | } |
415 | |
416 | // XInterface |
417 | void SAL_CALL OWeakRefListener::release() throw() |
418 | { |
419 | if( ! osl_decrementInterlockedCount( &m_aRefCount ) ) |
420 | delete this; |
421 | } |
422 | |
423 | void SAL_CALL OWeakRefListener::dispose() |
424 | throw(::com::sun::star::uno::RuntimeException) |
425 | { |
426 | Reference< XAdapter > xAdp; |
427 | { |
428 | MutexGuard guard(cppu::getWeakMutex()); |
429 | if( m_XWeakConnectionPoint.is() ) |
430 | { |
431 | xAdp = m_XWeakConnectionPoint; |
432 | m_XWeakConnectionPoint.clear(); |
433 | } |
434 | } |
435 | |
436 | if( xAdp.is() ) |
437 | xAdp->removeReference((XReference*)this); |
438 | } |
439 | |
440 | //------------------------------------------------------------------------ |
441 | //-- WeakReferenceHelper ---------------------------------------------------------- |
442 | //------------------------------------------------------------------------ |
443 | WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW(()) |
444 | : m_pImpl( 0 ) |
445 | { |
446 | if (xInt.is()) |
447 | { |
448 | m_pImpl = new OWeakRefListener(xInt); |
449 | m_pImpl->acquire(); |
450 | } |
451 | } |
452 | |
453 | WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW(()) |
454 | : m_pImpl( 0 ) |
455 | { |
456 | Reference< XInterface > xInt( rWeakRef.get() ); |
457 | if (xInt.is()) |
458 | { |
459 | m_pImpl = new OWeakRefListener(xInt); |
460 | m_pImpl->acquire(); |
461 | } |
462 | } |
463 | |
464 | void WeakReferenceHelper::clear() SAL_THROW(()) |
465 | { |
466 | try |
467 | { |
468 | if (m_pImpl) |
469 | { |
470 | if (m_pImpl->m_XWeakConnectionPoint.is()) |
471 | { |
472 | m_pImpl->m_XWeakConnectionPoint->removeReference( |
473 | (XReference*)m_pImpl); |
474 | m_pImpl->m_XWeakConnectionPoint.clear(); |
475 | } |
476 | m_pImpl->release(); |
477 | m_pImpl = 0; |
478 | } |
479 | } |
480 | catch (RuntimeException &) { OSL_ASSERT( 0 )do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "480" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } // assert here, but no unexpected() |
481 | } |
482 | |
483 | WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW(()) |
484 | { |
485 | if (this == &rWeakRef) |
486 | { |
487 | return *this; |
488 | } |
489 | Reference< XInterface > xInt( rWeakRef.get() ); |
490 | return operator = ( xInt ); |
491 | } |
492 | |
493 | WeakReferenceHelper & SAL_CALL |
494 | WeakReferenceHelper::operator= (const Reference< XInterface > & xInt) |
495 | SAL_THROW(()) |
496 | { |
497 | try |
498 | { |
499 | clear(); |
500 | if (xInt.is()) |
501 | { |
502 | m_pImpl = new OWeakRefListener(xInt); |
503 | m_pImpl->acquire(); |
504 | } |
505 | } |
506 | catch (RuntimeException &) { OSL_ASSERT( 0 )do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "506" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } // assert here, but no unexpected() |
507 | return *this; |
508 | } |
509 | |
510 | WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW(()) |
511 | { |
512 | clear(); |
513 | } |
514 | |
515 | Reference< XInterface > WeakReferenceHelper::get() const SAL_THROW(()) |
516 | { |
517 | try |
518 | { |
519 | Reference< XAdapter > xAdp; |
520 | { |
521 | MutexGuard guard(cppu::getWeakMutex()); |
522 | if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() ) |
523 | xAdp = m_pImpl->m_XWeakConnectionPoint; |
524 | } |
525 | |
526 | if (xAdp.is()) |
527 | return xAdp->queryAdapted(); |
528 | } |
529 | catch (RuntimeException &) { OSL_ASSERT( 0 )do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/cppuhelper/source/weak.cxx" ":" "529" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } // assert here, but no unexpected() |
530 | |
531 | return Reference< XInterface >(); |
532 | } |
533 | |
534 | } |
535 | } |
536 | } |
537 | } |
538 | |
539 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |