Virtual selectors
Where ordinary selectors specify a value stored in some object, virtual selectors specify a function to call to compute a value associated with some object. Use them to replace the special case xdump ver by new table EF_VERSION. Move configkeys[] to lib/common because nsc_init() needs it to initialize empfile[EF_VERSION].cadef.
This commit is contained in:
parent
38047a62f7
commit
da8a1daeef
12 changed files with 541 additions and 482 deletions
|
@ -158,9 +158,6 @@ Without such a key, you need to count records to find the record
|
||||||
index, and that works only if you can see a prefix of the complete
|
index, and that works only if you can see a prefix of the complete
|
||||||
table.
|
table.
|
||||||
|
|
||||||
The special table "ver" collects all scalar configuration parameters
|
|
||||||
in a single record. It does not occur in the table of tables.
|
|
||||||
|
|
||||||
|
|
||||||
Syntax of xdump command
|
Syntax of xdump command
|
||||||
|
|
||||||
|
@ -368,8 +365,7 @@ table itself. Let's try it:
|
||||||
[...]
|
[...]
|
||||||
/45
|
/45
|
||||||
|
|
||||||
It worked! Mind that the special table "ver" is not in the table of
|
It worked!
|
||||||
tables.
|
|
||||||
|
|
||||||
Now dump the two symbol tables we postponed. Because xdump accepts
|
Now dump the two symbol tables we postponed. Because xdump accepts
|
||||||
table IDs as well as names, we don't have to know their names:
|
table IDs as well as names, we don't have to know their names:
|
||||||
|
|
|
@ -142,6 +142,7 @@ enum {
|
||||||
EF_INFRASTRUCTURE,
|
EF_INFRASTRUCTURE,
|
||||||
EF_UPDATES, /* not actually static */
|
EF_UPDATES, /* not actually static */
|
||||||
EF_TABLE,
|
EF_TABLE,
|
||||||
|
EF_VERSION,
|
||||||
EF_META, /* not really configuration */
|
EF_META, /* not really configuration */
|
||||||
/* Symbol tables */
|
/* Symbol tables */
|
||||||
EF_AGREEMENT_STATUS,
|
EF_AGREEMENT_STATUS,
|
||||||
|
|
|
@ -95,14 +95,21 @@ typedef char packed_nsc_cat;
|
||||||
* promoted type.
|
* promoted type.
|
||||||
* If category is NSC_OFF, the value is in a context object, and
|
* If category is NSC_OFF, the value is in a context object, and
|
||||||
* val_as.sym specifies how to get it, as follows.
|
* val_as.sym specifies how to get it, as follows.
|
||||||
* If type is NSC_STRINGY, the value is an array of sym.len characters
|
* If sym.get is null, and type is NSC_STRINGY, the value is an array
|
||||||
* starting at sym.offs in the context object. sym.idx must be zero.
|
* of sym.len characters starting at sym.offs in the context object.
|
||||||
* Else if sym.len is zero, the value is in the context object at offset
|
* sym.idx must be zero.
|
||||||
* sym.off. sym.idx must be zero.
|
* Else if sym.get is null, and sym.len is zero, the value is in the
|
||||||
* Else sym.len is non-zero, and the value has index sym.idx in an
|
* context object at offset sym.off. sym.idx must be zero.
|
||||||
* array of sym.len elements at offset sym.off in in the context
|
* Else if sym.get is null, sym.len is non-zero, and the value has
|
||||||
* object. I.e. the value is at sym.off + sym.idx * SZ, where SZ is
|
* index sym.idx in an array of sym.len elements at offset sym.off in
|
||||||
* the size of the value.
|
* in the context object. I.e. the value is at sym.off + sym.idx *
|
||||||
|
* SZ, where SZ is the size of the value.
|
||||||
|
* If sym.get is not null, you obtain the value by calling get() like
|
||||||
|
* VAL->get(VAL, CNUM, CTXO), where CNUM is the country to use for
|
||||||
|
* coordinate translation and access control, and CTXO is the context
|
||||||
|
* object. get() either returns a null pointer and sets VAL->val_as
|
||||||
|
* to the value, as appropriate for the type. Or it returns another
|
||||||
|
* context object and sets VAL->val_as.sym for it.
|
||||||
*/
|
*/
|
||||||
struct valstr {
|
struct valstr {
|
||||||
packed_nsc_type val_type; /* type of value */
|
packed_nsc_type val_type; /* type of value */
|
||||||
|
@ -112,6 +119,7 @@ struct valstr {
|
||||||
ptrdiff_t off;
|
ptrdiff_t off;
|
||||||
int len;
|
int len;
|
||||||
int idx;
|
int idx;
|
||||||
|
void *(*get)(struct valstr *, natid, void *);
|
||||||
} sym;
|
} sym;
|
||||||
double dbl; /* cat NSC_VAL, type NSC_DOUBLE */
|
double dbl; /* cat NSC_VAL, type NSC_DOUBLE */
|
||||||
struct { /* cat NSC_VAL, type NSC_STRING, cat NSC_ID */
|
struct { /* cat NSC_VAL, type NSC_STRING, cat NSC_ID */
|
||||||
|
@ -197,11 +205,16 @@ typedef unsigned char nsc_flags;
|
||||||
*
|
*
|
||||||
* A selector describes an attribute of some context object.
|
* A selector describes an attribute of some context object.
|
||||||
* A selector with ca_type NSC_NOTYPE is invalid.
|
* A selector with ca_type NSC_NOTYPE is invalid.
|
||||||
* A valid selector describes a datum of type ca_type at offset
|
* If ca_get is null, the selector describes a datum of type ca_type
|
||||||
* ca_offs in the context object.
|
* at offset ca_offs in the context object.
|
||||||
* A datum of type NSC_STRINGY is an array of ca_len characters.
|
* A datum of type NSC_STRINGY is an array of ca_len characters.
|
||||||
* A datum of any other type is either a scalar of that type (if
|
* A datum of any other type is either a scalar of that type (if
|
||||||
* ca_len is zero), or an array of ca_len elements of that type.
|
* ca_len is zero), or an array of ca_len elements of that type.
|
||||||
|
* If ca_get is not null, the selector is virtual. Values can be
|
||||||
|
* obtained by calling ca_get(VAL, CNUM, CTXO), where VAL has been
|
||||||
|
* initialized from the selector and an index, CNUM is the country to
|
||||||
|
* use for coordinate translation and access control, and CTXO is the
|
||||||
|
* context object. See struct valstr for details.
|
||||||
* If flag NSC_DEITY is set, only to deities can use this selector.
|
* If flag NSC_DEITY is set, only to deities can use this selector.
|
||||||
* If flag NSC_EXTRA is set, xdump ignores this selector.
|
* If flag NSC_EXTRA is set, xdump ignores this selector.
|
||||||
* If flag NSC_CONST is set, the datum can't be changed from its
|
* If flag NSC_CONST is set, the datum can't be changed from its
|
||||||
|
@ -216,6 +229,7 @@ struct castr {
|
||||||
ptrdiff_t ca_off;
|
ptrdiff_t ca_off;
|
||||||
packed_nsc_type ca_type;
|
packed_nsc_type ca_type;
|
||||||
unsigned short ca_len;
|
unsigned short ca_len;
|
||||||
|
void *(*ca_get)(struct valstr *, natid, void *);
|
||||||
int ca_table;
|
int ca_table;
|
||||||
nsc_flags ca_flags;
|
nsc_flags ca_flags;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
.LV Expert
|
.LV Expert
|
||||||
.SY "xdump <TYPE|NUMBER> <RECORDS>"
|
.SY "xdump <TYPE|NUMBER> <RECORDS>"
|
||||||
.SY "xdump meta <TYPE|NUMBER>"
|
.SY "xdump meta <TYPE|NUMBER>"
|
||||||
.SY "xdump ver"
|
|
||||||
.SY "xdump meta ver"
|
|
||||||
The xdump command displays information on game configuration and state
|
The xdump command displays information on game configuration and state
|
||||||
in machine readable format. It is intended for use by clients and
|
in machine readable format. It is intended for use by clients and
|
||||||
tools. This info page gives an overview; see doc/xdump in the source
|
tools. This info page gives an overview; see doc/xdump in the source
|
||||||
|
|
|
@ -87,21 +87,19 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Evaluate a attribute of an object into VAL, return VAL.
|
* Evaluate a attribute of an object into VAL, return VAL.
|
||||||
* TYPE is the attribute's type.
|
* CA describes the attribute.
|
||||||
* PTR points to the context object.
|
* PTR points to the context object.
|
||||||
* The attribute is stored there at offset OFF + IDX * S, where S is
|
* IDX is the index within the attribute.
|
||||||
* its size.
|
|
||||||
* LEN is the #array elements if it is an array, else zero.
|
|
||||||
*/
|
*/
|
||||||
static struct valstr *
|
static struct valstr *
|
||||||
xdeval(struct valstr *val,
|
xdeval(struct valstr *val, struct castr *ca, void *ptr, int idx)
|
||||||
nsc_type type, void *ptr, ptrdiff_t off, int idx, int len)
|
|
||||||
{
|
{
|
||||||
val->val_type = type;
|
val->val_type = ca->ca_type;
|
||||||
val->val_cat = NSC_OFF;
|
val->val_cat = NSC_OFF;
|
||||||
val->val_as.sym.off = off;
|
val->val_as.sym.off = ca->ca_off;
|
||||||
val->val_as.sym.len = len;
|
val->val_as.sym.len = ca->ca_len;
|
||||||
val->val_as.sym.idx = idx;
|
val->val_as.sym.idx = idx;
|
||||||
|
val->val_as.sym.get = ca->ca_get;
|
||||||
return nstr_exec_val(val, player->cnum, ptr, NSC_NOTYPE);
|
return nstr_exec_val(val, player->cnum, ptr, NSC_NOTYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +173,7 @@ xdflds(struct castr ca[], void *ptr)
|
||||||
n = ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0;
|
n = ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0;
|
||||||
j = 0;
|
j = 0;
|
||||||
do {
|
do {
|
||||||
xdeval(&val, ca[i].ca_type, ptr, ca[i].ca_off, j, ca[i].ca_len);
|
xdeval(&val, &ca[i], ptr, j);
|
||||||
sep = xdprval(&val, sep);
|
sep = xdprval(&val, sep);
|
||||||
} while (++j < n);
|
} while (++j < n);
|
||||||
}
|
}
|
||||||
|
@ -337,62 +335,7 @@ xdmeta(int type)
|
||||||
return RET_OK;
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Extended dump command */
|
||||||
* Dump configkeys[], return RET_OK.
|
|
||||||
* If META, dump meta-data rather than data.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xdver(int meta)
|
|
||||||
{
|
|
||||||
static struct castr vers_ca = {
|
|
||||||
"version", 0, NSC_STRINGY, sizeof(PACKAGE_STRING), EF_BAD, 0
|
|
||||||
};
|
|
||||||
struct keymatch *kp;
|
|
||||||
char *sep;
|
|
||||||
int n;
|
|
||||||
struct castr ca;
|
|
||||||
struct valstr val;
|
|
||||||
|
|
||||||
xdhdr("version", meta);
|
|
||||||
|
|
||||||
if (meta) {
|
|
||||||
n = 0;
|
|
||||||
xdflds(mdchr_ca, &vers_ca);
|
|
||||||
pr("\n");
|
|
||||||
n++;
|
|
||||||
for (kp = configkeys; kp->km_key; ++kp) {
|
|
||||||
if (kp->km_type != NSC_NOTYPE && !(kp->km_flags & KM_INTERNAL)) {
|
|
||||||
ca.ca_type = kp->km_type;
|
|
||||||
ca.ca_flags = 0;
|
|
||||||
ca.ca_len = 0;
|
|
||||||
ca.ca_off = 0;
|
|
||||||
ca.ca_name = kp->km_key;
|
|
||||||
ca.ca_table = EF_BAD;
|
|
||||||
xdflds(mdchr_ca, &ca);
|
|
||||||
pr("\n");
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xdftr(n);
|
|
||||||
return RET_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
xdeval(&val, vers_ca.ca_type, version, vers_ca.ca_off, 0, vers_ca.ca_len);
|
|
||||||
sep = xdprval(&val, "");
|
|
||||||
for (kp = configkeys; kp->km_key; ++kp) {
|
|
||||||
if (kp->km_type != NSC_NOTYPE && !(kp->km_flags & KM_INTERNAL)) {
|
|
||||||
xdeval(&val, kp->km_type, kp->km_data, 0, 0, 0);
|
|
||||||
sep = xdprval(&val, sep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pr("\n");
|
|
||||||
|
|
||||||
xdftr(1);
|
|
||||||
|
|
||||||
return RET_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Experimental extended dump command */
|
|
||||||
int
|
int
|
||||||
xdump(void)
|
xdump(void)
|
||||||
{
|
{
|
||||||
|
@ -412,18 +355,17 @@ xdump(void)
|
||||||
|
|
||||||
natp = getnatp(player->cnum);
|
natp = getnatp(player->cnum);
|
||||||
type = isdigit(p[0]) ? atoi(p) : ef_byname(p);
|
type = isdigit(p[0]) ? atoi(p) : ef_byname(p);
|
||||||
if (type >= 0 && type < EF_MAX) {
|
if (type < 0 || type >= EF_MAX)
|
||||||
|
return RET_SYN;
|
||||||
|
|
||||||
if (meta)
|
if (meta)
|
||||||
return xdmeta(type);
|
return xdmeta(type);
|
||||||
else if ((EF_IS_GAME_STATE(type) || EF_IS_VIEW(type))
|
if ((EF_IS_GAME_STATE(type) || EF_IS_VIEW(type))
|
||||||
&& !(natp->nat_stat == STAT_ACTIVE || player->god)) {
|
&& !(natp->nat_stat == STAT_ACTIVE || player->god)) {
|
||||||
pr("Access to table %s denied\n", ef_nameof(type));
|
pr("Access to table %s denied\n", ef_nameof(type));
|
||||||
return RET_FAIL;
|
return RET_FAIL;
|
||||||
} else
|
}
|
||||||
|
if (type == EF_VERSION && !player->argp[2])
|
||||||
|
return xditem(type, "*"); /* backward compatibility */
|
||||||
return xditem(type, player->argp[2]);
|
return xditem(type, player->argp[2]);
|
||||||
} else if (!strncmp(p, "ver", strlen(p))) {
|
|
||||||
return xdver(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
return RET_SYN;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,7 @@ verify_row(int type, int row)
|
||||||
val.val_as.sym.off = ca[i].ca_off;
|
val.val_as.sym.off = ca[i].ca_off;
|
||||||
val.val_as.sym.len = ca[i].ca_len;
|
val.val_as.sym.len = ca[i].ca_len;
|
||||||
val.val_as.sym.idx = j;
|
val.val_as.sym.idx = j;
|
||||||
|
val.val_as.sym.get = ca[i].ca_get;
|
||||||
nstr_exec_val(&val, 0, row_ref, NSC_NOTYPE);
|
nstr_exec_val(&val, 0, row_ref, NSC_NOTYPE);
|
||||||
if (val.val_type != NSC_LONG)
|
if (val.val_type != NSC_LONG)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -55,16 +55,6 @@
|
||||||
#include "optlist.h"
|
#include "optlist.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
|
|
||||||
/* Dummy one */
|
|
||||||
static int emp_config_dummy;
|
|
||||||
|
|
||||||
/* things that can be changed */
|
|
||||||
struct keymatch configkeys[] = {
|
|
||||||
#define EMP_CONFIG_C_OUTPUT
|
|
||||||
#include "econfig-spec.h"
|
|
||||||
#undef EMP_CONFIG_C_OUTPUT
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct keymatch *keylookup(char *key, struct keymatch tbl[]);
|
static struct keymatch *keylookup(char *key, struct keymatch tbl[]);
|
||||||
static int set_paths(char *);
|
static int set_paths(char *);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,17 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
|
||||||
valtype = val->val_type;
|
valtype = val->val_type;
|
||||||
break;
|
break;
|
||||||
case NSC_OFF:
|
case NSC_OFF:
|
||||||
|
if (val->val_as.sym.get) {
|
||||||
|
do {
|
||||||
|
ptr = val->val_as.sym.get(val, cnum, ptr);
|
||||||
|
} while (ptr && val->val_as.sym.get);
|
||||||
|
if (!ptr) {
|
||||||
|
valtype = val->val_type;
|
||||||
|
val->val_cat = NSC_VAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
valtype = NSC_LONG;
|
valtype = NSC_LONG;
|
||||||
memb_ptr = ptr;
|
memb_ptr = ptr;
|
||||||
memb_ptr += val->val_as.sym.off;
|
memb_ptr += val->val_as.sym.off;
|
||||||
|
|
|
@ -221,3 +221,11 @@ float start_education = 0.0;
|
||||||
float start_happiness = 0.0;
|
float start_happiness = 0.0;
|
||||||
float start_technology = 0.0;
|
float start_technology = 0.0;
|
||||||
float start_research = 0.0;
|
float start_research = 0.0;
|
||||||
|
|
||||||
|
/* econfig keys */
|
||||||
|
static int emp_config_dummy;
|
||||||
|
struct keymatch configkeys[] = {
|
||||||
|
#define EMP_CONFIG_C_OUTPUT
|
||||||
|
#include "econfig-spec.h"
|
||||||
|
#undef EMP_CONFIG_C_OUTPUT
|
||||||
|
};
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "trade.h"
|
#include "trade.h"
|
||||||
#include "treaty.h"
|
#include "treaty.h"
|
||||||
|
#include "version.h"
|
||||||
#include "xy.h"
|
#include "xy.h"
|
||||||
|
|
||||||
/* Number of elements in ARRAY. */
|
/* Number of elements in ARRAY. */
|
||||||
|
@ -102,7 +103,8 @@ struct empfile empfile[] = {
|
||||||
* that can be changed by users.
|
* that can be changed by users.
|
||||||
*
|
*
|
||||||
* Whatever of the above can't be done here must be done in
|
* Whatever of the above can't be done here must be done in
|
||||||
* empfile_init() or empfile_fixup().
|
* empfile_init() or empfile_fixup(). Except cadef may be set in
|
||||||
|
* nsc_init() instead.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -187,10 +189,13 @@ struct empfile empfile[] = {
|
||||||
ARRAY_TABLE(update_time, EFF_CFG)},
|
ARRAY_TABLE(update_time, EFF_CFG)},
|
||||||
/*
|
/*
|
||||||
* Special tables. EF_META gets bogus size, cids and fids here.
|
* Special tables. EF_META gets bogus size, cids and fids here.
|
||||||
* Fixed up by empfile_init().
|
* Fixed up by empfile_init(). EF_VERSION's cadef is set by
|
||||||
|
* nsc_init().
|
||||||
*/
|
*/
|
||||||
{EF_TABLE, "table", NULL, empfile_ca,
|
{EF_TABLE, "table", NULL, empfile_ca,
|
||||||
ARRAY_TABLE(empfile, EFF_CFG)},
|
ARRAY_TABLE(empfile, EFF_CFG)},
|
||||||
|
{EF_VERSION, "version", NULL, NULL,
|
||||||
|
sizeof(PACKAGE_STRING), 0, version, 0, 0, 1, 1, -1, NULL, NULL},
|
||||||
{EF_META, "meta", NULL, mdchr_ca,
|
{EF_META, "meta", NULL, mdchr_ca,
|
||||||
PTR_CACHE(mdchr_ca, EFF_CFG)},
|
PTR_CACHE(mdchr_ca, EFF_CFG)},
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -432,6 +432,7 @@ nstr_resolve_sel(struct valstr *val, struct castr *ca)
|
||||||
val->val_as.sym.off = ca->ca_off;
|
val->val_as.sym.off = ca->ca_off;
|
||||||
val->val_as.sym.len = ca->ca_len;
|
val->val_as.sym.len = ca->ca_len;
|
||||||
val->val_as.sym.idx = 0;
|
val->val_as.sym.idx = 0;
|
||||||
|
val->val_as.sym.get = ca->ca_get;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue