A dynamic tracer for Linux

func.c 1.8KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include <errno.h>
  2. #include "func.h"
  3. #include "node.h"
  4. #include "ply.h"
  5. #include "sym.h"
  6. #include "type.h"
  7. static int func_validate_expr(const struct func *func, struct node *n, int strict)
  8. {
  9. struct tfield *f;
  10. struct node *arg;
  11. int fargs, nargs = 0;
  12. for (f = func->type->func.args, arg = n->expr.args;
  13. f && f->type && arg; f++, arg = arg->next, nargs++) {
  14. if ((!strict && (f->type->ttype == T_VOID))
  15. || (!strict && !arg->sym->type)
  16. || (!strict && (arg->sym->type->ttype == T_VOID))
  17. || type_compatible(arg->sym->type, f->type))
  18. continue;
  19. _e("%#N: %O argument is of type '%T', expected '%T'.\n",
  20. n, nargs, arg->sym->type, f->type);
  21. }
  22. if ((!f || !f->type) && !arg)
  23. return 0;
  24. nargs = node_nargs(n);
  25. fargs = type_nargs(func->type);
  26. if (f && f->type) {
  27. _e("%#N: too few arguments to %N; expected%s %d, got %d.\n",
  28. n, n, func->type->func.vargs? " at least" : "", fargs, nargs);
  29. return -EINVAL;
  30. }
  31. if (func->type->func.vargs)
  32. return 0;
  33. _e("%#N: too many arguments to %N; expected %d, got %d.\n",
  34. n, n, fargs, nargs);
  35. return -EINVAL;
  36. }
  37. int func_static_validate(const struct func *func, struct node *n)
  38. {
  39. int err = 0;
  40. if (!func->type)
  41. goto check_callback;
  42. switch (n->ntype) {
  43. case N_EXPR:
  44. if (func->type->ttype != T_FUNC) {
  45. _e("%#N: %N is not callable.\n", n, n);
  46. return -EINVAL;
  47. }
  48. err = func_validate_expr(func, n, 0);
  49. break;
  50. case N_IDENT:
  51. if (func->type->ttype == T_FUNC) {
  52. _e("%#N: %N is a function.\n", n, n);
  53. return -EINVAL;
  54. }
  55. break;
  56. default:
  57. /* num, str. nothing to validate. */
  58. break;
  59. }
  60. check_callback:
  61. if (!err && func->static_validate)
  62. err = func->static_validate(func, n);
  63. return err;
  64. }
  65. struct type *func_return_type(const struct func *func)
  66. {
  67. if (!func->type)
  68. return NULL;
  69. if (func->type->ttype == T_FUNC)
  70. return func->type->func.type;
  71. return func->type;
  72. }