static cstring_t *ascii_line = NULL;
-// Actual write code, but may write either data or header
-static int write_line(FILE *outfile, book_t *book, cstring_t *data,
- int header, size_t lino);
-
// Write one field (including subfields), consume data and report errors
static char *write_field(FILE *outfile, book_t *book, line_t *field,
- char *data, size_t *remaining, size_t lino);
+ char *data, size_t *remaining, size_t lino, size_t fino);
// Write this one field (data is ready), report errors in book->err_mess
static void one_field(FILE *outfile, book_t *book, line_t *field, char *data);
int write_header(FILE *outfile, book_t *book) {
// Only for CSV
- if (book->out_fmt != CBOOK_OUT_CSV)
+ if ((book->out_fmt != CBOOK_OUT_CSV)
+ && (book->out_fmt != CBOOK_OUT_MSCSV))
return 1;
- return write_line(outfile, book, NULL, 1, 0);
-}
-
-int write_csv(FILE *outfile, book_t *book, cstring_t *data, size_t lino) {
- return write_line(outfile, book, data, 0, lino);
+ return write_line(outfile, book, NULL, 0);
}
void write_done() {
ascii_line = NULL;
}
-// PRIVATE
-
-static int write_line(FILE *outfile, book_t *book, cstring_t *dataline,
- int header, size_t lino) {
+int write_line(FILE *outfile, book_t *book, cstring_t *dataline, size_t lino) {
size_t remaining = 0;
char *data = NULL;
data = dataline->string;
}
- int first = 1;
array_loop(book->lines, field, line_t *) {
- if (!first) {
- switch(book->out_fmt) {
- case CBOOK_OUT_CSV : fwrite(",", 1,1,outfile); break;
- case CBOOK_OUT_FIELDS: fwrite("\n", 1,1,outfile); break;
- }
- }
- first = 0;
-
- if (header) {
- char *n = (*field)->name;
- if (n)
- fwrite(n, strlen(n), 1, outfile);
- } else {
- data = write_field(outfile, book, *field, data,
- &remaining, lino);
- }
+ // Works for data (lino > 0) and header (lino == 0)
+ data = write_field(outfile, book, *field, data,
+ &remaining, lino, 0);
if (book->err_mess) {
book->err_line = lino;
return 1;
}
+// PRIVATE
+
static char *write_field(FILE *outfile, book_t *book, line_t *field,
- char *data, size_t *remaining, size_t lino) {
+ char *data, size_t *remaining, size_t lino, size_t fino) {
if (field->type == CBOOK_FMT_GROUP) {
- array_loop(field->children, subfield, line_t *) {
- data = write_field(outfile, book, *subfield,
- data, remaining, lino);
- if (book->err_mess)
- return 0;
+ for (size_t i = 0 ; i < field->tab ; i++) {
+ array_loop(field->children, subfield, line_t *) {
+ data = write_field(outfile, book, *subfield,
+ data, remaining, lino, i + 1);
+ if (book->err_mess)
+ return 0;
+ }
}
return data;
}
+
+ int first = (field == *((line_t **)array_first(book->lines)));
+ if (!first) {
+ switch(book->out_fmt) {
+ case CBOOK_OUT_CSV : fwrite(",", 1,1,outfile); break;
+ case CBOOK_OUT_MSCSV : fwrite(";", 1,1,outfile); break;
+ case CBOOK_OUT_FIELDS: fwrite("\n", 1,1,outfile); break;
+ }
+ }
- if (*remaining >= field->bytes) {
+ if (!lino) {
+ // Header
+ char *n = field->name;
+ if (n)
+ fwrite(n, 1, strlen(n), outfile);
+
+ // TODO: find a way to support multiple levels deep
+ if (fino) {
+ char tab[100];
+ sprintf(tab, "%zu", fino);
+ fwrite("(", 1, 1, outfile);
+ fwrite(tab, 1, strlen(tab), outfile);
+ fwrite(")", 1, 1, outfile);
+ }
+ } else if (*remaining >= field->bytes) {
char car = data[field->bytes];
data[field->bytes] = '\0';
switch(book->out_fmt) {
case CBOOK_OUT_CSV : break;
+ case CBOOK_OUT_MSCSV: break;
case CBOOK_OUT_FIELDS:
fwrite(field->name, 1, strlen(field->name), outfile);
fwrite(": ", 1, 2, outfile);
break;
case CBOOK_FMT_VARCHAR:
- // first 2 bytes -> BIN FIXED(15)
;
- // TODO:
- size_t coded = field->bytes - 2;
-
+ // first 2 bytes -> BIN FIXED(15)
+ size_t coded = 0;
+ coded = (unsigned char)data[0] * 256
+ + (unsigned char)data[1];
data = data + 2;
+
if (coded > (field->bytes - 2)) {
char buf[100];
sprintf(buf, "%zu", coded);
char *input = NULL;
char *output = NULL;
- CBOOK_OUT out_fmt = CBOOK_OUT_CSV;
+ CBOOK_OUT out_fmt = CBOOK_OUT_MSCSV;
int ignore_errors = 0;
int debug = 0;
int raw_ebcdic = 0;
char *arg = argv[i];
if (!strcmp("--debug", arg) || !strcmp("-d", arg)) {
debug = 1;
+ } else if (!strcmp("--output-csv", arg) || !strcmp("-c", arg)){
+ out_fmt = CBOOK_OUT_CSV;
+ } else if (!strcmp("--output-ms", arg) || !strcmp("-m", arg)){
+ out_fmt = CBOOK_OUT_MSCSV;
} else if (!strcmp("--output-flat", arg) || !strcmp("-o", arg)){
out_fmt = CBOOK_OUT_FIELDS;
} else if (!strcmp("--raw-ebcdic", arg) || !strcmp("-r", arg)) {
return 5;
}
if (book_filename) {
- fprintf(stderr, "Syntax error\n");
+ fprintf(stderr,"Syntax error (try '--help')\n");
return 5;
}
book_filename = argv[++i];
} else if (input && output) {
- fprintf(stderr, "Syntax error\n");
+ fprintf(stderr, "Syntax error (try '--help')\n");
return 5;
} else if (input) {
output = argv[i];
}
if (!book_filename) {
- fprintf(stderr, "Syntax error\n");
+ fprintf(stderr, "Syntax error (try '--help')\n");
return 5;
}
cstring_t *line = new_cstring();
int write_ok = 1;
while(readline(book, line, infile, ++lino)) {
- if (!write_csv(outfile, book, line, lino)) {
+ if (!write_line(outfile, book, line, lino)) {
write_ok = 0;
break;
}
printf("\t%s --b BOOK.PLI (IN.DATA (OUT.CSV))\n", program);
printf("\n");
printf("Parameters:\n");
- printf("\t> --help (or -h): this help message\n");
- printf("\t> BOOK.PLI: a data description include book (in PL/1)\n");
- printf("\t> IN.DATA: the text/binary input file, defaults to stdin\n");
- printf("\t> OUT.CSV: the CSV output file, defaults to stdout\n");
+ printf("\t-h / --help : this help message\n");
+ printf("\t-o / --output-flat : output is one line per field\n");
+ printf("\t-m / --output-ms : output is Microsoft CSV (default)\n");
+ printf("\t-c / --output-csv : output is CSV\n");
+ printf("\t-d / --debug : add lot of DEBUG information\n");
+ printf("\t-i / --ignore-errors : ignore errors and continue\n");
+ printf("\t-r / --raw-ebcdic : consider input to be raw EBCDIC\n");
+ printf("\tBOOK.PLI : a data description include book (in PL/1)\n");
+ printf("\tIN.DATA : the text/binary input file, defaults to stdin\n");
+ printf("\tOUT.CSV : the CSV output file, defaults to stdout\n");
}
line_t *process_line(book_t *book, const char data[]);
/* Reorder the lines inside the book according to their level */
-void reorder_lines(book_t *book);
+array_t *reorder_lines(array_t *lines);
+
+/* Compute the total size of all the given lines */
+size_t compute_size(array_t *lines);
/* Util: get the first word found in the given string */
char *get_word(char *line);
}
}
- // Compute only the first level (reorder_lines must ensure that
- // the size of sublevels are reported to higher levels)
- book->bytes = 0;
- array_loop(book->lines, line, line_t *) {
- book->bytes += (*line)->bytes;
- }
-
if (book->debug) {
fprintf(stderr, "Book has a size of: %zu bytes\n", book->bytes);
}
- reorder_lines(book);
+ book->lines = reorder_lines(book->lines);
+ book->bytes = compute_size(book->lines);
return 1;
}
size_t i;
cstring_t *str = new_cstring();
line_t *line = calloc(1, sizeof(line_t));
+ line->tab = 1; // default
line->children = new_array(sizeof(line_t *), 20);
// Copy of data
return line;
}
+size_t compute_size(array_t *lines) {
+ size_t sz = 0;
+
+ array_loop(lines, line, line_t *) {
+ if ((*line)->type == CBOOK_FMT_GROUP) {
+ (*line)->bytes = compute_size((*line)->children);
+ }
+
+ sz += (*line)->bytes;
+ }
+
+ return sz;
+}
+
+array_t *reorder_lines(array_t *lines) {
+ int change = 1;
+ line_t **prev = NULL;
+ array_t *tmp = new_array(sizeof(line_t *), 20);
+ while (change) {
+ change = 0;
+ array_loop(lines, line, line_t *) {
+ if (prev && *prev && (*line)-> level > (*prev)->level) {
+ array_push((*prev)->children, line);
+ change = 1;
+ } else {
+ array_push(tmp, line);
+ }
+
+ prev = line;
+ }
+ array_t *aroo = lines;
+ lines = tmp;
+ tmp = aroo;
+
+ array_cut_at(tmp, 0);
+ }
+ free_array(tmp);
+
+ array_loop(lines, line, line_t *) {
+ (*line)->children = reorder_lines((*line)->children);
+ }
-void reorder_lines(book_t *book) {
- // TODO
+ return lines;
}
char *get_word(char *line) {