1 /* debug.c -- Debugging support for Khepera
2 * Created: Fri Dec 23 10:53:10 1994 by faith@dict.org
3 * Copyright 1994-1997, 2002 Rickard E. Faith (faith@dict.org)
4 * Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * \section{Debugging Support}
26 *
27 * \intro These routines provide low-level support for run-time debugging
28 * messages. A set of global flags are maintained using "#define"
29 * statements. These flags are assumed to be 32-bit integers, the top two
30 * bits of which are used to select one of four sets of debugging lags.
31 * Each set, therefore, has 30 bits of flag information. The last set
32 * (i.e., when the top two bits are both set) is reserved for internal use
33 * by the \khepera library. For convenience, each flag can be given a
34 * unique name, so that flags can be set easily with command-line options.
35 *
36 */
37
38 #include "maaP.h"
39
40 #define TEST(flags,var) (((flags)>>31) \
41 ? (((flags)>>30) \
42 ? ((var[3] & (flags)) << 2) \
43 : ((var[2] & (flags)) << 2)) \
44 : (((flags)>>30) \
45 ? ((var[1] & (flags)) << 2) \
46 : ((var[0] & (flags)) << 2)))
47
48 static hsh_HashTable hash;
49 static dbg_Type setFlags[4];
50 static dbg_Type usedFlags[4];
51
52 /* |_dbg_exists| returns non-zero if |flag| has been associated with a name
53 (using the |_dbg_register| function). */
54
_dbg_exists(dbg_Type flag)55 static int _dbg_exists(dbg_Type flag)
56 {
57 return TEST(flag, usedFlags);
58 }
59
60 /* |_dbg_name| returns a pointer to the name that was associated with the
61 |flag|. */
62
_dbg_name(dbg_Type flag)63 static const char *_dbg_name(dbg_Type flag)
64 {
65 hsh_Position position;
66 void *key;
67 void *datum;
68
69 if (!hash) err_fatal(__func__, "No debugging names registered");
70 HSH_ITERATE(hash, position, key, datum) {
71 if (flag == (dbg_Type)datum) {
72 HSH_ITERATE_END(hash);
73 return key;
74 }
75 }
76
77 return "unknown flag";
78 }
79
80 /* |_dbg_register| is documented in the |dbg_register| section. */
81
_dbg_register(dbg_Type flag,const char * name)82 void _dbg_register(dbg_Type flag, const char *name)
83 {
84 dbg_Type tmp;
85
86 for (tmp = flag & 0x3fffffff; tmp && !(tmp & 1); tmp >>= 1);
87 if (!tmp || tmp >> 1)
88 err_fatal(__func__,
89 "Malformed flag (%lx):"
90 " a single low-order bit must be set",
91 flag);
92
93 if (!hash) hash = hsh_create(NULL, NULL);
94
95 if (_dbg_exists(flag))
96 err_fatal(__func__,
97 "The debug flag %lx has been used for \"%s\""
98 " and cannot be reused for \"%s\"",
99 flag,
100 _dbg_name(flag),
101 name);
102
103 hsh_insert(hash, name, (void *)flag);
104 }
105
106 /* \doc |dbg_register| is used to set up an asociated between a |flag| and
107 a |name|. After this association is made, calls to |dbg_set| can use
108 |name| to set the global debugging flag. Both of the high bits cannot
109 be set simultaneously---these flags are reserved for internal use by the
110 \khepera library.\footnote{For internal \khepera library use,
111 |_dbg_register| can be used to register flags which have both high bits
112 set.} */
113
dbg_register(dbg_Type flag,const char * name)114 void dbg_register(dbg_Type flag, const char *name)
115 {
116 /* These values are reserved for Khepera */
117 if ((flag & 0xc0000000) == 0xc0000000)
118 err_fatal(__func__,
119 "Flag (%lx) may not have both high-order bits set",
120 flag);
121
122 _dbg_register(flag, name);
123 }
124
125 /* \doc |dbg_set| sets the |name| flag. If |name| is ``none,'' then all
126 flags are cleared. */
127
dbg_set(const char * name)128 void dbg_set(const char *name)
129 {
130 dbg_Type flag;
131
132 if (!name) err_internal(__func__, "name is NULL");
133 if (!hash) err_fatal(__func__, "No debugging names registered");
134 if (!strcmp(name, "none")) {
135 setFlags[0] = setFlags[1] = setFlags[2] = setFlags[3] = 0;
136 return;
137 }
138 if (!strcmp(name, "all")) {
139 setFlags[0] = setFlags[1] = setFlags[2] = setFlags[3] = ~0;
140 return;
141 }
142
143 if (!(flag = (dbg_Type)hsh_retrieve(hash, name))) {
144 if (!(flag = (dbg_Type)hsh_retrieve(hash, name+1))
145 && *name != '-'
146 && *name != '+') {
147
148 fprintf(stderr, "Valid debugging flags are:\n");
149 dbg_list(stderr);
150 err_fatal(__func__,
151 "\"%s\" is not a valid debugging flag",
152 name);
153 } else {
154 if (*name == '+') setFlags[ flag >> 30 ] |= flag;
155 else setFlags[ flag >> 30 ] &= ~flag; /* - */
156 }
157 } else {
158 setFlags[ flag >> 30 ] |= flag;
159 }
160 }
161
162 /* \doc Used to set the flag using the predefined macro instead of the
163 string name. */
164
dbg_set_flag(dbg_Type flag)165 void dbg_set_flag(dbg_Type flag)
166 {
167 setFlags[ flag >> 30 ] |= flag;
168 }
169
170 /* \doc Used to unset the flag using the predefined macro instead of the
171 string name. */
172
dbg_unset_flag(dbg_Type flag)173 void dbg_unset_flag(dbg_Type flag)
174 {
175 setFlags[ flag >> 30 ] &= ~flag;
176 }
177
178 /* \doc This function tests the |flag|, returning non-zero if the
179 |flag| is set, and zero otherwise. */
180
dbg_test(dbg_Type flag)181 int dbg_test(dbg_Type flag)
182 {
183 return TEST(flag, setFlags);
184 }
185
186 /* \doc |dbg_destroy| destroys the memory associated with the debugging
187 support routines. This routine should \emph{never} be called by the
188 programmer: it is automatically called at program termination on systems
189 that support the |atexit| or |on_exit| calls. */
190
dbg_destroy(void)191 void dbg_destroy(void)
192 {
193 if (hash) hsh_destroy(hash);
194 hash = NULL;
195 setFlags[0] = setFlags[1] = setFlags[2] = setFlags[3] = 0;
196 usedFlags[0] = usedFlags[1] = usedFlags[2] = usedFlags[3] = 0;
197 }
198
199
_dbg_user(const void * key,const void * datum,void * arg)200 static int _dbg_user(const void *key, const void *datum, void *arg)
201 {
202 FILE *stream = (FILE *)arg;
203 dbg_Type flag = (dbg_Type)datum;
204
205 if ((flag & 0xc0000000) != 0xc0000000)
206 fprintf(stream, " %s\n", (char*) __UNCONST(key));
207 return 0;
208 }
209
_dbg_builtin(const void * key,const void * datum,void * arg)210 static int _dbg_builtin(const void *key, const void *datum, void *arg)
211 {
212 FILE *stream = (FILE *)arg;
213 dbg_Type flag = (dbg_Type)datum;
214
215 if ((flag & 0xc0000000) == 0xc0000000)
216 fprintf(stream, " %s (builtin)\n", (char*) __UNCONST(key));
217 return 0;
218 }
219
220 /* |dbg_list| lists all of the valid user-level debugging flags to the
221 specified |stream|. */
222
dbg_list(FILE * stream)223 void dbg_list(FILE *stream)
224 {
225 hsh_iterate_arg(hash, _dbg_user, stream);
226 hsh_iterate_arg(hash, _dbg_builtin, stream);
227 }
228