source: git/src/datain.c @ e2c1671

RELEASE/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 e2c1671 was 44bb30d, checked in by Olly Betts <olly@…>, 20 years ago

Applied Simeon Warner's patch for handling backcompass, backclino, and
omitted forward compass/clino readings in Compass DAT files.

git-svn-id: file:///home/survex-svn/survex/branches/survex-1_1@2880 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 47.4 KB
Line 
1/* datain.c
2 * Reads in survey files, dealing with special characters, keywords & data
3 * Copyright (C) 1991-2003,2005 Olly Betts
4 * Copyright (C) 2004 Simeon Warner
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include <limits.h>
26#include <stdarg.h>
27#include <time.h>
28
29#include "debug.h"
30#include "cavern.h"
31#include "filename.h"
32#include "message.h"
33#include "filelist.h"
34#include "netbits.h"
35#include "netskel.h"
36#include "readval.h"
37#include "datain.h"
38#include "commands.h"
39#include "out.h"
40#include "str.h"
41
42#define EPSILON (REAL_EPSILON * 1000)
43
44#define var(I) (pcs->Var[(I)])
45
46/* true if x is not-a-number value in Compass (999.0 or -999.0)    */
47/* Compass uses 999.0 but understands Karst data which used -999.0 */
48#define is_compass_NaN(x) ( fabs(fabs(x)-999.0) <  EPSILON )
49
50int ch;
51
52typedef enum {
53    CTYPE_OMIT, CTYPE_READING, CTYPE_PLUMB, CTYPE_INFERPLUMB, CTYPE_HORIZ
54} clino_type;
55
56/* Don't explicitly initialise as we can't set the jmp_buf - this has
57 * static scope so will be initialised like this anyway */
58parse file /* = { NULL, NULL, 0, fFalse, NULL } */ ;
59
60bool f_export_ok;
61
62static real value[Fr - 1];
63#define VAL(N) value[(N)-1]
64static real variance[Fr - 1];
65#define VAR(N) variance[(N)-1]
66
67void
68get_pos(filepos *fp)
69{
70   fp->ch = ch;
71   fp->offset = ftell(file.fh);
72   if (fp->offset == -1)
73      fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
74}
75
76void
77set_pos(const filepos *fp)
78{
79   ch = fp->ch;
80   if (fseek(file.fh, fp->offset, SEEK_SET) == -1)
81      fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
82}
83
84static void
85push_back(int c)
86{
87   if (c != EOF && ungetc(c, file.fh) == EOF)
88      fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
89}
90
91static void
92error_list_parent_files(void)
93{
94   if (!file.reported_where && file.parent) {
95      parse *p = file.parent;
96      const char *m = msg(/*In file included from*/5);
97      size_t len = strlen(m);
98
99      fprintf(STDERR, m);
100      m = msg(/*from*/3);
101
102      /* Suppress reporting of full include tree for further errors
103       * in this file */
104      file.reported_where = fTrue;
105
106      while (p) {
107         /* Force re-report of include tree for further errors in
108          * parent files */
109         p->reported_where = fFalse;
110         fprintf(STDERR, " %s:%d", p->filename, p->line);
111         p = p->parent;
112         if (p) fprintf(STDERR, ",\n%*s", (int)len, m);
113      }
114      fprintf(STDERR, ":\n");
115   }
116}
117
118void
119compile_error(int en, ...)
120{
121   va_list ap;
122   va_start(ap, en);
123   error_list_parent_files();
124   v_report(1, file.filename, file.line, en, ap);
125   va_end(ap);
126}
127
128void
129compile_error_skip(int en, ...)
130{
131   va_list ap;
132   va_start(ap, en);
133   error_list_parent_files();
134   v_report(1, file.filename, file.line, en, ap);
135   va_end(ap);
136   skipline();
137}
138
139void
140compile_error_token(int en)
141{
142   char *p = NULL;
143   static int len;
144   s_zero(&p);
145   skipblanks();
146   while (!isBlank(ch) && !isEol(ch)) {
147      s_catchar(&p, &len, (char)ch);
148      nextch();
149   }
150   compile_error_skip(en, p ? p : "");
151   osfree(p);
152}
153
154void
155compile_warning(int en, ...)
156{
157   va_list ap;
158   va_start(ap, en);
159   error_list_parent_files();
160   v_report(0, file.filename, file.line, en, ap);
161   va_end(ap);
162}
163
164/* This function makes a note where to put output files */
165static void
166using_data_file(const char *fnm)
167{
168   if (!fnm_output_base) {
169      /* was: fnm_output_base = base_from_fnm(fnm); */
170      fnm_output_base = baseleaf_from_fnm(fnm);
171   } else if (fnm_output_base_is_dir) {
172      /* --output pointed to directory so use the leaf basename in that dir */
173      char *lf, *p;
174      lf = baseleaf_from_fnm(fnm);
175      p = use_path(fnm_output_base, lf);
176      osfree(lf);
177      osfree(fnm_output_base);
178      fnm_output_base = p;
179      fnm_output_base_is_dir = 0;
180   }
181}
182
183static void
184skipword(void)
185{
186   while (!isBlank(ch) && !isEol(ch)) nextch();
187}
188
189extern void
190skipblanks(void)
191{
192   while (isBlank(ch)) nextch();
193}
194
195extern void
196skipline(void)
197{
198   while (!isEol(ch)) nextch();
199}
200
201#ifndef NO_PERCENTAGE
202static long int filelen;
203#endif
204
205static void
206process_bol(void)
207{
208#ifndef NO_PERCENTAGE
209   /* print %age of file done */
210   if (filelen > 0) {
211      filepos fp;
212      get_pos(&fp);
213      printf("%d%%\r", (int)(100 * fp.offset / filelen));
214   }
215#endif
216
217   nextch();
218   skipblanks();
219}
220
221static void
222process_eol(void)
223{
224   int eolchar;
225
226   skipblanks();
227
228   if (!isEol(ch)) {
229      if (!isComm(ch)) compile_error(/*End of line not blank*/15);
230      skipline();
231   }
232
233   eolchar = ch;
234   file.line++;
235   /* skip any different eol characters so we get line counts correct on
236    * DOS text files and similar, but don't count several adjacent blank
237    * lines as one */
238   while (ch != EOF) {
239      nextch();
240      if (ch == eolchar || !isEol(ch)) {
241         push_back(ch);
242         break;
243      }
244   }
245}
246
247static bool
248process_non_data_line(void)
249{
250   process_bol();
251
252   if (isData(ch)) return fFalse;
253
254   if (isKeywd(ch)) {
255      nextch();
256      handle_command();
257   }
258
259   process_eol();
260
261   return fTrue;
262}
263
264static void
265read_reading(reading r, bool f_optional)
266{
267   int n_readings;
268   q_quantity q;
269   VAL(r) = read_numeric(f_optional, &n_readings);
270   switch (r) {
271      case Tape: q = Q_LENGTH; break;
272      case Comp: q = Q_BEARING; break;
273      case BackComp: q = Q_BACKBEARING; break;
274      case Clino: q = Q_GRADIENT; break;
275      case BackClino: q = Q_BACKGRADIENT; break;
276      case FrDepth: case ToDepth: q = Q_DEPTH; break;
277      case Dx: q = Q_DX; break;
278      case Dy: q = Q_DY; break;
279      case Dz: q = Q_DZ; break;
280      case FrCount: case ToCount: q = Q_COUNT; break;
281      default:
282        q = Q_NULL; /* Suppress compiler warning */;
283        BUG("Unexpected case");
284   }
285   VAR(r) = var(q);
286   if (n_readings > 1) VAR(r) /= sqrt(n_readings);
287}
288
289static void
290read_bearing_or_omit(reading r)
291{
292   int n_readings;
293   q_quantity q = Q_NULL;
294   VAL(r) = read_numeric_or_omit(&n_readings);
295   switch (r) {
296      case Comp: q = Q_BEARING; break;
297      case BackComp: q = Q_BACKBEARING; break;
298      default:
299        q = Q_NULL; /* Suppress compiler warning */;
300        BUG("Unexpected case");
301   }
302   VAR(r) = var(q);
303   if (n_readings > 1) VAR(r) /= sqrt(n_readings);
304}
305
306/* For reading Compass MAK files which have a freeform syntax */
307static void
308nextch_handling_eol(void)
309{
310   nextch();
311   while (ch != EOF && isEol(ch)) {
312      process_eol();
313      nextch();
314   }
315}
316
317#define LITLEN(S) (sizeof(S"") - 1)
318#define has_ext(F,L,E) ((L) > LITLEN(E) + 1 &&\
319                        (F)[(L) - LITLEN(E) - 1] == FNM_SEP_EXT &&\
320                        strcasecmp((F) + (L) - LITLEN(E), E) == 0)
321extern void
322data_file(const char *pth, const char *fnm)
323{
324   int begin_lineno_store;
325   parse file_store;
326   volatile enum {FMT_SVX, FMT_DAT, FMT_MAK} fmt = FMT_SVX;
327
328   {
329      char *filename;
330      FILE *fh;
331      size_t len;
332
333      if (!pth) {
334         /* file specified on command line - don't do special translation */
335         fh = fopenWithPthAndExt(pth, fnm, EXT_SVX_DATA, "rb", &filename);
336      } else {
337         fh = fopen_portable(pth, fnm, EXT_SVX_DATA, "rb", &filename);
338      }
339
340      if (fh == NULL) {
341         compile_error(/*Couldn't open data file `%s'*/24, fnm);
342         return;
343      }
344
345      len = strlen(filename);
346      if (has_ext(filename, len, "dat")) {
347         fmt = FMT_DAT;
348      } else if (has_ext(filename, len, "mak")) {
349         fmt = FMT_MAK;
350      }
351
352      file_store = file;
353      if (file.fh) file.parent = &file_store;
354      file.fh = fh;
355      file.filename = filename;
356      file.line = 1;
357      file.reported_where = fFalse;
358   }
359
360   if (fPercent) printf("%s:\n", fnm);
361
362   using_data_file(file.filename);
363
364   begin_lineno_store = pcs->begin_lineno;
365   pcs->begin_lineno = 0;
366
367#ifndef NO_PERCENTAGE
368   /* Try to find how long the file is...
369    * However, under ANSI fseek( ..., SEEK_END) may not be supported */
370   filelen = 0;
371   if (fPercent) {
372      if (fseek(file.fh, 0l, SEEK_END) == 0) {
373         filepos fp;
374         get_pos(&fp);
375         filelen = fp.offset;
376      }
377      rewind(file.fh); /* reset file ptr to start & clear any error state */
378   }
379#endif
380
381   if (fmt == FMT_DAT) {
382      short *t;
383      int i;
384      settings *pcsNew;
385
386      pcsNew = osnew(settings);
387      *pcsNew = *pcs; /* copy contents */
388      pcsNew->begin_lineno = 0;
389      pcsNew->next = pcs;
390      pcs = pcsNew;
391      default_units(pcs);
392      default_calib(pcs);
393
394      pcs->style = STYLE_NORMAL;
395      pcs->units[Q_LENGTH] = METRES_PER_FOOT;
396      t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
397
398      t[EOF] = SPECIAL_EOL;
399      memset(t, 0, sizeof(short) * 33);
400      for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
401      t[127] = 0;
402      for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
403      t['\t'] |= SPECIAL_BLANK;
404      t[' '] |= SPECIAL_BLANK;
405      t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
406      t['\n'] |= SPECIAL_EOL;
407      t['\r'] |= SPECIAL_EOL;
408      t['.'] |= SPECIAL_DECIMAL;
409      t['-'] |= SPECIAL_MINUS;
410      t['+'] |= SPECIAL_PLUS;
411      pcs->Translate = t;
412      pcs->Case = OFF;
413      pcs->Truncate = INT_MAX;
414      pcs->infer = 7; /* FIXME: BIT(EQUATES)|BIT(EXPORTS)|BIT(PLUMBS); */
415   } else if (fmt == FMT_MAK) {
416      short *t;
417      int i;
418      settings *pcsNew;
419
420      pcsNew = osnew(settings);
421      *pcsNew = *pcs; /* copy contents */
422      pcsNew->begin_lineno = 0;
423      pcsNew->next = pcs;
424      pcs = pcsNew;
425
426      t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
427
428      t[EOF] = SPECIAL_EOL;
429      memset(t, 0, sizeof(short) * 33);
430      for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
431      t[127] = 0;
432      for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
433      t['['] = t[','] = t[';'] = 0;
434      t['\t'] |= SPECIAL_BLANK;
435      t[' '] |= SPECIAL_BLANK;
436      t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
437      t['\n'] |= SPECIAL_EOL;
438      t['\r'] |= SPECIAL_EOL;
439      t['.'] |= SPECIAL_DECIMAL;
440      t['-'] |= SPECIAL_MINUS;
441      t['+'] |= SPECIAL_PLUS;
442      pcs->Translate = t;
443      pcs->Case = OFF;
444      pcs->Truncate = INT_MAX;
445   }
446
447#ifdef HAVE_SETJMP_H
448   /* errors in nested functions can longjmp here */
449   if (setjmp(file.jbSkipLine)) {
450      process_eol();
451   }
452#endif
453
454   if (fmt == FMT_DAT) {
455      while (!feof(file.fh) && !ferror(file.fh)) {
456         static reading compass_order[] = {
457            Fr, To, Tape, CompassDATComp, CompassDATClino,
458            Ignore, Ignore, Ignore, Ignore, /*LRUD*/
459            CompassDATFlags, IgnoreAll
460         };
461         static reading compass_order_backsights[] = {
462            Fr, To, Tape, CompassDATComp, CompassDATClino,
463            Ignore, Ignore, Ignore, Ignore, /*LRUD*/
464            CompassDATBackComp, CompassDATBackClino,
465            CompassDATFlags, IgnoreAll
466         };
467         /* <Cave name> */
468         process_bol();
469         skipline();
470         process_eol();
471         /* SURVEY NAME: <Short name> */
472         get_token();
473         get_token();
474         /* if (ch != ':') ... */
475         nextch();
476         skipblanks();
477         get_token();
478         skipline();
479         process_eol();
480         /* SURVEY DATE: 7 10 79  COMMENT:<Long name> */
481         /* NB order is *month* *day* year */
482         get_token();
483         get_token();
484         if (ch == ':') {
485             struct tm t;
486
487             copy_on_write_meta(pcs);
488
489             nextch();
490             /* struct tm month uses 0 for Jan */
491             t.tm_mon = read_uint() - 1;
492             t.tm_mday = read_uint();
493             /* struct tm uses year - 1900 */
494             t.tm_year = read_uint();
495             /* Note: Larry says a 2 digit year is always 19XX */
496             if (t.tm_year >= 100) t.tm_year -= 1900;
497
498             pcs->meta->date1 = mktime(&t);
499             pcs->meta->date2 = pcs->meta->date1;
500         }
501         skipline();
502         process_eol();
503         /* SURVEY TEAM: */
504         get_token();
505         get_token();
506         skipline();
507         process_eol();
508         /* <Survey team> */
509         nextch();
510         skipline();
511         process_eol();
512         /* DECLINATION: 1.00  FORMAT: DDDDLUDRADLN  CORRECTIONS: 2.00 3.00 4.00 */
513         get_token();
514         nextch(); /* : */
515         skipblanks();
516         pcs->z[Q_DECLINATION] = -read_numeric(fFalse, NULL);
517         pcs->z[Q_DECLINATION] *= pcs->units[Q_DECLINATION];
518         get_token();
519         pcs->ordering = compass_order;
520         if (strcmp(buffer, "FORMAT") == 0) {
521            nextch(); /* : */
522            get_token();
523            if (strlen(buffer) >= 12 && buffer[11] == 'B') {
524               /* We have backsights for compass and clino */
525               pcs->ordering = compass_order_backsights;
526            }
527            get_token();
528         }
529         if (strcmp(buffer, "CORRECTIONS") == 0) {
530            nextch(); /* : */
531            pcs->z[Q_BEARING] = -rad(read_numeric(fFalse, NULL));
532            pcs->z[Q_GRADIENT] = -rad(read_numeric(fFalse, NULL));
533            pcs->z[Q_LENGTH] = -read_numeric(fFalse, NULL);
534         } else {
535            pcs->z[Q_BEARING] = 0;
536            pcs->z[Q_GRADIENT] = 0;
537            pcs->z[Q_LENGTH] = 0;
538         }
539         skipline();
540         process_eol();
541         /* BLANK LINE */
542         process_bol();
543         skipline();
544         process_eol();
545         /* heading line */
546         process_bol();
547         skipline();
548         process_eol();
549         /* BLANK LINE */
550         process_bol();
551         skipline();
552         process_eol();
553         while (!feof(file.fh)) {
554            process_bol();
555            if (ch == '\x0c') {
556               nextch();
557               process_eol();
558               break;
559            }
560            (void)data_normal();
561         }
562      }
563      {
564         settings *pcsParent = pcs->next;
565         SVX_ASSERT(pcsParent);
566         pcs->ordering = NULL;
567         free_settings(pcs);
568         pcs = pcsParent;
569      }
570   } else if (fmt == FMT_MAK) {
571      nextch_handling_eol();
572      while (!feof(file.fh) && !ferror(file.fh)) {
573         if (ch == '#') {
574            /* include a file */
575            int ch_store;
576            char *dat_pth = path_from_fnm(file.filename);
577            char *dat_fnm = NULL;
578            int dat_fnm_len;
579            nextch_handling_eol();
580            while (ch != ',' && ch != ';' && ch != EOF) {
581               while (isEol(ch)) process_eol();
582               s_catchar(&dat_fnm, &dat_fnm_len, (char)ch);
583               nextch_handling_eol();
584            }
585            while (ch != ';' && ch != EOF) {
586               prefix *name;
587               nextch_handling_eol();
588               name = read_prefix_stn(fTrue, fFalse);
589               if (name) {
590                  skipblanks();
591                  if (ch == '[') {
592                     /* fixed pt */
593                     node *stn;
594                     real x, y, z;
595                     name->sflags |= BIT(SFLAGS_FIXED);
596                     nextch_handling_eol();
597                     while (!isdigit(ch) && ch != '+' && ch != '-' &&
598                            ch != '.' && ch != ']' && ch != EOF) {
599                        nextch_handling_eol();
600                     }
601                     x = read_numeric(fFalse, NULL);
602                     while (!isdigit(ch) && ch != '+' && ch != '-' &&
603                            ch != '.' && ch != ']' && ch != EOF) {
604                        nextch_handling_eol();
605                     }
606                     y = read_numeric(fFalse, NULL);
607                     while (!isdigit(ch) && ch != '+' && ch != '-' &&
608                            ch != '.' && ch != ']' && ch != EOF) {
609                        nextch_handling_eol();
610                     }
611                     z = read_numeric(fFalse, NULL);
612                     stn = StnFromPfx(name);
613                     if (!fixed(stn)) {
614                        POS(stn, 0) = x;
615                        POS(stn, 1) = y;
616                        POS(stn, 2) = z;
617                        fix(stn);
618                     } else {
619                        if (x != POS(stn, 0) || y != POS(stn, 1) ||
620                            z != POS(stn, 2)) {
621                           compile_error(/*Station already fixed or equated to a fixed point*/46);
622                        } else {
623                           compile_warning(/*Station already fixed at the same coordinates*/55);
624                        }
625                     }
626                     while (ch != ']' && ch != EOF) nextch_handling_eol();
627                     if (ch == ']') {
628                        nextch_handling_eol();
629                        skipblanks();
630                     }
631                  } else {
632                     /* FIXME: link station - ignore for now */
633                     /* FIXME: perhaps issue warning? */
634                  }
635                  while (ch != ',' && ch != ';' && ch != EOF)
636                     nextch_handling_eol();
637               }
638            }
639            if (dat_fnm) {
640               ch_store = ch;
641               data_file(dat_pth, dat_fnm);
642               ch = ch_store;
643               osfree(dat_fnm);
644            }
645         } else {
646            /* FIXME: also check for % and $ later */
647            nextch_handling_eol();
648         }
649      }
650      {
651         settings *pcsParent = pcs->next;
652         SVX_ASSERT(pcsParent);
653         free_settings(pcs);
654         pcs = pcsParent;
655      }
656   } else {
657      while (!feof(file.fh) && !ferror(file.fh)) {
658         if (!process_non_data_line()) {
659            volatile int r;
660#ifdef CHASM3DX
661            twig *temp = limb;
662#endif
663            f_export_ok = fFalse;
664            switch (pcs->style) {
665             case STYLE_NORMAL:
666             case STYLE_DIVING:
667             case STYLE_CYLPOLAR:
668               r = data_normal();
669               break;
670             case STYLE_CARTESIAN:
671               r = data_cartesian();
672               break;
673             case STYLE_NOSURVEY:
674               r = data_nosurvey();
675               break;
676             case STYLE_IGNORE:
677               r = data_ignore();
678               break;
679             default:
680               r = 0; /* avoid warning */
681               BUG("bad style");
682            }
683            /* style function returns 0 => error */
684#ifdef CHASM3DX
685            if (!r && fUseNewFormat) {
686               /* we have just created a very naughty twiglet, and it must be
687                * punished */
688               osfree(limb);
689               limb = temp;
690            }
691#endif
692         }
693      }
694   }
695
696   /* don't allow *BEGIN at the end of a file, then *EXPORT in the
697    * including file */
698   f_export_ok = fFalse;
699
700#ifndef NO_PERCENTAGE
701   if (fPercent) putnl();
702#endif
703
704   if (pcs->begin_lineno) {
705      error_in_file(file.filename, pcs->begin_lineno,
706                    /*BEGIN with no matching END in this file*/23);
707      /* Implicitly close any unclosed BEGINs from this file */
708      do {
709         settings *pcsParent = pcs->next;
710         SVX_ASSERT(pcsParent);
711         free_settings(pcs);
712         pcs = pcsParent;
713      } while (pcs->begin_lineno);
714   }
715
716   pcs->begin_lineno = begin_lineno_store;
717
718   if (ferror(file.fh))
719      fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
720
721   (void)fclose(file.fh);
722
723   file = file_store;
724
725   /* don't free this - it may be pointed to by prefix.file */
726   /* osfree(file.filename); */
727}
728
729static real
730mod2pi(real a)
731{
732   return a - floor(a / (2 * M_PI)) * (2 * M_PI);
733}
734
735static real
736handle_plumb(clino_type *p_ctype)
737{
738   typedef enum {
739      CLINO_NULL=-1, CLINO_UP, CLINO_DOWN, CLINO_LEVEL
740   } clino_tok;
741   static sztok clino_tab[] = {
742      {"D",     CLINO_DOWN},
743      {"DOWN",  CLINO_DOWN},
744      {"H",     CLINO_LEVEL},
745      {"LEVEL", CLINO_LEVEL},
746      {"U",     CLINO_UP},
747      {"UP",    CLINO_UP},
748      {NULL,    CLINO_NULL}
749   };
750   static real clinos[] = {(real)M_PI_2, (real)(-M_PI_2), (real)0.0};
751   clino_tok tok;
752
753   skipblanks();
754   if (isalpha(ch)) {
755      filepos fp;
756      get_pos(&fp);
757      get_token();
758      tok = match_tok(clino_tab, TABSIZE(clino_tab));
759      if (tok != CLINO_NULL) {
760         *p_ctype = (tok == CLINO_LEVEL ? CTYPE_HORIZ : CTYPE_PLUMB);
761         return clinos[tok];
762      }
763      set_pos(&fp);
764   } else if (isSign(ch)) {
765      int chOld = ch;
766      nextch();
767      if (toupper(ch) == 'V') {
768         nextch();
769         *p_ctype = CTYPE_PLUMB;
770         return (!isMinus(chOld) ? M_PI_2 : -M_PI_2);
771      }
772
773      if (isOmit(chOld)) {
774         *p_ctype = CTYPE_OMIT;
775         /* no clino reading, so assume 0 with large sd */
776         return (real)0.0;
777      }
778   } else if (isOmit(ch)) {
779      /* OMIT char may not be a SIGN char too so we need to check here as
780       * well as above... */
781      nextch();
782      *p_ctype = CTYPE_OMIT;
783      /* no clino reading, so assume 0 with large sd */
784      return (real)0.0;
785   }
786   return HUGE_REAL;
787}
788
789static void
790warn_readings_differ(int msgno, real diff)
791{
792   char buf[64];
793   char *p;
794   sprintf(buf, "%.2f", deg(fabs(diff)));
795   p = strchr(buf, '.');
796   if (p) {
797      char *z = p;
798      while (*++p) {
799         if (*p != '0') z = p + 1;
800      }
801      if (*z) *z = '\0';
802   }
803   compile_warning(msgno, buf);
804}
805
806static bool
807handle_comp_units(void)
808{
809   bool fNoComp = fTrue;
810   if (VAL(Comp) != HUGE_REAL) {
811      fNoComp = fFalse;
812      VAL(Comp) *= pcs->units[Q_BEARING];
813      if (VAL(Comp) < (real)0.0 || VAL(Comp) - M_PI * 2.0 > EPSILON) {
814         compile_warning(/*Suspicious compass reading*/59);
815         VAL(Comp) = mod2pi(VAL(Comp));
816      }
817   }
818   if (VAL(BackComp) != HUGE_REAL) {
819      fNoComp = fFalse;
820      VAL(BackComp) *= pcs->units[Q_BACKBEARING];
821      if (VAL(BackComp) < (real)0.0 || VAL(BackComp) - M_PI * 2.0 > EPSILON) {
822         /* FIXME: different message for BackComp? */
823         compile_warning(/*Suspicious compass reading*/59);
824         VAL(BackComp) = mod2pi(VAL(BackComp));
825      }
826   }
827   return fNoComp;
828}
829
830static real
831handle_compass(real *p_var)
832{
833   real compvar = VAR(Comp);
834   real comp = VAL(Comp);
835   real backcomp = VAL(BackComp);
836   if (comp != HUGE_REAL) {
837      comp = (comp - pcs->z[Q_BEARING]) * pcs->sc[Q_BEARING];
838      comp -= pcs->z[Q_DECLINATION];
839   }
840   if (backcomp != HUGE_REAL) {
841      backcomp = (backcomp - pcs->z[Q_BACKBEARING])
842              * pcs->sc[Q_BACKBEARING];
843      backcomp -= pcs->z[Q_DECLINATION];
844      backcomp -= M_PI;
845      if (comp != HUGE_REAL) {
846         real diff = comp - backcomp;
847         real adj = fabs(diff) > M_PI ? M_PI : 0;
848         diff -= floor((diff + M_PI) / (2 * M_PI)) * 2 * M_PI;
849         if (sqrd(diff / 2.0) > compvar + VAR(Q_BACKBEARING)) {
850            /* fore and back readings differ by more than 2 sds */
851            warn_readings_differ(/*Compass reading and back compass reading disagree by %s degrees*/98, diff);
852         }
853         comp = (comp / compvar + backcomp / VAR(BackComp));
854         compvar = (compvar + VAR(BackComp)) / 4;
855         comp *= compvar;
856         comp += adj;
857      } else {
858         comp = backcomp;
859         compvar = VAR(BackComp);
860      }
861   }
862   *p_var = compvar;
863   return comp;
864}
865
866static int
867process_normal(prefix *fr, prefix *to, bool fToFirst,
868               clino_type ctype, clino_type backctype)
869{
870   real tape = VAL(Tape);
871   real clin = VAL(Clino);
872   real backclin = VAL(BackClino);
873
874   real dx, dy, dz;
875   real vx, vy, vz;
876#ifndef NO_COVARIANCES
877   real cxy, cyz, czx;
878#endif
879
880   bool fNoComp;
881
882   /* adjusted tape is negative -- probably the calibration is wrong */
883   if (tape < (real)0.0) {
884      /* TRANSLATE different message for topofil? */
885      compile_warning(/*Negative adjusted tape reading*/79);
886   }
887
888   fNoComp = handle_comp_units();
889
890   if (ctype == CTYPE_READING) {
891      real diff_from_abs90;
892      clin *= pcs->units[Q_GRADIENT];
893      /* percentage scale */
894      if (pcs->f_clino_percent) clin = atan(clin);
895      diff_from_abs90 = fabs(clin) - M_PI_2;
896      if (diff_from_abs90 > EPSILON) {
897         compile_warning(/*Clino reading over 90 degrees (absolute value)*/51);
898      } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
899                 diff_from_abs90 >= -EPSILON) {
900         ctype = CTYPE_INFERPLUMB;
901      }
902   }
903
904   if (backctype == CTYPE_READING) {
905      backclin *= pcs->units[Q_BACKGRADIENT];
906      /* percentage scale */
907      if (pcs->f_backclino_percent) backclin = atan(backclin);
908      if (ctype != CTYPE_READING) {
909         real diff_from_abs90 = fabs(backclin) - M_PI_2;
910         if (diff_from_abs90 > EPSILON) {
911            /* FIXME: different message for BackClino? */
912            compile_warning(/*Clino reading over 90 degrees (absolute value)*/51);
913         } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
914                    diff_from_abs90 >= -EPSILON) {
915            backctype = CTYPE_INFERPLUMB;
916         }
917      }
918   }
919
920   /* un-infer the plumb if the backsight was just a reading */
921   if (ctype == CTYPE_INFERPLUMB && backctype == CTYPE_READING) {
922       ctype = CTYPE_READING;
923   }
924
925   if (ctype != CTYPE_OMIT && backctype != CTYPE_OMIT && ctype != backctype) {
926      compile_error_skip(/*Clino and BackClino readings must be of the same type*/84);
927      return 0;
928   }
929
930   if (ctype == CTYPE_PLUMB || ctype == CTYPE_INFERPLUMB ||
931       backctype == CTYPE_PLUMB || backctype == CTYPE_INFERPLUMB) {
932      /* plumbed */
933      if (!fNoComp) {
934         if (ctype == CTYPE_PLUMB ||
935             (ctype == CTYPE_INFERPLUMB && VAL(Comp) != 0.0) ||
936             backctype == CTYPE_PLUMB ||
937             (backctype == CTYPE_INFERPLUMB && VAL(BackComp) != 0.0)) {
938            /* FIXME: Different message for BackComp? */
939            compile_warning(/*Compass reading given on plumbed leg*/21);
940         }
941      }
942
943      dx = dy = (real)0.0;
944      if (ctype != CTYPE_OMIT) {
945         if (backctype != CTYPE_OMIT && (clin > 0) == (backclin > 0)) {
946            /* We've got two UPs or two DOWNs - FIXME: not ideal message */
947            compile_error_skip(/*Clino and BackClino readings must be of the same type*/84);
948            return 0;
949         }
950         dz = (clin > (real)0.0) ? tape : -tape;
951      } else {
952         dz = (backclin < (real)0.0) ? tape : -tape;
953      }
954      vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
955      vz = var(Q_POS) / 3.0 + VAR(Tape);
956#ifndef NO_COVARIANCES
957      /* Correct values - no covariances in this case! */
958      cxy = cyz = czx = (real)0.0;
959#endif
960   } else {
961      /* Each of ctype and backctype are either CTYPE_READING/CTYPE_HORIZ
962       * or CTYPE_OMIT */
963      /* clino */
964      real L2, cosG, LcosG, cosG2, sinB, cosB, dx2, dy2, dz2, v, V;
965      if (fNoComp) {
966         compile_error_skip(/*Compass reading may not be omitted except on plumbed legs*/14);
967         return 0;
968      }
969      if (tape == (real)0.0) {
970         dx = dy = dz = (real)0.0;
971         vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
972#ifndef NO_COVARIANCES
973         cxy = cyz = czx = (real)0.0;
974#endif
975#if DEBUG_DATAIN_1
976         printf("Zero length leg: vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
977#endif
978      } else {
979         real sinGcosG;
980         /* take into account variance in LEVEL case */
981         real var_clin = var(Q_LEVEL);
982         real var_comp;
983         real comp = handle_compass(&var_comp);
984         /* ctype != CTYPE_READING is LEVEL case */
985         if (ctype == CTYPE_READING) {
986            clin = (clin - pcs->z[Q_GRADIENT]) * pcs->sc[Q_GRADIENT];
987            var_clin = VAR(Clino);
988         }
989         if (backctype == CTYPE_READING) {
990            backclin = (backclin - pcs->z[Q_BACKGRADIENT])
991               * pcs->sc[Q_BACKGRADIENT];
992            if (ctype == CTYPE_READING) {
993               if (sqrd((clin + backclin) / 3.0) > var_clin + VAR(BackClino)) {
994                  /* fore and back readings differ by more than 3 sds */
995                  warn_readings_differ(/*Clino reading and back clino reading disagree by %s degrees*/99, clin + backclin);
996               }
997               clin = (clin / var_clin - backclin / VAR(BackClino));
998               var_clin = (var_clin + VAR(BackClino)) / 4;
999               clin *= var_clin;
1000            } else {
1001               clin = -backclin;
1002               var_clin = VAR(BackClino);
1003            }
1004         }
1005
1006#if DEBUG_DATAIN
1007         printf("    %4.2f %4.2f %4.2f\n", tape, comp, clin);
1008#endif
1009         cosG = cos(clin);
1010         LcosG = tape * cosG;
1011         sinB = sin(comp);
1012         cosB = cos(comp);
1013#if DEBUG_DATAIN_1
1014         printf("sinB = %f, cosG = %f, LcosG = %f\n", sinB, cosG, LcosG);
1015#endif
1016         dx = LcosG * sinB;
1017         dy = LcosG * cosB;
1018         dz = tape * sin(clin);
1019/*      printf("%.2f\n",clin); */
1020#if DEBUG_DATAIN_1
1021         printf("dx = %f\ndy = %f\ndz = %f\n", dx, dy, dz);
1022#endif
1023         dx2 = dx * dx;
1024         L2 = tape * tape;
1025         V = VAR(Tape) / L2;
1026         dy2 = dy * dy;
1027         cosG2 = cosG * cosG;
1028         sinGcosG = sin(clin) * cosG;
1029         dz2 = dz * dz;
1030         v = dz2 * var_clin;
1031#ifdef NO_COVARIANCES
1032         vx = (var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1033               (.5 + sinB * sinB * cosG2) * v);
1034         vy = (var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1035               (.5 + cosB * cosB * cosG2) * v);
1036         if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1037            /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1038            vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1039         } else {
1040            vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1041         }
1042         /* for Surveyor87 errors: vx=vy=vz=var(Q_POS)/3.0; */
1043#else
1044         vx = var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1045            (sinB * sinB * v);
1046         vy = var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1047            (cosB * cosB * v);
1048         if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1049            /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1050            vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1051         } else {
1052            vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1053         }
1054         /* usual covariance formulae are fine in no clino case since
1055          * dz = 0 so value of var_clin is ignored */
1056         cxy = sinB * cosB * (VAR(Tape) * cosG2 + var_clin * dz2)
1057               - var_comp * dx * dy;
1058         czx = VAR(Tape) * sinB * sinGcosG - var_clin * dx * dz;
1059         cyz = VAR(Tape) * cosB * sinGcosG - var_clin * dy * dz;
1060#if 0
1061         printf("vx = %6.3f, vy = %6.3f, vz = %6.3f\n", vx, vy, vz);
1062         printf("cxy = %6.3f, cyz = %6.3f, czx = %6.3f\n", cxy, cyz, czx);
1063#endif
1064#endif
1065#if DEBUG_DATAIN_1
1066         printf("In DATAIN.C, vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1067#endif
1068      }
1069   }
1070#if DEBUG_DATAIN_1
1071   printf("Just before addleg, vx = %f\n", vx);
1072#endif
1073   /*printf("dx,dy,dz = %.2f %.2f %.2f\n\n", dx, dy, dz);*/
1074   addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1075#ifndef NO_COVARIANCES
1076                , cyz, czx, cxy
1077#endif
1078                );
1079
1080#ifdef CHASM3DX
1081   if (fUseNewFormat) {
1082      /* new twiglet and insert into twig tree */
1083      twig *twiglet = osnew(twig);
1084      twiglet->from = fr;
1085      twiglet->to = to;
1086      twiglet->down = twiglet->right = NULL;
1087      twiglet->source = twiglet->drawings
1088        = twiglet->date = twiglet->instruments = twiglet->tape = NULL;
1089      twiglet->up = limb->up;
1090      limb->right = twiglet;
1091      limb = twiglet;
1092
1093      /* record pre-fettling deltas */
1094      twiglet->delta[0] = dx;
1095      twiglet->delta[1] = dy;
1096      twiglet->delta[2] = dz;
1097   }
1098#endif
1099   return 1;
1100}
1101
1102static int
1103process_diving(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1104{
1105   real tape = VAL(Tape);
1106
1107   real dx, dy, dz;
1108   real vx, vy, vz;
1109#ifndef NO_COVARIANCES
1110   real cxy = 0, cyz = 0, czx = 0;
1111#endif
1112
1113   handle_comp_units();
1114
1115   /* depth gauge readings increase upwards with default calibration */
1116   if (fDepthChange) {
1117      SVX_ASSERT(VAL(FrDepth) == 0.0);
1118      dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1119      dz *= pcs->sc[Q_DEPTH];
1120   } else {
1121      dz = VAL(ToDepth) - VAL(FrDepth);
1122      dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1123   }
1124
1125   /* adjusted tape is negative -- probably the calibration is wrong */
1126   if (tape < (real)0.0) {
1127      compile_warning(/*Negative adjusted tape reading*/79);
1128   }
1129
1130   /* check if tape is less than depth change */
1131   if (tape < fabs(dz)) {
1132      /* FIXME: allow margin of error based on variances? */
1133      compile_warning(/*Tape reading is less than change in depth*/62);
1134   }
1135
1136   if (tape == (real)0.0 && dz == 0.0) {
1137      dx = dy = dz = (real)0.0;
1138      vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1139   } else if (VAL(Comp) == HUGE_REAL &&
1140              VAL(BackComp) == HUGE_REAL) {
1141      /* plumb */
1142      dx = dy = (real)0.0;
1143      if (dz < 0) tape = -tape;
1144      /* FIXME: Should use FrDepth sometimes... */
1145      dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth))
1146         / (VAR(Tape) * 2 * VAR(ToDepth));
1147      vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1148      /* FIXME: Should use FrDepth sometimes... */
1149      vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth)
1150                              / (VAR(Tape) + VAR(ToDepth));
1151   } else {
1152      real L2, sinB, cosB, dz2, D2;
1153      real var_comp;
1154      real comp = handle_compass(&var_comp);
1155      sinB = sin(comp);
1156      cosB = cos(comp);
1157      L2 = tape * tape;
1158      dz2 = dz * dz;
1159      D2 = L2 - dz2;
1160      if (D2 <= (real)0.0) {
1161         /* FIXME: Should use FrDepth sometimes... */
1162         real vsum = VAR(Tape) + 2 * VAR(ToDepth);
1163         dx = dy = (real)0.0;
1164         vx = vy = var(Q_POS) / 3.0;
1165         /* FIXME: Should use FrDepth sometimes... */
1166         vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth) / vsum;
1167         if (dz > 0) {
1168            /* FIXME: Should use FrDepth sometimes... */
1169            dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth)) / vsum;
1170         } else {
1171            dz = (dz * VAR(Tape) - tape * 2 * VAR(ToDepth)) / vsum;
1172         }
1173      } else {
1174         real D = sqrt(D2);
1175         /* FIXME: Should use FrDepth sometimes... */
1176         real F = VAR(Tape) * L2 + 2 * VAR(ToDepth) * D2;
1177         dx = D * sinB;
1178         dy = D * cosB;
1179
1180         vx = var(Q_POS) / 3.0 +
1181            sinB * sinB * F / D2 + var_comp * dy * dy;
1182         vy = var(Q_POS) / 3.0 +
1183            cosB * cosB * F / D2 + var_comp * dx * dx;
1184         /* FIXME: Should use FrDepth sometimes... */
1185         vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1186
1187#ifndef NO_COVARIANCES
1188         cxy = sinB * cosB * (F / D2 + var_comp * D2);
1189         /* FIXME: Should use FrDepth sometimes... */
1190         cyz = -2 * VAR(ToDepth) * dy / D;
1191         czx = -2 * VAR(ToDepth) * dx / D;
1192#endif
1193      }
1194   }
1195   addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1196#ifndef NO_COVARIANCES
1197                , cxy, cyz, czx
1198#endif
1199                );
1200#ifdef CHASM3DX
1201   if (fUseNewFormat) {
1202      /* new twiglet and insert into twig tree */
1203      twig *twiglet = osnew(twig);
1204      twiglet->from = fr;
1205      twiglet->to = to;
1206      twiglet->down = twiglet->right = NULL;
1207      twiglet->source = twiglet->drawings
1208        = twiglet->date = twiglet->instruments = twiglet->tape = NULL;
1209      twiglet->up = limb->up;
1210      limb->right = twiglet;
1211      limb = twiglet;
1212
1213      /* record pre-fettling deltas */
1214      twiglet->delta[0] = dx;
1215      twiglet->delta[1] = dy;
1216      twiglet->delta[2] = dz;
1217   }
1218#endif
1219
1220   return 1;
1221}
1222
1223static int
1224process_cartesian(prefix *fr, prefix *to, bool fToFirst)
1225{
1226   real dx = (VAL(Dx) * pcs->units[Q_DX] - pcs->z[Q_DX]) * pcs->sc[Q_DX];
1227   real dy = (VAL(Dy) * pcs->units[Q_DY] - pcs->z[Q_DY]) * pcs->sc[Q_DY];
1228   real dz = (VAL(Dz) * pcs->units[Q_DZ] - pcs->z[Q_DZ]) * pcs->sc[Q_DZ];
1229
1230   addlegbyname(fr, to, fToFirst, dx, dy, dz, VAR(Dx), VAR(Dy), VAR(Dz)
1231#ifndef NO_COVARIANCES
1232                , 0, 0, 0
1233#endif
1234                );
1235
1236#ifdef CHASM3DX
1237   if (fUseNewFormat) {
1238      /* new twiglet and insert into twig tree */
1239      twig *twiglet = osnew(twig);
1240      twiglet->from = fr;
1241      twiglet->to = to;
1242      twiglet->down = twiglet->right = NULL;
1243      twiglet->source = twiglet->drawings
1244        = twiglet->date = twiglet->instruments = twiglet->tape = NULL;
1245      twiglet->up = limb->up;
1246      limb->right = twiglet;
1247      limb = twiglet;
1248
1249      /* record pre-fettling deltas */
1250      twiglet->delta[0] = dx;
1251      twiglet->delta[1] = dy;
1252      twiglet->delta[2] = dz;
1253   }
1254#endif
1255
1256   return 1;
1257}
1258
1259extern int
1260data_cartesian(void)
1261{
1262   prefix *fr = NULL, *to = NULL;
1263
1264   bool fMulti = fFalse;
1265
1266   reading first_stn = End;
1267
1268   reading *ordering;
1269
1270   again:
1271
1272   for (ordering = pcs->ordering ; ; ordering++) {
1273      skipblanks();
1274      switch (*ordering) {
1275       case Fr:
1276         fr = read_prefix_stn(fFalse, fTrue);
1277         if (first_stn == End) first_stn = Fr;
1278         break;
1279       case To:
1280         to = read_prefix_stn(fFalse, fTrue);
1281         if (first_stn == End) first_stn = To;
1282         break;
1283       case Station:
1284         fr = to;
1285         to = read_prefix_stn(fFalse, fFalse);
1286         first_stn = To;
1287         break;
1288       case Dx: case Dy: case Dz:
1289         read_reading(*ordering, fFalse);
1290         break;
1291       case Ignore:
1292         skipword(); break;
1293       case IgnoreAllAndNewLine:
1294         skipline();
1295         /* fall through */
1296       case Newline:
1297         if (fr != NULL) {
1298            int r;
1299            r = process_cartesian(fr, to, first_stn == To);
1300            if (!r) skipline();
1301         }
1302         fMulti = fTrue;
1303         while (1) {
1304            process_eol();
1305            process_bol();
1306            if (isData(ch)) break;
1307            if (!isComm(ch)) {
1308               push_back(ch);
1309               return 1;
1310            }
1311         }
1312         break;
1313       case IgnoreAll:
1314         skipline();
1315         /* fall through */
1316       case End:
1317         if (!fMulti) {
1318            int r = process_cartesian(fr, to, first_stn == To);
1319            process_eol();
1320            return r;
1321         }
1322         do {
1323            process_eol();
1324            process_bol();
1325         } while (isComm(ch));
1326         goto again;
1327       default: BUG("Unknown reading in ordering");
1328      }
1329   }
1330}
1331
1332static int
1333process_cylpolar(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1334{
1335   real tape = VAL(Tape);
1336
1337   real dx, dy, dz;
1338   real vx, vy, vz;
1339#ifndef NO_COVARIANCES
1340   real cxy = 0;
1341#endif
1342
1343   handle_comp_units();
1344
1345   /* depth gauge readings increase upwards with default calibration */
1346   if (fDepthChange) {
1347      SVX_ASSERT(VAL(FrDepth) == 0.0);
1348      dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1349      dz *= pcs->sc[Q_DEPTH];
1350   } else {
1351      dz = VAL(ToDepth) - VAL(FrDepth);
1352      dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1353   }
1354
1355   /* adjusted tape is negative -- probably the calibration is wrong */
1356   if (tape < (real)0.0) {
1357      compile_warning(/*Negative adjusted tape reading*/79);
1358   }
1359
1360   if (VAL(Comp) == HUGE_REAL && VAL(BackComp) == HUGE_REAL) {
1361      /* plumb */
1362      dx = dy = (real)0.0;
1363      vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1364      /* FIXME: Should use FrDepth sometimes... */
1365      vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1366   } else {
1367      real sinB, cosB;
1368      real var_comp;
1369      real comp = handle_compass(&var_comp);
1370      sinB = sin(comp);
1371      cosB = cos(comp);
1372
1373      dx = tape * sinB;
1374      dy = tape * cosB;
1375
1376      vx = var(Q_POS) / 3.0 +
1377         VAR(Tape) * sinB * sinB + var_comp * dy * dy;
1378      vy = var(Q_POS) / 3.0 +
1379         VAR(Tape) * cosB * cosB + var_comp * dx * dx;
1380      /* FIXME: Should use FrDepth sometimes... */
1381      vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1382
1383#ifndef NO_COVARIANCES
1384      cxy = (VAR(Tape) - var_comp * tape * tape) * sinB * cosB;
1385#endif
1386   }
1387   addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1388#ifndef NO_COVARIANCES
1389                , cxy, 0, 0
1390#endif
1391                );
1392#ifdef CHASM3DX
1393   if (fUseNewFormat) {
1394      /* new twiglet and insert into twig tree */
1395      twig *twiglet = osnew(twig);
1396      twiglet->from = fr;
1397      twiglet->to = to;
1398      twiglet->down = twiglet->right = NULL;
1399      twiglet->source = twiglet->drawings
1400        = twiglet->date = twiglet->instruments = twiglet->tape = NULL;
1401      twiglet->up = limb->up;
1402      limb->right = twiglet;
1403      limb = twiglet;
1404
1405      /* record pre-fettling deltas */
1406      twiglet->delta[0] = dx;
1407      twiglet->delta[1] = dy;
1408      twiglet->delta[2] = dz;
1409   }
1410#endif
1411
1412   return 1;
1413}
1414
1415/* Process tape/compass/clino, diving, and cylpolar styles of survey data
1416 * Also handles topofil (fromcount/tocount or count) in place of tape */
1417extern int
1418data_normal(void)
1419{
1420   prefix *fr = NULL, *to = NULL;
1421   reading first_stn = End;
1422
1423   bool fTopofil = fFalse, fMulti = fFalse;
1424   bool fRev;
1425   clino_type ctype, backctype;
1426   bool fDepthChange;
1427   unsigned long compass_dat_flags = 0;
1428
1429   reading *ordering;
1430
1431   VAL(Tape) = 0;
1432   VAL(Comp) = VAL(BackComp) = HUGE_VAL;
1433   VAL(FrCount) = VAL(ToCount) = 0;
1434   VAL(FrDepth) = VAL(ToDepth) = 0;
1435
1436   fRev = fFalse;
1437   ctype = backctype = CTYPE_OMIT;
1438   fDepthChange = fFalse;
1439
1440   /* ordering may omit clino reading, so set up default here */
1441   /* this is also used if clino reading is the omit character */
1442   VAL(Clino) = VAL(BackClino) = 0;
1443
1444   again:
1445
1446   for (ordering = pcs->ordering; ; ordering++) {
1447      skipblanks();
1448      switch (*ordering) {
1449       case Fr:
1450          fr = read_prefix_stn(fFalse, fTrue);
1451          if (first_stn == End) first_stn = Fr;
1452          break;
1453       case To:
1454          to = read_prefix_stn(fFalse, fTrue);
1455          if (first_stn == End) first_stn = To;
1456          break;
1457       case Station:
1458          fr = to;
1459          to = read_prefix_stn(fFalse, fFalse);
1460          first_stn = To;
1461          break;
1462       case Dir: {
1463          typedef enum {
1464             DIR_NULL=-1, DIR_FORE, DIR_BACK
1465          } dir_tok;
1466          static sztok dir_tab[] = {
1467             {"B",     DIR_BACK},
1468             {"F",     DIR_FORE},
1469          };
1470          dir_tok tok;
1471          get_token();
1472          tok = match_tok(dir_tab, TABSIZE(dir_tab));
1473          switch (tok) {
1474           case DIR_FORE:
1475             break;
1476           case DIR_BACK:
1477             fRev = fTrue;
1478             break;
1479           default:
1480             compile_error_skip(/*Found `%s', expecting `F' or `B'*/131,
1481                                buffer);
1482             process_eol();
1483             return 0;
1484          }
1485          break;
1486       }
1487       case Tape:
1488          read_reading(Tape, fFalse);
1489          if (VAL(Tape) < (real)0.0)
1490             compile_warning(/*Negative tape reading*/60);
1491          break;
1492       case Count:
1493          VAL(FrCount) = VAL(ToCount);
1494          read_reading(ToCount, fFalse);
1495          fTopofil = fTrue;
1496          break;
1497       case FrCount:
1498          read_reading(FrCount, fFalse);
1499          break;
1500       case ToCount:
1501          read_reading(ToCount, fFalse);
1502          fTopofil = fTrue;
1503          break;
1504       case Comp:
1505          read_bearing_or_omit(Comp);
1506          break;
1507       case BackComp:
1508          read_bearing_or_omit(BackComp);
1509          break;
1510       case Clino:
1511          read_reading(Clino, fTrue);
1512          if (VAL(Clino) == HUGE_REAL) {
1513             VAL(Clino) = handle_plumb(&ctype);
1514             if (VAL(Clino) != HUGE_REAL) break;
1515             compile_error_token(/*Expecting numeric field, found `%s'*/9);
1516             process_eol();
1517             return 0;
1518          }
1519          ctype = CTYPE_READING;
1520          break;
1521       case BackClino:
1522          read_reading(BackClino, fTrue);
1523          if (VAL(BackClino) == HUGE_REAL) {
1524             VAL(BackClino) = handle_plumb(&backctype);
1525             if (VAL(BackClino) != HUGE_REAL) break;
1526             compile_error_token(/*Expecting numeric field, found `%s'*/9);
1527             process_eol();
1528             return 0;
1529          }
1530          backctype = CTYPE_READING;
1531          break;
1532       case FrDepth:
1533          read_reading(FrDepth, fFalse);
1534          break;
1535       case ToDepth:
1536          read_reading(ToDepth, fFalse);
1537          break;
1538       case Depth:
1539          VAL(FrDepth) = VAL(ToDepth);
1540          read_reading(ToDepth, fFalse);
1541          break;
1542       case DepthChange:
1543          fDepthChange = fTrue;
1544          VAL(FrDepth) = 0;
1545          read_reading(ToDepth, fFalse);
1546          break;
1547       case CompassDATComp:
1548          read_bearing_or_omit(Comp);
1549          if (is_compass_NaN(VAL(Comp))) VAL(Comp) = HUGE_REAL;
1550          break;
1551       case CompassDATBackComp:
1552          read_bearing_or_omit(BackComp);
1553          if (is_compass_NaN(VAL(BackComp))) VAL(BackComp) = HUGE_REAL;
1554          break;
1555       case CompassDATClino:
1556          read_reading(Clino, fTrue);
1557          if (is_compass_NaN(VAL(Clino))) {
1558             VAL(Clino) = HUGE_REAL;
1559             ctype = CTYPE_OMIT;
1560          } else if (VAL(Clino) == HUGE_REAL) {
1561             compile_error_token(/*Expecting numeric field, found `%s'*/9);
1562             process_eol();
1563             return 0;
1564          } else ctype = CTYPE_READING;
1565          break;
1566       case CompassDATBackClino:
1567          read_reading(BackClino, fTrue);
1568          if (is_compass_NaN(VAL(BackClino))) {
1569             VAL(BackClino) = HUGE_REAL;
1570             backctype = CTYPE_OMIT;
1571          } else if (VAL(BackClino) == HUGE_REAL) {
1572             compile_error_token(/*Expecting numeric field, found `%s'*/9);
1573             process_eol();
1574             return 0;
1575          } else backctype = CTYPE_READING;
1576          break;
1577       case CompassDATFlags:
1578          if (ch == '#') {
1579             nextch();
1580             if (ch == '|') {
1581                filepos fp;
1582                get_pos(&fp);
1583                nextch();
1584                while (ch >= 'A' && ch <= 'Z') {
1585                   compass_dat_flags |= BIT(ch - 'A');
1586                   /* FIXME: we currently understand X (exclude data)
1587                    * but should also handle at least some of:
1588                    * L exclude from length
1589                    * P no plot
1590                    * C no adjustment
1591                    */
1592                   nextch();
1593                }
1594                if (ch == '#') {
1595                   nextch();
1596                } else {
1597                   compass_dat_flags = 0;
1598                   set_pos(&fp);
1599                   push_back('|');
1600                   ch = '#';
1601                }
1602             } else {
1603                push_back(ch);
1604                ch = '#';
1605             }
1606          }
1607          break;
1608       case Ignore:
1609          skipword(); break;
1610       case IgnoreAllAndNewLine:
1611          skipline();
1612          /* fall through */
1613       case Newline:
1614          if (fr != NULL) {
1615             int r;
1616             if (fTopofil)
1617                VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1618             /* Note: frdepth == todepth test works regardless of fDepthChange
1619              * (frdepth always zero, todepth is change of depth) and also
1620              * works for STYLE_NORMAL (both remain 0) */
1621             if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1622                 VAL(Tape) == (real)0.0 && VAL(FrDepth) == VAL(ToDepth)) {
1623                process_equate(fr, to);
1624                goto inferred_equate;
1625             }
1626             if (fRev) {
1627                prefix *t = fr;
1628                fr = to;
1629                to = t;
1630             }
1631             if (fTopofil) {
1632                VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1633             } else {
1634                VAL(Tape) *= pcs->units[Q_LENGTH];
1635                VAL(Tape) -= pcs->z[Q_LENGTH];
1636                VAL(Tape) *= pcs->sc[Q_LENGTH];
1637             }
1638             switch (pcs->style) {
1639              case STYLE_NORMAL:
1640                r = process_normal(fr, to, (first_stn == To) ^ fRev,
1641                                   ctype, backctype);
1642                break;
1643              case STYLE_DIVING:
1644                r = process_diving(fr, to, (first_stn == To) ^ fRev,
1645                                   fDepthChange);
1646                break;
1647              case STYLE_CYLPOLAR:
1648                r = process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1649                                     fDepthChange);
1650                break;
1651              default:
1652                r = 0; /* avoid warning */
1653                BUG("bad style");
1654             }
1655             if (!r) skipline();
1656
1657             /* Swap fr and to back to how they were for next line */
1658             if (fRev) {
1659                prefix *t = fr;
1660                fr = to;
1661                to = t;
1662             }
1663          }
1664
1665          fRev = fFalse;
1666          ctype = backctype = CTYPE_OMIT;
1667          fDepthChange = fFalse;
1668
1669          /* ordering may omit clino reading, so set up default here */
1670          /* this is also used if clino reading is the omit character */
1671          VAL(Clino) = VAL(BackClino) = 0;
1672
1673          inferred_equate:
1674
1675          fMulti = fTrue;
1676          while (1) {
1677              process_eol();
1678              process_bol();
1679              if (isData(ch)) break;
1680              if (!isComm(ch)) {
1681                 push_back(ch);
1682                 return 1;
1683              }
1684          }
1685          break;
1686       case IgnoreAll:
1687          skipline();
1688          /* fall through */
1689       case End:
1690          if (!fMulti) {
1691             int r;
1692             /* Compass ignore flag is 'X' */
1693             if ((compass_dat_flags & BIT('X' - 'A'))) {
1694                process_eol();
1695                return 1;
1696             }
1697             if (fRev) {
1698                prefix *t = fr;
1699                fr = to;
1700                to = t;
1701             }
1702             if (fTopofil) VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1703             /* Note: frdepth == todepth test works regardless of fDepthChange
1704              * (frdepth always zero, todepth is change of depth) and also
1705              * works for STYLE_NORMAL (both remain 0) */
1706             if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1707                 VAL(Tape) == (real)0.0 && VAL(FrDepth) == VAL(ToDepth)) {
1708                process_equate(fr, to);
1709                process_eol();
1710                return 1;
1711             }
1712             if (fTopofil) {
1713                VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1714             } else {
1715                VAL(Tape) *= pcs->units[Q_LENGTH];
1716                VAL(Tape) -= pcs->z[Q_LENGTH];
1717                VAL(Tape) *= pcs->sc[Q_LENGTH];
1718             }
1719             switch (pcs->style) {
1720              case STYLE_NORMAL:
1721                r = process_normal(fr, to, (first_stn == To) ^ fRev,
1722                                   ctype, backctype);
1723                break;
1724              case STYLE_DIVING:
1725                r = process_diving(fr, to, (first_stn == To) ^ fRev,
1726                                   fDepthChange);
1727                break;
1728              case STYLE_CYLPOLAR:
1729                r = process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1730                                     fDepthChange);
1731                break;
1732              default:
1733                r = 0; /* Suppress compiler warning */;
1734                BUG("bad style");
1735             }
1736             process_eol();
1737             return r;
1738          }
1739          do {
1740             process_eol();
1741             process_bol();
1742          } while (isComm(ch));
1743          goto again;
1744       default:
1745          BUG("Unknown reading in ordering");
1746      }
1747   }
1748}
1749
1750static int
1751process_nosurvey(prefix *fr, prefix *to, bool fToFirst)
1752{
1753   nosurveylink *link;
1754   int shape;
1755
1756#ifdef CHASM3DX
1757   if (fUseNewFormat) {
1758      /* new twiglet and insert into twig tree */
1759      twig *twiglet = osnew(twig);
1760      twiglet->from = fr;
1761      twiglet->to = to;
1762      twiglet->down = twiglet->right = NULL;
1763      twiglet->source = twiglet->drawings
1764        = twiglet->date = twiglet->instruments = twiglet->tape = NULL;
1765      twiglet->up = limb->up;
1766      limb->right = twiglet;
1767      limb = twiglet;
1768      /* delta is only used to calculate error - pass zero and cope
1769       * elsewhere */
1770      twiglet->delta[0] = twiglet->delta[1] = twiglet->delta[2] = 0;
1771   }
1772#endif
1773
1774   /* Suppress "unused fixed point" warnings for these stations
1775    * We do this if it's a 0 or 1 node - 1 node might be an sdfix
1776    */
1777   shape = fr->shape;
1778   if (shape == 0 || shape == 1) fr->shape = -1 - shape;
1779   shape = to->shape;
1780   if (shape == 0 || shape == 1) to->shape = -1 - shape;
1781
1782   /* add to linked list which is dealt with after network is solved */
1783   link = osnew(nosurveylink);
1784   if (fToFirst) {
1785      link->to = StnFromPfx(to);
1786      link->fr = StnFromPfx(fr);
1787   } else {
1788      link->fr = StnFromPfx(fr);
1789      link->to = StnFromPfx(to);
1790   }
1791   link->flags = pcs->flags;
1792   link->next = nosurveyhead;
1793   nosurveyhead = link;
1794   return 1;
1795}
1796
1797extern int
1798data_nosurvey(void)
1799{
1800   prefix *fr = NULL, *to = NULL;
1801
1802   bool fMulti = fFalse;
1803
1804   reading first_stn = End;
1805
1806   reading *ordering;
1807
1808   again:
1809
1810   for (ordering = pcs->ordering ; ; ordering++) {
1811      skipblanks();
1812      switch (*ordering) {
1813       case Fr:
1814          fr = read_prefix_stn(fFalse, fTrue);
1815          if (first_stn == End) first_stn = Fr;
1816          break;
1817       case To:
1818          to = read_prefix_stn(fFalse, fTrue);
1819          if (first_stn == End) first_stn = To;
1820          break;
1821       case Station:
1822          fr = to;
1823          to = read_prefix_stn(fFalse, fFalse);
1824          first_stn = To;
1825          break;
1826       case Ignore:
1827         skipword(); break;
1828       case IgnoreAllAndNewLine:
1829         skipline();
1830         /* fall through */
1831       case Newline:
1832         if (fr != NULL) {
1833            int r;
1834            r = process_nosurvey(fr, to, first_stn == To);
1835            if (!r) skipline();
1836         }
1837         if (ordering[1] == End) {
1838            do {
1839               process_eol();
1840               process_bol();
1841            } while (isComm(ch));
1842            if (!isData(ch)) {
1843               push_back(ch);
1844               return 1;
1845            }
1846            goto again;
1847         }
1848         fMulti = fTrue;
1849         while (1) {
1850            process_eol();
1851            process_bol();
1852            if (isData(ch)) break;
1853            if (!isComm(ch)) {
1854               push_back(ch);
1855               return 1;
1856            }
1857         }
1858         break;
1859       case IgnoreAll:
1860         skipline();
1861         /* fall through */
1862       case End:
1863         if (!fMulti) {
1864            int r = process_nosurvey(fr, to, first_stn == To);
1865            process_eol();
1866            return r;
1867         }
1868         do {
1869            process_eol();
1870            process_bol();
1871         } while (isComm(ch));
1872         goto again;
1873       default: BUG("Unknown reading in ordering");
1874      }
1875   }
1876}
1877
1878/* totally ignore a line of survey data */
1879extern int
1880data_ignore(void)
1881{
1882   skipline();
1883   process_eol();
1884   return 1;
1885}
Note: See TracBrowser for help on using the repository browser.