• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

trixi-framework / FTObjectLibrary / 30206241592

26 Jul 2026 02:31PM UTC coverage: 92.391% (-2.2%) from 94.58%
30206241592

Pull #79

github

web-flow
Merge 79dc9ef6b into 58212d52c
Pull Request #79: Type mods2

89 of 126 new or added lines in 17 files covered. (70.63%)

33 existing lines in 4 files now uncovered.

2732 of 2957 relevant lines covered (92.39%)

14.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.63
/Source/FTObjects/FTExceptionClass.f90
1
! MIT License
2
!
3
! Copyright (c) 2010-present David A. Kopriva and other contributors: AUTHORS.md
4
!
5
! Permission is hereby granted, free of charge, to any person obtaining a copy  
6
! of this software and associated documentation files (the "Software"), to deal  
7
! in the Software without restriction, including without limitation the rights  
8
! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
9
! copies of the Software, and to permit persons to whom the Software is  
10
! furnished to do so, subject to the following conditions:
11
!
12
! The above copyright notice and this permission notice shall be included in all  
13
! copies or substantial portions of the Software.
14
!
15
! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
16
! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
17
! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
18
! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
19
! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
20
! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
21
! SOFTWARE.
22
!
23
! FTObjectLibrary contains code that, to the best of our knowledge, has been released as
24
! public domain software:
25
! * `b3hs_hash_key_jenkins`: originally by Rich Townsend, 
26
! https://groups.google.com/forum/#!topic/comp.lang.fortran/RWoHZFt39ng, 2005
27
!
28
! --- End License
29

30
!
31
!////////////////////////////////////////////////////////////////////////
32
!
33
!      FTExceptionClass.f90
34
!      Created: January 29, 2013 5:06 PM 
35
!      By: David Kopriva  
36
!
37
!
38
!>An FTException object gives a way to pass generic
39
!>information about an exceptional situation.
40
!>
41
!>An FTException object gives a way to pass generic
42
!>information about an exceptional situation. Methods for
43
!>dealing with exceptions are defined in the SharedExceptionManagerModule
44
!>module.
45
!>
46
!>An FTException object wraps:
47
!>
48
!>- A severity indicator
49
!>- A name for the exception
50
!>- An optional dictionary that contains whatever information is deemed necessary.
51
!>
52
!>It is expected that classes will define exceptions that use instances
53
!>of the FTException Class.
54
!>
55
!>### Defined constants:
56
!>
57
!>-   FT_ERROR_NONE    = 0
58
!>-   FT_ERROR_WARNING = 1
59
!>-   FT_ERROR_FATAL   = 2
60
!>
61
!>### Initialization
62
!>
63
!>            CALL e  %  initFTException(severity,exceptionName,infoDictionary)
64
!>
65
!>Plus the convenience initializers, which automatically create a FTValueDictionary with a single key called "message":
66
!>
67
!>        CALL e % initWarningException(msg = "message")
68
!>        CALL e % initFatalException(msg = "message")
69
!>
70
!>Plus an assertion exception
71
!>
72
!>        CALL e % initAssertionFailureException(msg,expectedValueObject,observedValueObject,level)
73
!>
74
!>### Destruction
75
!>
76
!>        CALL releaseFTExceptionClass(e) [pointers]
77
!>        CALL releaseFTException(e) [pointers, TYPE]
78
!>
79
!>###Setting the infoDictionary
80
!>
81
!>        CALL e  %  setInfoDictionary(infoDictionary)
82
!>###Getting the infoDictionary
83
!>
84
!>        dict => e % infoDictionary
85
!>###Getting the name of the exception
86
!>
87
!>        name = e % exceptionName()
88
!>###Getting the severity level of the exception
89
!>
90
!>        level = e % severity()
91
!> Severity levels are FT_ERROR_WARNING or FT_ERROR_FATAL
92
!>###Printing the exception
93
!>
94
!>        CALL e % printDescription()
95
!>
96
!
97
!////////////////////////////////////////////////////////////////////////
98
!
99
      Module FTExceptionClass
100
      USE FTStackClass
101
      USE FTDictionaryClass
102
      USE FTValueDictionaryClass
103
      USE FTLinkedListIteratorClass
104
      IMPLICIT NONE
105
!
106
!     ----------------
107
!     Global constants
108
!     ----------------
109
!
110
      INTEGER, PARAMETER :: FT_ERROR_NONE = 0, FT_ERROR_WARNING = 1, FT_ERROR_FATAL = 2
