A dynamic tracer for Linux

node.c 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 nprint(node_t *n, FILE *fp)
  8. {
  9. switch (n->ntype) {
  10. case N_CONS:
  11. fputs("<CONS>", fp);
  12. break;
  13. case N_OP:
  14. fputc(n->op, fp);
  15. break;
  16. case N_IDENT:
  17. fputs(n->ident, fp);
  18. break;
  19. case N_NUM:
  20. fprintf(fp, "%#"PRIx64, n->num);
  21. break;
  22. case N_STRING:
  23. fprintf(fp, "\"%s\"", n->string);
  24. break;
  25. default:
  26. fputs("<INVALID>", fp);
  27. }
  28. }
  29. int __node_dump_pre(node_t *n, void *_info)
  30. {
  31. ndump_info_t *info = _info;
  32. switch (n->ntype) {
  33. case N_CONS:
  34. info->indent += 2;
  35. break;
  36. default:
  37. fprintf(info->fp, "%*s", info->indent, "");
  38. nprint(n, info->fp);
  39. fputc('\n', info->fp);
  40. }
  41. return 0;
  42. }
  43. int __node_dump_post(node_t *n, void *_info)
  44. {
  45. ndump_info_t *info = _info;
  46. node_t *next;
  47. if (n->ntype == N_CONS)
  48. info->indent -= 2;
  49. return 0;
  50. }
  51. void ndump(node_t *n, ndump_info_t *info)
  52. {
  53. nwalk(n, __node_dump_pre, __node_dump_post, info);
  54. }
  55. int nwalk(node_t *n,
  56. int (*pre)(node_t *, void *),
  57. int (*post)(node_t *, void *),
  58. void *ctx)
  59. {
  60. int err = 0;
  61. if (pre && (err = pre(n, ctx)))
  62. return err;
  63. if (n->ntype == N_CONS) {
  64. err = ncar(n) ? nwalk(ncar(n), pre, post, ctx) : 0;
  65. if (err)
  66. return err;
  67. err = ncdr(n) ? nwalk(ncdr(n), pre, post, ctx) : 0;
  68. if (err)
  69. return err;
  70. }
  71. if (post && (err = post(n, ctx)))
  72. return err;
  73. return 0;
  74. }
  75. /* high-level constructors */
  76. node_t *ncall(char *name, node_t *args)
  77. {
  78. return ncons(nop('('), ncons(nident(name), args));
  79. }
  80. node_t *nmap(char *name, node_t *key)
  81. {
  82. return ncons(nop('{'), ncons(nident(name), key));
  83. }
  84. /* basic constructors */
  85. static node_t *__node(ntype_t ntype)
  86. {
  87. node_t *n = calloc(1, sizeof(*n));
  88. assert(n);
  89. n->ntype = ntype;
  90. return n;
  91. }
  92. node_t *ncons(node_t *car, node_t *cdr)
  93. {
  94. node_t *n = __node(N_CONS);
  95. assert(car);
  96. car->up = n;
  97. if (cdr)
  98. cdr->up = n;
  99. n->cons.car = car;
  100. n->cons.cdr = cdr;
  101. return n;
  102. }
  103. node_t *nop(op_t op)
  104. {
  105. node_t *n = __node(N_OP);
  106. n->op = op;
  107. return n;
  108. }
  109. node_t *nident(char *name)
  110. {
  111. node_t *n = __node(N_IDENT);
  112. n->ident = name;
  113. return n;
  114. }
  115. node_t *nnum(int64_t num)
  116. {
  117. node_t *n = __node(N_NUM);
  118. n->num = num;
  119. return n;
  120. }
  121. node_t *nstring(char *string)
  122. {
  123. node_t *n = __node(N_STRING);
  124. n->string = string;
  125. return n;
  126. }