Open SCAP Library

assume.h
1
2 /*
3 * Copyright 2009 Red Hat Inc., Durham, North Carolina.
4 * All Rights Reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Authors:
21 * Lukas Kuklinek <lkuklinek@redhat.com>
22 */
23
24 #pragma once
25 #ifndef ASSUME_H
26 #define ASSUME_H
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include "util.h"
31
32 /*
33 * Note: the term "terminate" used in the following text means a call to abort()
34 * in the case the code was compiled without NDEBUG defined. The retval
35 * argument is ignored in that case. In the other case (NDEBUG is defined)
36 * terminate means that `return (retval)' is used instead of aborting the
37 * program. This is because we are in a library and taking down a program
38 * from inside a library function isn't safe.
39 * Unless ASSUME_VERBOSE is defined during compilation time, assume won't
40 * emit any messages to stderr. In debugging mode (i.e. when NDEBUG is
41 * undefined) the error message is always written to stderr.
42 *
43 * Usage:
44 *
45 * 1. assume(expr, retval)
46 *
47 * Check whether expr is true, terminate if not.
48 *
49 * 2. assume(expr, retval, f_branch)
50 *
51 * Check whether expr is true, execute f_branch if not and terminate. The break
52 * statement can be used to skip the termination.
53 *
54 * 3. assume(expr, retval, f_branch, t_branch)
55 *
56 * Check whether expr is true, execute f_branch if not and terminate. If expr
57 * is true, then execute t_branch.
58 *
59 */
60
61 #define __LB(l, ...) l
62 #define __RB(l, ...) __VA_ARGS__
63 #define __emitmsg_fp stderr
64
65 /*
66 * == Implementation note #1 ==
67 * We use ftrylockfile here because it's better to drop the message than to
68 * cause a deadlock.
69 */
70 #define __atomic_emitmsg(...) \
71 do { \
72 if (ftrylockfile(__emitmsg_fp) == 0) { \
73 fprintf (__emitmsg_fp, __VA_ARGS__); \
74 funlockfile(__emitmsg_fp); \
75 } \
76 } while (0)
77
78 #ifndef NDEBUG
79 # define __terminate(retval) abort()
80 # define __emitmsg(...) __atomic_emitmsg (__VA_ARGS__)
81 #else
82 # define __terminate(retval) return retval
83 # ifdef ASSUME_VERBOSE
84 # define __emitmsg(...) __atomic_emitmsg (__VA_ARGS__)
85 # else
86 # define __emitmsg(...) while(0)
87 # endif /* ASSUME_VERBOSE */
88 #endif /* NDEBUG */
89
90 #define __assume(expr, exprstr, retval, ...) \
91 do { \
92 if (!(expr)) { \
93 int OSCAP_CONCAT(__cont, __LINE__) = 1; \
94 __emitmsg ("%s:%d (%s): Assumption `%s' not fulfilled!\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, exprstr); \
95 do {__LB(__VA_ARGS__)} while((OSCAP_CONCAT(__cont, __LINE__) = 0)); \
96 if (OSCAP_CONCAT(__cont, __LINE__) == 0) __terminate(retval); \
97 } else { \
98 do {__RB(__VA_ARGS__)} while(0); \
99 } \
100 } while (0)
101
102 #if defined(__GNUC__)
103 # define assume(expr, retval, ...) __assume(__builtin_expect(expr, 1), #expr, retval, __VA_ARGS__)
104 #else
105 # define assume(expr, retval, ...) __assume(expr, #expr, retval, __VA_ARGS__)
106 #endif
107
111 #define assume_r(...) assume(__VA_ARGS__)
112
116 #ifndef NDEBUG
117 # define assume_d(...) assume(__VA_ARGS__)
118 #else
119 # define assume_d(...) while(0)
120 #endif
121
122 #ifndef NDEBUG
123 // Assume and always execute.
124 // In debug mode it asserts for return value
125 // Elsewhere it only executes the expression.
126 # define assume_ex(expr, retval, ...) assume(expr, retval, __VA_ARGS__)
127 #else
128 # define assume_ex(expr, retval, ...) expr
129 #endif
130
131
132 #endif /* ASSUME_H */