The Sol Programming Language!
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.

object.c 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. #include "ast.h" // For CALL_METHOD
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <assert.h>
  6. #include <dlfcn.h>
  7. #include <stdarg.h>
  8. sol_object_t *sol_cast_int(sol_state_t *state, sol_object_t *obj) {
  9. sol_object_t *res, *ls;
  10. if(sol_is_int(obj)) {
  11. return sol_incref(obj);
  12. }
  13. ls = sol_new_list(state);
  14. sol_list_insert(state, ls, 0, obj);
  15. res = CALL_METHOD(state, obj, toint, ls);
  16. sol_obj_free(ls);
  17. return res;
  18. }
  19. sol_object_t *sol_cast_float(sol_state_t *state, sol_object_t *obj) {
  20. sol_object_t *res, *ls;
  21. if(sol_is_float(obj)) {
  22. return sol_incref(obj);
  23. }
  24. ls = sol_new_list(state);
  25. sol_list_insert(state, ls, 0, obj);
  26. res = CALL_METHOD(state, obj, tofloat, ls);
  27. sol_obj_free(ls);
  28. return res;
  29. }
  30. sol_object_t *sol_cast_string(sol_state_t *state, sol_object_t *obj) {
  31. sol_object_t *res, *ls;
  32. if(sol_is_string(obj)) {
  33. return sol_incref(obj);
  34. }
  35. ls = sol_new_list(state);
  36. sol_list_insert(state, ls, 0, obj);
  37. res = CALL_METHOD(state, obj, tostring, ls);
  38. sol_obj_free(ls);
  39. return res;
  40. }
  41. sol_object_t *sol_cast_repr(sol_state_t *state, sol_object_t *obj) {
  42. sol_object_t *res, *ls = sol_new_list(state);
  43. sol_list_insert(state, ls, 0, obj);
  44. res = CALL_METHOD(state, obj, repr, ls);
  45. sol_obj_free(ls);
  46. return res;
  47. }
  48. // This will not fail here; error checking is done in sol_state_init().
  49. sol_object_t *sol_new_singlet(sol_state_t *state, const char *name) {
  50. sol_object_t *res = malloc(sizeof(sol_object_t));
  51. if(res) {
  52. res->type = SOL_SINGLET;
  53. res->refcnt = 0;
  54. res->ops = &(state->SingletOps);
  55. res->str = strdup(name);
  56. }
  57. return sol_incref(res); // XXX Segfault
  58. }
  59. sol_object_t *sol_f_singlet_free(sol_state_t *state, sol_object_t *singlet) {
  60. free(singlet->str);
  61. }
  62. // And, now, for the rest of the checked stuff...
  63. void sol_init_object(sol_state_t *state, sol_object_t *obj) {
  64. if(obj->ops->init) {
  65. obj->ops->init(state, obj);
  66. }
  67. }
  68. sol_object_t *sol_new_int(sol_state_t *state, long i) {
  69. sol_object_t *res;
  70. #ifdef SOL_ICACHE
  71. if(!state->icache_bypass && i >= SOL_ICACHE_MIN && i <= SOL_ICACHE_MAX) {
  72. res = sol_incref(state->icache[i - SOL_ICACHE_MIN]);
  73. if(res->ival != i) {
  74. printf("WARNING: Integer at %ld mutated to %ld! Resetting...\n", i, res->ival);
  75. res->ival = i;
  76. }
  77. return res;
  78. }
  79. #endif
  80. res = sol_alloc_object(state);
  81. res->type = SOL_INTEGER;
  82. res->ival = i;
  83. res->ops = &(state->IntOps);
  84. sol_init_object(state, res);
  85. return res;
  86. }
  87. sol_object_t *sol_new_float(sol_state_t *state, double f) {
  88. sol_object_t *res = sol_alloc_object(state);
  89. res->type = SOL_FLOAT;
  90. res->fval = f;
  91. res->ops = &(state->FloatOps);
  92. sol_init_object(state, res);
  93. return res;
  94. }
  95. sol_object_t *sol_new_string(sol_state_t *state, const char *s) {
  96. sol_object_t *res = sol_alloc_object(state);
  97. res->type = SOL_STRING;
  98. res->str = strdup(s);
  99. if(!res->str) {
  100. sol_obj_free(res);
  101. sol_set_error(state, state->OutOfMemory);
  102. return sol_incref(state->None);
  103. }
  104. res->ops = &(state->StringOps);
  105. sol_init_object(state, res);
  106. return res;
  107. }
  108. int sol_string_cmp(sol_state_t *state, sol_object_t *str, const char *s) {
  109. return strcmp(str->str, s);
  110. }
  111. sol_object_t *sol_string_concat(sol_state_t *state, sol_object_t *a, sol_object_t *b) {
  112. sol_object_t *res, *sa = sol_cast_string(state, a), *sb = sol_cast_string(state, b);
  113. int n = strlen(sa->str) + strlen(sb->str) + 1;
  114. char *s = malloc(n);
  115. res = sol_new_string(state, strncat(strncpy(s, a->str, n), b->str, n));
  116. sol_obj_free(sa);
  117. sol_obj_free(sb);
  118. free(s);
  119. return res;
  120. }
  121. sol_object_t *sol_string_concat_cstr(sol_state_t *state, sol_object_t *a, char *s) {
  122. sol_object_t *b = sol_new_string(state, s);
  123. sol_object_t *res = sol_string_concat(state, a, b);
  124. sol_obj_free(b);
  125. return res;
  126. }
  127. sol_object_t *sol_f_str_free(sol_state_t *state, sol_object_t *obj) {
  128. free(obj->str);
  129. return obj;
  130. }
  131. sol_object_t *sol_new_list(sol_state_t *state) {
  132. sol_object_t *res = sol_alloc_object(state);
  133. res->type = SOL_LIST;
  134. res->seq = dsl_seq_new_array(NULL, &(state->obfuncs));
  135. res->ops = &(state->ListOps);
  136. sol_init_object(state, res);
  137. return res;
  138. }
  139. sol_object_t *sol_list_from_seq(sol_state_t *state, dsl_seq *seq) {
  140. sol_object_t *res = sol_alloc_object(state);
  141. res->type = SOL_LIST;
  142. res->seq = seq;
  143. res->ops = &(state->ListOps);
  144. sol_init_object(state, res);
  145. return res;
  146. }
  147. int sol_list_len(sol_state_t *state, sol_object_t *list) {
  148. return dsl_seq_len(list->seq);
  149. }
  150. sol_object_t *sol_list_sublist(sol_state_t *state, sol_object_t *list, int idx) {
  151. int i = 0;
  152. dsl_seq *subl;
  153. if(idx < 0) {
  154. return sol_set_error_string(state, "Create sublist at negative index");
  155. }
  156. subl = dsl_seq_copy(list->seq);
  157. for(i = 0; i < idx; i++) {
  158. dsl_seq_delete(subl, 0);
  159. }
  160. return sol_list_from_seq(state, subl);
  161. }
  162. sol_object_t *sol_list_get_index(sol_state_t *state, sol_object_t *list, int idx) {
  163. if(idx < 0 || idx >= dsl_seq_len(list->seq)) {
  164. return sol_incref(state->None);
  165. }
  166. return sol_incref(AS_OBJ(dsl_seq_get(list->seq, idx)));
  167. }
  168. void sol_list_set_index(sol_state_t *state, sol_object_t *list, int idx, sol_object_t *obj) {
  169. if(idx < 0 || idx >= dsl_seq_len(list->seq)) {
  170. return;
  171. }
  172. dsl_seq_set(list->seq, idx, obj);
  173. }
  174. void sol_list_insert(sol_state_t *state, sol_object_t *list, int idx, sol_object_t *obj) {
  175. if(idx < 0 || idx > dsl_seq_len(list->seq)) {
  176. return;
  177. }
  178. dsl_seq_insert(list->seq, idx, obj);
  179. }
  180. sol_object_t *sol_list_remove(sol_state_t *state, sol_object_t *list, int idx) {
  181. if(idx < 0 || idx >= dsl_seq_len(list->seq)) {
  182. return sol_incref(state->None);
  183. }
  184. return dsl_seq_remove(list->seq, idx);
  185. }
  186. sol_object_t *sol_list_copy(sol_state_t *state, sol_object_t *list) {
  187. return sol_list_from_seq(state, dsl_seq_copy(list->seq));
  188. }
  189. sol_object_t *sol_list_truncate(sol_state_t *state, sol_object_t *list, int len) {
  190. dsl_seq *newseq = dsl_seq_copy(list->seq);
  191. dsl_seq_iter *iter = dsl_new_seq_iter(newseq);
  192. int pos = dsl_seq_iter_seek(iter, len);
  193. int sz = dsl_seq_len(newseq);
  194. int i;
  195. if(pos >= len) {
  196. for(i = 0; i < sz - pos; i++) {
  197. dsl_seq_iter_delete_at(iter);
  198. }
  199. }
  200. dsl_free_seq_iter(iter);
  201. return sol_list_from_seq(state, newseq);
  202. }
  203. void sol_list_append(sol_state_t *state, sol_object_t *dest, sol_object_t *src) {
  204. dsl_seq *oldseq = dest->seq;
  205. dest->seq = dsl_seq_append(dest->seq, src->seq);
  206. dsl_free_seq(oldseq);
  207. }
  208. sol_object_t *sol_f_list_free(sol_state_t *state, sol_object_t *list) {
  209. dsl_free_seq(list->seq);
  210. return list;
  211. }
  212. /*int sol_test_cycle(sol_state_t *state, sol_object_t *seq) {
  213. sol_object_t *seen[1024]={};
  214. sol_object_t *cur = seq, **item;
  215. while(cur) {
  216. item = seen;
  217. while(*item) {
  218. if(*item == cur) return 1;
  219. item++;
  220. }
  221. *item = cur;
  222. if(sol_is_list(seq)) {
  223. cur = cur->lnext;
  224. } else {
  225. cur = cur->mnext;
  226. }
  227. }
  228. return 0;
  229. }
  230. int sol_validate_list(sol_state_t *state, sol_object_t *list) {
  231. sol_object_t *cur = list;
  232. int i = 0;
  233. char msg[128];
  234. while(cur) {
  235. if(!sol_is_list(cur)) {
  236. snprintf(msg, 128, "Node at index %d not a list node", i);
  237. sol_obj_free(sol_set_error_string(state, msg));
  238. return 1;
  239. }
  240. /*if(cur->lnext && !cur->lvalue) {
  241. snprintf(msg, 128, "Node at index %d has a next node but NULL value", i);
  242. sol_obj_free(sol_set_error_string(state, msg));
  243. return 1;
  244. }*//*
  245. cur = cur->lnext;
  246. i++;
  247. }
  248. if(sol_test_cycle(state, list)) {
  249. snprintf(msg, 128, "Cycle detected");
  250. sol_obj_free(sol_set_error_string(state, msg));
  251. return 1;
  252. }
  253. return 0;
  254. }*/
  255. sol_object_t *sol_new_map(sol_state_t *state) {
  256. sol_object_t *map = sol_alloc_object(state);
  257. map->type = SOL_MAP;
  258. map->ops = &(state->MapOps);
  259. map->seq = dsl_seq_new_array(NULL, &(state->obfuncs));
  260. sol_init_object(state, map);
  261. return map;
  262. }
  263. sol_object_t *sol_map_from_seq(sol_state_t *state, dsl_seq *seq) {
  264. sol_object_t *map = sol_alloc_object(state);
  265. if(sol_has_error(state)) {
  266. return sol_incref(state->None);
  267. }
  268. map->type = SOL_MAP;
  269. map->ops = &(state->MapOps);
  270. map->seq = seq;
  271. return map;
  272. }
  273. int sol_map_len(sol_state_t *state, sol_object_t *map) {
  274. return dsl_seq_len(map->seq);
  275. }
  276. sol_object_t *sol_map_mcell(sol_state_t *state, sol_object_t *map, sol_object_t *key) {
  277. sol_object_t *list, *cmp, *icmp, *res = NULL;
  278. dsl_seq_iter *iter;
  279. if(!sol_is_map(map)) {
  280. printf("WARNING: Attempt to index non-map as map\n");
  281. return sol_incref(state->None);
  282. }
  283. list = sol_new_list(state);
  284. iter = dsl_new_seq_iter(map->seq);
  285. if(sol_has_error(state)) {
  286. dsl_free_seq_iter(iter);
  287. sol_obj_free(list);
  288. return sol_incref(state->None);
  289. }
  290. sol_list_insert(state, list, 0, state->None);
  291. sol_list_insert(state, list, 1, key);
  292. while(!res && !dsl_seq_iter_is_invalid(iter)) {
  293. sol_list_set_index(state, list, 0, AS_OBJ(dsl_seq_iter_at(iter))->key);
  294. cmp = CALL_METHOD(state, AS_OBJ(dsl_seq_iter_at(iter))->key, cmp, list);
  295. if(sol_has_error(state)) {
  296. sol_obj_free(cmp);
  297. sol_clear_error(state);
  298. continue;
  299. }
  300. icmp = sol_cast_int(state, cmp);
  301. sol_obj_free(cmp);
  302. if(icmp->ival == 0) {
  303. res = AS_OBJ(dsl_seq_iter_at(iter));
  304. }
  305. sol_obj_free(icmp);
  306. dsl_seq_iter_next(iter);
  307. }
  308. dsl_free_seq_iter(iter);
  309. sol_obj_free(list);
  310. if(res) {
  311. return sol_incref(res);
  312. }
  313. return sol_incref(state->None);
  314. }
  315. int sol_map_has(sol_state_t *state, sol_object_t *map, sol_object_t *key) {
  316. sol_object_t *mcell = sol_map_mcell(state, map, key);
  317. int res = !sol_is_none(state, mcell);
  318. sol_decref(mcell);
  319. return res;
  320. }
  321. sol_object_t *sol_map_get(sol_state_t *state, sol_object_t *map, sol_object_t *key) {
  322. sol_object_t *mcell = sol_map_mcell(state, map, key), *ret;
  323. if(sol_is_none(state, mcell)) {
  324. ret = mcell;
  325. } else {
  326. ret = mcell->val;
  327. }
  328. sol_obj_free(mcell);
  329. return sol_incref(ret);
  330. }
  331. sol_object_t *sol_map_get_name(sol_state_t *state, sol_object_t *map, char *name) {
  332. sol_object_t *key = sol_new_string(state, name);
  333. sol_object_t *res = sol_map_get(state, map, key);
  334. sol_obj_free(key);
  335. return res;
  336. }
  337. void sol_map_set(sol_state_t *state, sol_object_t *map, sol_object_t *key, sol_object_t *val) {
  338. sol_object_t *mcell = sol_map_mcell(state, map, key), *newcell, *temp;
  339. if(sol_is_none(state, mcell)) {
  340. newcell = sol_alloc_object(state);
  341. newcell->type = SOL_MCELL;
  342. newcell->ops = &(state->MCellOps);
  343. newcell->key = sol_incref(key);
  344. newcell->val = sol_incref(val);
  345. dsl_seq_insert(map->seq, 0, newcell);
  346. sol_obj_free(newcell);
  347. } else {
  348. temp = mcell->val;
  349. mcell->val = sol_incref(val);
  350. sol_obj_free(temp);
  351. }
  352. sol_obj_free(mcell);
  353. }
  354. void sol_map_set_name(sol_state_t *state, sol_object_t *map, char *name, sol_object_t *val) {
  355. sol_object_t *key = sol_new_string(state, name);
  356. sol_map_set(state, map, key, val);
  357. sol_obj_free(key);
  358. }
  359. void sol_map_set_existing(sol_state_t *state, sol_object_t *map, sol_object_t *key, sol_object_t *val) {
  360. sol_object_t *mcell = sol_map_mcell(state, map, key), *temp;
  361. if(!sol_is_none(state, mcell)) {
  362. temp = mcell->val;
  363. mcell->val = sol_incref(val);
  364. sol_obj_free(temp);
  365. }
  366. sol_obj_free(mcell);
  367. }
  368. sol_object_t *sol_map_copy(sol_state_t *state, sol_object_t *map) {
  369. return sol_map_from_seq(state, dsl_seq_copy(map->seq));
  370. }
  371. void sol_map_merge(sol_state_t *state, sol_object_t *dest, sol_object_t *src) {
  372. dsl_seq_iter *iter = dsl_new_seq_iter(src->seq);
  373. while(!dsl_seq_iter_is_invalid(iter)) {
  374. sol_map_set(state, dest, AS_OBJ(dsl_seq_iter_at(iter))->key, AS_OBJ(dsl_seq_iter_at(iter))->val);
  375. dsl_seq_iter_next(iter);
  376. }
  377. dsl_free_seq_iter(iter);
  378. }
  379. void sol_map_merge_existing(sol_state_t *state, sol_object_t *dest, sol_object_t *src) {
  380. dsl_seq_iter *iter = dsl_new_seq_iter(src->seq);
  381. while(!dsl_seq_iter_is_invalid(iter)) {
  382. sol_map_set_existing(state, dest, AS_OBJ(dsl_seq_iter_at(iter))->key, AS_OBJ(dsl_seq_iter_at(iter))->val);
  383. dsl_seq_iter_next(iter);
  384. }
  385. dsl_free_seq_iter(iter);
  386. }
  387. void sol_map_invert(sol_state_t *state, sol_object_t *map) {
  388. dsl_seq *pairs = dsl_seq_copy(map->seq);
  389. dsl_seq_iter *iter = dsl_new_seq_iter(pairs);
  390. sol_object_t *mcell;
  391. while(!dsl_seq_iter_is_invalid(iter)) {
  392. mcell = dsl_seq_iter_at(iter);
  393. sol_map_set(state, map, mcell->val, mcell->key);
  394. dsl_seq_iter_next(iter);
  395. }
  396. dsl_free_seq_iter(iter);
  397. dsl_free_seq(pairs);
  398. }
  399. sol_object_t *sol_f_map_free(sol_state_t *state, sol_object_t *map) {
  400. dsl_free_seq(map->seq);
  401. return map;
  402. }
  403. sol_object_t *sol_f_mcell_free(sol_state_t *state, sol_object_t *mcell) {
  404. if(mcell->key) {
  405. sol_obj_free(mcell->key);
  406. } else {
  407. printf("WARNING: Freed mcell with NULL key\n");
  408. }
  409. if(mcell->val) {
  410. sol_obj_free(mcell->val);
  411. } else {
  412. printf("WARNING: Freed mcell with NULL value\n");
  413. }
  414. return mcell;
  415. }
  416. /*int sol_validate_map(sol_state_t *state, sol_object_t *map) {
  417. sol_object_t *cur = map;
  418. int i = 0;
  419. char msg[128];
  420. while(cur) {
  421. if(!sol_is_map(cur)) {
  422. snprintf(msg, 128, "Node at index %d not a map node", i);
  423. sol_obj_free(sol_set_error_string(state, msg));
  424. return 1;
  425. }
  426. if(cur->mnext && (!cur->mkey || !cur->mval)) {
  427. snprintf(msg, 128, "Node at index %d has a next node but NULL key or value", i);
  428. sol_obj_free(sol_set_error_string(state, msg));
  429. return 1;
  430. }
  431. cur = cur->mnext;
  432. i++;
  433. }
  434. return 0;
  435. }*/
  436. sol_object_t *sol_new_cfunc(sol_state_t *state, sol_cfunc_t cfunc) {
  437. sol_object_t *res = sol_alloc_object(state);
  438. res->type = SOL_CFUNCTION;
  439. res->ops = &(state->CFuncOps);
  440. res->cfunc = cfunc;
  441. sol_init_object(state, res);
  442. return res;
  443. }
  444. sol_object_t *sol_new_cdata(sol_state_t *state, void *cdata, sol_ops_t *ops) {
  445. sol_object_t *res = sol_alloc_object(state);
  446. res->type = SOL_CDATA;
  447. res->ops = ops;
  448. res->cdata = cdata;
  449. sol_init_object(state, res);
  450. return res;
  451. }
  452. sol_object_t *sol_f_astnode_free(sol_state_t *state, sol_object_t *node) {
  453. switch(node->type) {
  454. case SOL_STMT:
  455. st_free((stmt_node *) node->node);
  456. break;
  457. case SOL_EXPR:
  458. ex_free((expr_node *) node->node);
  459. break;
  460. }
  461. return node;
  462. }
  463. sol_object_t *sol_new_buffer(sol_state_t *state, void *buffer, ssize_t sz, sol_owntype_t own, sol_freefunc_t freef, sol_movefunc_t movef) {
  464. sol_object_t *res = sol_alloc_object(state);
  465. res->type = SOL_BUFFER;
  466. res->ops = &(state->BufferOps);
  467. res->buffer = buffer;
  468. res->sz = sz;
  469. res->own = own;
  470. res->freef = freef;
  471. res->movef = movef;
  472. sol_init_object(state, res);
  473. return res;
  474. }
  475. sol_object_t *sol_f_buffer_free(sol_state_t *state, sol_object_t *buf) {
  476. switch(buf->own) {
  477. case OWN_FREE:
  478. free(buf->buffer);
  479. break;
  480. case OWN_CALLF:
  481. if(buf->freef) buf->freef(buf->buffer, buf->sz);
  482. break;
  483. }
  484. return buf;
  485. }
  486. sol_object_t *sol_new_dylib(sol_state_t *state, void *handle) {
  487. sol_object_t *res = sol_alloc_object(state);
  488. res->type = SOL_DYLIB;
  489. res->ops = &(state->DyLibOps);
  490. res->dlhandle = handle;
  491. sol_init_object(state, res);
  492. return res;
  493. }
  494. sol_object_t *sol_f_dylib_free(sol_state_t *state, sol_object_t *dylib) {
  495. dlclose(dylib->dlhandle);
  496. return dylib;
  497. }
  498. sol_object_t *sol_new_dysym(sol_state_t *state, void *sym, dsl_seq *argtp, sol_buftype_t rettp) {
  499. sol_object_t *res = sol_alloc_object(state);
  500. res->type = SOL_DYSYM;
  501. res->ops = &(state->DySymOps);
  502. res->dlsym = sym;
  503. if(argtp) {
  504. res->argtp = dsl_seq_copy(argtp);
  505. } else {
  506. res->argtp = dsl_seq_new_array(NULL, &(state->obfuncs));
  507. }
  508. res->rettp = rettp;
  509. sol_init_object(state, res);
  510. return res;
  511. }
  512. sol_object_t *sol_new_stream(sol_state_t *state, FILE *stream, sol_modes_t modes) {
  513. sol_object_t *res = sol_alloc_object(state);
  514. res->type = SOL_STREAM;
  515. res->ops = &(state->StreamOps);
  516. res->stream = stream;
  517. res->modes = modes;
  518. sol_init_object(state, res);
  519. return res;
  520. }
  521. size_t sol_stream_printf(sol_state_t *state, sol_object_t *stream, const char *fmt, ...) {
  522. va_list va;
  523. size_t res;
  524. if(!(stream->modes & MODE_WRITE)) {
  525. if(state) {
  526. sol_obj_free(sol_set_error_string(state, "Write to non-writable stream"));
  527. }
  528. return 0;
  529. }
  530. va_start(va, fmt);
  531. //res = vfprintf(stream->stream, fmt, va);
  532. res = vprintf(fmt, va);
  533. va_end(va);
  534. return res;
  535. }
  536. size_t sol_stream_vprintf(sol_state_t *state, sol_object_t *stream, const char *fmt, va_list va) {
  537. if(!(stream->modes & MODE_WRITE)) {
  538. if(state) {
  539. sol_obj_free(sol_set_error_string(state, "Write to non-writable stream"));
  540. }
  541. return 0;
  542. }
  543. //return vfprintf(stream->stream, fmt, va);
  544. return vprintf(fmt, va);
  545. }
  546. size_t sol_stream_scanf(sol_state_t *state, sol_object_t *stream, const char *fmt, ...) {
  547. va_list va;
  548. size_t res;
  549. if(!(stream->modes & MODE_READ)) {
  550. if(state) {
  551. sol_obj_free(sol_set_error_string(state, "Read from non-readable stream"));
  552. }
  553. return 0;
  554. }
  555. va_start(va, fmt);
  556. res = vfscanf(stream->stream, fmt, va);
  557. va_end(va);
  558. return res;
  559. }
  560. size_t sol_stream_fread(sol_state_t *state, sol_object_t *stream, char *buffer, size_t sz, size_t memb) {
  561. if(!(stream->modes & MODE_READ)) {
  562. if(state) {
  563. sol_obj_free(sol_set_error_string(state, "Read from non-readable stream"));
  564. }
  565. return 0;
  566. }
  567. return fread(buffer, sz, memb, stream->stream);
  568. }
  569. size_t sol_stream_fwrite(sol_state_t *state, sol_object_t *stream, char *buffer, size_t sz, size_t memb) {
  570. if(!(stream->modes & MODE_WRITE)) {
  571. if(state) {
  572. sol_obj_free(sol_set_error_string(state, "Write to non-writable stream"));
  573. }
  574. return 0;
  575. }
  576. return fwrite(buffer, sz, memb, stream->stream);
  577. }
  578. char *sol_stream_fgets(sol_state_t *state, sol_object_t *stream, char *buffer, size_t sz) {
  579. if(!(stream->modes & MODE_READ)) {
  580. if(state) {
  581. sol_obj_free(sol_set_error_string(state, "Read from non-readable stream"));
  582. }
  583. return NULL;
  584. }
  585. return fgets(buffer, sz, stream->stream);
  586. }
  587. int sol_stream_fputc(sol_state_t *state, sol_object_t *stream, int ch) {
  588. if(!(stream->modes & MODE_WRITE)) {
  589. if(state) {
  590. sol_obj_free(sol_set_error_string(state, "Write to non-writable stream"));
  591. }
  592. return 0;
  593. }
  594. return fputc(ch, stream->stream);
  595. }
  596. int sol_stream_feof(sol_state_t *state, sol_object_t *stream) {
  597. return feof(stream->stream);
  598. }
  599. int sol_stream_ferror(sol_state_t *state, sol_object_t *stream) {
  600. return ferror(stream->stream);
  601. }
  602. int sol_stream_fseek(sol_state_t *state, sol_object_t *stream, long offset, int whence) {
  603. return fseek(stream->stream, offset, whence);
  604. }
  605. long sol_stream_ftell(sol_state_t *state, sol_object_t *stream) {
  606. return ftell(stream->stream);
  607. }
  608. int sol_stream_fflush(sol_state_t *state, sol_object_t *stream) {
  609. return fflush(stream->stream);
  610. }
  611. sol_object_t *sol_f_stream_free(sol_state_t *state, sol_object_t *stream) {
  612. //printf("IO: Closing open file\n");
  613. fclose(stream->stream);
  614. return stream;
  615. }