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 21KB

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