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
RevLine 
[421b7d2]1/* validate.c
[d1b1380]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 *
[bf9faf6]8 *   Copyright (C) 1993,1994,1996,2000,2001,2024 Olly Betts
[846746e]9 *
[89231c4]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.
[846746e]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
[89231c4]17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
[846746e]19 *
[89231c4]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
[ecbc6c18]22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[d1b1380]23 */
24
[4c83f84]25#include <config.h>
[d1b1380]26
[a420b49]27#include "cavern.h"
[c082b69]28#include "filename.h"
29#include "message.h"
[d1b1380]30#include "netbits.h"
31#include "validate.h"
32
33/* maximum absolute value allowed for a coordinate of a fixed station */
[577d6c1]34#define MAX_POS 10000000.0
[d1b1380]35
[a420b49]36static bool validate_prefix_tree(void);
37static bool validate_prefix_subtree(prefix *pfx);
[d1b1380]38
[a420b49]39static bool validate_station_list(void);
[d1b1380]40
[a420b49]41#undef validate
42extern bool
43validate(void)
44{
[63d4f07]45   bool fOk = true;
46   if (!validate_prefix_tree()) fOk = false;
47   if (!validate_station_list()) fOk = false;
[a420b49]48   if (fOk) puts("*** Data structures passed consistency checks");
[6d3f931]49   else puts("*** Data structures FAILED consistency checks");
[a420b49]50   return fOk;
51}
[d1b1380]52
[a420b49]53static bool
54validate_prefix_tree(void)
55{
[63d4f07]56   bool fOk = true;
[a420b49]57   if (root->up != NULL) {
58      printf("*** root->up == %p\n", root->up);
[63d4f07]59      fOk = false;
[a420b49]60   }
61   if (root->right != NULL) {
62      printf("*** root->right == %p\n", root->right);
[63d4f07]63      fOk = false;
[a420b49]64   }
65   if (root->stn != NULL) {
66      printf("*** root->stn == %p\n", root->stn);
[63d4f07]67      fOk = false;
[a420b49]68   }
69   if (root->pos != NULL) {
70      printf("*** root->pos == %p\n", root->pos);
[63d4f07]71      fOk = false;
[a420b49]72   }
73   fOk &= validate_prefix_subtree(root);
74   return fOk;
75}
[d1b1380]76
[a420b49]77static bool
78validate_prefix_subtree(prefix *pfx)
79{
[63d4f07]80   bool fOk = true;
[a420b49]81   prefix *pfx2;
82   pfx2 = pfx->down;
83   /* this happens now, as nodes are freed after solving */
[d1b1380]84#if 0
[a420b49]85   if (pfx2 == NULL) {
86      if (pfx->stn == NULL) {
87         printf("*** Leaf prefix '");
88         print_prefix(pfx);
89         printf("' has no station attached\n");
[63d4f07]90         fOk = false;
[a420b49]91      }
92      return fOk;
[d1b1380]93   }
94#endif
95
[a420b49]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");
[63d4f07]103         fOk = false;
[a420b49]104      }
105      if (pfx2->up != pfx) {
106         printf("*** Prefix '");
107         print_prefix(pfx2);
108         printf("' ->up is '");
109         print_prefix(pfx);
110         printf("'\n");
[63d4f07]111         fOk = false;
[a420b49]112      }
113      fOk &= validate_prefix_subtree(pfx2);
114      pfx2 = pfx2->right;
[d1b1380]115   }
[a420b49]116   return fOk;
117}
118
119static bool
120validate_station_list(void)
121{
[63d4f07]122   bool fOk = true;
[bf9faf6]123   node *stn2;
[a420b49]124   int d, d2;
125
[4c07c51]126   SVX_ASSERT(!stnlist || !stnlist->prev);
[6d3f931]127   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]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;
[095ef764]139#if 0
[bf9faf6]140         printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
[095ef764]141#endif
[bf9faf6]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) {
[a420b49]149                  printf("*** Station '");
150                  print_prefix(stn->name);
[bf9faf6]151                  printf("', leg %d is used, but an earlier leg isn't\n", d);
[63d4f07]152                  fOk = false;
[a420b49]153               }
[bf9faf6]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) {
[a420b49]172                  printf("*** Station '");
173                  print_prefix(stn2->name);
[bf9faf6]174                  printf("' [%p], leg %d points to NULL\n", stn2, d2);
[63d4f07]175                  fOk = false;
[bf9faf6]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) {
[a420b49]183                     printf("*** Station '");
184                     print_prefix(stn->name);
[bf9faf6]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");
[63d4f07]190                     fOk = false;
[a420b49]191                  }
[bf9faf6]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               }
[a420b49]215            }
216
[bf9faf6]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               }
[a420b49]227            }
228         }
[d1b1380]229      }
[a420b49]230   }
231   return fOk;
232}
233
234#undef dump_node
235extern void
236dump_node(node *stn)
237{
[f192c5c]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    }
[d1b1380]251
[f192c5c]252    printf(" colour %ld", stn->colour);
253    if (fixed(stn)) {
254        printf(" FIXED\n");
255    } else {
256        putnl();
257    }
[d1b1380]258
[f192c5c]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    }
[a420b49]273}
[d1b1380]274
[b6e9e7e]275/* This doesn't cover removed stations - might be nice to have
276 * dump_entire_network() which iterates prefix tree */
[cb3d1e2]277#undef dump_network
[a420b49]278extern void
279dump_network(void)
280{
281   node *stn;
[6d3f931]282   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]283   for (stn = fixedlist; stn; stn = stn->next) dump_node(stn);
[6d3f931]284   for (stn = stnlist; stn; stn = stn->next) dump_node(stn);
[a420b49]285}
Note: See TracBrowser for help on using the repository browser.