2
0

sqstdio.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /* see copyright notice in squirrel.h */
  2. #include <new>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <squirrel.h>
  6. #include <sqstdio.h>
  7. #include "sqstdstream.h"
  8. //#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
  9. static const SQChar SQSTD_FILE_TYPE_TAG[] = _SC("std_stream_file");
  10. //basic API
  11. SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
  12. {
  13. return (SQFILE)scfopen(filename,mode);
  14. }
  15. SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
  16. {
  17. return (SQInteger)fread(buffer,size,count,(FILE *)file);
  18. }
  19. SQChar *sqstd_fgets(SQChar* buffer, SQInteger count, SQFILE file)
  20. {
  21. return (SQChar*)fgets(buffer,count,(FILE *)file);
  22. }
  23. SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
  24. {
  25. return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
  26. }
  27. SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin)
  28. {
  29. SQInteger realorigin;
  30. switch(origin) {
  31. case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
  32. case SQ_SEEK_END: realorigin = SEEK_END; break;
  33. case SQ_SEEK_SET: realorigin = SEEK_SET; break;
  34. default: return -1; //failed
  35. }
  36. return fseek((FILE *)file,(long)offset,(int)realorigin);
  37. }
  38. SQInteger sqstd_ftell(SQFILE file)
  39. {
  40. return ftell((FILE *)file);
  41. }
  42. SQInteger sqstd_fflush(SQFILE file)
  43. {
  44. return fflush((FILE *)file);
  45. }
  46. SQInteger sqstd_fclose(SQFILE file)
  47. {
  48. return fclose((FILE *)file);
  49. }
  50. SQInteger sqstd_feof(SQFILE file)
  51. {
  52. return feof((FILE *)file);
  53. }
  54. //File
  55. struct SQFile : public SQStream {
  56. SQFile() { _handle = NULL; _owns = false;}
  57. SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
  58. virtual ~SQFile() { Close(); }
  59. bool Open(const SQChar *filename ,const SQChar *mode) {
  60. Close();
  61. if( (_handle = sqstd_fopen(filename,mode)) ) {
  62. _owns = true;
  63. return true;
  64. }
  65. return false;
  66. }
  67. void Close() {
  68. if(_handle && _owns) {
  69. sqstd_fclose(_handle);
  70. _handle = NULL;
  71. _owns = false;
  72. }
  73. }
  74. SQInteger Read(void *buffer,SQInteger size) {
  75. return sqstd_fread(buffer,1,size,_handle);
  76. }
  77. SQInteger Gets(char *buffer,SQInteger size) {
  78. SQChar *res = sqstd_fgets(buffer,size,_handle);
  79. return res ? scstrlen(res) : 0;
  80. }
  81. SQInteger Write(const void *buffer,SQInteger size) {
  82. return sqstd_fwrite((const SQUserPointer)buffer,1,size,_handle);
  83. }
  84. SQInteger Flush() {
  85. return sqstd_fflush(_handle);
  86. }
  87. SQInteger Tell() {
  88. return sqstd_ftell(_handle);
  89. }
  90. SQInteger Len() {
  91. SQInteger prevpos=Tell();
  92. Seek(0,SQ_SEEK_END);
  93. SQInteger size=Tell();
  94. Seek(prevpos,SQ_SEEK_SET);
  95. return size;
  96. }
  97. SQInteger Seek(SQInteger offset, SQInteger origin) {
  98. return sqstd_fseek(_handle,offset,origin);
  99. }
  100. bool IsValid() { return _handle?true:false; }
  101. bool EOS() { return Tell()==Len()?true:false;}
  102. SQFILE GetHandle() {return _handle;}
  103. private:
  104. SQFILE _handle;
  105. bool _owns;
  106. };
  107. static SQRESULT _file__typeof(HSQUIRRELVM v)
  108. {
  109. sq_pushstring(v,_SC("file"),-1);
  110. return 1;
  111. }
  112. static SQRESULT _file_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  113. {
  114. SQFile *self = (SQFile*)p;
  115. self->~SQFile();
  116. sq_free(self,sizeof(SQFile));
  117. return 1;
  118. }
  119. static SQRESULT _file_constructor(HSQUIRRELVM v)
  120. {
  121. const SQChar *filename,*mode;
  122. bool owns = true;
  123. SQFile *f;
  124. SQFILE newf;
  125. if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
  126. sq_getstring(v, 2, &filename);
  127. sq_getstring(v, 3, &mode);
  128. newf = sqstd_fopen(filename, mode);
  129. if(!newf) return sq_throwerror(v, _SC("cannot open file"));
  130. } else if(sq_gettype(v,2) == OT_USERPOINTER) {
  131. owns = !(sq_gettype(v,3) == OT_NULL);
  132. sq_getuserpointer(v,2,&newf);
  133. } else {
  134. return sq_throwerror(v,_SC("wrong parameter"));
  135. }
  136. f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
  137. if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
  138. f->~SQFile();
  139. sq_free(f,sizeof(SQFile));
  140. return sq_throwerror(v, _SC("cannot create blob with negative size"));
  141. }
  142. sq_setreleasehook(v,1,_file_releasehook);
  143. return 0;
  144. }
  145. static SQRESULT _file_close(HSQUIRRELVM v)
  146. {
  147. SQFile *self = NULL;
  148. if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
  149. && self != NULL)
  150. {
  151. self->Close();
  152. }
  153. return 0;
  154. }
  155. //bindings
  156. #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
  157. static const SQRegFunction _file_methods[] = {
  158. _DECL_FILE_FUNC(constructor,3,_SC("x")),
  159. _DECL_FILE_FUNC(_typeof,1,_SC("x")),
  160. _DECL_FILE_FUNC(close,1,_SC("x")),
  161. {NULL,(SQFUNCTION)0,0,NULL}
  162. };
  163. SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
  164. {
  165. SQInteger top = sq_gettop(v);
  166. sq_pushregistrytable(v);
  167. sq_pushstring(v,_SC("std_file"),-1);
  168. if(SQ_SUCCEEDED(sq_get(v,-2))) {
  169. sq_remove(v,-2); //removes the registry
  170. sq_pushroottable(v); // push the this
  171. sq_pushuserpointer(v,file); //file
  172. if(own){
  173. sq_pushinteger(v,1); //true
  174. }
  175. else{
  176. sq_pushnull(v); //false
  177. }
  178. if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) {
  179. sq_remove(v,-2);
  180. return SQ_OK;
  181. }
  182. }
  183. sq_settop(v,top);
  184. return SQ_ERROR;
  185. }
  186. SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
  187. {
  188. SQFile *fileobj = NULL;
  189. if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) {
  190. *file = fileobj->GetHandle();
  191. return SQ_OK;
  192. }
  193. return sq_throwerror(v,_SC("not a file"));
  194. }
  195. #define IO_BUFFER_SIZE 2048
  196. struct IOBuffer {
  197. unsigned char buffer[IO_BUFFER_SIZE];
  198. SQInteger size;
  199. SQInteger ptr;
  200. SQFILE file;
  201. };
  202. SQInteger _read_byte(IOBuffer *iobuffer)
  203. {
  204. if(iobuffer->ptr < iobuffer->size) {
  205. SQInteger ret = iobuffer->buffer[iobuffer->ptr];
  206. iobuffer->ptr++;
  207. return ret;
  208. }
  209. else {
  210. if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
  211. {
  212. SQInteger ret = iobuffer->buffer[0];
  213. iobuffer->ptr = 1;
  214. return ret;
  215. }
  216. }
  217. return 0;
  218. }
  219. SQInteger _read_two_bytes(IOBuffer *iobuffer)
  220. {
  221. if(iobuffer->ptr < iobuffer->size) {
  222. if(iobuffer->size < 2) return 0;
  223. SQInteger ret = *((const wchar_t*)&iobuffer->buffer[iobuffer->ptr]);
  224. iobuffer->ptr += 2;
  225. return ret;
  226. }
  227. else {
  228. if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
  229. {
  230. if(iobuffer->size < 2) return 0;
  231. SQInteger ret = *((const wchar_t*)&iobuffer->buffer[0]);
  232. iobuffer->ptr = 2;
  233. return ret;
  234. }
  235. }
  236. return 0;
  237. }
  238. static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer iobuf)
  239. {
  240. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  241. return _read_byte(iobuffer);
  242. }
  243. #ifdef SQUNICODE
  244. static SQInteger _io_file_lexfeed_UTF8(SQUserPointer iobuf)
  245. {
  246. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  247. #define READ(iobuf) \
  248. if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \
  249. return 0;
  250. static const SQInteger utf8_lengths[16] =
  251. {
  252. 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */
  253. 0,0,0,0, /* 1000 to 1011 : not valid */
  254. 2,2, /* 1100, 1101 : 2 bytes */
  255. 3, /* 1110 : 3 bytes */
  256. 4 /* 1111 :4 bytes */
  257. };
  258. static const unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};
  259. unsigned char inchar;
  260. SQInteger c = 0;
  261. READ(iobuffer);
  262. c = inchar;
  263. //
  264. if(c >= 0x80) {
  265. SQInteger tmp;
  266. SQInteger codelen = utf8_lengths[c>>4];
  267. if(codelen == 0)
  268. return 0;
  269. //"invalid UTF-8 stream";
  270. tmp = c&byte_masks[codelen];
  271. for(SQInteger n = 0; n < codelen-1; n++) {
  272. tmp<<=6;
  273. READ(iobuffer);
  274. tmp |= inchar & 0x3F;
  275. }
  276. c = tmp;
  277. }
  278. return c;
  279. }
  280. #endif
  281. static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer iobuf)
  282. {
  283. SQInteger ret;
  284. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  285. if( (ret = _read_two_bytes(iobuffer)) > 0 )
  286. return ret;
  287. return 0;
  288. }
  289. static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer iobuf)
  290. {
  291. SQInteger c;
  292. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  293. if( (c = _read_two_bytes(iobuffer)) > 0 ) {
  294. c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
  295. return c;
  296. }
  297. return 0;
  298. }
  299. SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
  300. {
  301. SQInteger ret;
  302. if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
  303. return -1;
  304. }
  305. SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size)
  306. {
  307. return sqstd_fwrite(p,1,size,(SQFILE)file);
  308. }
  309. SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror,SQBool show_warnings)
  310. {
  311. SQFILE file = sqstd_fopen(filename,_SC("rb"));
  312. SQInteger ret;
  313. unsigned short us;
  314. unsigned char uc;
  315. SQLEXREADFUNC func = _io_file_lexfeed_PLAIN;
  316. if(file){
  317. ret = sqstd_fread(&us,1,2,file);
  318. if(ret != 2) {
  319. //probably an empty file
  320. us = 0;
  321. }
  322. if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE
  323. sqstd_fseek(file,0,SQ_SEEK_SET);
  324. if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
  325. sqstd_fclose(file);
  326. return SQ_OK;
  327. }
  328. }
  329. else { //SCRIPT
  330. switch(us)
  331. {
  332. //gotta swap the next 2 lines on BIG endian machines
  333. case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
  334. case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
  335. case 0xBBEF:
  336. if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) {
  337. sqstd_fclose(file);
  338. return sq_throwerror(v,_SC("io error"));
  339. }
  340. if(uc != 0xBF) {
  341. sqstd_fclose(file);
  342. return sq_throwerror(v,_SC("Unrecognozed ecoding"));
  343. }
  344. #ifdef SQUNICODE
  345. func = _io_file_lexfeed_UTF8;
  346. #else
  347. func = _io_file_lexfeed_PLAIN;
  348. #endif
  349. break;//UTF-8 ;
  350. default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
  351. }
  352. IOBuffer buffer;
  353. buffer.ptr = 0;
  354. buffer.size = 0;
  355. buffer.file = file;
  356. if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,filename,printerror,show_warnings))){
  357. sqstd_fclose(file);
  358. return SQ_OK;
  359. }
  360. }
  361. sqstd_fclose(file);
  362. return SQ_ERROR;
  363. }
  364. return sq_throwerror(v,_SC("cannot open the file"));
  365. }
  366. SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror,SQBool show_warnings)
  367. {
  368. if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror,show_warnings))) {
  369. sq_push(v,-2);
  370. if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
  371. sq_remove(v,retval?-2:-1); //removes the closure
  372. return 1;
  373. }
  374. sq_pop(v,1); //removes the closure
  375. }
  376. return SQ_ERROR;
  377. }
  378. SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
  379. {
  380. SQFILE file = sqstd_fopen(filename,_SC("wb+"));
  381. if(!file) return sq_throwerror(v,_SC("cannot open the file"));
  382. if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
  383. sqstd_fclose(file);
  384. return SQ_OK;
  385. }
  386. sqstd_fclose(file);
  387. return SQ_ERROR; //forward the error
  388. }
  389. SQRESULT sqstd_writeclosuretofile_as_source(HSQUIRRELVM v,const SQChar *filename)
  390. {
  391. SQFILE file = sqstd_fopen(filename,_SC("wb+"));
  392. if(!file) return sq_throwerror(v,_SC("cannot open the file"));
  393. if(SQ_SUCCEEDED(sq_writeclosure_as_source(v,file_write,file))) {
  394. sqstd_fclose(file);
  395. return SQ_OK;
  396. }
  397. sqstd_fclose(file);
  398. return SQ_ERROR; //forward the error
  399. }
  400. SQInteger _g_io_loadfile(HSQUIRRELVM v)
  401. {
  402. SQ_FUNC_VARS(v);
  403. SQ_GET_STRING(v, 2, filename);
  404. SQ_OPT_BOOL(v, 3, printerror, SQFalse);
  405. SQ_OPT_BOOL(v, 4, show_warnings, SQTrue);
  406. if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror,show_warnings)))
  407. return 1;
  408. return SQ_ERROR; //propagates the error
  409. }
  410. SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
  411. {
  412. const SQChar *filename;
  413. sq_getstring(v,2,&filename);
  414. if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))
  415. return 1;
  416. return SQ_ERROR; //propagates the error
  417. }
  418. #include "sqstdblobimpl.h"
  419. SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size);
  420. SQInteger _g_io_dumpclosure(HSQUIRRELVM v)
  421. {
  422. SQBlob b(0,8192);
  423. if(SQ_SUCCEEDED(sq_writeclosure(v,blob_write,&b))) {
  424. sq_pushstring(v, (const SQChar*)b.GetBuf(), b.Len());
  425. return 1;
  426. }
  427. return SQ_ERROR; //forward the error
  428. }
  429. SQInteger blob_read(SQUserPointer file,SQUserPointer p,SQInteger size);
  430. SQInteger _g_io_loadstring(HSQUIRRELVM v)
  431. {
  432. if(sq_gettype(v, 2) != OT_STRING) return sq_throwerror(v, _SC("string expected as parameter"));
  433. SQInteger rc, size = sq_getsize(v, 2);
  434. const SQChar *dump;
  435. sq_getstring(v, 2, &dump);
  436. unsigned short tag = *((unsigned short*)dump);
  437. if(tag == SQ_BYTECODE_STREAM_TAG){
  438. SQBlob b(0, size);
  439. b.Write(dump, size);
  440. b.Seek(0, SQ_SEEK_SET);
  441. rc = sq_readclosure(v, blob_read, &b);
  442. }
  443. else
  444. {
  445. rc = sq_compilebuffer(v, dump, size, _SC("loadstring"), SQFalse, SQFalse);
  446. }
  447. return rc < 0 ? rc : 1;
  448. }
  449. SQInteger _g_io_dostring(HSQUIRRELVM v)
  450. {
  451. SQ_FUNC_VARS(v);
  452. SQInteger rc = _g_io_loadstring(v);
  453. if(rc < 0) return rc;
  454. SQ_OPT_BOOL(v, 3, retval, SQFalse);
  455. sq_push(v,1); //this environment
  456. if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
  457. sq_remove(v,retval?-2:-1); //removes the closure
  458. return 1;
  459. }
  460. sq_pop(v,1); //removes the closure
  461. return SQ_ERROR; //forward the error
  462. }
  463. SQInteger _g_io_dofile(HSQUIRRELVM v)
  464. {
  465. SQ_FUNC_VARS(v);
  466. SQ_GET_STRING(v, 2, filename);
  467. SQ_OPT_BOOL(v, 3, printerror, SQFalse);
  468. SQ_OPT_BOOL(v, 4, show_warnings, SQTrue);
  469. sq_push(v,1); //repush the this
  470. if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror,show_warnings)))
  471. return 1;
  472. return SQ_ERROR; //propagates the error
  473. }
  474. SQInteger _g_io_readfile(HSQUIRRELVM v)
  475. {
  476. SQ_FUNC_VARS_NO_TOP(v);
  477. SQ_GET_STRING(v, 2, filename);
  478. SQFile fs;
  479. if(fs.Open(filename, "rb"))
  480. {
  481. SQInteger size,res;
  482. SQChar *data;
  483. size = fs.Len();
  484. data = sq_getscratchpad(v,size);
  485. res = fs.Read(data,size);
  486. if(res <= 0)
  487. return sq_throwerror(v,_SC("no data left to read"));
  488. sq_pushstring(v,data,res);
  489. return 1;
  490. }
  491. return sq_throwerror(v,_SC("could not open file %s"), filename);
  492. }
  493. SQInteger _g_io_writefile(HSQUIRRELVM v)
  494. {
  495. SQ_FUNC_VARS_NO_TOP(v);
  496. SQ_GET_STRING(v, 2, filename);
  497. SQ_GET_STRING(v, 3, data);
  498. SQFile fs;
  499. if(fs.Open(filename, "wb"))
  500. {
  501. SQInteger res = fs.Write(data, data_size);
  502. if(res != data_size)
  503. return sq_throwerror(v,_SC("could not write to file"));
  504. return 0;
  505. }
  506. return sq_throwerror(v,_SC("could not open file %s"), filename);
  507. }
  508. #define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
  509. static const SQRegFunction iolib_funcs[]={
  510. _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sbb")),
  511. _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sbb")),
  512. _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
  513. _DECL_GLOBALIO_FUNC(dostring,-2,_SC(".sb")),
  514. _DECL_GLOBALIO_FUNC(loadstring,2,_SC(".s")),
  515. _DECL_GLOBALIO_FUNC(dumpclosure,3,_SC(".sc")),
  516. _DECL_GLOBALIO_FUNC(readfile,2,_SC(".s")),
  517. _DECL_GLOBALIO_FUNC(writefile,3,_SC(".ss")),
  518. {NULL,(SQFUNCTION)0,0,NULL}
  519. };
  520. SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
  521. {
  522. //create delegate
  523. declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
  524. sq_pushstring(v,_SC("stdout"),-1);
  525. sqstd_createfile(v,stdout,SQFalse);
  526. sq_newslot(v,-3,SQFalse);
  527. sq_pushstring(v,_SC("stdin"),-1);
  528. sqstd_createfile(v,stdin,SQFalse);
  529. sq_newslot(v,-3,SQFalse);
  530. sq_pushstring(v,_SC("stderr"),-1);
  531. sqstd_createfile(v,stderr,SQFalse);
  532. sq_newslot(v,-3,SQFalse);
  533. return SQ_OK;
  534. }