111
      INTEGER, PARAMETER :: ERROR_MSG_STRING_LENGTH = 132
112
      
113
      CHARACTER(LEN=21), PARAMETER :: FTFatalErrorException       = "FTFatalErrorException"
114
      CHARACTER(LEN=23), PARAMETER :: FTWarningErrorException     = "FTWarningErrorException"
115
      CHARACTER(LEN=27), PARAMETER :: FTAssertionFailureException = "FTAssertionFailureException"
116
!
117
!     ---------------
118
!     Error base type
119
!     ---------------
120
!
121
      TYPE, EXTENDS(FTObject) :: FTException
122
         INTEGER, PRIVATE                                :: severity_
123
         CHARACTER(LEN=ERROR_MSG_STRING_LENGTH), PRIVATE :: exceptionName_
124
         CLASS(FTDictionary), POINTER, PRIVATE           :: infoDictionary_ => NULL()
125
!
126
!        --------         
127
         CONTAINS
128
!        --------         
129
!
130
         PROCEDURE :: initFTException
131
         PROCEDURE :: initWarningException
132
         PROCEDURE :: initFatalException
133
         PROCEDURE :: initAssertionFailureException
134
         FINAL     :: destructException
135
         PROCEDURE :: setInfoDictionary
136
         PROCEDURE :: infoDictionary
137
         PROCEDURE :: exceptionName
138
         PROCEDURE :: severity
139
         PROCEDURE :: printDescription => printFTExceptionDescription
140
         PROCEDURE :: className => exceptionClassName
141
      END TYPE FTException
142
            
143
      INTERFACE cast
144
         MODULE PROCEDURE castToException
145
      END INTERFACE cast
146
!
147
!     ========      
148
      CONTAINS
149
!     ========
150
!
151
!//////////////////////////////////////////////////////////////////////// 
152
! 
153
      SUBROUTINE initWarningException(self,msg)  
1✔
154
!
155
! ---------------------------------------------
156
!>A convenience initializer for a warning error 
157
!>that includes the key "message" in the
158
!>infoDictionary. Use this initializer as an 
159
!>example of how to write one's own exception.
160
! --------------------------------------------
161
!
162
         IMPLICIT NONE
163
         CLASS(FTException)                     :: self
164
         CHARACTER(LEN=*)                       :: msg
165
         
166
         CLASS(FTValueDictionary), POINTER :: userDictionary => NULL()
167
         CLASS(FTDictionary)     , POINTER :: dictPtr        => NULL()
168
            
169
         ALLOCATE(userDictionary)
1✔
170
         CALL userDictionary % initWithSize(64)
1✔
171
         CALL userDictionary % addValueForKey(msg,"message")
1✔
172
         
173
         dictPtr => userDictionary
1✔
174
         CALL self % initFTException(severity       = FT_ERROR_WARNING,&
175
                                     exceptionName  = FTWarningErrorException,&
176
                                     infoDictionary = dictPtr)
1✔
177
         CALL releaseMemberDictionary(self)
1✔
178
         
179
      END SUBROUTINE initWarningException
1✔
180
!
181
!//////////////////////////////////////////////////////////////////////// 
182
! 
183
      SUBROUTINE initFatalException(self,msg)  
1✔
184
!
185
! ---------------------------------------------
186
!>A convenience initializer for a fatal error 
187
!>that includes the key "message" in the
188
!>infoDictionary.Use this initializer as an 
189
!>example of how to write one's own exception.
190
! --------------------------------------------
191
!
192
         IMPLICIT NONE
193
         CLASS(FTException)                     :: self
194
         CHARACTER(LEN=*)                       :: msg
195
         
196
         CLASS(FTValueDictionary), POINTER :: userDictionary => NULL()
197
         CLASS(FTDictionary)     , POINTER :: dictPtr        => NULL()
198
            
199
         ALLOCATE(userDictionary)
1✔
200
         CALL userDictionary % initWithSize(8)
1✔
201
         CALL userDictionary % addValueForKey(msg,"message")
1✔
202
         
203
         dictPtr => userDictionary
1✔
204
         CALL self % initFTException(severity       = FT_ERROR_FATAL,&
205
                                     exceptionName  = FTFatalErrorException,&
206
                                     infoDictionary = dictPtr)
1✔
207
         
208
         CALL releaseMemberDictionary(self)
1✔
209
         
