2 * smatch/smatch_parse_call_math.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
11 #include "smatch_slist.h"
12 #include "smatch_extra.h"
19 } alloc_functions
[] = {
24 {"__vmalloc_node", 0},
27 DECLARE_PTR_LIST(llong_list
, long long);
29 static struct llong_list
*num_list
;
30 static struct string_list
*op_list
;
32 static void push_val(long long val
)
36 p
= malloc(sizeof(*p
));
38 add_ptr_list(&num_list
, p
);
41 static long long pop_val()
48 p
= last_ptr_list((struct ptr_list
*)num_list
);
49 delete_ptr_list_last((struct ptr_list
**)&num_list
);
56 static void push_op(char c
)
62 add_ptr_list(&op_list
, p
);
71 sm_msg("internal smatch error %s", __func__
);
75 p
= last_ptr_list((struct ptr_list
*)op_list
);
77 delete_ptr_list_last((struct ptr_list
**)&op_list
);
84 static int op_precedence(char c
)
98 static int top_op_precedence()
105 p
= last_ptr_list((struct ptr_list
*)op_list
);
106 return op_precedence(p
[0]);
109 static long long do_op(long long left
, char op
, long long right
)
126 static void pop_until(char c
)
129 long long left
, right
, res
;
131 while (top_op_precedence() && op_precedence(c
) <= top_op_precedence()) {
135 res
= do_op(left
, op
, right
);
140 static int get_implied_param(struct expression
*call
, int param
, long long *val
)
142 struct expression
*arg
;
144 arg
= get_argument_from_call_expr(call
->args
, param
);
145 return get_implied_value(arg
, val
);
148 static int read_number(struct expression
*call
, char *p
, char **end
, long long *val
)
157 param
= strtol(p
, &p
, 10);
158 if (!get_implied_param(call
, param
, val
))
162 *val
= strtoll(p
, end
, 10);
169 static char *read_op(char *p
)
185 int parse_call_math(struct expression
*call
, char *math
, long long *val
)
190 /* try to implement shunting yard algorithm. */
195 sm_msg("parsing %s", c
);
197 /* read a number and push it onto the number stack */
198 if (!read_number(call
, c
, &c
, &tmp
))
203 sm_msg("val = %lld remaining = %s", tmp
, c
);
213 sm_msg("op = %c remaining = %s", *c
, c
);
224 pop_until(0); /* discard stack */
228 int parse_call_math_sval(struct expression
*call
, char *math
, sval_t
*val
)
230 val
->type
= &llong_ctype
; /* this should be large enough to hold the size values */
231 return parse_call_math(call
, math
, &val
->value
);
234 static struct smatch_state
*alloc_state_sname(char *sname
)
236 struct smatch_state
*state
;
238 state
= __alloc_smatch_state(0);
240 state
->data
= INT_PTR(1);
244 static int get_arg_number(struct expression
*expr
)
250 expr
= strip_expr(expr
);
251 if (expr
->type
!= EXPR_SYMBOL
)
256 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, arg
) {
260 } END_FOR_EACH_PTR(arg
);
265 static int format_expr_helper(char *buf
, int remaining
, struct expression
*expr
)
273 if (expr
->type
== EXPR_BINOP
) {
274 ret
= format_expr_helper(cur
, remaining
, expr
->left
);
282 ret
= snprintf(cur
, remaining
, " %s ", show_special(expr
->op
));
288 ret
= format_expr_helper(cur
, remaining
, expr
->right
);
298 val
= get_arg_number(expr
);
300 ret
= snprintf(cur
, remaining
, "<%lld>", val
);
307 if (get_implied_value(expr
, &val
)) {
308 ret
= snprintf(cur
, remaining
, "%lld", val
);
318 static char *format_expr(struct expression
*expr
)
323 ret
= format_expr_helper(buf
, sizeof(buf
), expr
);
327 return alloc_sname(buf
);
330 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
332 int size_arg
= PTR_INT(_size_arg
);
333 struct expression
*right
;
334 struct expression
*size_expr
;
337 right
= strip_expr(expr
->right
);
338 size_expr
= get_argument_from_call_expr(right
->args
, size_arg
);
340 sname
= format_expr(size_expr
);
343 set_state_expr(my_id
, expr
->left
, alloc_state_sname(sname
));
346 static char *swap_format(struct expression
*call
, char *format
)
348 static char buf
[256];
351 struct expression
*arg
;
356 if (format
[0] == '<' && format
[2] == '>' && format
[3] == '\0') {
357 param
= strtol(format
+ 1, NULL
, 10);
358 arg
= get_argument_from_call_expr(call
->args
, param
);
361 return format_expr(arg
);
370 param
= strtol(p
, &p
, 10);
374 arg
= get_argument_from_call_expr(call
->args
, param
);
377 param
= get_arg_number(arg
);
379 ret
= snprintf(out
, buf
+ sizeof(buf
) - out
, "<%ld>", param
);
381 if (out
>= buf
+ sizeof(buf
))
383 } else if (get_implied_value(arg
, &val
)) {
384 ret
= snprintf(out
, buf
+ sizeof(buf
) - out
, "%lld", val
);
386 if (out
>= buf
+ sizeof(buf
))
398 return alloc_sname(buf
);
401 static char *buf_size_recipe
;
402 static int db_buf_size_callback(void *unused
, int argc
, char **argv
, char **azColName
)
407 if (!buf_size_recipe
)
408 buf_size_recipe
= alloc_sname(argv
[0]);
409 else if (strcmp(buf_size_recipe
, argv
[0]) != 0)
410 buf_size_recipe
= alloc_sname("invalid");
414 static char *get_allocation_recipe_from_call(struct expression
*expr
)
417 static char sql_filter
[1024];
420 expr
= strip_expr(expr
);
421 if (expr
->fn
->type
!= EXPR_SYMBOL
)
423 sym
= expr
->fn
->symbol
;
427 for (i
= 0; i
< ARRAY_SIZE(alloc_functions
); i
++) {
428 if (strcmp(sym
->ident
->name
, alloc_functions
[i
].func
) == 0) {
431 snprintf(buf
, sizeof(buf
), "<%d>", alloc_functions
[i
].param
);
432 buf_size_recipe
= alloc_sname(buf
);
433 return swap_format(expr
, buf_size_recipe
);
437 if (sym
->ctype
.modifiers
& MOD_STATIC
) {
438 snprintf(sql_filter
, 1024, "file = '%s' and function = '%s';",
439 get_filename(), sym
->ident
->name
);
441 snprintf(sql_filter
, 1024, "function = '%s' and static = 0;",
445 buf_size_recipe
= NULL
;
446 run_sql(db_buf_size_callback
, "select value from return_states where type=%d and %s",
447 BUF_SIZE
, sql_filter
);
448 if (!buf_size_recipe
|| strcmp(buf_size_recipe
, "invalid") == 0)
450 return swap_format(expr
, buf_size_recipe
);
453 static void match_call_assignment(struct expression
*expr
)
457 sname
= get_allocation_recipe_from_call(expr
->right
);
460 set_state_expr(my_id
, expr
->left
, alloc_state_sname(sname
));
463 static void match_returns_call(struct expression
*call
)
466 struct range_list
*rl
;
468 sname
= get_allocation_recipe_from_call(call
);
470 sm_msg("sname = %s", sname
);
473 get_implied_range_list(call
, &rl
);
474 sm_msg("info: return_allocation %d '%s' '%s' %s",
475 get_return_id(), show_ranges(rl
), sname
, global_static());
478 static void match_return(struct expression
*expr
)
480 struct smatch_state
*state
;
481 struct range_list
*rl
;
483 expr
= strip_expr(expr
);
487 if (expr
->type
== EXPR_CALL
) {
488 match_returns_call(expr
);
492 state
= get_state_expr(my_id
, expr
);
493 if (!state
|| !state
->data
)
495 get_implied_range_list(expr
, &rl
);
496 sm_msg("info: return_allocation %d '%s' '%s' %s",
497 get_return_id(), show_ranges(rl
), state
->name
, global_static());
500 void register_parse_call_math(int id
)
507 for (i
= 0; i
< ARRAY_SIZE(alloc_functions
); i
++)
508 add_function_assign_hook(alloc_functions
[i
].func
, &match_alloc
,
509 INT_PTR(alloc_functions
[i
].param
));
510 add_hook(&match_call_assignment
, CALL_ASSIGNMENT_HOOK
);
511 add_hook(&match_return
, RETURN_HOOK
);