source: git/src/validate.c @ f192c5c

stereo-2025
Last change on this file since f192c5c was f192c5c, checked in by Olly Betts <olly@…>, 4 months ago

Improve dump_node() output

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/* validate.c
2 *
3 *   Checks that SURVEX's data structures are valid and consistent
4 *
5 *   NB The checks currently done aren't very comprehensive - more will be
6 *    added if bugs require them
7 *
8 *   Copyright (C) 1993,1994,1996,2000,2001,2024 Olly Betts
9 *
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.
14 *
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.
19 *
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
23 */
24
25#include <config.h>
26
27#include "cavern.h"
28#include "filename.h"
29#include "message.h"
30#include "netbits.h"
31#include "validate.h"
32
33/* maximum absolute value allowed for a coordinate of a fixed station */
34#define MAX_POS 10000000.0
35
36static bool validate_prefix_tree(void);
37static bool validate_prefix_subtree(prefix *pfx);
38
39static bool validate_station_list(void);
40
41#undef validate
42extern bool
43validate(void)
44{
45   bool fOk = true;
46   if (!validate_prefix_tree()) fOk = false;
47   if (!validate_station_list()) fOk = false;
48   if (fOk) puts("*** Data structures passed consistency checks");
49   else puts("*** Data structures FAILED consistency checks");
50   return fOk;
51}
52
53static bool
54validate_prefix_tree(void)
55{
56   bool fOk = true;
57   if (root->up != NULL) {
58      printf("*** root->up == %p\n", root->up);
59      fOk = false;
60   }
61   if (root->right != NULL) {
62      printf("*** root->right == %p\n", root->right);
63      fOk = false;
64   }
65   if (root->stn != NULL) {
66      printf("*** root->stn == %p\n", root->stn);
67      fOk = false;
68   }
69   if (root->pos != NULL) {
70      printf("*** root->pos == %p\n", root->pos);
71      fOk = false;
72   }
73   fOk &= validate_prefix_subtree(root);
74   return fOk;
75}
76
77static bool
78validate_prefix_subtree(prefix *pfx)
79{
80   bool fOk = true;
81   prefix *pfx2;
82   pfx2 = pfx->down;
83   /* this happens now, as nodes are freed after solving */
84#if 0
85   if (pfx2 == NULL) {
86      if (pfx->stn == NULL) {
87         printf("*** Leaf prefix '");
88         print_prefix(pfx);
89         printf("' has no station attached\n");
90         fOk = false;
91      }
92      return fOk;
93   }
94#endif
95
96   while (pfx2 != NULL) {
97      if (pfx2->stn != NULL && pfx2->stn->name != pfx2) {
98         printf("*** Prefix '");
99         print_prefix(pfx2);
100         printf("' ->stn->name is '");
101         print_prefix(pfx2->stn->name);
102         printf("'\n");
103         fOk = false;
104      }
105      if (pfx2->up != pfx) {
106         printf("*** Prefix '");
107         print_prefix(pfx2);
108         printf("' ->up is '");
109         print_prefix(pfx);
110         printf("'\n");
111         fOk = false;
112      }
113      fOk &= validate_prefix_subtree(pfx2);
114      pfx2 = pfx2->right;
115   }
116   return fOk;
117}
118
119static bool
120validate_station_list(void)
121{
122   bool fOk = true;
123   node *stn2;
124   int d, d2;
125
126   SVX_ASSERT(!stnlist || !stnlist->prev);
127   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
128   for (int fixed = 0; fixed < 2; ++fixed) {
129      for (node *stn = fixed ? fixedlist : stnlist; stn; stn = stn->next) {
130         if (fixed(stn) != fixed) {
131             printf("*** Station '");
132             print_prefix(stn->name);
133             printf("' is %sfixed but on %sfixed list\n",
134                    fixed ? "un" : "", fixed ? "" : "un");
135             fOk = false;
136         }
137
138         bool fGap = false;
139#if 0
140         printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
141#endif
142         SVX_ASSERT(stn->prev == NULL || stn->prev->next == stn);
143         SVX_ASSERT(stn->next == NULL || stn->next->prev == stn);
144         for (d = 0; d <= 2; d++) {
145            if (!stn->leg[d]) {
146               fGap = true;
147            } else {
148               if (fGap) {
149                  printf("*** Station '");
150                  print_prefix(stn->name);
151                  printf("', leg %d is used, but an earlier leg isn't\n", d);
152                  fOk = false;
153               }
154               stn2 = stn->leg[d]->l.to;
155               SVX_ASSERT(stn2);
156               d2 = reverse_leg_dirn(stn->leg[d]);
157               if (stn2->leg[d2] == NULL) {
158                  /* fine iff stn is at the disconnected end of a fragment */
159                  node *s;
160                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
161                  for (s = stnlist; s; s = s->next) if (s == stn) break;
162                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
163                  if (s) {
164                     printf("*** Station '");
165                     print_prefix(stn->name);
166                     printf("', leg %d doesn't reciprocate from station '", d);
167                     print_prefix(stn2->name);
168                     printf("'\n");
169                     fOk = false;
170                  }
171               } else if (stn2->leg[d2]->l.to == NULL) {
172                  printf("*** Station '");
173                  print_prefix(stn2->name);
174                  printf("' [%p], leg %d points to NULL\n", stn2, d2);
175                  fOk = false;
176               } else if (stn2->leg[d2]->l.to!=stn) {
177                  /* fine iff stn is at the disconnected end of a fragment */
178                  node *s;
179                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
180                  for (s = stnlist; s; s = s->next) if (s == stn) break;
181                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
182                  if (s) {
183                     printf("*** Station '");
184                     print_prefix(stn->name);
185                     printf("' [%p], leg %d reciprocates via station '", stn, d);
186                     print_prefix(stn2->name);
187                     printf("' to station '");
188                     print_prefix(stn2->leg[d2]->l.to->name);
189                     printf("'\n");
190                     fOk = false;
191                  }
192               } else if ((data_here(stn->leg[d]) != 0) ^
193                          (data_here(stn2->leg[d2]) == 0)) {
194                  printf("*** Station '");
195                  print_prefix(stn->name);
196                  printf("' [%p], leg %d reciprocates via station '", stn, d);
197                  print_prefix(stn2->name);
198                  if (data_here(stn->leg[d]))
199                     printf("' - data on both legs\n");
200                  else
201                     printf("' - data on neither leg\n");
202                  fOk = false;
203               }
204               if (data_here(stn->leg[d])) {
205                  int i;
206                  for (i = 0; i < 3; i++)
207                     if (fabs(stn->leg[d]->d[i]) > MAX_POS) {
208                        printf("*** Station '");
209                        print_prefix(stn->name);
210                        printf("', leg %d, d[%d] = %g\n",
211                               d, i, (double)(stn->leg[d]->d[i]));
212                        fOk = false;
213                     }
214               }
215            }
216
217            if (fixed(stn)) {
218               if (fabs(POS(stn, 0)) > MAX_POS ||
219                   fabs(POS(stn, 1)) > MAX_POS ||
220                   fabs(POS(stn, 2)) > MAX_POS) {
221                  printf("*** Station '");
222                  print_prefix(stn->name);
223                  printf("' fixed at coords (%f,%f,%f)\n",
224                         POS(stn, 0), POS(stn, 1), POS(stn, 2) );
225                  fOk = false;
226               }
227            }
228         }
229      }
230   }
231   return fOk;
232}
233
234#undef dump_node
235extern void
236dump_node(node *stn)
237{
238    printf("stn [%p]", stn);
239    if (stn->name) {
240        if (stn->name->stn == stn) {
241            printf("<->");
242        } else {
243            printf("-->");
244        }
245        printf("name ");
246        print_prefix(stn->name);
247        printf(" (%p)", stn->name);
248    } else {
249        printf("-->NULL");
250    }
251
252    printf(" colour %ld", stn->colour);
253    if (fixed(stn)) {
254        printf(" FIXED\n");
255    } else {
256        putnl();
257    }
258
259    for (int d = 0; d <= 2; d++) {
260        linkfor *leg = stn->leg[d];
261        if (leg) {
262            const char* type;
263            if (data_here(leg)) {
264                type = fZeros(&leg->v) ? "=>" : "->";
265            } else {
266                type = fZeros(&reverse_leg(leg)->v) ? "<=" : "<-";
267            }
268            printf("  leg #%d %s stn [%p] ", d, type, leg->l.to);
269            print_prefix(leg->l.to->name);
270            printf(" | rev %d\n", reverse_leg_dirn(leg));
271        }
272    }
273}
274
275/* This doesn't cover removed stations - might be nice to have
276 * dump_entire_network() which iterates prefix tree */
277#undef dump_network
278extern void
279dump_network(void)
280{
281   node *stn;
282   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
283   for (stn = fixedlist; stn; stn = stn->next) dump_node(stn);
284   for (stn = stnlist; stn; stn = stn->next) dump_node(stn);
285}
Note: See TracBrowser for help on using the repository browser.