210
      END SUBROUTINE initFatalException
1✔
211
!
212
!//////////////////////////////////////////////////////////////////////// 
213
! 
214
      SUBROUTINE initFTException(self,severity,exceptionName,infoDictionary)
4✔
215
!
216
! -----------------------------------
217
!>The main initializer for the class 
218
! -----------------------------------
219
!
220
         IMPLICIT NONE
221
         CLASS(FTException)                     :: self
222
         INTEGER                                :: severity
223
         CHARACTER(LEN=*)                       :: exceptionName
224
         CLASS(FTDictionary), POINTER, OPTIONAL :: infoDictionary
225
         
226
         CALL self  %  FTObject  %  init()
4✔
227
         
228
         self  %  severity_        = severity
4✔
229
         self  %  exceptionName_   = exceptionName
4✔
230
         self  %  infoDictionary_  => NULL()
4✔
231
         IF(PRESENT(infoDictionary) .AND. ASSOCIATED(infoDictionary))   THEN 
4✔
232
            CALL self % setInfoDictionary(infoDictionary)
4✔
233
         END IF 
234
         
235
      END SUBROUTINE initFTException
4✔
236
!
237
!//////////////////////////////////////////////////////////////////////// 
238
! 
239
      SUBROUTINE initAssertionFailureException(self,msg,expectedValueObject,observedValueObject,level)
1✔
240
!
241
! ------------------------------------------------
242
!>A convenience initializer for an assertion error 
243
!>that includes the keys:
244
!>
245
!>-"message"
246
!>-"expectedValue"
247
!>-"observedValue"
248
!>
249
!>in the infoDictionary
250
!
251
! ------------------------------------------------
252
!
253
         IMPLICIT NONE
254
         CLASS(FTException)      :: self
255
         CLASS(FTValue), POINTER :: expectedValueObject, ObservedValueObject
256
         INTEGER                 :: level
257
         CHARACTER(LEN=*)        :: msg
258
         
259
         CLASS(FTValueDictionary), POINTER :: userDictionary => NULL()
260
         CLASS(FTDictionary)     , POINTER :: dictPtr        => NULL()
261
         CLASS(FTObject)         , POINTER :: objectPtr      => NULL()
262
            
263
         ALLOCATE(userDictionary)
1✔
264
         CALL userDictionary % initWithSize(8)
1✔
265
         CALL userDictionary % addValueForKey(msg,"message")
1✔
266
         objectPtr => expectedValueObject
1✔
267
         CALL userDictionary % addObjectForKey(object = objectPtr,key = "expectedValue")
1✔
268
         objectPtr => ObservedValueObject
1✔
269
         CALL userDictionary % addObjectForKey(object = objectPtr,key = "observedValue")
1✔
270
         
271
         dictPtr => userDictionary
1✔
272
         CALL self % initFTException(severity       = level,&
273
                                     exceptionName  = FTAssertionFailureException,&
274
                                     infoDictionary = dictPtr)
1✔
275
         
276
         CALL releaseMemberDictionary(self)
1✔
277
         
278
      END SUBROUTINE initAssertionFailureException
1✔
279
!
280
!//////////////////////////////////////////////////////////////////////// 
281
! 
282
      SUBROUTINE releaseFTExceptionClass(self)  
4✔
283
         IMPLICIT NONE
284
         CLASS(FTException) , POINTER :: self
285
         CLASS(FTObject)    , POINTER :: obj
286
         
287
         IF(.NOT. ASSOCIATED(self)) RETURN
4✔
288
         
289
         obj => self
4✔
290
         CALL release(obj) 
4✔
291
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
4✔
292
      END SUBROUTINE releaseFTExceptionClass
293
!
294
!//////////////////////////////////////////////////////////////////////// 
295
! 
296
      SUBROUTINE releaseFTException(self)  
1✔
297
         IMPLICIT NONE
298
         TYPE(FTException)  , POINTER :: self
299
         CLASS(FTObject)    , POINTER :: obj
300
         
301
         IF(.NOT. ASSOCIATED(self)) RETURN
1✔
302
         
303
         obj => self
1✔
304
         CALL release(obj) 
1✔
305
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
1✔
306
      END SUBROUTINE releaseFTException
307
!
308
!//////////////////////////////////////////////////////////////////////// 
309
! 
310
      SUBROUTINE destructException(self)
4✔
311
!
312
! -------------------------------------------------------------
313
!>The destructor for the class. Do not call this directly. Call
314
!>the release() procedure instead
315
! -------------------------------------------------------------
316
!
317

