diff options
Diffstat (limited to 'core/file.c')
-rw-r--r-- | core/file.c | 854 |
1 files changed, 1 insertions, 853 deletions
diff --git a/core/file.c b/core/file.c index d604f94cd..9682bc0c3 100644 --- a/core/file.c +++ b/core/file.c @@ -14,6 +14,7 @@ #include "file.h" #include "git-access.h" #include "qthelperfromc.h" +#include "import-csv.h" /* For SAMPLE_* */ #include <libdivecomputer/parser.h> @@ -114,55 +115,6 @@ int try_to_open_zip(const char *filename) return success; } -static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, const char *tag) -{ - char *buf; - - if (mem->size == 0 && readfile(filename, mem) < 0) - return report_error(translate("gettextFromC", "Failed to read '%s'"), filename); - - /* Surround the CSV file content with XML tags to enable XSLT - * parsing - * - * Tag markers take: strlen("<></>") = 5 - */ - buf = realloc(mem->buffer, mem->size + 7 + strlen(tag) * 2); - if (buf != NULL) { - char *starttag = NULL; - char *endtag = NULL; - - starttag = malloc(3 + strlen(tag)); - endtag = malloc(5 + strlen(tag)); - - if (starttag == NULL || endtag == NULL) { - /* this is fairly silly - so the malloc fails, but we strdup the error? - * let's complete the silliness by freeing the two pointers in case one malloc succeeded - * and the other one failed - this will make static analysis tools happy */ - free(starttag); - free(endtag); - free(buf); - return report_error("Memory allocation failed in %s", __func__); - } - - sprintf(starttag, "<%s>", tag); - sprintf(endtag, "\n</%s>", tag); - - memmove(buf + 2 + strlen(tag), buf, mem->size); - memcpy(buf, starttag, 2 + strlen(tag)); - memcpy(buf + mem->size + 2 + strlen(tag), endtag, 5 + strlen(tag)); - mem->size += (6 + 2 * strlen(tag)); - mem->buffer = buf; - - free(starttag); - free(endtag); - } else { - free(mem->buffer); - return report_error("realloc failed in %s", __func__); - } - - return 0; -} - int db_test_func(void *param, int columns, char **data, char **column) { (void) param; @@ -266,55 +218,6 @@ timestamp_t parse_date(const char *date) return utc_mktime(&tm); } -enum csv_format { - CSV_DEPTH, - CSV_TEMP, - CSV_PRESSURE, - POSEIDON_DEPTH, - POSEIDON_TEMP, - POSEIDON_SETPOINT, - POSEIDON_SENSOR1, - POSEIDON_SENSOR2, - POSEIDON_NDL, - POSEIDON_CEILING -}; - -static void add_sample_data(struct sample *sample, enum csv_format type, double val) -{ - switch (type) { - case CSV_DEPTH: - sample->depth.mm = feet_to_mm(val); - break; - case CSV_TEMP: - sample->temperature.mkelvin = F_to_mkelvin(val); - break; - case CSV_PRESSURE: - sample->pressure[0].mbar = psi_to_mbar(val * 4); - break; - case POSEIDON_DEPTH: - sample->depth.mm = lrint(val * 0.5 * 1000); - break; - case POSEIDON_TEMP: - sample->temperature.mkelvin = C_to_mkelvin(val * 0.2); - break; - case POSEIDON_SETPOINT: - sample->setpoint.mbar = lrint(val * 10); - break; - case POSEIDON_SENSOR1: - sample->o2sensor[0].mbar = lrint(val * 10); - break; - case POSEIDON_SENSOR2: - sample->o2sensor[1].mbar = lrint(val * 10); - break; - case POSEIDON_NDL: - sample->ndl.seconds = lrint(val * 60); - break; - case POSEIDON_CEILING: - sample->stopdepth.mm = lrint(val * 1000); - break; - } -} - /* * Cochran comma-separated values: depth in feet, temperature in F, pressure in psi. * @@ -331,60 +234,6 @@ static void add_sample_data(struct sample *sample, enum csv_format type, double * * Followed by the data values (all comma-separated, all one long line). */ -static int try_to_open_csv(struct memblock *mem, enum csv_format type) -{ - char *p = mem->buffer; - char *header[8]; - int i, time; - timestamp_t date; - struct dive *dive; - struct divecomputer *dc; - - for (i = 0; i < 8; i++) { - header[i] = p; - p = strchr(p, ','); - if (!p) - return 0; - p++; - } - - date = parse_date(header[2]); - if (!date) - return 0; - - dive = alloc_dive(); - dive->when = date; - dive->number = atoi(header[1]); - dc = &dive->dc; - - time = 0; - for (;;) { - char *end; - double val; - struct sample *sample; - - errno = 0; - val = strtod(p, &end); // FIXME == localization issue - if (end == p) - break; - if (errno) - break; - - sample = prepare_sample(dc); - sample->time.seconds = time; - add_sample_data(sample, type, val); - finish_sample(dc); - - time++; - dc->duration.seconds = time; - if (*end != ',') - break; - p = end + 1; - } - record_dive(dive); - return 1; -} - static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem) { // hack to be able to provide a comment for the translated string @@ -541,704 +390,3 @@ int parse_file(const char *filename) return ret; } -#define MATCH(buffer, pattern) \ - memcmp(buffer, pattern, strlen(pattern)) - -char *parse_mkvi_value(const char *haystack, const char *needle) -{ - char *lineptr, *valueptr, *endptr, *ret = NULL; - - if ((lineptr = strstr(haystack, needle)) != NULL) { - if ((valueptr = strstr(lineptr, ": ")) != NULL) { - valueptr += 2; - } - if ((endptr = strstr(lineptr, "\n")) != NULL) { - char terminator = '\n'; - if (*(endptr - 1) == '\r') { - --endptr; - terminator = '\r'; - } - *endptr = 0; - ret = copy_string(valueptr); - *endptr = terminator; - - } - } - return ret; -} - -char *next_mkvi_key(const char *haystack) -{ - char *valueptr, *endptr, *ret = NULL; - - if ((valueptr = strstr(haystack, "\n")) != NULL) { - valueptr += 1; - if ((endptr = strstr(valueptr, ": ")) != NULL) { - *endptr = 0; - ret = strdup(valueptr); - *endptr = ':'; - } - } - return ret; -} - -int parse_txt_file(const char *filename, const char *csv) -{ - struct memblock memtxt, memcsv; - - if (readfile(filename, &memtxt) < 0) { - return report_error(translate("gettextFromC", "Failed to read '%s'"), filename); - } - - /* - * MkVI stores some information in .txt file but the whole profile and events are stored in .csv file. First - * make sure the input .txt looks like proper MkVI file, then start parsing the .csv. - */ - if (MATCH(memtxt.buffer, "MkVI_Config") == 0) { - int d, m, y, he; - int hh = 0, mm = 0, ss = 0; - int prev_depth = 0, cur_sampletime = 0, prev_setpoint = -1, prev_ndl = -1; - bool has_depth = false, has_setpoint = false, has_ndl = false; - char *lineptr, *key, *value; - int cur_cylinder_index = 0; - unsigned int prev_time = 0; - - struct dive *dive; - struct divecomputer *dc; - struct tm cur_tm; - - value = parse_mkvi_value(memtxt.buffer, "Dive started at"); - if (sscanf(value, "%d-%d-%d %d:%d:%d", &y, &m, &d, &hh, &mm, &ss) != 6) { - free(value); - return -1; - } - free(value); - cur_tm.tm_year = y; - cur_tm.tm_mon = m - 1; - cur_tm.tm_mday = d; - cur_tm.tm_hour = hh; - cur_tm.tm_min = mm; - cur_tm.tm_sec = ss; - - dive = alloc_dive(); - dive->when = utc_mktime(&cur_tm);; - dive->dc.model = strdup("Poseidon MkVI Discovery"); - value = parse_mkvi_value(memtxt.buffer, "Rig Serial number"); - dive->dc.deviceid = atoi(value); - free(value); - dive->dc.divemode = CCR; - dive->dc.no_o2sensors = 2; - - dive->cylinder[cur_cylinder_index].cylinder_use = OXYGEN; - dive->cylinder[cur_cylinder_index].type.size.mliter = 3000; - dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = 200000; - dive->cylinder[cur_cylinder_index].type.description = strdup("3l Mk6"); - dive->cylinder[cur_cylinder_index].gasmix.o2.permille = 1000; - cur_cylinder_index++; - - dive->cylinder[cur_cylinder_index].cylinder_use = DILUENT; - dive->cylinder[cur_cylinder_index].type.size.mliter = 3000; - dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = 200000; - dive->cylinder[cur_cylinder_index].type.description = strdup("3l Mk6"); - value = parse_mkvi_value(memtxt.buffer, "Helium percentage"); - he = atoi(value); - free(value); - value = parse_mkvi_value(memtxt.buffer, "Nitrogen percentage"); - dive->cylinder[cur_cylinder_index].gasmix.o2.permille = (100 - atoi(value) - he) * 10; - free(value); - dive->cylinder[cur_cylinder_index].gasmix.he.permille = he * 10; - cur_cylinder_index++; - - lineptr = strstr(memtxt.buffer, "Dive started at"); - while (lineptr && *lineptr && (lineptr = strchr(lineptr, '\n')) && ++lineptr) { - key = next_mkvi_key(lineptr); - if (!key) - break; - value = parse_mkvi_value(lineptr, key); - if (!value) { - free(key); - break; - } - add_extra_data(&dive->dc, key, value); - free(key); - free(value); - } - dc = &dive->dc; - - /* - * Read samples from the CSV file. A sample contains all the lines with same timestamp. The CSV file has - * the following format: - * - * timestamp, type, value - * - * And following fields are of interest to us: - * - * 6 sensor1 - * 7 sensor2 - * 8 depth - * 13 o2 tank pressure - * 14 diluent tank pressure - * 20 o2 setpoint - * 39 water temp - */ - - if (readfile(csv, &memcsv) < 0) { - free(dive); - return report_error(translate("gettextFromC", "Poseidon import failed: unable to read '%s'"), csv); - } - lineptr = memcsv.buffer; - for (;;) { - struct sample *sample; - int type; - int value; - int sampletime; - int gaschange = 0; - - /* Collect all the information for one sample */ - sscanf(lineptr, "%d,%d,%d", &cur_sampletime, &type, &value); - - has_depth = false; - has_setpoint = false; - has_ndl = false; - sample = prepare_sample(dc); - - /* - * There was a bug in MKVI download tool that resulted in erroneous sample - * times. This fix should work similarly as the vendor's own. - */ - - sample->time.seconds = cur_sampletime < 0xFFFF * 3 / 4 ? cur_sampletime : prev_time; - prev_time = sample->time.seconds; - - do { - int i = sscanf(lineptr, "%d,%d,%d", &sampletime, &type, &value); - switch (i) { - case 3: - switch (type) { - case 0: - //Mouth piece position event: 0=OC, 1=CC, 2=UN, 3=NC - switch (value) { - case 0: - add_event(dc, cur_sampletime, 0, 0, 0, - QT_TRANSLATE_NOOP("gettextFromC", "Mouth piece position OC")); - break; - case 1: - add_event(dc, cur_sampletime, 0, 0, 0, - QT_TRANSLATE_NOOP("gettextFromC", "Mouth piece position CC")); - break; - case 2: - add_event(dc, cur_sampletime, 0, 0, 0, - QT_TRANSLATE_NOOP("gettextFromC", "Mouth piece position unknown")); - break; - case 3: - add_event(dc, cur_sampletime, 0, 0, 0, - QT_TRANSLATE_NOOP("gettextFromC", "Mouth piece position not connected")); - break; - } - break; - case 3: - //Power Off event - add_event(dc, cur_sampletime, 0, 0, 0, - QT_TRANSLATE_NOOP("gettextFromC", "Power off")); - break; - case 4: - //Battery State of Charge in % -#ifdef SAMPLE_EVENT_BATTERY - add_event(dc, cur_sampletime, SAMPLE_EVENT_BATTERY, 0, - value, QT_TRANSLATE_NOOP("gettextFromC", "battery")); -#endif - break; - case 6: - //PO2 Cell 1 Average - add_sample_data(sample, POSEIDON_SENSOR1, value); - break; - case 7: - //PO2 Cell 2 Average - add_sample_data(sample, POSEIDON_SENSOR2, value); - break; - case 8: - //Depth * 2 - has_depth = true; - prev_depth = value; - add_sample_data(sample, POSEIDON_DEPTH, value); - break; - //9 Max Depth * 2 - //10 Ascent/Descent Rate * 2 - case 11: - //Ascent Rate Alert >10 m/s - add_event(dc, cur_sampletime, SAMPLE_EVENT_ASCENT, 0, 0, - QT_TRANSLATE_NOOP("gettextFromC", "ascent")); - break; - case 13: - //O2 Tank Pressure - add_sample_pressure(sample, 0, lrint(value * 1000)); - break; - case 14: - //Diluent Tank Pressure - add_sample_pressure(sample, 1, lrint(value * 1000)); - break; - //16 Remaining dive time #1? - //17 related to O2 injection - case 20: - //PO2 Setpoint - has_setpoint = true; - prev_setpoint = value; - add_sample_data(sample, POSEIDON_SETPOINT, value); - break; - case 22: - //End of O2 calibration Event: 0 = OK, 2 = Failed, rest of dive setpoint 1.0 - if (value == 2) - add_event(dc, cur_sampletime, 0, SAMPLE_FLAGS_END, 0, - QT_TRANSLATE_NOOP("gettextFromC", "O₂ calibration failed")); - add_event(dc, cur_sampletime, 0, SAMPLE_FLAGS_END, 0, - QT_TRANSLATE_NOOP("gettextFromC", "O₂ calibration")); - break; - case 25: - //25 Max Ascent depth - add_sample_data(sample, POSEIDON_CEILING, value); - break; - case 31: - //Start of O2 calibration Event - add_event(dc, cur_sampletime, 0, SAMPLE_FLAGS_BEGIN, 0, - QT_TRANSLATE_NOOP("gettextFromC", "O₂ calibration")); - break; - case 37: - //Remaining dive time #2? - has_ndl = true; - prev_ndl = value; - add_sample_data(sample, POSEIDON_NDL, value); - break; - case 39: - // Water Temperature in Celcius - add_sample_data(sample, POSEIDON_TEMP, value); - break; - case 85: - //He diluent part in % - gaschange += value << 16; - break; - case 86: - //O2 diluent part in % - gaschange += value; - break; - //239 Unknown, maybe PO2 at sensor validation? - //240 Unknown, maybe PO2 at sensor validation? - //247 Unknown, maybe PO2 Cell 1 during pressure test - //248 Unknown, maybe PO2 Cell 2 during pressure test - //250 PO2 Cell 1 - //251 PO2 Cell 2 - default: - break; - } /* sample types */ - break; - case EOF: - break; - default: - printf("Unable to parse input: %s\n", lineptr); - break; - } - - lineptr = strchr(lineptr, '\n'); - if (!lineptr || !*lineptr) - break; - lineptr++; - - /* Grabbing next sample time */ - sscanf(lineptr, "%d,%d,%d", &cur_sampletime, &type, &value); - } while (sampletime == cur_sampletime); - - if (gaschange) - add_event(dc, cur_sampletime, SAMPLE_EVENT_GASCHANGE2, 0, gaschange, - QT_TRANSLATE_NOOP("gettextFromC", "gaschange")); - if (!has_depth) - add_sample_data(sample, POSEIDON_DEPTH, prev_depth); - if (!has_setpoint && prev_setpoint >= 0) - add_sample_data(sample, POSEIDON_SETPOINT, prev_setpoint); - if (!has_ndl && prev_ndl >= 0) - add_sample_data(sample, POSEIDON_NDL, prev_ndl); - finish_sample(dc); - - if (!lineptr || !*lineptr) - break; - } - record_dive(dive); - return 1; - } else { - return 0; - } - - return 0; -} - -#define MAXCOLDIGITS 10 -#define DATESTR 9 -#define TIMESTR 6 - -int parse_dan_format(const char *filename, char **params, int pnr) -{ - int ret = 0, i; - size_t end_ptr = 0; - struct memblock mem, mem_csv; - char tmpbuf[MAXCOLDIGITS]; - - char *ptr = NULL; - char *NL = NULL; - char *iter = NULL; - - if (readfile(filename, &mem) < 0) - return report_error(translate("gettextFromC", "Failed to read '%s'"), filename); - - /* Determine NL (new line) character and the start of CSV data */ - if ((ptr = strstr(mem.buffer, "\r\n")) != NULL) { - NL = "\r\n"; - } else if ((ptr = strstr(mem.buffer, "\n")) != NULL) { - NL = "\n"; - } else { - fprintf(stderr, "DEBUG: failed to detect NL\n"); - return -1; - } - - while ((end_ptr < mem.size) && (ptr = strstr(mem.buffer + end_ptr, "ZDH"))) { - - /* - * Process the dives, but let the last round be parsed - * from C++ code - */ - - if (end_ptr) - process_dives(true, false); - - mem_csv.buffer = malloc(mem.size + 1); - mem_csv.size = mem.size; - - iter = ptr + 4; - iter = strchr(iter, '|'); - if (iter) { - memcpy(tmpbuf, ptr + 4, iter - ptr - 4); - tmpbuf[iter - ptr - 4] = 0; - params[pnr] = "diveNro"; - params[pnr + 1] = strdup(tmpbuf); - } - - //fprintf(stderr, "DEBUG: BEGIN end_ptr %d round %d <%s>\n", end_ptr, j++, ptr); - iter = ptr + 1; - for (i = 0; i <= 4 && iter; ++i) { - iter = strchr(iter, '|'); - if (iter) - ++iter; - } - - if (!iter) { - fprintf(stderr, "DEBUG: Data corrupt"); - return -1; - } - - /* Setting date */ - memcpy(tmpbuf, iter, 8); - tmpbuf[8] = 0; - params[pnr + 2] = "date"; - params[pnr + 3] = strdup(tmpbuf); - - /* Setting time, gotta prepend it with 1 to - * avoid octal parsing (this is stripped out in - * XSLT */ - tmpbuf[0] = '1'; - memcpy(tmpbuf + 1, iter + 8, 6); - tmpbuf[7] = 0; - params[pnr + 4] = "time"; - params[pnr + 5] = strdup(tmpbuf); - params[pnr + 6] = NULL; - - ptr = strstr(ptr, "ZDP{"); - if (ptr && ptr[4] == '}') { - end_ptr += ptr - (char *)mem_csv.buffer; - return report_error(translate("gettextFromC", "No dive profile found from '%s'"), filename); - } - if (ptr) - ptr = strstr(ptr, NL); - if (ptr) { - ptr += strlen(NL); - } else { - fprintf(stderr, "DEBUG: Data corrupt"); - return -1; - } - end_ptr = ptr - (char *)mem.buffer; - - /* Copy the current dive data to start of mem_csv buffer */ - memcpy(mem_csv.buffer, ptr, mem.size - (ptr - (char *)mem.buffer)); - ptr = strstr(mem_csv.buffer, "ZDP}"); - if (ptr) { - *ptr = 0; - } else { - fprintf(stderr, "DEBUG: failed to find end ZDP\n"); - return -1; - } - mem_csv.size = ptr - (char*)mem_csv.buffer; - - if (try_to_xslt_open_csv(filename, &mem_csv, "csv")) - return -1; - - ret |= parse_xml_buffer(filename, mem_csv.buffer, mem_csv.size, &dive_table, (const char **)params); - end_ptr += ptr - (char *)mem_csv.buffer; - free(mem_csv.buffer); - } - - free(mem.buffer); - for (i = 0; params[i]; i += 2) - free(params[i + 1]); - - return ret; -} - -int parse_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate) -{ - int ret, i; - struct memblock mem; - time_t now; - struct tm *timep = NULL; - char tmpbuf[MAXCOLDIGITS]; - - /* Increase the limits for recursion and variables on XSLT - * parsing */ - xsltMaxDepth = 30000; -#if LIBXSLT_VERSION > 10126 - xsltMaxVars = 150000; -#endif - - if (filename == NULL) - return report_error("No CSV filename"); - - mem.size = 0; - if (!strcmp("DL7", csvtemplate)) { - return parse_dan_format(filename, params, pnr); - } else if (strcmp(params[0], "date")) { - time(&now); - timep = localtime(&now); - - strftime(tmpbuf, MAXCOLDIGITS, "%Y%m%d", timep); - params[pnr++] = "date"; - params[pnr++] = strdup(tmpbuf); - - /* As the parameter is numeric, we need to ensure that the leading zero - * is not discarded during the transform, thus prepend time with 1 */ - - strftime(tmpbuf, MAXCOLDIGITS, "1%H%M", timep); - params[pnr++] = "time"; - params[pnr++] = strdup(tmpbuf); - params[pnr++] = NULL; - } - - if (try_to_xslt_open_csv(filename, &mem, csvtemplate)) - return -1; - - /* - * Lets print command line for manual testing with xsltproc if - * verbosity level is high enough. The printed line needs the - * input file added as last parameter. - */ - -#ifndef SUBSURFACE_MOBILE - if (verbose >= 2) { - fprintf(stderr, "(echo '<csv>'; cat %s;echo '</csv>') | xsltproc ", filename); - for (i=0; params[i]; i+=2) - fprintf(stderr, "--stringparam %s %s ", params[i], params[i+1]); - fprintf(stderr, "%s/xslt/csv2xml.xslt -\n", SUBSURFACE_SOURCE); - } -#endif - ret = parse_xml_buffer(filename, mem.buffer, mem.size, &dive_table, (const char **)params); - - free(mem.buffer); - for (i = 0; params[i]; i += 2) - free(params[i + 1]); - - return ret; -} - -#define SBPARAMS 40 -int parse_seabear_log(const char *filename) -{ - char *params[SBPARAMS]; - int pnr = 0; - - pnr = parse_seabear_header(filename, params, pnr); - - if (parse_seabear_csv_file(filename, params, pnr, "csv") < 0) { - return -1; - } - - return 0; -} - -int parse_seabear_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate) -{ - int ret, i; - struct memblock mem; - time_t now; - struct tm *timep = NULL; - char *ptr, *ptr_old = NULL; - char *NL = NULL; - char tmpbuf[MAXCOLDIGITS]; - - /* Increase the limits for recursion and variables on XSLT - * parsing */ - xsltMaxDepth = 30000; -#if LIBXSLT_VERSION > 10126 - xsltMaxVars = 150000; -#endif - - time(&now); - timep = localtime(&now); - - strftime(tmpbuf, MAXCOLDIGITS, "%Y%m%d", timep); - params[pnr++] = "date"; - params[pnr++] = strdup(tmpbuf); - - /* As the parameter is numeric, we need to ensure that the leading zero - * is not discarded during the transform, thus prepend time with 1 */ - strftime(tmpbuf, MAXCOLDIGITS, "1%H%M", timep); - params[pnr++] = "time"; - params[pnr++] = strdup(tmpbuf); - - - if (filename == NULL) - return report_error("No CSV filename"); - - if (readfile(filename, &mem) < 0) - return report_error(translate("gettextFromC", "Failed to read '%s'"), filename); - - /* Determine NL (new line) character and the start of CSV data */ - ptr = mem.buffer; - while ((ptr = strstr(ptr, "\r\n\r\n")) != NULL) { - ptr_old = ptr; - ptr += 1; - NL = "\r\n"; - } - - if (!ptr_old) { - ptr = mem.buffer; - while ((ptr = strstr(ptr, "\n\n")) != NULL) { - ptr_old = ptr; - ptr += 1; - NL = "\n"; - } - ptr_old += 2; - } else - ptr_old += 4; - - /* - * If file does not contain empty lines, it is not a valid - * Seabear CSV file. - */ - if (NL == NULL) - return -1; - - /* - * On my current sample of Seabear DC log file, the date is - * without any identifier. Thus we must search for the previous - * line and step through from there. That is the line after - * Serial number. - */ - ptr = strstr(mem.buffer, "Serial number:"); - if (ptr) - ptr = strstr(ptr, NL); - - /* - * Write date and time values to params array, if available in - * the CSV header - */ - - if (ptr) { - ptr += strlen(NL) + 2; - /* - * pnr is the index of NULL on the params as filled by - * the init function. The two last entries should be - * date and time. Here we overwrite them with the data - * from the CSV header. - */ - - memcpy(params[pnr - 3], ptr, 4); - memcpy(params[pnr - 3] + 4, ptr + 5, 2); - memcpy(params[pnr - 3] + 6, ptr + 8, 2); - params[pnr - 3][8] = 0; - - memcpy(params[pnr - 1] + 1, ptr + 11, 2); - memcpy(params[pnr - 1] + 3, ptr + 14, 2); - params[pnr - 1][5] = 0; - } - - params[pnr++] = NULL; - - /* Move the CSV data to the start of mem buffer */ - memmove(mem.buffer, ptr_old, mem.size - (ptr_old - (char*)mem.buffer)); - mem.size = (int)mem.size - (ptr_old - (char*)mem.buffer); - - if (try_to_xslt_open_csv(filename, &mem, csvtemplate)) - return -1; - - /* - * Lets print command line for manual testing with xsltproc if - * verbosity level is high enough. The printed line needs the - * input file added as last parameter. - */ - - if (verbose >= 2) { - fprintf(stderr, "xsltproc "); - for (i=0; params[i]; i+=2) - fprintf(stderr, "--stringparam %s %s ", params[i], params[i+1]); - fprintf(stderr, "xslt/csv2xml.xslt\n"); - } - - ret = parse_xml_buffer(filename, mem.buffer, mem.size, &dive_table, (const char **)params); - free(mem.buffer); - for (i = 0; params[i]; i += 2) - free(params[i + 1]); - - return ret; -} - -int parse_manual_file(const char *filename, char **params, int pnr) -{ - struct memblock mem; - time_t now; - struct tm *timep; - char curdate[9]; - char curtime[6]; - int ret, i; - - - time(&now); - timep = localtime(&now); - strftime(curdate, DATESTR, "%Y%m%d", timep); - - /* As the parameter is numeric, we need to ensure that the leading zero - * is not discarded during the transform, thus prepend time with 1 */ - strftime(curtime, TIMESTR, "1%H%M", timep); - - - params[pnr++] = strdup("date"); - params[pnr++] = strdup(curdate); - params[pnr++] = strdup("time"); - params[pnr++] = strdup(curtime); - params[pnr++] = NULL; - - if (filename == NULL) - return report_error("No manual CSV filename"); - - mem.size = 0; - if (try_to_xslt_open_csv(filename, &mem, "manualCSV")) - return -1; - -#ifndef SUBSURFACE_MOBILE - if (verbose >= 2) { - fprintf(stderr, "(echo '<manualCSV>'; cat %s;echo '</manualCSV>') | xsltproc ", filename); - for (i=0; params[i]; i+=2) - fprintf(stderr, "--stringparam %s %s ", params[i], params[i+1]); - fprintf(stderr, "%s/xslt/manualcsv2xml.xslt -\n", SUBSURFACE_SOURCE); - } -#endif - ret = parse_xml_buffer(filename, mem.buffer, mem.size, &dive_table, (const char **)params); - - free(mem.buffer); - for (i = 0; i < pnr - 2; ++i) - free(params[i]); - return ret; -} |