Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
9.2 KiB

  1. #include "sqplus.h"
  2. #ifdef _PS3
  3. #undef _STD_USING
  4. #endif
  5. #include <stdio.h>
  6. #if defined(VSCRIPT_DLL_EXPORT) || defined(VSQUIRREL_TEST)
  7. #include "memdbgon.h"
  8. #endif
  9. namespace SqPlus {
  10. static int getVarInfo(StackHandler & sa,VarRefPtr & vr) {
  11. HSQOBJECT htable = sa.GetObjectHandle(1);
  12. SquirrelObject table(htable);
  13. #ifdef _DEBUG
  14. SQObjectType type = (SQObjectType)sa.GetType(2);
  15. #endif
  16. const SQChar * el = sa.GetString(2);
  17. ScriptStringVar256 varNameTag;
  18. getVarNameTag(varNameTag,sizeof(varNameTag),el);
  19. SQUserPointer data=0;
  20. if (!table.RawGetUserData(varNameTag,&data)) {
  21. // throw SquirrelError("getVarInfo: Could not retrieve UserData");
  22. return sa.ThrowError(_T("getVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
  23. } // if
  24. vr = (VarRefPtr)data;
  25. return SQ_OK;
  26. } // getVarInfo
  27. static int getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data) {
  28. HSQOBJECT ho = sa.GetObjectHandle(1);
  29. SquirrelObject instance(ho);
  30. #ifdef _DEBUG
  31. SQObjectType type = (SQObjectType)sa.GetType(2);
  32. #endif
  33. const SQChar * el = sa.GetString(2);
  34. ScriptStringVar256 varNameTag;
  35. getVarNameTag(varNameTag,sizeof(varNameTag),el);
  36. SQUserPointer ivrData=0;
  37. if (!instance.RawGetUserData(varNameTag,&ivrData)) {
  38. // throw SquirrelError("getInstanceVarInfo: Could not retrieve UserData");
  39. return sa.ThrowError(_T("getInstanceVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
  40. } // if
  41. vr = (VarRefPtr)ivrData;
  42. unsigned char * up;
  43. if (!(vr->access & (VAR_ACCESS_STATIC|VAR_ACCESS_CONSTANT))) {
  44. #ifdef SQ_USE_CLASS_INHERITANCE
  45. SQUserPointer typetag; instance.GetTypeTag(&typetag);
  46. if (typetag != vr->instanceType) {
  47. SquirrelObject typeTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
  48. up = (unsigned char *)typeTable.GetUserPointer(INT((size_t)vr->instanceType)); // <TODO> 64-bit compatible version.
  49. if (!up) {
  50. throw SquirrelError(_T("Invalid Instance Type"));
  51. } // if
  52. } else {
  53. up = (unsigned char *)instance.GetInstanceUP(0);
  54. } // if
  55. #else
  56. up = (unsigned char *)instance.GetInstanceUP(0);
  57. #endif
  58. up += (size_t)vr->offsetOrAddrOrConst; // Offset
  59. } else {
  60. up = (unsigned char *)vr->offsetOrAddrOrConst; // Address
  61. } // if
  62. data = up;
  63. return SQ_OK;
  64. } // getInstanceVarInfo
  65. static int setVar(StackHandler & sa,VarRef * vr,void * data) {
  66. if (vr->access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) {
  67. ScriptStringVar256 msg;
  68. const SQChar * el = sa.GetString(2);
  69. SCSNPRINTF(msg.s,sizeof(msg),_T("setVar(): Cannot write to constant: %s"),el);
  70. throw SquirrelError(msg.s);
  71. } // if
  72. switch (vr->type) {
  73. case TypeInfo<INT>::TypeID: {
  74. INT * val = (INT *)data; // Address
  75. if (val) {
  76. *val = sa.GetInt(3);
  77. return sa.Return(*val);
  78. } // if
  79. break;
  80. } // case
  81. case TypeInfo<FLOAT>::TypeID: {
  82. FLOAT * val = (FLOAT *)data; // Address
  83. if (val) {
  84. *val = sa.GetFloat(3);
  85. return sa.Return(*val);
  86. } // if
  87. break;
  88. } // case
  89. case TypeInfo<bool>::TypeID: {
  90. bool * val = (bool *)data; // Address
  91. if (val) {
  92. *val = sa.GetBool(3) ? true : false;
  93. return sa.Return(*val);
  94. } // if
  95. break;
  96. } // case
  97. case VAR_TYPE_INSTANCE: {
  98. HSQUIRRELVM v = sa.GetVMPtr();
  99. // vr->copyFunc is the LHS variable type: the RHS var's type is ClassType<>::type() (both point to ClassType<>::copy()).
  100. // src will be null if the LHS and RHS types don't match.
  101. SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->copyFunc); // Effectively performs: ClassType<>::type() == ClassType<>getCopyFunc().
  102. if (!src) throw SquirrelError(_T("INSTANCE type assignment mismatch"));
  103. vr->copyFunc(data,src);
  104. #if 0 // Return an instance on the stack (allocates memory)
  105. if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address
  106. ScriptStringVar256 msg;
  107. SCSNPRINTF(msg.s,sizeof(msg),_T("getVar(): Could not create instance: %s"),vr->typeName);
  108. throw SquirrelError(msg.s);
  109. } // if
  110. return 1;
  111. #else // Don't return on stack.
  112. return 0;
  113. #endif
  114. }
  115. case TypeInfo<SQUserPointer>::TypeID: {
  116. ScriptStringVar256 msg;
  117. const SQChar * el = sa.GetString(2);
  118. SCSNPRINTF(msg.s,sizeof(msg),_T("setVar(): Cannot write to an SQUserPointer: %s"),el);
  119. throw SquirrelError(msg.s);
  120. } // case
  121. case TypeInfo<ScriptStringVarBase>::TypeID: {
  122. ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address
  123. if (val) {
  124. const SQChar * strVal = sa.GetString(3);
  125. if (strVal) {
  126. *val = strVal;
  127. return sa.Return(val->s);
  128. } // if
  129. } // if
  130. break;
  131. } // case
  132. } // switch
  133. return SQ_ERROR;
  134. } // setVar
  135. static int getVar(StackHandler & sa,VarRef * vr,void * data) {
  136. switch (vr->type) {
  137. case TypeInfo<INT>::TypeID: {
  138. if (!(vr->access & VAR_ACCESS_CONSTANT)) {
  139. INT * val = (INT *)data; // Address
  140. if (val) {
  141. return sa.Return(*val);
  142. } // if
  143. } else {
  144. INT * val = (INT *)&data; // Constant value
  145. return sa.Return(*val);
  146. } // if
  147. break;
  148. } // case
  149. case TypeInfo<FLOAT>::TypeID: {
  150. if (!(vr->access & VAR_ACCESS_CONSTANT)) {
  151. FLOAT * val = (FLOAT *)data; // Address
  152. if (val) {
  153. return sa.Return(*val);
  154. } // if
  155. } else {
  156. FLOAT * val = (FLOAT *)&data; // Constant value
  157. return sa.Return(*val);
  158. } // if
  159. break;
  160. } // case
  161. case TypeInfo<bool>::TypeID: {
  162. if (!(vr->access & VAR_ACCESS_CONSTANT)) {
  163. bool * val = (bool *)data; // Address
  164. if (val) {
  165. return sa.Return(*val);
  166. } // if
  167. } else {
  168. bool * val = (bool *)&data; // Constant value
  169. return sa.Return(*val);
  170. } // if
  171. break;
  172. } // case
  173. case VAR_TYPE_INSTANCE:
  174. if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address. Allocates memory.
  175. ScriptStringVar256 msg;
  176. SCSNPRINTF(msg.s,sizeof(msg),_T("getVar(): Could not create instance: %s"),vr->typeName);
  177. throw SquirrelError(msg.s);
  178. } // if
  179. return 1;
  180. case TypeInfo<SQUserPointer>::TypeID: {
  181. return sa.Return(data); // The address of member variable, not the variable itself.
  182. } // case
  183. case TypeInfo<ScriptStringVarBase>::TypeID: {
  184. if (!(vr->access & VAR_ACCESS_CONSTANT)) {
  185. ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address
  186. if (val) {
  187. return sa.Return(val->s);
  188. } // if
  189. } else {
  190. throw SquirrelError(_T("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)"));
  191. } // if
  192. break;
  193. } // case
  194. case TypeInfo<const SQChar *>::TypeID: {
  195. if (!(vr->access & VAR_ACCESS_CONSTANT)) {
  196. throw SquirrelError(_T("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT"));
  197. } else {
  198. return sa.Return((const SQChar *)data); // Address
  199. } // if
  200. break;
  201. } // case
  202. } // switch
  203. return SQ_ERROR;
  204. } // getVar
  205. // === Global Vars ===
  206. SQInteger setVarFunc(HSQUIRRELVM v) {
  207. StackHandler sa(v);
  208. if (sa.GetType(1) == OT_TABLE) {
  209. VarRefPtr vr;
  210. int res = getVarInfo(sa,vr);
  211. if (res != SQ_OK) return res;
  212. return setVar(sa,vr,vr->offsetOrAddrOrConst);
  213. } // if
  214. return SQ_ERROR;
  215. } // setVarFunc
  216. SQInteger getVarFunc(HSQUIRRELVM v) {
  217. StackHandler sa(v);
  218. if (sa.GetType(1) == OT_TABLE) {
  219. VarRefPtr vr;
  220. int res = getVarInfo(sa,vr);
  221. if (res != SQ_OK) return res;
  222. return getVar(sa,vr,vr->offsetOrAddrOrConst);
  223. } // if
  224. return SQ_ERROR;
  225. } // getVarFunc
  226. // === Instance Vars ===
  227. SQInteger setInstanceVarFunc(HSQUIRRELVM v) {
  228. StackHandler sa(v);
  229. if (sa.GetType(1) == OT_INSTANCE) {
  230. VarRefPtr vr;
  231. void * data;
  232. int res = getInstanceVarInfo(sa,vr,data);
  233. if (res != SQ_OK) return res;
  234. return setVar(sa,vr,data);
  235. } // if
  236. return SQ_ERROR;
  237. } // setInstanceVarFunc
  238. SQInteger getInstanceVarFunc(HSQUIRRELVM v) {
  239. StackHandler sa(v);
  240. if (sa.GetType(1) == OT_INSTANCE) {
  241. VarRefPtr vr;
  242. void * data;
  243. int res = getInstanceVarInfo(sa,vr,data);
  244. if (res != SQ_OK) return res;
  245. return getVar(sa,vr,data);
  246. } // if
  247. return SQ_ERROR;
  248. } // getInstanceVarFunc
  249. // === Classes ===
  250. BOOL CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName) {
  251. int n = 0;
  252. int oldtop = sq_gettop(v);
  253. sq_pushroottable(v);
  254. sq_pushstring(v,name,-1);
  255. if (baseName) {
  256. sq_pushstring(v,baseName,-1);
  257. if (SQ_FAILED(sq_get(v,-3))) { // Make sure the base exists if specified by baseName.
  258. sq_settop(v,oldtop);
  259. return FALSE;
  260. } // if
  261. } // if
  262. if (SQ_FAILED(sq_newclass(v,baseName ? 1 : 0))) { // Will inherit from base class on stack from sq_get() above.
  263. sq_settop(v,oldtop);
  264. return FALSE;
  265. } // if
  266. newClass.AttachToStackObject(-1);
  267. sq_settypetag(v,-1,classType);
  268. sq_createslot(v,-3);
  269. sq_pop(v,1);
  270. return TRUE;
  271. } // CreateClass
  272. SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,SQUserPointer classType,SQFUNCTION constructor) {
  273. int top = sq_gettop(v);
  274. SquirrelObject newClass;
  275. if (CreateClass(v,newClass,classType,scriptClassName)) {
  276. SquirrelVM::CreateFunction(newClass,constructor,_T("constructor"));
  277. } // if
  278. sq_settop(v,top);
  279. return newClass;
  280. } // RegisterClassType
  281. }; // namespace SqPlus
  282. // sqPlus