318
         IMPLICIT NONE  
319
         TYPE(FTException)       :: self
320

321
         CALL releaseMemberDictionary(self)
4✔
322
         
323
      END SUBROUTINE destructException 
4✔
324
!
325
!//////////////////////////////////////////////////////////////////////// 
326
! 
327
      SUBROUTINE setInfoDictionary( self, dict )  
4✔
328
!
329
! ---------------------------------------------
330
!>Sets and retains the exception infoDictionary
331
! ---------------------------------------------
332
!
333
         IMPLICIT NONE
334
         CLASS(FTException)           :: self
335
         CLASS(FTDictionary), POINTER :: dict
336
         
337
         IF(ASSOCIATED(self % infoDictionary_)) CALL releaseMemberDictionary(self)
4✔
338
         self  %  infoDictionary_ => dict
4✔
339
         CALL self  %  infoDictionary_  %  retain()
4✔
340
      END SUBROUTINE setInfoDictionary
4✔
341
!
342
!//////////////////////////////////////////////////////////////////////// 
343
! 
344
      SUBROUTINE releaseMemberDictionary(self)  
7✔
345
         IMPLICIT NONE  
346
         CLASS(FTException)       :: self
347
         CLASS(FTObject), POINTER :: obj
348
         
349
         IF(ASSOCIATED(self % infoDictionary_))   THEN
7✔
350
            obj => self % infoDictionary_
7✔
351
            CALL releaseFTObject(self = obj)
7✔
352
            IF(.NOT. ASSOCIATED(obj)) self% infoDictionary_ => NULL()
7✔
353
         END IF
354
      END SUBROUTINE releaseMemberDictionary
7✔
355
!
356
!//////////////////////////////////////////////////////////////////////// 
357
! 
358
     FUNCTION infoDictionary(self)
4✔
359
!
360
! ---------------------------------------------
361
!>Returns the exception's infoDictionary. Does
362
!>not transfer ownership/reference count is 
363
!>unchanged.
364
! ---------------------------------------------
365
!
366
        IMPLICIT NONE  
367
        CLASS(FTException) :: self
368
        CLASS(FTDictionary), POINTER :: infoDictionary
369
        
370
        infoDictionary => self % infoDictionary_
4✔
371
        
372
     END FUNCTION infoDictionary
4✔
373
!
374
!//////////////////////////////////////////////////////////////////////// 
375
! 
376
     FUNCTION exceptionName(self)  
6✔
377
!
378
! ---------------------------------------------
379
!>Returns the string representing the name set
380
!>for the exception.
381
! ---------------------------------------------
382
!
383
        IMPLICIT NONE  
384
        CLASS(FTException) :: self
385
        CHARACTER(LEN=ERROR_MSG_STRING_LENGTH) :: exceptionName
386
        exceptionName = self % exceptionName_
6✔
387
     END FUNCTION exceptionName
6✔
388
!
389
!//////////////////////////////////////////////////////////////////////// 
390
! 
391
     INTEGER FUNCTION severity(self)  
8✔
392
!
393
! ---------------------------------------------
394
!>Returns the severity level of the exception.
395
! ---------------------------------------------
396
!
397
        IMPLICIT NONE  
398
        CLASS(FTException) :: self
399
        severity = self % severity_
8✔
400
     END FUNCTION severity    
8✔
401
!
402
!//////////////////////////////////////////////////////////////////////// 
403
! 
404
     SUBROUTINE printFTExceptionDescription(self,iUnit)  
2✔
405
!
406
! ----------------------------------------------
407
!>A basic printing of the exception and the info
408
!>held in the infoDictionary.
409
! ----------------------------------------------
410
!
411
        IMPLICIT NONE  
412
        CLASS(FTException) :: self
413
        INTEGER            :: iUnit
414
        
415
        CLASS(FTDictionary), POINTER :: dict => NULL()
416
        
417
!        WRITE(iUnit,*) "-------------"
418
        WRITE(iUnit,*) " "
2✔
419
        WRITE(iUnit,*) "Exception Named: ", TRIM(self  %  exceptionName())
2✔
420
        dict => self % infoDictionary()
2✔
421
        IF(ASSOCIATED(dict)) CALL dict % printDescription(iUnit)
2✔
422
        
423
     END SUBROUTINE printFTExceptionDescription     
