xref: /plan9-contrib/sys/src/cmd/aux/gps/util.c (revision 7c881178665bb2c60319a9d7087bda946bd96483)
1*7c881178SDavid du Colombier #include <u.h>
2*7c881178SDavid du Colombier #include <libc.h>
3*7c881178SDavid du Colombier #include "dat.h"
4*7c881178SDavid du Colombier 
5*7c881178SDavid du Colombier Place nowhere = {
6*7c881178SDavid du Colombier 	Undef, Undef
7*7c881178SDavid du Colombier };
8*7c881178SDavid du Colombier 
9*7c881178SDavid du Colombier static void
setlat(Place * p,double lat)10*7c881178SDavid du Colombier setlat(Place *p, double lat)
11*7c881178SDavid du Colombier {
12*7c881178SDavid du Colombier 	p->lat = lat;
13*7c881178SDavid du Colombier }
14*7c881178SDavid du Colombier 
15*7c881178SDavid du Colombier static void
setlon(Place * p,double lon)16*7c881178SDavid du Colombier setlon(Place *p, double lon)
17*7c881178SDavid du Colombier {
18*7c881178SDavid du Colombier 	p->lon = lon;
19*7c881178SDavid du Colombier }
20*7c881178SDavid du Colombier 
21*7c881178SDavid du Colombier static int
printlatlon(char * p,int n,double lat,char po,char ne)22*7c881178SDavid du Colombier printlatlon(char *p, int n, double lat, char po, char ne)
23*7c881178SDavid du Colombier {
24*7c881178SDavid du Colombier 	char c;
25*7c881178SDavid du Colombier 	double d;
26*7c881178SDavid du Colombier 	int deg, min, sec;
27*7c881178SDavid du Colombier 
28*7c881178SDavid du Colombier 	if(lat > 0)
29*7c881178SDavid du Colombier 		c = po;
30*7c881178SDavid du Colombier 	else if(lat < 0){
31*7c881178SDavid du Colombier 		c = ne;
32*7c881178SDavid du Colombier 		lat = -lat;
33*7c881178SDavid du Colombier 	} else
34*7c881178SDavid du Colombier 		c = ' ';
35*7c881178SDavid du Colombier 	sec = 3600 * modf(lat, &d);
36*7c881178SDavid du Colombier 	deg = d;
37*7c881178SDavid du Colombier 	min = sec/60;
38*7c881178SDavid du Colombier 	sec = sec % 60;
39*7c881178SDavid du Colombier 	return snprint(p, n, "%#3.3d°%#2.2d′%#2.2d″%c", deg, min, sec, c);
40*7c881178SDavid du Colombier }
41*7c881178SDavid du Colombier 
42*7c881178SDavid du Colombier int
placeconv(Fmt * fp)43*7c881178SDavid du Colombier placeconv(Fmt *fp)
44*7c881178SDavid du Colombier {
45*7c881178SDavid du Colombier 	char str[256];
46*7c881178SDavid du Colombier 	int n;
47*7c881178SDavid du Colombier 	Place pl;
48*7c881178SDavid du Colombier 
49*7c881178SDavid du Colombier 	pl = va_arg(fp->args, Place);
50*7c881178SDavid du Colombier 	n = 0;
51*7c881178SDavid du Colombier 	n += printlatlon(str+n, sizeof(str)-n, pl.lat, 'N', 'S');
52*7c881178SDavid du Colombier 	n += snprint(str+n, sizeof(str)-n, ", ");
53*7c881178SDavid du Colombier 	printlatlon(str+n, sizeof(str)-n, pl.lon, 'E', 'W');
54*7c881178SDavid du Colombier 	return fmtstrcpy(fp, str);
55*7c881178SDavid du Colombier }
56*7c881178SDavid du Colombier 
57*7c881178SDavid du Colombier int
strtolatlon(char * p,char ** ep,Place * pl)58*7c881178SDavid du Colombier strtolatlon(char *p, char **ep, Place *pl)
59*7c881178SDavid du Colombier {
60*7c881178SDavid du Colombier 	double latlon;
61*7c881178SDavid du Colombier 	int neg = 0;
62*7c881178SDavid du Colombier 
63*7c881178SDavid du Colombier 	while(*p == '0') p++;
64*7c881178SDavid du Colombier 	latlon = strtod(p, &p);
65*7c881178SDavid du Colombier 	if(latlon < 0){
66*7c881178SDavid du Colombier 		latlon = -latlon;
67*7c881178SDavid du Colombier 		neg = 1;
68*7c881178SDavid du Colombier 	}
69*7c881178SDavid du Colombier 	if(*p == ':'){
70*7c881178SDavid du Colombier 		p++;
71*7c881178SDavid du Colombier 		while(*p == '0') p++;
72*7c881178SDavid du Colombier 		latlon += strtod(p, &p)/60.0;
73*7c881178SDavid du Colombier 		if(*p == ':'){
74*7c881178SDavid du Colombier 			p++;
75*7c881178SDavid du Colombier 			while(*p == '0') p++;
76*7c881178SDavid du Colombier 			latlon += strtod(p, &p)/3600.0;
77*7c881178SDavid du Colombier 		}
78*7c881178SDavid du Colombier 	}
79*7c881178SDavid du Colombier 	switch (*p++){
80*7c881178SDavid du Colombier 	case 'N':
81*7c881178SDavid du Colombier 	case 'n':
82*7c881178SDavid du Colombier 		if(neg) latlon = -latlon;
83*7c881178SDavid du Colombier 		if(pl->lat != Undef)
84*7c881178SDavid du Colombier 			return -1;
85*7c881178SDavid du Colombier 		setlat(pl, latlon);
86*7c881178SDavid du Colombier 		break;
87*7c881178SDavid du Colombier 	case 'S':
88*7c881178SDavid du Colombier 	case 's':
89*7c881178SDavid du Colombier 		if(!neg) latlon = -latlon;
90*7c881178SDavid du Colombier 		if(pl->lat != Undef)
91*7c881178SDavid du Colombier 			return -1;
92*7c881178SDavid du Colombier 		setlat(pl, latlon);
93*7c881178SDavid du Colombier 		break;
94*7c881178SDavid du Colombier 	case 'E':
95*7c881178SDavid du Colombier 	case 'e':
96*7c881178SDavid du Colombier 		if(neg) latlon = -latlon;
97*7c881178SDavid du Colombier 		if(pl->lon != Undef)
98*7c881178SDavid du Colombier 			return -1;
99*7c881178SDavid du Colombier 		setlon(pl, latlon);
100*7c881178SDavid du Colombier 		break;
101*7c881178SDavid du Colombier 	case 'W':
102*7c881178SDavid du Colombier 	case 'w':
103*7c881178SDavid du Colombier 		if(!neg) latlon = -latlon;
104*7c881178SDavid du Colombier 		if(pl->lon != Undef)
105*7c881178SDavid du Colombier 			return -1;
106*7c881178SDavid du Colombier 		setlon(pl, latlon);
107*7c881178SDavid du Colombier 		break;
108*7c881178SDavid du Colombier 	case '\0':
109*7c881178SDavid du Colombier 	case ' ':
110*7c881178SDavid du Colombier 	case '\t':
111*7c881178SDavid du Colombier 	case '\n':
112*7c881178SDavid du Colombier 		p--;
113*7c881178SDavid du Colombier 		if(neg) latlon = -latlon;
114*7c881178SDavid du Colombier 		if(pl->lat == Undef){
115*7c881178SDavid du Colombier 			setlat(pl, latlon);
116*7c881178SDavid du Colombier 		} else if(pl->lon == Undef){
117*7c881178SDavid du Colombier 			latlon = -latlon;
118*7c881178SDavid du Colombier 			setlon(pl, latlon);
119*7c881178SDavid du Colombier 		} else return -1;
120*7c881178SDavid du Colombier 		break;
121*7c881178SDavid du Colombier 	default:
122*7c881178SDavid du Colombier 		return -1;
123*7c881178SDavid du Colombier 	}
124*7c881178SDavid du Colombier 	if(ep)
125*7c881178SDavid du Colombier 		*ep = p;
126*7c881178SDavid du Colombier 	return 0;
127*7c881178SDavid du Colombier }
128*7c881178SDavid du Colombier 
129*7c881178SDavid du Colombier Place
strtopos(char * p,char ** ep)130*7c881178SDavid du Colombier strtopos(char *p, char **ep)
131*7c881178SDavid du Colombier {
132*7c881178SDavid du Colombier 	Place pl = nowhere;
133*7c881178SDavid du Colombier 
134*7c881178SDavid du Colombier 	if(strtolatlon(p, &p, &pl) < 0)
135*7c881178SDavid du Colombier 		return nowhere;
136*7c881178SDavid du Colombier 	while(*p == ' ' || *p == '\t' || *p == '\n')
137*7c881178SDavid du Colombier 		p++;
138*7c881178SDavid du Colombier 	if(strtolatlon(p, &p, &pl) < 0)
139*7c881178SDavid du Colombier 		return nowhere;
140*7c881178SDavid du Colombier 	if(ep)
141*7c881178SDavid du Colombier 		*ep = p;
142*7c881178SDavid du Colombier 	return pl;
143*7c881178SDavid du Colombier }
144*7c881178SDavid du Colombier 
145*7c881178SDavid du Colombier static void
rtcset(long t)146*7c881178SDavid du Colombier rtcset(long t)		/* We may use this some day */
147*7c881178SDavid du Colombier {
148*7c881178SDavid du Colombier 	static int fd;
149*7c881178SDavid du Colombier 	long r;
150*7c881178SDavid du Colombier 	int n;
151*7c881178SDavid du Colombier 	char buf[32];
152*7c881178SDavid du Colombier 
153*7c881178SDavid du Colombier 	if(fd <= 0 && (fd = open("#r/rtc", ORDWR)) < 0){
154*7c881178SDavid du Colombier 		fprint(2, "Can't open #r/rtc: %r\n");
155*7c881178SDavid du Colombier 		return;
156*7c881178SDavid du Colombier 	}
157*7c881178SDavid du Colombier 	n = read(fd, buf, sizeof buf - 1);
158*7c881178SDavid du Colombier 	if(n <= 0){
159*7c881178SDavid du Colombier 		fprint(2, "Can't read #r/rtc: %r\n");
160*7c881178SDavid du Colombier 		return;
161*7c881178SDavid du Colombier 	}
162*7c881178SDavid du Colombier 	buf[n] = '\0';
163*7c881178SDavid du Colombier 	r = strtol(buf, nil, 0);
164*7c881178SDavid du Colombier 	if(r <= 0){
165*7c881178SDavid du Colombier 		fprint(2, "ridiculous #r/rtc: %ld\n", r);
166*7c881178SDavid du Colombier 		return;
167*7c881178SDavid du Colombier 	}
168*7c881178SDavid du Colombier 	if(r - t > 1 || t - r > 0){
169*7c881178SDavid du Colombier 		seek(fd, 0, 0);
170*7c881178SDavid du Colombier 		fprint(fd, "%ld", t);
171*7c881178SDavid du Colombier 		fprint(2, "correcting #r/rtc: %ld → %ld\n", r, t);
172*7c881178SDavid du Colombier 	}
173*7c881178SDavid du Colombier 	seek(fd, 0, 0);
174*7c881178SDavid du Colombier }
175