Ejemplo n.º 1
0
static int gbAsm(RAsm *a, RAsmOp *op, const char *buf) {
	int mn_len, i, len = 1;
	ut32 mn = 0;
	ut64 num;
	if (!a || !op || !buf)
		return 0;
	strncpy (op->buf_asm, buf, R_ASM_BUFSIZE-1);
	op->buf_asm[R_ASM_BUFSIZE-1] = 0;
	i = strlen (op->buf_asm);
	while (strstr (op->buf_asm, "  "))
		r_str_replace_in (op->buf_asm, (ut32)i, "  ", " ", R_TRUE);
	r_str_replace_in (op->buf_asm, (ut32)i, " ,", ",", R_TRUE);
	mn_len = r_str_do_until_token (str_op, op->buf_asm, ' ');
	if (mn_len < 2 || mn_len > 4)
		return 0;
	for (i = 0; i < mn_len; i++)
		mn = (mn << 8) | op->buf_asm[i];
	switch (mn) {
		case 0x6e6f70:			//nop
			op->buf[0] = 0x00;
			break;
		case 0x696e63:			//inc
			if ((i = strlen (op->buf_asm)) < 5)
				return op->size = 0;
			r_str_replace_in (op->buf_asm, (ut32)i, "[ ", "[", R_TRUE);
			r_str_replace_in (op->buf_asm, (ut32)i, " ]", "]", R_TRUE);
			r_str_do_until_token (str_op, &op->buf_asm[4], '\0');
			if (op->buf_asm[4] == 'b') {
				if (op->buf_asm[5] == 'c')
					op->buf[0] = 0x03;
				else	op->buf[0] = 0x04;
			} else if (op->buf_asm[4] == 'c')
				op->buf[0] = 0x0c;
			else if (op->buf_asm[4] == 'd') {
				if (op->buf_asm[5] == 'e')
					op->buf[0] = 0x13;
				else	op->buf[0] = 0x14;
			} else if (op->buf_asm[4] == 'e')
				op->buf[0] = 0x1c;
			else if (op->buf_asm[4] == 'h') {
				if (op->buf_asm[5] == 'l')
					op->buf[0] = 0x23;
				else	op->buf[0] = 0x24;
			} else if (op->buf_asm[4] == 'l')
				op->buf[0] = 0x2c;
			else if (op->buf_asm[4] == 'a')
				op->buf[0] = 0x3c;
			else if (op->buf_asm[4] == 's'
				&& op->buf_asm[5] == 'p')
				op->buf[0] = 0x33;
			else if (op->buf_asm[4] == '['
				&& op->buf_asm[5] == 'h'
				&& op->buf_asm[6] == 'l'
				&& op->buf_asm[7] == ']')
				op->buf[0] = 0x34;
			else	len = 0;	
			break;
		case 0x646563:			//dec
			if ((i = strlen (op->buf_asm)) < 5)
				return op->size = 0;
			r_str_replace_in (op->buf_asm, (ut32)i, "[ ", "[", R_TRUE);
			r_str_replace_in (op->buf_asm, (ut32)i, " ]", "]", R_TRUE);
			r_str_do_until_token (str_op, &op->buf_asm[4], '\0');
			if (op->buf_asm[4] == 'b') {
				if (op->buf_asm[5] == 'c')
					op->buf[0] = 0x0b;
				else	op->buf[0] = 0x05;
			} else if (op->buf_asm[4] == 'c')
				op->buf[0] = 0x0d;
			else if (op->buf_asm[4] == 'd') {
				if (op->buf_asm[5] == 'e')
					op->buf[0] = 0x1b;
				else	op->buf[0] = 0x15;
			} else if (op->buf_asm[4] == 'e')
				op->buf[0] = 0x1d;
			else if (op->buf_asm[4] == 'h') {
				if (op->buf_asm[5] == 'l')
					op->buf[0] = 0x2b;
				else	op->buf[0] = 0x25;
			} else if (op->buf_asm[4] == 'l')
				op->buf[0] = 0x2d;
			else if (op->buf_asm[4] == 'a')
				op->buf[0] = 0x3d;
			else if (op->buf_asm[4] == 's'
				&& op->buf_asm[5] == 'p')
				op->buf[0] = 0x3b;
			else if (op->buf_asm[4] == '['
				&& op->buf_asm[5] == 'h'
				&& op->buf_asm[6] == 'l'
				&& op->buf_asm[7] == ']')
				op->buf[0] = 0x35;
			else	len = 0;	
			break;
		case 0x726c6361:		//rlca
			op->buf[0] = 0x07;
			break;
		case 0x72726361:		//rrca
			op->buf[0] = 0xf0;
			break;
		case 0x73746f70:		//stop
			op->buf[0] = 0x10;
			break;
		case 0x726c61:			//rla
			op->buf[0] = 0x17;
			break;
		case 0x727261:			//rra
			op->buf[0] = 0x1f;
			break;
		case 0x646161:			//daa
			op->buf[0] = 0x27;
			break;
		case 0x63706c:			//cpl
			op->buf[0] = 0x2f;
			break;
		case 0x616464:			//add
			r_str_replace_in (op->buf_asm, strlen(op->buf_asm), ", ", ",", R_TRUE);
			if (strlen(op->buf_asm) < 5)
				return op->size = 0;
			if (op->buf_asm[4] == 's'
				&& op->buf_asm[5] == 'p'
				&& op->buf_asm[6] == ','
				&& op->buf_asm[7] != '\0') {
				op->buf[0] = 0xe8;
				num = r_num_get (NULL, &op->buf_asm[7]);
				op->buf[1] = (ut8)(num & 0xff);
				len = 2;
			}
			else if (!strcmp (op->buf_asm, "hl,bc"))
				op->buf[0] = 0x09;
			else if (!strcmp (&op->buf_asm[4], "hl,de"))
				op->buf[0] = 0x19;
			else if (!strcmp (&op->buf_asm[4], "hl,hl"))
				op->buf[0] = 0x29;
			else if (!strcmp (&op->buf_asm[4], "hl,sp"))
				op->buf[0] = 0x39;
			else	len = gb_parse_arith1 (op->buf, 5, op->buf_asm, 0x80, 0xc6);
			break;
		case 0x616463:			//adc
			len = gb_parse_arith1 (op->buf, 5, op->buf_asm, 0x88, 0xce);
			break;
		case 0x737562:			//sub
			len = gb_parse_arith1 (op->buf, 5, op->buf_asm, 0x90, 0xd6);
			break;
		case 0x736263:			//sbc
			len = gb_parse_arith1 (op->buf, 5, op->buf_asm, 0x98, 0xde);
			break;
		case 0x616e64:			//and
			len = gb_parse_arith1 (op->buf, 5, op->buf_asm, 0xa0, 0xe6);
			break;
		case 0x786f72:			//xor
			len = gb_parse_arith1 (op->buf, 5, op->buf_asm, 0xa8, 0xee);
			break;
		case 0x6f72:			//or
			len = gb_parse_arith1 (op->buf, 4, op->buf_asm, 0xb0, 0xf6);
			break;
		case 0x6370:			//cp
			len = gb_parse_arith1 (op->buf, 4, op->buf_asm, 0xb8, 0xfe);
			break;
		case 0x736366:			//scf
			op->buf[0] = 0x37;
			break;
		case 0x636366:			//ccf
			op->buf[0] = 0x3f;
			break;
		case 0x68616c74:		//halt
			op->buf[0] = 0x76;
			break;
		case 0x726574:			//ret
			if (strlen(op->buf_asm) < 5)
				op->buf[0] = 0xc9;
			else if (strlen (op->buf_asm) < 6) {	//there is no way that there can be "  " - we did r_str_replace_in
				str_op(&op->buf_asm[4]);
				if (op->buf_asm[4] == 'z')	//ret Z
					op->buf[0] = 0xc8;
				else if (op->buf_asm[4] == 'c')	//ret C
					op->buf[0] = 0xd8;
				else	return op->size = 0;
			} else {
				str_op(&op->buf_asm[4]);
				if (op->buf_asm[4] != 'n')
					return op->size = 0;
				str_op(&op->buf_asm[5]);	//if (!(strlen(op->buf_asm) < 6)) => must be 6 or greater
				if (op->buf_asm[5] == 'z')	//ret nZ
					op->buf[0] = 0xc0;
				else if (op->buf_asm[5] == 'c')	//ret nC
					op->buf[0] = 0xd0;
				else	return op->size = 0;
			}
			break;
		case 0x72657469:		//reti
			op->buf[0] = 0xd9;
			break;
		case 0x6469:			//di
			op->buf[0] = 0xf3;
			break;
		case 0x6569:			//ei
			op->buf[0] = 0xfb;
			break;
		case 0x727374:			//rst
			if (strlen (op->buf_asm) < 5)
				return op->size = 0;
			num = r_num_get (NULL, &op->buf_asm[4]);
			if ((num & 7) || ((num/8) > 7))
				return op->size = 0;
			op->buf[0] = (ut8)((num & 0xff) + 0xc7);
			break;
		case 0x70757368:		//push
			if (strlen (op->buf_asm) < 7)
				return op->size = 0;
			str_op (&op->buf_asm[5]);
			str_op (&op->buf_asm[6]);
			if (op->buf_asm[5] == 'b' && op->buf_asm[6] == 'c') {
				op->buf[0] = 0xc5;
			} else if (op->buf_asm[5] == 'd' && op->buf_asm[6] == 'e') {
				op->buf[0] = 0xd5;
			} else if (op->buf_asm[5] == 'h' && op->buf_asm[6] == 'l') {
				op->buf[0] = 0xe5;
			} else if (op->buf_asm[5] == 'a' && op->buf_asm[6] == 'f') {
				op->buf[0] = 0xf5;
			} else len = 0;
			break;
		case 0x706f70:			//pop	
			if (strlen (op->buf_asm) < 6)
				return op->size = 0;
			str_op (&op->buf_asm[4]);
			str_op (&op->buf_asm[5]);
			if (op->buf_asm[4] == 'b' && op->buf_asm[5] == 'c') {
				op->buf[0] = 0xc1;
			} else if (op->buf_asm[4] == 'd' && op->buf_asm[5] == 'e') {
				op->buf[0] = 0xd1;
			} else if (op->buf_asm[4] == 'h' && op->buf_asm[5] == 'l') {
				op->buf[0] = 0xe1;
			} else if (op->buf_asm[4] == 'a' && op->buf_asm[5] == 'f') {
				op->buf[0] = 0xf1;
			} else len = 0;
			break;
		case 0x6a70:			//jp
			if (strlen(op->buf_asm) < 4)
				return op->size = 0;
			{
				char *p = strchr (op->buf_asm, (int)',');
				if (!p) {
					str_op (&op->buf_asm[3]);
					str_op (&op->buf_asm[4]);
					if (op->buf_asm[3] == 'h' && op->buf_asm[4] == 'l')
						op->buf[0] = 0xe9;
					else {
						num = r_num_get (NULL, &op->buf_asm[3]);
						len = 3;
						op->buf[0] = 0xc3;
						op->buf[1] = (ut8)(num & 0xff);
						op->buf[2] = (ut8)((num & 0xff00) >> 8);
					}
				} else {
					str_op (p-2);
					str_op (p-1);
					if (*(p-2) == 'n') {
						if (*(p-1) == 'z')
							op->buf[0] = 0xc2;
						else if (*(p-1) == 'c')
							op->buf[0] = 0xd2;
						else	return op->size = 0;
					} else if (*(p-2) == ' ') {
						if (*(p-1) == 'z')
							op->buf[0] = 0xca;
						else if (*(p-1) == 'c')
							op->buf[0] = 0xda;
						else	return op->size = 0;
					} else	return op->size = 0;
					r_str_replace_in (p, strlen(p), ", ", ",", R_TRUE);
					if (p[1] == '\0')
						return op->size = 0;
					num = r_num_get (NULL, p + 1);
					op->buf[1] = (ut8)(num & 0xff);
					op->buf[2] = (ut8)((num & 0xff00) >> 8);
					len = 3;
				}
			}
Ejemplo n.º 2
0
/*--------------------------------------------------------------------------*/
FilterResult filter(const char *start, 
                    const char **end, 
                    SLPAttributes slp_attr, 
                    int recursion_depth)
/* Parameters:                                                              */
/* start -- (IN) The start of the string to work in.                        */
/* end -- (OUT) The end of the string processed. After successful processing*/
/*              (ie, no PARSE_ERRORs), this will be pointed at the character*/
/*              following the last char in this level of the expression.    */
/* slp_attr -- (IN) The attributes handle to compare on.                    */
/* return_value -- (OUT) The result of the search. Only valid if SLP_OK was */
/*                       returned.                                          */
/*                                                                          */
/* Returns: SLP_OK on successful search (ie, the search was do-able).       */
/*          SLP_PARSE_ERROR on search error.  The end of the expression is  */
/*          returned through end.                                           */
/*--------------------------------------------------------------------------*/
{
    char *operator; /* Pointer to the operator substring. */
    const char *cur; /* Current working character. */
    const char *last_char; /* The last character in the working string. */
    FilterResult err = FR_UNSET; /* The result of an evaluation. */

    if(recursion_depth <= 0)
    {
        return FR_PARSE_ERROR;
    }

    recursion_depth--;

    if(*start != BRACKET_OPEN)
    {
        return FR_PARSE_ERROR;
    }

    /***** Get the current expression. *****/
    last_char = *end = find_bracket_end(start);
    if(*end == 0)
    {
        return FR_PARSE_ERROR;
    }
    (*end)++; /* Move the end pointer past the closing bracket. */

    /**** 
     * Check for the three legal characters that can follow an expression,
     * if the following character isn't one of those, the following character 
     * is trash.
     ****/
    if(!(**end == BRACKET_OPEN || **end == BRACKET_CLOSE || **end == '\0'))
    {
        return FR_PARSE_ERROR;
    }

    /***** check for boolean op. *****/
    cur = start;
    cur++;

    switch(*cur)
    {
    case('&'): /***** And. *****/
    case('|'): /***** Or. *****/
        {
            FilterResult stop_condition; /* Stop when this value is received. Used for short circuiting. */

            if(*cur == '&')
            {
                stop_condition = FR_EVAL_FALSE;
            }
            else if(*cur == '|')
            {
                stop_condition = FR_EVAL_TRUE;
            }

            cur++; /* Move past operator. */

            /*** Ensure that we have at least one operator. ***/
            if(*cur != BRACKET_OPEN || cur >= last_char)
            {
                return FR_PARSE_ERROR;
            }

            /*** Evaluate each operand. ***/
            /* NOTE: Due to the condition on the above "if", we are guarenteed that the first iteration of the loop is valid. */
            do 
            {
                err = filter(cur, &cur, slp_attr, recursion_depth);
                /*** Propagate errors. ***/
                if(err != FR_EVAL_TRUE && err != FR_EVAL_FALSE)
                {
                    return err;
                }

                /*** Short circuit. ***/
                if(err == stop_condition)
                {
                    return stop_condition;
                }
            } while(*cur == BRACKET_OPEN && cur < last_char); 


            /*** If we ever get here, it means we've evaluated every operand without short circuiting -- meaning that the operation failed. ***/
            return(stop_condition == FR_EVAL_TRUE ? FR_EVAL_FALSE : FR_EVAL_TRUE);
        }


    case('!'): /***** Not. *****/
        /**** Child. ****/
        cur++;
        err = filter(cur, &cur, slp_attr, recursion_depth);
        /*** Return errors. ***/
        if(err != FR_EVAL_TRUE && err != FR_EVAL_FALSE)
        {
            return err;
        }

        /*** Perform "not". ***/
        return(err == FR_EVAL_TRUE ? FR_EVAL_FALSE : FR_EVAL_TRUE);

    default: /***** Unknown operator. *****/
        ;
        /* We don't do anything here because this will catch the first character of every leaf predicate. */
    }

    /***** Check for leaf operator. *****/
    if(IS_VALID_TAG_CHAR(*cur))
    {
        Operation op;
        char *lhs, *rhs; /* The two operands. */
        char *val_start; /* The character after the operator. ie, the start of the rhs. */
        int lhs_len, rhs_len; /* Length of the lhs/rhs. */
        SLPType type;
        SLPError slp_err;

        /**** Demux leaf op. ****/
        /* Since all search operators contain a "=", we look for the equals 
         * sign, and then poke around on either side of that for the real 
         * value. 
         */
        operator = (char *)memchr(cur, '=', last_char - cur);
        if(operator == 0)
        {
            /**** No search operator. ****/
            return FR_PARSE_ERROR;
        }

        /* The rhs always follows the operator. (This doesn't really make 
        sense for PRESENT ops, but ignore that). */
        val_start = operator + 1; 

        /* Check for APPROX, GREATER, or LESS. Note that we shuffle the 
        operator pointer back to point at the start of the op. */
        if(operator == cur)
        {/* Check that we can poke back one char. */
            return FR_PARSE_ERROR;
        }

        switch(*(operator - 1))
        {
        case('~'):
            op = EQUAL; /* See Assumptions. */
            operator--;
            break;
        case('>'):
            op = GREATER;
            operator--;
            break;
        case('<'):
            op = LESS;
            operator--;
            break;
        default: /* No prefix to the '='. */
            /**** Check for PRESENT. ****/
            if((operator == last_char - 2) && (*(operator+1) == '*'))
            {
                op = PRESENT;
            }
            /**** It's none of the above: therefore it's EQUAL. ****/
            else
            {
                op = EQUAL;
            }
        }


        /***** Get operands. *****/
        /**** Left. ****/
        lhs_len = operator - cur;
        lhs = (char *)cur;

        /**** Right ****/
        rhs_len = last_char - val_start;
        rhs = val_start;

        /***** Do leaf operation. *****/
        /**** Check that tag exists. ****/
        slp_err = SLPAttrGetType_len(slp_attr, lhs, lhs_len, &type);
        if(slp_err == SLP_TAG_ERROR)
        { /* Tag  doesn't exist. */
            return FR_EVAL_FALSE;
        }
        else if(slp_err == SLP_OK)
        { /* Tag exists. */
            /**** Do operation. *****/
            if(op == PRESENT)
            {
                /*** Since the PRESENT operation is the same for all types, 
                do that now. ***/
                return FR_EVAL_TRUE;
            }
            else
            {
                /*** A type-specific operation. ***/
                switch(type)
                {
                case(SLP_BOOLEAN):
                    err = bool_op(slp_attr, lhs, lhs_len, rhs, rhs_len, op); 
                    break;
                case(SLP_INTEGER):
                    err = int_op(slp_attr, lhs, lhs_len, rhs, op); 
                    break;
                case(SLP_KEYWORD):
                    err = keyw_op(slp_attr, lhs, rhs, op); 
                    break;
                case(SLP_STRING):
                    err = str_op(slp_attr, lhs, lhs_len, rhs, rhs_len, op); 
                    break;
                case(SLP_OPAQUE):
                    assert(0); /* Opaque is not yet supported. */
                }
            }
        }
        else
        { /* Some other tag-related error. */
            err = FR_INTERNAL_SYSTEM_ERROR;
        }

        assert(err != FR_UNSET);
        return err;
    }

    /***** No operator. *****/
    return FR_PARSE_ERROR;
}