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; } }
/*--------------------------------------------------------------------------*/ 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; }