diff --git a/include/file.h b/include/file.h index 5f831c36..6a328eab 100644 --- a/include/file.h +++ b/include/file.h @@ -38,28 +38,37 @@ #include struct empfile { - int ef_uid; /* Table ID */ + /* Members with immutable values */ + int uid; /* Table ID */ char *name; /* Empire name (e.g., "treaty") */ char *file; /* if backed by file, file name relative to data directory */ - int flags; /* EFF_XY, ... */ + struct castr *cadef; /* table column selectors (column meta-data) */ int size; /* size of a table entry */ + int flags; /* only EFF_IMMUTABLE immutable, see below + for use of remaining bits */ + /* Members whose values are fixed when the cache is mapped */ + char *cache; /* pointer to cache */ + int csize; /* cache size, in entries */ + /* and flags bit EFF_MEM */ + /* Members whose values may vary throughout operation */ + int baseid; /* id of first entry in cache */ + int cids; /* # entries in cache */ + int fids; /* # entries in table */ + int fd; /* file descriptor, -1 if not open */ + /* and flags bit EFF_RDONLY */ + /* User callbacks */ void (*init)(int, char *); /* called after entry creation, unless null */ int (*postread)(int, char *); /* called after read, unless null */ int (*prewrite)(int, char *); /* called before write, unless null */ - int fd; /* file descriptor, -1 if not open */ - int baseid; /* id of first entry in cache */ - int cids; /* # entries in cache */ - int csize; /* cache size, in entries */ - char *cache; /* pointer to cache */ - int fids; /* # entries in table */ - struct castr *cadef; /* table column selectors (column meta-data) */ }; /* - * struct empfile flags + * Flag bits for struct empfile member flags + * Immutable flags are properties of the table and thus cannot change. + * The remaining flags record how the table is being used. */ -/* Immutable flags */ +/* Immutable flags, fixed at compile-time */ /* * EFF_XY / EFF_OWNER / EFF_GROUP assert that coordinates / owner / * group of such a table's entries can be safely obtained by @@ -70,17 +79,16 @@ struct empfile { #define EFF_GROUP bit(2) /* Table is allocated statically */ #define EFF_STATIC bit(3) +/* All the immutable flags */ +#define EFF_IMMUTABLE (EFF_XY | EFF_OWNER | EFF_GROUP | EFF_STATIC) /* Flags set when table contents is mapped */ /* Table is entirely in memory */ -#define EFF_MEM bit(4) +#define EFF_MEM bit(8) /* Table is read-only */ -#define EFF_RDONLY bit(5) -/* Transient flags, just to control ef_open() */ +#define EFF_RDONLY bit(9) +/* Transient flags, only occur in argument of ef_open() */ /* Create table file, clobbering any existing file */ -#define EFF_CREATE bit(6) - -/* Flags that may be passed to ef_open() */ -#define EFF_OPEN (EFF_MEM | EFF_RDONLY | EFF_CREATE) +#define EFF_CREATE bit(10) /* * Empire `file types' diff --git a/src/lib/common/file.c b/src/lib/common/file.c index 4e346c17..76c57335 100644 --- a/src/lib/common/file.c +++ b/src/lib/common/file.c @@ -54,7 +54,8 @@ static int do_write(struct empfile *, void *, int, int); /* * Open the file-backed table TYPE (EF_SECTOR, ...). - * HOW are EFF_OPEN flags to control operation. + * HOW are flags to control operation. Naturally, immutable flags are + * not permitted. * Return non-zero on success, zero on failure. * You must call ef_close() before the next ef_open(). */ @@ -66,8 +67,8 @@ ef_open(int type, int how) if (ef_check(type) < 0) return 0; - if (CANT_HAPPEN(how & ~EFF_OPEN)) - how &= EFF_OPEN; + if (CANT_HAPPEN(how & EFF_IMMUTABLE)) + how &= ~EFF_IMMUTABLE; /* open file */ ep = &empfile[type]; @@ -122,14 +123,14 @@ ef_open(int type, int how) } ep->baseid = 0; ep->cids = 0; - ep->flags = (ep->flags & ~EFF_OPEN) | (how & ~EFF_CREATE); + ep->flags = (ep->flags & EFF_IMMUTABLE) | (how & ~EFF_CREATE); ep->fd = fd; /* map file into cache */ if ((how & EFF_MEM) && ep->fids) { if (fillcache(ep, 0) != ep->fids) { ep->cids = 0; /* prevent cache flush */ - ep->flags &= ~EFF_OPEN; /* maintain invariant */ + ep->flags &= EFF_IMMUTABLE; /* maintain invariant */ ef_close(type); return 0; } @@ -150,7 +151,7 @@ ef_close(int type) retval = ef_flush(type); ep = &empfile[type]; - ep->flags &= ~EFF_OPEN; + ep->flags &= EFF_IMMUTABLE; if (!(ep->flags & EFF_STATIC)) { free(ep->cache); ep->cache = NULL; @@ -395,7 +396,7 @@ ef_extend(int type, int count) /* FIXME lazy bastards... do this right */ /* XXX this will cause problems if there are ef_ptrs (to the * old allocated structure) active when we do the re-open */ - how = ep->flags & EFF_OPEN; + how = ep->flags & ~EFF_IMMUTABLE; ef_close(type); ef_open(type, how); } else { @@ -554,7 +555,7 @@ ef_init(void) for (i = 0; ca[i].ca_name; i++) ; ef_fix_size(&empfile[EF_META], i); - for (ep = empfile; ep->ef_uid >= 0; ep++) { + for (ep = empfile; ep->uid >= 0; ep++) { if (ep->cadef == symbol_ca) { lup = (struct symbol *)ep->cache; for (i = 0; lup[i].name; i++) ; diff --git a/src/lib/global/file.c b/src/lib/global/file.c index 7ebd97e4..58f405a1 100644 --- a/src/lib/global/file.c +++ b/src/lib/global/file.c @@ -54,106 +54,99 @@ #include "commodity.h" #include "nsc.h" +/* Some abbreviations: */ +#define SZ(array) (sizeof(array) / sizeof((array)[0])) +/* Unmapped cache initializers for members flags... */ +#define UNMAPPED_INIT(type, flags) \ + sizeof(type), flags, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL +/* Same for cache mapped to array with known size */ +#define ARRAY_INIT(array, flags) \ + sizeof(*(array)), flags, (char *)(array), \ + SZ((array)), 0, SZ((array)) - 1, SZ((array)) - 1, -1, NULL, NULL, NULL +/* Same for unknown size, size to be filled in by ef_init() */ +#define PTR_INIT(ptr, flags) sizeof(*(ptr)), flags, (char *)(ptr), \ + 0, 0, 0, 0, -1, NULL, NULL, NULL +/* Common configuration table flags */ +#define EFF_CFG (EFF_RDONLY | EFF_MEM | EFF_STATIC) + struct empfile empfile[] = { + /* + * How empfile[] is initialized: + * + * Members uid, name, file, size, cadef, and the EFF_IMMUTABLE + * bits of flags get their final value. + * If flags & EFF_STATIC, the cache is mapped here, and members + * cache, csize get their final value. + * Members baseid, cids, fids and the EFF_MEM|EFF_RDONLY bits of + * flags are initialized according the initial cache contents. + * Member fd is initialized to -1. + * Members init, postread, prewrite get initialized to NULL, but + * that can be changed by users. + * + * Whatever of the above can't be done here must be done in + * ef_init(). + */ + /* Dynamic game data */ - {EF_SECTOR, "sect", "sector", EFF_XY | EFF_OWNER, - sizeof(struct sctstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, sect_ca}, - {EF_SHIP, "ship", "ship", EFF_XY | EFF_OWNER | EFF_GROUP, - sizeof(struct shpstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, ship_ca}, - {EF_PLANE, "plane", "plane", EFF_XY | EFF_OWNER | EFF_GROUP, - sizeof(struct plnstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, plane_ca}, - {EF_LAND, "land", "land", EFF_XY | EFF_OWNER | EFF_GROUP, - sizeof(struct lndstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, land_ca}, - {EF_NUKE, "nuke", "nuke", EFF_XY | EFF_OWNER, - sizeof(struct nukstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, nuke_ca}, - {EF_NEWS, "news", "news", 0, - sizeof(struct nwsstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, news_ca}, - {EF_TREATY, "treaty", "treaty", 0, - sizeof(struct trtstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, treaty_ca}, - {EF_TRADE, "trade", "trade", 0, - sizeof(struct trdstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, trade_ca}, - {EF_POWER, "pow", "power", 0, - sizeof(struct powstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, NULL}, - {EF_NATION, "nat", "nation", EFF_OWNER, - sizeof(struct natstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, nat_ca}, - {EF_LOAN, "loan", "loan", 0, - sizeof(struct lonstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, loan_ca}, - {EF_MAP, "map", "map", 0, - DEF_WORLD_X * DEF_WORLD_Y / 2, NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, NULL}, - {EF_BMAP, "bmap", "bmap", 0, - DEF_WORLD_X * DEF_WORLD_Y / 2, NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, NULL}, - {EF_COMM, "commodity", "commodity", 0, - sizeof(struct comstr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, commodity_ca}, - {EF_LOST, "lost", "lostitems", EFF_OWNER, - sizeof(struct loststr), NULL, NULL, NULL, - -1, -1, 0, 0, NULL, 0, lost_ca}, + {EF_SECTOR, "sect", "sector", sect_ca, + UNMAPPED_INIT(struct sctstr, EFF_XY | EFF_OWNER)}, + {EF_SHIP, "ship", "ship", ship_ca, + UNMAPPED_INIT(struct shpstr, EFF_XY | EFF_OWNER | EFF_GROUP)}, + {EF_PLANE, "plane", "plane", plane_ca, + UNMAPPED_INIT(struct plnstr, EFF_XY | EFF_OWNER | EFF_GROUP)}, + {EF_LAND, "land", "land", land_ca, + UNMAPPED_INIT(struct lndstr, EFF_XY | EFF_OWNER | EFF_GROUP)}, + {EF_NUKE, "nuke", "nuke", nuke_ca, + UNMAPPED_INIT(struct nukstr, EFF_XY | EFF_OWNER)}, + {EF_NEWS, "news", "news", news_ca, + UNMAPPED_INIT(struct nwsstr, 0)}, + {EF_TREATY, "treaty", "treaty", treaty_ca, + UNMAPPED_INIT(struct trtstr, 0)}, + {EF_TRADE, "trade", "trade", trade_ca, + UNMAPPED_INIT(struct trdstr, 0)}, + {EF_POWER, "pow", "power", NULL, + UNMAPPED_INIT(struct powstr, 0)}, + {EF_NATION, "nat", "nation", nat_ca, + UNMAPPED_INIT(struct natstr, EFF_OWNER)}, + {EF_LOAN, "loan", "loan", loan_ca, + UNMAPPED_INIT(struct lonstr, 0)}, + {EF_MAP, "map", "map", NULL, + 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL}, + {EF_BMAP, "bmap", "bmap", NULL, + 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL}, + {EF_COMM, "commodity", "commodity", commodity_ca, + UNMAPPED_INIT(struct comstr, 0)}, + {EF_LOST, "lost", "lostitems", lost_ca, + UNMAPPED_INIT(struct loststr, EFF_OWNER)}, /* Static game data (configuration) */ -#define EFF_CFG (EFF_RDONLY | EFF_MEM | EFF_STATIC) -#define SZ(array) (sizeof(array) / sizeof((array)[0])) -#define CFGTAB(type, name, array, ca) \ -{(type), (name), NULL, EFF_RDONLY | EFF_MEM | EFF_STATIC, \ - sizeof((array)[0]), NULL, NULL, NULL, \ - -1, 0, SZ((array)) - 1, SZ((array)), (char *)(array), SZ((array)) - 1, (ca)} - CFGTAB(EF_SECTOR_CHR, "sect chr", dchr, dchr_ca), - {EF_SHIP_CHR, "ship chr", NULL, EFF_CFG, - sizeof(mchr[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)mchr, 0, mchr_ca}, - {EF_PLANE_CHR, "plane chr", NULL, EFF_CFG, - sizeof(plchr[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)plchr, 0, plchr_ca}, - {EF_LAND_CHR, "land chr", NULL, EFF_CFG, - sizeof(lchr[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)lchr, 0, lchr_ca}, - {EF_NUKE_CHR, "nuke chr", NULL, EFF_CFG, - sizeof(nchr[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)nchr, 0, nchr_ca}, - CFGTAB(EF_NEWS_CHR, "news chr", rpt, rpt_ca), - {EF_TREATY_FLAGS, "treaty flags", NULL, EFF_CFG, - sizeof(treaty_flags[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)treaty_flags, 0, symbol_ca}, - CFGTAB(EF_ITEM, "item", ichr, ichr_ca), - CFGTAB(EF_INFRASTRUCTURE, "infrastructure", intrchr, intrchr_ca), - CFGTAB(EF_PRODUCT, "product", pchr, pchr_ca), - CFGTAB(EF_TABLE, "table", empfile, empfile_ca), - {EF_SHIP_CHR_FLAGS, "ship chr flags", NULL, EFF_CFG, - sizeof(ship_chr_flags[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)ship_chr_flags, 0, symbol_ca}, - {EF_PLANE_CHR_FLAGS, "plane chr flags", NULL, EFF_CFG, - sizeof(plane_chr_flags[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)plane_chr_flags, 0, symbol_ca}, - {EF_LAND_CHR_FLAGS, "land chr flags", NULL, EFF_CFG, - sizeof(land_chr_flags[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)land_chr_flags, 0, symbol_ca}, - {EF_NUKE_CHR_FLAGS, "nuke chr flags", NULL, EFF_CFG, - sizeof(nuke_chr_flags[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)nuke_chr_flags, 0, symbol_ca}, - {EF_META, "meta", NULL, EFF_CFG, - sizeof(mdchr_ca[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)mdchr_ca, 0, mdchr_ca}, - {EF_META_TYPE, "meta type", NULL, EFF_CFG, - sizeof(meta_type[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)meta_type, 0, symbol_ca}, - {EF_META_FLAGS, "meta flags", NULL, EFF_CFG, - sizeof(meta_flags[0]), NULL, NULL, NULL, - -1, -1, 0, 0, (char *)meta_flags, 0, symbol_ca}, + {EF_SECTOR_CHR, "sect chr", NULL, dchr_ca, ARRAY_INIT(dchr, EFF_CFG)}, + {EF_SHIP_CHR, "ship chr", NULL, mchr_ca, PTR_INIT(mchr, EFF_CFG)}, + {EF_PLANE_CHR, "plane chr", NULL, plchr_ca, PTR_INIT(plchr, EFF_CFG)}, + {EF_LAND_CHR, "land chr", NULL, lchr_ca, PTR_INIT(lchr, EFF_CFG)}, + {EF_NUKE_CHR, "nuke chr", NULL, nchr_ca, PTR_INIT(nchr, EFF_CFG)}, + {EF_NEWS_CHR, "news chr", NULL, rpt_ca, ARRAY_INIT(rpt, EFF_CFG)}, + {EF_TREATY_FLAGS, "treaty flags", NULL, symbol_ca, + PTR_INIT(treaty_flags, EFF_CFG)}, + {EF_ITEM, "item", NULL, ichr_ca, ARRAY_INIT(ichr, EFF_CFG)}, + {EF_INFRASTRUCTURE, "infrastructure", NULL, intrchr_ca, + ARRAY_INIT(intrchr, EFF_CFG)}, + {EF_PRODUCT, "product", NULL, pchr_ca, ARRAY_INIT(pchr, EFF_CFG)}, + {EF_TABLE, "table", NULL, empfile_ca, ARRAY_INIT(empfile, EFF_CFG)}, + {EF_SHIP_CHR_FLAGS, "ship chr flags", NULL, symbol_ca, + PTR_INIT(ship_chr_flags, EFF_CFG)}, + {EF_PLANE_CHR_FLAGS, "plane chr flags", NULL, symbol_ca, + PTR_INIT(plane_chr_flags, EFF_CFG)}, + {EF_LAND_CHR_FLAGS, "land chr flags", NULL, symbol_ca, + PTR_INIT(land_chr_flags, EFF_CFG)}, + {EF_NUKE_CHR_FLAGS, "nuke chr flags", NULL, symbol_ca, + PTR_INIT(nuke_chr_flags, EFF_CFG)}, + {EF_META, "meta", NULL, mdchr_ca, PTR_INIT(mdchr_ca, EFF_CFG)}, + {EF_META_TYPE, "meta type", NULL, symbol_ca, + PTR_INIT(meta_type, EFF_CFG)}, + {EF_META_FLAGS, "meta flags", NULL, symbol_ca, + PTR_INIT(meta_flags, EFF_CFG)}, /* Sentinel */ - {EF_BAD, NULL, NULL, 0, - 0, NULL, NULL, NULL, - -1, -1, 0,0,NULL, 0, NULL} + {EF_BAD, NULL, NULL, NULL, 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL}, }; diff --git a/src/lib/global/nsc.c b/src/lib/global/nsc.c index 3f3d7e34..40c277ef 100644 --- a/src/lib/global/nsc.c +++ b/src/lib/global/nsc.c @@ -492,7 +492,7 @@ struct castr rpt_ca[] = { struct castr empfile_ca[] = { {NSC_STRING, 0, 0, offsetof(struct empfile, name), "name", EF_BAD}, - {NSC_INT, 0, 0, offsetof(struct empfile, ef_uid), "uid", EF_BAD}, + {NSC_INT, 0, 0, offsetof(struct empfile, uid), "uid", EF_BAD}, {NSC_STRING, 0, 0, offsetof(struct empfile, file), "file_name", EF_BAD}, {NSC_INT, 0, 0, offsetof(struct empfile, flags), "flags", EF_BAD}, {NSC_NOTYPE, 0, 0, 0, NULL, EF_BAD}