2✔
424
!
425
!//////////////////////////////////////////////////////////////////////// 
426
! 
427
      SUBROUTINE castToException(obj,cast) 
9✔
428
!
429
! -----------------------------------------------------
430
!>Cast the base class FTObject to the FTException class
431
! -----------------------------------------------------
432
!
433
         IMPLICIT NONE  
434
         CLASS(FTObject)   , POINTER :: obj
435
         CLASS(FTException), POINTER :: cast
436
         
437
         cast => NULL()
9✔
438
         SELECT TYPE (e => obj)
439
            TYPE is (FTException)
440
               cast => e
9✔
441
            CLASS DEFAULT
442
               
443
         END SELECT
444
         
445
      END SUBROUTINE castToException
9✔
446
!
447
!//////////////////////////////////////////////////////////////////////// 
448
! 
449
      FUNCTION exceptionFromObject(obj) RESULT(cast)
1✔
450
!
451
!     -----------------------------------------------------
452
!     Cast the base class FTObject to the FTException class
453
!     -----------------------------------------------------
454
!
455
         IMPLICIT NONE  
456
         CLASS(FTObject)   , POINTER :: obj
457
         CLASS(FTException), POINTER :: cast
458
         
459
         cast => NULL()
1✔
460
         SELECT TYPE (e => obj)
461
            TYPE is (FTException)
462
               cast => e
1✔
463
            CLASS DEFAULT
464
               
465
         END SELECT
466
         
467
      END FUNCTION exceptionFromObject
1✔
468
!
469
!//////////////////////////////////////////////////////////////////////// 
470
! 
471
!      -----------------------------------------------------------------
472
!> Class name returns a string with the name of the type of the object
473
!>
474
!>  ### Usage:
475
!>
476
!>        PRINT *,  obj % className()
477
!>        if( obj % className = "FTException")
478
!>
479
      FUNCTION exceptionClassName(self)  RESULT(s)
1✔
480
         IMPLICIT NONE  
481
         CLASS(FTException)                         :: self
482
         CHARACTER(LEN=CLASS_NAME_CHARACTER_LENGTH) :: s
483
         
484
         s = "FTException"
1✔
485
         IF( self % refCount() >= 0) CONTINUE  !Quiet unused variable warnings
1✔
486
 
487
      END FUNCTION exceptionClassName
1✔
488

489
      END Module FTExceptionClass
18✔
490
!
491
!//////////////////////////////////////////////////////////////////////// 
492
! 
493
!@mark -
494
     
495
      Module SharedExceptionManagerModule
496
!>
497
!>All exceptions are posted to the SharedExceptionManagerModule. 
498
!>
499
!>To use exceptions,first initialize it
500
!>        CALL initializeFTExceptions
501
!>From that point on, all exceptions will be posted there. Note that the
502
!>FTTestSuiteManager class will initialize the SharedExceptionManagerModule,
503
!>so there is no need to do the initialization separately if the FTTestSuiteManager
504
!>class has been initialized.
505
!>
506
!>The exceptions are posted to a stack. To access the exceptions they will be
507
!>peeked or popped from that stack.
508
!>
509
!>###Initialization
510
!>        CALL initializeFTExceptions
511
!>###Finalization
512
!>        CALL destructFTExceptions
513
!>###Throwing an exception
514
!>         CALL throw(exception)
515
!>###Getting the number of exceptions
516
!>         n = errorCount()
517
!>###Getting the maximum exception severity
518
!>         s = maximumErrorSeverity()
519
!>###Catching all exceptions
520
!>         IF(catch())     THEN
521
!>            Do something with the exceptions
522
!>         END IF
523
!>###Getting the named exception caught
524
!>         CLASS(FTException), POINTER :: e
525
!>         e => errorObject()
526
!>###Popping the top exception
527
!>         e => popLastException()
528
!>###Peeking the top exception
529
!>         e => peekLastException()
530
!>###Catching an exception with a given name
531
!>         IF(catch(name))   THEN
532
!>            !Do something with the exception, e.g.
533
!>            e              => errorObject()
534
!>            d              => e % infoDictionary()
535
!>            userDictionary => valueDictionaryFromDictionary(dict = d)
536
!>            msg = userDictionary % stringValueForKey("message")
537
!>         END IF
538
!>###Printing all exceptions
539
!>      call printAllExceptions
540
!>         
541
      USE FTExceptionClass
542
      IMPLICIT NONE  
