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