A dynamic tracer for Linux

node.c 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include <inttypes.h>
  4. #include <search.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include "node.h"
  9. void node_print(node_t *n, FILE *fp)
  10. {
  11. switch (n->ntype) {
  12. case N_LIST:
  13. fputs("()", fp);
  14. break;
  15. case N_IDENT:
  16. fputs(n->ident, fp);
  17. break;
  18. case N_NUM:
  19. fprintf(fp, "%#"PRIx64, n->num);
  20. break;
  21. case N_STRING:
  22. fprintf(fp, "\"%s\"", n->string);
  23. break;
  24. default:
  25. fputs("<INVALID>", fp);
  26. }
  27. /* if (n->type) { */
  28. /* fputc(' ', fp); */
  29. /* type_dump(n->type, fp); */
  30. /* } */
  31. }
  32. struct node_dump_info {
  33. FILE *fp;
  34. int indent;
  35. };
  36. int __node_dump_pre(node_t *n, void *_info)
  37. {
  38. struct node_dump_info *info = _info;
  39. switch (n->ntype) {
  40. case N_LIST:
  41. fprintf(info->fp, "%s%*s(",
  42. info->indent? "\n" : "",
  43. info->indent, "");
  44. info->indent += 2;
  45. break;
  46. default:
  47. if (n->prev) {
  48. node_t *c;
  49. for (c = n->next; c; c = c->next) {
  50. if (c->ntype == N_LIST) {
  51. fprintf(info->fp, "\n%*s",
  52. info->indent, "");
  53. break;
  54. }
  55. }
  56. if (!c)
  57. fputc(' ', info->fp);
  58. }
  59. node_print(n, info->fp);
  60. }
  61. return 0;
  62. }
  63. int __node_dump_post(node_t *n, void *_info)
  64. {
  65. struct node_dump_info *info = _info;
  66. node_t *c;
  67. if (n->ntype != N_LIST)
  68. return 0;
  69. info->indent -= 2;
  70. for (c = n->list; c; c = c->next) {
  71. if (c->ntype == N_LIST) {
  72. fprintf(info->fp, "\n%*s)", info->indent, "");
  73. return 0;
  74. }
  75. }
  76. fputc(')', info->fp);
  77. return 0;
  78. }
  79. void node_dump(node_t *n, FILE *fp)
  80. {
  81. struct node_dump_info info = {
  82. .fp = fp,
  83. };
  84. node_walk(n, __node_dump_pre, __node_dump_post, &info);
  85. }
  86. int node_walk(node_t *n,
  87. int (*pre)(node_t *, void *),
  88. int (*post)(node_t *, void *),
  89. void *ctx)
  90. {
  91. int err = 0;
  92. if (pre && (err = pre(n, ctx)))
  93. return err;
  94. if (n->ntype == N_LIST) {
  95. node_t *c;
  96. for (c = n->list; c; c = c->next) {
  97. err = node_walk(c, pre, post, ctx);
  98. if (err)
  99. return err;
  100. }
  101. }
  102. if (post && (err = post(n, ctx)))
  103. return err;
  104. return 0;
  105. }
  106. /* constructors */
  107. static node_t *__node(ntype_t ntype)
  108. {
  109. node_t *n = calloc(1, sizeof(*n));
  110. assert(n);
  111. n->ntype = ntype;
  112. return n;
  113. }
  114. node_t *node_list(node_t *head)
  115. {
  116. node_t *n = __node(N_LIST);
  117. n->list = head;
  118. return n;
  119. }
  120. node_t *node_vlist(node_t *head, ...)
  121. {
  122. va_list ap;
  123. node_t *n, *next;
  124. n = node_list(head);
  125. va_start(ap, head);
  126. while ((next = va_arg(ap, node_t *))) {
  127. insque(next, head);
  128. head = next;
  129. }
  130. va_end(ap);
  131. return n;
  132. }
  133. node_t *node_ident(char *name)
  134. {
  135. node_t *n = __node(N_IDENT);
  136. n->ident = name;
  137. return n;
  138. }
  139. node_t *node_num(int64_t num)
  140. {
  141. node_t *n = __node(N_NUM);
  142. n->num = num;
  143. return n;
  144. }
  145. node_t *node_string(char *string)
  146. {
  147. node_t *n = __node(N_STRING);
  148. n->string = string;
  149. return n;
  150. }