543
!
544
!     --------------------
545
!     Global error stack  
546
!     --------------------
547
!
548
      TYPE(FTStack)    , POINTER, PRIVATE :: errorStack    => NULL()
549
      TYPE(FTException), POINTER, PRIVATE :: currentError_ => NULL()
550
      INTEGER                   , PRIVATE :: maxErrorLevel
551
      
552
      INTERFACE catch
553
         MODULE PROCEDURE catchAll
554
         MODULE PROCEDURE catchErrorWithName
555
      END INTERFACE catch
556
      
557
      PRIVATE :: catchAll, catchErrorWithName
558
!
559
!     ========      
560
      CONTAINS
561
!     ========
562
!
563
!
564
!//////////////////////////////////////////////////////////////////////// 
565
! 
566
      SUBROUTINE initializeFTExceptions
2✔
567
!
568
!>Called at start of execution. Will be called automatically if an 
569
!>exception is thrown.
570
!
571
         IMPLICIT NONE
572
         
573
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
2✔
574
            ALLOCATE(errorStack)
1✔
575
            CALL errorStack % init()
1✔
576
            currentError_ => NULL()
1✔
577
         END IF
578
         
579
         maxErrorLevel = FT_ERROR_NONE
2✔
580
         
581
      END SUBROUTINE initializeFTExceptions
2✔
582
!
583
!//////////////////////////////////////////////////////////////////////// 
584
! 
585
      SUBROUTINE destructFTExceptions
1✔
586
!
587
!>Called at the end of execution. This procedure will announce if there
588
!>are uncaught exceptions raised and print them.
589
!
590
         IMPLICIT NONE
591
         CLASS(FTObject), POINTER :: obj
592
!  
593
!        --------------------------------------------------
594
!        First see if there are any uncaught exceptions and
595
!        report them if there are.
596
!        --------------------------------------------------
597
!
598
         IF ( catch() )     THEN
1✔
599
           PRINT *
1✔
600
           PRINT *,"   ***********************************"
1✔
601
           IF(errorStack % COUNT() == 1)     THEN
1✔
602
              PRINT *, "   An uncaught exception was raised:"
×
603
           ELSE
604
              PRINT *, "   Uncaught exceptions were raised:"
1✔
605
           END IF
606
           PRINT *,"   ***********************************"
1✔
607
           PRINT *
1✔
608
           CALL printAllExceptions
1✔
609
         END IF 
610
!
611
!        -----------------------
612
!        Destruct the exceptions
613
!        -----------------------
614
!
615
          obj => errorStack
1✔
616
          CALL releaseFTObject(self = obj)
1✔
617
          IF(.NOT. ASSOCIATED(obj)) errorStack => NULL()
1✔
618
          CALL releaseCurrentError
1✔
619
        
620
      END SUBROUTINE destructFTExceptions
1✔
621
!
622
!//////////////////////////////////////////////////////////////////////// 
623
! 
624
      SUBROUTINE throw(exceptionToThrow)
1✔
625
!
626
!>Throws the exception: exceptionToThrow
627
!
628
         IMPLICIT NONE  
629
         TYPE (FTException), POINTER :: exceptionToThrow
630
         CLASS(FTObject)   , POINTER :: ptr => NULL()
631
         
632
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
1✔
633
            CALL initializeFTExceptions 
×
634
         END IF 
635
         
636
         ptr => exceptionToThrow
1✔
637
         CALL errorStack % push(ptr)
1✔
638
         
639
         maxErrorLevel = MAX(maxErrorLevel, exceptionToThrow % severity())
1✔
640
         
641
      END SUBROUTINE throw
1✔
642
!
643
!//////////////////////////////////////////////////////////////////////// 
644
! 
645
      SUBROUTINE throwClass(exceptionToThrow)
3✔
646
!
647
!>Throws the exception: exceptionToThrow
648
!
649
         IMPLICIT NONE  
650
         CLASS (FTException), POINTER :: exceptionToThrow
651
         CLASS(FTObject)    , POINTER :: ptr => NULL()
652
         
653
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
3✔
NEW
654
            CALL initializeFTExceptions 
×
655
         END IF 
656
         
657
         ptr => exceptionToThrow
3✔
658
         CALL errorStack % push(ptr)
3✔
659
         
660
         maxErrorLevel = MAX(maxErrorLevel, exceptionToThrow % severity())
3✔
661
         
662
      END SUBROUTINE throwClass
