コード例 #1
1
ファイル: xdump.c プロジェクト: gefla/empserver
/*
 * Dump items of type @type selected by @arg to @xd.
 * Return RET_OK on success, RET_SYN on error.
 */
static int
xditem(struct xdstr *xd, int type, char *arg)
{
    struct castr *ca;
    struct nstr_item ni;
    int n;
    unsigned char buf[EF_WITH_CADEF_MAX_ENTRY_SIZE];

    ca = ef_cadef(type);
    if (!ca)
	return RET_SYN;

    if (!snxtitem(&ni, type, arg, NULL))
	return RET_SYN;

    xdhdr(xd, ef_nameof(type), 0);

    n = 0;
    while (nxtitem(&ni, buf)) {
	if (!xdvisible(type, buf))
	    continue;
	++n;
	xdflds(xd, ca, buf);
	xd->pr("\n");
    }

    xdftr(xd, n);

    return RET_OK;
}
コード例 #2
0
ファイル: xdump.c プロジェクト: gefla/empserver
/*
 * Dump @val prefixed with @sep to @xd, return " ".
 * @val must be evaluated.
 * @ca describes the field from which the value was fetched.
 */
static char *
xdprval_sym(struct xdstr *xd, struct valstr *val, struct castr *ca,
	    char *sep)
{
    unsigned long bit;

    if (CANT_HAPPEN(val->val_cat != NSC_VAL)) {
	xd->pr("%snil", sep);
	return " ";
    }

    if (!xd->human || val->val_type != NSC_LONG
	|| ca->ca_table == EF_BAD || ef_cadef(ca->ca_table) != symbol_ca)
	return xdprval_nosym(xd, val, sep);

    if (ca->ca_flags & NSC_BITS) {
	xd->pr("%s(", sep);
	sep = "";
	for (bit = 1; bit; bit <<= 1) {
	    if (bit & val->val_as.lng)
		sep = xdprsym(xd, bit, ca->ca_table, sep);
	}
	xd->pr(")");
	return " ";
    }

    return xdprsym(xd, val->val_as.lng, ca->ca_table, sep);
}
コード例 #3
0
ファイル: xdump.c プロジェクト: gefla/empserver
/*
 * Dump meta-data for items of type @type to @xd.
 * Return RET_SYN when @type doesn't have meta-data, else RET_OK.
 */
static int
xdmeta(struct xdstr *xd, int type)
{
    struct castr *ca = ef_cadef(type);
    int i;
    int n = 0;

    if (!ca)
	return RET_SYN;

    xdhdr(xd, ef_nameof(type), 1);
    xdcolhdr(xd, ca);

    for (i = 0; ca[i].ca_name; i++) {
	if (ca[i].ca_flags & NSC_DEITY && !xd->divine)
	    continue;
	if (ca[i].ca_dump == CA_DUMP_NONE)
	    continue;
	xdflds(xd, mdchr_ca, &ca[i]);
	xd->pr("\n");
	n++;
    }

    xdftr(xd, n);

    return RET_OK;
}
コード例 #4
0
/*
 * Compile a value in @str into @val.
 * Return a pointer to the first character after the value on success,
 * NULL on error.
 * @type is the context type, a file type.
 */
char *
nstr_comp_val(char *str, struct valstr *val, int type)
{
    struct castr *ca = ef_cadef(type);
    char *tail = nstr_parse_val(str, val);
    if (!nstr_resolve_id(val, ca, nstr_match_ca(val, ca)))
	return NULL;
    return tail;
}
コード例 #5
0
static int
verify_table(int type)
{
    int retval = 0;
    int i;

    if (!ef_cadef(type))
	return 0;
    verify_ca(type);
    for (i = 0; i < ef_nelem(type); i++)
	retval |= verify_row(type, i);
    return retval;
}
コード例 #6
0
static int
verify_tabref(int type, int row, struct castr *ca, int idx, long val)
{
    int tabno = ca->ca_table;
    struct castr *ca_sym = ef_cadef(tabno);
    int i;

    if (ca->ca_flags & NSC_BITS) {
	/* symbol set */
	if (CANT_HAPPEN(ca_sym != symbol_ca))
	    return -1;
	for (i = 0; i < (int)sizeof(long) * 8; i++) {
	    if (val & (1UL << i)) {
		if (!symbol_by_value(1L << i, ef_ptr(tabno, 0))) {
		    verify_fail(type, row, ca, idx,
				"bit %d is not in symbol table %s",
				i, ef_nameof(tabno));
		    return -1;
		}
	    }
	}
    } else if (ca_sym == symbol_ca) {
	/* symbol */
	if (!symbol_by_value(val, ef_ptr(tabno, 0))) {
	    verify_fail(type, row, ca, idx,
			"value %ld is not in symbol table %s",
			val, ef_nameof(tabno));
	    return -1;
	}
    } else {
	/* table index */
	if (val >= ef_nelem(tabno) || val < -1) {
	    verify_fail(type, row, ca, idx,
			"value %ld indexes table %s out of bounds 0..%d",
			val, ef_nameof(tabno), ef_nelem(tabno));
	    return -1;
	}
	/* laziness: assumes TABNO is EFF_MEM */
	if (val >= 0 && !empobj_in_use(tabno, ef_ptr(tabno, val))) {
	    verify_fail(type, row, ca, idx,
			"value %ld refers to missing element of table %s",
			val, ef_nameof(tabno));
	    return -1;
	}
    }
    return 0;
}
コード例 #7
0
/*
 * Search table @type for an element matching @name, return its index.
 * Accepts EF_BAD, but of course never finds anything then.
 * Return M_NOTFOUND if there are no matches, M_NOTUNIQUE if there are
 * several.
 */
