A dynamic tracer for Linux

node.c 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. return 0;
  62. }
  63. void node_dump(node_t *n, node_dump_info_t *info)
  64. {
  65. node_walk(n, __node_dump_pre, __node_dump_post, info);
  66. }
  67. int node_walk(node_t *n,
  68. int (*pre)(node_t *, void *),
  69. int (*post)(node_t *, void *),
  70. void *ctx)
  71. {
  72. int err = 0;
  73. if (pre && (err = pre(n, ctx)))
  74. return err;
  75. if (n->ntype == N_EXPR) {
  76. node_t *a = n->expr.arg;
  77. for (a = n->expr.arg; a; a = a->next) {
  78. err = node_walk(a, pre, post, ctx);
  79. if (err)
  80. return err;
  81. }
  82. }
  83. if (post && (err = post(n, ctx)))
  84. return err;
  85. return 0;
  86. }
  87. static node_t *__node(ntype_t ntype)
  88. {
  89. node_t *n = calloc(1, sizeof(*n));
  90. assert(n);
  91. n->ntype = ntype;
  92. return n;
  93. }
  94. node_t *node_ident(char *name)
  95. {
  96. node_t *n = __node(N_ATOM);
  97. n->atom.atype = A_IDENT;
  98. n->atom.ident = name;
  99. return n;
  100. }
  101. node_t *node_num(int64_t num)
  102. {
  103. node_t *n = __node(N_ATOM);
  104. n->atom.atype = A_NUM;
  105. n->atom.num = num;
  106. return n;
  107. }
  108. node_t *node_string(char *string)
  109. {
  110. node_t *n = __node(N_ATOM);
  111. n->atom.atype = A_STRING;
  112. n->atom.string = string;
  113. return n;
  114. }
  115. node_t *node_expr(etype_t etype, node_t *arg)
  116. {
  117. node_t *n = __node(N_EXPR);
  118. node_t *next;
  119. n->expr.etype = etype;
  120. n->expr.arg = arg;
  121. for (next = arg; next; next = next->next)
  122. next->up = n;
  123. return n;
  124. }
  125. node_t *node_cons(node_t *head, node_t *tail)
  126. {
  127. node_t *next;
  128. assert(!head->next);
  129. head->next = tail;
  130. for (next = tail; next; next = next->next)
  131. next->up = head->up;
  132. return head;
  133. }