1 /****************************************************************************
2 **
3 ** This file is part of GAP, a system for computational discrete algebra.
4 **
5 ** Copyright of GAP belongs to its developers, whose names are too numerous
6 ** to list here. Please refer to the COPYRIGHT file for details.
7 **
8 ** SPDX-License-Identifier: GPL-2.0-or-later
9 **
10 ** This file declares functions for raising user errors and interacting
11 ** with the break loop.
12 **
13 */
14
15 #ifndef GAP_ERROR_H
16 #define GAP_ERROR_H
17
18 #include "system.h"
19 #include "intobj.h"
20
21 /****************************************************************************
22 **
23 *F RegisterBreakloopObserver( <func> )
24 **
25 ** Register a function which will be called when the break loop is entered
26 ** and left. Function should take a single Int argument which will be 1 when
27 ** break loop is entered, 0 when leaving.
28 **
29 ** Note that it is also possible to leave the break loop (or any GAP code)
30 ** by longjmping. This should be tracked with RegisterSyLongjmpObserver.
31 */
32
33 typedef void (*intfunc)(Int);
34
35 Int RegisterBreakloopObserver(intfunc func);
36
37 /****************************************************************************
38 **
39 *F OpenErrorOutput() . . . . . . . open the file or stream assigned to the
40 ** ERROR_OUTPUT global variable defined in
41 ** error.g, or "*errout*" otherwise
42 */
43 UInt OpenErrorOutput(void);
44
45 /****************************************************************************
46 **
47 *F ErrorQuit( <msg>, <arg1>, <arg2> ) . . . . . . . . . . . print and quit
48 */
49 void ErrorQuit(const Char * msg, Int arg1, Int arg2) NORETURN;
50
51 /****************************************************************************
52 **
53 *F ErrorMayQuit( <msg>, <arg1>, <arg2> ) . print, enter break loop and quit
54 ** no option to return anything.
55 */
56 void ErrorMayQuit(const Char * msg, Int arg1, Int arg2) NORETURN;
57
58
59 /****************************************************************************
60 **
61 *F ErrorMayQuitNrArgs( <narg>, <actual> ) . . . . wrong number of arguments
62 */
63 void ErrorMayQuitNrArgs(Int narg, Int actual) NORETURN;
64
65 /****************************************************************************
66 **
67 *F ErrorMayQuitNrAtLeastArgs( <narg>, <actual> ) . . . not enough arguments
68 */
69 void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) NORETURN;
70
71 /****************************************************************************
72 **
73 *F ErrorQuitRange3( <first>, <second>, <last> ) . . .divisibility rules
74 */
75 void ErrorQuitRange3(Obj first, Obj second, Obj last) NORETURN;
76
77
78 /****************************************************************************
79 **
80 *F ErrorReturnObj( <msg>, <arg1>, <arg2>, <msg2> ) . . print and return obj
81 */
82 Obj ErrorReturnObj(const Char * msg, Int arg1, Int arg2, const Char * msg2);
83
84
85 /****************************************************************************
86 **
87 *F ErrorReturnVoid( <msg>, <arg1>, <arg2>, <msg2> ) . . . print and return
88 */
89 void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2);
90
91
92 /****************************************************************************
93 **
94 *F RequireArgumentEx( <funcname>, <op>, <argname>, <msg>)
95 **
96 ** Raises an error via ErrorMayQuit with an error message of this form:
97 ** funcname: <argname> msg (not a %s)
98 ** Here, %s is replaced by a brief text which describes the type or content
99 ** of <op>.
100 **
101 ** If funcname is 0, then 'funcname: ' is omitted from the message.
102 ** If argname is 0, then '<argname> ' is omitted from the message.
103 */
104 Obj RequireArgumentEx(const char * funcname,
105 Obj op,
106 const char * argname,
107 const char * msg) NORETURN;
108
109 #define NICE_ARGNAME(op) "<" #op ">"
110
111 /****************************************************************************
112 **
113 *F RequireArgument
114 */
115 #define RequireArgument(funcname, op, msg) \
116 RequireArgumentEx(funcname, op, NICE_ARGNAME(op), msg)
117
118 /****************************************************************************
119 **
120 *F RequireArgumentConditionEx
121 */
122 #define RequireArgumentConditionEx(funcname, op, argname, cond, msg) \
123 do { \
124 if (!(cond)) { \
125 RequireArgumentEx(funcname, op, argname, msg); \
126 } \
127 } while (0)
128
129 /****************************************************************************
130 **
131 *F RequireArgumentCondition
132 */
133 #define RequireArgumentCondition(funcname, op, cond, msg) \
134 RequireArgumentConditionEx(funcname, op, NICE_ARGNAME(op), cond, msg)
135
136
137 /****************************************************************************
138 **
139 *F RequireInt
140 */
141 #define RequireInt(funcname, op) \
142 RequireArgumentCondition(funcname, op, IS_INT(op), "must be an integer")
143
144
145 /****************************************************************************
146 **
147 *F RequireSmallInt
148 */
149 #define RequireSmallInt(funcname, op, argname) \
150 RequireArgumentConditionEx(funcname, op, argname, IS_INTOBJ(op), \
151 "must be a small integer")
152
153
154 /****************************************************************************
155 **
156 *F RequirePositiveSmallInt
157 */
158 #define RequirePositiveSmallInt(funcname, op, argname) \
159 RequireArgumentConditionEx(funcname, op, argname, IS_POS_INTOBJ(op), \
160 "must be a positive small integer")
161
162
163 /****************************************************************************
164 **
165 *F RequireNonnegativeSmallInt
166 */
167 #define RequireNonnegativeSmallInt(funcname, op) \
168 RequireArgumentCondition(funcname, op, IS_NONNEG_INTOBJ(op), \
169 "must be a non-negative small integer")
170
171
172 /****************************************************************************
173 **
174 *F RequireSmallList
175 */
176 #define RequireSmallList(funcname, op) \
177 RequireArgumentCondition(funcname, op, IS_SMALL_LIST(op), \
178 "must be a small list")
179
180
181 /****************************************************************************
182 **
183 *F RequirePlainList
184 */
185 #define RequirePlainList(funcname, op) \
186 RequireArgumentCondition(funcname, op, IS_PLIST(op), \
187 "must be a plain list")
188
189
190 /****************************************************************************
191 **
192 *F RequireDenseList
193 */
194 #define RequireDenseList(funcname, op) \
195 RequireArgumentCondition(funcname, op, IS_DENSE_LIST(op), \
196 "must be a dense list")
197
198
199 /****************************************************************************
200 **
201 *F RequirePossList
202 */
203 #define RequirePossList(funcname, op) \
204 RequireArgumentCondition(funcname, op, IS_POSS_LIST(op), \
205 "must be a dense list of positive integers")
206
207
208 /****************************************************************************
209 **
210 *F RequireFunction
211 */
212 #define RequireFunction(funcname, op) \
213 RequireArgumentCondition(funcname, op, IS_FUNC(op), "must be a function")
214
215
216 /****************************************************************************
217 **
218 *F RequireStringRep
219 */
220 #define RequireStringRep(funcname, op) \
221 RequireArgumentCondition(funcname, op, IsStringConv(op), \
222 "must be a string")
223
224
225 /****************************************************************************
226 **
227 *F RequirePermutation
228 */
229 #define RequirePermutation(funcname, op) \
230 RequireArgumentCondition(funcname, op, IS_PERM(op), \
231 "must be a permutation")
232
233
234 /****************************************************************************
235 **
236 *F RequireTrueOrFalse
237 */
238 #define RequireTrueOrFalse(funcname, op) \
239 RequireArgumentCondition(funcname, op, op == True || op == False, \
240 "must be 'true' or 'false'")
241
242 /****************************************************************************
243 **
244 *F RequireMutable
245 */
246 #define RequireMutable(funcname, op, type) \
247 RequireArgumentCondition(funcname, op, IS_MUTABLE_OBJ(op), \
248 "must be a mutable " type)
249
250
251 /****************************************************************************
252 **
253 *F RequirePlainRec
254 */
255 #define RequirePlainRec(funcname, op) \
256 RequireArgumentCondition(funcname, op, IS_PREC(op), \
257 "must be a plain record")
258
259 /****************************************************************************
260 **
261 *F GetSmallIntEx, GetSmallInt
262 */
263 EXPORT_INLINE Int
GetSmallIntEx(const char * funcname,Obj op,const char * argname)264 GetSmallIntEx(const char * funcname, Obj op, const char * argname)
265 {
266 RequireSmallInt(funcname, op, argname);
267 return INT_INTOBJ(op);
268 }
269
270 #define GetSmallInt(funcname, op) \
271 GetSmallIntEx(funcname, op, NICE_ARGNAME(op))
272
273
274 /****************************************************************************
275 **
276 *F GetPositiveSmallIntEx, GetPositiveSmallInt
277 */
278 EXPORT_INLINE Int
GetPositiveSmallIntEx(const char * funcname,Obj op,const char * argname)279 GetPositiveSmallIntEx(const char * funcname, Obj op, const char * argname)
280 {
281 RequirePositiveSmallInt(funcname, op, argname);
282 return INT_INTOBJ(op);
283 }
284
285 #define GetPositiveSmallInt(funcname, op) \
286 GetPositiveSmallIntEx(funcname, op, NICE_ARGNAME(op))
287
288
289 /****************************************************************************
290 **
291 *F CheckIsPossList( <desc>, <poss> ) . . . . . . . . . . check for poss list
292 */
293 void CheckIsPossList(const Char * desc, Obj poss);
294
295
296 /****************************************************************************
297 **
298 *F CheckIsDenseList( <desc>, <listName>, <list> ) . . . check for dense list
299 */
300 void CheckIsDenseList(const Char * desc, const Char * listName, Obj list);
301
302
303 /****************************************************************************
304 **
305 *F CheckSameLength
306 */
307 void CheckSameLength(const Char * desc,
308 const Char * name1,
309 const Char * name2,
310 Obj op1,
311 Obj op2);
312
313
314 /****************************************************************************
315 **
316 *F RequireSameLength
317 **
318 ** This one is a bit different from the other Require functions, as it takes
319 ** two operands into account.
320 */
321 #define RequireSameLength(funcname, op1, op2) \
322 CheckSameLength(funcname, #op1, #op2, op1, op2)
323
324
325 /****************************************************************************
326 **
327 *F CALL_WITH_CATCH
328 */
329 Obj CALL_WITH_CATCH(Obj func, Obj args);
330
331
332 /****************************************************************************
333 **
334 *F AssertionFailure() . . . . . . . . . . . trigger a GAP assertion failure
335 **
336 ** This helper function is used by GAP's 'Assert' statement.
337 */
338 void AssertionFailure(void);
339
340
341 /****************************************************************************
342 **
343 *F * * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * *
344 */
345
346 /****************************************************************************
347 **
348 *F InitInfoError() . . . . . . . . . . . . . . . . . table of init functions
349 */
350 StructInitInfo * InitInfoError(void);
351
352
353 #endif // GAP_ERROR_H
354