double dmstor(const char *is, char **rs) { int sign, n, nl; char *p, *s, work[MAX_WORK]; double v, tv; if (rs) *rs = (char *)is; /* copy sting into work space */ while (isspace(sign = *is)) ++is; for (n = MAX_WORK, s = work, p = (char *)is; isgraph(*p) && --n ; ) *s++ = *p++; *s = '\0'; /* it is possible that a really odd input (like lots of leading zeros) could be truncated in copying into work. But ... */ sign = *(s = work); if (sign == '+' || sign == '-') s++; else sign = '+'; for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) { if (!(isdigit(*s) || *s == '.')) break; if ((tv = proj_strtod(s, &s)) == HUGE_VAL) return tv; switch (*s) { case 'D': case 'd': n = 0; break; case '\'': n = 1; break; case '"': n = 2; break; case 'r': case 'R': if (nl) { pj_errno = -16; return HUGE_VAL; } ++s; v = tv; goto skip; default: v += tv * vm[nl]; skip: n = 4; continue; } if (n < nl) { pj_errno = -16; return HUGE_VAL; } v += tv * vm[n]; ++s; } /* postfix sign */ if (*s && (p = strchr(sym, *s))) { sign = (p - sym) >= 4 ? '-' : '+'; ++s; } if (sign == '-') v = -v; if (rs) /* return point of next char after valid string */ *rs = (char *)is + (s - work); return v; }
static PJ_COORD parse_coord (const char *args) { /***************************************************************************** Attempt to interpret args as a PJ_COORD. ******************************************************************************/ int i; const char *endp; const char *dmsendp; const char *prev = args; PJ_COORD a = proj_coord (0,0,0,0); T.dimensions_given = 0; for (i = 0; i < 4; i++) { /* proj_strtod doesn't read values like 123d45'678W so we need a bit */ /* of help from proj_dmstor. proj_strtod effectively ignores what */ /* comes after "d", so we use that fact that when dms is larger than */ /* d the value was stated in "dms" form. */ /* This could be avoided if proj_dmstor used the same proj_strtod() */ /* as gie, but that is not the case (yet). When we remove projects.h */ /* from the public API we can change that. */ double d = proj_strtod(prev, (char **) &endp); double dms = PJ_TODEG(proj_dmstor (prev, (char **) &dmsendp)); /* TODO: When projects.h is removed, call proj_dmstor() in all cases */ if (d != dms && fabs(d) < fabs(dms) && fabs(dms) < fabs(d) + 1) { d = dms; endp = dmsendp; } /* A number like -81d00'00.000 will be parsed correctly by both */ /* proj_strtod and proj_dmstor but only the latter will return */ /* the correct end-pointer. */ if (d == dms && endp != dmsendp) endp = dmsendp; /* Break out if there were no more numerals */ if (prev==endp) return i > 1? a: proj_coord_error (); a.v[i] = d; prev = endp; T.dimensions_given++; } return a; }
static double strtod_scaled (const char *args, double default_scale) { /***************************************************************************** Interpret <args> as a numeric followed by a linear decadal prefix. Return the properly scaled numeric ******************************************************************************/ double s; const double GRS80_DEG = 111319.4908; /* deg-to-m at equator of GRS80 */ const char *endp = args; s = proj_strtod (args, (char **) &endp); if (args==endp) return HUGE_VAL; endp = column (args, 2); if (0==strcmp(endp, "km")) s *= 1000; else if (0==strcmp(endp, "m")) s *= 1; else if (0==strcmp(endp, "dm")) s /= 10; else if (0==strcmp(endp, "cm")) s /= 100; else if (0==strcmp(endp, "mm")) s /= 1000; else if (0==strcmp(endp, "um")) s /= 1e6; else if (0==strcmp(endp, "nm")) s /= 1e9; else if (0==strcmp(endp, "rad")) s = GRS80_DEG * proj_todeg (s); else if (0==strcmp(endp, "deg")) s = GRS80_DEG * s; else s *= default_scale; return s; }
static int roundtrip (const char *args) { /***************************************************************************** Check how far we go from the ACCEPTed point when doing successive back/forward transformation pairs. Without args, roundtrip defaults to 100 iterations: roundtrip With one arg, roundtrip will default to a tolerance of T.tolerance: roundtrip ntrips With two args: roundtrip ntrips tolerance Always returns 0. ******************************************************************************/ int ntrips; double d, r, ans; char *endp; PJ_COORD coo; if (nullptr==T.P) { if (T.ignore == proj_errno(T.P)) return another_skip(); return another_failure (); } ans = proj_strtod (args, &endp); if (endp==args) { /* Default to 100 iterations if not args. */ ntrips = 100; } else { if (ans < 1.0 || ans > 1000000.0) { errmsg (2, "Invalid number of roundtrips: %lf\n", ans); return another_failing_roundtrip (); } ntrips = (int)ans; } d = strtod_scaled (endp, 1); d = d==HUGE_VAL? T.tolerance: d; /* input ("accepted") values - probably in degrees */ coo = proj_angular_input (T.P, T.dir)? torad_coord (T.P, T.dir, T.a): T.a; r = proj_roundtrip (T.P, T.dir, ntrips, &coo); if (r <= d) return another_succeeding_roundtrip (); if (T.verbosity > -1) { if (0==T.op_ko && T.verbosity < 2) banner (T.operation); fprintf (T.fout, "%s", T.op_ko? " -----\n": delim); fprintf (T.fout, " FAILURE in %s(%d):\n", opt_strip_path (T.curr_file), (int) F->lineno); fprintf (T.fout, " roundtrip deviation: %.6f mm, expected: %.6f mm\n", 1000*r, 1000*d); } return another_failing_roundtrip (); }