Put a space in front of the shown line
[survex.git] / src / datain.c
blob1accc7f068bfc6745a9edce06a0fd889a4e5e9d8
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 PUTC(' ', STDERR);
129 while (!feof(file.fh)) {
130 int c = GETC(file.fh);
131 if (isEol(c)) break;
132 PUTC(c, STDERR);
134 fputnl(STDERR);
136 /* If we have a location in the line for the error, indicate it. */
137 if (col) {
138 col -= width;
139 PUTC(' ', STDERR);
140 while (--col) PUTC(' ', STDERR);
141 PUTC('^', STDERR);
142 while (width > 1) {
143 PUTC('~', STDERR);
144 --width;
146 fputnl(STDERR);
149 /* Revert to where we were. */
150 if (fseek(file.fh, cur_pos, SEEK_SET) == -1)
151 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
154 static int caret_width = 0;
156 static void
157 compile_v_report(int severity, int en, va_list ap)
159 int col = 0;
160 error_list_parent_files();
161 if (en < 0) {
162 en = -en;
163 if (file.fh) col = ftell(file.fh) - file.lpos;
165 v_report(severity, file.filename, file.line, col, en, ap);
166 if (file.fh)
167 show_line(col, caret_width);
170 void
171 compile_error(int en, ...)
173 va_list ap;
174 va_start(ap, en);
175 compile_v_report(1, en, ap);
176 va_end(ap);
179 void
180 compile_error_skip(int en, ...)
182 va_list ap;
183 va_start(ap, en);
184 compile_v_report(1, en, ap);
185 va_end(ap);
186 skipline();
189 static void
190 compile_error_reading(reading r, int en, ...)
192 va_list ap;
193 int col = 0;
194 va_start(ap, en);
195 error_list_parent_files();
196 if (LOC(r) >= file.lpos) col = LOC(r) - file.lpos;
197 v_report(1, file.filename, file.line, col, en, ap);
198 va_end(ap);
201 static void
202 compile_error_reading_skip(reading r, int en, ...)
204 va_list ap;
205 int col = 0;
206 va_start(ap, en);
207 error_list_parent_files();
208 if (LOC(r) >= file.lpos) col = LOC(r) - file.lpos;
209 v_report(1, file.filename, file.line, col, en, ap);
210 va_end(ap);
211 skipline();
214 void
215 compile_error_at(const char * filename, unsigned line, int en, ...)
217 va_list ap;
218 va_start(ap, en);
219 v_report(1, filename, line, 0, en, ap);
220 va_end(ap);
223 void
224 compile_error_pfx(const prefix * pfx, int en, ...)
226 va_list ap;
227 va_start(ap, en);
228 v_report(1, pfx->filename, pfx->line, 0, en, ap);
229 va_end(ap);
232 void
233 compile_error_token(int en)
235 char *p = NULL;
236 int len = 0;
237 skipblanks();
238 while (!isBlank(ch) && !isEol(ch)) {
239 s_catchar(&p, &len, (char)ch);
240 nextch();
242 if (p) {
243 caret_width = strlen(p);
244 compile_error(en, p);
245 caret_width = 0;
246 osfree(p);
247 } else {
248 compile_error(en, "");
252 void
253 compile_warning(int en, ...)
255 va_list ap;
256 va_start(ap, en);
257 compile_v_report(0, en, ap);
258 va_end(ap);
261 void
262 compile_warning_at(const char * filename, unsigned line, int en, ...)
264 va_list ap;
265 va_start(ap, en);
266 v_report(0, filename, line, 0, en, ap);
267 va_end(ap);
270 void
271 compile_warning_pfx(const prefix * pfx, int en, ...)
273 va_list ap;
274 va_start(ap, en);
275 v_report(0, pfx->filename, pfx->line, 0, en, ap);
276 va_end(ap);
279 /* This function makes a note where to put output files */
280 static void
281 using_data_file(const char *fnm)
283 if (!fnm_output_base) {
284 /* was: fnm_output_base = base_from_fnm(fnm); */
285 fnm_output_base = baseleaf_from_fnm(fnm);
286 } else if (fnm_output_base_is_dir) {
287 /* --output pointed to directory so use the leaf basename in that dir */
288 char *lf, *p;
289 lf = baseleaf_from_fnm(fnm);
290 p = use_path(fnm_output_base, lf);
291 osfree(lf);
292 osfree(fnm_output_base);
293 fnm_output_base = p;
294 fnm_output_base_is_dir = 0;
298 static void
299 skipword(void)
301 while (!isBlank(ch) && !isEol(ch)) nextch();
304 extern void
305 skipblanks(void)
307 while (isBlank(ch)) nextch();
310 extern void
311 skipline(void)
313 while (!isEol(ch)) nextch();
316 static void
317 process_eol(void)
319 int eolchar;
321 skipblanks();
323 if (!isEol(ch)) {
324 if (!isComm(ch)) compile_error(-/*End of line not blank*/15);
325 skipline();
328 eolchar = ch;
329 file.line++;
330 /* skip any different eol characters so we get line counts correct on
331 * DOS text files and similar, but don't count several adjacent blank
332 * lines as one */
333 while (ch != EOF) {
334 nextch();
335 if (ch == eolchar || !isEol(ch)) {
336 break;
338 if (ch == '\n') eolchar = ch;
340 file.lpos = ftell(file.fh) - 1;
343 static bool
344 process_non_data_line(void)
346 skipblanks();
348 if (isData(ch)) return fFalse;
350 if (isKeywd(ch)) {
351 nextch();
352 handle_command();
355 process_eol();
357 return fTrue;
360 static void
361 read_reading(reading r, bool f_optional)
363 int n_readings;
364 q_quantity q;
365 switch (r) {
366 case Tape: q = Q_LENGTH; break;
367 case BackTape: q = Q_BACKLENGTH; break;
368 case Comp: q = Q_BEARING; break;
369 case BackComp: q = Q_BACKBEARING; break;
370 case Clino: q = Q_GRADIENT; break;
371 case BackClino: q = Q_BACKGRADIENT; break;
372 case FrDepth: case ToDepth: q = Q_DEPTH; break;
373 case Dx: q = Q_DX; break;
374 case Dy: q = Q_DY; break;
375 case Dz: q = Q_DZ; break;
376 case FrCount: case ToCount: q = Q_COUNT; break;
377 case Left: q = Q_LEFT; break;
378 case Right: q = Q_RIGHT; break;
379 case Up: q = Q_UP; break;
380 case Down: q = Q_DOWN; break;
381 default:
382 q = Q_NULL; /* Suppress compiler warning */;
383 BUG("Unexpected case");
385 LOC(r) = ftell(file.fh);
386 VAL(r) = read_numeric_multi(f_optional, &n_readings);
387 VAR(r) = var(q);
388 if (n_readings > 1) VAR(r) /= sqrt(n_readings);
391 static void
392 read_bearing_or_omit(reading r)
394 int n_readings;
395 q_quantity q = Q_NULL;
396 LOC(r) = ftell(file.fh);
397 VAL(r) = read_numeric_multi_or_omit(&n_readings);
398 switch (r) {
399 case Comp: q = Q_BEARING; break;
400 case BackComp: q = Q_BACKBEARING; break;
401 default:
402 q = Q_NULL; /* Suppress compiler warning */;
403 BUG("Unexpected case");
405 VAR(r) = var(q);
406 if (n_readings > 1) VAR(r) /= sqrt(n_readings);
409 /* For reading Compass MAK files which have a freeform syntax */
410 static void
411 nextch_handling_eol(void)
413 nextch();
414 while (ch != EOF && isEol(ch)) {
415 process_eol();
419 #define LITLEN(S) (sizeof(S"") - 1)
420 #define has_ext(F,L,E) ((L) > LITLEN(E) + 1 &&\
421 (F)[(L) - LITLEN(E) - 1] == FNM_SEP_EXT &&\
422 strcasecmp((F) + (L) - LITLEN(E), E) == 0)
423 extern void
424 data_file(const char *pth, const char *fnm)
426 int begin_lineno_store;
427 parse file_store;
428 volatile enum {FMT_SVX, FMT_DAT, FMT_MAK} fmt = FMT_SVX;
431 char *filename;
432 FILE *fh;
433 size_t len;
435 if (!pth) {
436 /* file specified on command line - don't do special translation */
437 fh = fopenWithPthAndExt(pth, fnm, EXT_SVX_DATA, "rb", &filename);
438 } else {
439 fh = fopen_portable(pth, fnm, EXT_SVX_DATA, "rb", &filename);
442 if (fh == NULL) {
443 compile_error(-/*Couldnā€™t open file ā€œ%sā€*/24, fnm);
444 return;
447 len = strlen(filename);
448 if (has_ext(filename, len, "dat")) {
449 fmt = FMT_DAT;
450 } else if (has_ext(filename, len, "mak")) {
451 fmt = FMT_MAK;
454 file_store = file;
455 if (file.fh) file.parent = &file_store;
456 file.fh = fh;
457 file.filename = filename;
458 file.line = 1;
459 file.lpos = 0;
460 file.reported_where = fFalse;
461 nextch();
464 using_data_file(file.filename);
466 begin_lineno_store = pcs->begin_lineno;
467 pcs->begin_lineno = 0;
469 if (fmt == FMT_DAT) {
470 short *t;
471 int i;
472 settings *pcsNew;
474 pcsNew = osnew(settings);
475 *pcsNew = *pcs; /* copy contents */
476 pcsNew->begin_lineno = 0;
477 pcsNew->next = pcs;
478 pcs = pcsNew;
479 default_units(pcs);
480 default_calib(pcs);
482 pcs->style = STYLE_NORMAL;
483 pcs->units[Q_LENGTH] = METRES_PER_FOOT;
484 t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
486 t[EOF] = SPECIAL_EOL;
487 memset(t, 0, sizeof(short) * 33);
488 for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
489 t[127] = 0;
490 for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
491 t['\t'] |= SPECIAL_BLANK;
492 t[' '] |= SPECIAL_BLANK;
493 t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
494 t['\n'] |= SPECIAL_EOL;
495 t['\r'] |= SPECIAL_EOL;
496 t['.'] |= SPECIAL_DECIMAL;
497 t['-'] |= SPECIAL_MINUS;
498 t['+'] |= SPECIAL_PLUS;
499 pcs->Translate = t;
500 pcs->Case = OFF;
501 pcs->Truncate = INT_MAX;
502 pcs->infer = BIT(INFER_EQUATES)|BIT(INFER_EXPORTS)|BIT(INFER_PLUMBS);
503 } else if (fmt == FMT_MAK) {
504 short *t;
505 int i;
506 settings *pcsNew;
508 pcsNew = osnew(settings);
509 *pcsNew = *pcs; /* copy contents */
510 pcsNew->begin_lineno = 0;
511 pcsNew->next = pcs;
512 pcs = pcsNew;
514 t = ((short*)osmalloc(ossizeof(short) * 257)) + 1;
516 t[EOF] = SPECIAL_EOL;
517 memset(t, 0, sizeof(short) * 33);
518 for (i = 33; i < 127; i++) t[i] = SPECIAL_NAMES;
519 t[127] = 0;
520 for (i = 128; i < 256; i++) t[i] = SPECIAL_NAMES;
521 t['['] = t[','] = t[';'] = 0;
522 t['\t'] |= SPECIAL_BLANK;
523 t[' '] |= SPECIAL_BLANK;
524 t['\032'] |= SPECIAL_EOL; /* Ctrl-Z, so olde DOS text files are handled ok */
525 t['\n'] |= SPECIAL_EOL;
526 t['\r'] |= SPECIAL_EOL;
527 t['.'] |= SPECIAL_DECIMAL;
528 t['-'] |= SPECIAL_MINUS;
529 t['+'] |= SPECIAL_PLUS;
530 pcs->Translate = t;
531 pcs->Case = OFF;
532 pcs->Truncate = INT_MAX;
535 #ifdef HAVE_SETJMP_H
536 /* errors in nested functions can longjmp here */
537 if (setjmp(file.jbSkipLine)) {
538 skipline();
539 process_eol();
541 #endif
543 if (fmt == FMT_DAT) {
544 while (!feof(file.fh) && !ferror(file.fh)) {
545 static reading compass_order[] = {
546 Fr, To, Tape, CompassDATComp, CompassDATClino,
547 CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
548 CompassDATFlags, IgnoreAll
550 static reading compass_order_backsights[] = {
551 Fr, To, Tape, CompassDATComp, CompassDATClino,
552 CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
553 CompassDATBackComp, CompassDATBackClino,
554 CompassDATFlags, IgnoreAll
556 /* <Cave name> */
557 skipline();
558 process_eol();
559 /* SURVEY NAME: <Short name> */
560 get_token();
561 get_token();
562 /* if (ch != ':') ... */
563 nextch();
564 get_token();
565 skipline();
566 process_eol();
567 /* SURVEY DATE: 7 10 79 COMMENT:<Long name> */
568 get_token();
569 get_token();
570 copy_on_write_meta(pcs);
571 if (ch == ':') {
572 int year, month, day;
574 nextch();
576 /* NB order is *month* *day* year */
577 month = read_uint();
578 day = read_uint();
579 year = read_uint();
580 /* Note: Larry says a 2 digit year is always 19XX */
581 if (year < 100) year += 1900;
583 pcs->meta->days1 = pcs->meta->days2 = days_since_1900(year, month, day);
584 } else {
585 pcs->meta->days1 = pcs->meta->days2 = -1;
587 pcs->declination = HUGE_REAL;
588 skipline();
589 process_eol();
590 /* SURVEY TEAM: */
591 get_token();
592 get_token();
593 skipline();
594 process_eol();
595 /* <Survey team> */
596 nextch();
597 skipline();
598 process_eol();
599 /* DECLINATION: 1.00 FORMAT: DDDDLUDRADLN CORRECTIONS: 2.00 3.00 4.00 */
600 get_token();
601 nextch(); /* : */
602 skipblanks();
603 pcs->z[Q_DECLINATION] = -read_numeric(fFalse);
604 pcs->z[Q_DECLINATION] *= pcs->units[Q_DECLINATION];
605 get_token();
606 pcs->ordering = compass_order;
607 if (strcmp(buffer, "FORMAT") == 0) {
608 nextch(); /* : */
609 get_token();
610 if (strlen(buffer) >= 12 && buffer[11] == 'B') {
611 /* We have backsights for compass and clino */
612 pcs->ordering = compass_order_backsights;
614 get_token();
616 if (strcmp(buffer, "CORRECTIONS") == 0) {
617 nextch(); /* : */
618 pcs->z[Q_BEARING] = -rad(read_numeric(fFalse));
619 pcs->z[Q_GRADIENT] = -rad(read_numeric(fFalse));
620 pcs->z[Q_LENGTH] = -read_numeric(fFalse);
621 } else {
622 pcs->z[Q_BEARING] = 0;
623 pcs->z[Q_GRADIENT] = 0;
624 pcs->z[Q_LENGTH] = 0;
626 skipline();
627 process_eol();
628 /* BLANK LINE */
629 skipline();
630 process_eol();
631 /* heading line */
632 skipline();
633 process_eol();
634 /* BLANK LINE */
635 skipline();
636 process_eol();
637 while (!feof(file.fh)) {
638 if (ch == '\x0c') {
639 nextch();
640 process_eol();
641 break;
643 data_normal();
645 clear_last_leg();
648 settings *pcsParent = pcs->next;
649 SVX_ASSERT(pcsParent);
650 pcs->ordering = NULL;
651 free_settings(pcs);
652 pcs = pcsParent;
654 } else if (fmt == FMT_MAK) {
655 nextch_handling_eol();
656 while (!feof(file.fh) && !ferror(file.fh)) {
657 if (ch == '#') {
658 /* include a file */
659 int ch_store;
660 char *dat_pth = path_from_fnm(file.filename);
661 char *dat_fnm = NULL;
662 int dat_fnm_len;
663 nextch_handling_eol();
664 while (ch != ',' && ch != ';' && ch != EOF) {
665 while (isEol(ch)) process_eol();
666 s_catchar(&dat_fnm, &dat_fnm_len, (char)ch);
667 nextch_handling_eol();
669 while (ch != ';' && ch != EOF) {
670 prefix *name;
671 nextch_handling_eol();
672 name = read_prefix(PFX_STATION|PFX_OPT);
673 if (name) {
674 skipblanks();
675 if (ch == '[') {
676 /* fixed pt */
677 node *stn;
678 real x, y, z;
679 name->sflags |= BIT(SFLAGS_FIXED);
680 nextch_handling_eol();
681 while (!isdigit(ch) && ch != '+' && ch != '-' &&
682 ch != '.' && ch != ']' && ch != EOF) {
683 nextch_handling_eol();
685 x = read_numeric(fFalse);
686 while (!isdigit(ch) && ch != '+' && ch != '-' &&
687 ch != '.' && ch != ']' && ch != EOF) {
688 nextch_handling_eol();
690 y = read_numeric(fFalse);
691 while (!isdigit(ch) && ch != '+' && ch != '-' &&
692 ch != '.' && ch != ']' && ch != EOF) {
693 nextch_handling_eol();
695 z = read_numeric(fFalse);
696 stn = StnFromPfx(name);
697 if (!fixed(stn)) {
698 POS(stn, 0) = x;
699 POS(stn, 1) = y;
700 POS(stn, 2) = z;
701 fix(stn);
702 } else {
703 if (x != POS(stn, 0) || y != POS(stn, 1) ||
704 z != POS(stn, 2)) {
705 compile_error(/*Station already fixed or equated to a fixed point*/46);
706 } else {
707 compile_warning(/*Station already fixed at the same coordinates*/55);
710 while (ch != ']' && ch != EOF) nextch_handling_eol();
711 if (ch == ']') {
712 nextch_handling_eol();
713 skipblanks();
715 } else {
716 /* FIXME: link station - ignore for now */
717 /* FIXME: perhaps issue warning? */
719 while (ch != ',' && ch != ';' && ch != EOF)
720 nextch_handling_eol();
723 if (dat_fnm) {
724 ch_store = ch;
725 data_file(dat_pth, dat_fnm);
726 ch = ch_store;
727 osfree(dat_fnm);
729 } else {
730 /* FIXME: also check for % and $ later */
731 nextch_handling_eol();
735 settings *pcsParent = pcs->next;
736 SVX_ASSERT(pcsParent);
737 free_settings(pcs);
738 pcs = pcsParent;
740 } else {
741 while (!feof(file.fh) && !ferror(file.fh)) {
742 if (!process_non_data_line()) {
743 f_export_ok = fFalse;
744 switch (pcs->style) {
745 case STYLE_NORMAL:
746 case STYLE_DIVING:
747 case STYLE_CYLPOLAR:
748 data_normal();
749 break;
750 case STYLE_CARTESIAN:
751 data_cartesian();
752 break;
753 case STYLE_PASSAGE:
754 data_passage();
755 break;
756 case STYLE_NOSURVEY:
757 data_nosurvey();
758 break;
759 case STYLE_IGNORE:
760 data_ignore();
761 break;
762 default:
763 BUG("bad style");
767 clear_last_leg();
770 /* don't allow *BEGIN at the end of a file, then *EXPORT in the
771 * including file */
772 f_export_ok = fFalse;
774 if (pcs->begin_lineno) {
775 error_in_file(file.filename, pcs->begin_lineno,
776 /*BEGIN with no matching END in this file*/23);
777 /* Implicitly close any unclosed BEGINs from this file */
778 do {
779 settings *pcsParent = pcs->next;
780 SVX_ASSERT(pcsParent);
781 free_settings(pcs);
782 pcs = pcsParent;
783 } while (pcs->begin_lineno);
786 pcs->begin_lineno = begin_lineno_store;
788 if (ferror(file.fh))
789 fatalerror_in_file(file.filename, 0, /*Error reading file*/18);
791 (void)fclose(file.fh);
793 file = file_store;
795 /* don't free this - it may be pointed to by prefix.file */
796 /* osfree(file.filename); */
799 static real
800 mod2pi(real a)
802 return a - floor(a / (2 * M_PI)) * (2 * M_PI);
805 static real
806 handle_plumb(clino_type *p_ctype)
808 typedef enum {
809 CLINO_NULL=-1, CLINO_UP, CLINO_DOWN, CLINO_LEVEL
810 } clino_tok;
811 static sztok clino_tab[] = {
812 {"D", CLINO_DOWN},
813 {"DOWN", CLINO_DOWN},
814 {"H", CLINO_LEVEL},
815 {"LEVEL", CLINO_LEVEL},
816 {"U", CLINO_UP},
817 {"UP", CLINO_UP},
818 {NULL, CLINO_NULL}
820 static real clinos[] = {(real)M_PI_2, (real)(-M_PI_2), (real)0.0};
821 clino_tok tok;
823 skipblanks();
824 if (isalpha(ch)) {
825 filepos fp;
826 get_pos(&fp);
827 get_token();
828 tok = match_tok(clino_tab, TABSIZE(clino_tab));
829 if (tok != CLINO_NULL) {
830 *p_ctype = (tok == CLINO_LEVEL ? CTYPE_HORIZ : CTYPE_PLUMB);
831 return clinos[tok];
833 set_pos(&fp);
834 } else if (isSign(ch)) {
835 int chOld = ch;
836 nextch();
837 if (toupper(ch) == 'V') {
838 nextch();
839 *p_ctype = CTYPE_PLUMB;
840 return (!isMinus(chOld) ? M_PI_2 : -M_PI_2);
843 if (isOmit(chOld)) {
844 *p_ctype = CTYPE_OMIT;
845 /* no clino reading, so assume 0 with large sd */
846 return (real)0.0;
848 } else if (isOmit(ch)) {
849 /* OMIT char may not be a SIGN char too so we need to check here as
850 * well as above... */
851 nextch();
852 *p_ctype = CTYPE_OMIT;
853 /* no clino reading, so assume 0 with large sd */
854 return (real)0.0;
856 return HUGE_REAL;
859 static void
860 warn_readings_differ(int msgno, real diff, int units)
862 char buf[64];
863 char *p;
864 diff /= get_units_factor(units);
865 sprintf(buf, "%.2f", fabs(diff));
866 for (p = buf; *p; ++p) {
867 if (*p == '.') {
868 char *z = p;
869 while (*++p) {
870 if (*p != '0') z = p + 1;
872 p = z;
873 break;
876 strcpy(p, get_units_string(units));
877 compile_warning(msgno, buf);
880 static bool
881 handle_comp_units(void)
883 bool fNoComp = fTrue;
884 if (VAL(Comp) != HUGE_REAL) {
885 fNoComp = fFalse;
886 VAL(Comp) *= pcs->units[Q_BEARING];
887 if (VAL(Comp) < (real)0.0 || VAL(Comp) - M_PI * 2.0 > EPSILON) {
888 /* TRANSLATORS: Suspicious means something like 410 degrees or -20
889 * degrees */
890 compile_warning(/*Suspicious compass reading*/59);
891 VAL(Comp) = mod2pi(VAL(Comp));
894 if (VAL(BackComp) != HUGE_REAL) {
895 fNoComp = fFalse;
896 VAL(BackComp) *= pcs->units[Q_BACKBEARING];
897 if (VAL(BackComp) < (real)0.0 || VAL(BackComp) - M_PI * 2.0 > EPSILON) {
898 /* FIXME: different message for BackComp? */
899 compile_warning(/*Suspicious compass reading*/59);
900 VAL(BackComp) = mod2pi(VAL(BackComp));
903 return fNoComp;
906 static real
907 handle_compass(real *p_var)
909 real compvar = VAR(Comp);
910 real comp = VAL(Comp);
911 real backcomp = VAL(BackComp);
912 real declination;
913 if (pcs->z[Q_DECLINATION] != HUGE_REAL) {
914 declination = -pcs->z[Q_DECLINATION];
915 } else if (pcs->declination != HUGE_REAL) {
916 /* Cached value calculated for a previous compass reading taken on the
917 * same date (by the 'else' just below).
919 declination = pcs->declination;
920 } else {
921 if (!pcs->meta || pcs->meta->days1 == -1) {
922 compile_warning(/*No survey date specified - using 0 for magnetic declination*/304);
923 declination = 0;
924 } else {
925 int avg_days = (pcs->meta->days1 + pcs->meta->days2) / 2;
926 double dat = julian_date_from_days_since_1900(avg_days);
927 /* thgeomag() takes (lat, lon, h, dat) - i.e. (y, x, z, date). */
928 declination = thgeomag(pcs->dec_y, pcs->dec_x, pcs->dec_z, dat);
930 declination -= pcs->convergence;
931 /* We cache the calculated declination as the calculation is relatively
932 * expensive. We also cache an "assumed 0" answer so that we only
933 * warn once per such survey rather than for every line with a compass
934 * reading. */
935 pcs->declination = declination;
937 if (comp != HUGE_REAL) {
938 comp = (comp - pcs->z[Q_BEARING]) * pcs->sc[Q_BEARING];
939 comp += declination;
941 if (backcomp != HUGE_REAL) {
942 backcomp = (backcomp - pcs->z[Q_BACKBEARING])
943 * pcs->sc[Q_BACKBEARING];
944 backcomp += declination;
945 backcomp -= M_PI;
946 if (comp != HUGE_REAL) {
947 real diff = comp - backcomp;
948 real adj = fabs(diff) > M_PI ? M_PI : 0;
949 diff -= floor((diff + M_PI) / (2 * M_PI)) * 2 * M_PI;
950 if (sqrd(diff / 3.0) > compvar + VAR(BackComp)) {
951 /* fore and back readings differ by more than 3 sds */
952 /* TRANSLATORS: %s is replaced by the amount the readings disagree
953 * by, e.g. "2.5Ā°" or "3įµ". */
954 warn_readings_differ(/*COMPASS reading and BACKCOMPASS reading disagree by %s*/98,
955 diff, get_angle_units(Q_BEARING));
957 comp = (comp / compvar + backcomp / VAR(BackComp));
958 compvar = (compvar + VAR(BackComp)) / 4;
959 comp *= compvar;
960 comp += adj;
961 } else {
962 comp = backcomp;
963 compvar = VAR(BackComp);
966 *p_var = compvar;
967 return comp;
970 static int
971 process_normal(prefix *fr, prefix *to, bool fToFirst,
972 clino_type ctype, clino_type backctype)
974 real tape = VAL(Tape);
975 real clin = VAL(Clino);
976 real backclin = VAL(BackClino);
978 real dx, dy, dz;
979 real vx, vy, vz;
980 #ifndef NO_COVARIANCES
981 real cxy, cyz, czx;
982 #endif
984 bool fNoComp;
986 /* adjusted tape is negative -- probably the calibration is wrong */
987 if (tape < (real)0.0) {
988 /* TRANSLATE different message for topofil? */
989 compile_warning(/*Negative adjusted tape reading*/79);
992 fNoComp = handle_comp_units();
994 if (ctype == CTYPE_READING) {
995 bool range_0_180;
996 real z;
997 real diff_from_abs90;
998 clin *= pcs->units[Q_GRADIENT];
999 /* percentage scale */
1000 if (pcs->f_clino_percent) clin = atan(clin);
1001 /* We want to warn if there's a reading which it would be impossible
1002 * to have read from the instrument (e.g. on a -90 to 90 degree scale
1003 * you can't read "96" (it's probably a typo for "69"). However, the
1004 * gradient reading from a topofil is typically in the range 0 to 180,
1005 * with 90 being horizontal.
1007 * Really we should allow the valid range to be specified, but for now
1008 * we infer it from the zero error - if this is within 45 degrees of
1009 * 90 then we assume the range is 0 to 180.
1011 z = pcs->z[Q_GRADIENT];
1012 range_0_180 = (z > M_PI_4 && z < 3*M_PI_4);
1013 diff_from_abs90 = fabs(clin) - M_PI_2;
1014 if (diff_from_abs90 > EPSILON) {
1015 if (!range_0_180) {
1016 int clino_units = get_angle_units(Q_GRADIENT);
1017 const char * units = get_units_string(clino_units);
1018 real right_angle = M_PI_2 / get_units_factor(clino_units);
1019 /* TRANSLATORS: %.f%s will be replaced with a right angle in the
1020 * units currently in use, e.g. "90Ā°" or "100įµ". And "absolute
1021 * value" means the reading ignoring the sign (so it might be
1022 * < -90Ā° or > 90Ā°. */
1023 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1024 right_angle, units);
1026 } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
1027 diff_from_abs90 >= -EPSILON) {
1028 ctype = CTYPE_INFERPLUMB;
1030 if (range_0_180 && ctype != CTYPE_INFERPLUMB) {
1031 /* FIXME: Warning message not ideal... */
1032 if (clin < 0.0 || clin - M_PI > EPSILON) {
1033 int clino_units = get_angle_units(Q_GRADIENT);
1034 const char * units = get_units_string(clino_units);
1035 real right_angle = M_PI_2 / get_units_factor(clino_units);
1036 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1037 right_angle, units);
1042 if (backctype == CTYPE_READING) {
1043 backclin *= pcs->units[Q_BACKGRADIENT];
1044 /* percentage scale */
1045 if (pcs->f_backclino_percent) backclin = atan(backclin);
1046 /* FIXME: Add range_0_180 handling here too */
1047 if (ctype != CTYPE_READING) {
1048 real diff_from_abs90 = fabs(backclin) - M_PI_2;
1049 if (diff_from_abs90 > EPSILON) {
1050 /* FIXME: different message for BackClino? */
1051 int clino_units = get_angle_units(Q_BACKGRADIENT);
1052 const char * units = get_units_string(clino_units);
1053 real right_angle = M_PI_2 / get_units_factor(clino_units);
1054 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1055 right_angle, units);
1056 } else if (TSTBIT(pcs->infer, INFER_PLUMBS) &&
1057 diff_from_abs90 >= -EPSILON) {
1058 backctype = CTYPE_INFERPLUMB;
1063 /* un-infer the plumb if the backsight was just a reading */
1064 if (ctype == CTYPE_INFERPLUMB && backctype == CTYPE_READING) {
1065 ctype = CTYPE_READING;
1068 if (ctype != CTYPE_OMIT && backctype != CTYPE_OMIT && ctype != backctype) {
1069 /* TRANSLATORS: In data with backsights, the user has tried to give a
1070 * plumb for the foresight and a clino reading for the backsight, or
1071 * something similar. */
1072 compile_error_reading_skip(Clino, /*CLINO and BACKCLINO readings must be of the same type*/84);
1073 return 0;
1076 if (ctype == CTYPE_PLUMB || ctype == CTYPE_INFERPLUMB ||
1077 backctype == CTYPE_PLUMB || backctype == CTYPE_INFERPLUMB) {
1078 /* plumbed */
1079 if (!fNoComp) {
1080 if (ctype == CTYPE_PLUMB ||
1081 (ctype == CTYPE_INFERPLUMB && VAL(Comp) != 0.0) ||
1082 backctype == CTYPE_PLUMB ||
1083 (backctype == CTYPE_INFERPLUMB && VAL(BackComp) != 0.0)) {
1084 /* FIXME: Different message for BackComp? */
1085 /* TRANSLATORS: A "plumbed leg" is one measured using a plumbline
1086 * (a weight on a string). So the problem here is that the leg is
1087 * vertical, so a compass reading has no meaning! */
1088 compile_warning(/*Compass reading given on plumbed leg*/21);
1092 dx = dy = (real)0.0;
1093 if (ctype != CTYPE_OMIT) {
1094 if (backctype != CTYPE_OMIT && (clin > 0) == (backclin > 0)) {
1095 /* TRANSLATORS: We've been told the foresight and backsight are
1096 * both "UP", or that they're both "DOWN". */
1097 compile_error_reading_skip(Clino, /*Plumbed CLINO and BACKCLINO readings can't be in the same direction*/92);
1098 return 0;
1100 dz = (clin > (real)0.0) ? tape : -tape;
1101 } else {
1102 dz = (backclin < (real)0.0) ? tape : -tape;
1104 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1105 vz = var(Q_POS) / 3.0 + VAR(Tape);
1106 #ifndef NO_COVARIANCES
1107 /* Correct values - no covariances in this case! */
1108 cxy = cyz = czx = (real)0.0;
1109 #endif
1110 } else {
1111 /* Each of ctype and backctype are either CTYPE_READING/CTYPE_HORIZ
1112 * or CTYPE_OMIT */
1113 /* clino */
1114 real L2, cosG, LcosG, cosG2, sinB, cosB, dx2, dy2, dz2, v, V;
1115 if (fNoComp) {
1116 /* TRANSLATORS: Here "legs" are survey legs, i.e. measurements between
1117 * survey stations. */
1118 compile_error_reading_skip(Comp, /*Compass reading may not be omitted except on plumbed legs*/14);
1119 return 0;
1121 if (tape == (real)0.0) {
1122 dx = dy = dz = (real)0.0;
1123 vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1124 #ifndef NO_COVARIANCES
1125 cxy = cyz = czx = (real)0.0;
1126 #endif
1127 #if DEBUG_DATAIN_1
1128 printf("Zero length leg: vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1129 #endif
1130 } else {
1131 real sinGcosG;
1132 /* take into account variance in LEVEL case */
1133 real var_clin = var(Q_LEVEL);
1134 real var_comp;
1135 real comp = handle_compass(&var_comp);
1136 /* ctype != CTYPE_READING is LEVEL case */
1137 if (ctype == CTYPE_READING) {
1138 clin = (clin - pcs->z[Q_GRADIENT]) * pcs->sc[Q_GRADIENT];
1139 var_clin = VAR(Clino);
1141 if (backctype == CTYPE_READING) {
1142 backclin = (backclin - pcs->z[Q_BACKGRADIENT])
1143 * pcs->sc[Q_BACKGRADIENT];
1144 if (ctype == CTYPE_READING) {
1145 if (sqrd((clin + backclin) / 3.0) > var_clin + VAR(BackClino)) {
1146 /* fore and back readings differ by more than 3 sds */
1147 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1148 * by, e.g. "2.5Ā°" or "3įµ". */
1149 warn_readings_differ(/*CLINO reading and BACKCLINO reading disagree by %s*/99,
1150 clin + backclin, get_angle_units(Q_GRADIENT));
1152 clin = (clin / var_clin - backclin / VAR(BackClino));
1153 var_clin = (var_clin + VAR(BackClino)) / 4;
1154 clin *= var_clin;
1155 } else {
1156 clin = -backclin;
1157 var_clin = VAR(BackClino);
1161 #if DEBUG_DATAIN
1162 printf(" %4.2f %4.2f %4.2f\n", tape, comp, clin);
1163 #endif
1164 cosG = cos(clin);
1165 LcosG = tape * cosG;
1166 sinB = sin(comp);
1167 cosB = cos(comp);
1168 #if DEBUG_DATAIN_1
1169 printf("sinB = %f, cosG = %f, LcosG = %f\n", sinB, cosG, LcosG);
1170 #endif
1171 dx = LcosG * sinB;
1172 dy = LcosG * cosB;
1173 dz = tape * sin(clin);
1174 /* printf("%.2f\n",clin); */
1175 #if DEBUG_DATAIN_1
1176 printf("dx = %f\ndy = %f\ndz = %f\n", dx, dy, dz);
1177 #endif
1178 dx2 = dx * dx;
1179 L2 = tape * tape;
1180 V = VAR(Tape) / L2;
1181 dy2 = dy * dy;
1182 cosG2 = cosG * cosG;
1183 sinGcosG = sin(clin) * cosG;
1184 dz2 = dz * dz;
1185 v = dz2 * var_clin;
1186 #ifdef NO_COVARIANCES
1187 vx = (var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1188 (.5 + sinB * sinB * cosG2) * v);
1189 vy = (var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1190 (.5 + cosB * cosB * cosG2) * v);
1191 if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1192 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1193 vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1194 } else {
1195 vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1197 /* for Surveyor87 errors: vx=vy=vz=var(Q_POS)/3.0; */
1198 #else
1199 vx = var(Q_POS) / 3.0 + dx2 * V + dy2 * var_comp +
1200 (sinB * sinB * v);
1201 vy = var(Q_POS) / 3.0 + dy2 * V + dx2 * var_comp +
1202 (cosB * cosB * v);
1203 if (ctype == CTYPE_OMIT && backctype == CTYPE_OMIT) {
1204 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1205 vz = var(Q_POS) / 3.0 + L2 * (real)0.1;
1206 } else {
1207 vz = var(Q_POS) / 3.0 + dz2 * V + L2 * cosG2 * var_clin;
1209 /* usual covariance formulae are fine in no clino case since
1210 * dz = 0 so value of var_clin is ignored */
1211 cxy = sinB * cosB * (VAR(Tape) * cosG2 + var_clin * dz2)
1212 - var_comp * dx * dy;
1213 czx = VAR(Tape) * sinB * sinGcosG - var_clin * dx * dz;
1214 cyz = VAR(Tape) * cosB * sinGcosG - var_clin * dy * dz;
1215 #if 0
1216 printf("vx = %6.3f, vy = %6.3f, vz = %6.3f\n", vx, vy, vz);
1217 printf("cxy = %6.3f, cyz = %6.3f, czx = %6.3f\n", cxy, cyz, czx);
1218 #endif
1219 #endif
1220 #if DEBUG_DATAIN_1
1221 printf("In DATAIN.C, vx = %f, vy = %f, vz = %f\n", vx, vy, vz);
1222 #endif
1225 #if DEBUG_DATAIN_1
1226 printf("Just before addleg, vx = %f\n", vx);
1227 #endif
1228 /*printf("dx,dy,dz = %.2f %.2f %.2f\n\n", dx, dy, dz);*/
1229 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1230 #ifndef NO_COVARIANCES
1231 , cyz, czx, cxy
1232 #endif
1234 return 1;
1237 static int
1238 process_diving(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1240 real tape = VAL(Tape);
1242 real dx, dy, dz;
1243 real vx, vy, vz;
1244 #ifndef NO_COVARIANCES
1245 real cxy = 0, cyz = 0, czx = 0;
1246 #endif
1248 handle_comp_units();
1250 /* depth gauge readings increase upwards with default calibration */
1251 if (fDepthChange) {
1252 SVX_ASSERT(VAL(FrDepth) == 0.0);
1253 dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1254 dz *= pcs->sc[Q_DEPTH];
1255 } else {
1256 dz = VAL(ToDepth) - VAL(FrDepth);
1257 dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1260 /* adjusted tape is negative -- probably the calibration is wrong */
1261 if (tape < (real)0.0) {
1262 compile_warning(/*Negative adjusted tape reading*/79);
1265 /* check if tape is less than depth change */
1266 if (tape < fabs(dz)) {
1267 /* FIXME: allow margin of error based on variances? */
1268 /* TRANSLATORS: This means that the data fed in said this.
1270 * It could be a gross error (e.g. the decimal point is missing from the
1271 * depth gauge reading) or it could just be due to random error on a near
1272 * vertical leg */
1273 compile_warning(/*Tape reading is less than change in depth*/62);
1276 if (tape == (real)0.0 && dz == 0.0) {
1277 dx = dy = dz = (real)0.0;
1278 vx = vy = vz = (real)(var(Q_POS) / 3.0); /* Position error only */
1279 } else if (VAL(Comp) == HUGE_REAL &&
1280 VAL(BackComp) == HUGE_REAL) {
1281 /* plumb */
1282 dx = dy = (real)0.0;
1283 if (dz < 0) tape = -tape;
1284 /* FIXME: Should use FrDepth sometimes... */
1285 dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth))
1286 / (VAR(Tape) * 2 * VAR(ToDepth));
1287 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1288 /* FIXME: Should use FrDepth sometimes... */
1289 vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth)
1290 / (VAR(Tape) + VAR(ToDepth));
1291 } else {
1292 real L2, sinB, cosB, dz2, D2;
1293 real var_comp;
1294 real comp = handle_compass(&var_comp);
1295 sinB = sin(comp);
1296 cosB = cos(comp);
1297 L2 = tape * tape;
1298 dz2 = dz * dz;
1299 D2 = L2 - dz2;
1300 if (D2 <= (real)0.0) {
1301 /* FIXME: Should use FrDepth sometimes... */
1302 real vsum = VAR(Tape) + 2 * VAR(ToDepth);
1303 dx = dy = (real)0.0;
1304 vx = vy = var(Q_POS) / 3.0;
1305 /* FIXME: Should use FrDepth sometimes... */
1306 vz = var(Q_POS) / 3.0 + VAR(Tape) * 2 * VAR(ToDepth) / vsum;
1307 if (dz > 0) {
1308 /* FIXME: Should use FrDepth sometimes... */
1309 dz = (dz * VAR(Tape) + tape * 2 * VAR(ToDepth)) / vsum;
1310 } else {
1311 dz = (dz * VAR(Tape) - tape * 2 * VAR(ToDepth)) / vsum;
1313 } else {
1314 real D = sqrt(D2);
1315 /* FIXME: Should use FrDepth sometimes... */
1316 real F = VAR(Tape) * L2 + 2 * VAR(ToDepth) * D2;
1317 dx = D * sinB;
1318 dy = D * cosB;
1320 vx = var(Q_POS) / 3.0 +
1321 sinB * sinB * F / D2 + var_comp * dy * dy;
1322 vy = var(Q_POS) / 3.0 +
1323 cosB * cosB * F / D2 + var_comp * dx * dx;
1324 /* FIXME: Should use FrDepth sometimes... */
1325 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1327 #ifndef NO_COVARIANCES
1328 cxy = sinB * cosB * (F / D2 + var_comp * D2);
1329 /* FIXME: Should use FrDepth sometimes... */
1330 cyz = -2 * VAR(ToDepth) * dy / D;
1331 czx = -2 * VAR(ToDepth) * dx / D;
1332 #endif
1334 /* FIXME: If there's a clino reading, check it against the depth reading,
1335 * and average.
1336 * if (VAL(Clino) != HUGE_REAL || VAL(BackClino) != HUGE_REAL) { ... }
1339 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1340 #ifndef NO_COVARIANCES
1341 , cxy, cyz, czx
1342 #endif
1344 return 1;
1347 static int
1348 process_cartesian(prefix *fr, prefix *to, bool fToFirst)
1350 real dx = (VAL(Dx) * pcs->units[Q_DX] - pcs->z[Q_DX]) * pcs->sc[Q_DX];
1351 real dy = (VAL(Dy) * pcs->units[Q_DY] - pcs->z[Q_DY]) * pcs->sc[Q_DY];
1352 real dz = (VAL(Dz) * pcs->units[Q_DZ] - pcs->z[Q_DZ]) * pcs->sc[Q_DZ];
1354 addlegbyname(fr, to, fToFirst, dx, dy, dz, VAR(Dx), VAR(Dy), VAR(Dz)
1355 #ifndef NO_COVARIANCES
1356 , 0, 0, 0
1357 #endif
1359 return 1;
1362 static void
1363 data_cartesian(void)
1365 prefix *fr = NULL, *to = NULL;
1367 bool fMulti = fFalse;
1369 reading first_stn = End;
1371 reading *ordering;
1373 again:
1375 for (ordering = pcs->ordering ; ; ordering++) {
1376 skipblanks();
1377 switch (*ordering) {
1378 case Fr:
1379 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
1380 if (first_stn == End) first_stn = Fr;
1381 break;
1382 case To:
1383 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
1384 if (first_stn == End) first_stn = To;
1385 break;
1386 case Station:
1387 fr = to;
1388 to = read_prefix(PFX_STATION);
1389 first_stn = To;
1390 break;
1391 case Dx: case Dy: case Dz:
1392 read_reading(*ordering, fFalse);
1393 break;
1394 case Ignore:
1395 skipword(); break;
1396 case IgnoreAllAndNewLine:
1397 skipline();
1398 /* fall through */
1399 case Newline:
1400 if (fr != NULL) {
1401 if (!process_cartesian(fr, to, first_stn == To))
1402 skipline();
1404 fMulti = fTrue;
1405 while (1) {
1406 process_eol();
1407 skipblanks();
1408 if (isData(ch)) break;
1409 if (!isComm(ch)) {
1410 return;
1413 break;
1414 case IgnoreAll:
1415 skipline();
1416 /* fall through */
1417 case End:
1418 if (!fMulti) {
1419 process_cartesian(fr, to, first_stn == To);
1420 process_eol();
1421 return;
1423 do {
1424 process_eol();
1425 skipblanks();
1426 } while (isComm(ch));
1427 goto again;
1428 default: BUG("Unknown reading in ordering");
1433 static int
1434 process_cylpolar(prefix *fr, prefix *to, bool fToFirst, bool fDepthChange)
1436 real tape = VAL(Tape);
1438 real dx, dy, dz;
1439 real vx, vy, vz;
1440 #ifndef NO_COVARIANCES
1441 real cxy = 0;
1442 #endif
1444 handle_comp_units();
1446 /* depth gauge readings increase upwards with default calibration */
1447 if (fDepthChange) {
1448 SVX_ASSERT(VAL(FrDepth) == 0.0);
1449 dz = VAL(ToDepth) * pcs->units[Q_DEPTH] - pcs->z[Q_DEPTH];
1450 dz *= pcs->sc[Q_DEPTH];
1451 } else {
1452 dz = VAL(ToDepth) - VAL(FrDepth);
1453 dz *= pcs->units[Q_DEPTH] * pcs->sc[Q_DEPTH];
1456 /* adjusted tape is negative -- probably the calibration is wrong */
1457 if (tape < (real)0.0) {
1458 compile_warning(/*Negative adjusted tape reading*/79);
1461 if (VAL(Comp) == HUGE_REAL && VAL(BackComp) == HUGE_REAL) {
1462 /* plumb */
1463 dx = dy = (real)0.0;
1464 vx = vy = var(Q_POS) / 3.0 + dz * dz * var(Q_PLUMB);
1465 /* FIXME: Should use FrDepth sometimes... */
1466 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1467 } else {
1468 real sinB, cosB;
1469 real var_comp;
1470 real comp = handle_compass(&var_comp);
1471 sinB = sin(comp);
1472 cosB = cos(comp);
1474 dx = tape * sinB;
1475 dy = tape * cosB;
1477 vx = var(Q_POS) / 3.0 +
1478 VAR(Tape) * sinB * sinB + var_comp * dy * dy;
1479 vy = var(Q_POS) / 3.0 +
1480 VAR(Tape) * cosB * cosB + var_comp * dx * dx;
1481 /* FIXME: Should use FrDepth sometimes... */
1482 vz = var(Q_POS) / 3.0 + 2 * VAR(ToDepth);
1484 #ifndef NO_COVARIANCES
1485 cxy = (VAR(Tape) - var_comp * tape * tape) * sinB * cosB;
1486 #endif
1488 addlegbyname(fr, to, fToFirst, dx, dy, dz, vx, vy, vz
1489 #ifndef NO_COVARIANCES
1490 , cxy, 0, 0
1491 #endif
1493 return 1;
1496 /* Process tape/compass/clino, diving, and cylpolar styles of survey data
1497 * Also handles topofil (fromcount/tocount or count) in place of tape */
1498 static void
1499 data_normal(void)
1501 prefix *fr = NULL, *to = NULL;
1502 reading first_stn = End;
1504 bool fTopofil = fFalse, fMulti = fFalse;
1505 bool fRev;
1506 clino_type ctype, backctype;
1507 bool fDepthChange;
1508 unsigned long compass_dat_flags = 0;
1510 reading *ordering;
1512 VAL(Tape) = VAL(BackTape) = HUGE_REAL;
1513 VAL(Comp) = VAL(BackComp) = HUGE_REAL;
1514 VAL(FrCount) = VAL(ToCount) = 0;
1515 VAL(FrDepth) = VAL(ToDepth) = 0;
1516 VAL(Left) = VAL(Right) = VAL(Up) = VAL(Down) = HUGE_REAL;
1518 fRev = fFalse;
1519 ctype = backctype = CTYPE_OMIT;
1520 fDepthChange = fFalse;
1522 /* ordering may omit clino reading, so set up default here */
1523 /* this is also used if clino reading is the omit character */
1524 VAL(Clino) = VAL(BackClino) = 0;
1526 again:
1528 /* We clear these flags in the normal course of events, but if there's an
1529 * error in a reading, we might not, so make sure it has been cleared here.
1531 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1532 for (ordering = pcs->ordering; ; ordering++) {
1533 skipblanks();
1534 switch (*ordering) {
1535 case Fr:
1536 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT|PFX_ANON);
1537 if (first_stn == End) first_stn = Fr;
1538 break;
1539 case To:
1540 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT|PFX_ANON);
1541 if (first_stn == End) first_stn = To;
1542 break;
1543 case Station:
1544 fr = to;
1545 to = read_prefix(PFX_STATION);
1546 first_stn = To;
1547 break;
1548 case Dir: {
1549 typedef enum {
1550 DIR_NULL=-1, DIR_FORE, DIR_BACK
1551 } dir_tok;
1552 static sztok dir_tab[] = {
1553 {"B", DIR_BACK},
1554 {"F", DIR_FORE},
1556 dir_tok tok;
1557 get_token();
1558 tok = match_tok(dir_tab, TABSIZE(dir_tab));
1559 switch (tok) {
1560 case DIR_FORE:
1561 break;
1562 case DIR_BACK:
1563 fRev = fTrue;
1564 break;
1565 default:
1566 file.lpos += strlen(buffer);
1567 compile_error_skip(-/*Found ā€œ%sā€, expecting ā€œFā€ or ā€œBā€*/131,
1568 buffer);
1569 process_eol();
1570 return;
1572 break;
1574 case Tape: case BackTape: {
1575 reading r = *ordering;
1576 read_reading(r, fTrue);
1577 if (VAL(r) == HUGE_REAL) {
1578 if (!isOmit(ch)) {
1579 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1580 /* Avoid also warning about omitted tape reading. */
1581 VAL(r) = 0;
1582 } else {
1583 nextch();
1585 } else if (VAL(r) < (real)0.0) {
1586 compile_warning(-/*Negative tape reading*/60);
1588 break;
1590 case Count:
1591 VAL(FrCount) = VAL(ToCount);
1592 LOC(FrCount) = LOC(ToCount);
1593 read_reading(ToCount, fFalse);
1594 fTopofil = fTrue;
1595 break;
1596 case FrCount:
1597 read_reading(FrCount, fFalse);
1598 break;
1599 case ToCount:
1600 read_reading(ToCount, fFalse);
1601 fTopofil = fTrue;
1602 break;
1603 case Comp: case BackComp:
1604 read_bearing_or_omit(*ordering);
1605 break;
1606 case Clino: case BackClino: {
1607 reading r = *ordering;
1608 clino_type * p_ctype = (r == Clino ? &ctype : &backctype);
1609 read_reading(r, fTrue);
1610 if (VAL(r) == HUGE_REAL) {
1611 VAL(r) = handle_plumb(p_ctype);
1612 if (VAL(r) != HUGE_REAL) break;
1613 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1614 skipline();
1615 process_eol();
1616 return;
1618 *p_ctype = CTYPE_READING;
1619 break;
1621 case FrDepth: case ToDepth:
1622 read_reading(*ordering, fFalse);
1623 break;
1624 case Depth:
1625 VAL(FrDepth) = VAL(ToDepth);
1626 LOC(FrDepth) = LOC(ToDepth);
1627 read_reading(ToDepth, fFalse);
1628 break;
1629 case DepthChange:
1630 fDepthChange = fTrue;
1631 VAL(FrDepth) = 0;
1632 read_reading(ToDepth, fFalse);
1633 break;
1634 case CompassDATComp:
1635 read_bearing_or_omit(Comp);
1636 if (is_compass_NaN(VAL(Comp))) VAL(Comp) = HUGE_REAL;
1637 break;
1638 case CompassDATBackComp:
1639 read_bearing_or_omit(BackComp);
1640 if (is_compass_NaN(VAL(BackComp))) VAL(BackComp) = HUGE_REAL;
1641 break;
1642 case CompassDATClino: case CompassDATBackClino: {
1643 reading r;
1644 clino_type * p_ctype;
1645 if (*ordering == CompassDATClino) {
1646 r = Clino;
1647 p_ctype = &ctype;
1648 } else {
1649 r = BackClino;
1650 p_ctype = &backctype;
1652 read_reading(r, fFalse);
1653 if (is_compass_NaN(VAL(r))) {
1654 VAL(r) = HUGE_REAL;
1655 *p_ctype = CTYPE_OMIT;
1656 } else {
1657 *p_ctype = CTYPE_READING;
1659 break;
1661 case CompassDATLeft: case CompassDATRight:
1662 case CompassDATUp: case CompassDATDown: {
1663 /* FIXME: need to actually make use of these entries! */
1664 reading actual = Left + (*ordering - CompassDATLeft);
1665 read_reading(actual, fFalse);
1666 if (VAL(actual) < 0) VAL(actual) = HUGE_REAL;
1667 break;
1669 case CompassDATFlags:
1670 if (ch == '#') {
1671 filepos fp;
1672 get_pos(&fp);
1673 nextch();
1674 if (ch == '|') {
1675 nextch();
1676 while (ch >= 'A' && ch <= 'Z') {
1677 compass_dat_flags |= BIT(ch - 'A');
1678 /* We currently understand:
1679 * L (exclude from length)
1680 * X (exclude data)
1681 * FIXME: but should also handle at least some of:
1682 * C (no adjustment) (set all (co)variances to 0?)
1683 * P (no plot) (new flag in 3d for "hidden by default"?)
1685 nextch();
1687 if (ch == '#') {
1688 nextch();
1689 } else {
1690 compass_dat_flags = 0;
1691 set_pos(&fp);
1693 } else {
1694 set_pos(&fp);
1697 break;
1698 case Ignore:
1699 skipword(); break;
1700 case IgnoreAllAndNewLine:
1701 skipline();
1702 /* fall through */
1703 case Newline:
1704 if (fr != NULL) {
1705 int r;
1706 int save_flags;
1707 int implicit_splay;
1708 if (fTopofil) {
1709 VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1710 LOC(Tape) = LOC(ToCount);
1712 /* Note: frdepth == todepth test works regardless of fDepthChange
1713 * (frdepth always zero, todepth is change of depth) and also
1714 * works for STYLE_NORMAL (both remain 0) */
1715 if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1716 (VAL(Tape) == (real)0.0 || VAL(Tape) == HUGE_REAL) &&
1717 (VAL(BackTape) == (real)0.0 || VAL(BackTape) == HUGE_REAL) &&
1718 VAL(FrDepth) == VAL(ToDepth)) {
1719 process_equate(fr, to);
1720 goto inferred_equate;
1722 if (fRev) {
1723 prefix *t = fr;
1724 fr = to;
1725 to = t;
1727 if (fTopofil) {
1728 VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1729 } else if (VAL(Tape) != HUGE_REAL) {
1730 VAL(Tape) *= pcs->units[Q_LENGTH];
1731 VAL(Tape) -= pcs->z[Q_LENGTH];
1732 VAL(Tape) *= pcs->sc[Q_LENGTH];
1734 if (VAL(BackTape) != HUGE_REAL) {
1735 VAL(BackTape) *= pcs->units[Q_BACKLENGTH];
1736 VAL(BackTape) -= pcs->z[Q_BACKLENGTH];
1737 VAL(BackTape) *= pcs->sc[Q_BACKLENGTH];
1738 if (VAL(Tape) != HUGE_REAL) {
1739 real diff = VAL(Tape) - VAL(BackTape);
1740 if (sqrd(diff / 3.0) > VAR(Tape) + VAR(BackTape)) {
1741 /* fore and back readings differ by more than 3 sds */
1742 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1743 * by, e.g. "0.12m" or "0.2ft". */
1744 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1745 diff, get_length_units(Q_LENGTH));
1747 VAL(Tape) = VAL(Tape) / VAR(Tape) + VAL(BackTape) / VAR(BackTape);
1748 VAR(Tape) = (VAR(Tape) + VAR(BackTape)) / 4;
1749 VAL(Tape) *= VAR(Tape);
1750 } else {
1751 VAL(Tape) = VAL(BackTape);
1752 VAR(Tape) = VAR(BackTape);
1754 } else if (VAL(Tape) == HUGE_REAL) {
1755 compile_error_reading(Tape, /*Tape reading may not be omitted*/94);
1756 goto inferred_equate;
1758 implicit_splay = TSTBIT(pcs->flags, FLAGS_IMPLICIT_SPLAY);
1759 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1760 save_flags = pcs->flags;
1761 if (implicit_splay) {
1762 pcs->flags |= BIT(FLAGS_SPLAY);
1764 switch (pcs->style) {
1765 case STYLE_NORMAL:
1766 r = process_normal(fr, to, (first_stn == To) ^ fRev,
1767 ctype, backctype);
1768 break;
1769 case STYLE_DIVING:
1770 /* FIXME: Handle any clino readings */
1771 r = process_diving(fr, to, (first_stn == To) ^ fRev,
1772 fDepthChange);
1773 break;
1774 case STYLE_CYLPOLAR:
1775 r = process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1776 fDepthChange);
1777 break;
1778 default:
1779 r = 0; /* avoid warning */
1780 BUG("bad style");
1782 pcs->flags = save_flags;
1783 if (!r) skipline();
1785 /* Swap fr and to back to how they were for next line */
1786 if (fRev) {
1787 prefix *t = fr;
1788 fr = to;
1789 to = t;
1793 fRev = fFalse;
1794 ctype = backctype = CTYPE_OMIT;
1795 fDepthChange = fFalse;
1797 /* ordering may omit clino reading, so set up default here */
1798 /* this is also used if clino reading is the omit character */
1799 VAL(Clino) = VAL(BackClino) = 0;
1800 LOC(Clino) = LOC(BackClino) = -1;
1802 inferred_equate:
1804 fMulti = fTrue;
1805 while (1) {
1806 process_eol();
1807 skipblanks();
1808 if (isData(ch)) break;
1809 if (!isComm(ch)) {
1810 return;
1813 break;
1814 case IgnoreAll:
1815 skipline();
1816 /* fall through */
1817 case End:
1818 if (!fMulti) {
1819 int save_flags;
1820 int implicit_splay;
1821 /* Compass ignore flag is 'X' */
1822 if ((compass_dat_flags & BIT('X' - 'A'))) {
1823 process_eol();
1824 return;
1826 if (fRev) {
1827 prefix *t = fr;
1828 fr = to;
1829 to = t;
1831 if (fTopofil) {
1832 VAL(Tape) = VAL(ToCount) - VAL(FrCount);
1833 LOC(Tape) = LOC(ToCount);
1835 /* Note: frdepth == todepth test works regardless of fDepthChange
1836 * (frdepth always zero, todepth is change of depth) and also
1837 * works for STYLE_NORMAL (both remain 0) */
1838 if (TSTBIT(pcs->infer, INFER_EQUATES) &&
1839 (VAL(Tape) == (real)0.0 || VAL(Tape) == HUGE_REAL) &&
1840 (VAL(BackTape) == (real)0.0 || VAL(BackTape) == HUGE_REAL) &&
1841 VAL(FrDepth) == VAL(ToDepth)) {
1842 process_equate(fr, to);
1843 process_eol();
1844 return;
1846 if (fTopofil) {
1847 VAL(Tape) *= pcs->units[Q_COUNT] * pcs->sc[Q_COUNT];
1848 } else if (VAL(Tape) != HUGE_REAL) {
1849 VAL(Tape) *= pcs->units[Q_LENGTH];
1850 VAL(Tape) -= pcs->z[Q_LENGTH];
1851 VAL(Tape) *= pcs->sc[Q_LENGTH];
1853 if (VAL(BackTape) != HUGE_REAL) {
1854 VAL(BackTape) *= pcs->units[Q_BACKLENGTH];
1855 VAL(BackTape) -= pcs->z[Q_BACKLENGTH];
1856 VAL(BackTape) *= pcs->sc[Q_BACKLENGTH];
1857 if (VAL(Tape) != HUGE_REAL) {
1858 real diff = VAL(Tape) - VAL(BackTape);
1859 if (sqrd(diff / 3.0) > VAR(Tape) + VAR(BackTape)) {
1860 /* fore and back readings differ by more than 3 sds */
1861 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1862 * by, e.g. "0.12m" or "0.2ft". */
1863 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1864 diff, get_length_units(Q_LENGTH));
1866 VAL(Tape) = VAL(Tape) / VAR(Tape) + VAL(BackTape) / VAR(BackTape);
1867 VAR(Tape) = (VAR(Tape) + VAR(BackTape)) / 4;
1868 VAL(Tape) *= VAR(Tape);
1869 } else {
1870 VAL(Tape) = VAL(BackTape);
1871 VAR(Tape) = VAR(BackTape);
1873 } else if (VAL(Tape) == HUGE_REAL) {
1874 compile_error_reading(Tape, /*Tape reading may not be omitted*/94);
1875 process_eol();
1876 return;
1878 implicit_splay = TSTBIT(pcs->flags, FLAGS_IMPLICIT_SPLAY);
1879 pcs->flags &= ~(BIT(FLAGS_ANON_ONE_END) | BIT(FLAGS_IMPLICIT_SPLAY));
1880 save_flags = pcs->flags;
1881 if (implicit_splay) {
1882 pcs->flags |= BIT(FLAGS_SPLAY);
1884 if ((compass_dat_flags & BIT('L' - 'A'))) {
1885 /* 'L' means "exclude from length" - map this to Survex's
1886 * FLAGS_DUPLICATE. */
1887 pcs->flags |= BIT(FLAGS_DUPLICATE);
1889 switch (pcs->style) {
1890 case STYLE_NORMAL:
1891 process_normal(fr, to, (first_stn == To) ^ fRev,
1892 ctype, backctype);
1893 break;
1894 case STYLE_DIVING:
1895 /* FIXME: Handle any clino readings */
1896 process_diving(fr, to, (first_stn == To) ^ fRev,
1897 fDepthChange);
1898 break;
1899 case STYLE_CYLPOLAR:
1900 process_cylpolar(fr, to, (first_stn == To) ^ fRev,
1901 fDepthChange);
1902 break;
1903 default:
1904 BUG("bad style");
1906 pcs->flags = save_flags;
1908 process_eol();
1909 return;
1911 do {
1912 process_eol();
1913 skipblanks();
1914 } while (isComm(ch));
1915 goto again;
1916 default:
1917 BUG("Unknown reading in ordering");
1922 static int
1923 process_lrud(prefix *stn)
1925 SVX_ASSERT(next_lrud);
1926 lrud * xsect = osnew(lrud);
1927 xsect->stn = stn;
1928 xsect->l = (VAL(Left) * pcs->units[Q_LEFT] - pcs->z[Q_LEFT]) * pcs->sc[Q_LEFT];
1929 xsect->r = (VAL(Right) * pcs->units[Q_RIGHT] - pcs->z[Q_RIGHT]) * pcs->sc[Q_RIGHT];
1930 xsect->u = (VAL(Up) * pcs->units[Q_UP] - pcs->z[Q_UP]) * pcs->sc[Q_UP];
1931 xsect->d = (VAL(Down) * pcs->units[Q_DOWN] - pcs->z[Q_DOWN]) * pcs->sc[Q_DOWN];
1932 xsect->meta = pcs->meta;
1933 if (pcs->meta) ++pcs->meta->ref_count;
1934 xsect->next = NULL;
1935 *next_lrud = xsect;
1936 next_lrud = &(xsect->next);
1938 return 1;
1941 static void
1942 data_passage(void)
1944 prefix *stn = NULL;
1945 reading *ordering;
1947 for (ordering = pcs->ordering ; ; ordering++) {
1948 skipblanks();
1949 switch (*ordering) {
1950 case Station:
1951 stn = read_prefix(PFX_STATION);
1952 break;
1953 case Left: case Right: case Up: case Down: {
1954 reading r = *ordering;
1955 read_reading(r, fTrue);
1956 if (VAL(r) == HUGE_REAL) {
1957 if (!isOmit(ch)) {
1958 compile_error_token(-/*Expecting numeric field, found ā€œ%sā€*/9);
1959 } else {
1960 nextch();
1962 VAL(r) = -1;
1964 break;
1966 case Ignore:
1967 skipword(); break;
1968 case IgnoreAll:
1969 skipline();
1970 /* fall through */
1971 case End: {
1972 process_lrud(stn);
1973 process_eol();
1974 return;
1976 default: BUG("Unknown reading in ordering");
1981 static int
1982 process_nosurvey(prefix *fr, prefix *to, bool fToFirst)
1984 nosurveylink *link;
1986 /* Suppress "unused fixed point" warnings for these stations */
1987 fr->sflags |= BIT(SFLAGS_USED);
1988 to->sflags |= BIT(SFLAGS_USED);
1990 /* add to linked list which is dealt with after network is solved */
1991 link = osnew(nosurveylink);
1992 if (fToFirst) {
1993 link->to = StnFromPfx(to);
1994 link->fr = StnFromPfx(fr);
1995 } else {
1996 link->fr = StnFromPfx(fr);
1997 link->to = StnFromPfx(to);
1999 link->flags = pcs->flags | (STYLE_NOSURVEY << FLAGS_STYLE_BIT0);
2000 link->meta = pcs->meta;
2001 if (pcs->meta) ++pcs->meta->ref_count;
2002 link->next = nosurveyhead;
2003 nosurveyhead = link;
2004 return 1;
2007 static void
2008 data_nosurvey(void)
2010 prefix *fr = NULL, *to = NULL;
2012 bool fMulti = fFalse;
2014 reading first_stn = End;
2016 reading *ordering;
2018 again:
2020 for (ordering = pcs->ordering ; ; ordering++) {
2021 skipblanks();
2022 switch (*ordering) {
2023 case Fr:
2024 fr = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
2025 if (first_stn == End) first_stn = Fr;
2026 break;
2027 case To:
2028 to = read_prefix(PFX_STATION|PFX_ALLOW_ROOT);
2029 if (first_stn == End) first_stn = To;
2030 break;
2031 case Station:
2032 fr = to;
2033 to = read_prefix(PFX_STATION);
2034 first_stn = To;
2035 break;
2036 case Ignore:
2037 skipword(); break;
2038 case IgnoreAllAndNewLine:
2039 skipline();
2040 /* fall through */
2041 case Newline:
2042 if (fr != NULL) {
2043 if (!process_nosurvey(fr, to, first_stn == To))
2044 skipline();
2046 if (ordering[1] == End) {
2047 do {
2048 process_eol();
2049 skipblanks();
2050 } while (isComm(ch));
2051 if (!isData(ch)) {
2052 return;
2054 goto again;
2056 fMulti = fTrue;
2057 while (1) {
2058 process_eol();
2059 skipblanks();
2060 if (isData(ch)) break;
2061 if (!isComm(ch)) {
2062 return;
2065 break;
2066 case IgnoreAll:
2067 skipline();
2068 /* fall through */
2069 case End:
2070 if (!fMulti) {
2071 (void)process_nosurvey(fr, to, first_stn == To);
2072 process_eol();
2073 return;
2075 do {
2076 process_eol();
2077 skipblanks();
2078 } while (isComm(ch));
2079 goto again;
2080 default: BUG("Unknown reading in ordering");
2085 /* totally ignore a line of survey data */
2086 static void
2087 data_ignore(void)
2089 skipline();
2090 process_eol();