ltm.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. ** $Id: ltm.c,v 1.61 2001/01/19 13:20:30 roberto Exp roberto $
  3. ** Tag methods
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "lua.h"
  9. #include "ldo.h"
  10. #include "lmem.h"
  11. #include "lobject.h"
  12. #include "lstate.h"
  13. #include "ltm.h"
  14. const char *const luaT_eventname[] = { /* ORDER TM */
  15. "gettable", "settable", "index", "getglobal", "setglobal", "add", "sub",
  16. "mul", "div", "pow", "unm", "lt", "concat", "gc", "function",
  17. "le", "gt", "ge", /* deprecated options!! */
  18. NULL
  19. };
  20. static int findevent (const char *name) {
  21. int i;
  22. for (i=0; luaT_eventname[i]; i++)
  23. if (strcmp(luaT_eventname[i], name) == 0)
  24. return i;
  25. return -1; /* name not found */
  26. }
  27. static int luaI_checkevent (lua_State *L, const char *name, int t) {
  28. int e = findevent(name);
  29. if (e >= TM_N)
  30. luaO_verror(L, "event `%.50s' is deprecated", name);
  31. if (e == TM_GC && t == LUA_TTABLE)
  32. luaO_verror(L, "event `gc' for tables is deprecated");
  33. if (e < 0)
  34. luaO_verror(L, "`%.50s' is not a valid event name", name);
  35. return e;
  36. }
  37. /* events in LUA_TNIL are all allowed, since this is used as a
  38. * 'placeholder' for "default" fallbacks
  39. */
  40. /* ORDER LUA_T, ORDER TM */
  41. static const unsigned char luaT_validevents[NUM_TAGS][TM_N] = {
  42. {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */
  43. {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */
  44. {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */
  45. {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */
  46. {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */
  47. {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* LUA_TFUNCTION */
  48. };
  49. int luaT_validevent (int t, int e) { /* ORDER LUA_T */
  50. return (t >= NUM_TAGS) ? 1 : (int)luaT_validevents[t][e];
  51. }
  52. static void init_entry (lua_State *L, int tag) {
  53. int i;
  54. for (i=0; i<TM_N; i++)
  55. luaT_gettm(G(L), tag, i) = NULL;
  56. G(L)->TMtable[tag].collected = NULL;
  57. }
  58. void luaT_init (lua_State *L) {
  59. int t;
  60. G(L)->TMtable = luaM_newvector(L, NUM_TAGS+2, struct TM);
  61. G(L)->sizeTM = NUM_TAGS+2;
  62. G(L)->ntag = NUM_TAGS;
  63. for (t=0; t<G(L)->ntag; t++)
  64. init_entry(L, t);
  65. }
  66. LUA_API int lua_newtag (lua_State *L) {
  67. int tag;
  68. LUA_ENTRY;
  69. luaM_growvector(L, G(L)->TMtable, G(L)->ntag, G(L)->sizeTM, struct TM,
  70. MAX_INT, "tag table overflow");
  71. init_entry(L, G(L)->ntag);
  72. tag = G(L)->ntag++;
  73. LUA_EXIT;
  74. return tag;
  75. }
  76. static void checktag (lua_State *L, int tag) {
  77. if (!(0 <= tag && tag < G(L)->ntag))
  78. luaO_verror(L, "%d is not a valid tag", tag);
  79. }
  80. void luaT_realtag (lua_State *L, int tag) {
  81. if (!validtag(G(L), tag))
  82. luaO_verror(L, "tag %d was not created by `newtag'", tag);
  83. }
  84. LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) {
  85. int e;
  86. LUA_ENTRY;
  87. checktag(L, tagto);
  88. checktag(L, tagfrom);
  89. for (e=0; e<TM_N; e++) {
  90. if (luaT_validevent(tagto, e))
  91. luaT_gettm(G(L), tagto, e) = luaT_gettm(G(L), tagfrom, e);
  92. }
  93. LUA_EXIT;
  94. return tagto;
  95. }
  96. int luaT_tag (const TObject *o) {
  97. int t = ttype(o);
  98. switch (t) {
  99. case LUA_TUSERDATA: return tsvalue(o)->u.d.tag;
  100. case LUA_TTABLE: return hvalue(o)->htag;
  101. default: return t;
  102. }
  103. }
  104. LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) {
  105. int e;
  106. LUA_ENTRY;
  107. e = luaI_checkevent(L, event, t);
  108. checktag(L, t);
  109. if (luaT_validevent(t, e) && luaT_gettm(G(L), t, e)) {
  110. setclvalue(L->top, luaT_gettm(G(L), t, e));
  111. }
  112. else
  113. setnilvalue(L->top);
  114. incr_top;
  115. LUA_EXIT;
  116. }
  117. LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) {
  118. int e;
  119. LUA_ENTRY;
  120. e = luaI_checkevent(L, event, t);
  121. checktag(L, t);
  122. if (!luaT_validevent(t, e))
  123. luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s",
  124. luaT_eventname[e], luaO_typenames[t],
  125. (t == LUA_TTABLE || t == LUA_TUSERDATA) ?
  126. " with default tag" : "");
  127. switch (ttype(L->top - 1)) {
  128. case LUA_TNIL:
  129. luaT_gettm(G(L), t, e) = NULL;
  130. break;
  131. case LUA_TFUNCTION:
  132. luaT_gettm(G(L), t, e) = clvalue(L->top - 1);
  133. break;
  134. default:
  135. luaD_error(L, "tag method must be a function (or nil)");
  136. }
  137. L->top--;
  138. LUA_EXIT;
  139. }