working version (All but BIT)
authorNiki <david.roulet@solidaris.be>
Tue, 25 Jun 2024 14:57:16 +0000 (16:57 +0200)
committerNiki <david.roulet@solidaris.be>
Tue, 25 Jun 2024 14:57:16 +0000 (16:57 +0200)
src/cbook/cbook_csv.c
src/cbook/cbook_pl1.c
src/cutils

index 135922d5204f1da3db7ed2d4688952d946404c4f..8bbdc13faffe28b6b36dff7385164c97de2ca63e 100755 (executable)
@@ -19,6 +19,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h> // C99
 
 #include "cbook.h"
 #include "cutils/cutils.h"
@@ -40,7 +41,10 @@ static char *write_field(FILE *outfile, book_t *book, line_t *field,
 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
 
@@ -169,11 +173,39 @@ static void one_field(FILE *outfile, book_t *book, line_t *field, char *data) {
                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 {
@@ -288,29 +320,6 @@ static void one_field(FILE *outfile, book_t *book, line_t *field, char *data) {
                                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)
@@ -323,50 +332,84 @@ static void one_field(FILE *outfile, book_t *book, line_t *field, char *data) {
                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..."
@@ -380,65 +423,83 @@ static void ascii(FILE *outfile, char *ebcdic, size_t sz) {
 
        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';
+               }
+       }
+}
+
index b8309c0dafbde5ad3eb29925de8fee46db950024..643358a4a215d7c6563103a8a1483d4528aaebb2 100755 (executable)
@@ -177,11 +177,17 @@ skip:
                }
        }
        
+       // 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);
 
        return 1;
@@ -748,22 +754,23 @@ CBOOK_FORMAT format(char *text, char **pic_fmt) {
                        return CBOOK_FMT_ERROR;
                }
                
-               // Only BINARY and DECIMAL have a sign in those we support
-               if ((sign || unsign)
-                               && fmt != CBOOK_FMT_DECIMAL
-                               && fmt != CBOOK_FMT_FIXED_BINARY) {
-                       return CBOOK_FMT_ERROR;
-               }
-               
-               // Manage the UNISGNED variants
-               if (unsign && fmt == CBOOK_FMT_DECIMAL)
-                       fmt = CBOOK_FMT_UDECIMAL;
-               if (unsign && fmt == CBOOK_FMT_FIXED_BINARY)
-                       fmt = CBOOK_FMT_UFIXED_BINARY;
-
                prev = fmt;
        }
 
+       // Only BINARY and DECIMAL have a sign in those we support
+       if ((sign || unsign)
+                       && fmt != CBOOK_FMT_DECIMAL
+                       && fmt != CBOOK_FMT_FIXED_BINARY) {
+               return CBOOK_FMT_ERROR;
+       }
+       
+       // Manage the UNISGNED variants
+       if (unsign && fmt == CBOOK_FMT_DECIMAL)
+               fmt = CBOOK_FMT_UDECIMAL;
+       if (unsign && fmt == CBOOK_FMT_FIXED_BINARY)
+               fmt = CBOOK_FMT_UFIXED_BINARY;
+
+
        if (var) {
                if (fmt != CBOOK_FMT_CHAR) {
                        return CBOOK_FMT_ERROR;
index 6e1a12739841bc4f7d4e5a2fc8b36d72fc0e8cb2..0dbfba1b2c91562142588c6ebf0538233eccd1ef 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6e1a12739841bc4f7d4e5a2fc8b36d72fc0e8cb2
+Subproject commit 0dbfba1b2c91562142588c6ebf0538233eccd1ef