3✔
663
!
664
!//////////////////////////////////////////////////////////////////////// 
665
! 
666
      LOGICAL FUNCTION catchAll()
2✔
667
!
668
! -------------------------------------------
669
!>Returns .TRUE. if there are any exceptions.
670
! -------------------------------------------
671
!
672
         IMPLICIT NONE
673
         
674
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
2✔
675
            catchAll = .FALSE.
1✔
676
            RETURN 
1✔
677
         END IF 
678
         
679
         catchAll = .false.
1✔
680
         IF ( errorStack % count() > 0 )     THEN
1✔
681
            catchAll = .true.
1✔
682
         END IF
683
         CALL releaseCurrentError
1✔
684
         
685
      END FUNCTION catchAll
1✔
686
!
687
!//////////////////////////////////////////////////////////////////////// 
688
! 
689
      INTEGER FUNCTION errorCount()
1✔
690
!
691
! ------------------------------------------
692
!>Returns the number of exceptions that have 
693
!>been thrown.
694
! ------------------------------------------
695
!
696
         IMPLICIT NONE
697
                  
698
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
1✔
699
            CALL initializeFTExceptions 
×
700
         END IF 
701

702
         errorCount = errorStack % count() 
1✔
703
      END FUNCTION    
1✔
704
!
705
!//////////////////////////////////////////////////////////////////////// 
706
! 
707
      INTEGER FUNCTION maximumErrorSeverity()
1✔
708
!
709
! -----------------------------------------------
710
!>Returns the maxSeverity of exceptions that have 
711
!>been thrown.
712
! -----------------------------------------------
713
!
714
         IMPLICIT NONE
715
                  
716
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
1✔
717
            CALL initializeFTExceptions 
×
718
         END IF 
719

720
         maximumErrorSeverity = maxErrorLevel
1✔
721
          
722
      END FUNCTION maximumErrorSeverity
1✔
723
!
724
!//////////////////////////////////////////////////////////////////////// 
725
! 
726
      LOGICAL FUNCTION catchErrorWithName(exceptionName)
3✔
727
!
728
! --------------------------------------------
729
!>Returns .TRUE. if there is an exception with
730
!>the requested name. If so, it pops the 
731
!>exception and saves the pointer to it so that
732
!>it can be accessed with the currentError()
733
!>function.
734
! --------------------------------------------
735
!
736
     
737
         IMPLICIT NONE  
738
         CHARACTER(LEN=*) :: exceptionName
739
         
740
         TYPE(FTLinkedListIterator)   :: iterator
3✔
741
         CLASS(FTLinkedList), POINTER :: ptr => NULL()
742
         CLASS(FTObject)    , POINTER :: obj => NULL()
743
         CLASS(FTException) , POINTER :: e   => NULL()
744
         
745
         catchErrorWithName = .false.
3✔
746
                  
747
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
3✔
748
            CALL initializeFTExceptions 
1✔
749
            RETURN 
1✔
750
         END IF 
751
         
752
         IF ( errorStack % COUNT() == 0 )     THEN
2✔
753
            RETURN 
×
754
         END IF 
755

756
         ptr => errorStack
2✔
757
         CALL iterator % initWithFTLinkedListClass(ptr)
2✔
758
         CALL iterator % setToStart()
2✔
759
         
760
         DO WHILE (.NOT.iterator % isAtEnd())
5✔
761
            obj => iterator % object()
4✔
762
            CALL cast(obj,e)
4✔
763
            IF ( e % exceptionName() == exceptionName )     THEN
4✔
764
               CALL setCurrentError(e)
1✔
765
               catchErrorWithName = .true.
1✔
766
               CALL errorStack % remove(obj)
1✔
767
               EXIT
5✔
768
           END IF 
769
           CALL iterator % moveToNext()
3✔
770
         END DO
771
         
772
      END FUNCTION catchErrorWithName
6✔
773
!
774
!//////////////////////////////////////////////////////////////////////// 
775
! 
776
      FUNCTION errorObject()
1✔
777
!
778
! -------------------------------------------
779
!>Returns a pointer to the current exception.
780
! -------------------------------------------
781
!
782
         IMPLICIT NONE
783
         CLASS(FTException), POINTER :: errorObject
784
         
785
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
1✔
786
            CALL initializeFTExceptions 
×
787
         END IF 
788
         
789
         errorObject => currentError_
1✔
790
      END FUNCTION errorObject
