+static int suunto_dive_match(struct dive **divep, const char *name, int len, char *buf)
+{
+ struct dive *dive = *divep;
+
+ return MATCH(".o2pct", percent, &dive->cylinder[0].gasmix.o2) ||
+ MATCH(".hepct_0", percent, &dive->cylinder[0].gasmix.he) ||
+ MATCH(".o2pct_2", percent, &dive->cylinder[1].gasmix.o2) ||
+ MATCH(".hepct_1", percent, &dive->cylinder[1].gasmix.he) ||
+ MATCH(".o2pct_3", percent, &dive->cylinder[2].gasmix.o2) ||
+ MATCH(".hepct_2", percent, &dive->cylinder[2].gasmix.he) ||
+ MATCH(".o2pct_4", percent, &dive->cylinder[3].gasmix.o2) ||
+ MATCH(".hepct_3", percent, &dive->cylinder[3].gasmix.he) ||
+ MATCH(".cylindersize", cylindersize, &dive->cylinder[0].type.size) ||
+ MATCH(".cylinderworkpressure", pressure, &dive->cylinder[0].type.workingpressure) ||
+ 0;
+}
+
+static const char *country, *city;
+
+static void divinglog_place(char *place, void *_location)
+{
+ char **location = _location;
+ char buffer[256], *p;
+ int len;
+
+ len = snprintf(buffer, sizeof(buffer),
+ "%s%s%s%s%s",
+ place,
+ city ? ", " : "",
+ city ? city : "",
+ country ? ", " : "",
+ country ? country : "");
+
+ p = malloc(len+1);
+ memcpy(p, buffer, len+1);
+ *location = p;
+
+ city = NULL;
+ country = NULL;
+}
+
+static int divinglog_dive_match(struct dive **divep, const char *name, int len, char *buf)
+{
+ struct dive *dive = *divep;
+
+ return MATCH(".divedate", divedate, &dive->when) ||
+ MATCH(".entrytime", divetime, &dive->when) ||
+ MATCH(".depth", depth, &dive->maxdepth) ||
+ MATCH(".tanksize", cylindersize, &dive->cylinder[0].type.size) ||
+ MATCH(".presw", pressure, &dive->cylinder[0].type.workingpressure) ||
+ MATCH(".comments", utf8_string, &dive->notes) ||
+ MATCH(".buddy.names", utf8_string, &dive->buddy) ||
+ MATCH(".country.name", utf8_string, &country) ||
+ MATCH(".city.name", utf8_string, &city) ||
+ MATCH(".place.name", divinglog_place, &dive->location) ||
+ 0;
+}
+
+static int buffer_value(char *buffer)
+{
+ int val = atoi(buffer);
+ free(buffer);
+ return val;
+}
+
+static void uemis_length_unit(char *buffer, void *_unused)
+{
+ input_units.length = buffer_value(buffer) ? FEET : METERS;
+}
+
+static void uemis_volume_unit(char *buffer, void *_unused)
+{
+ input_units.volume = buffer_value(buffer) ? CUFT : LITER;
+}
+
+static void uemis_pressure_unit(char *buffer, void *_unused)
+{
+#if 0
+ input_units.pressure = buffer_value(buffer) ? PSI : BAR;
+#endif
+}
+
+static void uemis_temperature_unit(char *buffer, void *_unused)
+{
+ input_units.temperature = buffer_value(buffer) ? FAHRENHEIT : CELSIUS;
+}
+
+static void uemis_weight_unit(char *buffer, void *_unused)
+{
+ input_units.weight = buffer_value(buffer) ? LBS : KG;
+}
+
+static void uemis_time_unit(char *buffer, void *_unused)
+{
+}
+
+static void uemis_date_unit(char *buffer, void *_unused)
+{
+}
+
+/* Modified julian day, yay! */
+static void uemis_date_time(char *buffer, void *_when)
+{
+ time_t *when = _when;
+ union int_or_float val;
+
+ switch (integer_or_float(buffer, &val)) {
+ case FLOAT:
+ *when = (val.fp - 40587) * 86400;
+ break;
+ default:
+ fprintf(stderr, "Strange julian date: %s", buffer);
+ }
+ free(buffer);
+}
+
+/*
+ * Uemis doesn't know time zones. You need to do them as
+ * minutes, not hours.
+ *
+ * But that's ok, we don't track timezones yet either. We
+ * just turn everything into "localtime expressed as UTC".
+ */
+static void uemis_time_zone(char *buffer, void *_when)
+{
+#if 0 /* seems like this is only used to display it correctly
+ * the stored time appears to be UTC */
+
+ time_t *when = _when;
+ signed char tz = atoi(buffer);
+
+ *when += tz * 3600;
+#endif
+}
+
+static void uemis_ts(char *buffer, void *_when)
+{
+ struct tm tm;
+ time_t *when = _when;
+
+ strptime(buffer, "%Y-%m-%dT%H:%M:%S", &tm);
+ *when = utc_mktime(&tm);
+}
+
+static void uemis_duration(char *buffer, void *_duration)
+{
+ duration_t *duration = _duration;
+ duration->seconds = atof(buffer) * 60 + 0.5;
+}
+
+/* 0 - air ; 1 - nitrox1 ; 2 - nitrox2 ; 3 = nitrox3 */
+static int uemis_gas_template;
+
+/*
+ * Christ. Uemis tank data is a total mess.
+ *
+ * We're passed a "virtual cylinder" (0 - 6) for the different
+ * Uemis tank cases ("air", "nitrox_1", "nitrox_2.{bottom,deco}"
+ * and "nitrox_3.{bottom,deco,travel}". We need to turn that
+ * into the actual cylinder data depending on the gas template,
+ * and ignore the ones that are irrelevant for that template.
+ *
+ * So for "template 2" (nitrox_2), we ignore virtual tanks 0-1
+ * (which are "air" and "nitrox_1" respectively), and tanks 4-6
+ * (which are the three "nitrox_3" tanks), and we turn virtual
+ * tanks 2/3 into actual tanks 0/1.
+ *
+ * Confused yet?
+ */
+static int uemis_cylinder_index(void *_cylinder)