#include <stdlib.h>
#include <string.h>
+#include <stdint.h> // C99
#include "cbook.h"
#include "cutils/cutils.h"
static void one_field(FILE *outfile, book_t *book, line_t *field, char *data);
// Convert EBCDIC to ASCII
-static void ascii(FILE *outfile, char *ebcdic, size_t sz);
+static void ascii(book_t *book, FILE *outfile, char *ebcdic, size_t sz);
+
+// Convert one car EBCDIC to ASCII
+static char ascii_car(unsigned char ebcdic);
// PUBLIC
break;
}
+ if (book->debug) {
+ fprintf(stderr, "\n");
+ for (size_t i = 0 ; i < field->bytes ; i++) {
+ char *type;
+ switch(field->type) {
+ case CBOOK_FMT_CHAR: type = "CHAR"; break;
+ case CBOOK_FMT_VARCHAR: type = "VARCHAR"; break;
+ case CBOOK_FMT_DECIMAL: type = "DEC"; break;
+ case CBOOK_FMT_UDECIMAL:type = "UDEC"; break;
+ case CBOOK_FMT_FIXED_BINARY: type= "BIN" ;break;
+ case CBOOK_FMT_UFIXED_BINARY:type= "UBIN";break;
+ case CBOOK_FMT_PICTURE: type = "PIC"; break;
+ default: type = "OTHER";
+ }
+ unsigned char byte = (unsigned char)data[i];
+ char ascii = '?';
+ if (byte >= 32 && byte <= 126)
+ ascii = byte;
+ if (book->raw_ebcdic)
+ ascii = ascii_car(byte);
+ fprintf(stderr,
+ "%s (%s) -- Byte %zu = 0x%02X : %.3i (%c)\n",
+ type, field->name, i, byte, byte, ascii
+ );
+ }
+ }
+
+
switch(field->type) {
case CBOOK_FMT_CHAR:
fwrite("\"", 1, 1, outfile);
if (book->raw_ebcdic) {
- ascii(outfile, data, field->bytes);
+ ascii(book, outfile, data, field->bytes);
fwrite(ascii_line->string, 1,
ascii_line->length, outfile);
} else {
if (str->length == dec_idx)
cstring_add_car(str, '.');
}
-
- if (book->debug) {
- if ((x1 >= 0) && (x1 <= 9))
- x1 = '0' + x1;
- else
- x1 = '?';
- if ((x2 >= 0) && (x2 <= 9))
- x2 = '0' + x2;
- else
- x2 = '?';
- if (last && field->type == CBOOK_FMT_DECIMAL) {
- if (positive == 1) x2 = '+';
- else if(positive == 0) x2 = '-';
- else x2 = '!';
- }
- fprintf(stderr, "%s -- Byte %zu = "
- "0x%02X : %.3i (%c) -> (%c,%c)\n",
- field->name, i+1, byte, byte,
- (byte>=32 && byte<=126) ? byte : '?',
- x1, x2
- );
- }
-
}
if (positive)
free_cstring(str);
break;
case CBOOK_FMT_PICTURE:
- fwrite(data, 1, field->bytes, outfile);
- if (book->debug) {
- fprintf(stderr, "\n");
- for (size_t i = 0 ; i < field->bytes ; i++) {
- unsigned char byte = (unsigned char)data[i];
- fprintf(stderr, "%s -- Byte %zu = "
- "0x%02X : %.3i "
- "(%c)\n",
- field->name, i,
- byte, byte,
- (byte>=32 && byte<=126) ? byte : '?'
- );
- }
- }
+ field->type = CBOOK_FMT_CHAR;
+ one_field(outfile, book, field, data);
+ field->type = CBOOK_FMT_PICTURE;
break;
- //TODO: the rest
case CBOOK_FMT_FIXED_BINARY:
case CBOOK_FMT_UFIXED_BINARY:
- default:
- ;
- if (book->debug) {
- fprintf(stderr, "\n");
- for (size_t i = 0 ; i < field->bytes ; i++) {
- unsigned char byte = (unsigned char)data[i];
- fprintf(stderr, "%s -- Byte %zu = "
- "0x%02X : %.3i "
- "(%c)\n",
- field->name, i,
- byte, byte,
- (byte>=32 && byte<=126) ? byte : '?'
- );
+ if (field->bytes > 8) {
+ char aa[100];
+ sprintf(aa, "%zu", field->bytes);
+ book->err_mess = cstring_concat(
+ "BINARY size unsupported: ", aa
+ );
+ break;
+ }
+
+ char o[100];
+
+ int signbit = (field->type == CBOOK_FMT_FIXED_BINARY)
+ && ((unsigned char)data[0] & 0x80);
+
+ /*
+ TODO: fix for positive values
+
+ char c[8];
+ uint64_t *i64 = (uint64_t *)(void*)c;
+ int64_t *u64 = (int64_t *)(void*)c;
+
+ if (field->type == CBOOK_FMT_FIXED_BINARY) {
+ *u64 = 0;
+ if (signbit) {
+ for (int i = 0 ; i < 8 ; i++) {
+ c[i] = (unsigned char)0xFF;
+ }
+ } else {
+ *u64 = 0;
}
+
+ memcpy(c + (8 - field->bytes), data, field->bytes);
+ sprintf(o, "%li", *i64);
+ } else {
+ *u64 = 0;
+ memcpy(c + (8 - field->bytes), data, field->bytes);
+ sprintf(o, "%lu", *u64);
+ }
+ */
+
+ size_t val = 0;
+ for (size_t i = 0 ; i < field->bytes ; i++) {
+ unsigned char byte = (unsigned char)data[i];
+ //if (!i && signbit)
+ // byte = (byte & 0x7F);
+ if (signbit)
+ byte = ~byte;
+ val = val * 256 + byte;
+ }
+
+ if (signbit) {
+ val++;
+ fwrite(&"-", 1, 1, outfile);
}
+ sprintf(o, "%zu", val);
+
+ fwrite(o, 1, strlen(o), outfile);
+ break;
+ default:
+ ;
cstring_t *tmp = new_cstring();
cstring_add(tmp, "FMT_");
cstring_add_car(tmp, '0' + field->type);
cstring_add(tmp, " is not yet supported");
book->err_mess = cstring_convert(tmp);
+
break;
}
}
-static void ascii(FILE *outfile, char *ebcdic, size_t sz) {
+static void ascii(book_t *book, FILE *outfile, char *ebcdic, size_t sz) {
/* - Professor: "So the American government went to
* IBM to come up with an encryption standard,
* and they came up with..."
for (size_t i = 0 ; i < sz ; i++) {
unsigned char byte = ebcdic[i];
- if ((byte >= 0xF0) && (byte <= 0xF9)) { /* 0 - 9 */
- cstring_add_car(ascii_line, byte - 0xC0);
- } else if ((byte >= 0xC1) && (byte <= 0xC9)) { /* A - I */
- cstring_add_car(ascii_line, byte - 0x80);
- } else if ((byte >= 0xD1) && (byte <= 0xD9)) { /* J - R */
- cstring_add_car(ascii_line, byte - 0x87);
- } else if ((byte >= 0xE2) && (byte <= 0xE9)) { /* S - Z */
- cstring_add_car(ascii_line, byte - 0x8F);
- } else if ((byte >= 0x81) && (byte <= 0x89)) { /* a - i */
- cstring_add_car(ascii_line, byte - 0x20);
- } else if ((byte >= 0x91) && (byte <= 0x99)) { /* j - r */
- cstring_add_car(ascii_line, byte - 0x27);
- } else if ((byte >= 0xA2) && (byte <= 0xA9)) { /* s - z */
- cstring_add_car(ascii_line, byte - 0x2F);
+ byte = ascii_car(byte);
+ if (byte) {
+ if (byte == '"') // double the quotes
+ cstring_add_car(ascii_line, byte);
+ cstring_add_car(ascii_line, byte);
} else {
- switch(byte) {
- case 0x40: cstring_add_car(ascii_line, ' '); break;
- case 0x4F: cstring_add_car(ascii_line, '!'); break;
- case 0x7F: // double it
- cstring_add_car(ascii_line, '"');
- cstring_add_car(ascii_line, '"');
- break;
- case 0x7B: cstring_add_car(ascii_line, '#'); break;
- case 0x5B: cstring_add_car(ascii_line, '$'); break;
- case 0x6C: cstring_add_car(ascii_line, '%'); break;
- case 0x50: cstring_add_car(ascii_line, '&'); break;
- case 0x7D: cstring_add_car(ascii_line, '\''); break;
- case 0x4D: cstring_add_car(ascii_line, '('); break;
- case 0x5D: cstring_add_car(ascii_line, ')'); break;
- case 0x5C: cstring_add_car(ascii_line, '*'); break;
- case 0x4E: cstring_add_car(ascii_line, '+'); break;
- case 0x6B: cstring_add_car(ascii_line, ','); break;
- case 0x60: cstring_add_car(ascii_line, '-'); break;
- case 0x4B: cstring_add_car(ascii_line, '.'); break;
- case 0x61: cstring_add_car(ascii_line, '/'); break;
- case 0x7A: cstring_add_car(ascii_line, ':'); break;
- case 0x5E: cstring_add_car(ascii_line, ';'); break;
- case 0x4C: cstring_add_car(ascii_line, '<'); break;
- case 0x7E: cstring_add_car(ascii_line, '='); break;
- case 0x6E: cstring_add_car(ascii_line, '>'); break;
- case 0x6F: cstring_add_car(ascii_line, '?'); break;
- case 0x7C: cstring_add_car(ascii_line, '@'); break;
- case 0x4A: cstring_add_car(ascii_line, '['); break;
- case 0xE0: cstring_add_car(ascii_line, '\\'); break;
- case 0x5A: cstring_add_car(ascii_line, ']'); break;
- case 0x5F: cstring_add_car(ascii_line, '^'); break;
- case 0x6D: cstring_add_car(ascii_line, '_'); break;
- case 0x79: cstring_add_car(ascii_line, '`'); break;
- case 0xC0: cstring_add_car(ascii_line, '{'); break;
- case 0x6A: cstring_add_car(ascii_line, '|'); break;
- case 0xD0: cstring_add_car(ascii_line, '}'); break;
- case 0xA1: cstring_add_car(ascii_line, '~'); break;
- // TODO: 0xC2A5 = 0xE0 \ (idem à 0x5C !!!)
- default:
- // 0x2117 = (P) or ℗ char
- cstring_add_car(ascii_line, 0x21);
- cstring_add_car(ascii_line, 0x17);
- break;
- }
+ // Unknown char -> 0x2117 = (P) or ℗
+ cstring_add_car(ascii_line, 0x21);
+ cstring_add_car(ascii_line, 0x17);
+
+ char bit[100];
+ sprintf(bit, "%zu", i+1);
+ char byte2[3];
+ sprintf(byte2, "%02X", byte);
+ cstring_t *tmp = new_cstring();
+ cstring_add(tmp, "Bad character: ");
+ cstring_add(tmp, "Byte ");
+ cstring_add(tmp, bit);
+ cstring_add(tmp, " = 0x");
+ cstring_add(tmp, byte2);
+ book->err_mess = cstring_convert(tmp);
}
}
}
+
+static char ascii_car(unsigned char byte) {
+ if ((byte >= 0xF0) && (byte <= 0xF9)) { /* 0 - 9 */
+ return(byte - 0xC0);
+ } else if ((byte >= 0xC1) && (byte <= 0xC9)) { /* A - I */
+ return(byte - 0x80);
+ } else if ((byte >= 0xD1) && (byte <= 0xD9)) { /* J - R */
+ return(byte - 0x87);
+ } else if ((byte >= 0xE2) && (byte <= 0xE9)) { /* S - Z */
+ return(byte - 0x8F);
+ } else if ((byte >= 0x81) && (byte <= 0x89)) { /* a - i */
+ return(byte - 0x20);
+ } else if ((byte >= 0x91) && (byte <= 0x99)) { /* j - r */
+ return(byte - 0x27);
+ } else if ((byte >= 0xA2) && (byte <= 0xA9)) { /* s - z */
+ return(byte - 0x2F);
+ } else {
+ switch(byte) {
+ case 0x40: return(' ');
+ case 0x4F: return('!');
+ case 0x7F: return('"');
+ case 0x7B: return('#');
+ case 0x5B: return('$');
+ case 0x6C: return('%');
+ case 0x50: return('&');
+ case 0x7D: return('\'');
+ case 0x4D: return('(');
+ case 0x5D: return(')');
+ case 0x5C: return('*');
+ case 0x4E: return('+');
+ case 0x6B: return(',');
+ case 0x60: return('-');
+ case 0x4B: return('.');
+ case 0x61: return('/');
+ case 0x7A: return(':');
+ case 0x5E: return(';');
+ case 0x4C: return('<');
+ case 0x7E: return('=');
+ case 0x6E: return('>');
+ case 0x6F: return('?');
+ case 0x7C: return('@');
+ case 0x4A: return('[');
+ case 0xE0: return('\\');
+ case 0x5A: return(']');
+ case 0x5F: return('^');
+ case 0x6D: return('_');
+ case 0x79: return('`');
+ case 0xC0: return('{');
+ case 0x6A: return('|');
+ case 0xD0: return('}');
+ case 0xA1: return('~');
+ default: return '\0';
+ }
+ }
+}
+