📄 genio.c
字号:
/* genio.c 9-9-92 genebank input/output routines *//* Tierra Simulator V4.0: Copyright (c) 1991, 1992 Tom Ray & Virtual Life */#ifndef lintstatic char sccsid[] = "@(#)genio.c 1.5 7/21/92";#endif#include "license.h"#include "tierra.h"#include "extern.h"#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#ifdef MEM_CHK#include <memcheck.h>#endif#define WritEcoS(bits) WritEcoB(bits, mes[9])/* * open_ar - open a genebank archive * * file - the filename; * size - the creature size * format - a byte, usually the instruction set number * mode - 0 if the file exists its contents should be preserved, * < 0, if doesn't exit create it * else if the file should be created (or truncated). mode > 1 * is taken as the number of index entries to allocate * (will be rounded to the next highest # such that * index + header is a multiple of 1K) * * returns a pointer to a file opened for update, or NULL if unsuccessful. * open_ar fails if size or format are incompatible with the archive. */FILE *open_ar(file, size, format, mode) I8s *file; I32s size, mode, format;{ FILE *fp = NULL; head_t head; struct stat buf; if (( mode > 0) || (mode < 0 && (stat(file, &buf) == -1))) { if (mode < 0) /* if file doesn't exist, no entries */ mode = 0; if (fp = fopen(file, "w+b")) { strcpy(head.magic, "tie"); head.magic[3] = '0' + format; head.size = size; head.n = 0; head.n_alloc = (((int) ((sizeof(head_t) + mode * sizeof(indx_t)) / 1024.0) + 1) * 1024 - sizeof head) / sizeof(indx_t); head.g_off = sizeof(head_t) + head.n_alloc * sizeof(indx_t); write_head(fp, &head); } } else if (mode < 1 && (fp = fopen(file, "r+b"))) { head = read_head(fp); if (head.size != size || (format > -1) && head.magic[3] != format + '0' || strncmp(head.magic, "tie", 3)) { fclose(fp); fp = NULL; errno = EINVAL; } } return fp;}/* * read_head - read header from a genebank archive */head_t read_head(fp) FILE *fp;{ head_t t; if ((fp != NULL) && !fseek(fp, 0, 0)) fread(&t, sizeof(head_t), 1, fp); else {#ifdef ARG fprintf(stderr, "Tierra read_head() file access failed"); exit(errno);#else FEError(-400,EXIT,NOWRITE, "Tierra read_head() file access failed");#endif } if (GFormat < 0) GFormat = t.magic[3] -'0'; /* autoselect */ return t;}/* * write_head - write header to a genebank archive */void write_head(fp, head) FILE *fp; head_t *head;{ if (!fseek(fp, 0, 0)) fwrite(head, sizeof(head_t), 1, fp); else {#ifdef ARG fprintf(stderr, "Tierra write_head() file access failed"); exit(errno);#else FEError(-401,EXIT,NOWRITE, "Tierra write_head() file access failed");#endif }}/* * read_indx - read the index from a genebank archive */indx_t *read_indx(fp, head) FILE *fp; head_t *head;{#ifdef ERROR I32s i;#endif /* ERROR */ indx_t *t = 0;#ifdef __TURBOC__ t = &GIndx;#else /* __TURBOC__ */ if (!fseek(fp, sizeof(head_t), 0)) { t = (indx_t *) thcalloc(head->n_alloc, sizeof(indx_t)); if (t != NULL) fread(t, sizeof(indx_t), head->n, fp); } else {#ifdef ARG fprintf(stderr, "Tierra read_index() file access failed"); exit(errno);#else /* ARG */ FEError(-402,EXIT,NOWRITE, "Tierra read_index() file access failed");#endif /* ARG */ }#ifdef ERROR if (t != NULL) for (i = 0; i < head->n; i++) if (!(t + i)->psize)#ifdef ARG { fprintf(stderr, "Tierra read_index() indx array corrupted"); exit(errno); }#else /* ARG */ FEError(-403,EXIT,NOWRITE, "Tierra read_index() indx array corrupted");#endif /* ARG */#endif /* ERROR */#endif /* __TURBOC__ */ return t;}/* * write_indx - write the index to a genebank archive */void write_indx(fp, head, indx) FILE *fp; head_t *head; indx_t *indx;{#ifdef ERROR I32s i;#endif /* ERROR */#ifdef __TURBOC__ return ;#endif /* __TURBOC__ */#ifdef ERROR for (i = 0; i < head->n; i++) if (!(indx + i)->psize)#ifdef ARG { fprintf(stderr, "Tierra write_index() indx array corrupted"); exit(errno); }#else /* ARG */ FEError(-404,EXIT,NOWRITE, "Tierra write_index() indx array corrupted");#endif /* ARG */#endif /* ERROR */ if (!fseek(fp, sizeof(head_t), 0)) fwrite(indx, sizeof(indx_t), head->n_alloc, fp); else {#ifdef ARG fprintf(stderr, "Tierra write_index() file access failed"); exit(errno);#else FEError(-405,EXIT,NOWRITE, "Tierra write_index() file access failed");#endif }}/* * find_gen - find the index of a genome in an archive by its 3 letter name * * will return n (number of genomes) if not found, otherwise the position * (0 - n-1) in archive */I32s find_gen(fp, indx, gen, n) FILE *fp; indx_t *indx; I8s *gen; I32s n;{ I32s i;#ifdef __TURBOC__ if (!strncmp("---", gen, 3)) { fseek(fp, sizeof(head_t) + (n * sizeof(indx_t)), 0); fread(indx, sizeof(indx_t), 1, fp); i = n; } else { fseek(fp, sizeof(head_t), 0); /* seek past head */ for(i = 0; i < n; i++) /* scan index for gen */ { fread(indx, sizeof(indx_t), 1, fp); if (!strncmp(indx->gen, gen, 3)) break; } }#else /* __TURBOC__ */ for (i = 0; i < n; i++) if (!strncmp((indx + i)->gen, gen, 3)) break;#endif /* __TURBOC__ */ return i;}/* * get_gen - read a genome from genebank archive and return a pointer * to a struct g_list containing all saved info. * * fp - pointer to open archive file * head - archive header * indxn - index entry of desired genome * n - position of desired genome in archive * * reads the genome and reformats its other args into the form used * internally by tierra. the genotype must be in archive. n can be * determined by find_gen(). currently no error checking */Pgl get_gen(fp, head, indxn, n) FILE *fp; indx_t *indxn; head_t *head; I32s n;{ Pgl t = (Pgl) tcalloc(1, sizeof(GList)); fseek(fp, head->g_off + (n * head->size * (sizeof(Instruction) + sizeof(GenBits))), 0); t->genome = (FpInst) tcalloc(head->size, sizeof(Instruction)); t->gbits = (FpGenB) tcalloc(head->size, sizeof(GenBits)); fread(t->genome, head->size * sizeof(Instruction), 1, fp); fread(t->gbits, head->size * sizeof(GenBits), 1, fp); t->gen.size = head->size; strncpy(t->gen.label, indxn->gen, 3); t->parent.size = indxn->psize; strncpy(t->parent.label, indxn->pgen, 3); t->bits = indxn->bits; t->hash = indxn->hash; t->d1 = indxn->d1; t->d2 = indxn->d2; t->originI = indxn->originI; t->originC = indxn->originC; t->MaxPropPop = (float) indxn->mpp / 10000.; t->MaxPropInst = (float) indxn->mpi / 10000.; t->mpp_time = indxn->mppT; t->ploidy = (indxn->pt & 0360) >> 4; t->track = indxn->pt & 017; return t;}/* * add_gen - replace or add a genotype to end of genebank archive * * fp - pointer to open archive file * head - header of archive * indx - index of archive * gen - genotype to be added * * reformats the genotype and replaces it in the archive, or adds it to * the end if not found. args head & indx are modified by this fn. * returns 0 on add, and 1 on replace. * * Scheme of add_gen(): * * 1) find the gen in the file, or find out if it is not in the file. * This may be done with find_gen() if we have indx in RAM, or by * by repeated freads if we don't have indx. * 2) If gen is not in file and file is full, we must enlarge the file by * moving the genotypes out to make room for more indexes. * Three strategies are used here. In Unix, we read the entire index * and bank of genomes into RAM, then write them back out into their * new locations. In DOS, when memory is available, we will copy * the genomes one by one from their old to their new locations on disk, * then we write the free index structures over with zeros. In DOS * when memory is not available, we copy the genomes byte by byte. * 3) We write the new genome and genbits to the file. * 4) We determine if this was an add or a replace. * 5) We write the new updated head. * 6) We update the index of the new gen in RAM. * 7) We write the new index to the file. * 8) We return add or replace. * */I32s add_gen(fp, head, indx, gen) FILE *fp; head_t *head; indx_t **indx; Pgl gen;{ I8s t_buf = '\0'; I32s n, s, ret, oldoff, gensiz, old_n_alloc, i; I32s wsiz = 0, rsiz = 0, segs, rem; indx_t t_indx, *tp_indx, *tindx;#ifdef __TURBOC__ I8s buf[512];#else /* __TURBOC__ */ I8s *buf;#endif /* __TURBOC__ */ Swap = 0; /* to avoid recursion */ gensiz = (head->size * (sizeof(Instruction) + sizeof(GenBits)));/* 1) find the gen in the file, or find out if it is not in the file. * This may be done with find_gen() if we have indx in RAM, or by * by repeated freads if we don't have indx. */ n = find_gen(fp, *indx, gen->gen.label, head->n); /* does not alloc *//* 2) If gen is not in file and file is full, we must enlarge the file by * moving the genotypes out to make room for more indexes. * Three strategies are used here. In Unix, we read the entire index * and bank of genomes into RAM, then write them back out into their * new locations. In DOS, when memory is available, we will copy the * genomes one by one from their old to their new locations on disk, * then we write over with zeros, the free index structures. In DOS * when memory is not available, we copy the genomes byte by byte. */ /* n == head->n means not in index */ /* head->n == head->n_alloc means file is full */ /* if not in file and file is full */ if (n == head->n && head->n == head->n_alloc) { old_n_alloc = head->n_alloc; head->n_alloc += 1024 / sizeof(indx_t); oldoff = head->g_off; head->g_off = sizeof(head_t) + (head->n_alloc * sizeof(indx_t));#ifdef __TURBOC__ fseek(fp, 0, SEEK_END); /* make room at end for slide */ fwrite(&t_buf, sizeof(I8s), head->g_off - oldoff, fp);/* write zeros*/ segs = (gensiz * head->n) / 512; rem = (gensiz * head->n) % 512; if (rem) { fseek(fp, (segs * 512) + oldoff, 0); rsiz += fread(buf, sizeof(I8s), rem, fp); fseek(fp, (segs * 512) + head->g_off, 0); wsiz += fwrite(buf, sizeof(I8s), rem, fp); } if (segs) for(i = segs - 1; i >= 0; i--) { fseek(fp, (i * 512) + oldoff, 0); rsiz += fread(buf, sizeof(I8s), 512, fp); fseek(fp, (i * 512) + head->g_off, 0); wsiz += fwrite(buf, sizeof(I8s), 512, fp); }#ifdef ERROR if ((rsiz != gensiz * head->n) || (wsiz != gensiz * head->n))#ifdef ARG { fprintf(stderr, "Tierra add_gen() rsiz or wsiz bad"); exit(errno); }#else /* ARG */ FEError(-406,EXIT,NOWRITE, "Tierra add_gen() rsiz or wsiz bad");#endif /* ARG */#endif /* ERROR */#else /* __TURBOC__ */ fseek(fp, oldoff, 0); buf = (I8s *) thcalloc(s = gensiz * head->n , 1); fread(buf, s, 1, fp); fseek(fp, head->g_off, 0); fwrite(buf, s, 1, fp); if (buf) { thfree(buf); buf = NULL; } tindx = (indx_t *) threcalloc(*indx, sizeof(indx_t) * head->n_alloc, sizeof(indx_t) * old_n_alloc); if (tindx) { *indx = tindx; for (i = old_n_alloc * sizeof(indx_t); i < head->n_alloc * sizeof(indx_t); i++) ((I8s *) *indx)[i] = (I8s) 0; } else if (*indx) { thfree(*indx); *indx = NULL; }#endif /* __TURBOC__ */ }/* 3) We write the new genome and genbits to the file. */ fseek(fp, head->g_off + (n * gensiz), 0); fwrite(gen->genome, head->size * sizeof(Instruction), 1, fp); fwrite(gen->gbits, head->size * sizeof(GenBits), 1, fp);/* 4) We determine if this was an add or a replace. */ head->n += ret = (n == head->n);/* 5) We write the new updated head. */ write_head(fp, head); /* no alloc *//* 6) We update the index of the new gen in RAM. */#ifdef __TURBOC__ tp_indx = *indx; /* fake pointers for meat of function */#else /* __TURBOC__ */ tp_indx = &((*indx)[n]);#endif /* __TURBOC__ */ strncpy((tp_indx)->gen, gen->gen.label, 3); (tp_indx)->psize = gen->parent.size; strncpy((tp_indx)->pgen, gen->parent.label, 3); (tp_indx)->bits = gen->bits; (tp_indx)->hash = gen->hash; (tp_indx)->d1 = gen->d1; (tp_indx)->d2 = gen->d2; (tp_indx)->originI = gen->originI; (tp_indx)->originC = gen->originC; (tp_indx)->mpp = (short) (gen->MaxPropPop * 10000); (tp_indx)->mpi = (short) (gen->MaxPropInst * 10000); (tp_indx)->mppT = (gen->mpp_time); (tp_indx)->pt = (gen->ploidy << 4) + gen->track;/* 7) We write the new index to the file. */#ifdef ERROR#ifdef __TURBOC__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -