ltm.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. ** $Id: ltm.c,v 1.64 2001/01/26 11:45:51 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 "lstring.h"
  14. #include "ltable.h"
  15. #include "ltm.h"
  16. const char *const luaT_eventname[] = { /* ORDER TM */
  17. "gettable", "settable", "index", "getglobal", "setglobal", "add", "sub",
  18. "mul", "div", "pow", "unm", "lt", "concat", "gc", "function",
  19. "le", "gt", "ge", /* deprecated options!! */
  20. NULL
  21. };
  22. static int findevent (const char *name) {
  23. int i;
  24. for (i=0; luaT_eventname[i]; i++)
  25. if (strcmp(luaT_eventname[i], name) == 0)
  26. return i;
  27. return -1; /* name not found */
  28. }
  29. static int luaI_checkevent (lua_State *L, const char *name, int t) {
  30. int e = findevent(name);
  31. if (e >= TM_N)
  32. luaO_verror(L, "event `%.50s' is deprecated", name);
  33. if (e == TM_GC && t == LUA_TTABLE)
  34. luaO_verror(L, "event `gc' for tables is deprecated");
  35. if (e < 0)
  36. luaO_verror(L, "`%.50s' is not a valid event name", name);
  37. return e;
  38. }
  39. /* events in LUA_TNIL are all allowed, since this is used as a
  40. * 'placeholder' for "default" fallbacks
  41. */
  42. /* ORDER LUA_T, ORDER TM */
  43. static const unsigned char luaT_validevents[NUM_TAGS][TM_N] = {
  44. {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */
  45. {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */
  46. {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */
  47. {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */
  48. {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */
  49. {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* LUA_TFUNCTION */
  50. };
  51. int luaT_validevent (int t, int e) { /* ORDER LUA_T */
  52. return (t >= NUM_TAGS) ? 1 : (int)luaT_validevents[t][e];
  53. }
  54. void luaT_init (lua_State *L) {
  55. static const char *const typenames[NUM_TAGS] = {
  56. "userdata", "nil", "number", "string", "table", "function"
  57. };
  58. int i;
  59. for (i=0; i<NUM_TAGS; i++)
  60. luaT_newtag(L, typenames[i], i);
  61. }
  62. int luaT_newtag (lua_State *L, const char *name, int basictype) {
  63. int tag;
  64. int i;
  65. TString *ts;
  66. luaM_growvector(L, G(L)->TMtable, G(L)->ntag, G(L)->sizeTM, struct TM,
  67. MAX_INT, "tag table overflow");
  68. tag = G(L)->ntag;
  69. if (name == NULL)
  70. ts = NULL;
  71. else {
  72. TObject *v;
  73. ts = luaS_new(L, name);
  74. v = luaH_setstr(L, G(L)->type2tag, ts);
  75. if (ttype(v) != LUA_TNIL) return LUA_TNONE; /* invalid name */
  76. setnvalue(v, tag);
  77. }
  78. for (i=0; i<TM_N; i++)
  79. luaT_gettm(G(L), tag, i) = NULL;
  80. G(L)->TMtable[tag].collected = NULL;
  81. G(L)->TMtable[tag].name = ts;
  82. G(L)->TMtable[tag].basictype = basictype;
  83. G(L)->ntag++;
  84. return tag;
  85. }
  86. static void checktag (lua_State *L, int tag) {
  87. if (!(0 <= tag && tag < G(L)->ntag))
  88. luaO_verror(L, "%d is not a valid tag", tag);
  89. }
  90. LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) {
  91. int e;
  92. LUA_LOCK(L);
  93. checktag(L, tagto);
  94. checktag(L, tagfrom);
  95. for (e=0; e<TM_N; e++) {
  96. if (luaT_validevent(tagto, e))
  97. luaT_gettm(G(L), tagto, e) = luaT_gettm(G(L), tagfrom, e);
  98. }
  99. LUA_UNLOCK(L);
  100. return tagto;
  101. }
  102. int luaT_tag (const TObject *o) {
  103. int t = ttype(o);
  104. switch (t) {
  105. case LUA_TUSERDATA: return tsvalue(o)->u.d.tag;
  106. case LUA_TTABLE: return hvalue(o)->htag;
  107. default: return t;
  108. }
  109. }
  110. const char *luaT_typename (global_State *G, const TObject *o) {
  111. int t = ttype(o);
  112. int tag;
  113. TString *ts;
  114. switch (t) {
  115. case LUA_TUSERDATA:
  116. tag = tsvalue(o)->u.d.tag;
  117. break;
  118. case LUA_TTABLE:
  119. tag = hvalue(o)->htag;
  120. break;
  121. default:
  122. tag = t;
  123. }
  124. ts = G->TMtable[tag].name;
  125. if (ts == NULL)
  126. ts = G->TMtable[t].name;
  127. return ts->str;
  128. }
  129. LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) {
  130. int e;
  131. LUA_LOCK(L);
  132. e = luaI_checkevent(L, event, t);
  133. checktag(L, t);
  134. if (luaT_validevent(t, e) && luaT_gettm(G(L), t, e)) {
  135. setclvalue(L->top, luaT_gettm(G(L), t, e));
  136. }
  137. else
  138. setnilvalue(L->top);
  139. incr_top;
  140. LUA_UNLOCK(L);
  141. }
  142. LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) {
  143. int e;
  144. LUA_LOCK(L);
  145. e = luaI_checkevent(L, event, t);
  146. checktag(L, t);
  147. if (!luaT_validevent(t, e))
  148. luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s",
  149. luaT_eventname[e], basictypename(G(L), t),
  150. (t == LUA_TTABLE || t == LUA_TUSERDATA) ?
  151. " with default tag" : "");
  152. switch (ttype(L->top - 1)) {
  153. case LUA_TNIL:
  154. luaT_gettm(G(L), t, e) = NULL;
  155. break;
  156. case LUA_TFUNCTION:
  157. luaT_gettm(G(L), t, e) = clvalue(L->top - 1);
  158. break;
  159. default:
  160. luaD_error(L, "tag method must be a function (or nil)");
  161. }
  162. L->top--;
  163. LUA_UNLOCK(L);
  164. }