lfunc.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. ** $Id: lfunc.c,v 1.47 2001/09/07 17:39:10 roberto Exp $
  3. ** Auxiliary functions to manipulate prototypes and closures
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdlib.h>
  7. #define LUA_PRIVATE
  8. #include "lua.h"
  9. #include "lfunc.h"
  10. #include "lmem.h"
  11. #include "lobject.h"
  12. #include "lstate.h"
  13. #define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
  14. cast(int, sizeof(TObject)*((n)-1)))
  15. #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
  16. cast(int, sizeof(LClosureEntry)*((n)-1)))
  17. Closure *luaF_newCclosure (lua_State *L, int nelems) {
  18. Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
  19. c->c.isC = 1;
  20. c->c.next = G(L)->rootcl;
  21. G(L)->rootcl = c;
  22. c->c.marked = 0;
  23. c->c.nupvalues = nelems;
  24. return c;
  25. }
  26. Closure *luaF_newLclosure (lua_State *L, int nelems) {
  27. Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
  28. c->l.isC = 0;
  29. c->l.marked = 0;
  30. c->l.nupvalues = nelems;
  31. return c;
  32. }
  33. /*
  34. ** returns the open pointer in a closure that points higher into the stack
  35. */
  36. static StkId uppoint (LClosure *cl) {
  37. StkId lp = NULL;
  38. int i;
  39. for (i=0; i<cl->nupvalues; i++) {
  40. if (cl->upvals[i].heap == NULL && (lp == NULL || cl->upvals[i].val > lp))
  41. lp = cl->upvals[i].val;
  42. }
  43. return lp;
  44. }
  45. void luaF_LConlist (lua_State *L, Closure *cl) {
  46. StkId cli = uppoint(&cl->l);
  47. if (cli == NULL) { /* no more open entries? */
  48. cl->l.next = G(L)->rootcl; /* insert in final list */
  49. G(L)->rootcl = cl;
  50. }
  51. else { /* insert in list of open closures, ordered by decreasing uppoints */
  52. Closure **p = &L->opencl;
  53. while (*p != NULL && uppoint(&(*p)->l) > cli) p = &(*p)->l.next;
  54. cl->l.next = *p;
  55. *p = cl;
  56. }
  57. }
  58. static int closeCl (lua_State *L, LClosure *cl, StkId level) {
  59. int got = 0; /* flag: 1 if some pointer in the closure was corrected */
  60. int i;
  61. for (i=0; i<cl->nupvalues; i++) {
  62. StkId var;
  63. if (cl->upvals[i].heap == NULL && (var=cl->upvals[i].val) >= level) {
  64. if (ttype(var) != LUA_TUPVAL) {
  65. UpVal *v = luaM_new(L, UpVal);
  66. v->val = *var;
  67. v->marked = 0;
  68. v->next = G(L)->rootupval;
  69. G(L)->rootupval = v;
  70. setupvalue(var, v);
  71. }
  72. cl->upvals[i].heap = vvalue(var);
  73. cl->upvals[i].val = &vvalue(var)->val;
  74. got = 1;
  75. }
  76. }
  77. return got;
  78. }
  79. void luaF_close (lua_State *L, StkId level) {
  80. Closure *affected = NULL; /* closures with open pointers >= level */
  81. Closure *cl;
  82. while ((cl=L->opencl) != NULL) {
  83. if (!closeCl(L, cast(LClosure *, cl), level)) break;
  84. /* some pointer in `cl' changed; will re-insert it in original list */
  85. L->opencl = cl->l.next; /* remove from original list */
  86. cl->l.next = affected;
  87. affected = cl; /* insert in affected list */
  88. }
  89. /* re-insert all affected closures in original list */
  90. while ((cl=affected) != NULL) {
  91. affected = cl->l.next;
  92. luaF_LConlist(L, cl);
  93. }
  94. }
  95. Proto *luaF_newproto (lua_State *L) {
  96. Proto *f = luaM_new(L, Proto);
  97. f->k = NULL;
  98. f->sizek = 0;
  99. f->p = NULL;
  100. f->sizep = 0;
  101. f->code = NULL;
  102. f->sizecode = 0;
  103. f->nupvalues = 0;
  104. f->numparams = 0;
  105. f->is_vararg = 0;
  106. f->maxstacksize = 0;
  107. f->marked = 0;
  108. f->lineinfo = NULL;
  109. f->sizelocvars = 0;
  110. f->sizelineinfo = 0;
  111. f->locvars = NULL;
  112. f->lineDefined = 0;
  113. f->source = NULL;
  114. f->next = G(L)->rootproto; /* chain in list of protos */
  115. G(L)->rootproto = f;
  116. return f;
  117. }
  118. void luaF_freeproto (lua_State *L, Proto *f) {
  119. luaM_freearray(L, f->code, f->sizecode, Instruction);
  120. luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
  121. luaM_freearray(L, f->k, f->sizek, TObject);
  122. luaM_freearray(L, f->p, f->sizep, Proto *);
  123. luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
  124. luaM_freelem(L, f);
  125. }
  126. void luaF_freeclosure (lua_State *L, Closure *c) {
  127. int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
  128. sizeLclosure(c->l.nupvalues);
  129. luaM_free(L, c, size);
  130. }
  131. /*
  132. ** Look for n-th local variable at line `line' in function `func'.
  133. ** Returns NULL if not found.
  134. */
  135. const l_char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
  136. int i;
  137. for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
  138. if (pc < f->locvars[i].endpc) { /* is variable active? */
  139. local_number--;
  140. if (local_number == 0)
  141. return getstr(f->locvars[i].varname);
  142. }
  143. }
  144. return NULL; /* not found */
  145. }