A dynamic tracer for Linux

node.c 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include <inttypes.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include "node.h"
  7. void node_print_atom(node_t *n, FILE *fp)
  8. {
  9. switch (n->atom.atype) {
  10. case A_IDENT:
  11. fputs(n->atom.ident, fp);
  12. break;
  13. case A_NUM:
  14. fprintf(fp, "%#"PRIx64, n->atom.num);
  15. break;
  16. case A_STRING:
  17. fprintf(fp, "\"%s\"", n->atom.string);
  18. break;
  19. default:
  20. fputs("INVALID_ATOM", fp);
  21. }
  22. }
  23. void node_print_expr(node_t *n, FILE *fp)
  24. {
  25. if (!isprint(n->expr.etype)) {
  26. fputs("INVALID_EXPR", fp);
  27. return;
  28. }
  29. fputc(n->expr.etype, fp);
  30. }
  31. void node_print(node_t *n, FILE *fp)
  32. {
  33. switch (n->ntype) {
  34. case N_ATOM:
  35. node_print_atom(n, fp);
  36. break;
  37. case N_EXPR:
  38. node_print_expr(n, fp);
  39. break;
  40. default:
  41. fputs("INVALID_NODE", fp);
  42. }
  43. }
  44. int __node_dump_pre(node_t *n, void *_info)
  45. {
  46. node_dump_info_t *info = _info;
  47. fprintf(info->fp, "%*s", info->indent, "");
  48. node_print(n, info->fp);
  49. fputc('\n', info->fp);
  50. if (n->ntype == N_EXPR) {
  51. info->indent += 2;
  52. }
  53. return 0;
  54. }
  55. int __node_dump_post(node_t *n, void *_info)
  56. {
  57. node_dump_info_t *info = _info;
  58. node_t *next;
  59. if (n->ntype == N_EXPR)
  60. info->indent -= 2;
  61. if (n->up && n->up->ntype == N_EXPR && n->up->expr.arg == n) {
  62. for (next = n->next; next; next = next->next) {
  63. node_dump(next, info);
  64. }
  65. }
  66. return 0;
  67. }
  68. void node_dump(node_t *n, node_dump_info_t *info)
  69. {
  70. node_walk(n, __node_dump_pre, __node_dump_post, info);
  71. }
  72. int node_walk(node_t *n,
  73. int (*pre)(node_t *, void *),
  74. int (*post)(node_t *, void *),
  75. void *ctx)
  76. {
  77. int err = 0;
  78. if (pre && (err = pre(n, ctx)))
  79. return err;
  80. if (n->ntype == N_EXPR) {
  81. err = node_walk(n->expr.arg, pre, post, ctx);
  82. if (err)
  83. return err;
  84. }
  85. if (post && (err = post(n, ctx)))
  86. return err;
  87. return 0;
  88. }
  89. static node_t *__node(ntype_t ntype)
  90. {
  91. node_t *n = calloc(1, sizeof(*n));
  92. assert(n);
  93. n->ntype = ntype;
  94. return n;
  95. }
  96. node_t *node_ident(char *name)
  97. {
  98. node_t *n = __node(N_ATOM);
  99. n->atom.atype = A_IDENT;
  100. n->atom.ident = name;
  101. return n;
  102. }
  103. node_t *node_num(int64_t num)
  104. {
  105. node_t *n = __node(N_ATOM);
  106. n->atom.atype = A_NUM;
  107. n->atom.num = num;
  108. return n;
  109. }
  110. node_t *node_string(char *string)
  111. {
  112. node_t *n = __node(N_ATOM);
  113. n->atom.atype = A_STRING;
  114. n->atom.string = string;
  115. return n;
  116. }
  117. node_t *node_expr(etype_t etype, node_t *arg)
  118. {
  119. node_t *n = __node(N_EXPR);
  120. node_t *next;
  121. n->expr.etype = etype;
  122. n->expr.arg = arg;
  123. for (next = arg; next; next = next->next)
  124. next->up = n;
  125. return n;
  126. }
  127. node_t *node_cons(node_t *head, node_t *tail)
  128. {
  129. node_t *next;
  130. assert(!head->next);
  131. head->next = tail;
  132. for (next = tail; next; next = next->next)
  133. next->up = head->up;
  134. return head;
  135. }