Update stats in expected walls.srv output
[survex.git] / src / validate.c
blob45df86c65bea0d0e6e048da7cd5f0e8c9eb2fd4d
1 /* validate.c
3 * Checks that SURVEX's data structures are valid and consistent
5 * NB The checks currently done aren't very comprehensive - more will be
6 * added if bugs require them
8 * Copyright (C) 1993,1994,1996,2000,2001 Olly Betts
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <config.h>
27 #include "cavern.h"
28 #include "filename.h"
29 #include "message.h"
30 #include "netbits.h"
31 #include "validate.h"
33 /* maximum absolute value allowed for a coordinate of a fixed station */
34 #define MAX_POS 10000000.0
36 static bool validate_prefix_tree(void);
37 static bool validate_prefix_subtree(prefix *pfx);
39 static bool validate_station_list(void);
41 #if 0
42 extern void
43 check_fixed(void)
45 /* not a requirement -- we allow hanging sections of survey
46 * which get spotted and removed */
47 node *stn;
48 printf("*** Checking fixed-ness\n");
49 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
50 for (stn = stnlist; stn; stn = stn->next) {
51 if (stn->status && !fixed(stn)) {
52 printf("*** Station '");
53 print_prefix(stn->name);
54 printf("' has status %d but isn't fixed\n", stn->status);
58 #endif
60 #undef validate
61 extern bool
62 validate(void)
64 bool fOk = true;
65 if (!validate_prefix_tree()) fOk = false;
66 if (!validate_station_list()) fOk = false;
67 if (fOk) puts("*** Data structures passed consistency checks");
68 else puts("*** Data structures FAILED consistency checks");
69 return fOk;
72 static bool
73 validate_prefix_tree(void)
75 bool fOk = true;
76 if (root->up != NULL) {
77 printf("*** root->up == %p\n", root->up);
78 fOk = false;
80 if (root->right != NULL) {
81 printf("*** root->right == %p\n", root->right);
82 fOk = false;
84 if (root->stn != NULL) {
85 printf("*** root->stn == %p\n", root->stn);
86 fOk = false;
88 if (root->pos != NULL) {
89 printf("*** root->pos == %p\n", root->pos);
90 fOk = false;
92 fOk &= validate_prefix_subtree(root);
93 return fOk;
96 static bool
97 validate_prefix_subtree(prefix *pfx)
99 bool fOk = true;
100 prefix *pfx2;
101 pfx2 = pfx->down;
102 /* this happens now, as nodes are freed after solving */
103 #if 0
104 if (pfx2 == NULL) {
105 if (pfx->stn == NULL) {
106 printf("*** Leaf prefix '");
107 print_prefix(pfx);
108 printf("' has no station attached\n");
109 fOk = false;
111 return fOk;
113 #endif
115 while (pfx2 != NULL) {
116 if (pfx2->stn != NULL && pfx2->stn->name != pfx2) {
117 printf("*** Prefix '");
118 print_prefix(pfx2);
119 printf("' ->stn->name is '");
120 print_prefix(pfx2->stn->name);
121 printf("'\n");
122 fOk = false;
124 if (pfx2->up != pfx) {
125 printf("*** Prefix '");
126 print_prefix(pfx2);
127 printf("' ->up is '");
128 print_prefix(pfx);
129 printf("'\n");
130 fOk = false;
132 fOk &= validate_prefix_subtree(pfx2);
133 pfx2 = pfx2->right;
135 return fOk;
138 static bool
139 validate_station_list(void)
141 bool fOk = true;
142 node *stn, *stn2;
143 int d, d2;
145 SVX_ASSERT(!stnlist || !stnlist->prev);
146 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
147 for (stn = stnlist; stn; stn = stn->next) {
148 bool fGap = false;
149 #if 0
150 printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
151 #endif
152 SVX_ASSERT(stn->prev == NULL || stn->prev->next == stn);
153 SVX_ASSERT(stn->next == NULL || stn->next->prev == stn);
154 for (d = 0; d <= 2; d++) {
155 if (!stn->leg[d]) {
156 fGap = true;
157 } else {
158 if (fGap) {
159 printf("*** Station '");
160 print_prefix(stn->name);
161 printf("', leg %d is used, but an earlier leg isn't\n", d);
162 fOk = false;
164 stn2 = stn->leg[d]->l.to;
165 SVX_ASSERT(stn2);
166 #if 0
167 if (stn->status && !stn2->status) {
168 printf("*** Station '");
169 print_prefix(stn->name);
170 printf("' has status %d and connects to '", stn->status);
171 print_prefix(stn2->name);
172 printf("' which has status %d\n", stn2->status);
173 fOk = false;
175 #endif
176 d2 = reverse_leg_dirn(stn->leg[d]);
177 if (stn2->leg[d2] == NULL) {
178 /* fine iff stn is at the disconnected end of a fragment */
179 node *s;
180 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
181 for (s = stnlist; s; s = s->next) if (s == stn) break;
182 if (s) {
183 printf("*** Station '");
184 print_prefix(stn->name);
185 printf("', leg %d doesn't reciprocate from station '", d);
186 print_prefix(stn2->name);
187 printf("'\n");
188 fOk = false;
190 } else if (stn2->leg[d2]->l.to == NULL) {
191 printf("*** Station '");
192 print_prefix(stn2->name);
193 printf("' [%p], leg %d points to NULL\n", stn2, d2);
194 fOk = false;
195 } else if (stn2->leg[d2]->l.to!=stn) {
196 /* fine iff stn is at the disconnected end of a fragment */
197 node *s;
198 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
199 for (s = stnlist; s; s = s->next) if (s == stn) break;
200 if (s) {
201 printf("*** Station '");
202 print_prefix(stn->name);
203 printf("' [%p], leg %d reciprocates via station '", stn, d);
204 print_prefix(stn2->name);
205 printf("' to station '");
206 print_prefix(stn2->leg[d2]->l.to->name);
207 printf("'\n");
208 fOk = false;
210 } else if ((data_here(stn->leg[d]) != 0) ^
211 (data_here(stn2->leg[d2]) == 0)) {
212 printf("*** Station '");
213 print_prefix(stn->name);
214 printf("' [%p], leg %d reciprocates via station '", stn, d);
215 print_prefix(stn2->name);
216 if (data_here(stn->leg[d]))
217 printf("' - data on both legs\n");
218 else
219 printf("' - data on neither leg\n");
220 fOk = false;
222 if (data_here(stn->leg[d])) {
223 int i;
224 for (i = 0; i < 3; i++)
225 if (fabs(stn->leg[d]->d[i]) > MAX_POS) {
226 printf("*** Station '");
227 print_prefix(stn->name);
228 printf("', leg %d, d[%d] = %g\n",
229 d, i, (double)(stn->leg[d]->d[i]));
230 fOk = false;
235 if (fixed(stn)) {
236 if (fabs(POS(stn, 0)) > MAX_POS ||
237 fabs(POS(stn, 1)) > MAX_POS ||
238 fabs(POS(stn, 2)) > MAX_POS) {
239 printf("*** Station '");
240 print_prefix(stn->name);
241 printf("' fixed at coords (%f,%f,%f)\n",
242 POS(stn, 0), POS(stn, 1), POS(stn, 2) );
243 fOk = false;
249 return fOk;
252 #undef dump_node
253 extern void
254 dump_node(node *stn)
256 int d;
257 if (stn->name)
258 print_prefix(stn->name);
259 else
260 printf("<null>");
262 printf(" stn [%p] name (%p) colour %ld %sfixed\n",
263 stn, stn->name, stn->colour, fixed(stn) ? "" : "un");
265 for (d = 0; d <= 2; d++) {
266 if (stn->leg[d]) {
267 printf(" leg %d -> stn [%p] rev %d ", d, stn->leg[d]->l.to,
268 reverse_leg_dirn(stn->leg[d]));
269 print_prefix(stn->leg[d]->l.to->name);
270 putnl();
275 /* This doesn't cover removed stations - might be nice to have
276 * dump_entire_network() which iterates prefix tree */
277 #undef dump_network
278 extern void
279 dump_network(void)
281 node *stn;
282 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
283 for (stn = stnlist; stn; stn = stn->next) dump_node(stn);