Show line contents with compile errors or warnings
[survex.git] / src / datain.c
blob19c5fc787d35f688903fc4b35cc6b960bb85ed55
1 /* datain.c
2 * Reads in survey files, dealing with special characters, keywords & data
3 * Copyright (C) 1991-2003,2005,2009,2010,2011,2012,2013,2014,2015,2016 Olly Betts
4 * Copyright (C) 2004 Simeon Warner
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <limits.h>
26 #include <stdarg.h>
28 #include "debug.h"
29 #include "cavern.h"
30 #include "date.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 #include "thgeomag.h"
43 #define EPSILON (REAL_EPSILON * 1000)
45 #define var(I) (pcs->Var[(I)])
47 /* true if x is not-a-number value in Compass (999.0 or -999.0) */
48 /* Compass uses 999.0 but understands Karst data which used -999.0 */
49 #define is_compass_NaN(x) ( fabs(fabs(x)-999.0) < EPSILON )
51 int ch;
53 typedef enum {
54 CTYPE_OMIT, CTYPE_READING, CTYPE_PLUMB, CTYPE_INFERPLUMB, CTYPE_HORIZ
55 } clino_type;
57 /* Don't explicitly initialise as we can't set the jmp_buf - this has
58 * static scope so will be initialised like this anyway */
59 parse file /* = { NULL, NULL, 0, fFalse, NULL } */ ;
61 bool f_export_ok;
63 static real value[Fr - 1];
64 #define VAL(N) value[(N)-1]
65 static real variance[Fr - 1];
66 #define VAR(N) variance[(N)-1]
67 static long location[Fr - 1];
68 #define LOC(N) location[(N)-1]
70 /* style functions */
71 static void data_normal(void);
72 static void data_cartesian(void);
73 static void data_passage(void);
74 static void data_nosurvey(void);
75 static void data_ignore(void);
77 void
78 get_pos(filepos *fp)
80 fp->ch = ch;
81 fp->offset = ftell(file.fh);
82 if (fp->offset == -1)
83 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
86 void
87 set_pos(const filepos *fp)
89 ch = fp->ch;
90 if (fseek(file.fh, fp->offset, SEEK_SET) == -1)
91 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
94 static void
95 report_parent(parse * p) {
96 if (p->parent)
97 report_parent(p->parent);
98 /* Force re-report of include tree for further errors in
99 * parent files */
100 p->reported_where = fFalse;
101 /* TRANSLATORS: %s is replaced by the filename of the parent file, and %u
102 * by the line number in that file. Your translation should also contain
103 * %s:%u so that automatic parsing of error messages to determine the file
104 * and line number still works. */
105 fprintf(STDERR, msg(/*In file included from %s:%u:\n*/5), p->filename, p->line);
108 static void
109 error_list_parent_files(void)
111 if (!file.reported_where && file.parent) {
112 report_parent(file.parent);
113 /* Suppress reporting of full include tree for further errors
114 * in this file */
115 file.reported_where = fTrue;
119 void v_report_line_contents(const char *filename, unsigned line, ...);
122 void
123 v_report_line_contents(const char *filename, unsigned line, ...)
125 va_list ap;
126 va_start(ap, line);
127 v_report(-1, filename, line, 0, 0, ap);
128 va_end(ap);
132 char *get_line_contents();
134 char*
135 get_line_contents()
137 #define MAX_REPORTING_WIDTH 80
138 filepos fp_stored;
139 filepos fp;
140 static char line[MAX_REPORTING_WIDTH + 1];
141 int p = 0;
143 /* Rewind to beginning of line */
144 get_pos(&fp_stored);
146 fp.ch = '\n';
147 fp.offset = file.lpos;
148 set_pos(&fp);
150 /* Read the line until EOL */
151 while((p < MAX_REPORTING_WIDTH) && (!feof(file.fh)))
153 nextch();
154 if(isEol(ch)) break;
155 line[p++] = ch;
157 line[p++] = 0;
159 /* Revert to where we were */
160 set_pos(&fp_stored);
162 return line;
165 static void
166 compile_v_report(int severity, int en, va_list ap)
168 int col = 0;
169 error_list_parent_files();
170 if (en < 0) {
171 en = -en;
172 if (file.fh) col = ftell(file.fh) - file.lpos;
174 if(file.fh)
175 v_report_line_contents(file.filename, file.line, get_line_contents());
176 v_report(severity, file.filename, file.line, col, en, ap);
179 void
180 compile_error(int en, ...)
182 va_list ap;
183 va_start(ap, en);
184 compile_v_report(1, en, ap);
185 va_end(ap);
188 void
189 compile_error_skip(int en, ...)
191 va_list ap;
192 va_start(ap, en);
193 compile_v_report(1, en, ap);
194 va_end(ap);
195 skipline();
198 static void
199 compile_error_reading(reading r, int en, ...)
201 va_list ap;
202 int col = 0;
203 va_start(ap, en);
204 error_list_parent_files();
205 if (LOC(r) >= file.lpos) col = LOC(r) - file.lpos;
206 v_report(1, file.filename, file.line, col, en, ap);
207 va_end(ap);
210 static void
211 compile_error_reading_skip(reading r, int en, ...)
213 va_list ap;
214 int col = 0;
215 va_start(ap, en);
216 error_list_parent_files();
217 if (LOC(r) >= file.lpos) col = LOC(r) - file.lpos;
218 v_report(1, file.filename, file.line, col, en, ap);
219 va_end(ap);
220 skipline();
223 void
224 compile_error_at(const char * filename, unsigned line, int en, ...)
226 va_list ap;
227 va_start(ap, en);
228 v_report(1, filename, line, 0, en, ap);
229 va_end(ap);
232 void
233 compile_error_pfx(const prefix * pfx, int en, ...)
235 va_list ap;
236 va_start(ap, en);
237 v_report(1, pfx->filename, pfx->line, 0, en, ap);
238 va_end(ap);
241 void
242 compile_error_token(int en)
244 char *p = NULL;
245 int len = 0;
246 skipblanks();
247 while (!isBlank(ch) && !isEol(ch)) {
248 s_catchar(&p, &len, (char)ch);
249 nextch();
251 compile_error(en, p ? p : "");
252 osfree(p);
255 void
256 compile_warning(int en, ...)
258 va_list ap;
259 va_start(ap, en);
260 compile_v_report(0, en, ap);
261 va_end(ap);
264 void
265 compile_warning_at(const char * filename, unsigned line, int en, ...)
267 va_list ap;
268 va_start(ap, en);
269 v_report(0, filename, line, 0, en, ap);
270 va_end(ap);
273 void
274 compile_warning_pfx(const prefix * pfx, int en, ...)
276 va_list ap;
277 va_start(ap, en);
278 v_report(0, pfx->filename, pfx->line, 0, en, ap);
279 va_end(ap);
282 /* This function makes a note where to put output files */
283 static void
284 using_data_file(const char *fnm)
286 if (!fnm_output_base) {
287 /* was: fnm_output_base = base_from_fnm(fnm); */
288 fnm_output_base = baseleaf_from_fnm(fnm);
289 } else if (fnm_output_base_is_dir) {
290 /* --output pointed to directory so use the leaf basename in that dir */
291 char *lf, *p;
292 lf = baseleaf_from_fnm(fnm);
293 p = use_path(fnm_output_base, lf);
294 osfree(lf);
295 osfree(fnm_output_base);
296 fnm_output_base = p;
297 fnm_output_base_is_dir = 0;
301 static void
302 skipword(void)
304 while (!isBlank(ch) && !isEol(ch)) nextch();
307 extern void
308 skipblanks(void)
310 while (isBlank(ch)) nextch();
313 extern void
314 skipline(void)
316 while (!isEol(ch)) nextch();
319 static void
320 process_eol(void)
322 int eolchar;
324 skipblanks();
326 if (!isEol(ch)) {
327 if (!isComm(ch)) compile_error(-/*End of line not blank*/15);
328 skipline();
331 eolchar = ch;
332 file.line++;
333 /* skip any different eol characters so we get line counts correct on
334 * DOS text files and similar, but don't count several adjacent blank
335 * lines as one */
336 while (ch != EOF) {
337 nextch();
338 if (ch == eolchar || !isEol(ch)) {
339 break;
341 if (ch == '\n') eolchar = ch;
343 file.lpos = ftell(file.fh) - 1;
346 static bool
347 process_non_data_line(void)
349 skipblanks();
351 if (isData(ch)) return fFalse;
353 if (isKeywd(ch)) {
354 nextch();
355 handle_command();
358 process_eol();
360 return fTrue;
363 static void
364 read_reading(reading r, bool f_optional)
366 int n_readings;
367 q_quantity q;
368 switch (r) {
369 case Tape: q = Q_LENGTH; break;
370 case BackTape: q = Q_BACKLENGTH; break;
371 case Comp: q = Q_BEARING; break;
372 case BackComp: q = Q_BACKBEARING; break;
373 case Clino: q = Q_GRADIENT; break;
374 case BackClino: q = Q_BACKGRADIENT; break;
375 case FrDepth: case ToDepth: q = Q_DEPTH; break;
376 case Dx: q = Q_DX; break;
377 case Dy: q = Q_DY; break;
378 case Dz: q = Q_DZ; break;
379 case FrCount: case ToCount: q = Q_COUNT; break;
380 case Left: q = Q_LEFT; break;
381 case Right: q = Q_RIGHT; break;
382 case Up: q = Q_UP; break;
383 case Down: q = Q_DOWN; break;
384 default:
385 q = Q_NULL; /* Suppress compiler warning */;
386 BUG("Unexpected case");
388 LOC(r) = ftell(file.fh);
389 VAL(r) = read_numeric_multi(f_optional, &n_readings);
390 VAR(r) = var(q);
391 if (n_readings > 1) VAR(r) /= sqrt(n_readings);
394 static void
395 read_bearing_or_omit(reading r)
397 int n_readings;
398 q_quantity q = Q_NULL;
399 LOC(r) = ftell(file.fh);
400 VAL(r) = read_numeric_multi_or_omit(&n_readings);
401 switch (r) {
402 case Comp: q = Q_BEARING; break;
403 case BackComp: q = Q_BACKBEARING; break;
404 default:
405 q = Q_NULL; /* Suppress compiler warning */;
406 BUG("Unexpected case");
408 VAR(r) = var(q);
409 if (n_readings > 1) VAR(r) /= sqrt(n_readings);
412 /* For reading Compass MAK files which have a freeform syntax */
413 static void
414 nextch_handling_eol(void)
416 nextch();
417 while (ch != EOF && isEol(ch)) {
418 process_eol();
422 #define LITLEN(S) (sizeof(S"") - 1)
423 #define has_ext(F,L,E) ((L) > LITLEN(E) + 1 &&\
424 (F)[(L) - LITLEN(E) - 1] == FNM_SEP_EXT &&\
425 strcasecmp((F) + (L) - LITLEN(E), E) == 0)
426 extern void
427 data_file(const char *pth, const char *fnm)
429 int begin_lineno_store;
430 parse file_store;
431 volatile enum {FMT_SVX, FMT_DAT, FMT_MAK} fmt = FMT_SVX;
434 char *filename;
435 FILE *fh;
436 size_t len;
438 if (!pth) {
439 /* file specified on command line - don't do special translation */
440 fh = fopenWithPthAndExt(pth, fnm, EXT_SVX_DATA, "rb", &filename);
441 } else {
442 fh = fopen_portable(pth, fnm, EXT_SVX_DATA, "rb", &filename);
445 if (fh == NULL) {
446 compile_error(-/*Couldnā€™t open file ā€œ%sā€*/24, fnm);
447 return;
450 len = strlen(filename);
451 if (has_ext(filename, len, "dat")) {
452 fmt = FMT_DAT;
453 } else if (has_ext(filename, len, "mak")) {
454 fmt = FMT_MAK;
457 file_store = file;
458 if (file.fh) file.parent = &file_store;
459 file.fh = fh;
460 file.filename = filename;
461 file.line = 1;
462 file.lpos = 0;
463 file.reported_where = fFalse;
464 nextch();
467 using_data_file(file.filename);
469 begin_lineno_store = pcs->begin_lineno;
470 pcs->begin_lineno = 0;
472 if (fmt == FMT_DAT) {
473 short *t;
474 int i;
475 settings *pcsNew;
477 pcsNew = osnew(settings);
478 *pcsNew = *pcs; /* copy contents */
479 pcsNew->begin_lineno = 0;
480 pcsNew->next = pcs;
481 pcs = pcsNew;
482 default_units(pcs);
483 default_calib(pcs);
485 pcs->style = STYLE_NORMAL;
486 pcs->units[Q_LENGTH] = METRES_PER_FOOT;
487 t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
489 t[EOF] = SPECIAL_EOL;
490 memset(t, 0, sizeof(short) * 33);
491 for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
492 t[127] = 0;
493 for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
494 t['\t'] |= SPECIAL_BLANK;
495 t[' '] |= SPECIAL_BLANK;
496 t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
497 t['\n'] |= SPECIAL_EOL;
498 t['\r'] |= SPECIAL_EOL;
499 t['.'] |= SPECIAL_DECIMAL;
500 t['-'] |= SPECIAL_MINUS;
501 t['+'] |= SPECIAL_PLUS;
502 pcs->Translate = t;
503 pcs->Case = OFF;
504 pcs->Truncate = INT_MAX;
505 pcs->infer = BIT(INFER_EQUATES)|BIT(INFER_EXPORTS)|BIT(INFER_PLUMBS);
506 } else if (fmt == FMT_MAK) {
507 short *t;
508 int i;
509 settings *pcsNew;
511 pcsNew = osnew(settings);
512 *pcsNew = *pcs; /* copy contents */
513 pcsNew->begin_lineno = 0;
514 pcsNew->next = pcs;
515 pcs = pcsNew;
517 t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
519 t[EOF] = SPECIAL_EOL;
520 memset(t, 0, sizeof(short) * 33);
521 for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
522 t[127] = 0;
523 for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
524 t['['] = t[','] = t[';'] = 0;
525 t['\t'] |= SPECIAL_BLANK;
526 t[' '] |= SPECIAL_BLANK;
527 t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
528 t['\n'] |= SPECIAL_EOL;
529 t['\r'] |= SPECIAL_EOL;
530 t['.'] |= SPECIAL_DECIMAL;
531 t['-'] |= SPECIAL_MINUS;
532 t['+'] |= SPECIAL_PLUS;
533 pcs->Translate = t;
534 pcs->Case = OFF;
535 pcs->Truncate = INT_MAX;
538 #ifdef HAVE_SETJMP_H
539 /* errors in nested functions can longjmp here */
540 if (setjmp(file.jbSkipLine)) {
541 skipline();
542 process_eol();
544 #endif
546 if (fmt == FMT_DAT) {
547 while (!feof(file.fh) && !ferror(file.fh)) {
548 static reading compass_order[] = {
549 Fr, To, Tape, CompassDATComp, CompassDATClino,
550 CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
551 CompassDATFlags, IgnoreAll
553 static reading compass_order_backsights[] = {
554 Fr, To, Tape, CompassDATComp, CompassDATClino,
555 CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
556 CompassDATBackComp, CompassDATBackClino,
557 CompassDATFlags, IgnoreAll
559 /* <Cave name> */
560 skipline();
561 process_eol();
562 /* SURVEY NAME: <Short name> */
563 get_token();
564 get_token();
565 /* if (ch != ':') ... */
566 nextch();
567 get_token();
568 skipline();
569 process_eol();
570 /* SURVEY DATE: 7 10 79 COMMENT:<Long name> */
571 get_token();
572 get_token();
573 copy_on_write_meta(pcs);
574 if (ch == ':') {
575 int year, month, day;
577 nextch();
579 /* NB order is *month* *day* year */
580 month = read_uint();
581 day = read_uint();
582 year = read_uint();
583 /* Note: Larry says a 2 digit year is always 19XX */
584 if (year < 100) year += 1900;
586 pcs->meta->days1 = pcs->meta->days2 = days_since_1900(year, month, day);
587 } else {
588 pcs->meta->days1 = pcs->meta->days2 = -1;
590 pcs->declination = HUGE_REAL;
591 skipline();
592 process_eol();
593 /* SURVEY TEAM: */
594 get_token();
595 get_token();
596 skipline();
597 process_eol();
598 /* <Survey team> */
599 nextch();
600 skipline();
601 process_eol();
602 /* DECLINATION: 1.00 FORMAT: DDDDLUDRADLN CORRECTIONS: 2.00 3.00 4.00 */
603 get_token();
604 nextch(); /* : */
605 skipblanks();
606 pcs->z[Q_DECLINATION] = -read_numeric(fFalse);
607 pcs->z[Q_DECLINATION] *= pcs->units[Q_DECLINATION];
608 get_token();
609 pcs->ordering = compass_order;
610 if (strcmp(buffer, "FORMAT") == 0) {
611 nextch(); /* : */
612 get_token();
613 if (strlen(buffer) >= 12 && buffer[11] == 'B') {
614 /* We have backsights for compass and clino */
615 pcs->ordering = compass_order_backsights;
617 get_token();
619 if (strcmp(buffer, "CORRECTIONS") == 0) {
620 nextch(); /* : */
621 pcs->z[Q_BEARING] = -rad(read_numeric(fFalse));
622 pcs->z[Q_GRADIENT] = -rad(read_numeric(fFalse));
623 pcs->z[Q_LENGTH] = -read_numeric(fFalse);
624 } else {
625 pcs->z[Q_BEARING] = 0;
626 pcs->z[Q_GRADIENT] = 0;
627 pcs->z[Q_LENGTH] = 0;
629 skipline();
630 process_eol();
631 /* BLANK LINE */
632 skipline();
633 process_eol();
634 /* heading line */
635 skipline();
636 process_eol();
637 /* BLANK LINE */
638 skipline();
639 process_eol();
640 while (!feof(file.fh)) {
641 if (ch == '\x0c') {
642 nextch();
643 process_eol();
644 break;
646 data_normal();
648 clear_last_leg();
651 settings *pcsParent = pcs->next;
652 SVX_ASSERT(pcsParent);
653 pcs->ordering = NULL;
654 free_settings(pcs);
655 pcs = pcsParent;
657 } else if (fmt == FMT_MAK) {
658 nextch_handling_eol();
659 while (!feof(file.fh) && !ferror(file.fh)) {
660 if (ch == '#') {
661 /* include a file */
662 int ch_store;
663 char *dat_pth = path_from_fnm(file.filename);
664 char *dat_fnm = NULL;
665 int dat_fnm_len;
666 nextch_handling_eol();
667 while (ch != ',' && ch != ';' && ch != EOF) {
668 while (isEol(ch)) process_eol();
669 s_catchar(&dat_fnm, &dat_fnm_len, (char)ch);
670 nextch_handling_eol();
672 while (ch != ';' && ch != EOF) {
673 prefix *name;
674 nextch_handling_eol();
675 name = read_prefix(PFX_STATION|PFX_OPT);
676 if (name) {
677 skipblanks();
678 if (ch == '[') {
679 /* fixed pt */
680 node *stn;
681 real x, y, z;
682 name->sflags |= BIT(SFLAGS_FIXED);
683 nextch_handling_eol();
684 while (!isdigit(ch) && ch != '+' && ch != '-' &&
685 ch != '.' && ch != ']' && ch != EOF) {
686 nextch_handling_eol();
688 x = read_numeric(fFalse);
689 while (!isdigit(ch) && ch != '+' && ch != '-' &&
690 ch != '.' && ch != ']' && ch != EOF) {
691 nextch_handling_eol();
693 y = read_numeric(fFalse);
694 while (!isdigit(ch) && ch != '+' && ch != '-' &&
695 ch != '.' && ch != ']' && ch != EOF) {
696 nextch_handling_eol();
698 z = read_numeric(fFalse);
699 stn = StnFromPfx(name);
700 if (!fixed(stn)) {
701 POS(stn, 0) = x;
702 POS(stn, 1) = y;
703 POS(stn, 2) = z;
704 fix(stn);
705 } else {
706 if (x != POS(stn, 0) || y != POS(stn, 1) ||
707 z != POS(stn, 2)) {
708 compile_error(/*Station already fixed or equated to a fixed point*/46);
709 } else {
710 compile_warning(/*Station already fixed at the same coordinates*/55);
713 while (ch != ']' && ch != EOF) nextch_handling_eol();
714 if (ch == ']') {
715 nextch_handling_eol();
716 skipblanks();
718 } else {
719 /* FIXME: link station - ignore for now */
720 /* FIXME: perhaps issue warning? */
722 while (ch != ',' && ch != ';' && ch != EOF)
723 nextch_handling_eol();
726 if (dat_fnm) {
727 ch_store = ch;
728 data_file(dat_pth, dat_fnm);
729 ch = ch_store;
730 osfree(dat_fnm);
732 } else {
733 /* FIXME: also check for % and $ later */
734 nextch_handling_eol();
738 settings *pcsParent = pcs->next;
739 SVX_ASSERT(pcsParent);
740 free_settings(pcs);
741 pcs = pcsParent;
743 } else {
744 while (!feof(file.fh) && !ferror(file.fh)) {
745 if (!process_non_data_line()) {
746 f_export_ok = fFalse;
747 switch (pcs->style) {
748 case STYLE_NORMAL:
749 case STYLE_DIVING:
750 case STYLE_CYLPOLAR:
751 data_normal();
752 break;
753 case STYLE_CARTESIAN:
754 data_cartesian();
755 break;
756 case STYLE_PASSAGE:
757 data_passage();
758 break;
759 case STYLE_NOSURVEY:
760 data_nosurvey();
761 break;
762 case STYLE_IGNORE:
763 data_ignore();
764 break;
765 default:
766 BUG("bad style");
770 clear_last_leg();
773 /* don't allow *BEGIN at the end of a file, then *EXPORT in the
774 * including file */
775 f_export_ok = fFalse;
777 if (pcs->begin_lineno) {
778 error_in_file(file.filename, pcs->begin_lineno,
779 /*BEGIN with no matching END in this file*/23);
780 /* Implicitly close any unclosed BEGINs from this file */
781 do {
782 settings *pcsParent = pcs->next;
783 SVX_ASSERT(pcsParent);
784 free_settings(pcs);
785 pcs = pcsParent;
786 } while (pcs->begin_lineno);
789 pcs->begin_lineno = begin_lineno_store;
791 if (ferror(file.fh))
792 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
794 (void)fclose(file.fh);
796 file = file_store;
798 /* don't free this - it may be pointed to by prefix.file */
799 /* osfree(file.filename); */
802 static real
803 mod2pi(real a)
805 return a - floor(a / (2 * M_PI)) * (2 * M_PI);
808 static real
809 handle_plumb(clino_type *p_ctype)
811 typedef enum {
812 CLINO_NULL=-1, CLINO_UP, CLINO_DOWN, CLINO_LEVEL
813 } clino_tok;
814 static sztok clino_tab[] = {
815 {"D", CLINO_DOWN},
816 {"DOWN", CLINO_DOWN},
817 {"H", CLINO_LEVEL},
818 {"LEVEL", CLINO_LEVEL},
819 {"U", CLINO_UP},
820 {"UP", CLINO_UP},
821 {NULL, CLINO_NULL}
823 static real clinos[] = {(real)M_PI_2, (real)(-M_PI_2), (real)0.0};
824 clino_tok tok;
826 skipblanks();
827 if (isalpha(ch)) {
828 filepos fp;
829 get_pos(&fp);
830 get_token();
831 tok = match_tok(clino_tab, TABSIZE(clino_tab));
832 if (tok != CLINO_NULL) {
833 *p_ctype = (tok == CLINO_LEVEL ? CTYPE_HORIZ : CTYPE_PLUMB);
834 return clinos[tok];
836 set_pos(&fp);
837 } else if (isSign(ch)) {
838 int chOld = ch;
839 nextch();
840 if (toupper(ch) == 'V') {
841 nextch();
842 *p_ctype = CTYPE_PLUMB;
843 return (!isMinus(chOld) ? M_PI_2 : -M_PI_2);
846 if (isOmit(chOld)) {
847 *p_ctype = CTYPE_OMIT;
848 /* no clino reading, so assume 0 with large sd */
849 return (real)0.0;
851 } else if (isOmit(ch)) {
852 /* OMIT char may not be a SIGN char too so we need to check here as
853 * well as above... */
854 nextch();
855 *p_ctype = CTYPE_OMIT;
856 /* no clino reading, so assume 0 with large sd */
857 return (real)0.0;
859 return HUGE_REAL;
862 static void
863 warn_readings_differ(int msgno, real diff, int units)
865 char buf[64];
866 char *p;
867 diff /= get_units_factor(units);
868 sprintf(buf, "%.2f", fabs(diff));
869 for (p = buf; *p; ++p) {
870 if (*p == '.') {
871 char *z = p;
872 while (*++p) {
873 if (*p != '0') z = p + 1;
875 p = z;
876 break;
879 strcpy(p, get_units_string(units));
880 compile_warning(msgno, buf);
883 static bool
884 handle_comp_units(void)
886 bool fNoComp = fTrue;
887 if (VAL(Comp) != HUGE_REAL) {
888 fNoComp = fFalse;
889 VAL(Comp) *= pcs->units[Q_BEARING];
890 if (VAL(Comp) < (real)0.0 || VAL(Comp) - M_PI * 2.0 > EPSILON) {
891 /* TRANSLATORS: Suspicious means something like 410 degrees or -20
892 * degrees */
893 compile_warning(/*Suspicious compass reading*/59);
894 VAL(Comp) = mod2pi(VAL(Comp));
897 if (VAL(BackComp) != HUGE_REAL) {
898 fNoComp = fFalse;
899 VAL(BackComp) *= pcs->units[Q_BACKBEARING];
900 if (VAL(BackComp) < (real)0.0 || VAL(BackComp) - M_PI * 2.0 > EPSILON) {
901 /* FIXME: different message for BackComp? */
902 compile_warning(/*Suspicious compass reading*/59);
903 VAL(BackComp) = mod2pi(VAL(BackComp));
906 return fNoComp;
909 static real
910 handle_compass(real *p_var)
912 real compvar = VAR(Comp);
913 real comp = VAL(Comp);
914 real backcomp = VAL(BackComp);
915 real declination;
916 if (pcs->z[Q_DECLINATION] != HUGE_REAL) {
917 declination = -pcs->z[Q_DECLINATION];
918 } else if (pcs->declination != HUGE_REAL) {
919 /* Cached value calculated for a previous compass reading taken on the
920 * same date (by the 'else' just below).
922 declination = pcs->declination;
923 } else {
924 if (!pcs->meta || pcs->meta->days1 == -1) {
925 compile_warning(/*No survey date specified - using 0 for magnetic declination*/304);
926 declination = 0;
927 } else {
928 int avg_days = (pcs->meta->days1 + pcs->meta->days2) / 2;
929 double dat = julian_date_from_days_since_1900(avg_days);
930 /* thgeomag() takes (lat, lon, h, dat) - i.e. (y, x, z, date). */
931 declination = thgeomag(pcs->dec_y, pcs->dec_x, pcs->dec_z, dat);
933 declination -= pcs->convergence;
934 /* We cache the calculated declination as the calculation is relatively
935 * expensive. We also cache an "assumed 0" answer so that we only
936 * warn once per such survey rather than for every line with a compass
937 * reading. */
938 pcs->declination = declination;
940 if (comp != HUGE_REAL) {
941 comp = (comp - pcs->z[Q_BEARING]) * pcs->sc[Q_BEARING];
942 comp += declination;
944 if (backcomp != HUGE_REAL) {
945 backcomp = (backcomp - pcs->z[Q_BACKBEARING])
946 * pcs->sc[Q_BACKBEARING];
947 backcomp += declination;
948 backcomp -= M_PI;
949 if (comp != HUGE_REAL) {
950 real diff = comp - backcomp;
951 real adj = fabs(diff) > M_PI ? M_PI : 0;
952 diff -= floor((diff + M_PI) / (2 * M_PI)) * 2 * M_PI;
953 if (sqrd(diff / 3.0) > compvar + VAR(BackComp)) {
954 /* fore and back readings differ by more than 3 sds */
955 /* TRANSLATORS: %s is replaced by the amount the readings disagree
956 * by, e.g. "2.5Ā°" or "3įµ". */
957 warn_readings_differ(/*COMPASS reading and BACKCOMPASS reading disagree by %s*/98,
958 diff, get_angle_units(Q_BEARING));
960 comp = (comp / compvar + backcomp / VAR(BackComp));
961 compvar = (compvar + VAR(BackComp)) / 4;
962 comp *= compvar;
963 comp += adj;
964 } else {
965 comp = backcomp;
966 compvar = VAR(BackComp);
969 *p_var = compvar;
970 return comp;
973 static int
974 process_normal(prefix *fr, prefix *to, bool fToFirst,
975 clino_type ctype, clino_type backctype)
977 real tape = VAL(Tape);
978 real clin = VAL(Clino);
979 real backclin = VAL(BackClino);
981 real dx, dy, dz;
982 real vx, vy, vz;
983 #ifndef NO_COVARIANCES
984 real cxy, cyz, czx;
985 #endif
987 bool fNoComp;
989 /* adjusted tape is negative -- probably the calibration is wrong */
990 if (tape < (real)0.0) {
991 /* TRANSLATE different message for topofil? */
992 compile_warning(/*Negative adjusted tape reading*/79);
995 fNoComp = handle_comp_units();
997 if (ctype == CTYPE_READING) {
998 bool range_0_180;
999 real z;
1000 real diff_from_abs90;
1001 clin *= pcs->units[Q_GRADIENT];
1002 /* percentage scale */
1003 if (pcs->f_clino_percent) clin = atan(clin);
1004 /* We want to warn if there's a reading which it would be impossible
1005 * to have read from the instrument (e.g. on a -90 to 90 degree scale
1006 * you can't read "96" (it's probably a typo for "69"). However, the
1007 * gradient reading from a topofil is typically in the range 0 to 180,
1008 * with 90 being horizontal.
1010 * Really we should allow the valid range to be specified, but for now
1011 * we infer it from the zero error - if this is within 45 degrees of
1012 * 90 then we assume the range is 0 to 180.
1014 z = pcs->z[Q_GRADIENT];
1015 range_0_180 = (z > M_PI_4 && z < 3*M_PI_4);
1016 diff_from_abs90 = fabs(clin) - M_PI_2;
1017 if (diff_from_abs90 > EPSILON) {
1018 if (!range_0_180) {
1019 int clino_units = get_angle_units(Q_GRADIENT);
1020 const char * units = get_units_string(clino_units);
1021 real right_angle = M_PI_2 / get_units_factor(clino_units);
1022 /* TRANSLATORS: %.f%s will be replaced with a right angle in the
1023 * units currently in use, e.g. "90Ā°" or "100įµ". And "absolute
1024 * value" means the reading ignoring the sign (so it might be
1025 * < -90Ā° or > 90Ā°. */
1026 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1027 right_angle, units);
1029 } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
1030 diff_from_abs90 >= -EPSILON) {
1031 ctype = CTYPE_INFERPLUMB;
1033 if (range_0_180 && ctype != CTYPE_INFERPLUMB) {
1034 /* FIXME: Warning message not ideal... */
1035 if (clin < 0.0 || clin - M_PI > EPSILON) {
1036 int clino_units = get_angle_units(Q_GRADIENT);
1037 const char * units = get_units_string(clino_units);
1038 real right_angle = M_PI_2 / get_units_factor(clino_units);
1039 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1040 right_angle, units);
1045 if (backctype == CTYPE_READING) {
1046 backclin *= pcs->units[Q_BACKGRADIENT];
1047 /* percentage scale */
1048 if (pcs->f_backclino_percent) backclin = atan(backclin);
1049 /* FIXME: Add range_0_180 handling here too */
1050 if (ctype != CTYPE_READING) {
1051 real diff_from_abs90 = fabs(backclin) - M_PI_2;
1052 if (diff_from_abs90 > EPSILON) {
1053 /* FIXME: different message for BackClino? */
1054 int clino_units = get_angle_units(Q_BACKGRADIENT);
1055 const char * units = get_units_string(clino_units);
1056 real right_angle = M_PI_2 / get_units_factor(clino_units);
1057 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1058 right_angle, units);
1059 } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
1060 diff_from_abs90 >= -EPSILON) {
1061 backctype = CTYPE_INFERPLUMB;
1066 /* un-infer the plumb if the backsight was just a reading */
1067 if (ctype == CTYPE_INFERPLUMB && backctype == CTYPE_READING) {
1068 ctype = CTYPE_READING;
1071 if (ctype != CTYPE_OMIT && backctype != CTYPE_OMIT && ctype != backctype) {
1072 /* TRANSLATORS: In data with backsights, the user has tried to give a
1073 * plumb for the foresight and a clino reading for the backsight, or
1074 * something similar. */
1075 compile_error_reading_skip(Clino, /*CLINO and BACKCLINO readings must be of the same type*/84);
1076 return 0;
1079 if (ctype == CTYPE_PLUMB || ctype == CTYPE_INFERPLUMB ||
1080 backctype == CTYPE_PLUMB || backctype == CTYPE_INFERPLUMB) {
1081 /* plumbed */
1082 if (!fNoComp) {
1083 if (ctype == CTYPE_PLUMB ||
1084 (ctype == CTYPE_INFERPLUMB && VAL(Comp) != 0.0) ||
1085 backctype == CTYPE_PLUMB ||
1086 (backctype == CTYPE_INFERPLUMB && VAL(BackComp) != 0.0)) {
1087 /* FIXME: Different message for BackComp? */
1088 /* TRANSLATORS: A "plumbed leg" is one measured using a plumbline
1089 * (a weight on a string). So the problem here is that the leg is
1090 * vertical, so a compass reading has no meaning! */
1091 compile_warning(/*Compass reading given on plumbed leg*/21);
1095 dx = dy = (real)0.0;
1096 if (ctype != CTYPE_OMIT) {
1097 if (backctype != CTYPE_OMIT && (clin > 0) == (backclin > 0)) {
1098 /* TRANSLATORS: We've been told the foresight and backsight are
1099 * both "UP", or that they're both "DOWN". */
1100 compile_error_reading_skip(Clino, /*Plumbed CLINO and BACKCLINO readings can't be in the same direction*/92);
1101 return 0;
1103 dz = (clin > (real)0.0) ? tape : -tape;
1104 } else {
1105 dz = (backclin < (real)0.0) ? tape : -tape;
1107 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1108 vz = var(Q_POS) / 3.0 + VAR(Tape);
1109 #ifndef NO_COVARIANCES
1110 /* Correct values - no covariances in this case! */
1111 cxy = cyz = czx = (real)0.0;
1112 #endif
1113 } else {
1114 /* Each of ctype and backctype are either CTYPE_READING/CTYPE_HORIZ
1115 * or CTYPE_OMIT */
1116 /* clino */
1117 real L2, cosG, LcosG, cosG2, sinB, cosB, dx2, dy2, dz2, v, V;
1118 if (fNoComp) {
1119 /* TRANSLATORS: Here "legs" are survey legs, i.e. measurements between
1120 * survey stations. */
1121 compile_error_reading_skip(Comp, /*Compass reading may not be omitted except on plumbed legs*/14);
1122 return 0;
1124 if (tape == (real)0.0) {
1125 dx = dy = dz = (real)0.0;
1126 vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1127 #ifndef NO_COVARIANCES
1128 cxy = cyz = czx = (real)0.0;
1129 #endif
1130 #if DEBUG_DATAIN_1
1131 printf("Zero length leg: vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1132 #endif
1133 } else {
1134 real sinGcosG;
1135 /* take into account variance in LEVEL case */
1136 real var_clin = var(Q_LEVEL);
1137 real var_comp;
1138 real comp = handle_compass(&var_comp);
1139 /* ctype != CTYPE_READING is LEVEL case */
1140 if (ctype == CTYPE_READING) {
1141 clin = (clin - pcs->z[Q_GRADIENT]) * pcs->sc[Q_GRADIENT];
1142 var_clin = VAR(Clino);
1144 if (backctype == CTYPE_READING) {
1145 backclin = (backclin - pcs->z[Q_BACKGRADIENT])
1146 * pcs->sc[Q_BACKGRADIENT];
1147 if (ctype == CTYPE_READING) {
1148 if (sqrd((clin + backclin) / 3.0) > var_clin + VAR(BackClino)) {
1149 /* fore and back readings differ by more than 3 sds */
1150 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1151 * by, e.g. "2.5Ā°" or "3įµ". */
1152 warn_readings_differ(/*CLINO reading and BACKCLINO reading disagree by %s*/99,
1153 clin + backclin, get_angle_units(Q_GRADIENT));
1155 clin = (clin / var_clin - backclin / VAR(BackClino));
1156 var_clin = (var_clin + VAR(BackClino)) / 4;
1157 clin *= var_clin;
1158 } else {
1159 clin = -backclin;
1160 var_clin = VAR(BackClino);
1164 #if DEBUG_DATAIN
1165 printf(" %4.2f %4.2f %4.2f\n", tape, comp, clin);
1166 #endif
1167 cosG = cos(clin);
1168 LcosG = tape * cosG;
1169 sinB = sin(comp);
1170 cosB = cos(comp);
1171 #if DEBUG_DATAIN_1
1172 printf("sinB = %f, cosG = %f, LcosG = %f\n", sinB, cosG, LcosG);
1173 #endif
1174 dx = LcosG * sinB;
1175 dy = LcosG * cosB;
1176 dz = tape * sin(clin);
1177 /* printf("%.2f\n",clin); */
1178 #if DEBUG_DATAIN_1
1179 printf("dx = %f\ndy = %f\ndz = %f\n", dx, dy, dz);
1180 #endif
1181 dx2 = dx * dx;
1182 L2 = tape * tape;
1183 V = VAR(Tape) / L2;
1184 dy2 = dy * dy;
1185 cosG2 = cosG * cosG;
1186 sinGcosG = sin(clin) * cosG;
1187 dz2 = dz * dz;
1188 v = dz2 * var_clin;
1189 #ifdef NO_COVARIANCES
1190 vx = (var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1191 (.5 + sinB * sinB * cosG2) * v);
1192 vy = (var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1193 (.5 + cosB * cosB * cosG2) * v);
1194 if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1195 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1196 vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1197 } else {
1198 vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1200 /* for Surveyor87 errors: vx=vy=vz=var(Q_POS)/3.0; */
1201 #else
1202 vx = var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1203 (sinB * sinB * v);
1204 vy = var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1205 (cosB * cosB * v);
1206 if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1207 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1208 vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1209 } else {
1210 vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1212 /* usual covariance formulae are fine in no clino case since
1213 * dz = 0 so value of var_clin is ignored */
1214 cxy = sinB * cosB * (VAR(Tape) * cosG2 + var_clin * dz2)
1215 - var_comp * dx * dy;
1216 czx = VAR(Tape) * sinB * sinGcosG - var_clin * dx * dz;
1217 cyz = VAR(Tape) * cosB * sinGcosG - var_clin * dy * dz;
1218 #if 0
1219 printf("vx = %6.3f, vy = %6.3f, vz = %6.3f\n", vx, vy, vz);
1220 printf("cxy = %6.3f, cyz = %6.3f, czx = %6.3f\n", cxy, cyz, czx);
1221 #endif
1222 #endif
1223 #if DEBUG_DATAIN_1
1224 printf("In DATAIN.C, vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1225 #endif
1228 #if DEBUG_DATAIN_1
1229 printf("Just before addleg, vx = %f\n", vx);
1230 #endif
1231 /*printf("dx,dy,dz = %.2f %.2f %.2f\n\n", dx, dy, dz);*/
1232 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1233 #ifndef NO_COVARIANCES
1234 , cyz, czx, cxy
1235 #endif
1237 return 1;
1240 static int
1241 process_diving(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1243 real tape = VAL(Tape);
1245 real dx, dy, dz;
1246 real vx, vy, vz;
1247 #ifndef NO_COVARIANCES
1248 real cxy = 0, cyz = 0, czx = 0;
1249 #endif
1251 handle_comp_units();
1253 /* depth gauge readings increase upwards with default calibration */
1254 if (fDepthChange) {
1255 SVX_ASSERT(VAL(FrDepth) == 0.0);
1256 dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1257 dz *= pcs->sc[Q_DEPTH];
1258 } else {
1259 dz = VAL(ToDepth) - VAL(FrDepth);
1260 dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1263 /* adjusted tape is negative -- probably the calibration is wrong */
1264 if (tape < (real)0.0) {
1265 compile_warning(/*Negative adjusted tape reading*/79);
1268 /* check if tape is less than depth change */
1269 if (tape < fabs(dz)) {
1270 /* FIXME: allow margin of error based on variances? */
1271 /* TRANSLATORS: This means that the data fed in said this.
1273 * It could be a gross error (e.g. the decimal point is missing from the
1274 * depth gauge reading) or it could just be due to random error on a near
1275 * vertical leg */
1276 compile_warning(/*Tape reading is less than change in depth*/62);
1279 if (tape == (real)0.0 && dz == 0.0) {
1280 dx = dy = dz = (real)0.0;
1281 vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1282 } else if (VAL(Comp) == HUGE_REAL &&
1283 VAL(BackComp) == HUGE_REAL) {
1284 /* plumb */
1285 dx = dy = (real)0.0;
1286 if (dz < 0) tape = -tape;
1287 /* FIXME: Should use FrDepth sometimes... */
1288 dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth))
1289 / (VAR(Tape) * 2 * VAR(ToDepth));
1290 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1291 /* FIXME: Should use FrDepth sometimes... */
1292 vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth)
1293 / (VAR(Tape) + VAR(ToDepth));
1294 } else {
1295 real L2, sinB, cosB, dz2, D2;
1296 real var_comp;
1297 real comp = handle_compass(&var_comp);
1298 sinB = sin(comp);
1299 cosB = cos(comp);
1300 L2 = tape * tape;
1301 dz2 = dz * dz;
1302 D2 = L2 - dz2;
1303 if (D2 <= (real)0.0) {
1304 /* FIXME: Should use FrDepth sometimes... */
1305 real vsum = VAR(Tape) + 2 * VAR(ToDepth);
1306 dx = dy = (real)0.0;
1307 vx = vy = var(Q_POS) / 3.0;
1308 /* FIXME: Should use FrDepth sometimes... */
1309 vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth) / vsum;
1310 if (dz > 0) {
1311 /* FIXME: Should use FrDepth sometimes... */
1312 dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth)) / vsum;
1313 } else {
1314 dz = (dz * VAR(Tape) - tape * 2 * VAR(ToDepth)) / vsum;
1316 } else {
1317 real D = sqrt(D2);
1318 /* FIXME: Should use FrDepth sometimes... */
1319 real F = VAR(Tape) * L2 + 2 * VAR(ToDepth) * D2;
1320 dx = D * sinB;
1321 dy = D * cosB;
1323 vx = var(Q_POS) / 3.0 +
1324 sinB * sinB * F / D2 + var_comp * dy * dy;
1325 vy = var(Q_POS) / 3.0 +
1326 cosB * cosB * F / D2 + var_comp * dx * dx;
1327 /* FIXME: Should use FrDepth sometimes... */
1328 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1330 #ifndef NO_COVARIANCES
1331 cxy = sinB * cosB * (F / D2 + var_comp * D2);
1332 /* FIXME: Should use FrDepth sometimes... */
1333 cyz = -2 * VAR(ToDepth) * dy / D;
1334 czx = -2 * VAR(ToDepth) * dx / D;
1335 #endif
1337 /* FIXME: If there's a clino reading, check it against the depth reading,
1338 * and average.
1339 * if (VAL(Clino) != HUGE_REAL || VAL(BackClino) != HUGE_REAL) { ... }
1342 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1343 #ifndef NO_COVARIANCES
1344 , cxy, cyz, czx
1345 #endif
1347 return 1;
1350 static int
1351 process_cartesian(prefix *fr, prefix *to, bool fToFirst)
1353 real dx = (VAL(Dx) * pcs->units[Q_DX] - pcs->z[Q_DX]) * pcs->sc[Q_DX];
1354 real dy = (VAL(Dy) * pcs->units[Q_DY] - pcs->z[Q_DY]) * pcs->sc[Q_DY];
1355 real dz = (VAL(Dz) * pcs->units[Q_DZ] - pcs->z[Q_DZ]) * pcs->sc[Q_DZ];
1357 addlegbyname(fr, to, fToFirst, dx, dy, dz, VAR(Dx), VAR(Dy), VAR(Dz)
1358 #ifndef NO_COVARIANCES
1359 , 0, 0, 0
1360 #endif
1362 return 1;
1365 static void
1366 data_cartesian(void)
1368 prefix *fr = NULL, *to = NULL;
1370 bool fMulti = fFalse;
1372 reading first_stn = End;
1374 reading *ordering;
1376 again:
1378 for (ordering = pcs->ordering ; ; ordering++) {
1379 skipblanks();
1380 switch (*ordering) {
1381 case Fr:
1382 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
1383 if (first_stn == End) first_stn = Fr;
1384 break;
1385 case To:
1386 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
1387 if (first_stn == End) first_stn = To;
1388 break;
1389 case Station:
1390 fr = to;
1391 to = read_prefix(PFX_STATION);
1392 first_stn = To;
1393 break;
1394 case Dx: case Dy: case Dz:
1395 read_reading(*ordering, fFalse);
1396 break;
1397 case Ignore:
1398 skipword(); break;
1399 case IgnoreAllAndNewLine:
1400 skipline();
1401 /* fall through */
1402 case Newline:
1403 if (fr != NULL) {
1404 if (!process_cartesian(fr, to, first_stn == To))
1405 skipline();
1407 fMulti = fTrue;
1408 while (1) {
1409 process_eol();
1410 skipblanks();
1411 if (isData(ch)) break;
1412 if (!isComm(ch)) {
1413 return;
1416 break;
1417 case IgnoreAll:
1418 skipline();
1419 /* fall through */
1420 case End:
1421 if (!fMulti) {
1422 process_cartesian(fr, to, first_stn == To);
1423 process_eol();
1424 return;
1426 do {
1427 process_eol();
1428 skipblanks();
1429 } while (isComm(ch));
1430 goto again;
1431 default: BUG("Unknown reading in ordering");
1436 static int
1437 process_cylpolar(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1439 real tape = VAL(Tape);
1441 real dx, dy, dz;
1442 real vx, vy, vz;
1443 #ifndef NO_COVARIANCES
1444 real cxy = 0;
1445 #endif
1447 handle_comp_units();
1449 /* depth gauge readings increase upwards with default calibration */
1450 if (fDepthChange) {
1451 SVX_ASSERT(VAL(FrDepth) == 0.0);
1452 dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1453 dz *= pcs->sc[Q_DEPTH];
1454 } else {
1455 dz = VAL(ToDepth) - VAL(FrDepth);
1456 dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1459 /* adjusted tape is negative -- probably the calibration is wrong */
1460 if (tape < (real)0.0) {
1461 compile_warning(/*Negative adjusted tape reading*/79);
1464 if (VAL(Comp) == HUGE_REAL && VAL(BackComp) == HUGE_REAL) {
1465 /* plumb */
1466 dx = dy = (real)0.0;
1467 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1468 /* FIXME: Should use FrDepth sometimes... */
1469 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1470 } else {
1471 real sinB, cosB;
1472 real var_comp;
1473 real comp = handle_compass(&var_comp);
1474 sinB = sin(comp);
1475 cosB = cos(comp);
1477 dx = tape * sinB;
1478 dy = tape * cosB;
1480 vx = var(Q_POS) / 3.0 +
1481 VAR(Tape) * sinB * sinB + var_comp * dy * dy;
1482 vy = var(Q_POS) / 3.0 +
1483 VAR(Tape) * cosB * cosB + var_comp * dx * dx;
1484 /* FIXME: Should use FrDepth sometimes... */
1485 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1487 #ifndef NO_COVARIANCES
1488 cxy = (VAR(Tape) - var_comp * tape * tape) * sinB * cosB;
1489 #endif
1491 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1492 #ifndef NO_COVARIANCES
1493 , cxy, 0, 0
1494 #endif
1496 return 1;
1499 /* Process tape/compass/clino, diving, and cylpolar styles of survey data
1500 * Also handles topofil (fromcount/tocount or count) in place of tape */
1501 static void
1502 data_normal(void)
1504 prefix *fr = NULL, *to = NULL;
1505 reading first_stn = End;
1507 bool fTopofil = fFalse, fMulti = fFalse;
1508 bool fRev;
1509 clino_type ctype, backctype;
1510 bool fDepthChange;
1511 unsigned long compass_dat_flags = 0;
1513 reading *ordering;
1515 VAL(Tape) = VAL(BackTape) = HUGE_REAL;
1516 VAL(Comp) = VAL(BackComp) = HUGE_REAL;
1517 VAL(FrCount) = VAL(ToCount) = 0;
1518 VAL(FrDepth) = VAL(ToDepth) = 0;
1519 VAL(Left) = VAL(Right) = VAL(Up) = VAL(Down) = HUGE_REAL;
1521 fRev = fFalse;
1522 ctype = backctype = CTYPE_OMIT;
1523 fDepthChange = fFalse;
1525 /* ordering may omit clino reading, so set up default here */
1526 /* this is also used if clino reading is the omit character */
1527 VAL(Clino) = VAL(BackClino) = 0;
1529 again:
1531 /* We clear these flags in the normal course of events, but if there's an
1532 * error in a reading, we might not, so make sure it has been cleared here.
1534 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1535 for (ordering = pcs->ordering; ; ordering++) {
1536 skipblanks();
1537 switch (*ordering) {
1538 case Fr:
1539 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT|PFX_ANON);
1540 if (first_stn == End) first_stn = Fr;
1541 break;
1542 case To:
1543 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT|PFX_ANON);
1544 if (first_stn == End) first_stn = To;
1545 break;
1546 case Station:
1547 fr = to;
1548 to = read_prefix(PFX_STATION);
1549 first_stn = To;
1550 break;
1551 case Dir: {
1552 typedef enum {
1553 DIR_NULL=-1, DIR_FORE, DIR_BACK
1554 } dir_tok;
1555 static sztok dir_tab[] = {
1556 {"B", DIR_BACK},
1557 {"F", DIR_FORE},
1559 dir_tok tok;
1560 get_token();
1561 tok = match_tok(dir_tab, TABSIZE(dir_tab));
1562 switch (tok) {
1563 case DIR_FORE:
1564 break;
1565 case DIR_BACK:
1566 fRev = fTrue;
1567 break;
1568 default:
1569 file.lpos += strlen(buffer);
1570 compile_error_skip(-/*Found ā€œ%sā€, expecting ā€œFā€ or ā€œBā€*/131,
1571 buffer);
1572 process_eol();
1573 return;
1575 break;
1577 case Tape: case BackTape: {
1578 reading r = *ordering;
1579 read_reading(r, fTrue);
1580 if (VAL(r) == HUGE_REAL) {
1581 if (!isOmit(ch)) {
1582 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1583 /* Avoid also warning about omitted tape reading. */
1584 VAL(r) = 0;
1585 } else {
1586 nextch();
1588 } else if (VAL(r) < (real)0.0) {
1589 compile_warning(-/*Negative tape reading*/60);
1591 break;
1593 case Count:
1594 VAL(FrCount) = VAL(ToCount);
1595 LOC(FrCount) = LOC(ToCount);
1596 read_reading(ToCount, fFalse);
1597 fTopofil = fTrue;
1598 break;
1599 case FrCount:
1600 read_reading(FrCount, fFalse);
1601 break;
1602 case ToCount:
1603 read_reading(ToCount, fFalse);
1604 fTopofil = fTrue;
1605 break;
1606 case Comp: case BackComp:
1607 read_bearing_or_omit(*ordering);
1608 break;
1609 case Clino: case BackClino: {
1610 reading r = *ordering;
1611 clino_type * p_ctype = (r == Clino ? &ctype : &backctype);
1612 read_reading(r, fTrue);
1613 if (VAL(r) == HUGE_REAL) {
1614 VAL(r) = handle_plumb(p_ctype);
1615 if (VAL(r) != HUGE_REAL) break;
1616 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1617 skipline();
1618 process_eol();
1619 return;
1621 *p_ctype = CTYPE_READING;
1622 break;
1624 case FrDepth: case ToDepth:
1625 read_reading(*ordering, fFalse);
1626 break;
1627 case Depth:
1628 VAL(FrDepth) = VAL(ToDepth);
1629 LOC(FrDepth) = LOC(ToDepth);
1630 read_reading(ToDepth, fFalse);
1631 break;
1632 case DepthChange:
1633 fDepthChange = fTrue;
1634 VAL(FrDepth) = 0;
1635 read_reading(ToDepth, fFalse);
1636 break;
1637 case CompassDATComp:
1638 read_bearing_or_omit(Comp);
1639 if (is_compass_NaN(VAL(Comp))) VAL(Comp) = HUGE_REAL;
1640 break;
1641 case CompassDATBackComp:
1642 read_bearing_or_omit(BackComp);
1643 if (is_compass_NaN(VAL(BackComp))) VAL(BackComp) = HUGE_REAL;
1644 break;
1645 case CompassDATClino: case CompassDATBackClino: {
1646 reading r;
1647 clino_type * p_ctype;
1648 if (*ordering == CompassDATClino) {
1649 r = Clino;
1650 p_ctype = &ctype;
1651 } else {
1652 r = BackClino;
1653 p_ctype = &backctype;
1655 read_reading(r, fFalse);
1656 if (is_compass_NaN(VAL(r))) {
1657 VAL(r) = HUGE_REAL;
1658 *p_ctype = CTYPE_OMIT;
1659 } else {
1660 *p_ctype = CTYPE_READING;
1662 break;
1664 case CompassDATLeft: case CompassDATRight:
1665 case CompassDATUp: case CompassDATDown: {
1666 /* FIXME: need to actually make use of these entries! */
1667 reading actual = Left + (*ordering - CompassDATLeft);
1668 read_reading(actual, fFalse);
1669 if (VAL(actual) < 0) VAL(actual) = HUGE_REAL;
1670 break;
1672 case CompassDATFlags:
1673 if (ch == '#') {
1674 filepos fp;
1675 get_pos(&fp);
1676 nextch();
1677 if (ch == '|') {
1678 nextch();
1679 while (ch >= 'A' && ch <= 'Z') {
1680 compass_dat_flags |= BIT(ch - 'A');
1681 /* We currently understand:
1682 * L (exclude from length)
1683 * X (exclude data)
1684 * FIXME: but should also handle at least some of:
1685 * C (no adjustment) (set all (co)variances to 0?)
1686 * P (no plot) (new flag in 3d for "hidden by default"?)
1688 nextch();
1690 if (ch == '#') {
1691 nextch();
1692 } else {
1693 compass_dat_flags = 0;
1694 set_pos(&fp);
1696 } else {
1697 set_pos(&fp);
1700 break;
1701 case Ignore:
1702 skipword(); break;
1703 case IgnoreAllAndNewLine:
1704 skipline();
1705 /* fall through */
1706 case Newline:
1707 if (fr != NULL) {
1708 int r;
1709 int save_flags;
1710 int implicit_splay;
1711 if (fTopofil) {
1712 VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1713 LOC(Tape) = LOC(ToCount);
1715 /* Note: frdepth == todepth test works regardless of fDepthChange
1716 * (frdepth always zero, todepth is change of depth) and also
1717 * works for STYLE_NORMAL (both remain 0) */
1718 if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1719 (VAL(Tape) == (real)0.0 || VAL(Tape) == HUGE_REAL) &&
1720 (VAL(BackTape) == (real)0.0 || VAL(BackTape) == HUGE_REAL) &&
1721 VAL(FrDepth) == VAL(ToDepth)) {
1722 process_equate(fr, to);
1723 goto inferred_equate;
1725 if (fRev) {
1726 prefix *t = fr;
1727 fr = to;
1728 to = t;
1730 if (fTopofil) {
1731 VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1732 } else if (VAL(Tape) != HUGE_REAL) {
1733 VAL(Tape) *= pcs->units[Q_LENGTH];
1734 VAL(Tape) -= pcs->z[Q_LENGTH];
1735 VAL(Tape) *= pcs->sc[Q_LENGTH];
1737 if (VAL(BackTape) != HUGE_REAL) {
1738 VAL(BackTape) *= pcs->units[Q_BACKLENGTH];
1739 VAL(BackTape) -= pcs->z[Q_BACKLENGTH];
1740 VAL(BackTape) *= pcs->sc[Q_BACKLENGTH];
1741 if (VAL(Tape) != HUGE_REAL) {
1742 real diff = VAL(Tape) - VAL(BackTape);
1743 if (sqrd(diff / 3.0) > VAR(Tape) + VAR(BackTape)) {
1744 /* fore and back readings differ by more than 3 sds */
1745 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1746 * by, e.g. "0.12m" or "0.2ft". */
1747 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1748 diff, get_length_units(Q_LENGTH));
1750 VAL(Tape) = VAL(Tape) / VAR(Tape) + VAL(BackTape) / VAR(BackTape);
1751 VAR(Tape) = (VAR(Tape) + VAR(BackTape)) / 4;
1752 VAL(Tape) *= VAR(Tape);
1753 } else {
1754 VAL(Tape) = VAL(BackTape);
1755 VAR(Tape) = VAR(BackTape);
1757 } else if (VAL(Tape) == HUGE_REAL) {
1758 compile_error_reading(Tape, /*Tape reading may not be omitted*/94);
1759 goto inferred_equate;
1761 implicit_splay = TSTBIT(pcs->flags, FLAGS_IMPLICIT_SPLAY);
1762 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1763 save_flags = pcs->flags;
1764 if (implicit_splay) {
1765 pcs->flags |= BIT(FLAGS_SPLAY);
1767 switch (pcs->style) {
1768 case STYLE_NORMAL:
1769 r = process_normal(fr, to, (first_stn == To) ^ fRev,
1770 ctype, backctype);
1771 break;
1772 case STYLE_DIVING:
1773 /* FIXME: Handle any clino readings */
1774 r = process_diving(fr, to, (first_stn == To) ^ fRev,
1775 fDepthChange);
1776 break;
1777 case STYLE_CYLPOLAR:
1778 r = process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1779 fDepthChange);
1780 break;
1781 default:
1782 r = 0; /* avoid warning */
1783 BUG("bad style");
1785 pcs->flags = save_flags;
1786 if (!r) skipline();
1788 /* Swap fr and to back to how they were for next line */
1789 if (fRev) {
1790 prefix *t = fr;
1791 fr = to;
1792 to = t;
1796 fRev = fFalse;
1797 ctype = backctype = CTYPE_OMIT;
1798 fDepthChange = fFalse;
1800 /* ordering may omit clino reading, so set up default here */
1801 /* this is also used if clino reading is the omit character */
1802 VAL(Clino) = VAL(BackClino) = 0;
1803 LOC(Clino) = LOC(BackClino) = -1;
1805 inferred_equate:
1807 fMulti = fTrue;
1808 while (1) {
1809 process_eol();
1810 skipblanks();
1811 if (isData(ch)) break;
1812 if (!isComm(ch)) {
1813 return;
1816 break;
1817 case IgnoreAll:
1818 skipline();
1819 /* fall through */
1820 case End:
1821 if (!fMulti) {
1822 int save_flags;
1823 int implicit_splay;
1824 /* Compass ignore flag is 'X' */
1825 if ((compass_dat_flags & BIT('X' - 'A'))) {
1826 process_eol();
1827 return;
1829 if (fRev) {
1830 prefix *t = fr;
1831 fr = to;
1832 to = t;
1834 if (fTopofil) {
1835 VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1836 LOC(Tape) = LOC(ToCount);
1838 /* Note: frdepth == todepth test works regardless of fDepthChange
1839 * (frdepth always zero, todepth is change of depth) and also
1840 * works for STYLE_NORMAL (both remain 0) */
1841 if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1842 (VAL(Tape) == (real)0.0 || VAL(Tape) == HUGE_REAL) &&
1843 (VAL(BackTape) == (real)0.0 || VAL(BackTape) == HUGE_REAL) &&
1844 VAL(FrDepth) == VAL(ToDepth)) {
1845 process_equate(fr, to);
1846 process_eol();
1847 return;
1849 if (fTopofil) {
1850 VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1851 } else if (VAL(Tape) != HUGE_REAL) {
1852 VAL(Tape) *= pcs->units[Q_LENGTH];
1853 VAL(Tape) -= pcs->z[Q_LENGTH];
1854 VAL(Tape) *= pcs->sc[Q_LENGTH];
1856 if (VAL(BackTape) != HUGE_REAL) {
1857 VAL(BackTape) *= pcs->units[Q_BACKLENGTH];
1858 VAL(BackTape) -= pcs->z[Q_BACKLENGTH];
1859 VAL(BackTape) *= pcs->sc[Q_BACKLENGTH];
1860 if (VAL(Tape) != HUGE_REAL) {
1861 real diff = VAL(Tape) - VAL(BackTape);
1862 if (sqrd(diff / 3.0) > VAR(Tape) + VAR(BackTape)) {
1863 /* fore and back readings differ by more than 3 sds */
1864 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1865 * by, e.g. "0.12m" or "0.2ft". */
1866 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1867 diff, get_length_units(Q_LENGTH));
1869 VAL(Tape) = VAL(Tape) / VAR(Tape) + VAL(BackTape) / VAR(BackTape);
1870 VAR(Tape) = (VAR(Tape) + VAR(BackTape)) / 4;
1871 VAL(Tape) *= VAR(Tape);
1872 } else {
1873 VAL(Tape) = VAL(BackTape);
1874 VAR(Tape) = VAR(BackTape);
1876 } else if (VAL(Tape) == HUGE_REAL) {
1877 compile_error_reading(Tape, /*Tape reading may not be omitted*/94);
1878 process_eol();
1879 return;
1881 implicit_splay = TSTBIT(pcs->flags, FLAGS_IMPLICIT_SPLAY);
1882 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1883 save_flags = pcs->flags;
1884 if (implicit_splay) {
1885 pcs->flags |= BIT(FLAGS_SPLAY);
1887 if ((compass_dat_flags & BIT('L' - 'A'))) {
1888 /* 'L' means "exclude from length" - map this to Survex's
1889 * FLAGS_DUPLICATE. */
1890 pcs->flags |= BIT(FLAGS_DUPLICATE);
1892 switch (pcs->style) {
1893 case STYLE_NORMAL:
1894 process_normal(fr, to, (first_stn == To) ^ fRev,
1895 ctype, backctype);
1896 break;
1897 case STYLE_DIVING:
1898 /* FIXME: Handle any clino readings */
1899 process_diving(fr, to, (first_stn == To) ^ fRev,
1900 fDepthChange);
1901 break;
1902 case STYLE_CYLPOLAR:
1903 process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1904 fDepthChange);
1905 break;
1906 default:
1907 BUG("bad style");
1909 pcs->flags = save_flags;
1911 process_eol();
1912 return;
1914 do {
1915 process_eol();
1916 skipblanks();
1917 } while (isComm(ch));
1918 goto again;
1919 default:
1920 BUG("Unknown reading in ordering");
1925 static int
1926 process_lrud(prefix *stn)
1928 SVX_ASSERT(next_lrud);
1929 lrud * xsect = osnew(lrud);
1930 xsect->stn = stn;
1931 xsect->l = (VAL(Left) * pcs->units[Q_LEFT] - pcs->z[Q_LEFT]) * pcs->sc[Q_LEFT];
1932 xsect->r = (VAL(Right) * pcs->units[Q_RIGHT] - pcs->z[Q_RIGHT]) * pcs->sc[Q_RIGHT];
1933 xsect->u = (VAL(Up) * pcs->units[Q_UP] - pcs->z[Q_UP]) * pcs->sc[Q_UP];
1934 xsect->d = (VAL(Down) * pcs->units[Q_DOWN] - pcs->z[Q_DOWN]) * pcs->sc[Q_DOWN];
1935 xsect->meta = pcs->meta;
1936 if (pcs->meta) ++pcs->meta->ref_count;
1937 xsect->next = NULL;
1938 *next_lrud = xsect;
1939 next_lrud = &(xsect->next);
1941 return 1;
1944 static void
1945 data_passage(void)
1947 prefix *stn = NULL;
1948 reading *ordering;
1950 for (ordering = pcs->ordering ; ; ordering++) {
1951 skipblanks();
1952 switch (*ordering) {
1953 case Station:
1954 stn = read_prefix(PFX_STATION);
1955 break;
1956 case Left: case Right: case Up: case Down: {
1957 reading r = *ordering;
1958 read_reading(r, fTrue);
1959 if (VAL(r) == HUGE_REAL) {
1960 if (!isOmit(ch)) {
1961 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1962 } else {
1963 nextch();
1965 VAL(r) = -1;
1967 break;
1969 case Ignore:
1970 skipword(); break;
1971 case IgnoreAll:
1972 skipline();
1973 /* fall through */
1974 case End: {
1975 process_lrud(stn);
1976 process_eol();
1977 return;
1979 default: BUG("Unknown reading in ordering");
1984 static int
1985 process_nosurvey(prefix *fr, prefix *to, bool fToFirst)
1987 nosurveylink *link;
1989 /* Suppress "unused fixed point" warnings for these stations */
1990 fr->sflags |= BIT(SFLAGS_USED);
1991 to->sflags |= BIT(SFLAGS_USED);
1993 /* add to linked list which is dealt with after network is solved */
1994 link = osnew(nosurveylink);
1995 if (fToFirst) {
1996 link->to = StnFromPfx(to);
1997 link->fr = StnFromPfx(fr);
1998 } else {
1999 link->fr = StnFromPfx(fr);
2000 link->to = StnFromPfx(to);
2002 link->flags = pcs->flags | (STYLE_NOSURVEY << FLAGS_STYLE_BIT0);
2003 link->meta = pcs->meta;
2004 if (pcs->meta) ++pcs->meta->ref_count;
2005 link->next = nosurveyhead;
2006 nosurveyhead = link;
2007 return 1;
2010 static void
2011 data_nosurvey(void)
2013 prefix *fr = NULL, *to = NULL;
2015 bool fMulti = fFalse;
2017 reading first_stn = End;
2019 reading *ordering;
2021 again:
2023 for (ordering = pcs->ordering ; ; ordering++) {
2024 skipblanks();
2025 switch (*ordering) {
2026 case Fr:
2027 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
2028 if (first_stn == End) first_stn = Fr;
2029 break;
2030 case To:
2031 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
2032 if (first_stn == End) first_stn = To;
2033 break;
2034 case Station:
2035 fr = to;
2036 to = read_prefix(PFX_STATION);
2037 first_stn = To;
2038 break;
2039 case Ignore:
2040 skipword(); break;
2041 case IgnoreAllAndNewLine:
2042 skipline();
2043 /* fall through */
2044 case Newline:
2045 if (fr != NULL) {
2046 if (!process_nosurvey(fr, to, first_stn == To))
2047 skipline();
2049 if (ordering[1] == End) {
2050 do {
2051 process_eol();
2052 skipblanks();
2053 } while (isComm(ch));
2054 if (!isData(ch)) {
2055 return;
2057 goto again;
2059 fMulti = fTrue;
2060 while (1) {
2061 process_eol();
2062 skipblanks();
2063 if (isData(ch)) break;
2064 if (!isComm(ch)) {
2065 return;
2068 break;
2069 case IgnoreAll:
2070 skipline();
2071 /* fall through */
2072 case End:
2073 if (!fMulti) {
2074 (void)process_nosurvey(fr, to, first_stn == To);
2075 process_eol();
2076 return;
2078 do {
2079 process_eol();
2080 skipblanks();
2081 } while (isComm(ch));
2082 goto again;
2083 default: BUG("Unknown reading in ordering");
2088 /* totally ignore a line of survey data */
2089 static void
2090 data_ignore(void)
2092 skipline();
2093 process_eol();