extern CDECL int main(int argc, char **argv) { int d; time_t tmUserStart = time(NULL); clock_t tmCPUStart = clock(); { /* FIXME: localtime? */ struct tm * t = localtime(&tmUserStart); int y = t->tm_year + 1900; current_days_since_1900 = days_since_1900(y, t->tm_mon + 1, t->tm_mday); } /* Always buffer by line for aven's benefit. */ setvbuf(stdout, NULL, _IOLBF, 0); msg_init(argv); #if OS_WIN32 || OS_UNIX_MACOSX pj_set_finder(msg_proj_finder); #endif pcs = osnew(settings); pcs->next = NULL; pcs->Translate = ((short*) osmalloc(ossizeof(short) * 257)) + 1; pcs->meta = NULL; pcs->proj = NULL; pcs->declination = HUGE_REAL; pcs->convergence = 0.0; /* Set up root of prefix hierarchy */ root = osnew(prefix); root->up = root->right = root->down = NULL; root->stn = NULL; root->pos = NULL; root->ident = NULL; root->min_export = root->max_export = 0; root->sflags = BIT(SFLAGS_SURVEY); root->filename = NULL; nosurveyhead = NULL; stnlist = NULL; cLegs = cStns = cComponents = 0; totadj = total = totplan = totvert = 0.0; for (d = 0; d <= 2; d++) { min[d] = HUGE_REAL; max[d] = -HUGE_REAL; pfxHi[d] = pfxLo[d] = NULL; } /* at least one argument must be given */ cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, -1); while (1) { int opt = cmdline_getopt(); if (opt == EOF) break; switch (opt) { case 'p': /* Ignore for compatibility with older versions. */ break; case 'o': { osfree(fnm_output_base); /* in case of multiple -o options */ /* can be a directory (in which case use basename of leaf input) * or a file (in which case just trim the extension off) */ if (fDirectory(optarg)) { /* this is a little tricky - we need to note the path here, * and then add the leaf later on (in datain.c) */ fnm_output_base = base_from_fnm(optarg); fnm_output_base_is_dir = 1; } else { fnm_output_base = base_from_fnm(optarg); } break; } case 'q': if (fQuiet) fMute = 1; fQuiet = 1; break; case 's': fSuppress = 1; break; case 'v': { int v = atoi(optarg); if (v < IMG_VERSION_MIN || v > IMG_VERSION_MAX) fatalerror(/*3d file format versions %d to %d supported*/88, IMG_VERSION_MIN, IMG_VERSION_MAX); img_output_version = v; break; } case 'w': f_warnings_are_errors = 1; break; case 'z': { /* Control which network optimisations are used (development tool) */ static int first_opt_z = 1; char c; if (first_opt_z) { optimize = 0; first_opt_z = 0; } /* Lollipops, Parallel legs, Iterate mx, Delta* */ while ((c = *optarg++) != '\0') if (islower((unsigned char)c)) optimize |= BITA(c); break; case 1: fLog = fTrue; break; #if OS_WIN32 case 2: atexit(pause_on_exit); break; #endif } } } if (fLog) { char *fnm; if (!fnm_output_base) { char *p; p = baseleaf_from_fnm(argv[optind]); fnm = add_ext(p, EXT_LOG); osfree(p); } else if (fnm_output_base_is_dir) { char *p; fnm = baseleaf_from_fnm(argv[optind]); p = use_path(fnm_output_base, fnm); osfree(fnm); fnm = add_ext(p, EXT_LOG); osfree(p); } else { fnm = add_ext(fnm_output_base, EXT_LOG); } if (!freopen(fnm, "w", stdout)) fatalerror(/*Failed to open output file “%s”*/47, fnm); osfree(fnm); } if (!fMute) { const char *p = COPYRIGHT_MSG; puts(PRETTYPACKAGE" "VERSION); while (1) { const char *q = p; p = strstr(p, "(C)"); if (p == NULL) { puts(q); break; } fwrite(q, 1, p - q, stdout); fputs(msg(/*©*/0), stdout); p += 3; } } atexit(delete_output_on_error); /* end of options, now process data files */ while (argv[optind]) { const char *fnm = argv[optind]; if (!fExplicitTitle) { char *lf; lf = baseleaf_from_fnm(fnm); if (survey_title) s_catchar(&survey_title, &survey_title_len, ' '); s_cat(&survey_title, &survey_title_len, lf); osfree(lf); } /* Select defaults settings */ default_all(pcs); data_file(NULL, fnm); /* first argument is current path */ optind++; } validate(); solve_network(/*stnlist*/); /* Find coordinates of all points */ validate(); /* close .3d file */ if (!img_close(pimg)) { char *fnm = add_ext(fnm_output_base, EXT_SVX_3D); fatalerror(img_error2msg(img_error()), fnm); } if (fhErrStat) safe_fclose(fhErrStat); out_current_action(msg(/*Calculating statistics*/120)); if (!fMute) do_stats(); if (!fQuiet) { /* clock() typically wraps after 72 minutes, but there doesn't seem * to be a better way. Still 72 minutes means some cave! * We detect if clock() could have wrapped and suppress CPU time * printing in this case. */ double tmUser = difftime(time(NULL), tmUserStart); double tmCPU; clock_t now = clock(); #define CLOCK_T_WRAP \ (sizeof(clock_t)<sizeof(long)?(1ul << (CHAR_BIT * sizeof(clock_t))):0) tmCPU = (now - (unsigned long)tmCPUStart) / (double)CLOCKS_PER_SEC; if (now < tmCPUStart) tmCPU += CLOCK_T_WRAP / (double)CLOCKS_PER_SEC; if (tmUser >= tmCPU + CLOCK_T_WRAP / (double)CLOCKS_PER_SEC) tmCPU = 0; /* tmUser is integer, tmCPU not - equivalent to (ceil(tmCPU) >= tmUser) */ if (tmCPU + 1 > tmUser) { printf(msg(/*CPU time used %5.2fs*/140), tmCPU); } else if (tmCPU == 0) { if (tmUser != 0.0) { printf(msg(/*Time used %5.2fs*/141), tmUser); } else { fputs(msg(/*Time used unavailable*/142), stdout); } } else { printf(msg(/*Time used %5.2fs (%5.2fs CPU time)*/143), tmUser, tmCPU); } putnl(); } if (msg_warnings || msg_errors) { if (msg_errors || (f_warnings_are_errors && msg_warnings)) { printf(msg(/*There were %d warning(s) and %d error(s) - no output files produced.*/113), msg_warnings, msg_errors); putnl(); return EXIT_FAILURE; } printf(msg(/*There were %d warning(s).*/16), msg_warnings); putnl(); } return EXIT_SUCCESS; }
img * img_open_survey(const char *fnm, const char *survey) { img *pimg; size_t len; char buf[LITLEN(FILEID) + 9]; int ch; if (fDirectory(fnm)) { img_errno = IMG_DIRECTORY; return NULL; } pimg = (img *)xosmalloc(ossizeof(img)); if (pimg == NULL) { img_errno = IMG_OUTOFMEMORY; return NULL; } pimg->buf_len = 257; pimg->label_buf = xosmalloc(pimg->buf_len); if (!pimg->label_buf) { osfree(pimg); img_errno = IMG_OUTOFMEMORY; return NULL; } pimg->fh = fopenWithPthAndExt("", fnm, EXT_SVX_3D, "rb", &(pimg->filename_opened)); if (pimg->fh == NULL) { osfree(pimg->label_buf); osfree(pimg); img_errno = IMG_FILENOTFOUND; return NULL; } pimg->fRead = fTrue; /* reading from this file */ img_errno = IMG_NONE; pimg->flags = 0; /* for version >= 3 we use label_buf to store the prefix for reuse */ /* for VERSION_COMPASS_PLT, 0 value indicates we haven't * entered a survey yet */ /* for VERSION_CMAP_SHOT, we store the last station here * to detect whether we MOVE or LINE */ pimg->label_len = 0; pimg->label_buf[0] = '\0'; pimg->survey = NULL; pimg->survey_len = 0; pimg->separator = '.'; pimg->date1 = 0; pimg->date2 = 0; pimg->is_extended_elevation = 0; pimg->l = pimg->r = pimg->u = pimg->d = -1.0; pimg->title = pimg->datestamp = NULL; if (survey) { len = strlen(survey); if (len) { if (survey[len - 1] == '.') len--; if (len) { char *p; pimg->survey = xosmalloc(len + 2); if (!pimg->survey) { img_errno = IMG_OUTOFMEMORY; goto error; } memcpy(pimg->survey, survey, len); /* Set title to leaf survey name */ pimg->survey[len] = '\0'; p = strchr(pimg->survey, '.'); if (p) p++; else p = pimg->survey; pimg->title = my_strdup(p); if (!pimg->title) { img_errno = IMG_OUTOFMEMORY; goto error; } pimg->survey[len] = '.'; pimg->survey[len + 1] = '\0'; } } pimg->survey_len = len; } /* [VERSION_COMPASS_PLT, VERSION_CMAP_STATION, VERSION_CMAP_SHOT] pending * IMG_LINE or IMG_MOVE - both have 4 added. * [VERSION_SURVEX_POS] already skipped heading line, or there wasn't one * [version 0] not in the middle of a 'LINE' command * [version >= 3] not in the middle of turning a LINE into a MOVE */ pimg->pending = 0; len = strlen(fnm); if (has_ext(fnm, len, EXT_SVX_POS)) { pos_file: pimg->version = VERSION_SURVEX_POS; if (!pimg->survey) pimg->title = baseleaf_from_fnm(fnm); pimg->datestamp = my_strdup(TIMENA); if (!pimg->datestamp) { img_errno = IMG_OUTOFMEMORY; goto error; } pimg->start = 0; return pimg; } if (has_ext(fnm, len, EXT_PLT) || has_ext(fnm, len, EXT_PLF)) { long fpos; plt_file: pimg->version = VERSION_COMPASS_PLT; /* Spaces aren't legal in Compass station names, but dots are, so * use space as the level separator */ pimg->separator = ' '; pimg->start = 0; if (!pimg->survey) pimg->title = baseleaf_from_fnm(fnm); pimg->datestamp = my_strdup(TIMENA); if (!pimg->datestamp) { img_errno = IMG_OUTOFMEMORY; goto error; } while (1) { ch = getc(pimg->fh); switch (ch) { case '\x1a': fseek(pimg->fh, -1, SEEK_CUR); /* FALL THRU */ case EOF: pimg->start = ftell(pimg->fh); return pimg; case 'N': { char *line, *q; fpos = ftell(pimg->fh) - 1; if (!pimg->survey) { /* FIXME : if there's only one survey in the file, it'd be nice * to use its description as the title here... */ ungetc('N', pimg->fh); pimg->start = fpos; return pimg; } line = getline_alloc(pimg->fh); if (!line) { img_errno = IMG_OUTOFMEMORY; goto error; } len = 0; while (line[len] > 32) ++len; if (pimg->survey_len != len || memcmp(line, pimg->survey, len) != 0) { osfree(line); continue; } q = strchr(line + len, 'C'); if (q && q[1]) { osfree(pimg->title); pimg->title = my_strdup(q + 1); } else if (!pimg->title) { pimg->title = my_strdup(pimg->label); } osfree(line); if (!pimg->title) { img_errno = IMG_OUTOFMEMORY; goto error; } if (!pimg->start) pimg->start = fpos; fseek(pimg->fh, pimg->start, SEEK_SET); return pimg; } case 'M': case 'D': pimg->start = ftell(pimg->fh) - 1; break; } while (ch != '\n' && ch != '\r') { ch = getc(pimg->fh); } } } if (has_ext(fnm, len, EXT_XYZ)) { char *line; xyz_file: /* Spaces aren't legal in CMAP station names, but dots are, so * use space as the level separator. */ pimg->separator = ' '; line = getline_alloc(pimg->fh); if (!line) { img_errno = IMG_OUTOFMEMORY; goto error; } /* FIXME: reparse date? */ len = strlen(line); if (len > 59) line[59] = '\0'; if (len > 45) { pimg->datestamp = my_strdup(line + 45); } else { pimg->datestamp = my_strdup(TIMENA); } if (strncmp(line, " Cave Survey Data Processed by CMAP ", LITLEN(" Cave Survey Data Processed by CMAP ")) == 0) { len = 0; } else { if (len > 45) { line[45] = '\0'; len = 45; } while (len > 2 && line[len - 1] == ' ') --len; if (len > 2) { line[len] = '\0'; pimg->title = my_strdup(line + 2); } } if (len <= 2) pimg->title = baseleaf_from_fnm(fnm); osfree(line); if (!pimg->datestamp || !pimg->title) { img_errno = IMG_OUTOFMEMORY; goto error; } line = getline_alloc(pimg->fh); if (!line) { img_errno = IMG_OUTOFMEMORY; goto error; } if (line[0] != ' ' || (line[1] != 'S' && line[1] != 'O')) { img_errno = IMG_BADFORMAT; goto error; } if (line[1] == 'S') { pimg->version = VERSION_CMAP_STATION; } else { pimg->version = VERSION_CMAP_SHOT; } osfree(line); line = getline_alloc(pimg->fh); if (!line) { img_errno = IMG_OUTOFMEMORY; goto error; } if (line[0] != ' ' || line[1] != '-') { img_errno = IMG_BADFORMAT; goto error; } osfree(line); pimg->start = ftell(pimg->fh); return pimg; } if (fread(buf, LITLEN(FILEID) + 1, 1, pimg->fh) != 1 || memcmp(buf, FILEID"\n", LITLEN(FILEID) + 1) != 0) { if (fread(buf + LITLEN(FILEID) + 1, 8, 1, pimg->fh) == 1 && memcmp(buf, FILEID"\r\nv0.01\r\n", LITLEN(FILEID) + 9) == 0) { /* v0 3d file with DOS EOLs */ pimg->version = 0; goto v03d; } rewind(pimg->fh); if (buf[1] == ' ') { if (buf[0] == ' ') { /* Looks like a CMAP .xyz file ... */ goto xyz_file; } else if (strchr("ZSNF", buf[0])) { /* Looks like a Compass .plt file ... */ /* Almost certainly it'll start "Z " */ goto plt_file; } } if (buf[0] == '(') { /* Looks like a Survex .pos file ... */ goto pos_file; } img_errno = IMG_BADFORMAT; goto error; } /* check file format version */ ch = getc(pimg->fh); pimg->version = 0; if (tolower(ch) == 'b') { /* binary file iff B/b prefix */ pimg->version = 1; ch = getc(pimg->fh); } if (ch != 'v') { img_errno = IMG_BADFORMAT; goto error; } ch = getc(pimg->fh); if (ch == '0') { if (fread(buf, 4, 1, pimg->fh) != 1 || memcmp(buf, ".01\n", 4) != 0) { img_errno = IMG_BADFORMAT; goto error; } /* nothing special to do */ } else if (pimg->version == 0) { if (ch < '2' || ch > '0' + LATEST_IMG_VERSION || getc(pimg->fh) != '\n') { img_errno = IMG_TOONEW; goto error; } pimg->version = ch - '0'; } else { img_errno = IMG_BADFORMAT; goto error; } v03d: if (!pimg->title) pimg->title = getline_alloc(pimg->fh); else osfree(getline_alloc(pimg->fh)); pimg->datestamp = getline_alloc(pimg->fh); if (!pimg->title || !pimg->datestamp) { img_errno = IMG_OUTOFMEMORY; error: osfree(pimg->title); osfree(pimg->datestamp); fclose(pimg->fh); osfree(pimg); return NULL; } pimg->start = ftell(pimg->fh); len = strlen(pimg->title); if (len > 11 && strcmp(pimg->title + len - 11, " (extended)") == 0) { pimg->title[len - 11] = '\0'; pimg->is_extended_elevation = 1; } return pimg; }