sqstdio.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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. virtual 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. virtual 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. protected:
  104. SQFILE _handle;
  105. bool _owns;
  106. };
  107. struct SQPopen : public SQFile {
  108. SQPopen():SQFile() {}
  109. SQPopen(SQFILE file, bool owns):SQFile(file, owns) {}
  110. bool Open(const SQChar *filename ,const SQChar *mode) {
  111. Close();
  112. if( (_handle = popen(filename,mode)) ) {
  113. _owns = true;
  114. return true;
  115. }
  116. return false;
  117. }
  118. int PClose() {
  119. int result = 0;
  120. if(_handle && _owns) {
  121. result = pclose((FILE*)_handle);
  122. _handle = NULL;
  123. _owns = false;
  124. }
  125. return result;
  126. }
  127. void Close() {
  128. PClose();
  129. }
  130. };
  131. static SQRESULT _popen__typeof(HSQUIRRELVM v)
  132. {
  133. sq_pushstring(v,_SC("popen"),-1);
  134. return 1;
  135. }
  136. static SQRESULT _popen_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  137. {
  138. SQPopen *self = (SQPopen*)p;
  139. self->~SQPopen();
  140. sq_free(self,sizeof(SQFile));
  141. return 1;
  142. }
  143. static SQRESULT _popen_constructor(HSQUIRRELVM v)
  144. {
  145. const SQChar *filename,*mode;
  146. bool owns = true;
  147. SQPopen *f;
  148. SQFILE newf;
  149. if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
  150. sq_getstring(v, 2, &filename);
  151. sq_getstring(v, 3, &mode);
  152. newf = popen(filename, mode);
  153. if(!newf) return sq_throwerror(v, _SC("cannot open file"));
  154. } else {
  155. return sq_throwerror(v,_SC("wrong parameter"));
  156. }
  157. f = new (sq_malloc(sizeof(SQPopen)))SQPopen(newf,owns);
  158. if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
  159. f->~SQPopen();
  160. sq_free(f,sizeof(SQPopen));
  161. return sq_throwerror(v, _SC("cannot create popen"));
  162. }
  163. sq_setreleasehook(v,1,_popen_releasehook);
  164. return 0;
  165. }
  166. static SQRESULT _popen_close(HSQUIRRELVM v)
  167. {
  168. SQPopen *self = NULL;
  169. if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
  170. && self != NULL)
  171. {
  172. sq_pushinteger(v, self->PClose());
  173. return 1;
  174. }
  175. return 0;
  176. }
  177. //bindings
  178. #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_popen_##name,nparams,typecheck}
  179. static const SQRegFunction _popen_methods[] = {
  180. _DECL_FILE_FUNC(constructor,3,_SC("x")),
  181. _DECL_FILE_FUNC(_typeof,1,_SC("x")),
  182. _DECL_FILE_FUNC(close,1,_SC("x")),
  183. {NULL,(SQFUNCTION)0,0,NULL}
  184. };
  185. #undef _DECL_FILE_FUNC
  186. static SQRESULT _file__typeof(HSQUIRRELVM v)
  187. {
  188. sq_pushstring(v,_SC("file"),-1);
  189. return 1;
  190. }
  191. static SQRESULT _file_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  192. {
  193. SQFile *self = (SQFile*)p;
  194. self->~SQFile();
  195. sq_free(self,sizeof(SQFile));
  196. return 1;
  197. }
  198. static SQRESULT _file_constructor(HSQUIRRELVM v)
  199. {
  200. const SQChar *filename,*mode;
  201. bool owns = true;
  202. SQFile *f;
  203. SQFILE newf;
  204. if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
  205. sq_getstring(v, 2, &filename);
  206. sq_getstring(v, 3, &mode);
  207. newf = sqstd_fopen(filename, mode);
  208. if(!newf) return sq_throwerror(v, _SC("cannot open file"));
  209. } else if(sq_gettype(v,2) == OT_USERPOINTER) {
  210. owns = !(sq_gettype(v,3) == OT_NULL);
  211. sq_getuserpointer(v,2,&newf);
  212. } else {
  213. return sq_throwerror(v,_SC("wrong parameter"));
  214. }
  215. f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
  216. if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
  217. f->~SQFile();
  218. sq_free(f,sizeof(SQFile));
  219. return sq_throwerror(v, _SC("cannot create blob with negative size"));
  220. }
  221. sq_setreleasehook(v,1,_file_releasehook);
  222. return 0;
  223. }
  224. static SQRESULT _file_close(HSQUIRRELVM v)
  225. {
  226. SQFile *self = NULL;
  227. if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
  228. && self != NULL)
  229. {
  230. self->Close();
  231. }
  232. return 0;
  233. }
  234. //bindings
  235. #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
  236. static const SQRegFunction _file_methods[] = {
  237. _DECL_FILE_FUNC(constructor,3,_SC("x")),
  238. _DECL_FILE_FUNC(_typeof,1,_SC("x")),
  239. _DECL_FILE_FUNC(close,1,_SC("x")),
  240. {NULL,(SQFUNCTION)0,0,NULL}
  241. };
  242. SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
  243. {
  244. SQInteger top = sq_gettop(v);
  245. sq_pushregistrytable(v);
  246. sq_pushstring(v,_SC("std_file"),-1);
  247. if(SQ_SUCCEEDED(sq_get(v,-2))) {
  248. sq_remove(v,-2); //removes the registry
  249. sq_pushroottable(v); // push the this
  250. sq_pushuserpointer(v,file); //file
  251. if(own){
  252. sq_pushinteger(v,1); //true
  253. }
  254. else{
  255. sq_pushnull(v); //false
  256. }
  257. if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) {
  258. sq_remove(v,-2);
  259. return SQ_OK;
  260. }
  261. }
  262. sq_settop(v,top);
  263. return SQ_ERROR;
  264. }
  265. SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
  266. {
  267. SQFile *fileobj = NULL;
  268. if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) {
  269. *file = fileobj->GetHandle();
  270. return SQ_OK;
  271. }
  272. return sq_throwerror(v,_SC("not a file"));
  273. }
  274. #define IO_BUFFER_SIZE 2048
  275. struct IOBuffer {
  276. unsigned char buffer[IO_BUFFER_SIZE];
  277. SQInteger size;
  278. SQInteger ptr;
  279. SQFILE file;
  280. };
  281. SQInteger _read_byte(IOBuffer *iobuffer)
  282. {
  283. if(iobuffer->ptr < iobuffer->size) {
  284. SQInteger ret = iobuffer->buffer[iobuffer->ptr];
  285. iobuffer->ptr++;
  286. return ret;
  287. }
  288. else {
  289. if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
  290. {
  291. SQInteger ret = iobuffer->buffer[0];
  292. iobuffer->ptr = 1;
  293. return ret;
  294. }
  295. }
  296. return 0;
  297. }
  298. SQInteger _read_two_bytes(IOBuffer *iobuffer)
  299. {
  300. if(iobuffer->ptr < iobuffer->size) {
  301. if(iobuffer->size < 2) return 0;
  302. SQInteger ret = *((const wchar_t*)&iobuffer->buffer[iobuffer->ptr]);
  303. iobuffer->ptr += 2;
  304. return ret;
  305. }
  306. else {
  307. if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
  308. {
  309. if(iobuffer->size < 2) return 0;
  310. SQInteger ret = *((const wchar_t*)&iobuffer->buffer[0]);
  311. iobuffer->ptr = 2;
  312. return ret;
  313. }
  314. }
  315. return 0;
  316. }
  317. static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer iobuf)
  318. {
  319. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  320. return _read_byte(iobuffer);
  321. }
  322. #ifdef SQUNICODE
  323. static SQInteger _io_file_lexfeed_UTF8(SQUserPointer iobuf)
  324. {
  325. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  326. #define READ(iobuf) \
  327. if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \
  328. return 0;
  329. static const SQInteger utf8_lengths[16] =
  330. {
  331. 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */
  332. 0,0,0,0, /* 1000 to 1011 : not valid */
  333. 2,2, /* 1100, 1101 : 2 bytes */
  334. 3, /* 1110 : 3 bytes */
  335. 4 /* 1111 :4 bytes */
  336. };
  337. static const unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};
  338. unsigned char inchar;
  339. SQInteger c = 0;
  340. READ(iobuffer);
  341. c = inchar;
  342. //
  343. if(c >= 0x80) {
  344. SQInteger tmp;
  345. SQInteger codelen = utf8_lengths[c>>4];
  346. if(codelen == 0)
  347. return 0;
  348. //"invalid UTF-8 stream";
  349. tmp = c&byte_masks[codelen];
  350. for(SQInteger n = 0; n < codelen-1; n++) {
  351. tmp<<=6;
  352. READ(iobuffer);
  353. tmp |= inchar & 0x3F;
  354. }
  355. c = tmp;
  356. }
  357. return c;
  358. }
  359. #endif
  360. static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer iobuf)
  361. {
  362. SQInteger ret;
  363. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  364. if( (ret = _read_two_bytes(iobuffer)) > 0 )
  365. return ret;
  366. return 0;
  367. }
  368. static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer iobuf)
  369. {
  370. SQInteger c;
  371. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  372. if( (c = _read_two_bytes(iobuffer)) > 0 ) {
  373. c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
  374. return c;
  375. }
  376. return 0;
  377. }
  378. SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
  379. {
  380. SQInteger ret;
  381. if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
  382. return -1;
  383. }
  384. SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size)
  385. {
  386. return sqstd_fwrite(p,1,size,(SQFILE)file);
  387. }
  388. SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror,SQBool show_warnings)
  389. {
  390. SQFILE file = sqstd_fopen(filename,_SC("rb"));
  391. SQInteger ret;
  392. unsigned short us;
  393. unsigned char uc;
  394. SQLEXREADFUNC func = _io_file_lexfeed_PLAIN;
  395. if(file){
  396. ret = sqstd_fread(&us,1,2,file);
  397. if(ret != 2) {
  398. //probably an empty file
  399. us = 0;
  400. }
  401. if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE
  402. sqstd_fseek(file,0,SQ_SEEK_SET);
  403. if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
  404. sqstd_fclose(file);
  405. return SQ_OK;
  406. }
  407. }
  408. else { //SCRIPT
  409. switch(us)
  410. {
  411. //gotta swap the next 2 lines on BIG endian machines
  412. case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
  413. case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
  414. case 0xBBEF:
  415. if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) {
  416. sqstd_fclose(file);
  417. return sq_throwerror(v,_SC("io error"));
  418. }
  419. if(uc != 0xBF) {
  420. sqstd_fclose(file);
  421. return sq_throwerror(v,_SC("Unrecognozed ecoding"));
  422. }
  423. #ifdef SQUNICODE
  424. func = _io_file_lexfeed_UTF8;
  425. #else
  426. func = _io_file_lexfeed_PLAIN;
  427. #endif
  428. break;//UTF-8 ;
  429. default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
  430. }
  431. IOBuffer buffer;
  432. buffer.ptr = 0;
  433. buffer.size = 0;
  434. buffer.file = file;
  435. if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,filename,printerror,show_warnings, SQ_MAX_INCLUDE_FILES))){
  436. sqstd_fclose(file);
  437. return SQ_OK;
  438. }
  439. }
  440. sqstd_fclose(file);
  441. return SQ_ERROR;
  442. }
  443. return sq_throwerror(v,_SC("cannot open the file"));
  444. }
  445. SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror,SQBool show_warnings)
  446. {
  447. if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror,show_warnings))) {
  448. sq_push(v,-2);
  449. if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
  450. sq_remove(v,retval?-2:-1); //removes the closure
  451. return 1;
  452. }
  453. sq_pop(v,1); //removes the closure
  454. }
  455. return SQ_ERROR;
  456. }
  457. SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
  458. {
  459. SQFILE file = sqstd_fopen(filename,_SC("wb+"));
  460. if(!file) return sq_throwerror(v,_SC("cannot open the file"));
  461. if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
  462. sqstd_fclose(file);
  463. return SQ_OK;
  464. }
  465. sqstd_fclose(file);
  466. return SQ_ERROR; //forward the error
  467. }
  468. SQRESULT sqstd_writeclosuretofile_as_source(HSQUIRRELVM v,const SQChar *filename)
  469. {
  470. SQFILE file = sqstd_fopen(filename,_SC("wb+"));
  471. if(!file) return sq_throwerror(v,_SC("cannot open the file"));
  472. if(SQ_SUCCEEDED(sq_writeclosure_as_source(v,file_write,file))) {
  473. sqstd_fclose(file);
  474. return SQ_OK;
  475. }
  476. sqstd_fclose(file);
  477. return SQ_ERROR; //forward the error
  478. }
  479. SQInteger _g_io_loadfile(HSQUIRRELVM v)
  480. {
  481. SQ_FUNC_VARS(v);
  482. SQ_GET_STRING(v, 2, filename);
  483. SQ_OPT_BOOL(v, 3, printerror, SQFalse);
  484. SQ_OPT_BOOL(v, 4, show_warnings, SQTrue);
  485. if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror,show_warnings)))
  486. return 1;
  487. return SQ_ERROR; //propagates the error
  488. }
  489. SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
  490. {
  491. const SQChar *filename;
  492. sq_getstring(v,2,&filename);
  493. if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))
  494. return 1;
  495. return SQ_ERROR; //propagates the error
  496. }
  497. #include "sqstdblobimpl.h"
  498. SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size);
  499. SQInteger _g_io_dumpclosure(HSQUIRRELVM v)
  500. {
  501. SQBlob b(0,8192);
  502. if(SQ_SUCCEEDED(sq_writeclosure(v,blob_write,&b))) {
  503. sq_pushstring(v, (const SQChar*)b.GetBuf(), b.Len());
  504. return 1;
  505. }
  506. return SQ_ERROR; //forward the error
  507. }
  508. SQInteger blob_read(SQUserPointer file,SQUserPointer p,SQInteger size);
  509. SQInteger _g_io_loadstring(HSQUIRRELVM v)
  510. {
  511. if(sq_gettype(v, 2) != OT_STRING) return sq_throwerror(v, _SC("string expected as parameter"));
  512. SQInteger rc, size = sq_getsize(v, 2);
  513. const SQChar *dump;
  514. sq_getstring(v, 2, &dump);
  515. unsigned short tag = *((unsigned short*)dump);
  516. if(tag == SQ_BYTECODE_STREAM_TAG){
  517. SQBlob b(0, size);
  518. b.Write(dump, size);
  519. b.Seek(0, SQ_SEEK_SET);
  520. rc = sq_readclosure(v, blob_read, &b);
  521. }
  522. else
  523. {
  524. rc = sq_compilebuffer(v, dump, size, _SC("loadstring"), SQFalse, SQFalse, SQ_MAX_INCLUDE_FILES);
  525. }
  526. return rc < 0 ? rc : 1;
  527. }
  528. SQInteger _g_io_dostring(HSQUIRRELVM v)
  529. {
  530. SQ_FUNC_VARS(v);
  531. SQInteger rc = _g_io_loadstring(v);
  532. if(rc < 0) return rc;
  533. SQ_OPT_BOOL(v, 3, retval, SQFalse);
  534. sq_push(v,1); //this environment
  535. if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
  536. sq_remove(v,retval?-2:-1); //removes the closure
  537. return 1;
  538. }
  539. sq_pop(v,1); //removes the closure
  540. return SQ_ERROR; //forward the error
  541. }
  542. SQInteger _g_io_dofile(HSQUIRRELVM v)
  543. {
  544. SQ_FUNC_VARS(v);
  545. SQ_GET_STRING(v, 2, filename);
  546. SQ_OPT_BOOL(v, 3, printerror, SQFalse);
  547. SQ_OPT_BOOL(v, 4, show_warnings, SQTrue);
  548. sq_push(v,1); //repush the this
  549. if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror,show_warnings)))
  550. return 1;
  551. return SQ_ERROR; //propagates the error
  552. }
  553. SQInteger _g_io_existsfile(HSQUIRRELVM v)
  554. {
  555. SQ_FUNC_VARS_NO_TOP(v);
  556. SQ_GET_STRING(v, 2, filename);
  557. SQFile fs;
  558. sq_pushbool(v, fs.Open(filename, "rb"));
  559. return 1;
  560. }
  561. SQInteger _g_io_readfile(HSQUIRRELVM v)
  562. {
  563. SQ_FUNC_VARS_NO_TOP(v);
  564. SQ_GET_STRING(v, 2, filename);
  565. SQFile fs;
  566. if(fs.Open(filename, "rb"))
  567. {
  568. SQInteger size,res;
  569. SQChar *data;
  570. size = fs.Len();
  571. data = sq_getscratchpad(v,size);
  572. res = fs.Read(data,size);
  573. if(res <= 0)
  574. return sq_throwerror(v,_SC("no data left to read"));
  575. sq_pushstring(v,data,res);
  576. return 1;
  577. }
  578. return sq_throwerror(v,_SC("could not open file %s"), filename);
  579. }
  580. SQInteger _g_io_writefile(HSQUIRRELVM v)
  581. {
  582. SQ_FUNC_VARS_NO_TOP(v);
  583. SQ_GET_STRING(v, 2, filename);
  584. SQ_GET_STRING(v, 3, data);
  585. SQFile fs;
  586. if(fs.Open(filename, "wb"))
  587. {
  588. SQInteger res = fs.Write(data, data_size);
  589. if(res != data_size)
  590. return sq_throwerror(v,_SC("could not write to file"));
  591. return 0;
  592. }
  593. return sq_throwerror(v,_SC("could not open file %s"), filename);
  594. }
  595. #define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
  596. static const SQRegFunction iolib_funcs[]={
  597. _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sbb")),
  598. _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sbb")),
  599. _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
  600. _DECL_GLOBALIO_FUNC(dostring,-2,_SC(".sb")),
  601. _DECL_GLOBALIO_FUNC(loadstring,2,_SC(".s")),
  602. _DECL_GLOBALIO_FUNC(dumpclosure,3,_SC(".sc")),
  603. _DECL_GLOBALIO_FUNC(existsfile,2,_SC(".s")),
  604. _DECL_GLOBALIO_FUNC(readfile,2,_SC(".s")),
  605. _DECL_GLOBALIO_FUNC(writefile,3,_SC(".ss")),
  606. {NULL,(SQFUNCTION)0,0,NULL}
  607. };
  608. SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
  609. {
  610. //create delegate
  611. declare_stream(v,_SC("popen"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_popen_methods,iolib_funcs);
  612. declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
  613. sq_pushstring(v,_SC("stdout"),-1);
  614. sqstd_createfile(v,stdout,SQFalse);
  615. sq_newslot(v,-3,SQFalse);
  616. sq_pushstring(v,_SC("stdin"),-1);
  617. sqstd_createfile(v,stdin,SQFalse);
  618. sq_newslot(v,-3,SQFalse);
  619. sq_pushstring(v,_SC("stderr"),-1);
  620. sqstd_createfile(v,stderr,SQFalse);
  621. sq_newslot(v,-3,SQFalse);
  622. return SQ_OK;
  623. }