1 /*
2  * Integer arithmetic evaluation, header file.
3  *
4  * (c) Thomas Pornin 2002
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. The name of the authors may not be used to endorse or promote
15  *    products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 
32 /*
33  * This arithmetic evaluator uses two files: this header file (arith.h)
34  * and the source file (arith.c). To use this code, the source file should
35  * be included from another .c file which defines some macros (see below).
36  * Then the functions defined in the arith.c file become available to the
37  * including source file. If those functions are defined with external
38  * linkage (that is, `ARITH_FUNCTION_HEADER' does not contain `static'),
39  * it is possible for other source files to use the arithmetic functions
40  * by including the arith.h header only. The source file which includes
41  * arith.c should *not* include arith.h.
42  *
43  * If the #include is for arith.h, the following macros should be
44  * defined:
45  *
46  * -- If the evaluator is supposed to use a native type:
47  *   NATIVE_SIGNED            the native signed integer type
48  *   NATIVE_UNSIGNED          the native unsigned integer type
49  *
50  * -- If the evaluator is supposed to use an emulated type:
51  *   SIMUL_ARITH_SUBTYPE      the native unsigned type used for the simulation
52  *   SIMUL_SUBTYPE_BITS       the native unsigned type size
53  *   SIMUL_NUMBITS            the emulated type size
54  *
55  * -- For both cases:
56  *   ARITH_TYPENAME           the central arithmetic type name
57  *   ARITH_FUNCTION_HEADER    the qualifiers to add to function definitions
58  *
59  * The presence (respectively absence) of the NATIVE_SIGNED macro triggers
60  * the use of the native type evaluator (respectively simulated type
61  * evaluator).
62  *
63  * If the #include is for arith.c, the macros for arith.h should be defined,
64  * and the following should be defined as well:
65  *
66  * -- If the evaluator is supposed to use a native type:
67  *   NATIVE_UNSIGNED_BITS     the native unsigned type size
68  *   NATIVE_SIGNED_MIN        the native signed minimum value
69  *   NATIVE_SIGNED_MAX        the native signed maximum value
70  * (the last two macros must evaluate to signed constant expressions)
71  *
72  * -- For both cases:
73  *   ARITH_WARNING(type)      code to perform on warning
74  *   ARITH_ERROR(type)        code to perform on error
75  *
76  * The macro ARITH_WARNING() and ARITH_ERROR() are invoked with a
77  * numerical argument which is one of the enumeration constants
78  * defined below (ARITH_EXCEP_*) that identifies the specific problem.
79  *
80  * If the #include is for arith.c, the macro ARITHMETIC_CHECKS may be
81  * defined. When this macro is defined, checks are performed so that all
82  * operation which would lead to undefined or implementation-defined
83  * behaviour are first reported through ARITH_WARNING(). Code is smaller
84  * and faster without these checks, of course. Regardless of the status
85  * of that macro, divisions by 0 and overflows on signed division are
86  * reported as errors through ARITH_ERROR().
87  *
88  */
89 
90 #ifndef ARITH_H__
91 #define ARITH_H__
92 
93 enum {
94 	/* Warnings */
95 	ARITH_EXCEP_CONV_O,    /* overflow on conversion */
96 	ARITH_EXCEP_NEG_O,     /* overflow on unary minus */
97 	ARITH_EXCEP_NOT_T,     /* trap representation on bitwise inversion */
98 	ARITH_EXCEP_PLUS_O,    /* overflow on addition */
99 	ARITH_EXCEP_PLUS_U,    /* underflow on addition */
100 	ARITH_EXCEP_MINUS_O,   /* overflow on subtraction */
101 	ARITH_EXCEP_MINUS_U,   /* underflow on subtraction */
102 	ARITH_EXCEP_AND_T,     /* trap representation on bitwise and */
103 	ARITH_EXCEP_XOR_T,     /* trap representation on bitwise xor */
104 	ARITH_EXCEP_OR_T,      /* trap representation on bitwise or */
105 	ARITH_EXCEP_LSH_W,     /* left shift by type width or more */
106 	ARITH_EXCEP_LSH_C,     /* left shift by negative count */
107 	ARITH_EXCEP_LSH_O,     /* overflow on left shift */
108 	ARITH_EXCEP_LSH_U,     /* underflow on left shift */
109 	ARITH_EXCEP_RSH_W,     /* right shift by type width or more */
110 	ARITH_EXCEP_RSH_C,     /* right shift by negative count */
111 	ARITH_EXCEP_RSH_N,     /* right shift of negative value */
112 	ARITH_EXCEP_STAR_O,    /* overflow on multiplication */
113 	ARITH_EXCEP_STAR_U,    /* underflow on multiplication */
114 
115 	/* Errors */
116 	ARITH_EXCEP_SLASH_D,   /* division by 0 */
117 	ARITH_EXCEP_SLASH_O,   /* overflow on division */
118 	ARITH_EXCEP_PCT_D,     /* division by 0 on modulus operator */
119 	ARITH_EXCEP_CONST_O    /* constant too large */
120 };
121 
122 #if !(defined pARI && defined aARI)
123 
124 #define pARI	void
125 #define pARI_
126 #define aARI
127 #define aARI_
128 
129 #define useARI	((void) 0)
130 
131 #else
132 
133 #define pARI_	pARI,
134 #define aARI_	aARI,
135 
136 #define useARI	((void) aARI)
137 
138 #endif
139 
140 #define arith_strc_(x, y)	x ## y
141 #define arith_strc(x, y)	arith_strc_(x, y)
142 
143 #define arith_u		arith_strc(u_, ARITH_TYPENAME)
144 #define arith_s		arith_strc(s_, ARITH_TYPENAME)
145 #define arith_op_u(op)	arith_strc(ARITH_TYPENAME, arith_strc(_u_, op))
146 #define arith_op_s(op)	arith_strc(ARITH_TYPENAME, arith_strc(_s_, op))
147 
148 #define ARITH_DECL_MONO_U_U(op)    ARITH_FUNCTION_HEADER arith_u \
149                                    arith_op_u(op)(pARI_ arith_u x)
150 #define ARITH_DECL_MONO_U_S(op)    ARITH_FUNCTION_HEADER arith_s \
151                                    arith_op_u(op)(pARI_ arith_u x)
152 #define ARITH_DECL_MONO_U_I(op)    ARITH_FUNCTION_HEADER int \
153                                    arith_op_u(op)(pARI_ arith_u x)
154 #define ARITH_DECL_MONO_U_L(op)    ARITH_FUNCTION_HEADER unsigned long \
155                                    arith_op_u(op)(pARI_ arith_u x)
156 #define ARITH_DECL_MONO_S_U(op)    ARITH_FUNCTION_HEADER arith_u \
157                                    arith_op_s(op)(pARI_ arith_s x)
158 #define ARITH_DECL_MONO_S_S(op)    ARITH_FUNCTION_HEADER arith_s \
159                                    arith_op_s(op)(pARI_ arith_s x)
160 #define ARITH_DECL_MONO_S_I(op)    ARITH_FUNCTION_HEADER int \
161                                    arith_op_s(op)(pARI_ arith_s x)
162 #define ARITH_DECL_MONO_S_L(op)    ARITH_FUNCTION_HEADER long \
163                                    arith_op_s(op)(pARI_ arith_s x)
164 #define ARITH_DECL_MONO_I_U(op)    ARITH_FUNCTION_HEADER arith_u \
165                                    arith_op_u(op)(pARI_ int x)
166 #define ARITH_DECL_MONO_L_U(op)    ARITH_FUNCTION_HEADER arith_u \
167                                    arith_op_u(op)(pARI_ unsigned long x)
168 #define ARITH_DECL_MONO_I_S(op)    ARITH_FUNCTION_HEADER arith_s \
169                                    arith_op_s(op)(pARI_ int x)
170 #define ARITH_DECL_MONO_L_S(op)    ARITH_FUNCTION_HEADER arith_s \
171                                    arith_op_s(op)(pARI_ long x)
172 #define ARITH_DECL_MONO_ST_US(op)  ARITH_FUNCTION_HEADER char *arith_op_u(op) \
173                                    (pARI_ char *c, arith_u *ru, arith_s *rs, int *sp)
174 
175 #define ARITH_DECL_BI_UU_U(op)     ARITH_FUNCTION_HEADER arith_u \
176                                    arith_op_u(op)(pARI_ arith_u x, arith_u y)
177 #define ARITH_DECL_BI_UI_U(op)     ARITH_FUNCTION_HEADER arith_u \
178                                    arith_op_u(op)(pARI_ arith_u x, int y)
179 #define ARITH_DECL_BI_UU_I(op)     ARITH_FUNCTION_HEADER int \
180                                    arith_op_u(op)(pARI_ arith_u x, arith_u y)
181 #define ARITH_DECL_BI_SS_S(op)     ARITH_FUNCTION_HEADER arith_s \
182                                    arith_op_s(op)(pARI_ arith_s x, arith_s y)
183 #define ARITH_DECL_BI_SI_S(op)     ARITH_FUNCTION_HEADER arith_s \
184                                    arith_op_s(op)(pARI_ arith_s x, int y)
185 #define ARITH_DECL_BI_SS_I(op)     ARITH_FUNCTION_HEADER int \
186                                    arith_op_s(op)(pARI_ arith_s x, arith_s y)
187 
188 #endif
189 
190 #ifdef NATIVE_SIGNED
191 
192 typedef NATIVE_SIGNED arith_s;
193 typedef NATIVE_UNSIGNED arith_u;
194 
195 #else
196 
197 #if SIMUL_NUMBITS > (2 * SIMUL_SUBTYPE_BITS)
198 #error Native subtype too small for arithmetic simulation.
199 #endif
200 
201 #define SIMUL_MSW_WIDTH   (SIMUL_NUMBITS / 2)
202 #define SIMUL_LSW_WIDTH   ((SIMUL_NUMBITS + 1) / 2)
203 
204 typedef struct {
205 	SIMUL_ARITH_SUBTYPE msw, lsw;
206 } arith_u, arith_s;
207 
208 #endif
209 
210 /* functions with the unsigned type */
211 
212 ARITH_DECL_MONO_S_U(to_u);
213 ARITH_DECL_MONO_I_U(fromint);
214 ARITH_DECL_MONO_L_U(fromulong);
215 ARITH_DECL_MONO_U_I(toint);
216 ARITH_DECL_MONO_U_L(toulong);
217 
218 ARITH_DECL_MONO_U_U(neg);
219 ARITH_DECL_MONO_U_U(not);
220 ARITH_DECL_MONO_U_I(lnot);
221 ARITH_DECL_MONO_U_I(lval);
222 
223 ARITH_DECL_BI_UU_U(plus);
224 ARITH_DECL_BI_UU_U(minus);
225 ARITH_DECL_BI_UI_U(lsh);
226 ARITH_DECL_BI_UI_U(rsh);
227 ARITH_DECL_BI_UU_I(lt);
228 ARITH_DECL_BI_UU_I(leq);
229 ARITH_DECL_BI_UU_I(gt);
230 ARITH_DECL_BI_UU_I(geq);
231 ARITH_DECL_BI_UU_I(same);
232 ARITH_DECL_BI_UU_I(neq);
233 ARITH_DECL_BI_UU_U(and);
234 ARITH_DECL_BI_UU_U(xor);
235 ARITH_DECL_BI_UU_U(or);
236 ARITH_DECL_BI_UU_U(star);
237 ARITH_DECL_BI_UU_U(slash);
238 ARITH_DECL_BI_UU_U(pct);
239 
240 /* functions with the signed type */
241 
242 ARITH_DECL_MONO_U_S(to_s);
243 ARITH_DECL_MONO_I_S(fromint);
244 ARITH_DECL_MONO_L_S(fromlong);
245 ARITH_DECL_MONO_S_I(toint);
246 ARITH_DECL_MONO_S_L(tolong);
247 
248 ARITH_DECL_MONO_S_S(neg);
249 ARITH_DECL_MONO_S_S(not);
250 ARITH_DECL_MONO_S_I(lnot);
251 ARITH_DECL_MONO_S_I(lval);
252 
253 ARITH_DECL_BI_SS_S(plus);
254 ARITH_DECL_BI_SS_S(minus);
255 ARITH_DECL_BI_SI_S(lsh);
256 ARITH_DECL_BI_SI_S(rsh);
257 ARITH_DECL_BI_SS_I(lt);
258 ARITH_DECL_BI_SS_I(leq);
259 ARITH_DECL_BI_SS_I(gt);
260 ARITH_DECL_BI_SS_I(geq);
261 ARITH_DECL_BI_SS_I(same);
262 ARITH_DECL_BI_SS_I(neq);
263 ARITH_DECL_BI_SS_S(and);
264 ARITH_DECL_BI_SS_S(xor);
265 ARITH_DECL_BI_SS_S(or);
266 ARITH_DECL_BI_SS_S(star);
267 ARITH_DECL_BI_SS_S(slash);
268 ARITH_DECL_BI_SS_S(pct);
269 
270 /* conversions from string */
271 ARITH_DECL_MONO_ST_US(octconst);
272 ARITH_DECL_MONO_ST_US(hexconst);
273 ARITH_DECL_MONO_ST_US(decconst);
274