1✔
791
!
792
!//////////////////////////////////////////////////////////////////////// 
793
! 
794
      SUBROUTINE setCurrentError(e)  
1✔
795
         IMPLICIT NONE  
796
         CLASS(FTException) , POINTER :: e
797
!
798
!        --------------------------------------------------------------
799
!        Check first to see if there is a current error. Since it
800
!        is retained, the current one must be released before resetting
801
!        the pointer.
802
!        --------------------------------------------------------------
803
!
804
         CALL releaseCurrentError
1✔
805
!
806
!        ------------------------------------
807
!        Set the pointer and retain ownership
808
!        ------------------------------------
809
!
810
         currentError_ => e
1✔
811
         CALL currentError_ % retain()
1✔
812
         
813
      END SUBROUTINE setCurrentError
1✔
814
!
815
!//////////////////////////////////////////////////////////////////////// 
816
! 
817
      FUNCTION popLastException()
1✔
818
!
819
! ----------------------------------------------------------------
820
!>Get the last exception posted. This is popped from the stack.
821
!>The caller is responsible for releasing the object after popping
822
! ----------------------------------------------------------------
823
!
824
         IMPLICIT NONE  
825
         CLASS(FTException), POINTER :: popLastException
826
         CLASS(FTObject)   , POINTER :: obj => NULL()
827
         
828
         obj => NULL()
1✔
829
         popLastException => NULL()
1✔
830
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
1✔
831
            CALL initializeFTExceptions 
×
832
         ELSE
833
            CALL errorStack % pop(obj)
1✔
834
            IF(ASSOCIATED(obj)) CALL cast(obj,popLastException)
1✔
835
         END IF 
836
         
837
      END FUNCTION popLastException
1✔
838
!
839
!//////////////////////////////////////////////////////////////////////// 
840
! 
841
      FUNCTION peekLastException()  
1✔
842
!
843
! ----------------------------------------------------------------
844
!>Get the last exception posted. This is NOT popped from the stack.
845
!>The caller does not own the object.
846
! ----------------------------------------------------------------
847
!
848
         IMPLICIT NONE  
849
         CLASS(FTException), POINTER :: peekLastException
850
         CLASS(FTObject)   , POINTER :: obj => NULL()
851
         
852
         IF ( .NOT.ASSOCIATED(errorStack) )     THEN
1✔
853
            CALL initializeFTExceptions 
×
854
         END IF 
855
         
856
         peekLastException => NULL()
1✔
857
         obj => errorStack % peek()
1✔
858
         CALL cast(obj,peekLastException)
1✔
859
         
860
      END FUNCTION peekLastException
1✔
861
!
862
!//////////////////////////////////////////////////////////////////////// 
863
! 
864
      SUBROUTINE printAllExceptions  
1✔
865
         IMPLICIT NONE  
866
         TYPE(FTLinkedListIterator)   :: iterator
1✔
867
         CLASS(FTLinkedList), POINTER :: list      => NULL()
868
         CLASS(FTObject)    , POINTER :: objectPtr => NULL()
869
         CLASS(FTException) , POINTER :: e         => NULL()
870
           
871
        list => errorStack
1✔
872
        CALL iterator % initWithFTLinkedListClass(list)
1✔
873
!
874
!       ----------------------------------------------------
875
!       Write out the descriptions of each of the exceptions
876
!       ----------------------------------------------------
877
!
878
        CALL iterator % setToStart
1✔
879
        DO WHILE (.NOT.iterator % isAtEnd())
3✔
880
            objectPtr => iterator % object()
2✔
881
            CALL cast(objectPtr,e)
2✔
882
            CALL e % printDescription(6)
2✔
883
            CALL iterator % moveToNext()
2✔
884
         END DO
885
            
886
      END SUBROUTINE printAllExceptions
1✔
887
!
888
!//////////////////////////////////////////////////////////////////////// 
889
! 
890
      SUBROUTINE releaseCurrentError
3✔
891
         IMPLICIT NONE
892
         CLASS(FTObject), POINTER :: obj
893
         
894
         IF ( ASSOCIATED(currentError_) )     THEN
3✔
895
           obj => currentError_
1✔
896
           CALL releaseFTObject(self = obj)
1✔
897
           IF(.NOT. ASSOCIATED(obj)) currentError_ => NULL()
1✔
898
         END IF 
899
 
900
      END SUBROUTINE releaseCurrentError
3✔
901

902
      END MODULE SharedExceptionManagerModule    
903
      
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc