1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* asserts.c */ |
4 | /* */ |
5 | /* Assertions for the ld65 linker */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2003-2011, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | /* common */ |
37 | #include "assertion.h" |
38 | #include "coll.h" |
39 | #include "xmalloc.h" |
40 | |
41 | /* ld65 */ |
42 | #include "asserts.h" |
43 | #include "error.h" |
44 | #include "expr.h" |
45 | #include "fileio.h" |
46 | #include "lineinfo.h" |
47 | #include "objdata.h" |
48 | #include "spool.h" |
49 | |
50 | |
51 | |
52 | /*****************************************************************************/ |
53 | /* Data */ |
54 | /*****************************************************************************/ |
55 | |
56 | |
57 | |
58 | /* Assertion struct decl */ |
59 | struct Assertion { |
60 | Collection LineInfos; /* File position of assertion */ |
61 | ExprNode* Expr; /* Expression to evaluate */ |
62 | AssertAction Action; /* What to do */ |
63 | unsigned Msg; /* Message to print */ |
64 | ObjData* Obj; /* Object file containing the assertion */ |
65 | }; |
66 | |
67 | /* List with all assertions */ |
68 | static Collection Assertions = STATIC_COLLECTION_INITIALIZER; |
69 | |
70 | |
71 | |
72 | /*****************************************************************************/ |
73 | /* Code */ |
74 | /*****************************************************************************/ |
75 | |
76 | |
77 | |
78 | Assertion* ReadAssertion (FILE* F, struct ObjData* O) |
79 | /* Read an assertion from the given file */ |
80 | { |
81 | /* Allocate memory */ |
82 | Assertion* A = xmalloc (sizeof (Assertion)); |
83 | |
84 | /* Read the fields from the file */ |
85 | A->LineInfos = EmptyCollection; |
86 | A->Expr = ReadExpr (F, O); |
87 | A->Action = (AssertAction) ReadVar (F); |
88 | A->Msg = MakeGlobalStringId (O, ReadVar (F)); |
89 | ReadLineInfoList (F, O, &A->LineInfos); |
90 | |
91 | /* Set remaining fields */ |
92 | A->Obj = O; |
93 | |
94 | /* Add the assertion to the global list */ |
95 | CollAppend (&Assertions, A); |
96 | |
97 | /* Return the new struct */ |
98 | return A; |
99 | } |
100 | |
101 | |
102 | |
103 | void CheckAssertions (void) |
104 | /* Check all assertions */ |
105 | { |
106 | unsigned I; |
107 | |
108 | /* Walk over all assertions */ |
109 | for (I = 0; I < CollCount (&Assertions); ++I) { |
110 | |
111 | const LineInfo* LI; |
112 | const char* Module; |
113 | unsigned Line; |
114 | |
115 | /* Get the assertion */ |
116 | Assertion* A = CollAtUnchecked (&Assertions, I); |
117 | |
118 | /* Ignore assertions that shouldn't be handled at link time */ |
119 | if (!AssertAtLinkTime (A->Action)) { |
120 | continue; |
121 | } |
122 | |
123 | /* Retrieve the relevant line info for this assertion */ |
124 | LI = CollConstAt (&A->LineInfos, 0); |
125 | |
126 | /* Get file name and line number from the source */ |
127 | Module = GetSourceName (LI); |
128 | Line = GetSourceLine (LI); |
129 | |
130 | /* If the expression is not constant, we're not able to handle it */ |
131 | if (!IsConstExpr (A->Expr)) { |
132 | Warning ("Cannot evaluate assertion in module '%s', line %u" , |
133 | Module, Line); |
134 | } else if (GetExprVal (A->Expr) == 0) { |
135 | |
136 | /* Assertion failed */ |
137 | const char* Message = GetString (A->Msg); |
138 | |
139 | switch (A->Action) { |
140 | |
141 | case ASSERT_ACT_WARN: |
142 | case ASSERT_ACT_LDWARN: |
143 | Warning ("%s(%u): %s" , Module, Line, Message); |
144 | break; |
145 | |
146 | case ASSERT_ACT_ERROR: |
147 | case ASSERT_ACT_LDERROR: |
148 | Error ("%s(%u): %s" , Module, Line, Message); |
149 | break; |
150 | |
151 | default: |
152 | Internal ("Invalid assertion action (%u) in module '%s', " |
153 | "line %u (file corrupt?)" , |
154 | A->Action, Module, Line); |
155 | break; |
156 | } |
157 | } |
158 | } |
159 | } |
160 | |