source: git/src/cavern.c @ 0938f88

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereostereo-2025walls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 0938f88 was 95c3272, checked in by Olly Betts <olly@…>, 24 years ago

Added a SPLAY flag for indicating splay shots in chambers and large
passages. Such legs are not counted in length calculations, and
ignored by extend.

Added handling for station flags (so far SURFACE and UNDERGROUND are
set).

Extend - preserve flags on stations and legs.

Brought flags entries in TODO together.

Use TSTBIT() where appropriate.

Printer drivers ignore surface moves when scaling (but need to ignore
non-underground stations too).

git-svn-id: file:///home/survex-svn/survex/trunk@921 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 11.5 KB
Line 
1/* > cavern.c
2 * SURVEX Cave surveying software: data reduction main and related functions
3 * Copyright (C) 1991-2001 Olly Betts
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <time.h>
25
26#include "cavern.h"
27#include "cmdline.h"
28#include "commands.h"
29#include "datain.h"
30#include "debug.h"
31#include "message.h"
32#include "filename.h"
33#include "filelist.h"
34#include "img.h"
35#include "listpos.h"
36#include "netbits.h"
37#include "netskel.h"
38#include "osdepend.h"
39#include "out.h"
40#include "str.h"
41#include "validate.h"
42
43#ifdef NEW3DFORMAT
44#if OS != RISCOS && OS != MSDOS
45#include <unistd.h> /* for getcwd() */
46#endif
47
48#include "new3dout.h"
49#ifndef MAXPATHLEN
50#define MAXPATHLEN 1024
51#endif
52#endif
53
54/* For funcs which want to be immune from messing around with different
55 * calling conventions */
56#ifndef CDECL
57# define CDECL
58#endif
59
60/* Globals */
61node *stnlist = NULL;
62settings *pcs;
63prefix *root;
64long cLegs, cStns;
65long cComponents;
66bool fExportUsed = fFalse;
67
68FILE *fhErrStat = NULL;
69img *pimgOut = NULL;
70#ifndef NO_PERCENTAGE
71bool fPercent = fFalse;
72#endif
73bool fAscii = fFalse;
74bool fQuiet = fFalse; /* just show brief summary + errors */
75static bool fMute = fFalse; /* just show errors */
76bool fSuppress = fFalse; /* only output 3d(3dx) file */
77static bool f_warnings_are_errors = fFalse; /* turn warnings into errors */   
78
79nosurveylink *nosurveyhead;
80
81real totadj, total, totplan, totvert;
82real min[3], max[3];
83prefix *pfxHi[3], *pfxLo[3];
84
85char *survey_title = NULL;
86int survey_title_len;
87
88bool fExplicitTitle = fFalse;
89
90char *fnm_output_base = NULL;
91int fnm_output_base_is_dir = 0;
92
93static void do_stats(void);
94
95static const struct option long_opts[] = {
96   /* const char *name; int has_arg (0 no_argument, 1 required_*, 2 optional_*); int *flag; int val; */
97#ifdef NO_PERCENTAGE
98   {"percentage", no_argument, 0, 0},
99   {"no-percentage", no_argument, 0, 0},
100#else
101   {"percentage", no_argument, 0, 'p'},
102   {"no-percentage", no_argument, (int*)&fPercent, 0},
103#endif
104   {"output", required_argument, 0, 'o'},
105   {"quiet", no_argument, 0, 'q'},
106   {"no-auxiliary-files", no_argument, 0, 's'},
107   {"warnings-are-errors", no_argument, 0, 'w'},
108#ifdef NEW3DFORMAT
109   {"new-format", no_argument, 0, 'x'},
110#endif
111   {"help", no_argument, 0, HLP_HELP},
112   {"version", no_argument, 0, HLP_VERSION},
113   {0, 0, 0, 0}
114};
115
116#ifdef NEW3DFORMAT
117#define short_opts "pxao:qswz:"
118#else
119#define short_opts "pao:qswz:"
120#endif
121
122/* TRANSLATE extract help messages to message file */
123static struct help_msg help[] = {
124/*                              <-- */
125   {HLP_ENCODELONG(0),          "display percentage progress"},
126   {'a',                        "output ascii variant of .3d file"},
127   {HLP_ENCODELONG(2),          "set location for output files"},
128   {HLP_ENCODELONG(3),          "only show brief summary (-qq for errors only)"},
129   {HLP_ENCODELONG(4),          "do not create .pos, .inf, or .err files"},
130#ifdef NEW3DFORMAT
131   {HLP_ENCODELONG(5),          "output data in 3dx format"},
132#endif
133 /*{'z',                        "set optimizations for network reduction"},*/
134   {0, 0}
135};
136
137/* atexit function */
138static void
139delete_output_on_error(void)
140{
141   if (msg_errors || (f_warnings_are_errors && msg_warnings))
142      filename_delete_output();
143}
144
145extern CDECL int
146main(int argc, char **argv)
147{
148   int d;
149   static clock_t tmCPUStart;
150   static time_t tmUserStart;
151   static double tmCPU, tmUser;
152
153   tmUserStart = time(NULL);
154   tmCPUStart = clock();
155   init_screen();
156
157   msg_init(argv[0]);
158
159   pcs = osnew(settings);
160   pcs->next = NULL;
161   pcs->Translate = ((short*) osmalloc(ossizeof(short) * 257)) + 1;
162
163   /* Set up root of prefix hierarchy */
164   root = osnew(prefix);
165   root->up = root->right = root->down = NULL;
166   root->stn = NULL;
167   root->pos = NULL;
168   /* FIXME: shouldn't need to set this really, but need to check that nothing assumes the value of root->ident isn't "" */
169   root->ident = "\\";
170   root->min_export = root->max_export = 0;
171   root->sflags = BIT(SFLAGS_SURVEY);
172   root->filename = NULL;
173
174   nosurveyhead = NULL;
175
176   stnlist = NULL;
177   cLegs = cStns = cComponents = 0;
178   totadj = total = totplan = totvert = 0.0;
179
180   for (d = 0; d <= 2; d++) {
181      min[d] = REAL_BIG;
182      max[d] = -REAL_BIG;
183      pfxHi[d] = pfxLo[d] = NULL;
184   }
185
186   cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, -1);
187   while (1) {
188      /* at least one argument must be given */
189      int opt = cmdline_getopt();
190      if (opt == EOF) break;
191      switch (opt) {
192       case 'a':
193         fAscii = fTrue;
194         break;
195       case 'p':
196#ifndef NO_PERCENTAGE
197         fPercent = 1;
198#endif
199         break;
200       case 'o': {
201         /* can be a directory (in which case use basename of leaf input)
202          * or a file (in which case just trim the extension off) */
203         if (fDirectory(optarg)) {
204            /* this is a little tricky - we need to note the path here,
205             * and then add the leaf later on (in datain.c) */
206            fnm_output_base = base_from_fnm(optarg);
207            fnm_output_base_is_dir = 1;
208         } else {
209            osfree(fnm_output_base); /* in case of multiple -o options */
210            fnm_output_base = base_from_fnm(optarg);
211         }
212         break;
213       }
214#ifdef NEW3DFORMAT
215       case 'x': {
216         fUseNewFormat = 1;
217         break;
218       }
219#endif
220       case 'q':
221         if (fQuiet) fMute = 1;
222         fQuiet = 1;
223         break;
224       case 's':
225         fSuppress = 1;
226         break;
227       case 'w':
228         f_warnings_are_errors = 1;
229         break;
230       case 'z': {
231         /* Control which network optimisations are used (development tool) */
232         static int first_opt_z = 1;
233         char c;
234         if (first_opt_z) {
235            optimize = 0;
236            first_opt_z = 0;
237         }
238         /* Lollipops, Parallel legs, Iterate mx, Delta* */
239         while ((c = *optarg++) != '\0')
240             if (islower(c)) optimize |= BITA(ch);
241         break;
242       }
243      }
244   }
245
246   out_puts(PACKAGE" "VERSION);
247   out_puts(COPYRIGHT_MSG);
248   putnl();
249
250   atexit(delete_output_on_error);
251
252   /* end of options, now process data files */
253   while (argv[optind]) {
254      const char *fnm = argv[optind];
255
256      if (!fExplicitTitle) {
257         char *lf;
258         lf = baseleaf_from_fnm(fnm);
259         if (survey_title) s_catchar(&survey_title, &survey_title_len, ' ');
260         s_cat(&survey_title, &survey_title_len, lf);
261         osfree(lf);
262      }
263
264      /* Select defaults settings */
265      default_all(pcs);
266#ifdef NEW3DFORMAT
267      /* we need to get the filename of the first one for our base_source */
268      /* and also run_file */
269      if (fUseNewFormat) {
270         create_twig(root, fnm);
271         rhizome = root->twig_link;
272         limb = get_twig(root);
273         firstfilename = osstrdup(fnm);
274         startingdir = osmalloc(MAXPATHLEN);
275#if (OS==RISCOS)
276         strcpy(startingdir, "@");
277#else
278         getcwd(startingdir, MAXPATHLEN);
279#endif
280      }
281#endif
282      data_file("", fnm); /* first argument is current path */
283
284      optind++;
285   }
286
287   validate();
288
289   solve_network(/*stnlist*/); /* Find coordinates of all points */
290   validate();
291
292#ifdef NEW3DFORMAT
293   if (fUseNewFormat) {
294     cave_close(pimgOut); /* this actually does all the writing */
295   } else {
296#endif
297     img_close(pimgOut); /* close .3d file */
298#ifdef NEW3DFORMAT
299   }
300#endif
301   if (fhErrStat) fclose(fhErrStat);
302
303   if (!fSuppress && !(msg_errors || (f_warnings_are_errors && msg_warnings)))
304      list_pos(root); /* produce .pos file */
305
306   out_current_action(msg(/*Calculating statistics*/120));
307   do_stats();
308   if (!fQuiet) {
309      /* clock() typically wraps after 72 minutes, but there doesn't seem
310       * to be a better way.  Still 72 minutes means some cave!
311       */
312      tmCPU = (clock_t)(clock() - tmCPUStart) / (double)CLOCKS_PER_SEC;
313      tmUser = difftime(time(NULL), tmUserStart);
314
315      /* tmCPU is integer, tmUser not - equivalent to (ceil(tmCPU) >= tmUser) */
316      if (tmCPU + 1 > tmUser) {
317         out_printf((msg(/*CPU time used %5.2fs*/140), tmCPU));
318      } else if (tmCPU == 0) {
319         if (tmUser == 0.0) {
320            out_printf((msg(/*Time used %5.2fs*/141), tmUser));
321         } else {
322            out_puts(msg(/*Time used unavailable*/142));
323         }
324      } else {
325         out_printf((msg(/*Time used %5.2fs (%5.2fs CPU time)*/143),
326                    tmUser, tmCPU));
327      }
328
329      out_puts(msg(/*Done.*/144));
330   }
331   if (msg_warnings || msg_errors) {
332      printf(msg(/*There were %d warning(s) and %d non-fatal error(s).*/16),
333             msg_warnings, msg_errors);
334      putnl();
335      /* FIXME: if (msg_errors || (f_warnings_are_errors && msg_warnings)) print "output not produced..."? */
336   }
337   if (msg_errors || (f_warnings_are_errors && msg_warnings))
338      return EXIT_FAILURE;
339   return EXIT_SUCCESS;
340}
341
342static void
343do_range(FILE *fh, int d, int msg1, int msg2, int msg3)
344{
345   if (!fMute) {
346      printf(msg(msg1), max[d] - min[d]);
347      fprint_prefix(stdout, pfxHi[d]);
348      printf(msg(msg2), max[d]);
349      fprint_prefix(stdout, pfxLo[d]);
350      printf(msg(msg3), min[d]);
351   }
352   if (fh) {
353      fprintf(fh, msg(msg1), max[d] - min[d]);
354      fprint_prefix(fh, pfxHi[d]);
355      fprintf(fh, msg(msg2), max[d]);
356      fprint_prefix(fh, pfxLo[d]);
357      fprintf(fh, msg(msg3), min[d]);
358   }
359}
360
361static void
362do_stats(void)
363{
364   FILE *fh = NULL;
365   long cLoops = cComponents + cLegs - cStns;
366   char buf[1024]; /* FIXME: try to remove static buffer */
367
368   if (!fSuppress && !(msg_errors || (f_warnings_are_errors && msg_warnings)))
369      fh = safe_fopen_with_ext(fnm_output_base, EXT_SVX_STAT, "w");
370
371   out_puts("");
372
373   if (cStns == 1)
374      sprintf(buf, msg(/*Survey contains 1 survey station,*/172));
375   else
376      sprintf(buf,
377              msg(/*Survey contains %ld survey stations,*/173), cStns);
378
379   if (cLegs == 1)
380      sprintf(buf + strlen(buf), msg(/* joined by 1 leg.*/174));
381   else
382      sprintf(buf + strlen(buf),
383              msg(/* joined by %ld legs.*/175), cLegs);
384
385   if (!fMute) out_puts(buf);
386   if (fh) fputsnl(buf, fh);
387
388   if (cLoops == 1)
389      sprintf(buf, msg(/*There is 1 loop.*/138));
390   else
391      sprintf(buf, msg(/*There are %ld loops.*/139), cLoops);
392
393   if (!fMute) out_puts(buf);
394   if (fh) fputsnl(buf, fh);
395
396   if (cComponents != 1) {
397      sprintf(buf,
398              msg(/*Survey has %ld connected components.*/178), cComponents);
399      if (!fMute) out_puts(buf);
400      if (fh) fputsnl(buf, fh);
401   }
402
403   sprintf(buf,
404           msg(/*Total length of survey legs = %7.2fm (%7.2fm adjusted)*/132),
405           total, totadj);
406   if (!fMute) out_puts(buf);
407   if (fh) fputsnl(buf, fh);
408
409   sprintf(buf,
410           msg(/*Total plan length of survey legs = %7.2fm*/133), totplan);
411   if (!fMute) out_puts(buf);
412   if (fh) fputsnl(buf, fh);
413
414   sprintf(buf, msg(/*Total vertical length of survey legs = %7.2fm*/134),
415           totvert);
416   if (!fMute) out_puts(buf);
417   if (fh) fputsnl(buf, fh);
418
419   do_range(fh, 2, /*Vertical range = %4.2fm (from */135,
420            /* at %4.2fm to */136, /* at %4.2fm)*/137);
421   do_range(fh, 1, /*North-South range = %4.2fm (from */148,
422            /* at %4.2fm to */196, /* at %4.2fm)*/197);
423   do_range(fh, 0, /*East-West range = %4.2fm (from */149,
424            /* at %4.2fm to */196, /* at %4.2fm)*/197);
425
426   print_node_stats(fh);
427   /* Also, could give:
428    *  # nodes stations (ie have other than two references or are fixed)
429    *  # fixed stations (list of?)
430    */
431
432   if (fh) fclose(fh);
433}
Note: See TracBrowser for help on using the repository browser.