Show location for backsights out of tolerance
[survex.git] / src / validate.c
bloba6298047ad41a43db52d22570deab3df024ad0a7
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 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
29 #include "cavern.h"
30 #include "filename.h"
31 #include "message.h"
32 #include "netbits.h"
33 #include "validate.h"
35 /* maximum absolute value allowed for a coordinate of a fixed station */
36 #define MAX_POS 10000000.0
38 static bool validate_prefix_tree(void);
39 static bool validate_prefix_subtree(prefix *pfx);
41 static bool validate_station_list(void);
43 #if 0
44 extern void
45 check_fixed(void)
47 /* not a requirement -- we allow hanging sections of survey
48 * which get spotted and removed */
49 node *stn;
50 printf("*** Checking fixed-ness\n");
51 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
52 for (stn = stnlist; stn; stn = stn->next) {
53 if (stn->status && !fixed(stn)) {
54 printf("*** Station '");
55 print_prefix(stn->name);
56 printf("' has status %d but isn't fixed\n", stn->status);
60 #endif
62 #undef validate
63 extern bool
64 validate(void)
66 bool fOk = true;
67 if (!validate_prefix_tree()) fOk = false;
68 if (!validate_station_list()) fOk = false;
69 if (fOk) puts("*** Data structures passed consistency checks");
70 else puts("*** Data structures FAILED consistency checks");
71 return fOk;
74 static bool
75 validate_prefix_tree(void)
77 bool fOk = true;
78 if (root->up != NULL) {
79 printf("*** root->up == %p\n", root->up);
80 fOk = false;
82 if (root->right != NULL) {
83 printf("*** root->right == %p\n", root->right);
84 fOk = false;
86 if (root->stn != NULL) {
87 printf("*** root->stn == %p\n", root->stn);
88 fOk = false;
90 if (root->pos != NULL) {
91 printf("*** root->pos == %p\n", root->pos);
92 fOk = false;
94 fOk &= validate_prefix_subtree(root);
95 return fOk;
98 static bool
99 validate_prefix_subtree(prefix *pfx)
101 bool fOk = true;
102 prefix *pfx2;
103 pfx2 = pfx->down;
104 /* this happens now, as nodes are freed after solving */
105 #if 0
106 if (pfx2 == NULL) {
107 if (pfx->stn == NULL) {
108 printf("*** Leaf prefix '");
109 print_prefix(pfx);
110 printf("' has no station attached\n");
111 fOk = false;
113 return fOk;
115 #endif
117 while (pfx2 != NULL) {
118 if (pfx2->stn != NULL && pfx2->stn->name != pfx2) {
119 printf("*** Prefix '");
120 print_prefix(pfx2);
121 printf("' ->stn->name is '");
122 print_prefix(pfx2->stn->name);
123 printf("'\n");
124 fOk = false;
126 if (pfx2->up != pfx) {
127 printf("*** Prefix '");
128 print_prefix(pfx2);
129 printf("' ->up is '");
130 print_prefix(pfx);
131 printf("'\n");
132 fOk = false;
134 fOk &= validate_prefix_subtree(pfx2);
135 pfx2 = pfx2->right;
137 return fOk;
140 static bool
141 validate_station_list(void)
143 bool fOk = true;
144 node *stn, *stn2;
145 int d, d2;
147 SVX_ASSERT(!stnlist || !stnlist->prev);
148 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
149 for (stn = stnlist; stn; stn = stn->next) {
150 bool fGap = false;
151 #if 0
152 printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
153 #endif
154 SVX_ASSERT(stn->prev == NULL || stn->prev->next == stn);
155 SVX_ASSERT(stn->next == NULL || stn->next->prev == stn);
156 for (d = 0; d <= 2; d++) {
157 if (!stn->leg[d]) {
158 fGap = true;
159 } else {
160 if (fGap) {
161 printf("*** Station '");
162 print_prefix(stn->name);
163 printf("', leg %d is used, but an earlier leg isn't\n", d);
164 fOk = false;
166 stn2 = stn->leg[d]->l.to;
167 SVX_ASSERT(stn2);
168 #if 0
169 if (stn->status && !stn2->status) {
170 printf("*** Station '");
171 print_prefix(stn->name);
172 printf("' has status %d and connects to '", stn->status);
173 print_prefix(stn2->name);
174 printf("' which has status %d\n", stn2->status);
175 fOk = false;
177 #endif
178 d2 = reverse_leg_dirn(stn->leg[d]);
179 if (stn2->leg[d2] == NULL) {
180 /* fine iff stn is at the disconnected end of a fragment */
181 node *s;
182 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
183 for (s = stnlist; s; s = s->next) if (s == stn) break;
184 if (s) {
185 printf("*** Station '");
186 print_prefix(stn->name);
187 printf("', leg %d doesn't reciprocate from station '", d);
188 print_prefix(stn2->name);
189 printf("'\n");
190 fOk = false;
192 } else if (stn2->leg[d2]->l.to == NULL) {
193 printf("*** Station '");
194 print_prefix(stn2->name);
195 printf("' [%p], leg %d points to NULL\n", stn2, d2);
196 fOk = false;
197 } else if (stn2->leg[d2]->l.to!=stn) {
198 /* fine iff stn is at the disconnected end of a fragment */
199 node *s;
200 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
201 for (s = stnlist; s; s = s->next) if (s == stn) break;
202 if (s) {
203 printf("*** Station '");
204 print_prefix(stn->name);
205 printf("' [%p], leg %d reciprocates via station '", stn, d);
206 print_prefix(stn2->name);
207 printf("' to station '");
208 print_prefix(stn2->leg[d2]->l.to->name);
209 printf("'\n");
210 fOk = false;
212 } else if ((data_here(stn->leg[d]) != 0) ^
213 (data_here(stn2->leg[d2]) == 0)) {
214 printf("*** Station '");
215 print_prefix(stn->name);
216 printf("' [%p], leg %d reciprocates via station '", stn, d);
217 print_prefix(stn2->name);
218 if (data_here(stn->leg[d]))
219 printf("' - data on both legs\n");
220 else
221 printf("' - data on neither leg\n");
222 fOk = false;
224 if (data_here(stn->leg[d])) {
225 int i;
226 for (i = 0; i < 3; i++)
227 if (fabs(stn->leg[d]->d[i]) > MAX_POS) {
228 printf("*** Station '");
229 print_prefix(stn->name);
230 printf("', leg %d, d[%d] = %g\n",
231 d, i, (double)(stn->leg[d]->d[i]));
232 fOk = false;
237 if (fixed(stn)) {
238 if (fabs(POS(stn, 0)) > MAX_POS ||
239 fabs(POS(stn, 1)) > MAX_POS ||
240 fabs(POS(stn, 2)) > MAX_POS) {
241 printf("*** Station '");
242 print_prefix(stn->name);
243 printf("' fixed at coords (%f,%f,%f)\n",
244 POS(stn, 0), POS(stn, 1), POS(stn, 2) );
245 fOk = false;
251 return fOk;
254 #undef dump_node
255 extern void
256 dump_node(node *stn)
258 int d;
259 if (stn->name)
260 print_prefix(stn->name);
261 else
262 printf("<null>");
264 printf(" stn [%p] name (%p) colour %ld %sfixed\n",
265 stn, stn->name, stn->colour, fixed(stn) ? "" : "un");
267 for (d = 0; d <= 2; d++) {
268 if (stn->leg[d]) {
269 printf(" leg %d -> stn [%p] rev %d ", d, stn->leg[d]->l.to,
270 reverse_leg_dirn(stn->leg[d]));
271 print_prefix(stn->leg[d]->l.to->name);
272 putnl();
277 /* This doesn't cover removed stations - might be nice to have
278 * dump_entire_network() which iterates prefix tree */
279 #undef dump_network
280 extern void
281 dump_network(void)
283 node *stn;
284 /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
285 for (stn = stnlist; stn; stn = stn->next) dump_node(stn);