source: git/src/validate.c @ 8a7804fb

Last change on this file since 8a7804fb was 0b99107, checked in by Olly Betts <olly@…>, 11 days ago

Eliminate old FSF addresses

Update GPL/LGPL licence files and boilerplate to direct people who
didn't receive the licence text to the FSF website, as the current
versions of the FSF licence texts now do, rather than giving a postal
address.

  • Property mode set to 100644
File size: 7.8 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
[0b99107]21 * along with this program; if not, see
22 * <https://www.gnu.org/licenses/>.
[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
[f498802]33/* Maximum absolute value of a coordinate of a fixed station for validate()
34 * to allow, in metres.
35 *
36 * The Northing of the equator in southern hemisphere UTM zones is 10000000m,
37 * which seems to be the largest coordinate in any common CRS.  We add an
38 * extra 100km to allow for extending such a zone North to cover a cave system
39 * which straddles the equator.
40 */
41#define MAX_POS 10100000.0
[d1b1380]42
[a420b49]43static bool validate_prefix_tree(void);
44static bool validate_prefix_subtree(prefix *pfx);
[d1b1380]45
[a420b49]46static bool validate_station_list(void);
[d1b1380]47
[a420b49]48#undef validate
49extern bool
50validate(void)
51{
[63d4f07]52   bool fOk = true;
53   if (!validate_prefix_tree()) fOk = false;
54   if (!validate_station_list()) fOk = false;
[a420b49]55   if (fOk) puts("*** Data structures passed consistency checks");
[6d3f931]56   else puts("*** Data structures FAILED consistency checks");
[a420b49]57   return fOk;
58}
[d1b1380]59
[a420b49]60static bool
61validate_prefix_tree(void)
62{
[63d4f07]63   bool fOk = true;
[a420b49]64   if (root->up != NULL) {
65      printf("*** root->up == %p\n", root->up);
[63d4f07]66      fOk = false;
[a420b49]67   }
68   if (root->right != NULL) {
69      printf("*** root->right == %p\n", root->right);
[63d4f07]70      fOk = false;
[a420b49]71   }
72   if (root->stn != NULL) {
73      printf("*** root->stn == %p\n", root->stn);
[63d4f07]74      fOk = false;
[a420b49]75   }
76   if (root->pos != NULL) {
77      printf("*** root->pos == %p\n", root->pos);
[63d4f07]78      fOk = false;
[a420b49]79   }
80   fOk &= validate_prefix_subtree(root);
81   return fOk;
82}
[d1b1380]83
[a420b49]84static bool
85validate_prefix_subtree(prefix *pfx)
86{
[63d4f07]87   bool fOk = true;
[a420b49]88   prefix *pfx2;
89   pfx2 = pfx->down;
90   /* this happens now, as nodes are freed after solving */
[d1b1380]91#if 0
[a420b49]92   if (pfx2 == NULL) {
93      if (pfx->stn == NULL) {
94         printf("*** Leaf prefix '");
95         print_prefix(pfx);
96         printf("' has no station attached\n");
[63d4f07]97         fOk = false;
[a420b49]98      }
99      return fOk;
[d1b1380]100   }
101#endif
102
[a420b49]103   while (pfx2 != NULL) {
104      if (pfx2->stn != NULL && pfx2->stn->name != pfx2) {
105         printf("*** Prefix '");
106         print_prefix(pfx2);
107         printf("' ->stn->name is '");
108         print_prefix(pfx2->stn->name);
109         printf("'\n");
[63d4f07]110         fOk = false;
[a420b49]111      }
112      if (pfx2->up != pfx) {
113         printf("*** Prefix '");
114         print_prefix(pfx2);
115         printf("' ->up is '");
116         print_prefix(pfx);
117         printf("'\n");
[63d4f07]118         fOk = false;
[a420b49]119      }
120      fOk &= validate_prefix_subtree(pfx2);
121      pfx2 = pfx2->right;
[d1b1380]122   }
[a420b49]123   return fOk;
124}
125
126static bool
127validate_station_list(void)
128{
[63d4f07]129   bool fOk = true;
[bf9faf6]130   node *stn2;
[a420b49]131   int d, d2;
132
[4c07c51]133   SVX_ASSERT(!stnlist || !stnlist->prev);
[6d3f931]134   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]135   for (int fixed = 0; fixed < 2; ++fixed) {
136      for (node *stn = fixed ? fixedlist : stnlist; stn; stn = stn->next) {
137         if (fixed(stn) != fixed) {
138             printf("*** Station '");
139             print_prefix(stn->name);
140             printf("' is %sfixed but on %sfixed list\n",
141                    fixed ? "un" : "", fixed ? "" : "un");
142             fOk = false;
143         }
144
145         bool fGap = false;
[095ef764]146#if 0
[bf9faf6]147         printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
[095ef764]148#endif
[bf9faf6]149         SVX_ASSERT(stn->prev == NULL || stn->prev->next == stn);
150         SVX_ASSERT(stn->next == NULL || stn->next->prev == stn);
151         for (d = 0; d <= 2; d++) {
152            if (!stn->leg[d]) {
153               fGap = true;
154            } else {
155               if (fGap) {
[a420b49]156                  printf("*** Station '");
157                  print_prefix(stn->name);
[bf9faf6]158                  printf("', leg %d is used, but an earlier leg isn't\n", d);
[63d4f07]159                  fOk = false;
[a420b49]160               }
[bf9faf6]161               stn2 = stn->leg[d]->l.to;
162               SVX_ASSERT(stn2);
163               d2 = reverse_leg_dirn(stn->leg[d]);
164               if (stn2->leg[d2] == NULL) {
165                  /* fine iff stn is at the disconnected end of a fragment */
166                  node *s;
167                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
168                  for (s = stnlist; s; s = s->next) if (s == stn) break;
169                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
170                  if (s) {
171                     printf("*** Station '");
172                     print_prefix(stn->name);
173                     printf("', leg %d doesn't reciprocate from station '", d);
174                     print_prefix(stn2->name);
175                     printf("'\n");
176                     fOk = false;
177                  }
178               } else if (stn2->leg[d2]->l.to == NULL) {
[a420b49]179                  printf("*** Station '");
180                  print_prefix(stn2->name);
[bf9faf6]181                  printf("' [%p], leg %d points to NULL\n", stn2, d2);
[63d4f07]182                  fOk = false;
[bf9faf6]183               } else if (stn2->leg[d2]->l.to!=stn) {
184                  /* fine iff stn is at the disconnected end of a fragment */
185                  node *s;
186                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
187                  for (s = stnlist; s; s = s->next) if (s == stn) break;
188                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
189                  if (s) {
[a420b49]190                     printf("*** Station '");
191                     print_prefix(stn->name);
[bf9faf6]192                     printf("' [%p], leg %d reciprocates via station '", stn, d);
193                     print_prefix(stn2->name);
194                     printf("' to station '");
195                     print_prefix(stn2->leg[d2]->l.to->name);
196                     printf("'\n");
[63d4f07]197                     fOk = false;
[a420b49]198                  }
[bf9faf6]199               } else if ((data_here(stn->leg[d]) != 0) ^
200                          (data_here(stn2->leg[d2]) == 0)) {
201                  printf("*** Station '");
202                  print_prefix(stn->name);
203                  printf("' [%p], leg %d reciprocates via station '", stn, d);
204                  print_prefix(stn2->name);
205                  if (data_here(stn->leg[d]))
206                     printf("' - data on both legs\n");
207                  else
208                     printf("' - data on neither leg\n");
209                  fOk = false;
210               }
211               if (data_here(stn->leg[d])) {
212                  int i;
213                  for (i = 0; i < 3; i++)
214                     if (fabs(stn->leg[d]->d[i]) > MAX_POS) {
215                        printf("*** Station '");
216                        print_prefix(stn->name);
217                        printf("', leg %d, d[%d] = %g\n",
218                               d, i, (double)(stn->leg[d]->d[i]));
219                        fOk = false;
220                     }
221               }
[a420b49]222            }
223
[bf9faf6]224            if (fixed(stn)) {
225               if (fabs(POS(stn, 0)) > MAX_POS ||
226                   fabs(POS(stn, 1)) > MAX_POS ||
227                   fabs(POS(stn, 2)) > MAX_POS) {
228                  printf("*** Station '");
229                  print_prefix(stn->name);
230                  printf("' fixed at coords (%f,%f,%f)\n",
231                         POS(stn, 0), POS(stn, 1), POS(stn, 2) );
232                  fOk = false;
233               }
[a420b49]234            }
235         }
[d1b1380]236      }
[a420b49]237   }
238   return fOk;
239}
240
241#undef dump_node
242extern void
243dump_node(node *stn)
244{
[f192c5c]245    printf("stn [%p]", stn);
246    if (stn->name) {
247        if (stn->name->stn == stn) {
248            printf("<->");
249        } else {
250            printf("-->");
251        }
252        printf("name ");
253        print_prefix(stn->name);
254        printf(" (%p)", stn->name);
255    } else {
256        printf("-->NULL");
257    }
[d1b1380]258
[f192c5c]259    printf(" colour %ld", stn->colour);
260    if (fixed(stn)) {
261        printf(" FIXED\n");
262    } else {
263        putnl();
264    }
[d1b1380]265
[f192c5c]266    for (int d = 0; d <= 2; d++) {
267        linkfor *leg = stn->leg[d];
268        if (leg) {
269            const char* type;
270            if (data_here(leg)) {
271                type = fZeros(&leg->v) ? "=>" : "->";
272            } else {
273                type = fZeros(&reverse_leg(leg)->v) ? "<=" : "<-";
274            }
275            printf("  leg #%d %s stn [%p] ", d, type, leg->l.to);
276            print_prefix(leg->l.to->name);
277            printf(" | rev %d\n", reverse_leg_dirn(leg));
278        }
279    }
[a420b49]280}
[d1b1380]281
[b6e9e7e]282/* This doesn't cover removed stations - might be nice to have
283 * dump_entire_network() which iterates prefix tree */
[cb3d1e2]284#undef dump_network
[a420b49]285extern void
286dump_network(void)
287{
288   node *stn;
[6d3f931]289   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]290   for (stn = fixedlist; stn; stn = stn->next) dump_node(stn);
[6d3f931]291   for (stn = stnlist; stn; stn = stn->next) dump_node(stn);
[a420b49]292}
Note: See TracBrowser for help on using the repository browser.