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