fallback.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. ** fallback.c
  3. ** TecCGraf - PUC-Rio
  4. */
  5. char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable roberto $";
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "mem.h"
  9. #include "fallback.h"
  10. #include "opcode.h"
  11. #include "lua.h"
  12. #include "table.h"
  13. #include "tree.h"
  14. #include "hash.h"
  15. static void errorFB (void);
  16. static void indexFB (void);
  17. static void gettableFB (void);
  18. static void arithFB (void);
  19. static void concatFB (void);
  20. static void orderFB (void);
  21. static void GDFB (void);
  22. static void funcFB (void);
  23. /*
  24. ** Warning: This list must be in the same order as the #define's
  25. */
  26. struct FB luaI_fallBacks[] = {
  27. {"gettable", {LUA_T_CFUNCTION, {gettableFB}}, 2, 1},
  28. {"arith", {LUA_T_CFUNCTION, {arithFB}}, 3, 1},
  29. {"order", {LUA_T_CFUNCTION, {orderFB}}, 3, 1},
  30. {"concat", {LUA_T_CFUNCTION, {concatFB}}, 2, 1},
  31. {"settable", {LUA_T_CFUNCTION, {gettableFB}}, 3, 0},
  32. {"gc", {LUA_T_CFUNCTION, {GDFB}}, 1, 0},
  33. {"function", {LUA_T_CFUNCTION, {funcFB}}, -1, -1},
  34. /* no fixed number of params or results */
  35. {"getglobal", {LUA_T_CFUNCTION, {indexFB}}, 1, 1},
  36. /* same default behavior of index FB */
  37. {"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1},
  38. {"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0}
  39. };
  40. #define N_FB (sizeof(luaI_fallBacks)/sizeof(struct FB))
  41. static int luaI_findevent (char *name)
  42. {
  43. int i;
  44. for (i=0; i<N_FB; i++)
  45. if (strcmp(luaI_fallBacks[i].kind, name) == 0)
  46. return i;
  47. /* name not found */
  48. lua_error("invalid event name");
  49. return 0; /* to avoid warnings */
  50. }
  51. void luaI_setfallback (void)
  52. {
  53. int i;
  54. char *name = lua_getstring(lua_getparam(1));
  55. lua_Object func = lua_getparam(2);
  56. if (name == NULL || !lua_isfunction(func))
  57. lua_error("incorrect argument to function `setfallback'");
  58. i = luaI_findevent(name);
  59. luaI_pushobject(&luaI_fallBacks[i].function);
  60. luaI_fallBacks[i].function = *luaI_Address(func);
  61. }
  62. static void errorFB (void)
  63. {
  64. lua_Object o = lua_getparam(1);
  65. if (lua_isstring(o))
  66. fprintf (stderr, "lua: %s\n", lua_getstring(o));
  67. else
  68. fprintf(stderr, "lua: unknown error\n");
  69. }
  70. static void indexFB (void)
  71. {
  72. lua_pushnil();
  73. }
  74. static void gettableFB (void)
  75. {
  76. lua_error("indexed expression not a table");
  77. }
  78. static void arithFB (void)
  79. {
  80. lua_error("unexpected type at conversion to number");
  81. }
  82. static void concatFB (void)
  83. {
  84. lua_error("unexpected type at conversion to string");
  85. }
  86. static void orderFB (void)
  87. {
  88. lua_error("unexpected type at comparison");
  89. }
  90. static void GDFB (void) { }
  91. static void funcFB (void)
  92. {
  93. lua_error("call expression not a function");
  94. }
  95. /* -------------------------------------------
  96. ** Reference routines
  97. */
  98. static struct ref {
  99. Object o;
  100. enum {LOCK, HOLD, FREE, COLLECTED} status;
  101. } *refArray = NULL;
  102. static int refSize = 0;
  103. int luaI_ref (Object *object, int lock)
  104. {
  105. int i;
  106. int oldSize;
  107. if (ttype(object) == LUA_T_NIL)
  108. return -1; /* special ref for nil */
  109. for (i=0; i<refSize; i++)
  110. if (refArray[i].status == FREE)
  111. goto found;
  112. /* no more empty spaces */
  113. oldSize = refSize;
  114. refSize = growvector(&refArray, refSize, struct ref, refEM, MAX_WORD);
  115. for (i=oldSize; i<refSize; i++)
  116. refArray[i].status = FREE;
  117. i = oldSize;
  118. found:
  119. refArray[i].o = *object;
  120. refArray[i].status = lock ? LOCK : HOLD;
  121. return i;
  122. }
  123. void lua_unref (int ref)
  124. {
  125. if (ref >= 0 && ref < refSize)
  126. refArray[ref].status = FREE;
  127. }
  128. Object *luaI_getref (int ref)
  129. {
  130. static Object nul = {LUA_T_NIL, {0}};
  131. if (ref == -1)
  132. return &nul;
  133. if (ref >= 0 && ref < refSize &&
  134. (refArray[ref].status == LOCK || refArray[ref].status == HOLD))
  135. return &refArray[ref].o;
  136. else
  137. return NULL;
  138. }
  139. void luaI_travlock (int (*fn)(Object *))
  140. {
  141. int i;
  142. for (i=0; i<refSize; i++)
  143. if (refArray[i].status == LOCK)
  144. fn(&refArray[i].o);
  145. }
  146. void luaI_invalidaterefs (void)
  147. {
  148. int i;
  149. for (i=0; i<refSize; i++)
  150. if (refArray[i].status == HOLD && !luaI_ismarked(&refArray[i].o))
  151. refArray[i].status = COLLECTED;
  152. }
  153. char *luaI_travfallbacks (int (*fn)(Object *))
  154. {
  155. int i;
  156. for (i=0; i<N_FB; i++)
  157. if (fn(&luaI_fallBacks[i].function))
  158. return luaI_fallBacks[i].kind;
  159. return NULL;
  160. }
  161. /* -------------------------------------------
  162. * Internal Methods
  163. */
  164. #define BASE_TAG 1000
  165. static struct IM {
  166. lua_Type tp;
  167. Object int_method[FB_N];
  168. } *luaI_IMtable = NULL;
  169. static int IMtable_size = 0;
  170. static int last_tag = BASE_TAG-1;
  171. int lua_newtag (char *t)
  172. {
  173. int i;
  174. ++last_tag;
  175. if ((last_tag-BASE_TAG) >= IMtable_size)
  176. IMtable_size = growvector(&luaI_IMtable, IMtable_size,
  177. struct IM, memEM, MAX_INT);
  178. if (strcmp(t, "table") == 0)
  179. luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_ARRAY;
  180. else if (strcmp(t, "userdata") == 0)
  181. luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_USERDATA;
  182. else
  183. lua_error("invalid type for new tag");
  184. for (i=0; i<FB_N; i++)
  185. luaI_IMtable[last_tag-BASE_TAG].int_method[i].ttype = LUA_T_NIL;
  186. return last_tag;
  187. }
  188. static int validtag (int tag)
  189. {
  190. return (BASE_TAG <= tag && tag <= last_tag);
  191. }
  192. static void checktag (int tag)
  193. {
  194. if (!validtag(tag))
  195. lua_error("invalid tag");
  196. }
  197. void luaI_settag (int tag, Object *o)
  198. {
  199. checktag(tag);
  200. if (ttype(o) != luaI_IMtable[tag-BASE_TAG].tp)
  201. lua_error("Tag is not compatible with this type");
  202. if (o->ttype == LUA_T_ARRAY)
  203. o->value.a->htag = tag;
  204. else /* must be userdata */
  205. o->value.ts->tag = tag;
  206. }
  207. int luaI_tag (Object *o)
  208. {
  209. lua_Type t = ttype(o);
  210. if (t == LUA_T_USERDATA)
  211. return o->value.ts->tag;
  212. else if (t == LUA_T_ARRAY)
  213. return o->value.a->htag;
  214. else return t;
  215. }
  216. Object *luaI_getim (int tag, int event)
  217. {
  218. if (tag == 0)
  219. return &luaI_fallBacks[event].function;
  220. else if (validtag(tag)) {
  221. Object *func = &luaI_IMtable[tag-BASE_TAG].int_method[event];
  222. if (func->ttype == LUA_T_NIL)
  223. return NULL;
  224. else
  225. return func;
  226. }
  227. else return NULL;
  228. }
  229. void luaI_setintmethod (void)
  230. {
  231. lua_Object tag = lua_getparam(1);
  232. lua_Object event = lua_getparam(2);
  233. lua_Object func = lua_getparam(3);
  234. if (!(lua_isnumber(tag) && lua_isstring(event) && lua_isfunction(func)))
  235. lua_error("incorrect arguments to function `setintmethod'");
  236. else {
  237. int i = luaI_findevent(lua_getstring(event));
  238. int t = lua_getnumber(tag);
  239. checktag(t);
  240. luaI_IMtable[t-BASE_TAG].int_method[i] = *luaI_Address(func);
  241. }
  242. }