diff --git a/include/libg1m.h b/include/libg1m.h index f517b29..dbaae6c 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -19,8 +19,9 @@ * WARNING: Do NOT include this header using ! * * Compile using one of these: - * libg1m-config --cflags - * pkg-config libg1m --cflags + * + * libg1m-config --cflags + * pkg-config libg1m --cflags * * and include using . * ************************************************************************** */ @@ -73,9 +74,10 @@ extern const char *g1m_error_strings[]; /* ************************************************************************** */ /* Main functions */ /* ************************************************************************** */ -/* open a handle */ +/* open and free a handle */ int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer, g1m_type_t expected_type); +void g1m_free(g1m_t *handle); /* open a handle using FILEs */ #ifndef G1M_DISABLED_FILE @@ -85,8 +87,13 @@ int g1m_fopen(g1m_t **handle, const char *path, FILE *stream, g1m_type_t expected_type); #endif +/* ************************************************************************** */ +/* Main MCS functions */ +/* ************************************************************************** */ /* make an MCS file out of a head */ int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead); +int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, g1m_mcshead_t *heads); +void g1m_free_mcsfile(g1m_mcsfile_t *handle); /* open MCS head for decoding, correct it for encoding */ int g1m_decode_mcsfile_head(g1m_mcshead_t *head, @@ -103,19 +110,18 @@ int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle, /* open CAS head for decoding * -------------------------- - * if the head corresponds to something you want as a file (e.g. g1m_mcstype_end - * then you should make the file using `g1m_make_mcsfile`, and call - * `g1m_decode_casfile_part` while the `g1m_mcsflag_unfinished` flag is set. + * if the head corresponds to something you want as a file (e.g. + * not `g1m_mcstype_end`), then you should make the file using + * `g1m_make_mcsfile`, and call `g1m_decode_casfile_part` while the + * `g1m_mcsflag_unfinished` flag is set. * Warning: there could be no parts to read! (e.g. unset variable) */ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer); +int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads, + g1m_buffer_t *buffer); int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer); -/* free handles */ -void g1m_free(g1m_t *handle); -void g1m_free_mcsfile(g1m_mcsfile_t *handle); - /* ************************************************************************** */ -/* MCS file manipulation */ +/* MCS archive management */ /* ************************************************************************** */ /* add MCS files */ int g1m_putmcs_program(g1m_t *handle, g1m_mcsfile_t **pfile, diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index 10a7c27..d0d36fe 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -146,9 +146,13 @@ G1M_MCSFUNC(string) /* ************************************************************************** */ # define G1M_CASFUNC(NAME) \ int g1m_decode_caspart_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer); +# define G1M_CASHFUNC(NAME) \ +int g1m_decode_cashpart_##NAME(g1m_mcshead_t *head, g1m_mcshead_t *heads, \ + g1m_buffer_t *buffer); G1M_CASFUNC(var) G1M_CASFUNC(program) +G1M_CASHFUNC(program) /* ************************************************************************** */ /* Picture utilities */ /* ************************************************************************** */ @@ -171,7 +175,6 @@ G1M_CASFUNC(program) G1M_PROTOTYPE_PIX(packed1bit) G1M_PROTOTYPE_PIX(packed4bits) G1M_PROTOTYPE_PIX(16bits) - /* ************************************************************************** */ /* Utilities */ /* ************************************************************************** */ @@ -180,7 +183,6 @@ int g1m_make_mcs(g1m_t **h); /* Free-ing */ void g1m_free_content(g1m_t *handle); -void g1m_free_mcsfile_content(g1m_mcsfile_t *handle); void g1m_free_mcs(g1m_t *handle); void g1m_free_line_content(g1m_line_t *line); diff --git a/include/libg1m/mcs.h b/include/libg1m/mcs.h index c21bd49..a7a7751 100644 --- a/include/libg1m/mcs.h +++ b/include/libg1m/mcs.h @@ -81,16 +81,17 @@ typedef struct g1m_mcs_cell_s { /* ************************************************************************** */ /* mcs file head flags */ # define g1m_mcsflag_unfinished 0x8000 /* is there still parts to read? */ +# define g1m_mcsflag_multiple 0x4000 /* is a group */ # define g1m_mcsflag_complex 0x0001 /* is a complex variable */ /* mcs file type -- what type of raw information is there * e.g. `head.flags & g1m_mcsmask_info == g1m_mcsinfo_g1m` */ # define g1m_mcsinfo(H) ((H)->flags & g1m_mcsmask_info) -# define g1m_mcsmask_info 0x6000 +# define g1m_mcsmask_info 0x0600 # define g1m_mcsinfo_none 0x0000 -# define g1m_mcsinfo_mcs 0x2000 -# define g1m_mcsinfo_cas 0x4000 -# define g1m_mcsinfo_caspro 0x6000 +# define g1m_mcsinfo_mcs 0x0200 +# define g1m_mcsinfo_cas 0x0400 +# define g1m_mcsinfo_caspro 0x0600 /* mcs file head */ typedef struct g1m_mcshead_s { diff --git a/src/core/free.c b/src/core/free.c index 0603c32..66d605c 100644 --- a/src/core/free.c +++ b/src/core/free.c @@ -41,60 +41,6 @@ void g1m_free_line_content(g1m_line_t *line) } } -/** - * g1m_free_mcsfile_content: - * Free an MCS file handle content. - * - * @arg handle the handle which has the content to free. - */ - -void g1m_free_mcsfile_content(g1m_mcsfile_t *handle) -{ - unsigned int type = handle->head.type; - - /* free content for unknown files */ - if (!type) - free(handle->content); - - /* free cells */ - if (type & (g1m_mcstype_mat | g1m_mcstype_vct | g1m_mcstype_list - | g1m_mcstype_spreadsheet) - && handle->head.width && handle->head.height) { - free(handle->cells[0]); - free(handle->cells); - } - - /* free the images */ - if ((type & (g1m_mcstype_pict | g1m_mcstype_capt))) { - for (int i = 0; i < handle->head.count; i++) - free(handle->pics[i]); - if (handle->pics != &handle->pic) - free(handle->pics); - } - - /* free the vars */ - if ((type & g1m_mcstype_alphamem) - && handle->vars != &handle->var) - free(handle->vars); - - /* free the content */ - if (type & (g1m_mcstype_program | g1m_mcstype_setup)) - free(handle->content); -} - -/** - * g1m_free_mcsfile: - * Free an MCS file handle. - * - * @arg handle the handle to free. - */ - -void g1m_free_mcsfile(g1m_mcsfile_t *handle) -{ - g1m_free_mcsfile_content(handle); - free(handle); -} - /** * g1m_free_mcs: * Free all of the MCS. diff --git a/src/decode/cas.c b/src/decode/cas.c index 5fd579b..6e0f18b 100644 --- a/src/decode/cas.c +++ b/src/decode/cas.c @@ -21,24 +21,32 @@ * ************************************************************************** */ #include #define FUNC(NAME) g1m_decode_caspart_##NAME +#define HFUNC(NAME) g1m_decode_cashpart_##NAME +#define READCOLON() { \ + uint8_t colon; GREAD(&colon, 1) \ + err = g1m_error_magic; \ + if (colon != ':') goto fail; } /* ************************************************************************** */ /* Type correspondance list */ /* ************************************************************************** */ /* Part parsing function type */ typedef int (*cas_decode_function)(g1m_mcsfile_t*, g1m_buffer_t*); +typedef int (*cas_heads_decode_function)(g1m_mcshead_t *head, + g1m_mcshead_t *heads, g1m_buffer_t *buffer); /* Correspondance type */ struct cas_corresp { unsigned int type; cas_decode_function decode; + cas_heads_decode_function hdecode; }; /* All correspondances */ -#define TTERM {0, NULL} +#define TTERM {0, NULL, NULL} static struct cas_corresp cas_types[] = { - {g1m_mcstype_var, FUNC(var)}, - {g1m_mcstype_program, FUNC(program)}, + {g1m_mcstype_var, FUNC(var), NULL}, + {g1m_mcstype_program, FUNC(program), HFUNC(program)}, TTERM }; @@ -50,7 +58,7 @@ static struct cas_corresp cas_types[] = { * @return the function (NULL if not found). */ -static cas_decode_function lookup_cas_decode(g1m_mcstype_t type) +static void *lookup_cas_decode(g1m_mcstype_t type, int heads) { /* lookup for the type */ struct cas_corresp *c = cas_types; @@ -61,7 +69,7 @@ static cas_decode_function lookup_cas_decode(g1m_mcstype_t type) } /* return the function */ - return (c->decode); + return (heads ? (void*)c->hdecode : (void*)c->decode); } /* ************************************************************************** */ @@ -126,6 +134,7 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) { /* check that the head exists */ if (!head) return (-1); + memset(head, 0, sizeof(g1m_mcshead_t)); /* read beginning of the header, try to guess a newer header */ uint8_t buf[49]; READ(buf, 7) @@ -160,6 +169,30 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) /* ************************************************************************** */ /* Part decoding functions */ /* ************************************************************************** */ +/** + * g1m_decode_casfiles_part: + * Decode the CASIOLINK group parts. + * + * @arg head the general head. + * @arg heads the heads to contribute to. + * @arg buffer the buffer to read from. + * @return the error that occurred (0 if ok). + */ + +int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads, + g1m_buffer_t *buffer) +{ + /* look for the decoding function */ + cas_heads_decode_function decode = (void*)lookup_cas_decode(head->type, 1); + if (!decode) { + log_error("No dedicated decoding function was found for this type!"); + return (g1m_error_unknown); + } + + /* decode the part */ + return ((*decode)(head, heads, buffer)); +} + /** * g1m_decode_casfile_part: * Decode a CASIOLINK Protocol content part. @@ -175,7 +208,7 @@ int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer) if (!file) return (g1m_error_op); /* look for the decoding function */ - cas_decode_function decode = lookup_cas_decode(file->head.type); + cas_decode_function decode = (void*)lookup_cas_decode(file->head.type, 0); if (!decode) { log_error("No dedicated decoding function was found for this type!"); return (g1m_error_unknown); @@ -192,7 +225,8 @@ int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer) * g1m_decode_cas: * Decode a CAS file. TODO. * - * The colon ':' (0x3A) is already read at this point. + * Is also sort of a guide for using the CAS MCS files. + * The colon ':' (0x3A) is already read at this point (CAS file id.). * * @arg handle the handle to create. * @arg buffer the buffer to read from. @@ -213,14 +247,32 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer, /* read each */ for (handle->count = 0;;) { /* read the head */ - log_info("Reading file head #%d", handle->count); - g1m_mcshead_t head; + log_info("Reading the next head."); + g1m_mcshead_t head = {}; if ((err = g1m_decode_casfile_head(&head, buffer))) goto fail; if (head.type == g1m_mcstype_end) break; + /* heads up! */ + int numheads = head.flags & g1m_mcsflag_multiple ? head.count : 1; + g1m_mcshead_t heads[numheads]; + if (head.flags & g1m_mcsflag_multiple) { + log_info("Is a head for multiple files!"); + g1m_prepare_mcsfile_heads(&head, heads); + while (head.flags & g1m_mcsflag_unfinished) { + READCOLON() + + /* decode a general part */ + err = g1m_decode_casfiles_part(&head, heads, buffer); + if (err) goto fail; + } + } else + heads[0] = head; + /* prepare space in the index */ - if (handle->count == handle->_size) { - int newsize = handle->_size + 4; + int required_size = handle->count + + (head.flags & g1m_mcsflag_multiple) ? head.count : 1; + if (required_size > handle->_size) { + int newsize = required_size + 2; log_info("index not big enough, allocating from %d to %d slots", handle->_size, newsize); @@ -238,33 +290,31 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer, handle->_size = newsize; } - /* prepare the file */ - log_info("Preparing the file."); - err = g1m_make_mcsfile(&handle->files[handle->count], &head); - if (err) goto fail; - - /* read each part */ - g1m_mcsfile_t *file = handle->files[handle->count]; handle->count++; -#if LOGLEVEL <= ll_info - for (int j = 1; file->head.flags & g1m_mcsflag_unfinished; j++) { -#else - while (file->head.flags & g1m_mcsflag_unfinished) { -#endif - log_info("Reading part #%d", j); - /* read the colon */ - uint8_t colon; GREAD(&colon, 1) - err = g1m_error_magic; - if (colon != ':') goto fail; - - /* read the part */ - err = g1m_decode_casfile_part(file, buffer); + for (int i = 0; i < numheads; i++) { + /* prepare the file */ + log_info("Preparing the group file #%d", i); + err = g1m_make_mcsfile(&handle->files[handle->count], &heads[i]); if (err) goto fail; + g1m_mcsfile_t *file = handle->files[handle->count]; handle->count++; + + /* read each part */ +#if LOGLEVEL <= ll_info + for (int j = 1; file->head.flags & g1m_mcsflag_unfinished; j++) { +#else + while (file->head.flags & g1m_mcsflag_unfinished) { +#endif + /* initialize */ + log_info("Reading part #%d", j); + READCOLON() + + /* read the part */ + err = g1m_decode_casfile_part(file, buffer); + if (err) goto fail; + } } /* read first colon of the next part */ - err = g1m_error_magic; - uint8_t nextcolon; GREAD(&nextcolon, 1) - if (nextcolon != ':') goto fail; + READCOLON() } /* everything went well :) */ diff --git a/src/decode/mcs/matrix.c b/src/decode/mcs/matrix.c index 7ae493c..98e54d9 100644 --- a/src/decode/mcs/matrix.c +++ b/src/decode/mcs/matrix.c @@ -80,11 +80,18 @@ int g1m_decode_mcs_matrix(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, for (uint_fast32_t y = 0; y < h; y++) for (uint_fast32_t x = 0; x < w; x++) { g1m_bcdtoa(&tab[y][x].real, rbuf, G1M_BCD_GOODBUFSIZE); + if (g1m_bcd_has_special(&tab[y][x].real)) { - g1m_bcdtoa(&tab[y][x].imgn, ibuf, G1M_BCD_GOODBUFSIZE); - log_info("[%" PRIuFAST32 "] %si + %s", y, ibuf, rbuf); + g1m_bcd_t ibcd = tab[y][x].imgn; + int ch = g1m_bcd_is_negative(&ibcd) ? '-' : '+'; + ibcd.flags &= ~g1m_bcdflag_neg; + + g1m_bcdtoa(&ibcd, ibuf, G1M_BCD_GOODBUFSIZE); + log_info("[%" PRIuFAST32 "][%" PRIuFAST32 "] %s %c %si", + y, x, rbuf, ch, ibuf); } else - log_info("[%" PRIuFAST32 "] %s", y, rbuf); + log_info("[%" PRIuFAST32 "][%" PRIuFAST32 "] %s", + y, x, rbuf); } #endif diff --git a/src/decode/mcs/program.c b/src/decode/mcs/program.c index 3368abe..3d61ad2 100644 --- a/src/decode/mcs/program.c +++ b/src/decode/mcs/program.c @@ -59,6 +59,41 @@ fail: return (err); } +/** + * g1m_decode_cashpart_program: + * Decode a CAS heads program part. + * + * @arg head the general head. + * @arg heads the heads to contribute to. + * @arg buffer the buffer to read from. + * @return the error code (0 if ok). + */ + +int g1m_decode_cashpart_program(g1m_mcshead_t *head, g1m_mcshead_t *heads, + g1m_buffer_t *buffer) +{ + /* get content */ + struct cas_spe_program headers[head->count]; + READ(headers, sizeof(struct cas_spe_program) * head->count) + + /* check the sum */ + uint8_t checksum; READ(&checksum, 1) + uint8_t csum = ~g1m_checksum8(headers, + sizeof(struct cas_spe_program) * head->count) + 1; + if (csum != checksum) + return (g1m_error_checksum); + + /* initialize */ + for (int i = 0; i < head->count; i++) { + heads[i].size = be16toh(headers[i].length); + /* program type? */ + } + + /* everything went well :D */ + head->flags &= ~g1m_mcsflag_unfinished; + return (0); +} + /** * g1m_decode_caspart_program: * Decode a CAS program part. diff --git a/src/manage/mcs.c b/src/manage/mcs.c index e152e70..6aa44c4 100644 --- a/src/manage/mcs.c +++ b/src/manage/mcs.c @@ -19,108 +19,6 @@ #include #define MCS_CHUNK_SIZE 16 -/* ************************************************************************** */ -/* Allocate files and content */ -/* ************************************************************************** */ -/** - * g1m_make_mcsfile: - * Make an MCS file out of a head. - * - * Will allocate all of the required parts of the MCS file for it to be - * filled later. - * - * @arg handle the file to allocate. - * @arg rawhead the head to use. - * @return the error (if any). - */ - -int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead) -{ - /* allocate the handle */ - *handle = malloc(sizeof(g1m_mcsfile_t)); - if (!handle) return (g1m_error_alloc); - g1m_mcsfile_t *h = *handle; - memset(h, 0, sizeof(g1m_mcsfile_t)); - - /* copy the head */ - memcpy(&h->head, rawhead, sizeof(g1m_mcshead_t)); - g1m_mcshead_t *head = &h->head; - - /* act differently according to the context */ - switch (head->type) { - case g1m_mcstype_list: case g1m_mcstype_mat: case g1m_mcstype_vct: - case g1m_mcstype_ssheet: - log_info("Preparing %d*%d matrix", head->width, head->height); - unsigned int wd = head->width, ht = head->height; - if (wd && ht) { - h->cells = malloc(sizeof(g1m_mcs_cell_t*) * ht); - if (!h->cells) goto fail; - h->cells[0] = malloc(sizeof(g1m_mcs_cell_t) * wd * ht); - if (!h->cells[0]) { free(h->cells); goto fail; } - - for (unsigned int y = 1; y < ht; y++) - h->cells[y] = &h->cells[0][h->head.width * y]; - } - break; - - case g1m_mcstype_var: - if (head->count <= 1) h->vars = &h->var; - else { - h->vars = malloc(sizeof(g1m_mcs_cell_t) * head->count); - if (!h->vars) goto fail; - memset(h->vars, 0, sizeof(g1m_mcs_cell_t) * head->count); - } - break; - - case g1m_mcstype_pict: case g1m_mcstype_capt: - /* set count */ - head->count = (head->type == g1m_mcstype_pict) ? 2 : 1; - - /* allocate directory */ - if (head->count <= 1) h->pics = &h->pic; - else { - h->pics = malloc(sizeof(uint32_t**) * head->count); - if (!h->pics) goto fail; - } - - /* allocate */ - for (int i = 0; i < head->count; i++) { - h->pics[i] = alloc_pixels(head->width, head->height); - if (!h->pics[i]) { - for (int j = 0; j < i; j++) - free(h->pics[j]); - if (h->pics != &h->pic) - free(h->pics); - goto fail; - } - } - - /* prepare */ - for (int i = 0; i < head->count; i++) - prepare_pixels(h->pics[i], head->width, head->height) - break; - - case g1m_mcstype_end: - break; - - /* those are TEMPORARY XXX */ - case g1m_mcstype_string: - break; - - default: - h->content = malloc(head->size); - if (!h->content) goto fail; - break; - } - - /* finish */ - return (0); -fail: - free(h); - *handle = NULL; - return (g1m_error_alloc); -} - /* ************************************************************************** */ /* Internal functions */ /* ************************************************************************** */ diff --git a/src/manage/mcsfile.c b/src/manage/mcsfile.c new file mode 100644 index 0000000..4b4d69c --- /dev/null +++ b/src/manage/mcsfile.c @@ -0,0 +1,190 @@ +/* ***************************************************************************** + * manage/mcsfile.c -- manage an MCS file. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#include + +/** + * g1m_make_mcsfile: + * Make an MCS file out of a head. + * + * Will allocate all of the required parts of the MCS file for it to be + * filled later. + * + * @arg handle the file to allocate. + * @arg rawhead the head to use. + * @return the error (if any). + */ + +int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead) +{ + /* allocate the handle */ + *handle = malloc(sizeof(g1m_mcsfile_t)); + if (!handle) return (g1m_error_alloc); + g1m_mcsfile_t *h = *handle; + memset(h, 0, sizeof(g1m_mcsfile_t)); + + /* copy the head */ + memcpy(&h->head, rawhead, sizeof(g1m_mcshead_t)); + g1m_mcshead_t *head = &h->head; + + switch (head->type) { + /* allocate the cells */ + case g1m_mcstype_list: case g1m_mcstype_mat: case g1m_mcstype_vct: + case g1m_mcstype_ssheet: + log_info("Preparing %d*%d matrix", head->width, head->height); + unsigned int wd = head->width, ht = head->height; + if (wd && ht) { + h->cells = malloc(sizeof(g1m_mcs_cell_t*) * ht); + if (!h->cells) goto fail; + h->cells[0] = malloc(sizeof(g1m_mcs_cell_t) * wd * ht); + if (!h->cells[0]) { free(h->cells); goto fail; } + + for (unsigned int y = 1; y < ht; y++) + h->cells[y] = &h->cells[0][h->head.width * y]; + } + break; + + /* allocate the variables */ + case g1m_mcstype_alphamem: + if (head->count <= 1) h->vars = &h->var; + else { + h->vars = malloc(sizeof(g1m_mcs_cell_t) * head->count); + if (!h->vars) goto fail; + memset(h->vars, 0, sizeof(g1m_mcs_cell_t) * head->count); + } + break; + + /* allocate the set of pixels */ + case g1m_mcstype_pict: case g1m_mcstype_capt: + /* set count */ + head->count = (head->type == g1m_mcstype_pict) ? 2 : 1; + + /* allocate directory */ + if (head->count <= 1) h->pics = &h->pic; + else { + h->pics = malloc(sizeof(uint32_t**) * head->count); + if (!h->pics) goto fail; + } + + /* allocate */ + for (int i = 0; i < head->count; i++) { + h->pics[i] = alloc_pixels(head->width, head->height); + if (!h->pics[i]) { + for (int j = 0; j < i; j++) + free(h->pics[j]); + if (h->pics != &h->pic) + free(h->pics); + goto fail; + } + } + + /* prepare */ + for (int i = 0; i < head->count; i++) + prepare_pixels(h->pics[i], head->width, head->height) + break; + + /* allocate nothing */ + case g1m_mcstype_end: + case g1m_mcstype_string: /* TEMPORARY XXX */ + break; + + /* allocate raw content */ + default: + h->content = malloc(head->size); + if (!h->content) goto fail; + break; + } + + /* finish */ + return (0); +fail: + free(h); + *handle = NULL; + return (g1m_error_alloc); +} + +/** + * g1m_prepare_mcsfile_heads: + * Prepare the heads from a general head. + * + * @arg head the main head. + * @arg heads the heads to prepare. + * @return the error (if any). + */ + +int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, g1m_mcshead_t *heads) +{ + /* check if the head is a multiple head */ + if (~head->flags & g1m_mcsflag_multiple) return (g1m_error_op); + + /* copy the data in each head */ + for (int i = 0; i < head->count; i++) { + heads[i] = *head; + heads[i].flags &= ~g1m_mcsflag_multiple; + } + + /* no error */ + return (0); +} + +/** + * g1m_free_mcsfile: + * Free an MCS file handle content. + * + * @arg handle the handle which has the content to free. + */ + +void g1m_free_mcsfile(g1m_mcsfile_t *handle) +{ + switch (handle->head.type) { + /* free the cells */ + case g1m_mcstype_mat: case g1m_mcstype_vct: case g1m_mcstype_list: + case g1m_mcstype_ssheet: + if (handle->head.width && handle->head.height) { + free(handle->cells[0]); + free(handle->cells); + } + break; + + /* free the set of pixels */ + case g1m_mcstype_pict: case g1m_mcstype_capt: + for (int i = 0; i < handle->head.count; i++) + free(handle->pics[i]); + if (handle->pics != &handle->pic) + free(handle->pics); + break; + + /* free the variables */ + case g1m_mcstype_alphamem: + if (handle->vars != &handle->var) + free(handle->vars); + break; + + /* free nothing */ + case g1m_mcstype_end: + case g1m_mcstype_string: /* TEMPORARY XXX */ + break; + + /* free the raw content */ + default: + free(handle->content); + } + + /* free the content */ + free(handle); +} diff --git a/src/type/cas.c b/src/type/cas.c index b9993a3..a639748 100644 --- a/src/type/cas.c +++ b/src/type/cas.c @@ -26,43 +26,46 @@ struct type_corresp { /* identification */ const char *datatype; - /* libg1m MCS file type */ + /* libg1m MCS file type, flags */ g1m_mcstype_t type; + unsigned int flags; }; /* ************************************************************************** */ /* Correspondances */ /* ************************************************************************** */ -/* All correspondances. Remarks: +/* All correspondances found by Tom Wheeley and Tom Lynn. Remarks: * - Correspondances with a NULL data type means the data type isn't to be * read. */ -#define TTERM {NULL, 0} +#define TTERM {NULL, 0, 0} static struct type_corresp cas_groups[] = { - /* not implemented yet types, described by Tom Wheeley and Tom Lynn */ - {"AA", 0}, // dynamic graph functions - {"AD", 0}, // variable memory - {"AL", 0}, // all - {"AM", 0}, // alpha variable memory - {"BU", 0}, // backup - {"DM", 0}, // defined memory - {"DD", 0}, // screenshot - {"EN", 0}, // one editor file - {"FN", 0}, // set of editor files - {"F1", 0}, // one function memory - {"F6", 0}, // set of function memories - {"GA", 0}, // set of graph functions - {"GF", 0}, // graph zoom factor (graph function?) - {"GR", 0}, // graph range - {"GT", 0}, // function table - {"MA", 0}, // set of matrices - {"PD", 0}, // polynomial equations - {"P1", 0}, // one program - {"PZ", 0}, // set of programs - {"RT", 0}, // recursion table - {"SD", 0}, // simultaneous equations - {"SR", 0}, // linear regression data - {"SS", 0}, // standard deviation data + /* implemented */ + {"P1", g1m_mcstype_program, 0}, // one program + {"PZ", g1m_mcstype_program, g1m_mcsflag_multiple}, // set of programs + + /* not implemented yet */ + {"AA", 0, 0}, // dynamic graph functions + {"AD", 0, 0}, // variable memory + {"AL", 0, 0}, // all + {"AM", 0, 0}, // alpha variable memory + {"BU", 0, 0}, // backup + {"DM", 0, 0}, // defined memory + {"DD", 0, 0}, // screenshot + {"EN", 0, 0}, // one editor file + {"FN", 0, 0}, // set of editor files + {"F1", 0, 0}, // one function memory + {"F6", 0, 0}, // set of function memories + {"GA", 0, 0}, // set of graph functions + {"GF", 0, 0}, // graph zoom factor (graph function?) + {"GR", 0, 0}, // graph range + {"GT", 0, 0}, // function table + {"MA", 0, 0}, // set of matrices + {"PD", 0, 0}, // polynomial equations + {"RT", 0, 0}, // recursion table + {"SD", 0, 0}, // simultaneous equations + {"SR", 0, 0}, // linear regression data + {"SS", 0, 0}, // standard deviation data /* terminating entry */ TTERM @@ -99,6 +102,7 @@ int g1m_maketype_cas(g1m_mcshead_t *head, const char *datatype) /* fill in info and return */ head->type = c->type; + head->flags |= c->flags; return (0); notfound: