Open SCAP Library
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 */