static void match_loop(struct statement *stmt) { struct expression *iterator; char *iter_set; char *iter_tested; if (get_macro_name(stmt->pos)) return; iterator = get_iterator_set(stmt->iterator_pre_statement); iter_set = expr_to_var(iterator); iterator = get_iterator_tested(stmt->iterator_pre_condition); iter_tested = expr_to_var(iterator); if (!iter_set || !iter_tested) goto free; if (strcmp(iter_set, iter_tested)) goto free; /* smatch doesn't handle loops correctly so this silences some * false positives. */ if (right_side_changes(stmt->iterator_pre_condition)) goto free; if (implied_condition_false(stmt->iterator_pre_condition)) sm_msg("warn: we never enter this loop"); free: free_string(iter_set); free_string(iter_tested); }
static void match_return(struct expression *ret_value) { struct expression *expr; char *macro; if (!ret_value) return; expr = ret_value; if (ret_value->type != EXPR_PREOP || ret_value->op != '-') return; macro = get_macro_name(expr->unop->pos); if (macro && !strcmp(macro, "PTR_ERR")) { sm_msg("warn: returning -%s()", macro); return; } if (!option_spammy) return; expr = get_assigned_expr(ret_value->unop); if (!expr) return; if (expr->type != EXPR_CALL) return; sm_msg("warn: should this return really be negated?"); }
static void match_call_assignment(struct expression *expr) { if (get_macro_name(expr->left->pos)) return; last_return = expr->left; last_func = expr->right; }
static int is_unconstant_macro(struct expression *expr) { char *macro; macro = get_macro_name(expr->pos); if (!macro) return 0; if (search_unconstant_macros(unconstant_macros, macro)) return 1; return 0; }
static void match_binop(struct expression *expr) { sval_t left, right, sval; if (expr->op != '&') return; if (!get_value(expr, &sval) || sval.value != 0) return; if (get_macro_name(expr->pos)) return; if (!get_value(expr->left, &left) || !get_value(expr->right, &right)) return; sm_msg("warn: odd binop '0x%llx & 0x%llx'", left.uvalue, right.uvalue); }
static void match_inside(struct expression *expr, struct position pos) { char *name; int matched = 0; if (positions_eq(expr->pos, pos)) matched++; if (positions_eq(expr->unop->pos, pos)) matched++; if (matched != 1) return; name = get_macro_name(pos); if (!name) return; sm_msg("warn: the '%s' macro might need parens", name); }
static void match_assign(struct expression *expr) { char *name; name = get_macro_name(expr->pos); if (!name || strcmp(name, "get_user") != 0) { match_normal_assign(expr); return; } name = expr_to_var(expr->right); if (!name || strcmp(name, "__val_gu") != 0) goto free; set_state_expr(my_max_id, expr->left, &user_data); set_state_expr(my_min_id, expr->left, &user_data); free: free_string(name); }
static void match_condition(struct expression *expr) { struct symbol *type; char *str; if (expr->type != EXPR_DEREF) return; type = get_type(expr); if (!type || type->type != SYM_ARRAY) return; if (get_macro_name(expr->pos)) return; str = expr_to_str(expr); sm_msg("warn: this array is probably non-NULL. '%s'", str); free_string(str); }
static void match_one_side(struct expression *expr, struct position pos, int op) { char *name; int matched = 0; if ((op == '+' || op == '*' || op == '|' || op == '&') && expr->op == op) return; if (positions_eq(expr->right->pos, pos)) matched++; if (positions_eq(expr->left->pos, pos)) matched++; if (matched != 1) return; name = get_macro_name(pos); if (!name) return; if (option_project == PROJ_WINE && !strcmp("BEGIN", name)) return; sm_msg("warn: the '%s' macro might need parens", name); }
static void match_condition(struct expression *expr) { sval_t sval; if (expr->type != EXPR_BINOP) return; if (expr->op == '|') { if (get_value(expr->left, &sval) || get_value(expr->right, &sval)) sm_msg("warn: suspicious bitop condition"); return; } if (expr->op != '&') return; if (get_macro_name(expr->pos)) return; if (is_unconstant_macro(expr->left) || is_unconstant_macro(expr->right)) return; if ((get_value(expr->left, &sval) && sval.value == 0) || (get_value(expr->right, &sval) && sval.value == 0)) sm_msg("warn: bitwise AND condition is false here"); }
char *part_property_expand_macros (Part *part, char *string) { static char mcode[] = {"@?~#&"}; char *value; char *tmp0, *temp, *qn, *q0, *t0; char *cls1, *cls2; GString *out; size_t sln; char *ret; g_return_val_if_fail (part != NULL, NULL); g_return_val_if_fail (IS_PART (part), NULL); g_return_val_if_fail (string != NULL, NULL); cls1 = cls2 = q0 = NULL; // Rules: // @<id> value of <id>. If no value, error // &<id> value of <id> if <id> is defined // ?<id>s...s text between s...s separators if <id> defined // ?<id>s...ss...s text between 1st s...s separators if <id> defined // else 2nd s...s clause // ~<id>s...s text between s...s separators if <id> undefined // ~<id>s...ss...s text between 1st s...s separators if <id> undefined // else 2nd s...s clause // #<id>s...s text between s...s separators if <id> defined, but // delete rest of tempalte if <id> undefined // Separators can be any of (, . ; / |) For an opening-closing pair of // separators the same character ahs to be used. // Examples: R^@refdes %1 %2 @value // V^@refdes %+ %- SIN(@offset @ampl @freq 0 0) // ?DC|DC @DC| tmp0 = temp = g_strdup (string); out = g_string_new (""); for (temp = string; *temp;) { // Look for any of the macro char codes. if (strchr (mcode, *temp)) { qn = get_macro_name (temp + 1, &cls1, &cls2, &sln); if (qn == NULL) return NULL; value = part_get_property (part, qn); if ((*temp == '@' || *temp == '&') && value) { out = g_string_append (out, value); } else if (*temp == '&' && !value) { g_warning ("expand macro error: macro %s undefined", qn); g_free (qn); return NULL; } else if (*temp == '?' || *temp == '~') { if (cls1 == NULL) { g_warning ("error in template: %s", temp); g_free (qn); return NULL; } q0 = (value ? (*temp == '?' ? cls1 : cls2) : (*temp == '?' ? cls2 : cls1)); if (q0) { t0 = part_property_expand_macros (part, q0); if (!t0) { g_warning ("error in template: %s", temp); g_free (qn); } else { out = g_string_append (out, t0); g_free (t0); } } } else if (*temp == '#') { if (value) { t0 = part_property_expand_macros (part, value); if (!t0) { g_warning ("error in template: %s", temp); g_free (qn); } else { out = g_string_append (out, t0); g_free (t0); } } else *(temp + sln) = 0; } temp += 1; temp += sln; if (qn) g_free (qn); if (cls1) g_free (cls1); if (cls2) g_free (cls2); } else { if (*temp == '\\') { temp++; switch (*temp) { case 'n': out = g_string_append_c (out, '\n'); break; case 't': out = g_string_append_c (out, '\t'); break; case 'r': out = g_string_append_c (out, '\r'); break; case 'f': out = g_string_append_c (out, '\f'); } temp++; } else { out = g_string_append_c (out, *temp); temp++; } } } if (tmp0) g_free (tmp0); out = g_string_append_c (out, '\0'); ret = g_strdup (out->str); g_string_free (out, TRUE); return ret; }