Add support for errors with a range of columns
[survex.git] / src / datain.c
blob33a4e205ecee8068748a3bae8add4e8bf262aa9c
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 static void
120 show_line(int col, int width)
122 /* Rewind to beginning of line. */
123 long cur_pos = ftell(file.fh);
124 if (cur_pos < 0 || fseek(file.fh, file.lpos, SEEK_SET) == -1)
125 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
127 /* Read the whole line and write it out. */
128 while (!feof(file.fh)) {
129 int c = GETC(file.fh);
130 if (isEol(c)) break;
131 PUTC(c, STDERR);
133 fputnl(STDERR);
135 /* If we have a location in the line for the error, indicate it. */
136 if (col) {
137 col -= width;
138 while (--col) PUTC(' ', STDERR);
139 PUTC('^', STDERR);
140 while (width > 1) {
141 PUTC('~', STDERR);
142 --width;
144 fputnl(STDERR);
147 /* Revert to where we were. */
148 if (fseek(file.fh, cur_pos, SEEK_SET) == -1)
149 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
152 static int caret_width = 0;
154 static void
155 compile_v_report(int severity, int en, va_list ap)
157 int col = 0;
158 error_list_parent_files();
159 if (en < 0) {
160 en = -en;
161 if (file.fh) col = ftell(file.fh) - file.lpos;
163 v_report(severity, file.filename, file.line, col, en, ap);
164 if (file.fh)
165 show_line(col, caret_width);
168 void
169 compile_error(int en, ...)
171 va_list ap;
172 va_start(ap, en);
173 compile_v_report(1, en, ap);
174 va_end(ap);
177 void
178 compile_error_skip(int en, ...)
180 va_list ap;
181 va_start(ap, en);
182 compile_v_report(1, en, ap);
183 va_end(ap);
184 skipline();
187 static void
188 compile_error_reading(reading r, int en, ...)
190 va_list ap;
191 int col = 0;
192 va_start(ap, en);
193 error_list_parent_files();
194 if (LOC(r) >= file.lpos) col = LOC(r) - file.lpos;
195 v_report(1, file.filename, file.line, col, en, ap);
196 va_end(ap);
199 static void
200 compile_error_reading_skip(reading r, int en, ...)
202 va_list ap;
203 int col = 0;
204 va_start(ap, en);
205 error_list_parent_files();
206 if (LOC(r) >= file.lpos) col = LOC(r) - file.lpos;
207 v_report(1, file.filename, file.line, col, en, ap);
208 va_end(ap);
209 skipline();
212 void
213 compile_error_at(const char * filename, unsigned line, int en, ...)
215 va_list ap;
216 va_start(ap, en);
217 v_report(1, filename, line, 0, en, ap);
218 va_end(ap);
221 void
222 compile_error_pfx(const prefix * pfx, int en, ...)
224 va_list ap;
225 va_start(ap, en);
226 v_report(1, pfx->filename, pfx->line, 0, en, ap);
227 va_end(ap);
230 void
231 compile_error_token(int en)
233 char *p = NULL;
234 int len = 0;
235 skipblanks();
236 while (!isBlank(ch) && !isEol(ch)) {
237 s_catchar(&p, &len, (char)ch);
238 nextch();
240 if (p) {
241 caret_width = strlen(p);
242 compile_error(en, p);
243 caret_width = 0;
244 osfree(p);
245 } else {
246 compile_error(en, "");
250 void
251 compile_warning(int en, ...)
253 va_list ap;
254 va_start(ap, en);
255 compile_v_report(0, en, ap);
256 va_end(ap);
259 void
260 compile_warning_at(const char * filename, unsigned line, int en, ...)
262 va_list ap;
263 va_start(ap, en);
264 v_report(0, filename, line, 0, en, ap);
265 va_end(ap);
268 void
269 compile_warning_pfx(const prefix * pfx, int en, ...)
271 va_list ap;
272 va_start(ap, en);
273 v_report(0, pfx->filename, pfx->line, 0, en, ap);
274 va_end(ap);
277 /* This function makes a note where to put output files */
278 static void
279 using_data_file(const char *fnm)
281 if (!fnm_output_base) {
282 /* was: fnm_output_base = base_from_fnm(fnm); */
283 fnm_output_base = baseleaf_from_fnm(fnm);
284 } else if (fnm_output_base_is_dir) {
285 /* --output pointed to directory so use the leaf basename in that dir */
286 char *lf, *p;
287 lf = baseleaf_from_fnm(fnm);
288 p = use_path(fnm_output_base, lf);
289 osfree(lf);
290 osfree(fnm_output_base);
291 fnm_output_base = p;
292 fnm_output_base_is_dir = 0;
296 static void
297 skipword(void)
299 while (!isBlank(ch) && !isEol(ch)) nextch();
302 extern void
303 skipblanks(void)
305 while (isBlank(ch)) nextch();
308 extern void
309 skipline(void)
311 while (!isEol(ch)) nextch();
314 static void
315 process_eol(void)
317 int eolchar;
319 skipblanks();
321 if (!isEol(ch)) {
322 if (!isComm(ch)) compile_error(-/*End of line not blank*/15);
323 skipline();
326 eolchar = ch;
327 file.line++;
328 /* skip any different eol characters so we get line counts correct on
329 * DOS text files and similar, but don't count several adjacent blank
330 * lines as one */
331 while (ch != EOF) {
332 nextch();
333 if (ch == eolchar || !isEol(ch)) {
334 break;
336 if (ch == '\n') eolchar = ch;
338 file.lpos = ftell(file.fh) - 1;
341 static bool
342 process_non_data_line(void)
344 skipblanks();
346 if (isData(ch)) return fFalse;
348 if (isKeywd(ch)) {
349 nextch();
350 handle_command();
353 process_eol();
355 return fTrue;
358 static void
359 read_reading(reading r, bool f_optional)
361 int n_readings;
362 q_quantity q;
363 switch (r) {
364 case Tape: q = Q_LENGTH; break;
365 case BackTape: q = Q_BACKLENGTH; break;
366 case Comp: q = Q_BEARING; break;
367 case BackComp: q = Q_BACKBEARING; break;
368 case Clino: q = Q_GRADIENT; break;
369 case BackClino: q = Q_BACKGRADIENT; break;
370 case FrDepth: case ToDepth: q = Q_DEPTH; break;
371 case Dx: q = Q_DX; break;
372 case Dy: q = Q_DY; break;
373 case Dz: q = Q_DZ; break;
374 case FrCount: case ToCount: q = Q_COUNT; break;
375 case Left: q = Q_LEFT; break;
376 case Right: q = Q_RIGHT; break;
377 case Up: q = Q_UP; break;
378 case Down: q = Q_DOWN; break;
379 default:
380 q = Q_NULL; /* Suppress compiler warning */;
381 BUG("Unexpected case");
383 LOC(r) = ftell(file.fh);
384 VAL(r) = read_numeric_multi(f_optional, &n_readings);
385 VAR(r) = var(q);
386 if (n_readings > 1) VAR(r) /= sqrt(n_readings);
389 static void
390 read_bearing_or_omit(reading r)
392 int n_readings;
393 q_quantity q = Q_NULL;
394 LOC(r) = ftell(file.fh);
395 VAL(r) = read_numeric_multi_or_omit(&n_readings);
396 switch (r) {
397 case Comp: q = Q_BEARING; break;
398 case BackComp: q = Q_BACKBEARING; break;
399 default:
400 q = Q_NULL; /* Suppress compiler warning */;
401 BUG("Unexpected case");
403 VAR(r) = var(q);
404 if (n_readings > 1) VAR(r) /= sqrt(n_readings);
407 /* For reading Compass MAK files which have a freeform syntax */
408 static void
409 nextch_handling_eol(void)
411 nextch();
412 while (ch != EOF && isEol(ch)) {
413 process_eol();
417 #define LITLEN(S) (sizeof(S"") - 1)
418 #define has_ext(F,L,E) ((L) > LITLEN(E) + 1 &&\
419 (F)[(L) - LITLEN(E) - 1] == FNM_SEP_EXT &&\
420 strcasecmp((F) + (L) - LITLEN(E), E) == 0)
421 extern void
422 data_file(const char *pth, const char *fnm)
424 int begin_lineno_store;
425 parse file_store;
426 volatile enum {FMT_SVX, FMT_DAT, FMT_MAK} fmt = FMT_SVX;
429 char *filename;
430 FILE *fh;
431 size_t len;
433 if (!pth) {
434 /* file specified on command line - don't do special translation */
435 fh = fopenWithPthAndExt(pth, fnm, EXT_SVX_DATA, "rb", &filename);
436 } else {
437 fh = fopen_portable(pth, fnm, EXT_SVX_DATA, "rb", &filename);
440 if (fh == NULL) {
441 compile_error(-/*Couldnā€™t open file ā€œ%sā€*/24, fnm);
442 return;
445 len = strlen(filename);
446 if (has_ext(filename, len, "dat")) {
447 fmt = FMT_DAT;
448 } else if (has_ext(filename, len, "mak")) {
449 fmt = FMT_MAK;
452 file_store = file;
453 if (file.fh) file.parent = &file_store;
454 file.fh = fh;
455 file.filename = filename;
456 file.line = 1;
457 file.lpos = 0;
458 file.reported_where = fFalse;
459 nextch();
462 using_data_file(file.filename);
464 begin_lineno_store = pcs->begin_lineno;
465 pcs->begin_lineno = 0;
467 if (fmt == FMT_DAT) {
468 short *t;
469 int i;
470 settings *pcsNew;
472 pcsNew = osnew(settings);
473 *pcsNew = *pcs; /* copy contents */
474 pcsNew->begin_lineno = 0;
475 pcsNew->next = pcs;
476 pcs = pcsNew;
477 default_units(pcs);
478 default_calib(pcs);
480 pcs->style = STYLE_NORMAL;
481 pcs->units[Q_LENGTH] = METRES_PER_FOOT;
482 t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
484 t[EOF] = SPECIAL_EOL;
485 memset(t, 0, sizeof(short) * 33);
486 for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
487 t[127] = 0;
488 for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
489 t['\t'] |= SPECIAL_BLANK;
490 t[' '] |= SPECIAL_BLANK;
491 t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
492 t['\n'] |= SPECIAL_EOL;
493 t['\r'] |= SPECIAL_EOL;
494 t['.'] |= SPECIAL_DECIMAL;
495 t['-'] |= SPECIAL_MINUS;
496 t['+'] |= SPECIAL_PLUS;
497 pcs->Translate = t;
498 pcs->Case = OFF;
499 pcs->Truncate = INT_MAX;
500 pcs->infer = BIT(INFER_EQUATES)|BIT(INFER_EXPORTS)|BIT(INFER_PLUMBS);
501 } else if (fmt == FMT_MAK) {
502 short *t;
503 int i;
504 settings *pcsNew;
506 pcsNew = osnew(settings);
507 *pcsNew = *pcs; /* copy contents */
508 pcsNew->begin_lineno = 0;
509 pcsNew->next = pcs;
510 pcs = pcsNew;
512 t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
514 t[EOF] = SPECIAL_EOL;
515 memset(t, 0, sizeof(short) * 33);
516 for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
517 t[127] = 0;
518 for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
519 t['['] = t[','] = t[';'] = 0;
520 t['\t'] |= SPECIAL_BLANK;
521 t[' '] |= SPECIAL_BLANK;
522 t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
523 t['\n'] |= SPECIAL_EOL;
524 t['\r'] |= SPECIAL_EOL;
525 t['.'] |= SPECIAL_DECIMAL;
526 t['-'] |= SPECIAL_MINUS;
527 t['+'] |= SPECIAL_PLUS;
528 pcs->Translate = t;
529 pcs->Case = OFF;
530 pcs->Truncate = INT_MAX;
533 #ifdef HAVE_SETJMP_H
534 /* errors in nested functions can longjmp here */
535 if (setjmp(file.jbSkipLine)) {
536 skipline();
537 process_eol();
539 #endif
541 if (fmt == FMT_DAT) {
542 while (!feof(file.fh) && !ferror(file.fh)) {
543 static reading compass_order[] = {
544 Fr, To, Tape, CompassDATComp, CompassDATClino,
545 CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
546 CompassDATFlags, IgnoreAll
548 static reading compass_order_backsights[] = {
549 Fr, To, Tape, CompassDATComp, CompassDATClino,
550 CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
551 CompassDATBackComp, CompassDATBackClino,
552 CompassDATFlags, IgnoreAll
554 /* <Cave name> */
555 skipline();
556 process_eol();
557 /* SURVEY NAME: <Short name> */
558 get_token();
559 get_token();
560 /* if (ch != ':') ... */
561 nextch();
562 get_token();
563 skipline();
564 process_eol();
565 /* SURVEY DATE: 7 10 79 COMMENT:<Long name> */
566 get_token();
567 get_token();
568 copy_on_write_meta(pcs);
569 if (ch == ':') {
570 int year, month, day;
572 nextch();
574 /* NB order is *month* *day* year */
575 month = read_uint();
576 day = read_uint();
577 year = read_uint();
578 /* Note: Larry says a 2 digit year is always 19XX */
579 if (year < 100) year += 1900;
581 pcs->meta->days1 = pcs->meta->days2 = days_since_1900(year, month, day);
582 } else {
583 pcs->meta->days1 = pcs->meta->days2 = -1;
585 pcs->declination = HUGE_REAL;
586 skipline();
587 process_eol();
588 /* SURVEY TEAM: */
589 get_token();
590 get_token();
591 skipline();
592 process_eol();
593 /* <Survey team> */
594 nextch();
595 skipline();
596 process_eol();
597 /* DECLINATION: 1.00 FORMAT: DDDDLUDRADLN CORRECTIONS: 2.00 3.00 4.00 */
598 get_token();
599 nextch(); /* : */
600 skipblanks();
601 pcs->z[Q_DECLINATION] = -read_numeric(fFalse);
602 pcs->z[Q_DECLINATION] *= pcs->units[Q_DECLINATION];
603 get_token();
604 pcs->ordering = compass_order;
605 if (strcmp(buffer, "FORMAT") == 0) {
606 nextch(); /* : */
607 get_token();
608 if (strlen(buffer) >= 12 && buffer[11] == 'B') {
609 /* We have backsights for compass and clino */
610 pcs->ordering = compass_order_backsights;
612 get_token();
614 if (strcmp(buffer, "CORRECTIONS") == 0) {
615 nextch(); /* : */
616 pcs->z[Q_BEARING] = -rad(read_numeric(fFalse));
617 pcs->z[Q_GRADIENT] = -rad(read_numeric(fFalse));
618 pcs->z[Q_LENGTH] = -read_numeric(fFalse);
619 } else {
620 pcs->z[Q_BEARING] = 0;
621 pcs->z[Q_GRADIENT] = 0;
622 pcs->z[Q_LENGTH] = 0;
624 skipline();
625 process_eol();
626 /* BLANK LINE */
627 skipline();
628 process_eol();
629 /* heading line */
630 skipline();
631 process_eol();
632 /* BLANK LINE */
633 skipline();
634 process_eol();
635 while (!feof(file.fh)) {
636 if (ch == '\x0c') {
637 nextch();
638 process_eol();
639 break;
641 data_normal();
643 clear_last_leg();
646 settings *pcsParent = pcs->next;
647 SVX_ASSERT(pcsParent);
648 pcs->ordering = NULL;
649 free_settings(pcs);
650 pcs = pcsParent;
652 } else if (fmt == FMT_MAK) {
653 nextch_handling_eol();
654 while (!feof(file.fh) && !ferror(file.fh)) {
655 if (ch == '#') {
656 /* include a file */
657 int ch_store;
658 char *dat_pth = path_from_fnm(file.filename);
659 char *dat_fnm = NULL;
660 int dat_fnm_len;
661 nextch_handling_eol();
662 while (ch != ',' && ch != ';' && ch != EOF) {
663 while (isEol(ch)) process_eol();
664 s_catchar(&dat_fnm, &dat_fnm_len, (char)ch);
665 nextch_handling_eol();
667 while (ch != ';' && ch != EOF) {
668 prefix *name;
669 nextch_handling_eol();
670 name = read_prefix(PFX_STATION|PFX_OPT);
671 if (name) {
672 skipblanks();
673 if (ch == '[') {
674 /* fixed pt */
675 node *stn;
676 real x, y, z;
677 name->sflags |= BIT(SFLAGS_FIXED);
678 nextch_handling_eol();
679 while (!isdigit(ch) && ch != '+' && ch != '-' &&
680 ch != '.' && ch != ']' && ch != EOF) {
681 nextch_handling_eol();
683 x = read_numeric(fFalse);
684 while (!isdigit(ch) && ch != '+' && ch != '-' &&
685 ch != '.' && ch != ']' && ch != EOF) {
686 nextch_handling_eol();
688 y = read_numeric(fFalse);
689 while (!isdigit(ch) && ch != '+' && ch != '-' &&
690 ch != '.' && ch != ']' && ch != EOF) {
691 nextch_handling_eol();
693 z = read_numeric(fFalse);
694 stn = StnFromPfx(name);
695 if (!fixed(stn)) {
696 POS(stn, 0) = x;
697 POS(stn, 1) = y;
698 POS(stn, 2) = z;
699 fix(stn);
700 } else {
701 if (x != POS(stn, 0) || y != POS(stn, 1) ||
702 z != POS(stn, 2)) {
703 compile_error(/*Station already fixed or equated to a fixed point*/46);
704 } else {
705 compile_warning(/*Station already fixed at the same coordinates*/55);
708 while (ch != ']' && ch != EOF) nextch_handling_eol();
709 if (ch == ']') {
710 nextch_handling_eol();
711 skipblanks();
713 } else {
714 /* FIXME: link station - ignore for now */
715 /* FIXME: perhaps issue warning? */
717 while (ch != ',' && ch != ';' && ch != EOF)
718 nextch_handling_eol();
721 if (dat_fnm) {
722 ch_store = ch;
723 data_file(dat_pth, dat_fnm);
724 ch = ch_store;
725 osfree(dat_fnm);
727 } else {
728 /* FIXME: also check for % and $ later */
729 nextch_handling_eol();
733 settings *pcsParent = pcs->next;
734 SVX_ASSERT(pcsParent);
735 free_settings(pcs);
736 pcs = pcsParent;
738 } else {
739 while (!feof(file.fh) && !ferror(file.fh)) {
740 if (!process_non_data_line()) {
741 f_export_ok = fFalse;
742 switch (pcs->style) {
743 case STYLE_NORMAL:
744 case STYLE_DIVING:
745 case STYLE_CYLPOLAR:
746 data_normal();
747 break;
748 case STYLE_CARTESIAN:
749 data_cartesian();
750 break;
751 case STYLE_PASSAGE:
752 data_passage();
753 break;
754 case STYLE_NOSURVEY:
755 data_nosurvey();
756 break;
757 case STYLE_IGNORE:
758 data_ignore();
759 break;
760 default:
761 BUG("bad style");
765 clear_last_leg();
768 /* don't allow *BEGIN at the end of a file, then *EXPORT in the
769 * including file */
770 f_export_ok = fFalse;
772 if (pcs->begin_lineno) {
773 error_in_file(file.filename, pcs->begin_lineno,
774 /*BEGIN with no matching END in this file*/23);
775 /* Implicitly close any unclosed BEGINs from this file */
776 do {
777 settings *pcsParent = pcs->next;
778 SVX_ASSERT(pcsParent);
779 free_settings(pcs);
780 pcs = pcsParent;
781 } while (pcs->begin_lineno);
784 pcs->begin_lineno = begin_lineno_store;
786 if (ferror(file.fh))
787 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
789 (void)fclose(file.fh);
791 file = file_store;
793 /* don't free this - it may be pointed to by prefix.file */
794 /* osfree(file.filename); */
797 static real
798 mod2pi(real a)
800 return a - floor(a / (2 * M_PI)) * (2 * M_PI);
803 static real
804 handle_plumb(clino_type *p_ctype)
806 typedef enum {
807 CLINO_NULL=-1, CLINO_UP, CLINO_DOWN, CLINO_LEVEL
808 } clino_tok;
809 static sztok clino_tab[] = {
810 {"D", CLINO_DOWN},
811 {"DOWN", CLINO_DOWN},
812 {"H", CLINO_LEVEL},
813 {"LEVEL", CLINO_LEVEL},
814 {"U", CLINO_UP},
815 {"UP", CLINO_UP},
816 {NULL, CLINO_NULL}
818 static real clinos[] = {(real)M_PI_2, (real)(-M_PI_2), (real)0.0};
819 clino_tok tok;
821 skipblanks();
822 if (isalpha(ch)) {
823 filepos fp;
824 get_pos(&fp);
825 get_token();
826 tok = match_tok(clino_tab, TABSIZE(clino_tab));
827 if (tok != CLINO_NULL) {
828 *p_ctype = (tok == CLINO_LEVEL ? CTYPE_HORIZ : CTYPE_PLUMB);
829 return clinos[tok];
831 set_pos(&fp);
832 } else if (isSign(ch)) {
833 int chOld = ch;
834 nextch();
835 if (toupper(ch) == 'V') {
836 nextch();
837 *p_ctype = CTYPE_PLUMB;
838 return (!isMinus(chOld) ? M_PI_2 : -M_PI_2);
841 if (isOmit(chOld)) {
842 *p_ctype = CTYPE_OMIT;
843 /* no clino reading, so assume 0 with large sd */
844 return (real)0.0;
846 } else if (isOmit(ch)) {
847 /* OMIT char may not be a SIGN char too so we need to check here as
848 * well as above... */
849 nextch();
850 *p_ctype = CTYPE_OMIT;
851 /* no clino reading, so assume 0 with large sd */
852 return (real)0.0;
854 return HUGE_REAL;
857 static void
858 warn_readings_differ(int msgno, real diff, int units)
860 char buf[64];
861 char *p;
862 diff /= get_units_factor(units);
863 sprintf(buf, "%.2f", fabs(diff));
864 for (p = buf; *p; ++p) {
865 if (*p == '.') {
866 char *z = p;
867 while (*++p) {
868 if (*p != '0') z = p + 1;
870 p = z;
871 break;
874 strcpy(p, get_units_string(units));
875 compile_warning(msgno, buf);
878 static bool
879 handle_comp_units(void)
881 bool fNoComp = fTrue;
882 if (VAL(Comp) != HUGE_REAL) {
883 fNoComp = fFalse;
884 VAL(Comp) *= pcs->units[Q_BEARING];
885 if (VAL(Comp) < (real)0.0 || VAL(Comp) - M_PI * 2.0 > EPSILON) {
886 /* TRANSLATORS: Suspicious means something like 410 degrees or -20
887 * degrees */
888 compile_warning(/*Suspicious compass reading*/59);
889 VAL(Comp) = mod2pi(VAL(Comp));
892 if (VAL(BackComp) != HUGE_REAL) {
893 fNoComp = fFalse;
894 VAL(BackComp) *= pcs->units[Q_BACKBEARING];
895 if (VAL(BackComp) < (real)0.0 || VAL(BackComp) - M_PI * 2.0 > EPSILON) {
896 /* FIXME: different message for BackComp? */
897 compile_warning(/*Suspicious compass reading*/59);
898 VAL(BackComp) = mod2pi(VAL(BackComp));
901 return fNoComp;
904 static real
905 handle_compass(real *p_var)
907 real compvar = VAR(Comp);
908 real comp = VAL(Comp);
909 real backcomp = VAL(BackComp);
910 real declination;
911 if (pcs->z[Q_DECLINATION] != HUGE_REAL) {
912 declination = -pcs->z[Q_DECLINATION];
913 } else if (pcs->declination != HUGE_REAL) {
914 /* Cached value calculated for a previous compass reading taken on the
915 * same date (by the 'else' just below).
917 declination = pcs->declination;
918 } else {
919 if (!pcs->meta || pcs->meta->days1 == -1) {
920 compile_warning(/*No survey date specified - using 0 for magnetic declination*/304);
921 declination = 0;
922 } else {
923 int avg_days = (pcs->meta->days1 + pcs->meta->days2) / 2;
924 double dat = julian_date_from_days_since_1900(avg_days);
925 /* thgeomag() takes (lat, lon, h, dat) - i.e. (y, x, z, date). */
926 declination = thgeomag(pcs->dec_y, pcs->dec_x, pcs->dec_z, dat);
928 declination -= pcs->convergence;
929 /* We cache the calculated declination as the calculation is relatively
930 * expensive. We also cache an "assumed 0" answer so that we only
931 * warn once per such survey rather than for every line with a compass
932 * reading. */
933 pcs->declination = declination;
935 if (comp != HUGE_REAL) {
936 comp = (comp - pcs->z[Q_BEARING]) * pcs->sc[Q_BEARING];
937 comp += declination;
939 if (backcomp != HUGE_REAL) {
940 backcomp = (backcomp - pcs->z[Q_BACKBEARING])
941 * pcs->sc[Q_BACKBEARING];
942 backcomp += declination;
943 backcomp -= M_PI;
944 if (comp != HUGE_REAL) {
945 real diff = comp - backcomp;
946 real adj = fabs(diff) > M_PI ? M_PI : 0;
947 diff -= floor((diff + M_PI) / (2 * M_PI)) * 2 * M_PI;
948 if (sqrd(diff / 3.0) > compvar + VAR(BackComp)) {
949 /* fore and back readings differ by more than 3 sds */
950 /* TRANSLATORS: %s is replaced by the amount the readings disagree
951 * by, e.g. "2.5Ā°" or "3įµ". */
952 warn_readings_differ(/*COMPASS reading and BACKCOMPASS reading disagree by %s*/98,
953 diff, get_angle_units(Q_BEARING));
955 comp = (comp / compvar + backcomp / VAR(BackComp));
956 compvar = (compvar + VAR(BackComp)) / 4;
957 comp *= compvar;
958 comp += adj;
959 } else {
960 comp = backcomp;
961 compvar = VAR(BackComp);
964 *p_var = compvar;
965 return comp;
968 static int
969 process_normal(prefix *fr, prefix *to, bool fToFirst,
970 clino_type ctype, clino_type backctype)
972 real tape = VAL(Tape);
973 real clin = VAL(Clino);
974 real backclin = VAL(BackClino);
976 real dx, dy, dz;
977 real vx, vy, vz;
978 #ifndef NO_COVARIANCES
979 real cxy, cyz, czx;
980 #endif
982 bool fNoComp;
984 /* adjusted tape is negative -- probably the calibration is wrong */
985 if (tape < (real)0.0) {
986 /* TRANSLATE different message for topofil? */
987 compile_warning(/*Negative adjusted tape reading*/79);
990 fNoComp = handle_comp_units();
992 if (ctype == CTYPE_READING) {
993 bool range_0_180;
994 real z;
995 real diff_from_abs90;
996 clin *= pcs->units[Q_GRADIENT];
997 /* percentage scale */
998 if (pcs->f_clino_percent) clin = atan(clin);
999 /* We want to warn if there's a reading which it would be impossible
1000 * to have read from the instrument (e.g. on a -90 to 90 degree scale
1001 * you can't read "96" (it's probably a typo for "69"). However, the
1002 * gradient reading from a topofil is typically in the range 0 to 180,
1003 * with 90 being horizontal.
1005 * Really we should allow the valid range to be specified, but for now
1006 * we infer it from the zero error - if this is within 45 degrees of
1007 * 90 then we assume the range is 0 to 180.
1009 z = pcs->z[Q_GRADIENT];
1010 range_0_180 = (z > M_PI_4 && z < 3*M_PI_4);
1011 diff_from_abs90 = fabs(clin) - M_PI_2;
1012 if (diff_from_abs90 > EPSILON) {
1013 if (!range_0_180) {
1014 int clino_units = get_angle_units(Q_GRADIENT);
1015 const char * units = get_units_string(clino_units);
1016 real right_angle = M_PI_2 / get_units_factor(clino_units);
1017 /* TRANSLATORS: %.f%s will be replaced with a right angle in the
1018 * units currently in use, e.g. "90Ā°" or "100įµ". And "absolute
1019 * value" means the reading ignoring the sign (so it might be
1020 * < -90Ā° or > 90Ā°. */
1021 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1022 right_angle, units);
1024 } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
1025 diff_from_abs90 >= -EPSILON) {
1026 ctype = CTYPE_INFERPLUMB;
1028 if (range_0_180 && ctype != CTYPE_INFERPLUMB) {
1029 /* FIXME: Warning message not ideal... */
1030 if (clin < 0.0 || clin - M_PI > EPSILON) {
1031 int clino_units = get_angle_units(Q_GRADIENT);
1032 const char * units = get_units_string(clino_units);
1033 real right_angle = M_PI_2 / get_units_factor(clino_units);
1034 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1035 right_angle, units);
1040 if (backctype == CTYPE_READING) {
1041 backclin *= pcs->units[Q_BACKGRADIENT];
1042 /* percentage scale */
1043 if (pcs->f_backclino_percent) backclin = atan(backclin);
1044 /* FIXME: Add range_0_180 handling here too */
1045 if (ctype != CTYPE_READING) {
1046 real diff_from_abs90 = fabs(backclin) - M_PI_2;
1047 if (diff_from_abs90 > EPSILON) {
1048 /* FIXME: different message for BackClino? */
1049 int clino_units = get_angle_units(Q_BACKGRADIENT);
1050 const char * units = get_units_string(clino_units);
1051 real right_angle = M_PI_2 / get_units_factor(clino_units);
1052 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1053 right_angle, units);
1054 } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
1055 diff_from_abs90 >= -EPSILON) {
1056 backctype = CTYPE_INFERPLUMB;
1061 /* un-infer the plumb if the backsight was just a reading */
1062 if (ctype == CTYPE_INFERPLUMB && backctype == CTYPE_READING) {
1063 ctype = CTYPE_READING;
1066 if (ctype != CTYPE_OMIT && backctype != CTYPE_OMIT && ctype != backctype) {
1067 /* TRANSLATORS: In data with backsights, the user has tried to give a
1068 * plumb for the foresight and a clino reading for the backsight, or
1069 * something similar. */
1070 compile_error_reading_skip(Clino, /*CLINO and BACKCLINO readings must be of the same type*/84);
1071 return 0;
1074 if (ctype == CTYPE_PLUMB || ctype == CTYPE_INFERPLUMB ||
1075 backctype == CTYPE_PLUMB || backctype == CTYPE_INFERPLUMB) {
1076 /* plumbed */
1077 if (!fNoComp) {
1078 if (ctype == CTYPE_PLUMB ||
1079 (ctype == CTYPE_INFERPLUMB && VAL(Comp) != 0.0) ||
1080 backctype == CTYPE_PLUMB ||
1081 (backctype == CTYPE_INFERPLUMB && VAL(BackComp) != 0.0)) {
1082 /* FIXME: Different message for BackComp? */
1083 /* TRANSLATORS: A "plumbed leg" is one measured using a plumbline
1084 * (a weight on a string). So the problem here is that the leg is
1085 * vertical, so a compass reading has no meaning! */
1086 compile_warning(/*Compass reading given on plumbed leg*/21);
1090 dx = dy = (real)0.0;
1091 if (ctype != CTYPE_OMIT) {
1092 if (backctype != CTYPE_OMIT && (clin > 0) == (backclin > 0)) {
1093 /* TRANSLATORS: We've been told the foresight and backsight are
1094 * both "UP", or that they're both "DOWN". */
1095 compile_error_reading_skip(Clino, /*Plumbed CLINO and BACKCLINO readings can't be in the same direction*/92);
1096 return 0;
1098 dz = (clin > (real)0.0) ? tape : -tape;
1099 } else {
1100 dz = (backclin < (real)0.0) ? tape : -tape;
1102 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1103 vz = var(Q_POS) / 3.0 + VAR(Tape);
1104 #ifndef NO_COVARIANCES
1105 /* Correct values - no covariances in this case! */
1106 cxy = cyz = czx = (real)0.0;
1107 #endif
1108 } else {
1109 /* Each of ctype and backctype are either CTYPE_READING/CTYPE_HORIZ
1110 * or CTYPE_OMIT */
1111 /* clino */
1112 real L2, cosG, LcosG, cosG2, sinB, cosB, dx2, dy2, dz2, v, V;
1113 if (fNoComp) {
1114 /* TRANSLATORS: Here "legs" are survey legs, i.e. measurements between
1115 * survey stations. */
1116 compile_error_reading_skip(Comp, /*Compass reading may not be omitted except on plumbed legs*/14);
1117 return 0;
1119 if (tape == (real)0.0) {
1120 dx = dy = dz = (real)0.0;
1121 vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1122 #ifndef NO_COVARIANCES
1123 cxy = cyz = czx = (real)0.0;
1124 #endif
1125 #if DEBUG_DATAIN_1
1126 printf("Zero length leg: vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1127 #endif
1128 } else {
1129 real sinGcosG;
1130 /* take into account variance in LEVEL case */
1131 real var_clin = var(Q_LEVEL);
1132 real var_comp;
1133 real comp = handle_compass(&var_comp);
1134 /* ctype != CTYPE_READING is LEVEL case */
1135 if (ctype == CTYPE_READING) {
1136 clin = (clin - pcs->z[Q_GRADIENT]) * pcs->sc[Q_GRADIENT];
1137 var_clin = VAR(Clino);
1139 if (backctype == CTYPE_READING) {
1140 backclin = (backclin - pcs->z[Q_BACKGRADIENT])
1141 * pcs->sc[Q_BACKGRADIENT];
1142 if (ctype == CTYPE_READING) {
1143 if (sqrd((clin + backclin) / 3.0) > var_clin + VAR(BackClino)) {
1144 /* fore and back readings differ by more than 3 sds */
1145 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1146 * by, e.g. "2.5Ā°" or "3įµ". */
1147 warn_readings_differ(/*CLINO reading and BACKCLINO reading disagree by %s*/99,
1148 clin + backclin, get_angle_units(Q_GRADIENT));
1150 clin = (clin / var_clin - backclin / VAR(BackClino));
1151 var_clin = (var_clin + VAR(BackClino)) / 4;
1152 clin *= var_clin;
1153 } else {
1154 clin = -backclin;
1155 var_clin = VAR(BackClino);
1159 #if DEBUG_DATAIN
1160 printf(" %4.2f %4.2f %4.2f\n", tape, comp, clin);
1161 #endif
1162 cosG = cos(clin);
1163 LcosG = tape * cosG;
1164 sinB = sin(comp);
1165 cosB = cos(comp);
1166 #if DEBUG_DATAIN_1
1167 printf("sinB = %f, cosG = %f, LcosG = %f\n", sinB, cosG, LcosG);
1168 #endif
1169 dx = LcosG * sinB;
1170 dy = LcosG * cosB;
1171 dz = tape * sin(clin);
1172 /* printf("%.2f\n",clin); */
1173 #if DEBUG_DATAIN_1
1174 printf("dx = %f\ndy = %f\ndz = %f\n", dx, dy, dz);
1175 #endif
1176 dx2 = dx * dx;
1177 L2 = tape * tape;
1178 V = VAR(Tape) / L2;
1179 dy2 = dy * dy;
1180 cosG2 = cosG * cosG;
1181 sinGcosG = sin(clin) * cosG;
1182 dz2 = dz * dz;
1183 v = dz2 * var_clin;
1184 #ifdef NO_COVARIANCES
1185 vx = (var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1186 (.5 + sinB * sinB * cosG2) * v);
1187 vy = (var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1188 (.5 + cosB * cosB * cosG2) * v);
1189 if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1190 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1191 vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1192 } else {
1193 vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1195 /* for Surveyor87 errors: vx=vy=vz=var(Q_POS)/3.0; */
1196 #else
1197 vx = var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1198 (sinB * sinB * v);
1199 vy = var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1200 (cosB * cosB * v);
1201 if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1202 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1203 vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1204 } else {
1205 vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1207 /* usual covariance formulae are fine in no clino case since
1208 * dz = 0 so value of var_clin is ignored */
1209 cxy = sinB * cosB * (VAR(Tape) * cosG2 + var_clin * dz2)
1210 - var_comp * dx * dy;
1211 czx = VAR(Tape) * sinB * sinGcosG - var_clin * dx * dz;
1212 cyz = VAR(Tape) * cosB * sinGcosG - var_clin * dy * dz;
1213 #if 0
1214 printf("vx = %6.3f, vy = %6.3f, vz = %6.3f\n", vx, vy, vz);
1215 printf("cxy = %6.3f, cyz = %6.3f, czx = %6.3f\n", cxy, cyz, czx);
1216 #endif
1217 #endif
1218 #if DEBUG_DATAIN_1
1219 printf("In DATAIN.C, vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1220 #endif
1223 #if DEBUG_DATAIN_1
1224 printf("Just before addleg, vx = %f\n", vx);
1225 #endif
1226 /*printf("dx,dy,dz = %.2f %.2f %.2f\n\n", dx, dy, dz);*/
1227 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1228 #ifndef NO_COVARIANCES
1229 , cyz, czx, cxy
1230 #endif
1232 return 1;
1235 static int
1236 process_diving(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1238 real tape = VAL(Tape);
1240 real dx, dy, dz;
1241 real vx, vy, vz;
1242 #ifndef NO_COVARIANCES
1243 real cxy = 0, cyz = 0, czx = 0;
1244 #endif
1246 handle_comp_units();
1248 /* depth gauge readings increase upwards with default calibration */
1249 if (fDepthChange) {
1250 SVX_ASSERT(VAL(FrDepth) == 0.0);
1251 dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1252 dz *= pcs->sc[Q_DEPTH];
1253 } else {
1254 dz = VAL(ToDepth) - VAL(FrDepth);
1255 dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1258 /* adjusted tape is negative -- probably the calibration is wrong */
1259 if (tape < (real)0.0) {
1260 compile_warning(/*Negative adjusted tape reading*/79);
1263 /* check if tape is less than depth change */
1264 if (tape < fabs(dz)) {
1265 /* FIXME: allow margin of error based on variances? */
1266 /* TRANSLATORS: This means that the data fed in said this.
1268 * It could be a gross error (e.g. the decimal point is missing from the
1269 * depth gauge reading) or it could just be due to random error on a near
1270 * vertical leg */
1271 compile_warning(/*Tape reading is less than change in depth*/62);
1274 if (tape == (real)0.0 && dz == 0.0) {
1275 dx = dy = dz = (real)0.0;
1276 vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1277 } else if (VAL(Comp) == HUGE_REAL &&
1278 VAL(BackComp) == HUGE_REAL) {
1279 /* plumb */
1280 dx = dy = (real)0.0;
1281 if (dz < 0) tape = -tape;
1282 /* FIXME: Should use FrDepth sometimes... */
1283 dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth))
1284 / (VAR(Tape) * 2 * VAR(ToDepth));
1285 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1286 /* FIXME: Should use FrDepth sometimes... */
1287 vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth)
1288 / (VAR(Tape) + VAR(ToDepth));
1289 } else {
1290 real L2, sinB, cosB, dz2, D2;
1291 real var_comp;
1292 real comp = handle_compass(&var_comp);
1293 sinB = sin(comp);
1294 cosB = cos(comp);
1295 L2 = tape * tape;
1296 dz2 = dz * dz;
1297 D2 = L2 - dz2;
1298 if (D2 <= (real)0.0) {
1299 /* FIXME: Should use FrDepth sometimes... */
1300 real vsum = VAR(Tape) + 2 * VAR(ToDepth);
1301 dx = dy = (real)0.0;
1302 vx = vy = var(Q_POS) / 3.0;
1303 /* FIXME: Should use FrDepth sometimes... */
1304 vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth) / vsum;
1305 if (dz > 0) {
1306 /* FIXME: Should use FrDepth sometimes... */
1307 dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth)) / vsum;
1308 } else {
1309 dz = (dz * VAR(Tape) - tape * 2 * VAR(ToDepth)) / vsum;
1311 } else {
1312 real D = sqrt(D2);
1313 /* FIXME: Should use FrDepth sometimes... */
1314 real F = VAR(Tape) * L2 + 2 * VAR(ToDepth) * D2;
1315 dx = D * sinB;
1316 dy = D * cosB;
1318 vx = var(Q_POS) / 3.0 +
1319 sinB * sinB * F / D2 + var_comp * dy * dy;
1320 vy = var(Q_POS) / 3.0 +
1321 cosB * cosB * F / D2 + var_comp * dx * dx;
1322 /* FIXME: Should use FrDepth sometimes... */
1323 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1325 #ifndef NO_COVARIANCES
1326 cxy = sinB * cosB * (F / D2 + var_comp * D2);
1327 /* FIXME: Should use FrDepth sometimes... */
1328 cyz = -2 * VAR(ToDepth) * dy / D;
1329 czx = -2 * VAR(ToDepth) * dx / D;
1330 #endif
1332 /* FIXME: If there's a clino reading, check it against the depth reading,
1333 * and average.
1334 * if (VAL(Clino) != HUGE_REAL || VAL(BackClino) != HUGE_REAL) { ... }
1337 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1338 #ifndef NO_COVARIANCES
1339 , cxy, cyz, czx
1340 #endif
1342 return 1;
1345 static int
1346 process_cartesian(prefix *fr, prefix *to, bool fToFirst)
1348 real dx = (VAL(Dx) * pcs->units[Q_DX] - pcs->z[Q_DX]) * pcs->sc[Q_DX];
1349 real dy = (VAL(Dy) * pcs->units[Q_DY] - pcs->z[Q_DY]) * pcs->sc[Q_DY];
1350 real dz = (VAL(Dz) * pcs->units[Q_DZ] - pcs->z[Q_DZ]) * pcs->sc[Q_DZ];
1352 addlegbyname(fr, to, fToFirst, dx, dy, dz, VAR(Dx), VAR(Dy), VAR(Dz)
1353 #ifndef NO_COVARIANCES
1354 , 0, 0, 0
1355 #endif
1357 return 1;
1360 static void
1361 data_cartesian(void)
1363 prefix *fr = NULL, *to = NULL;
1365 bool fMulti = fFalse;
1367 reading first_stn = End;
1369 reading *ordering;
1371 again:
1373 for (ordering = pcs->ordering ; ; ordering++) {
1374 skipblanks();
1375 switch (*ordering) {
1376 case Fr:
1377 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
1378 if (first_stn == End) first_stn = Fr;
1379 break;
1380 case To:
1381 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
1382 if (first_stn == End) first_stn = To;
1383 break;
1384 case Station:
1385 fr = to;
1386 to = read_prefix(PFX_STATION);
1387 first_stn = To;
1388 break;
1389 case Dx: case Dy: case Dz:
1390 read_reading(*ordering, fFalse);
1391 break;
1392 case Ignore:
1393 skipword(); break;
1394 case IgnoreAllAndNewLine:
1395 skipline();
1396 /* fall through */
1397 case Newline:
1398 if (fr != NULL) {
1399 if (!process_cartesian(fr, to, first_stn == To))
1400 skipline();
1402 fMulti = fTrue;
1403 while (1) {
1404 process_eol();
1405 skipblanks();
1406 if (isData(ch)) break;
1407 if (!isComm(ch)) {
1408 return;
1411 break;
1412 case IgnoreAll:
1413 skipline();
1414 /* fall through */
1415 case End:
1416 if (!fMulti) {
1417 process_cartesian(fr, to, first_stn == To);
1418 process_eol();
1419 return;
1421 do {
1422 process_eol();
1423 skipblanks();
1424 } while (isComm(ch));
1425 goto again;
1426 default: BUG("Unknown reading in ordering");
1431 static int
1432 process_cylpolar(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1434 real tape = VAL(Tape);
1436 real dx, dy, dz;
1437 real vx, vy, vz;
1438 #ifndef NO_COVARIANCES
1439 real cxy = 0;
1440 #endif
1442 handle_comp_units();
1444 /* depth gauge readings increase upwards with default calibration */
1445 if (fDepthChange) {
1446 SVX_ASSERT(VAL(FrDepth) == 0.0);
1447 dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1448 dz *= pcs->sc[Q_DEPTH];
1449 } else {
1450 dz = VAL(ToDepth) - VAL(FrDepth);
1451 dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1454 /* adjusted tape is negative -- probably the calibration is wrong */
1455 if (tape < (real)0.0) {
1456 compile_warning(/*Negative adjusted tape reading*/79);
1459 if (VAL(Comp) == HUGE_REAL && VAL(BackComp) == HUGE_REAL) {
1460 /* plumb */
1461 dx = dy = (real)0.0;
1462 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1463 /* FIXME: Should use FrDepth sometimes... */
1464 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1465 } else {
1466 real sinB, cosB;
1467 real var_comp;
1468 real comp = handle_compass(&var_comp);
1469 sinB = sin(comp);
1470 cosB = cos(comp);
1472 dx = tape * sinB;
1473 dy = tape * cosB;
1475 vx = var(Q_POS) / 3.0 +
1476 VAR(Tape) * sinB * sinB + var_comp * dy * dy;
1477 vy = var(Q_POS) / 3.0 +
1478 VAR(Tape) * cosB * cosB + var_comp * dx * dx;
1479 /* FIXME: Should use FrDepth sometimes... */
1480 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1482 #ifndef NO_COVARIANCES
1483 cxy = (VAR(Tape) - var_comp * tape * tape) * sinB * cosB;
1484 #endif
1486 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1487 #ifndef NO_COVARIANCES
1488 , cxy, 0, 0
1489 #endif
1491 return 1;
1494 /* Process tape/compass/clino, diving, and cylpolar styles of survey data
1495 * Also handles topofil (fromcount/tocount or count) in place of tape */
1496 static void
1497 data_normal(void)
1499 prefix *fr = NULL, *to = NULL;
1500 reading first_stn = End;
1502 bool fTopofil = fFalse, fMulti = fFalse;
1503 bool fRev;
1504 clino_type ctype, backctype;
1505 bool fDepthChange;
1506 unsigned long compass_dat_flags = 0;
1508 reading *ordering;
1510 VAL(Tape) = VAL(BackTape) = HUGE_REAL;
1511 VAL(Comp) = VAL(BackComp) = HUGE_REAL;
1512 VAL(FrCount) = VAL(ToCount) = 0;
1513 VAL(FrDepth) = VAL(ToDepth) = 0;
1514 VAL(Left) = VAL(Right) = VAL(Up) = VAL(Down) = HUGE_REAL;
1516 fRev = fFalse;
1517 ctype = backctype = CTYPE_OMIT;
1518 fDepthChange = fFalse;
1520 /* ordering may omit clino reading, so set up default here */
1521 /* this is also used if clino reading is the omit character */
1522 VAL(Clino) = VAL(BackClino) = 0;
1524 again:
1526 /* We clear these flags in the normal course of events, but if there's an
1527 * error in a reading, we might not, so make sure it has been cleared here.
1529 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1530 for (ordering = pcs->ordering; ; ordering++) {
1531 skipblanks();
1532 switch (*ordering) {
1533 case Fr:
1534 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT|PFX_ANON);
1535 if (first_stn == End) first_stn = Fr;
1536 break;
1537 case To:
1538 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT|PFX_ANON);
1539 if (first_stn == End) first_stn = To;
1540 break;
1541 case Station:
1542 fr = to;
1543 to = read_prefix(PFX_STATION);
1544 first_stn = To;
1545 break;
1546 case Dir: {
1547 typedef enum {
1548 DIR_NULL=-1, DIR_FORE, DIR_BACK
1549 } dir_tok;
1550 static sztok dir_tab[] = {
1551 {"B", DIR_BACK},
1552 {"F", DIR_FORE},
1554 dir_tok tok;
1555 get_token();
1556 tok = match_tok(dir_tab, TABSIZE(dir_tab));
1557 switch (tok) {
1558 case DIR_FORE:
1559 break;
1560 case DIR_BACK:
1561 fRev = fTrue;
1562 break;
1563 default:
1564 file.lpos += strlen(buffer);
1565 compile_error_skip(-/*Found ā€œ%sā€, expecting ā€œFā€ or ā€œBā€*/131,
1566 buffer);
1567 process_eol();
1568 return;
1570 break;
1572 case Tape: case BackTape: {
1573 reading r = *ordering;
1574 read_reading(r, fTrue);
1575 if (VAL(r) == HUGE_REAL) {
1576 if (!isOmit(ch)) {
1577 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1578 /* Avoid also warning about omitted tape reading. */
1579 VAL(r) = 0;
1580 } else {
1581 nextch();
1583 } else if (VAL(r) < (real)0.0) {
1584 compile_warning(-/*Negative tape reading*/60);
1586 break;
1588 case Count:
1589 VAL(FrCount) = VAL(ToCount);
1590 LOC(FrCount) = LOC(ToCount);
1591 read_reading(ToCount, fFalse);
1592 fTopofil = fTrue;
1593 break;
1594 case FrCount:
1595 read_reading(FrCount, fFalse);
1596 break;
1597 case ToCount:
1598 read_reading(ToCount, fFalse);
1599 fTopofil = fTrue;
1600 break;
1601 case Comp: case BackComp:
1602 read_bearing_or_omit(*ordering);
1603 break;
1604 case Clino: case BackClino: {
1605 reading r = *ordering;
1606 clino_type * p_ctype = (r == Clino ? &ctype : &backctype);
1607 read_reading(r, fTrue);
1608 if (VAL(r) == HUGE_REAL) {
1609 VAL(r) = handle_plumb(p_ctype);
1610 if (VAL(r) != HUGE_REAL) break;
1611 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1612 skipline();
1613 process_eol();
1614 return;
1616 *p_ctype = CTYPE_READING;
1617 break;
1619 case FrDepth: case ToDepth:
1620 read_reading(*ordering, fFalse);
1621 break;
1622 case Depth:
1623 VAL(FrDepth) = VAL(ToDepth);
1624 LOC(FrDepth) = LOC(ToDepth);
1625 read_reading(ToDepth, fFalse);
1626 break;
1627 case DepthChange:
1628 fDepthChange = fTrue;
1629 VAL(FrDepth) = 0;
1630 read_reading(ToDepth, fFalse);
1631 break;
1632 case CompassDATComp:
1633 read_bearing_or_omit(Comp);
1634 if (is_compass_NaN(VAL(Comp))) VAL(Comp) = HUGE_REAL;
1635 break;
1636 case CompassDATBackComp:
1637 read_bearing_or_omit(BackComp);
1638 if (is_compass_NaN(VAL(BackComp))) VAL(BackComp) = HUGE_REAL;
1639 break;
1640 case CompassDATClino: case CompassDATBackClino: {
1641 reading r;
1642 clino_type * p_ctype;
1643 if (*ordering == CompassDATClino) {
1644 r = Clino;
1645 p_ctype = &ctype;
1646 } else {
1647 r = BackClino;
1648 p_ctype = &backctype;
1650 read_reading(r, fFalse);
1651 if (is_compass_NaN(VAL(r))) {
1652 VAL(r) = HUGE_REAL;
1653 *p_ctype = CTYPE_OMIT;
1654 } else {
1655 *p_ctype = CTYPE_READING;
1657 break;
1659 case CompassDATLeft: case CompassDATRight:
1660 case CompassDATUp: case CompassDATDown: {
1661 /* FIXME: need to actually make use of these entries! */
1662 reading actual = Left + (*ordering - CompassDATLeft);
1663 read_reading(actual, fFalse);
1664 if (VAL(actual) < 0) VAL(actual) = HUGE_REAL;
1665 break;
1667 case CompassDATFlags:
1668 if (ch == '#') {
1669 filepos fp;
1670 get_pos(&fp);
1671 nextch();
1672 if (ch == '|') {
1673 nextch();
1674 while (ch >= 'A' && ch <= 'Z') {
1675 compass_dat_flags |= BIT(ch - 'A');
1676 /* We currently understand:
1677 * L (exclude from length)
1678 * X (exclude data)
1679 * FIXME: but should also handle at least some of:
1680 * C (no adjustment) (set all (co)variances to 0?)
1681 * P (no plot) (new flag in 3d for "hidden by default"?)
1683 nextch();
1685 if (ch == '#') {
1686 nextch();
1687 } else {
1688 compass_dat_flags = 0;
1689 set_pos(&fp);
1691 } else {
1692 set_pos(&fp);
1695 break;
1696 case Ignore:
1697 skipword(); break;
1698 case IgnoreAllAndNewLine:
1699 skipline();
1700 /* fall through */
1701 case Newline:
1702 if (fr != NULL) {
1703 int r;
1704 int save_flags;
1705 int implicit_splay;
1706 if (fTopofil) {
1707 VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1708 LOC(Tape) = LOC(ToCount);
1710 /* Note: frdepth == todepth test works regardless of fDepthChange
1711 * (frdepth always zero, todepth is change of depth) and also
1712 * works for STYLE_NORMAL (both remain 0) */
1713 if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1714 (VAL(Tape) == (real)0.0 || VAL(Tape) == HUGE_REAL) &&
1715 (VAL(BackTape) == (real)0.0 || VAL(BackTape) == HUGE_REAL) &&
1716 VAL(FrDepth) == VAL(ToDepth)) {
1717 process_equate(fr, to);
1718 goto inferred_equate;
1720 if (fRev) {
1721 prefix *t = fr;
1722 fr = to;
1723 to = t;
1725 if (fTopofil) {
1726 VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1727 } else if (VAL(Tape) != HUGE_REAL) {
1728 VAL(Tape) *= pcs->units[Q_LENGTH];
1729 VAL(Tape) -= pcs->z[Q_LENGTH];
1730 VAL(Tape) *= pcs->sc[Q_LENGTH];
1732 if (VAL(BackTape) != HUGE_REAL) {
1733 VAL(BackTape) *= pcs->units[Q_BACKLENGTH];
1734 VAL(BackTape) -= pcs->z[Q_BACKLENGTH];
1735 VAL(BackTape) *= pcs->sc[Q_BACKLENGTH];
1736 if (VAL(Tape) != HUGE_REAL) {
1737 real diff = VAL(Tape) - VAL(BackTape);
1738 if (sqrd(diff / 3.0) > VAR(Tape) + VAR(BackTape)) {
1739 /* fore and back readings differ by more than 3 sds */
1740 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1741 * by, e.g. "0.12m" or "0.2ft". */
1742 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1743 diff, get_length_units(Q_LENGTH));
1745 VAL(Tape) = VAL(Tape) / VAR(Tape) + VAL(BackTape) / VAR(BackTape);
1746 VAR(Tape) = (VAR(Tape) + VAR(BackTape)) / 4;
1747 VAL(Tape) *= VAR(Tape);
1748 } else {
1749 VAL(Tape) = VAL(BackTape);
1750 VAR(Tape) = VAR(BackTape);
1752 } else if (VAL(Tape) == HUGE_REAL) {
1753 compile_error_reading(Tape, /*Tape reading may not be omitted*/94);
1754 goto inferred_equate;
1756 implicit_splay = TSTBIT(pcs->flags, FLAGS_IMPLICIT_SPLAY);
1757 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1758 save_flags = pcs->flags;
1759 if (implicit_splay) {
1760 pcs->flags |= BIT(FLAGS_SPLAY);
1762 switch (pcs->style) {
1763 case STYLE_NORMAL:
1764 r = process_normal(fr, to, (first_stn == To) ^ fRev,
1765 ctype, backctype);
1766 break;
1767 case STYLE_DIVING:
1768 /* FIXME: Handle any clino readings */
1769 r = process_diving(fr, to, (first_stn == To) ^ fRev,
1770 fDepthChange);
1771 break;
1772 case STYLE_CYLPOLAR:
1773 r = process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1774 fDepthChange);
1775 break;
1776 default:
1777 r = 0; /* avoid warning */
1778 BUG("bad style");
1780 pcs->flags = save_flags;
1781 if (!r) skipline();
1783 /* Swap fr and to back to how they were for next line */
1784 if (fRev) {
1785 prefix *t = fr;
1786 fr = to;
1787 to = t;
1791 fRev = fFalse;
1792 ctype = backctype = CTYPE_OMIT;
1793 fDepthChange = fFalse;
1795 /* ordering may omit clino reading, so set up default here */
1796 /* this is also used if clino reading is the omit character */
1797 VAL(Clino) = VAL(BackClino) = 0;
1798 LOC(Clino) = LOC(BackClino) = -1;
1800 inferred_equate:
1802 fMulti = fTrue;
1803 while (1) {
1804 process_eol();
1805 skipblanks();
1806 if (isData(ch)) break;
1807 if (!isComm(ch)) {
1808 return;
1811 break;
1812 case IgnoreAll:
1813 skipline();
1814 /* fall through */
1815 case End:
1816 if (!fMulti) {
1817 int save_flags;
1818 int implicit_splay;
1819 /* Compass ignore flag is 'X' */
1820 if ((compass_dat_flags & BIT('X' - 'A'))) {
1821 process_eol();
1822 return;
1824 if (fRev) {
1825 prefix *t = fr;
1826 fr = to;
1827 to = t;
1829 if (fTopofil) {
1830 VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1831 LOC(Tape) = LOC(ToCount);
1833 /* Note: frdepth == todepth test works regardless of fDepthChange
1834 * (frdepth always zero, todepth is change of depth) and also
1835 * works for STYLE_NORMAL (both remain 0) */
1836 if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1837 (VAL(Tape) == (real)0.0 || VAL(Tape) == HUGE_REAL) &&
1838 (VAL(BackTape) == (real)0.0 || VAL(BackTape) == HUGE_REAL) &&
1839 VAL(FrDepth) == VAL(ToDepth)) {
1840 process_equate(fr, to);
1841 process_eol();
1842 return;
1844 if (fTopofil) {
1845 VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1846 } else if (VAL(Tape) != HUGE_REAL) {
1847 VAL(Tape) *= pcs->units[Q_LENGTH];
1848 VAL(Tape) -= pcs->z[Q_LENGTH];
1849 VAL(Tape) *= pcs->sc[Q_LENGTH];
1851 if (VAL(BackTape) != HUGE_REAL) {
1852 VAL(BackTape) *= pcs->units[Q_BACKLENGTH];
1853 VAL(BackTape) -= pcs->z[Q_BACKLENGTH];
1854 VAL(BackTape) *= pcs->sc[Q_BACKLENGTH];
1855 if (VAL(Tape) != HUGE_REAL) {
1856 real diff = VAL(Tape) - VAL(BackTape);
1857 if (sqrd(diff / 3.0) > VAR(Tape) + VAR(BackTape)) {
1858 /* fore and back readings differ by more than 3 sds */
1859 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1860 * by, e.g. "0.12m" or "0.2ft". */
1861 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1862 diff, get_length_units(Q_LENGTH));
1864 VAL(Tape) = VAL(Tape) / VAR(Tape) + VAL(BackTape) / VAR(BackTape);
1865 VAR(Tape) = (VAR(Tape) + VAR(BackTape)) / 4;
1866 VAL(Tape) *= VAR(Tape);
1867 } else {
1868 VAL(Tape) = VAL(BackTape);
1869 VAR(Tape) = VAR(BackTape);
1871 } else if (VAL(Tape) == HUGE_REAL) {
1872 compile_error_reading(Tape, /*Tape reading may not be omitted*/94);
1873 process_eol();
1874 return;
1876 implicit_splay = TSTBIT(pcs->flags, FLAGS_IMPLICIT_SPLAY);
1877 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1878 save_flags = pcs->flags;
1879 if (implicit_splay) {
1880 pcs->flags |= BIT(FLAGS_SPLAY);
1882 if ((compass_dat_flags & BIT('L' - 'A'))) {
1883 /* 'L' means "exclude from length" - map this to Survex's
1884 * FLAGS_DUPLICATE. */
1885 pcs->flags |= BIT(FLAGS_DUPLICATE);
1887 switch (pcs->style) {
1888 case STYLE_NORMAL:
1889 process_normal(fr, to, (first_stn == To) ^ fRev,
1890 ctype, backctype);
1891 break;
1892 case STYLE_DIVING:
1893 /* FIXME: Handle any clino readings */
1894 process_diving(fr, to, (first_stn == To) ^ fRev,
1895 fDepthChange);
1896 break;
1897 case STYLE_CYLPOLAR:
1898 process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1899 fDepthChange);
1900 break;
1901 default:
1902 BUG("bad style");
1904 pcs->flags = save_flags;
1906 process_eol();
1907 return;
1909 do {
1910 process_eol();
1911 skipblanks();
1912 } while (isComm(ch));
1913 goto again;
1914 default:
1915 BUG("Unknown reading in ordering");
1920 static int
1921 process_lrud(prefix *stn)
1923 SVX_ASSERT(next_lrud);
1924 lrud * xsect = osnew(lrud);
1925 xsect->stn = stn;
1926 xsect->l = (VAL(Left) * pcs->units[Q_LEFT] - pcs->z[Q_LEFT]) * pcs->sc[Q_LEFT];
1927 xsect->r = (VAL(Right) * pcs->units[Q_RIGHT] - pcs->z[Q_RIGHT]) * pcs->sc[Q_RIGHT];
1928 xsect->u = (VAL(Up) * pcs->units[Q_UP] - pcs->z[Q_UP]) * pcs->sc[Q_UP];
1929 xsect->d = (VAL(Down) * pcs->units[Q_DOWN] - pcs->z[Q_DOWN]) * pcs->sc[Q_DOWN];
1930 xsect->meta = pcs->meta;
1931 if (pcs->meta) ++pcs->meta->ref_count;
1932 xsect->next = NULL;
1933 *next_lrud = xsect;
1934 next_lrud = &(xsect->next);
1936 return 1;
1939 static void
1940 data_passage(void)
1942 prefix *stn = NULL;
1943 reading *ordering;
1945 for (ordering = pcs->ordering ; ; ordering++) {
1946 skipblanks();
1947 switch (*ordering) {
1948 case Station:
1949 stn = read_prefix(PFX_STATION);
1950 break;
1951 case Left: case Right: case Up: case Down: {
1952 reading r = *ordering;
1953 read_reading(r, fTrue);
1954 if (VAL(r) == HUGE_REAL) {
1955 if (!isOmit(ch)) {
1956 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1957 } else {
1958 nextch();
1960 VAL(r) = -1;
1962 break;
1964 case Ignore:
1965 skipword(); break;
1966 case IgnoreAll:
1967 skipline();
1968 /* fall through */
1969 case End: {
1970 process_lrud(stn);
1971 process_eol();
1972 return;
1974 default: BUG("Unknown reading in ordering");
1979 static int
1980 process_nosurvey(prefix *fr, prefix *to, bool fToFirst)
1982 nosurveylink *link;
1984 /* Suppress "unused fixed point" warnings for these stations */
1985 fr->sflags |= BIT(SFLAGS_USED);
1986 to->sflags |= BIT(SFLAGS_USED);
1988 /* add to linked list which is dealt with after network is solved */
1989 link = osnew(nosurveylink);
1990 if (fToFirst) {
1991 link->to = StnFromPfx(to);
1992 link->fr = StnFromPfx(fr);
1993 } else {
1994 link->fr = StnFromPfx(fr);
1995 link->to = StnFromPfx(to);
1997 link->flags = pcs->flags | (STYLE_NOSURVEY << FLAGS_STYLE_BIT0);
1998 link->meta = pcs->meta;
1999 if (pcs->meta) ++pcs->meta->ref_count;
2000 link->next = nosurveyhead;
2001 nosurveyhead = link;
2002 return 1;
2005 static void
2006 data_nosurvey(void)
2008 prefix *fr = NULL, *to = NULL;
2010 bool fMulti = fFalse;
2012 reading first_stn = End;
2014 reading *ordering;
2016 again:
2018 for (ordering = pcs->ordering ; ; ordering++) {
2019 skipblanks();
2020 switch (*ordering) {
2021 case Fr:
2022 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
2023 if (first_stn == End) first_stn = Fr;
2024 break;
2025 case To:
2026 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
2027 if (first_stn == End) first_stn = To;
2028 break;
2029 case Station:
2030 fr = to;
2031 to = read_prefix(PFX_STATION);
2032 first_stn = To;
2033 break;
2034 case Ignore:
2035 skipword(); break;
2036 case IgnoreAllAndNewLine:
2037 skipline();
2038 /* fall through */
2039 case Newline:
2040 if (fr != NULL) {
2041 if (!process_nosurvey(fr, to, first_stn == To))
2042 skipline();
2044 if (ordering[1] == End) {
2045 do {
2046 process_eol();
2047 skipblanks();
2048 } while (isComm(ch));
2049 if (!isData(ch)) {
2050 return;
2052 goto again;
2054 fMulti = fTrue;
2055 while (1) {
2056 process_eol();
2057 skipblanks();
2058 if (isData(ch)) break;
2059 if (!isComm(ch)) {
2060 return;
2063 break;
2064 case IgnoreAll:
2065 skipline();
2066 /* fall through */
2067 case End:
2068 if (!fMulti) {
2069 (void)process_nosurvey(fr, to, first_stn == To);
2070 process_eol();
2071 return;
2073 do {
2074 process_eol();
2075 skipblanks();
2076 } while (isComm(ch));
2077 goto again;
2078 default: BUG("Unknown reading in ordering");
2083 /* totally ignore a line of survey data */
2084 static void
2085 data_ignore(void)
2087 skipline();
2088 process_eol();