1 /*++
2
3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Exceptions.c
15
16 Abstract:
17
18 Exception logging routines.
19
20 --*/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h> // for memset()
25 #include "Exceptions.h"
26
27 //
28 // Max length of a saved exception message
29 //
30 #define MAX_EXCEPTION_MSG 200
31
32 //
33 // We use this structure to track exceptions thrown. We nest deeper on
34 // TryException() calls, and come back out on CatchException() calls.
35 // We save off the first exception message for a given exception level,
36 // but we save the count of how many were thrown.
37 //
38 typedef struct {
39 int ExceptionCount;
40 char ExceptionMsg[MAX_EXCEPTION_MSG];
41 } EXCEPTION_LOG;
42
43 static EXCEPTION_LOG ExceptionLog[MAX_EXCEPTION_NESTING + 1];
44 static int ExceptionLevel;
45
46 //
47 // Initialize our data and structures for tracking exceptions.
48 //
49 int
InitExceptions(VOID)50 InitExceptions (
51 VOID
52 )
53 {
54 ExceptionLevel = -1;
55 memset ((char *) &ExceptionLog, 0, sizeof (ExceptionLog));
56 return 0;
57 }
58 //
59 // This function replaces the _try() exception macro. It sets the
60 // nesting level.
61 //
62 int
TryException(VOID)63 TryException (
64 VOID
65 )
66 {
67 //
68 // Boost our exception level if we would not go out of range
69 //
70 ExceptionLevel++;
71 if (ExceptionLevel >= MAX_EXCEPTION_NESTING) {
72 fprintf (stderr, "ERROR: Max exception nesting level exceeded\n");
73 ExceptionLevel--;
74 return 1;
75 }
76
77 return 0;
78 }
79 //
80 // This function replaces the _catch() exception macro. It's used to decrement
81 // the nesting level and return any exeption error messages that were
82 // thrown at the current nesting level.
83 //
84 char *
CatchException(VOID)85 CatchException (
86 VOID
87 )
88 {
89 //
90 // Return a pointer to exception message. NULL if no exceptions at this level
91 //
92 if (ExceptionLevel >= 0) {
93 ExceptionLevel--;
94 if (ExceptionLog[ExceptionLevel + 1].ExceptionMsg[0]) {
95 return ExceptionLog[ExceptionLevel + 1].ExceptionMsg;
96 } else {
97 return NULL;
98 }
99 } else {
100 fprintf (stderr, "ERROR: Invalid nesting level call to CatchException()\n");
101 return NULL;
102 }
103 }
104 //
105 // This function can be used to test for exceptions between the TryException()
106 // and CatchException() calls in a given function.
107 //
108 int
ExceptionThrown(VOID)109 ExceptionThrown (
110 VOID
111 )
112 {
113 return ExceptionLog[ExceptionLevel].ExceptionCount;
114 }
115 //
116 // This function replaces the _throw() exception macro. It saves off the
117 // given error message at the current exeption level nesting.
118 //
119 int
ThrowException(char * Msg)120 ThrowException (
121 char *Msg
122 )
123 {
124 if (ExceptionLevel < 0) {
125 //
126 // fprintf (stderr, "ERROR: Exception thrown out of scope");
127 // Haven't yet enabled handling of exceptions, so just emit the message.
128 //
129 fprintf (stderr, Msg);
130 return 1;
131 }
132 //
133 // Only log the first
134 //
135 if (ExceptionLog[ExceptionLevel].ExceptionMsg[0] == 0) {
136 strncpy (ExceptionLog[ExceptionLevel].ExceptionMsg, Msg, MAX_EXCEPTION_MSG);
137 }
138
139 ExceptionLog[ExceptionLevel].ExceptionCount++;
140 return 0;
141 }
142