示例#1
0
bool expr_handler::fold_alu_op3(alu_node& n) {

	if (n.src.size() < 3)
		return false;

	if (!sh.safe_math && (n.bc.op_ptr->flags & AF_M_ASSOC)) {
		if (fold_assoc(&n))
			return true;
		if (n.src.size() < 3)
			return fold_alu_op2(n);
	}

	value* v0 = n.src[0]->gvalue();
	value* v1 = n.src[1]->gvalue();
	value* v2 = n.src[2]->gvalue();

	/* LDS instructions look like op3 with no dst - don't fold. */
	if (!n.dst[0])
		return false;
	assert(v0 && v1 && v2 && n.dst[0]);

	bool isc0 = v0->is_const();
	bool isc1 = v1->is_const();
	bool isc2 = v2->is_const();

	literal dv, cv0, cv1, cv2;

	if (isc0) {
		cv0 = v0->get_const_value();
		apply_alu_src_mod(n.bc, 0, cv0);
	}

	if (isc1) {
		cv1 = v1->get_const_value();
		apply_alu_src_mod(n.bc, 1, cv1);
	}

	if (isc2) {
		cv2 = v2->get_const_value();
		apply_alu_src_mod(n.bc, 2, cv2);
	}

	unsigned flags = n.bc.op_ptr->flags;

	if (flags & AF_CMOV) {
		int src = 0;

		if (v1 == v2 && n.bc.src[1].neg == n.bc.src[2].neg) {
			// result doesn't depend on condition, convert to MOV
			src = 1;
		} else if (isc0) {
			// src0 is const, condition can be evaluated, convert to MOV
			bool cond = evaluate_condition(n.bc.op_ptr->flags & (AF_CC_MASK |
					AF_CMP_TYPE_MASK), cv0, literal(0));
			src = cond ? 1 : 2;
		}

		if (src) {
			// if src is selected, convert to MOV
			convert_to_mov(n, n.src[src], n.bc.src[src].neg);
			return fold_alu_op1(n);
		}
	}

	// handle (MULADD a, x, MUL (x, b)) => (MUL x, ADD (a, b))
	if (!sh.safe_math && (n.bc.op == ALU_OP3_MULADD ||
			n.bc.op == ALU_OP3_MULADD_IEEE)) {

		unsigned op = n.bc.op == ALU_OP3_MULADD_IEEE ?
				ALU_OP2_MUL_IEEE : ALU_OP2_MUL;

		if (!isc2 && v2->def && v2->def->is_alu_op(op)) {

			alu_node *md = static_cast<alu_node*>(v2->def);
			value *mv0 = md->src[0]->gvalue();
			value *mv1 = md->src[1]->gvalue();

			int es0 = -1, es1;

			if (v0 == mv0) {
				es0 = 0;
				es1 = 0;
			} else if (v0 == mv1) {
				es0 = 0;
				es1 = 1;
			} else if (v1 == mv0) {
				es0 = 1;
				es1 = 0;
			} else if (v1 == mv1) {
				es0 = 1;
				es1 = 1;
			}

			value *va0 = es0 == 0 ? v1 : v0;
			value *va1 = es1 == 0 ? mv1 : mv0;

			/* Don't fold if no equal multipliers were found.
			 * Also don#t fold if the operands of the to be created ADD are both
			 * relatively accessed with different AR values because that would
			 * create impossible code.
			 */
			if (es0 != -1 &&
			    (!va0->is_rel() || !va1->is_rel() ||
			     (va0->rel == va1->rel))) {

				alu_node *add = sh.create_alu();
				add->bc.set_op(ALU_OP2_ADD);

				add->dst.resize(1);
				add->src.resize(2);

				value *t = sh.create_temp_value();
				t->def = add;
				add->dst[0] = t;
				add->src[0] = va0;
				add->src[1] = va1;
				add->bc.src[0] = n.bc.src[!es0];
				add->bc.src[1] = md->bc.src[!es1];

				add->bc.src[1].neg ^= n.bc.src[2].neg ^
						(n.bc.src[es0].neg != md->bc.src[es1].neg);

				n.insert_before(add);
				vt.add_value(t);

				t = t->gvalue();

				if (es0 == 1) {
					n.src[0] = n.src[1];
					n.bc.src[0] = n.bc.src[1];
				}

				n.src[1] = t;
				memset(&n.bc.src[1], 0, sizeof(bc_alu_src));

				n.src.resize(2);

				n.bc.set_op(op);
				return fold_alu_op2(n);
			}
		}
	}

	if (!isc0 && !isc1 && !isc2)
		return false;

	if (isc0 && isc1 && isc2) {
		switch (n.bc.op) {
		case ALU_OP3_MULADD_IEEE:
		case ALU_OP3_MULADD: dv = cv0.f * cv1.f + cv2.f; break;

		// TODO

		default:
			return false;
		}
	} else {
		if (isc0 && isc1) {
			switch (n.bc.op) {
			case ALU_OP3_MULADD:
			case ALU_OP3_MULADD_IEEE:
				dv = cv0.f * cv1.f;
				n.bc.set_op(ALU_OP2_ADD);
				n.src[0] = sh.get_const_value(dv);
				memset(&n.bc.src[0], 0, sizeof(bc_alu_src));
				n.src[1] = n.src[2];
				n.bc.src[1] = n.bc.src[2];
				n.src.resize(2);
				return fold_alu_op2(n);
			}
		}

		if (n.bc.op == ALU_OP3_MULADD) {
			if ((isc0 && cv0 == literal(0)) || (isc1 && cv1 == literal(0))) {
				convert_to_mov(n, n.src[2], n.bc.src[2].neg,  n.bc.src[2].abs);
				return fold_alu_op1(n);
			}
		}

		if (n.bc.op == ALU_OP3_MULADD || n.bc.op == ALU_OP3_MULADD_IEEE) {
			unsigned op = n.bc.op == ALU_OP3_MULADD_IEEE ?
					ALU_OP2_MUL_IEEE : ALU_OP2_MUL;

			if (isc1 && v0 == v2) {
				cv1.f += (n.bc.src[2].neg != n.bc.src[0].neg ? -1.0f : 1.0f);
				n.src[1] = sh.get_const_value(cv1);
				n.bc.src[1].neg = 0;
				n.bc.src[1].abs = 0;
				n.bc.set_op(op);
				n.src.resize(2);
				return fold_alu_op2(n);
			} else if (isc0 && v1 == v2) {
				cv0.f += (n.bc.src[2].neg != n.bc.src[1].neg ? -1.0f : 1.0f);
				n.src[0] = sh.get_const_value(cv0);
				n.bc.src[0].neg = 0;
				n.bc.src[0].abs = 0;
				n.bc.set_op(op);
				n.src.resize(2);
				return fold_alu_op2(n);
			}
		}

		return false;
	}

	apply_alu_dst_mod(n.bc, dv);
	assign_source(n.dst[0], get_const(dv));
	return true;
}
示例#2
0
// fold the chain of associative ops, e.g. (ADD 2, (ADD x, 3)) => (ADD x, 5)
bool expr_handler::fold_assoc(alu_node *n) {

	alu_node *a = n;
	literal cr;

	int last_arg = -3;

	unsigned op = n->bc.op;
	bool allow_neg = false, cur_neg = false;
	bool distribute_neg = false;

	switch(op) {
	case ALU_OP2_ADD:
		distribute_neg = true;
		allow_neg = true;
		break;
	case ALU_OP2_MUL:
	case ALU_OP2_MUL_IEEE:
		allow_neg = true;
		break;
	case ALU_OP3_MULADD:
		allow_neg = true;
		op = ALU_OP2_MUL;
		break;
	case ALU_OP3_MULADD_IEEE:
		allow_neg = true;
		op = ALU_OP2_MUL_IEEE;
		break;
	default:
		if (n->bc.op_ptr->src_count != 2)
			return false;
	}

	// check if we can evaluate the op
	if (!eval_const_op(op, cr, literal(0), literal(0)))
		return false;

	while (true) {

		value *v0 = a->src[0]->gvalue();
		value *v1 = a->src[1]->gvalue();

		last_arg = -2;

		if (v1->is_const()) {
			literal arg = v1->get_const_value();
			apply_alu_src_mod(a->bc, 1, arg);
			if (cur_neg && distribute_neg)
				arg.f = -arg.f;

			if (a == n)
				cr = arg;
			else
				eval_const_op(op, cr, cr, arg);

			if (v0->def) {
				alu_node *d0 = static_cast<alu_node*>(v0->def);
				if ((d0->is_alu_op(op) ||
						(op == ALU_OP2_MUL_IEEE &&
								d0->is_alu_op(ALU_OP2_MUL))) &&
						!d0->bc.omod && !d0->bc.clamp &&
						!a->bc.src[0].abs &&
						(!a->bc.src[0].neg || allow_neg)) {
					cur_neg ^= a->bc.src[0].neg;
					a = d0;
					continue;
				}
			}
			last_arg = 0;

		}

		if (v0->is_const()) {
			literal arg = v0->get_const_value();
			apply_alu_src_mod(a->bc, 0, arg);
			if (cur_neg && distribute_neg)
				arg.f = -arg.f;

			if (last_arg == 0) {
				eval_const_op(op, cr, cr, arg);
				last_arg = -1;
				break;
			}

			if (a == n)
				cr = arg;
			else
				eval_const_op(op, cr, cr, arg);

			if (v1->def) {
				alu_node *d1 = static_cast<alu_node*>(v1->def);
				if ((d1->is_alu_op(op) ||
						(op == ALU_OP2_MUL_IEEE &&
								d1->is_alu_op(ALU_OP2_MUL))) &&
						!d1->bc.omod && !d1->bc.clamp &&
						!a->bc.src[1].abs &&
						(!a->bc.src[1].neg || allow_neg)) {
					cur_neg ^= a->bc.src[1].neg;
					a = d1;
					continue;
				}
			}

			last_arg = 1;
		}

		break;
	};

	if (last_arg == -1) {
		// result is const
		apply_alu_dst_mod(n->bc, cr);

		if (n->bc.op == op) {
			convert_to_mov(*n, sh.get_const_value(cr));
			fold_alu_op1(*n);
			return true;
		} else { // MULADD => ADD
			n->src[0] = n->src[2];
			n->bc.src[0] = n->bc.src[2];
			n->src[1] = sh.get_const_value(cr);
			memset(&n->bc.src[1], 0, sizeof(bc_alu_src));

			n->src.resize(2);
			n->bc.set_op(ALU_OP2_ADD);
		}
	} else if (last_arg >= 0) {
		n->src[0] = a->src[last_arg];
		n->bc.src[0] = a->bc.src[last_arg];
		n->bc.src[0].neg ^= cur_neg;
		n->src[1] = sh.get_const_value(cr);
		memset(&n->bc.src[1], 0, sizeof(bc_alu_src));
	}

	return false;
}
示例#3
0
bool expr_handler::fold_alu_op2(alu_node& n) {

	if (n.src.size() < 2)
		return false;

	unsigned flags = n.bc.op_ptr->flags;

	if (flags & AF_SET) {
		return fold_setcc(n);
	}

	if (!sh.safe_math && (flags & AF_M_ASSOC)) {
		if (fold_assoc(&n))
			return true;
	}

	value* v0 = n.src[0]->gvalue();
	value* v1 = n.src[1]->gvalue();

	assert(v0 && v1);

	// handle some operations with equal args, e.g. x + x => x * 2
	if (v0 == v1) {
		if (n.bc.src[0].neg == n.bc.src[1].neg &&
				n.bc.src[0].abs == n.bc.src[1].abs) {
			switch (n.bc.op) {
			case ALU_OP2_MIN: // (MIN x, x) => (MOV x)
			case ALU_OP2_MIN_DX10:
			case ALU_OP2_MAX:
			case ALU_OP2_MAX_DX10:
				convert_to_mov(n, v0, n.bc.src[0].neg, n.bc.src[0].abs);
				return fold_alu_op1(n);
			case ALU_OP2_ADD:  // (ADD x, x) => (MUL x, 2)
				if (!sh.safe_math) {
					n.src[1] = sh.get_const_value(2.0f);
					memset(&n.bc.src[1], 0, sizeof(bc_alu_src));
					n.bc.set_op(ALU_OP2_MUL);
					return fold_alu_op2(n);
				}
				break;
			}
		}
		if (n.bc.src[0].neg != n.bc.src[1].neg &&
				n.bc.src[0].abs == n.bc.src[1].abs) {
			switch (n.bc.op) {
			case ALU_OP2_ADD:  // (ADD x, -x) => (MOV 0)
				if (!sh.safe_math) {
					convert_to_mov(n, sh.get_const_value(literal(0)));
					return fold_alu_op1(n);
				}
				break;
			}
		}
	}

	if (n.bc.op == ALU_OP2_ADD) {
		if (fold_mul_add(&n))
			return true;
	}

	bool isc0 = v0->is_const();
	bool isc1 = v1->is_const();

	if (!isc0 && !isc1)
		return false;

	literal dv, cv0, cv1;

	if (isc0) {
		cv0 = v0->get_const_value();
		apply_alu_src_mod(n.bc, 0, cv0);
	}

	if (isc1) {
		cv1 = v1->get_const_value();
		apply_alu_src_mod(n.bc, 1, cv1);
	}

	if (isc0 && isc1) {

		if (!eval_const_op(n.bc.op, dv, cv0, cv1))
			return false;

	} else { // one source is const

		if (isc0 && cv0 == literal(0)) {
			switch (n.bc.op) {
			case ALU_OP2_ADD:
			case ALU_OP2_ADD_INT:
			case ALU_OP2_MAX_UINT:
			case ALU_OP2_OR_INT:
			case ALU_OP2_XOR_INT:
				convert_to_mov(n, n.src[1], n.bc.src[1].neg,  n.bc.src[1].abs);
				return fold_alu_op1(n);
			case ALU_OP2_AND_INT:
			case ALU_OP2_ASHR_INT:
			case ALU_OP2_LSHL_INT:
			case ALU_OP2_LSHR_INT:
			case ALU_OP2_MIN_UINT:
			case ALU_OP2_MUL:
			case ALU_OP2_MULHI_UINT:
			case ALU_OP2_MULLO_UINT:
				convert_to_mov(n, sh.get_const_value(literal(0)));
				return fold_alu_op1(n);
			}
		} else if (isc1 && cv1 == literal(0)) {
			switch (n.bc.op) {
			case ALU_OP2_ADD:
			case ALU_OP2_ADD_INT:
			case ALU_OP2_ASHR_INT:
			case ALU_OP2_LSHL_INT:
			case ALU_OP2_LSHR_INT:
			case ALU_OP2_MAX_UINT:
			case ALU_OP2_OR_INT:
			case ALU_OP2_SUB_INT:
			case ALU_OP2_XOR_INT:
				convert_to_mov(n, n.src[0], n.bc.src[0].neg,  n.bc.src[0].abs);
				return fold_alu_op1(n);
			case ALU_OP2_AND_INT:
			case ALU_OP2_MIN_UINT:
			case ALU_OP2_MUL:
			case ALU_OP2_MULHI_UINT:
			case ALU_OP2_MULLO_UINT:
				convert_to_mov(n, sh.get_const_value(literal(0)));
				return fold_alu_op1(n);
			}
		} else if (isc0 && cv0 == literal(1.0f)) {
			switch (n.bc.op) {
			case ALU_OP2_MUL:
			case ALU_OP2_MUL_IEEE:
				convert_to_mov(n, n.src[1], n.bc.src[1].neg,  n.bc.src[1].abs);
				return fold_alu_op1(n);
			}
		} else if (isc1 && cv1 == literal(1.0f)) {
			switch (n.bc.op) {
			case ALU_OP2_MUL:
			case ALU_OP2_MUL_IEEE:
				convert_to_mov(n, n.src[0], n.bc.src[0].neg,  n.bc.src[0].abs);
				return fold_alu_op1(n);
			}
		}

		return false;
	}

	apply_alu_dst_mod(n.bc, dv);
	assign_source(n.dst[0], get_const(dv));
	return true;
}
示例#4
0
static void edit_float( const dsc* desc, pics* picture, TEXT** output)
{
    /**************************************
     *
     *	e d i t _ f l o a t
     *
     **************************************
     *
     * Functional description
     *	Edit data from a descriptor through an edit string to a running
     *	output pointer.
     *
     **************************************/
    TEXT temp[512];
    USHORT l, width, decimal_digits, w_digits, f_digits;

    double number = MOVQ_get_double(desc);
    const bool negative = (number < 0);
    if (negative)
        number = -number;

    // If exponents are explicitly requested (E-format edit_string), generate them.
    // Otherwise, the rules are: if the number in f-format will fit into the allotted
    // space, print it in f-format; otherwise print it in e-format.
    // (G-format is untrustworthy.)

    if (isnan(number))
        sprintf(temp, "NaN");
    else if (isinf(number))
        sprintf(temp, "Infinity");
    else if (picture->pic_exponents)
    {
        width = picture->pic_print_length - picture->pic_floats - picture->pic_literals;
        decimal_digits = picture->pic_fractions;
        sprintf(temp, "%*.*e", width, decimal_digits, number);
    }
    else if (number == 0)
        sprintf(temp, "%.0f", number);
    else
    {
        width = picture->pic_float_digits - 1 + picture->pic_floats;
        f_digits = (width > 2) ? width - 2 : 0;
        sprintf(temp, "%.*f", f_digits, number);
        w_digits = strlen(temp);
        if (f_digits)
        {
            TEXT* p = temp + w_digits;	// find the end
            w_digits = w_digits - (f_digits + 1);
            while (*--p == '0')
                --f_digits;
            if (*p != '.')
                ++p;
            *p = 0;				// move the end
        }
        if ((w_digits > width) || (!f_digits && w_digits == 1 && temp[0] == '0'))
        {
            // if the number doesn't fit in the default window, revert
            // to exponential notation; displaying the maximum number of
            // mantissa digits.

            if (number < 1e100)
                decimal_digits = (width > 6) ? width - 6 : 0;
            else
                decimal_digits = (width > 7) ? width - 7 : 0;
            sprintf(temp, "%.*e", decimal_digits, number);
        }
    }

    TEXT* p = temp;
    picture->pic_pointer = picture->pic_string;
    picture->pic_count = 0;
    TEXT* out = *output;

    for (l = picture->pic_length - picture->pic_print_length; l > 0; --l)
        *out++ = ' ';

    bool is_signed = false;

    for (;;)
    {
        const TEXT e = generate(picture);
        TEXT c = e;
        if (!c || c == '?')
            break;
        c = UPPER(c);

        switch (c)
        {
        case 'G':
            if (!is_signed)
            {
                if (negative)
                    *out++ = '-';
                else
                    *out++ = ' ';
                is_signed = true;
            }
            else if (*p)
                *out++ = *p++;
            break;

        case 'B':
            *out++ = ' ';
            break;

        case '"':
        case '\'':
        case '\\':
            literal(picture, c, &out);
            break;

        case '9':
        case 'Z':
        {
            if (!(*p) || *p > '9' || *p < '0')
                break;
            TEXT d = *p++;
            if (c == '9' && d == ' ')
                d = '0';
            else if (c == 'Z' && d == '0')
                d = ' ';
            *out++ = d;
        }
        break;

        case '.':
            *out++ = (*p == c) ? *p++ : c;
            break;

        case 'E':
            if (!*p)
                break;
            *out++ = e;
            if (UPPER(*p) == c)
                ++p;
            break;

        case '+':
        case '-':
            if (!*p)
                break;
            if (*p != '+' && *p != '-')
            {
                if (is_signed)
                    *out++ = c;
                else if (c == '-' && !negative)
                    *out++ = ' ';
                else if (c == '+' && negative)
                    *out++ = '-';
                else
                    *out++ = c;
                is_signed = true;
            }
            else if (*p == '-' || c == '+')
                *out++ = *p++;
            else
            {
                *out++ = ' ';
                p++;
            }
            break;

        default:
            *out++ = c;
            break;
        }
    }

    *output = out;
}
示例#5
0
bool expr_handler::fold_setcc(alu_node &n) {

	value* v0 = n.src[0]->gvalue();
	value* v1 = n.src[1]->gvalue();

	assert(v0 && v1 && n.dst[0]);

	unsigned flags = n.bc.op_ptr->flags;
	unsigned cc = flags & AF_CC_MASK;
	unsigned cmp_type = flags & AF_CMP_TYPE_MASK;
	unsigned dst_type = flags & AF_DST_TYPE_MASK;

	bool cond_result;
	bool have_result = false;

	bool isc0 = v0->is_const();
	bool isc1 = v1->is_const();

	literal dv, cv0, cv1;

	if (isc0) {
		cv0 = v0->get_const_value();
		apply_alu_src_mod(n.bc, 0, cv0);
	}

	if (isc1) {
		cv1 = v1->get_const_value();
		apply_alu_src_mod(n.bc, 1, cv1);
	}

	if (isc0 && isc1) {
		cond_result = evaluate_condition(flags, cv0, cv1);
		have_result = true;
	} else if (isc1) {
		if (cmp_type == AF_FLOAT_CMP) {
			if (n.bc.src[0].abs && !n.bc.src[0].neg) {
				if (cv1.f < 0.0f && (cc == AF_CC_GT || cc == AF_CC_NE)) {
					cond_result = true;
					have_result = true;
				} else if (cv1.f <= 0.0f && cc == AF_CC_GE) {
					cond_result = true;
					have_result = true;
				}
			} else if (n.bc.src[0].abs && n.bc.src[0].neg) {
				if (cv1.f > 0.0f && (cc == AF_CC_GE || cc == AF_CC_E)) {
					cond_result = false;
					have_result = true;
				} else if (cv1.f >= 0.0f && cc == AF_CC_GT) {
					cond_result = false;
					have_result = true;
				}
			}
		} else if (cmp_type == AF_UINT_CMP && cv1.u == 0 && cc == AF_CC_GE) {
			cond_result = true;
			have_result = true;
		}
	} else if (isc0) {
		if (cmp_type == AF_FLOAT_CMP) {
			if (n.bc.src[1].abs && !n.bc.src[1].neg) {
				if (cv0.f <= 0.0f && cc == AF_CC_GT) {
					cond_result = false;
					have_result = true;
				} else if (cv0.f < 0.0f && (cc == AF_CC_GE || cc == AF_CC_E)) {
					cond_result = false;
					have_result = true;
				}
			} else if (n.bc.src[1].abs && n.bc.src[1].neg) {
				if (cv0.f >= 0.0f && cc == AF_CC_GE) {
					cond_result = true;
					have_result = true;
				} else if (cv0.f > 0.0f && (cc == AF_CC_GT || cc == AF_CC_NE)) {
					cond_result = true;
					have_result = true;
				}
			}
		} else if (cmp_type == AF_UINT_CMP && cv0.u == 0 && cc == AF_CC_GT) {
			cond_result = false;
			have_result = true;
		}
	} else if (v0 == v1) {
		bc_alu_src &s0 = n.bc.src[0], &s1 = n.bc.src[1];
		if (s0.abs == s1.abs && s0.neg == s1.neg && cmp_type != AF_FLOAT_CMP) {
			// NOTE can't handle float comparisons here because of NaNs
			cond_result = (cc == AF_CC_E || cc == AF_CC_GE);
			have_result = true;
		}
	}

	if (have_result) {
		literal result;

		if (cond_result)
			result = dst_type != AF_FLOAT_DST ?
					literal(0xFFFFFFFFu) : literal(1.0f);
		else
			result = literal(0);

		convert_to_mov(n, sh.get_const_value(result));
		return fold_alu_op1(n);
	}

	return false;
}
示例#6
0
static void edit_alpha(const dsc* desc,
                       pics* picture, TEXT** output, USHORT max_length)
{
    /**************************************
     *
     *	e d i t _ a l p h a
     *
     **************************************
     *
     * Functional description
     *	Edit data from a descriptor through an edit string to a running
     *	output pointer.
     *
     **************************************/
    Firebird::VaryStr<512> temp;

    const TEXT* p = NULL;
    const USHORT l = MOVQ_get_string(desc, &p, &temp, sizeof(temp));
    const TEXT* const end = p + l;
    picture->pic_pointer = picture->pic_string;
    picture->pic_count = 0;
    TEXT* out = *output;

    while (p < end)
    {
        if ((out - *output) >= max_length)
            break;
        TEXT c = generate(picture);
        if (!c || c == '?')
            break;

        c = UPPER(c);

        switch (c)
        {
        case 'X':

            *out++ = *p++;
            break;

        case 'A':
            if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z'))
                *out++ = *p++;
            else
                IBERROR(69);	// Msg 69 conversion error
            break;

        case 'B':
            *out++ = ' ';
            break;

        case '"':
        case '\'':
        case '\\':
            literal(picture, c, &out);
            break;

        default:
            *out++ = c;
            break;
        }
    }

    *output = out;
}
示例#7
0
static void edit_date( const dsc* desc, pics* picture, TEXT** output)
{
    /**************************************
     *
     *	e d i t _ d a t e
     *
     **************************************
     *
     * Functional description
     *	Edit data from a descriptor through an edit string to a running
     *	output pointer.
     *
     **************************************/
    SLONG date[2];
    DSC temp_desc;
    TEXT d, temp[256];

    temp_desc.dsc_dtype = dtype_timestamp;
    temp_desc.dsc_scale = 0;
    temp_desc.dsc_sub_type = 0;
    temp_desc.dsc_length = sizeof(date);
    temp_desc.dsc_address = (UCHAR*) date;
    QLI_validate_desc(temp_desc);
    MOVQ_move(desc, &temp_desc);

    tm times;
    isc_decode_date((ISC_QUAD*) date, &times);
    TEXT* p = temp;

    const TEXT* nmonth = p;
    p = cvt_to_ascii((SLONG) times.tm_mon + 1, p, picture->pic_nmonths);

    const TEXT* day = p;
    p = cvt_to_ascii((SLONG) times.tm_mday, p, picture->pic_days);

    const TEXT* year = p;
    p = cvt_to_ascii((SLONG) times.tm_year + 1900, p, picture->pic_years);

    const TEXT* julians = p;
    p = cvt_to_ascii((SLONG) times.tm_yday + 1, p, picture->pic_julians);

    const TEXT* meridian = "";
    if (picture->pic_meridian)
    {
        if (times.tm_hour >= 12)
        {
            meridian = "PM";
            if (times.tm_hour > 12)
                times.tm_hour -= 12;
        }
        else
            meridian = "AM";
    }

    const SLONG seconds = date[1] % (60 * PRECISION);

    TEXT* hours = p;
    p = cvt_to_ascii((SLONG) times.tm_hour, p, picture->pic_hours);
    p = cvt_to_ascii((SLONG) times.tm_min, --p, picture->pic_minutes);
    p = cvt_to_ascii((SLONG) seconds, --p, 6);

    if (*hours == '0')
        *hours = ' ';

    SLONG rel_day = (date[0] + 3) % 7;
    if (rel_day < 0)
        rel_day += 7;
    const TEXT* weekday = alpha_weekdays[rel_day];
    const TEXT* month = alpha_months[times.tm_mon];

    picture->pic_pointer = picture->pic_string;
    picture->pic_count = 0;
    TEXT* out = *output;

    bool sig_day = false;
    bool blank = true;

    for (;;)
    {
        TEXT c = generate(picture);
        if (!c || c == '?')
            break;
        c = UPPER(c);

        switch (c)
        {
        case 'Y':
            *out++ = *year++;
            break;

        case 'M':
            if (*month)
                *out++ = *month++;
            break;

        case 'N':
            *out++ = *nmonth++;
            break;

        case 'D':
            d = *day++;
            if (!sig_day && d == '0' && blank)
                *out++ = ' ';
            else
            {
                sig_day = true;
                *out++ = d;
            }
            break;

        case 'J':
            if (*julians)
                *out++ = *julians++;
            break;

        case 'W':
            if (*weekday)
                *out++ = *weekday++;
            break;

        case 'B':
            *out++ = ' ';
            break;

        case 'P':
            if (*meridian)
                *out++ = *meridian++;
            break;

        case 'T':
            if (*hours)
                *out++ = *hours++;
            break;

        case '"':
        case '\'':
        case '\\':
            literal(picture, c, &out);
            break;

        default:
            *out++ = c;
            break;
        }
        if (c != 'B')
            blank = false;
    }

    *output = out;
}
示例#8
0
 oop protection_domain() { return literal(); }
示例#9
0
 symbolOop symbol() const          { return (symbolOop) literal(); }
示例#10
0
 bool equals(symbolOop class_name, oop class_loader) const {
   klassOop klass = (klassOop)literal();
   return (instanceKlass::cast(klass)->name() == class_name &&
           _loader == class_loader);
 }
示例#11
0
 klassOop klass() const { return (klassOop)literal(); }
 // Simple accessors, used only by SystemDictionary
 Symbol*            klassname()           const { return literal(); }