int
ef_elt_byname(int type, char *name)
{
    switch (type) {
    case EF_BAD:
	return M_NOTFOUND;
    case EF_NATION:
	return cnumb(name);
    case EF_SECTOR_CHR:
	return sct_typematch(name);
    case EF_SHIP_CHR:
	return stmtch(name, mchr,
		      offsetof(struct mchrstr, m_name),
		      sizeof(mchr[0]));
    case EF_LAND_CHR:
	return stmtch(name, lchr,
		      offsetof(struct lchrstr, l_name),
		      sizeof(lchr[0]));
    case EF_PLANE_CHR:
	return stmtch(name, plchr,
		      offsetof(struct plchrstr, pl_name),
		      sizeof(plchr[0]));
    case EF_NUKE_CHR:
	return stmtch(name, nchr,
		      offsetof(struct nchrstr, n_name),
		      sizeof(nchr[0]));
    case EF_ITEM:
	return stmtch(name, ichr,
		      offsetof(struct ichrstr, i_name),
		      sizeof(ichr[0]));
    case EF_PRODUCT:
	return stmtch(name, pchr,
		      offsetof(struct pchrstr, p_sname),
		      sizeof(pchr[0]));
    case EF_TABLE:
	return stmtch(name, empfile,
		      offsetof(struct empfile, name),
		      sizeof(empfile[0]));
    default:
	if (ef_cadef(type) == symbol_ca)
	    return stmtch(name, ef_ptr(type, 0),
			  offsetof(struct symbol, name),
			  sizeof(struct symbol));
    }
    return M_NOTFOUND;
}
コード例 #8
0
static int
verify_ca(int type)
{
    struct castr *ca = ef_cadef(type);
    int i;

    for (i = 0; ca[i].ca_name; i++) {
	/*
	 * Virtual selectors must be NSC_EXTRA, because xundump can't
	 * cope with them without setter methods.  Exception: if
	 * EFF_MEM is not set, xundump doesn't touch the table.
	 */
	if (CANT_HAPPEN((ef_flags(type) & EFF_MEM)
			&& ca[i].ca_get && !(ca[i].ca_flags & NSC_EXTRA)))
	    ca[i].ca_flags |= NSC_EXTRA;
    }
    return 0;
}
コード例 #9
0
static int
verify_row(int type, int row)
{
    struct castr *ca = ef_cadef(type);
    struct empobj *row_ref;
    int i, j, n;
    struct valstr val;
    int ret_val = 0;
    int flags = ef_flags(type);

    if (flags & EFF_MEM)
	row_ref = ef_ptr(type, row);
    else {
	row_ref = malloc(empfile[type].size);
	ef_read(type, row, row_ref);
    }

    if ((flags & EFF_TYPED) && !EF_IS_VIEW(type)) {
	if (row_ref->ef_type != type || row_ref->uid != row) {
	    verify_fail(type, row, NULL, 0, "header corrupt");
	    ret_val = -1;
	}
    }

    if (!empobj_in_use(type, row_ref))
	goto out;

    for (i = 0; ca[i].ca_name; ++i) {
	if (ca[i].ca_get)
	    continue;		/* virtual */
	n = CA_ARRAY_LEN(&ca[i]);
	j = 0;
	do {
	    if (ca[i].ca_table == EF_BAD)
		continue;
	    nstr_mksymval(&val, &ca[i], j);
	    nstr_eval(&val, 0, row_ref, NSC_NOTYPE);
	    if (CANT_HAPPEN(val.val_type != NSC_LONG)) {
		ret_val = -1;
		continue;
	    }
	    if (ca[i].ca_table == type && i == 0) {
		/* uid */
		if (val.val_as.lng != row) {
		    verify_fail(type, row, &ca[i], j,
				"value is %ld instead of %d",
				val.val_as.lng, row);
		    ret_val = -1;
		}
	    } else {
		if (verify_tabref(type, row, &ca[i], j, val.val_as.lng) < 0)
		    ret_val = -1;
	    }
	} while (++j < n);
    }

out:
    if (!(flags & EFF_MEM))
	free(row_ref);
    return ret_val;
}
コード例 #10
0
/*
 * Compile conditions into array @np[@len].
 * Return number of conditions, or -1 on error.
 * It is an error if there are more than @len conditions.
 * @type is the context type, a file type.
 * @str is the condition string, in Empire syntax, without the leading
 * '?'.
 */
int
nstr_comp(struct nscstr *np, int len, int type, char *str)
{
    struct castr *ca = ef_cadef(type);
    char *cond;
    char *tail;
    int i;
    struct nscstr dummy;
    int lft_caidx, rgt_caidx;
    int lft_val, rgt_val;
    int two_sels;

    cond = str;
    for (i = 0; ; ++i, ++np) {
	if (i >= len)
	    np = &dummy;

	/* left operand */
	if (!*cond) {
	    pr("%s -- %scondition expected\n", str, i ? "another " : "");
	    return -1;
	}
	tail = nstr_parse_val(cond, &np->lft);
	lft_caidx = nstr_match_ca(&np->lft, ca);

	/* operator */
	if (*tail != '<' && *tail != '=' && *tail != '>' && *tail != '#') {
	    if (*tail)
		pr("%s -- expected condition operator\n", cond);
	    else
		pr("%s -- missing condition operator\n", cond);
	    return -1;
	}
	np->operator = *tail;
	++tail;

	/* right operand */
	if (!*tail) {
	    pr("%s -- operand expected\n", cond);
	    return -1;
	}
	tail = nstr_parse_val(tail, &np->rgt);
	rgt_caidx = nstr_match_ca(&np->rgt, ca);

	/*
	 * Resolve identifiers
	 *
	 * If just one operand is an identifier, it names a selector.
	 * If both operands are identifiers, things get complicated:
	 * either can then name a selector or a symbolic value for the
	 * selector named by the other operand.
	 */
	if (np->lft.val_cat == NSC_ID && np->rgt.val_cat == NSC_ID) {
	    lft_val = nstr_match_val(&np->lft, ca, rgt_caidx);
	    rgt_val = nstr_match_val(&np->rgt, ca, lft_caidx);
	    two_sels = nstr_ca_comparable(ca, lft_caidx, rgt_caidx);
	    /*
	     * If lft_val >= 0 interpreting rgt as a selector and lft
	     * as one of its values works.  Likewise for rgt_val >= 0.
	     * If two_sels, interpreting both lft and rgt as selector
	     * works.
	     */
	    switch ((lft_val >= 0) + (rgt_val >= 0) + !!two_sels) {
	    case 0:		/* no interpretation */
		if (lft_caidx >= 0 && rgt_caidx >= 0) {
		    /*
		     * Both identifiers name selectors.  Since
		     * !two_sels, they can't be comparable.
		     * Example: type=civil.
		     */
		    pr("%.*s -- not comparable\n", (int)(tail-cond), cond);
		    return -1;
		}
		/*
		 * At least one identifier doesn't name a selector,
		 * and nstr_resolve_id() will fail for it below
		 */
		break;
	    case 1:		/* one unambigous interpretation */
		break;
	    default:		/* multiple interpretations */
		/*
		 * Last-resort disambiguation: if the identifier is
		 * the unabbreviated name of a selector, discard
		 * value, else discard selector interpretation.
		 * Example: resolve wing=g to wing='g', not wing=group
		 * or 'wing'=group.
		 */
		if (nstr_is_name_of_ca(&np->lft, ca, lft_caidx))
		    lft_val = -1;
		else
		    two_sels = 0;
		if (nstr_is_name_of_ca(&np->rgt, ca, rgt_caidx))
		    rgt_val = -1;
		else
		    two_sels = 0;
		if ((lft_val >= 0) + (rgt_val >= 0) + !!two_sels == 1)
		    break;	/* last-resort disambiguation worked */
		/*
		 * Example: n<n for sectors could mean newdes<n or
		 * n<newdes.
		 */
		pr("%.*s -- condition ambiguous\n", (int)(tail-cond), cond);
		return -1;
	    }
	    /* resolve identifiers naming values */
	    if (lft_val >= 0)
		nstr_resolve_val(&np->lft, lft_val, &ca[rgt_caidx]);
	    if (rgt_val >= 0)
		nstr_resolve_val(&np->rgt, rgt_val, &ca[lft_caidx]);
	}
	/* remaining identifiers name selectors */
	if (!nstr_resolve_id(&np->lft, ca, lft_caidx))
	    return -1;
	if (!nstr_resolve_id(&np->rgt, ca, rgt_caidx))
	    return -1;

	/* find operator type */
	np->optype = nstr_optype(np->lft.val_type, np->rgt.val_type);
	if (np->optype == NSC_NOTYPE) {
	    pr("%.*s -- not comparable\n", (int)(tail-cond), cond);
	    return -1;
	}

	/* another condition? */
	if (*tail == 0)
	    break;
	if (*tail != '&') {
	    pr("%s -- expected `&'\n", cond);
	    return -1;
	}
	cond = tail + 1;
    }

    if (i >= len) {
	/* could just return I and let caller gripe or enlarge buffer */
	pr("%s -- too many conditions\n", str);
	return -1;
    }

    return i + 1;
}